opencode-swarm 7.32.3 → 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.3",
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,8 +15539,12 @@ 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),
@@ -84599,7 +84603,7 @@ __export(exports_project_context, {
84599
84603
  LANG_BACKEND_DETECTION_TIMEOUT_MS: () => LANG_BACKEND_DETECTION_TIMEOUT_MS
84600
84604
  });
84601
84605
  import * as fs113 from "node:fs";
84602
- import * as path147 from "node:path";
84606
+ import * as path148 from "node:path";
84603
84607
  function detectFileExists2(directory, pattern) {
84604
84608
  if (pattern.includes("*") || pattern.includes("?")) {
84605
84609
  try {
@@ -84611,7 +84615,7 @@ function detectFileExists2(directory, pattern) {
84611
84615
  }
84612
84616
  }
84613
84617
  try {
84614
- fs113.accessSync(path147.join(directory, pattern));
84618
+ fs113.accessSync(path148.join(directory, pattern));
84615
84619
  return true;
84616
84620
  } catch {
84617
84621
  return false;
@@ -84620,7 +84624,7 @@ function detectFileExists2(directory, pattern) {
84620
84624
  function selectTestCommandFromScriptsTest(backend, directory) {
84621
84625
  let pkgRaw;
84622
84626
  try {
84623
- pkgRaw = fs113.readFileSync(path147.join(directory, "package.json"), "utf-8");
84627
+ pkgRaw = fs113.readFileSync(path148.join(directory, "package.json"), "utf-8");
84624
84628
  } catch {
84625
84629
  return null;
84626
84630
  }
@@ -84729,7 +84733,7 @@ var init_project_context = __esm(() => {
84729
84733
  init_package();
84730
84734
  init_agents2();
84731
84735
  init_critic();
84732
- import * as path148 from "node:path";
84736
+ import * as path149 from "node:path";
84733
84737
 
84734
84738
  // src/background/index.ts
84735
84739
  init_event_bus();
@@ -97595,6 +97599,10 @@ var DEFAULT_MEMORY_CONFIG = {
97595
97599
  enabled: false,
97596
97600
  provider: "local-jsonl",
97597
97601
  storageDir: ".swarm/memory",
97602
+ sqlite: {
97603
+ path: ".swarm/memory/memory.db",
97604
+ busyTimeoutMs: 5000
97605
+ },
97598
97606
  recall: {
97599
97607
  defaultMaxItems: 8,
97600
97608
  defaultTokenBudget: 1200,
@@ -97634,6 +97642,10 @@ function resolveMemoryConfig(input) {
97634
97642
  return {
97635
97643
  ...DEFAULT_MEMORY_CONFIG,
97636
97644
  ...input ?? {},
97645
+ sqlite: {
97646
+ ...DEFAULT_MEMORY_CONFIG.sqlite,
97647
+ ...input?.sqlite ?? {}
97648
+ },
97637
97649
  recall: {
97638
97650
  ...DEFAULT_MEMORY_CONFIG.recall,
97639
97651
  ...input?.recall ?? {},
@@ -97671,7 +97683,7 @@ class MemoryDisabledError extends Error {
97671
97683
  // src/memory/gateway.ts
97672
97684
  import { createHash as createHash9 } from "node:crypto";
97673
97685
  import { existsSync as existsSync50, readFileSync as readFileSync39 } from "node:fs";
97674
- import * as path96 from "node:path";
97686
+ import * as path97 from "node:path";
97675
97687
 
97676
97688
  // src/memory/local-jsonl-provider.ts
97677
97689
  init_utils2();
@@ -98373,6 +98385,367 @@ function toRecallBundle(input) {
98373
98385
  };
98374
98386
  }
98375
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
+
98376
98749
  // src/memory/gateway.ts
98377
98750
  class MemoryGateway {
98378
98751
  context;
@@ -98382,16 +98755,19 @@ class MemoryGateway {
98382
98755
  constructor(context, options = {}) {
98383
98756
  this.context = context;
98384
98757
  this.config = resolveMemoryConfig(options.config ?? DEFAULT_MEMORY_CONFIG);
98385
- this.provider = options.provider ?? new LocalJsonlMemoryProvider(context.directory, this.config);
98758
+ this.provider = options.provider ?? createConfiguredMemoryProvider(context.directory, this.config);
98386
98759
  this.now = options.now ?? (() => new Date);
98387
98760
  }
98388
98761
  isEnabled() {
98389
98762
  return this.config.enabled;
98390
98763
  }
98764
+ async dispose() {
98765
+ await this.provider.close?.();
98766
+ }
98391
98767
  deriveAllowedScopes() {
98392
- const resolvedRoot = path96.resolve(this.context.directory);
98393
- const repoId = createStableId(readGitRemoteUrl(resolvedRoot) ?? path96.basename(resolvedRoot));
98394
- 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));
98395
98771
  const scopes = [
98396
98772
  { type: "workspace", workspaceId },
98397
98773
  {
@@ -98591,6 +98967,12 @@ class MemoryGateway {
98591
98967
  function createMemoryGateway(context, options = {}) {
98592
98968
  return new MemoryGateway(context, options);
98593
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
+ }
98594
98976
  function sourceFromEvidence(evidenceRefs, context) {
98595
98977
  const first = evidenceRefs[0];
98596
98978
  if (!first) {
@@ -98612,7 +98994,7 @@ var gitRemoteUrlCache = new Map;
98612
98994
  function readGitRemoteUrl(directory) {
98613
98995
  if (gitRemoteUrlCache.has(directory))
98614
98996
  return gitRemoteUrlCache.get(directory);
98615
- const gitConfigPath = path96.join(directory, ".git", "config");
98997
+ const gitConfigPath = path97.join(directory, ".git", "config");
98616
98998
  if (!existsSync50(gitConfigPath)) {
98617
98999
  gitRemoteUrlCache.set(directory, undefined);
98618
99000
  return;
@@ -98660,7 +99042,7 @@ function scopeKey(scope) {
98660
99042
  workspaceId: scope.workspaceId,
98661
99043
  projectId: scope.projectId,
98662
99044
  repoId: scope.repoId,
98663
- repoRoot: scope.repoRoot ? path96.resolve(scope.repoRoot) : undefined,
99045
+ repoRoot: scope.repoRoot ? path97.resolve(scope.repoRoot) : undefined,
98664
99046
  runId: scope.runId,
98665
99047
  agentId: scope.agentId
98666
99048
  });
@@ -98907,12 +99289,12 @@ function buildScopesFromInput(input) {
98907
99289
  // src/memory/run-log.ts
98908
99290
  init_utils2();
98909
99291
  import { appendFile as appendFile12, mkdir as mkdir19 } from "node:fs/promises";
98910
- import * as path97 from "node:path";
99292
+ import * as path98 from "node:path";
98911
99293
  async function appendMemoryRunLog(directory, runId, event) {
98912
99294
  const safeRunId = sanitizeRunId(runId);
98913
- const relativePath = path97.join("runs", safeRunId, "memory.jsonl");
99295
+ const relativePath = path98.join("runs", safeRunId, "memory.jsonl");
98914
99296
  const filePath = validateSwarmPath(directory, relativePath);
98915
- await mkdir19(path97.dirname(filePath), { recursive: true });
99297
+ await mkdir19(path98.dirname(filePath), { recursive: true });
98916
99298
  await appendFile12(filePath, `${JSON.stringify({
98917
99299
  ...event,
98918
99300
  runId: safeRunId,
@@ -99690,16 +100072,16 @@ init_telemetry();
99690
100072
 
99691
100073
  // src/prm/replay.ts
99692
100074
  import { promises as fs68 } from "node:fs";
99693
- import path98 from "node:path";
100075
+ import path99 from "node:path";
99694
100076
  function isPathSafe2(targetPath, basePath) {
99695
- const resolvedTarget = path98.resolve(targetPath);
99696
- const resolvedBase = path98.resolve(basePath);
99697
- const rel = path98.relative(resolvedBase, resolvedTarget);
99698
- 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);
99699
100081
  }
99700
100082
  function isWithinReplaysDir(targetPath) {
99701
- const resolved = path98.resolve(targetPath);
99702
- const parts2 = resolved.split(path98.sep);
100083
+ const resolved = path99.resolve(targetPath);
100084
+ const parts2 = resolved.split(path99.sep);
99703
100085
  for (let i2 = 0;i2 < parts2.length - 1; i2++) {
99704
100086
  if (parts2[i2] === ".swarm" && parts2[i2 + 1] === "replays") {
99705
100087
  return true;
@@ -99712,10 +100094,10 @@ function sanitizeFilename(input) {
99712
100094
  }
99713
100095
  async function startReplayRecording(sessionID, directory) {
99714
100096
  try {
99715
- const replayDir = path98.join(directory, ".swarm", "replays");
100097
+ const replayDir = path99.join(directory, ".swarm", "replays");
99716
100098
  const safeSessionID = sanitizeFilename(sessionID);
99717
100099
  const filename = `${safeSessionID}-${Date.now()}.jsonl`;
99718
- const filepath = path98.join(replayDir, filename);
100100
+ const filepath = path99.join(replayDir, filename);
99719
100101
  if (!isPathSafe2(filepath, replayDir)) {
99720
100102
  console.warn(`[replay] Invalid path detected - path traversal attempt blocked for session ${sessionID}`);
99721
100103
  return null;
@@ -100096,7 +100478,7 @@ init_telemetry();
100096
100478
  init_dist();
100097
100479
  init_create_tool();
100098
100480
  import * as fs69 from "node:fs";
100099
- import * as path99 from "node:path";
100481
+ import * as path100 from "node:path";
100100
100482
  init_path_security();
100101
100483
  var WINDOWS_RESERVED_NAMES2 = /^(con|prn|aux|nul|com[1-9]|lpt[1-9])(\.|:|$)/i;
100102
100484
  function containsWindowsAttacks2(str) {
@@ -100113,14 +100495,14 @@ function containsWindowsAttacks2(str) {
100113
100495
  }
100114
100496
  function isPathInWorkspace2(filePath, workspace) {
100115
100497
  try {
100116
- const resolvedPath = path99.resolve(workspace, filePath);
100498
+ const resolvedPath = path100.resolve(workspace, filePath);
100117
100499
  if (!fs69.existsSync(resolvedPath)) {
100118
100500
  return true;
100119
100501
  }
100120
100502
  const realWorkspace = fs69.realpathSync(workspace);
100121
100503
  const realResolvedPath = fs69.realpathSync(resolvedPath);
100122
- const relativePath = path99.relative(realWorkspace, realResolvedPath);
100123
- if (relativePath.startsWith("..") || path99.isAbsolute(relativePath)) {
100504
+ const relativePath = path100.relative(realWorkspace, realResolvedPath);
100505
+ if (relativePath.startsWith("..") || path100.isAbsolute(relativePath)) {
100124
100506
  return false;
100125
100507
  }
100126
100508
  return true;
@@ -100129,7 +100511,7 @@ function isPathInWorkspace2(filePath, workspace) {
100129
100511
  }
100130
100512
  }
100131
100513
  function processFile2(file3, cwd, exportedOnly) {
100132
- const ext = path99.extname(file3);
100514
+ const ext = path100.extname(file3);
100133
100515
  if (containsControlChars(file3)) {
100134
100516
  return {
100135
100517
  file: file3,
@@ -100162,7 +100544,7 @@ function processFile2(file3, cwd, exportedOnly) {
100162
100544
  errorType: "path-outside-workspace"
100163
100545
  };
100164
100546
  }
100165
- const fullPath = path99.join(cwd, file3);
100547
+ const fullPath = path100.join(cwd, file3);
100166
100548
  if (!fs69.existsSync(fullPath)) {
100167
100549
  return {
100168
100550
  file: file3,
@@ -100454,15 +100836,15 @@ init_task_id();
100454
100836
  init_create_tool();
100455
100837
  init_resolve_working_directory();
100456
100838
  import * as fs70 from "node:fs";
100457
- import * as path100 from "node:path";
100839
+ import * as path101 from "node:path";
100458
100840
  var EVIDENCE_DIR = ".swarm/evidence";
100459
100841
  function isValidTaskId3(taskId) {
100460
100842
  return isStrictTaskId(taskId);
100461
100843
  }
100462
100844
  function isPathWithinSwarm(filePath, workspaceRoot) {
100463
- const normalizedWorkspace = path100.resolve(workspaceRoot);
100464
- const swarmPath = path100.join(normalizedWorkspace, ".swarm", "evidence");
100465
- 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);
100466
100848
  return normalizedPath.startsWith(swarmPath);
100467
100849
  }
100468
100850
  function readEvidenceFile(evidencePath) {
@@ -100543,7 +100925,7 @@ var check_gate_status = createSwarmTool({
100543
100925
  };
100544
100926
  return JSON.stringify(errorResult, null, 2);
100545
100927
  }
100546
- const evidencePath = path100.join(directory, EVIDENCE_DIR, `${taskIdInput}.json`);
100928
+ const evidencePath = path101.join(directory, EVIDENCE_DIR, `${taskIdInput}.json`);
100547
100929
  if (!isPathWithinSwarm(evidencePath, directory)) {
100548
100930
  const errorResult = {
100549
100931
  taskId: taskIdInput,
@@ -100640,7 +101022,7 @@ init_state();
100640
101022
  init_create_tool();
100641
101023
  init_resolve_working_directory();
100642
101024
  import * as fs71 from "node:fs";
100643
- import * as path101 from "node:path";
101025
+ import * as path102 from "node:path";
100644
101026
  function extractMatches(regex, text) {
100645
101027
  return Array.from(text.matchAll(regex));
100646
101028
  }
@@ -100792,10 +101174,10 @@ async function executeCompletionVerify(args2, directory) {
100792
101174
  let hasFileReadFailure = false;
100793
101175
  for (const filePath of fileTargets) {
100794
101176
  const normalizedPath = filePath.replace(/\\/g, "/");
100795
- const resolvedPath = path101.resolve(directory, normalizedPath);
100796
- const projectRoot = path101.resolve(directory);
100797
- const relative21 = path101.relative(projectRoot, resolvedPath);
100798
- 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);
100799
101181
  if (!withinProject) {
100800
101182
  blockedTasks.push({
100801
101183
  task_id: task.id,
@@ -100850,8 +101232,8 @@ async function executeCompletionVerify(args2, directory) {
100850
101232
  blockedTasks
100851
101233
  };
100852
101234
  try {
100853
- const evidenceDir = path101.join(directory, ".swarm", "evidence", `${phase}`);
100854
- 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");
100855
101237
  fs71.mkdirSync(evidenceDir, { recursive: true });
100856
101238
  const evidenceBundle = {
100857
101239
  schema_version: "1.0.0",
@@ -100928,11 +101310,11 @@ var completion_verify = createSwarmTool({
100928
101310
  // src/tools/complexity-hotspots.ts
100929
101311
  init_zod();
100930
101312
  import * as fs73 from "node:fs";
100931
- import * as path103 from "node:path";
101313
+ import * as path104 from "node:path";
100932
101314
 
100933
101315
  // src/quality/metrics.ts
100934
101316
  import * as fs72 from "node:fs";
100935
- import * as path102 from "node:path";
101317
+ import * as path103 from "node:path";
100936
101318
  var MAX_FILE_SIZE_BYTES4 = 256 * 1024;
100937
101319
  var MIN_DUPLICATION_LINES = 10;
100938
101320
  function estimateCyclomaticComplexity(content) {
@@ -100984,7 +101366,7 @@ async function computeComplexityDelta(files, workingDir) {
100984
101366
  let totalComplexity = 0;
100985
101367
  const analyzedFiles = [];
100986
101368
  for (const file3 of files) {
100987
- const fullPath = path102.isAbsolute(file3) ? file3 : path102.join(workingDir, file3);
101369
+ const fullPath = path103.isAbsolute(file3) ? file3 : path103.join(workingDir, file3);
100988
101370
  if (!fs72.existsSync(fullPath)) {
100989
101371
  continue;
100990
101372
  }
@@ -101107,7 +101489,7 @@ function countGoExports(content) {
101107
101489
  function getExportCountForFile(filePath) {
101108
101490
  try {
101109
101491
  const content = fs72.readFileSync(filePath, "utf-8");
101110
- const ext = path102.extname(filePath).toLowerCase();
101492
+ const ext = path103.extname(filePath).toLowerCase();
101111
101493
  switch (ext) {
101112
101494
  case ".ts":
101113
101495
  case ".tsx":
@@ -101133,7 +101515,7 @@ async function computePublicApiDelta(files, workingDir) {
101133
101515
  let totalExports = 0;
101134
101516
  const analyzedFiles = [];
101135
101517
  for (const file3 of files) {
101136
- const fullPath = path102.isAbsolute(file3) ? file3 : path102.join(workingDir, file3);
101518
+ const fullPath = path103.isAbsolute(file3) ? file3 : path103.join(workingDir, file3);
101137
101519
  if (!fs72.existsSync(fullPath)) {
101138
101520
  continue;
101139
101521
  }
@@ -101167,7 +101549,7 @@ async function computeDuplicationRatio(files, workingDir) {
101167
101549
  let duplicateLines = 0;
101168
101550
  const analyzedFiles = [];
101169
101551
  for (const file3 of files) {
101170
- const fullPath = path102.isAbsolute(file3) ? file3 : path102.join(workingDir, file3);
101552
+ const fullPath = path103.isAbsolute(file3) ? file3 : path103.join(workingDir, file3);
101171
101553
  if (!fs72.existsSync(fullPath)) {
101172
101554
  continue;
101173
101555
  }
@@ -101200,8 +101582,8 @@ function countCodeLines(content) {
101200
101582
  return lines.length;
101201
101583
  }
101202
101584
  function isTestFile(filePath) {
101203
- const basename15 = path102.basename(filePath);
101204
- const _ext = path102.extname(filePath).toLowerCase();
101585
+ const basename15 = path103.basename(filePath);
101586
+ const _ext = path103.extname(filePath).toLowerCase();
101205
101587
  const testPatterns = [
101206
101588
  ".test.",
101207
101589
  ".spec.",
@@ -101282,8 +101664,8 @@ function matchGlobSegment(globSegments, pathSegments) {
101282
101664
  }
101283
101665
  return gIndex === globSegments.length && pIndex === pathSegments.length;
101284
101666
  }
101285
- function matchesGlobSegment(path103, glob) {
101286
- const normalizedPath = path103.replace(/\\/g, "/");
101667
+ function matchesGlobSegment(path104, glob) {
101668
+ const normalizedPath = path104.replace(/\\/g, "/");
101287
101669
  const normalizedGlob = glob.replace(/\\/g, "/");
101288
101670
  if (normalizedPath.includes("//")) {
101289
101671
  return false;
@@ -101314,8 +101696,8 @@ function simpleGlobToRegex2(glob) {
101314
101696
  function hasGlobstar(glob) {
101315
101697
  return glob.includes("**");
101316
101698
  }
101317
- function globMatches(path103, glob) {
101318
- const normalizedPath = path103.replace(/\\/g, "/");
101699
+ function globMatches(path104, glob) {
101700
+ const normalizedPath = path104.replace(/\\/g, "/");
101319
101701
  if (!glob || glob === "") {
101320
101702
  if (normalizedPath.includes("//")) {
101321
101703
  return false;
@@ -101351,7 +101733,7 @@ function shouldExcludeFile(filePath, excludeGlobs) {
101351
101733
  async function computeTestToCodeRatio(workingDir, enforceGlobs, excludeGlobs) {
101352
101734
  let testLines = 0;
101353
101735
  let codeLines = 0;
101354
- const srcDir = path102.join(workingDir, "src");
101736
+ const srcDir = path103.join(workingDir, "src");
101355
101737
  if (fs72.existsSync(srcDir)) {
101356
101738
  await scanDirectoryForLines(srcDir, enforceGlobs, excludeGlobs, false, (lines) => {
101357
101739
  codeLines += lines;
@@ -101359,14 +101741,14 @@ async function computeTestToCodeRatio(workingDir, enforceGlobs, excludeGlobs) {
101359
101741
  }
101360
101742
  const possibleSrcDirs = ["lib", "app", "source", "core"];
101361
101743
  for (const dir of possibleSrcDirs) {
101362
- const dirPath = path102.join(workingDir, dir);
101744
+ const dirPath = path103.join(workingDir, dir);
101363
101745
  if (fs72.existsSync(dirPath)) {
101364
101746
  await scanDirectoryForLines(dirPath, enforceGlobs, excludeGlobs, false, (lines) => {
101365
101747
  codeLines += lines;
101366
101748
  });
101367
101749
  }
101368
101750
  }
101369
- const testsDir = path102.join(workingDir, "tests");
101751
+ const testsDir = path103.join(workingDir, "tests");
101370
101752
  if (fs72.existsSync(testsDir)) {
101371
101753
  await scanDirectoryForLines(testsDir, ["**"], ["node_modules", "dist"], true, (lines) => {
101372
101754
  testLines += lines;
@@ -101374,7 +101756,7 @@ async function computeTestToCodeRatio(workingDir, enforceGlobs, excludeGlobs) {
101374
101756
  }
101375
101757
  const possibleTestDirs = ["test", "__tests__", "specs"];
101376
101758
  for (const dir of possibleTestDirs) {
101377
- const dirPath = path102.join(workingDir, dir);
101759
+ const dirPath = path103.join(workingDir, dir);
101378
101760
  if (fs72.existsSync(dirPath) && dirPath !== testsDir) {
101379
101761
  await scanDirectoryForLines(dirPath, ["**"], ["node_modules", "dist"], true, (lines) => {
101380
101762
  testLines += lines;
@@ -101389,7 +101771,7 @@ async function scanDirectoryForLines(dirPath, includeGlobs, excludeGlobs, isTest
101389
101771
  try {
101390
101772
  const entries = fs72.readdirSync(dirPath, { withFileTypes: true });
101391
101773
  for (const entry of entries) {
101392
- const fullPath = path102.join(dirPath, entry.name);
101774
+ const fullPath = path103.join(dirPath, entry.name);
101393
101775
  if (entry.isDirectory()) {
101394
101776
  if (entry.name === "node_modules" || entry.name === "dist" || entry.name === "build" || entry.name === ".git") {
101395
101777
  continue;
@@ -101397,7 +101779,7 @@ async function scanDirectoryForLines(dirPath, includeGlobs, excludeGlobs, isTest
101397
101779
  await scanDirectoryForLines(fullPath, includeGlobs, excludeGlobs, isTestScan, callback);
101398
101780
  } else if (entry.isFile()) {
101399
101781
  const relativePath = fullPath.replace(`${dirPath}/`, "");
101400
- const ext = path102.extname(entry.name).toLowerCase();
101782
+ const ext = path103.extname(entry.name).toLowerCase();
101401
101783
  const validExts = [
101402
101784
  ".ts",
101403
101785
  ".tsx",
@@ -101648,7 +102030,7 @@ async function analyzeHotspots(days, topN, extensions, directory) {
101648
102030
  const extSet = new Set(extensions.map((e) => e.startsWith(".") ? e : `.${e}`));
101649
102031
  const filteredChurn = new Map;
101650
102032
  for (const [file3, count] of churnMap) {
101651
- const ext = path103.extname(file3).toLowerCase();
102033
+ const ext = path104.extname(file3).toLowerCase();
101652
102034
  if (extSet.has(ext)) {
101653
102035
  filteredChurn.set(file3, count);
101654
102036
  }
@@ -101659,7 +102041,7 @@ async function analyzeHotspots(days, topN, extensions, directory) {
101659
102041
  for (const [file3, churnCount] of filteredChurn) {
101660
102042
  let fullPath = file3;
101661
102043
  if (!fs73.existsSync(fullPath)) {
101662
- fullPath = path103.join(cwd, file3);
102044
+ fullPath = path104.join(cwd, file3);
101663
102045
  }
101664
102046
  const complexity = getComplexityForFile2(fullPath);
101665
102047
  if (complexity !== null) {
@@ -101827,7 +102209,7 @@ ${body2}`);
101827
102209
 
101828
102210
  // src/council/council-evidence-writer.ts
101829
102211
  init_task_file();
101830
- 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";
101831
102213
  import { join as join88 } from "node:path";
101832
102214
  var EVIDENCE_DIR2 = ".swarm/evidence";
101833
102215
  var VALID_TASK_ID = /^\d+\.\d+(\.\d+)*$/;
@@ -101866,7 +102248,7 @@ async function writeCouncilEvidence(workingDir, synthesis) {
101866
102248
  throw new Error(`writeCouncilEvidence: invalid taskId "${synthesis.taskId}" — must match N.M or N.M.P format`);
101867
102249
  }
101868
102250
  const dir = join88(workingDir, EVIDENCE_DIR2);
101869
- mkdirSync25(dir, { recursive: true });
102251
+ mkdirSync26(dir, { recursive: true });
101870
102252
  const filePath = taskEvidencePath(workingDir, synthesis.taskId);
101871
102253
  await _internals45.withTaskEvidenceLock(workingDir, synthesis.taskId, COUNCIL_AGENT_ID, async () => {
101872
102254
  const existingRoot = Object.create(null);
@@ -101904,7 +102286,7 @@ async function writeCouncilEvidence(workingDir, synthesis) {
101904
102286
  });
101905
102287
  try {
101906
102288
  const councilDir = join88(workingDir, ".swarm", "council");
101907
- mkdirSync25(councilDir, { recursive: true });
102289
+ mkdirSync26(councilDir, { recursive: true });
101908
102290
  const auditLine = JSON.stringify({
101909
102291
  round: synthesis.roundNumber,
101910
102292
  verdict: synthesis.overallVerdict,
@@ -102233,12 +102615,12 @@ function buildFinalCouncilFeedback(projectSummary, verdict, vetoedBy, requiredFi
102233
102615
  }
102234
102616
 
102235
102617
  // src/council/criteria-store.ts
102236
- 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";
102237
102619
  import { join as join89 } from "node:path";
102238
102620
  var COUNCIL_DIR = ".swarm/council";
102239
102621
  function writeCriteria(workingDir, taskId, criteria) {
102240
102622
  const dir = join89(workingDir, COUNCIL_DIR);
102241
- mkdirSync26(dir, { recursive: true });
102623
+ mkdirSync27(dir, { recursive: true });
102242
102624
  const payload = {
102243
102625
  taskId,
102244
102626
  criteria,
@@ -102400,7 +102782,7 @@ var submit_council_verdicts = createSwarmTool({
102400
102782
  init_zod();
102401
102783
  init_loader();
102402
102784
  import * as fs74 from "node:fs";
102403
- import * as path104 from "node:path";
102785
+ import * as path105 from "node:path";
102404
102786
 
102405
102787
  // src/council/general-council-advisory.ts
102406
102788
  var ADVISORY_HEADER = "[general_council] (advisory; not blocking)";
@@ -102828,10 +103210,10 @@ var convene_general_council = createSwarmTool({
102828
103210
  const round1 = input.round1Responses;
102829
103211
  const round2 = input.round2Responses ?? [];
102830
103212
  const result = synthesizeGeneralCouncil(input.question, input.mode, round1, round2);
102831
- const evidenceDir = path104.join(workingDir, ".swarm", "council", "general");
103213
+ const evidenceDir = path105.join(workingDir, ".swarm", "council", "general");
102832
103214
  const safeTimestamp = result.timestamp.replace(/[:.]/g, "-");
102833
103215
  const evidenceFile = `${safeTimestamp}-${input.mode}.json`;
102834
- const evidencePath = path104.join(evidenceDir, evidenceFile);
103216
+ const evidencePath = path105.join(evidenceDir, evidenceFile);
102835
103217
  try {
102836
103218
  await fs74.promises.mkdir(evidenceDir, { recursive: true });
102837
103219
  await fs74.promises.writeFile(evidencePath, JSON.stringify(result, null, 2));
@@ -103076,7 +103458,7 @@ init_state();
103076
103458
  init_task_id();
103077
103459
  init_create_tool();
103078
103460
  import * as fs75 from "node:fs";
103079
- import * as path105 from "node:path";
103461
+ import * as path106 from "node:path";
103080
103462
  function validateTaskIdFormat2(taskId) {
103081
103463
  return validateTaskIdFormat(taskId);
103082
103464
  }
@@ -103150,8 +103532,8 @@ async function executeDeclareScope(args2, fallbackDir) {
103150
103532
  };
103151
103533
  }
103152
103534
  }
103153
- normalizedDir = path105.normalize(args2.working_directory);
103154
- const pathParts = normalizedDir.split(path105.sep);
103535
+ normalizedDir = path106.normalize(args2.working_directory);
103536
+ const pathParts = normalizedDir.split(path106.sep);
103155
103537
  if (pathParts.includes("..")) {
103156
103538
  return {
103157
103539
  success: false,
@@ -103161,10 +103543,10 @@ async function executeDeclareScope(args2, fallbackDir) {
103161
103543
  ]
103162
103544
  };
103163
103545
  }
103164
- const resolvedDir = path105.resolve(normalizedDir);
103546
+ const resolvedDir = path106.resolve(normalizedDir);
103165
103547
  try {
103166
103548
  const realPath = fs75.realpathSync(resolvedDir);
103167
- const planPath2 = path105.join(realPath, ".swarm", "plan.json");
103549
+ const planPath2 = path106.join(realPath, ".swarm", "plan.json");
103168
103550
  if (!fs75.existsSync(planPath2)) {
103169
103551
  return {
103170
103552
  success: false,
@@ -103185,9 +103567,9 @@ async function executeDeclareScope(args2, fallbackDir) {
103185
103567
  }
103186
103568
  if (normalizedDir && fallbackDir) {
103187
103569
  try {
103188
- const canonicalWorkingDir = fs75.realpathSync(path105.resolve(normalizedDir));
103189
- const canonicalProjectRoot = fs75.realpathSync(path105.resolve(fallbackDir));
103190
- 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)) {
103191
103573
  return {
103192
103574
  success: false,
103193
103575
  message: `working_directory "${normalizedDir}" is a subdirectory of the project root. Use the project root "${fallbackDir}" instead.`,
@@ -103209,7 +103591,7 @@ async function executeDeclareScope(args2, fallbackDir) {
103209
103591
  };
103210
103592
  }
103211
103593
  const directory = normalizedDir || fallbackDir;
103212
- const planPath = path105.resolve(directory, ".swarm", "plan.json");
103594
+ const planPath = path106.resolve(directory, ".swarm", "plan.json");
103213
103595
  if (!fs75.existsSync(planPath)) {
103214
103596
  return {
103215
103597
  success: false,
@@ -103249,8 +103631,8 @@ async function executeDeclareScope(args2, fallbackDir) {
103249
103631
  const normalizeErrors = [];
103250
103632
  const dir = directory;
103251
103633
  const mergedFiles = rawMergedFiles.map((file3) => {
103252
- if (path105.isAbsolute(file3)) {
103253
- const relativePath = path105.relative(dir, file3).replace(/\\/g, "/");
103634
+ if (path106.isAbsolute(file3)) {
103635
+ const relativePath = path106.relative(dir, file3).replace(/\\/g, "/");
103254
103636
  if (relativePath.startsWith("..")) {
103255
103637
  normalizeErrors.push(`Path '${file3}' resolves outside the project directory`);
103256
103638
  return file3;
@@ -103311,7 +103693,7 @@ var declare_scope = createSwarmTool({
103311
103693
  init_zod();
103312
103694
  import * as child_process7 from "node:child_process";
103313
103695
  import * as fs76 from "node:fs";
103314
- import * as path106 from "node:path";
103696
+ import * as path107 from "node:path";
103315
103697
  init_create_tool();
103316
103698
  var MAX_DIFF_LINES = 500;
103317
103699
  var DIFF_TIMEOUT_MS = 30000;
@@ -103340,20 +103722,20 @@ function validateBase(base) {
103340
103722
  function validatePaths(paths) {
103341
103723
  if (!paths)
103342
103724
  return null;
103343
- for (const path107 of paths) {
103344
- if (!path107 || path107.length === 0) {
103725
+ for (const path108 of paths) {
103726
+ if (!path108 || path108.length === 0) {
103345
103727
  return "empty path not allowed";
103346
103728
  }
103347
- if (path107.length > MAX_PATH_LENGTH) {
103729
+ if (path108.length > MAX_PATH_LENGTH) {
103348
103730
  return `path exceeds maximum length of ${MAX_PATH_LENGTH}`;
103349
103731
  }
103350
- if (SHELL_METACHARACTERS2.test(path107)) {
103732
+ if (SHELL_METACHARACTERS2.test(path108)) {
103351
103733
  return "path contains shell metacharacters";
103352
103734
  }
103353
- if (path107.startsWith("-")) {
103735
+ if (path108.startsWith("-")) {
103354
103736
  return 'path cannot start with "-" (option-like arguments not allowed)';
103355
103737
  }
103356
- if (CONTROL_CHAR_PATTERN2.test(path107)) {
103738
+ if (CONTROL_CHAR_PATTERN2.test(path108)) {
103357
103739
  return "path contains control characters";
103358
103740
  }
103359
103741
  }
@@ -103461,8 +103843,8 @@ var diff = createSwarmTool({
103461
103843
  if (parts2.length >= 3) {
103462
103844
  const additions = parseInt(parts2[0], 10) || 0;
103463
103845
  const deletions = parseInt(parts2[1], 10) || 0;
103464
- const path107 = parts2[2];
103465
- files.push({ path: path107, additions, deletions });
103846
+ const path108 = parts2[2];
103847
+ files.push({ path: path108, additions, deletions });
103466
103848
  }
103467
103849
  }
103468
103850
  const contractChanges = [];
@@ -103502,7 +103884,7 @@ var diff = createSwarmTool({
103502
103884
  } else if (base === "unstaged") {
103503
103885
  const oldRef = `:${file3.path}`;
103504
103886
  oldContent = fileExistsInRef(oldRef) ? getContentFromRef(oldRef) : "";
103505
- newContent = fs76.readFileSync(path106.join(directory, file3.path), "utf-8");
103887
+ newContent = fs76.readFileSync(path107.join(directory, file3.path), "utf-8");
103506
103888
  } else {
103507
103889
  const oldRef = `${base}:${file3.path}`;
103508
103890
  oldContent = fileExistsInRef(oldRef) ? getContentFromRef(oldRef) : "";
@@ -103577,7 +103959,7 @@ var diff = createSwarmTool({
103577
103959
  init_zod();
103578
103960
  import * as child_process8 from "node:child_process";
103579
103961
  import * as fs77 from "node:fs";
103580
- import * as path107 from "node:path";
103962
+ import * as path108 from "node:path";
103581
103963
  init_create_tool();
103582
103964
  init_resolve_working_directory();
103583
103965
  var diff_summary = createSwarmTool({
@@ -103630,7 +104012,7 @@ var diff_summary = createSwarmTool({
103630
104012
  }
103631
104013
  try {
103632
104014
  let oldContent;
103633
- const newContent = fs77.readFileSync(path107.join(workingDir, filePath), "utf-8");
104015
+ const newContent = fs77.readFileSync(path108.join(workingDir, filePath), "utf-8");
103634
104016
  if (fileExistsInHead) {
103635
104017
  oldContent = child_process8.execFileSync("git", ["show", `HEAD:${filePath}`], {
103636
104018
  encoding: "utf-8",
@@ -103859,7 +104241,7 @@ init_zod();
103859
104241
  init_create_tool();
103860
104242
  init_path_security();
103861
104243
  import * as fs78 from "node:fs";
103862
- import * as path108 from "node:path";
104244
+ import * as path109 from "node:path";
103863
104245
  var MAX_FILE_SIZE_BYTES6 = 1024 * 1024;
103864
104246
  var MAX_EVIDENCE_FILES = 1000;
103865
104247
  var EVIDENCE_DIR3 = ".swarm/evidence";
@@ -103886,9 +104268,9 @@ function validateRequiredTypes(input) {
103886
104268
  return null;
103887
104269
  }
103888
104270
  function isPathWithinSwarm2(filePath, cwd) {
103889
- const normalizedCwd = path108.resolve(cwd);
103890
- const swarmPath = path108.join(normalizedCwd, ".swarm");
103891
- const normalizedPath = path108.resolve(filePath);
104271
+ const normalizedCwd = path109.resolve(cwd);
104272
+ const swarmPath = path109.join(normalizedCwd, ".swarm");
104273
+ const normalizedPath = path109.resolve(filePath);
103892
104274
  return normalizedPath.startsWith(swarmPath);
103893
104275
  }
103894
104276
  function parseCompletedTasks(planContent) {
@@ -103918,10 +104300,10 @@ function readEvidenceFiles(evidenceDir, _cwd) {
103918
104300
  if (!VALID_EVIDENCE_FILENAME_REGEX.test(filename)) {
103919
104301
  continue;
103920
104302
  }
103921
- const filePath = path108.join(evidenceDir, filename);
104303
+ const filePath = path109.join(evidenceDir, filename);
103922
104304
  try {
103923
- const resolvedPath = path108.resolve(filePath);
103924
- const evidenceDirResolved = path108.resolve(evidenceDir);
104305
+ const resolvedPath = path109.resolve(filePath);
104306
+ const evidenceDirResolved = path109.resolve(evidenceDir);
103925
104307
  if (!resolvedPath.startsWith(evidenceDirResolved)) {
103926
104308
  continue;
103927
104309
  }
@@ -104039,7 +104421,7 @@ var evidence_check = createSwarmTool({
104039
104421
  return JSON.stringify(errorResult, null, 2);
104040
104422
  }
104041
104423
  const requiredTypes = requiredTypesValue.split(",").map((t) => t.trim()).filter((t) => t.length > 0).map(normalizeEvidenceType);
104042
- const planPath = path108.join(cwd, PLAN_FILE);
104424
+ const planPath = path109.join(cwd, PLAN_FILE);
104043
104425
  if (!isPathWithinSwarm2(planPath, cwd)) {
104044
104426
  const errorResult = {
104045
104427
  error: "plan file path validation failed",
@@ -104071,7 +104453,7 @@ var evidence_check = createSwarmTool({
104071
104453
  };
104072
104454
  return JSON.stringify(result2, null, 2);
104073
104455
  }
104074
- const evidenceDir = path108.join(cwd, EVIDENCE_DIR3);
104456
+ const evidenceDir = path109.join(cwd, EVIDENCE_DIR3);
104075
104457
  const evidence = readEvidenceFiles(evidenceDir, cwd);
104076
104458
  const { tasksWithFullEvidence, gaps } = analyzeGaps(completedTasks, evidence, requiredTypes);
104077
104459
  const completeness = completedTasks.length > 0 ? Math.round(tasksWithFullEvidence.length / completedTasks.length * 100) / 100 : 1;
@@ -104089,7 +104471,7 @@ var evidence_check = createSwarmTool({
104089
104471
  init_zod();
104090
104472
  init_create_tool();
104091
104473
  import * as fs79 from "node:fs";
104092
- import * as path109 from "node:path";
104474
+ import * as path110 from "node:path";
104093
104475
  var EXT_MAP = {
104094
104476
  python: ".py",
104095
104477
  py: ".py",
@@ -104170,12 +104552,12 @@ var extract_code_blocks = createSwarmTool({
104170
104552
  if (prefix) {
104171
104553
  filename = `${prefix}_${filename}`;
104172
104554
  }
104173
- let filepath = path109.join(targetDir, filename);
104174
- const base = path109.basename(filepath, path109.extname(filepath));
104175
- 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);
104176
104558
  let counter = 1;
104177
104559
  while (fs79.existsSync(filepath)) {
104178
- filepath = path109.join(targetDir, `${base}_${counter}${ext}`);
104560
+ filepath = path110.join(targetDir, `${base}_${counter}${ext}`);
104179
104561
  counter++;
104180
104562
  }
104181
104563
  try {
@@ -104433,7 +104815,7 @@ init_zod();
104433
104815
  init_create_tool();
104434
104816
  init_path_security();
104435
104817
  import * as fs80 from "node:fs";
104436
- import * as path110 from "node:path";
104818
+ import * as path111 from "node:path";
104437
104819
  var MAX_FILE_PATH_LENGTH2 = 500;
104438
104820
  var MAX_SYMBOL_LENGTH = 256;
104439
104821
  var MAX_FILE_SIZE_BYTES7 = 1024 * 1024;
@@ -104481,7 +104863,7 @@ function validateSymbolInput(symbol3) {
104481
104863
  return null;
104482
104864
  }
104483
104865
  function isBinaryFile2(filePath, buffer) {
104484
- const ext = path110.extname(filePath).toLowerCase();
104866
+ const ext = path111.extname(filePath).toLowerCase();
104485
104867
  if (ext === ".json" || ext === ".md" || ext === ".txt") {
104486
104868
  return false;
104487
104869
  }
@@ -104505,15 +104887,15 @@ function parseImports(content, targetFile, targetSymbol) {
104505
104887
  const imports = [];
104506
104888
  let _resolvedTarget;
104507
104889
  try {
104508
- _resolvedTarget = path110.resolve(targetFile);
104890
+ _resolvedTarget = path111.resolve(targetFile);
104509
104891
  } catch {
104510
104892
  _resolvedTarget = targetFile;
104511
104893
  }
104512
- const targetBasename = path110.basename(targetFile, path110.extname(targetFile));
104894
+ const targetBasename = path111.basename(targetFile, path111.extname(targetFile));
104513
104895
  const targetWithExt = targetFile;
104514
104896
  const targetWithoutExt = targetFile.replace(/\.(ts|tsx|js|jsx|mjs|cjs)$/i, "");
104515
- const normalizedTargetWithExt = path110.normalize(targetWithExt).replace(/\\/g, "/");
104516
- const normalizedTargetWithoutExt = path110.normalize(targetWithoutExt).replace(/\\/g, "/");
104897
+ const normalizedTargetWithExt = path111.normalize(targetWithExt).replace(/\\/g, "/");
104898
+ const normalizedTargetWithoutExt = path111.normalize(targetWithoutExt).replace(/\\/g, "/");
104517
104899
  const importRegex = /import\s+(?:\{[\s\S]*?\}|(?:\*\s+as\s+\w+)|\w+)\s+from\s+['"`]([^'"`]+)['"`]|import\s+['"`]([^'"`]+)['"`]|require\s*\(\s*['"`]([^'"`]+)['"`]\s*\)/g;
104518
104900
  for (let match = importRegex.exec(content);match !== null; match = importRegex.exec(content)) {
104519
104901
  const modulePath = match[1] || match[2] || match[3];
@@ -104536,9 +104918,9 @@ function parseImports(content, targetFile, targetSymbol) {
104536
104918
  }
104537
104919
  const _normalizedModule = modulePath.replace(/^\.\//, "").replace(/^\.\.\\/, "../");
104538
104920
  let isMatch = false;
104539
- const _targetDir = path110.dirname(targetFile);
104540
- const targetExt = path110.extname(targetFile);
104541
- 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);
104542
104924
  const moduleNormalized = modulePath.replace(/\\/g, "/").replace(/^\.\//, "");
104543
104925
  const moduleName = modulePath.split(/[/\\]/).pop() || "";
104544
104926
  const moduleNameNoExt = moduleName.replace(/\.(ts|tsx|js|jsx|mjs|cjs)$/i, "");
@@ -104606,10 +104988,10 @@ function findSourceFiles2(dir, files = [], stats = { skippedDirs: [], skippedFil
104606
104988
  entries.sort((a, b) => a.toLowerCase().localeCompare(b.toLowerCase()));
104607
104989
  for (const entry of entries) {
104608
104990
  if (SKIP_DIRECTORIES4.has(entry)) {
104609
- stats.skippedDirs.push(path110.join(dir, entry));
104991
+ stats.skippedDirs.push(path111.join(dir, entry));
104610
104992
  continue;
104611
104993
  }
104612
- const fullPath = path110.join(dir, entry);
104994
+ const fullPath = path111.join(dir, entry);
104613
104995
  let stat8;
104614
104996
  try {
104615
104997
  stat8 = fs80.statSync(fullPath);
@@ -104623,7 +105005,7 @@ function findSourceFiles2(dir, files = [], stats = { skippedDirs: [], skippedFil
104623
105005
  if (stat8.isDirectory()) {
104624
105006
  findSourceFiles2(fullPath, files, stats);
104625
105007
  } else if (stat8.isFile()) {
104626
- const ext = path110.extname(fullPath).toLowerCase();
105008
+ const ext = path111.extname(fullPath).toLowerCase();
104627
105009
  if (SUPPORTED_EXTENSIONS3.includes(ext)) {
104628
105010
  files.push(fullPath);
104629
105011
  }
@@ -104680,7 +105062,7 @@ var imports = createSwarmTool({
104680
105062
  return JSON.stringify(errorResult, null, 2);
104681
105063
  }
104682
105064
  try {
104683
- const targetFile = path110.resolve(file3);
105065
+ const targetFile = path111.resolve(file3);
104684
105066
  if (!fs80.existsSync(targetFile)) {
104685
105067
  const errorResult = {
104686
105068
  error: `target file not found: ${file3}`,
@@ -104702,7 +105084,7 @@ var imports = createSwarmTool({
104702
105084
  };
104703
105085
  return JSON.stringify(errorResult, null, 2);
104704
105086
  }
104705
- const baseDir = path110.dirname(targetFile);
105087
+ const baseDir = path111.dirname(targetFile);
104706
105088
  const scanStats = {
104707
105089
  skippedDirs: [],
104708
105090
  skippedFiles: 0,
@@ -104787,7 +105169,7 @@ var imports = createSwarmTool({
104787
105169
  });
104788
105170
  // src/tools/knowledge-ack.ts
104789
105171
  init_zod();
104790
- import { randomUUID as randomUUID9 } from "node:crypto";
105172
+ import { randomUUID as randomUUID10 } from "node:crypto";
104791
105173
  init_state();
104792
105174
  init_logger();
104793
105175
  init_create_tool();
@@ -104820,7 +105202,7 @@ var knowledge_ack = createSwarmTool({
104820
105202
  let sessionId = ctx?.sessionID;
104821
105203
  if (!sessionId) {
104822
105204
  warn("[knowledge-ack] No sessionID in tool context — dedup disabled for this acknowledgment");
104823
- sessionId = randomUUID9();
105205
+ sessionId = randomUUID10();
104824
105206
  }
104825
105207
  const dedupKey = buildAckDedupKey(sessionId, a.id, a.result);
104826
105208
  if (swarmState.knowledgeAckDedup.has(dedupKey)) {
@@ -104850,7 +105232,7 @@ init_knowledge_store();
104850
105232
  init_knowledge_validator();
104851
105233
  init_manager();
104852
105234
  init_create_tool();
104853
- import { randomUUID as randomUUID10 } from "node:crypto";
105235
+ import { randomUUID as randomUUID11 } from "node:crypto";
104854
105236
  var VALID_CATEGORIES2 = [
104855
105237
  "process",
104856
105238
  "architecture",
@@ -104924,7 +105306,7 @@ var knowledge_add = createSwarmTool({
104924
105306
  project_name = plan?.title ?? "";
104925
105307
  } catch {}
104926
105308
  const entry = {
104927
- id: randomUUID10(),
105309
+ id: randomUUID11(),
104928
105310
  tier: "swarm",
104929
105311
  lesson,
104930
105312
  category,
@@ -105327,22 +105709,22 @@ init_schema();
105327
105709
  init_qa_gate_profile();
105328
105710
  init_manager2();
105329
105711
  import * as fs85 from "node:fs";
105330
- import * as path115 from "node:path";
105712
+ import * as path116 from "node:path";
105331
105713
 
105332
105714
  // src/full-auto/phase-approval.ts
105333
105715
  init_utils2();
105334
105716
  init_logger();
105335
105717
  init_state2();
105336
105718
  import * as fs81 from "node:fs";
105337
- import * as path111 from "node:path";
105719
+ import * as path112 from "node:path";
105338
105720
  var APPROVAL_TTL_MS = 24 * 60 * 60 * 1000;
105339
105721
  function readEvidenceDir(directory, phase) {
105340
105722
  try {
105341
- const dirPath = validateSwarmPath(directory, path111.posix.join("evidence", String(phase)));
105723
+ const dirPath = validateSwarmPath(directory, path112.posix.join("evidence", String(phase)));
105342
105724
  if (!fs81.existsSync(dirPath))
105343
105725
  return [];
105344
105726
  const entries = fs81.readdirSync(dirPath);
105345
- 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));
105346
105728
  } catch {
105347
105729
  return [];
105348
105730
  }
@@ -105481,16 +105863,16 @@ init_plan_schema();
105481
105863
  init_ledger();
105482
105864
  init_manager();
105483
105865
  import * as fs82 from "node:fs";
105484
- import * as path112 from "node:path";
105866
+ import * as path113 from "node:path";
105485
105867
  async function writeCheckpoint(directory) {
105486
105868
  try {
105487
105869
  const plan = await loadPlan(directory);
105488
105870
  if (!plan)
105489
105871
  return;
105490
- const swarmDir = path112.join(directory, ".swarm");
105872
+ const swarmDir = path113.join(directory, ".swarm");
105491
105873
  fs82.mkdirSync(swarmDir, { recursive: true });
105492
- const jsonPath = path112.join(swarmDir, "SWARM_PLAN.json");
105493
- 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");
105494
105876
  fs82.writeFileSync(jsonPath, JSON.stringify(plan, null, 2), "utf8");
105495
105877
  const md = derivePlanMarkdown(plan);
105496
105878
  fs82.writeFileSync(mdPath, md, "utf8");
@@ -105509,15 +105891,15 @@ init_telemetry();
105509
105891
  // src/turbo/lean/phase-ready.ts
105510
105892
  init_file_locks();
105511
105893
  import * as fs84 from "node:fs";
105512
- import * as path114 from "node:path";
105894
+ import * as path115 from "node:path";
105513
105895
 
105514
105896
  // src/turbo/lean/evidence.ts
105515
105897
  init_bun_compat();
105516
105898
  import { rmSync as rmSync6 } from "node:fs";
105517
105899
  import * as fs83 from "node:fs/promises";
105518
- import * as path113 from "node:path";
105900
+ import * as path114 from "node:path";
105519
105901
  function leanTurboEvidenceDir(directory, phase) {
105520
- return path113.join(directory, ".swarm", "evidence", String(phase), "lean-turbo");
105902
+ return path114.join(directory, ".swarm", "evidence", String(phase), "lean-turbo");
105521
105903
  }
105522
105904
  function validateLaneId(laneId) {
105523
105905
  if (laneId.length === 0) {
@@ -105539,16 +105921,16 @@ function validateLaneId(laneId) {
105539
105921
  function laneEvidencePath(directory, phase, laneId) {
105540
105922
  validateLaneId(laneId);
105541
105923
  const expectedDir = leanTurboEvidenceDir(directory, phase);
105542
- const resolvedPath = path113.resolve(path113.join(expectedDir, `${laneId}.json`));
105543
- const resolvedDir = path113.resolve(expectedDir);
105544
- 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) {
105545
105927
  throw new Error(`Invalid laneId: path traversal detected (got "${laneId}")`);
105546
105928
  }
105547
105929
  return resolvedPath;
105548
105930
  }
105549
105931
  async function atomicWriteJson(filePath, data) {
105550
105932
  const content = JSON.stringify(data, null, 2);
105551
- const dir = path113.dirname(filePath);
105933
+ const dir = path114.dirname(filePath);
105552
105934
  await fs83.mkdir(dir, { recursive: true });
105553
105935
  const tempPath = `${filePath}.tmp.${process.pid}.${Date.now()}.${Math.random().toString(36).slice(2)}`;
105554
105936
  try {
@@ -105562,7 +105944,7 @@ async function atomicWriteJson(filePath, data) {
105562
105944
  }
105563
105945
  }
105564
105946
  function phaseEvidencePath(directory, phase) {
105565
- return path113.join(leanTurboEvidenceDir(directory, phase), "lean-turbo-phase.json");
105947
+ return path114.join(leanTurboEvidenceDir(directory, phase), "lean-turbo-phase.json");
105566
105948
  }
105567
105949
  async function writeLaneEvidence(directory, phase, evidence) {
105568
105950
  const targetPath = laneEvidencePath(directory, phase, evidence.laneId);
@@ -105606,7 +105988,7 @@ async function listLaneEvidence(directory, phase) {
105606
105988
  if (entry === "lean-turbo-phase.json") {
105607
105989
  continue;
105608
105990
  }
105609
- const filePath = path113.join(evidenceDir, entry);
105991
+ const filePath = path114.join(evidenceDir, entry);
105610
105992
  let content;
105611
105993
  try {
105612
105994
  content = await fs83.readFile(filePath, "utf-8");
@@ -105630,7 +106012,7 @@ var DEFAULT_CONFIG2 = {
105630
106012
  };
105631
106013
  function defaultReadPlanJson(dir) {
105632
106014
  try {
105633
- const planPath = path114.join(dir, ".swarm", "plan.json");
106015
+ const planPath = path115.join(dir, ".swarm", "plan.json");
105634
106016
  if (!fs84.existsSync(planPath))
105635
106017
  return null;
105636
106018
  const raw = fs84.readFileSync(planPath, "utf-8");
@@ -105645,7 +106027,7 @@ function defaultReadPlanJson(dir) {
105645
106027
  }
105646
106028
  function readReviewerEvidenceFromFile(directory, phase) {
105647
106029
  try {
105648
- 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");
105649
106031
  if (!fs84.existsSync(evidencePath)) {
105650
106032
  return null;
105651
106033
  }
@@ -105665,7 +106047,7 @@ function readReviewerEvidenceFromFile(directory, phase) {
105665
106047
  }
105666
106048
  function readCriticEvidenceFromFile(directory, phase) {
105667
106049
  try {
105668
- 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");
105669
106051
  if (!fs84.existsSync(evidencePath)) {
105670
106052
  return null;
105671
106053
  }
@@ -105684,7 +106066,7 @@ function readCriticEvidenceFromFile(directory, phase) {
105684
106066
  }
105685
106067
  }
105686
106068
  function listLaneEvidenceSync(directory, phase) {
105687
- const evidenceDir = path114.join(directory, ".swarm", "evidence", String(phase), "lean-turbo");
106069
+ const evidenceDir = path115.join(directory, ".swarm", "evidence", String(phase), "lean-turbo");
105688
106070
  let entries;
105689
106071
  try {
105690
106072
  entries = fs84.readdirSync(evidenceDir);
@@ -105754,7 +106136,7 @@ function verifyLeanTurboPhaseReady(directory, phase, sessionIDOrConfig, config3)
105754
106136
  ...DEFAULT_CONFIG2,
105755
106137
  ...actualConfig
105756
106138
  };
105757
- const statePath = path114.join(directory, ".swarm", "turbo-state.json");
106139
+ const statePath = path115.join(directory, ".swarm", "turbo-state.json");
105758
106140
  if (!fs84.existsSync(statePath)) {
105759
106141
  return {
105760
106142
  ok: false,
@@ -105942,7 +106324,7 @@ function verifyLeanTurboPhaseReady(directory, phase, sessionIDOrConfig, config3)
105942
106324
  }
105943
106325
  }
105944
106326
  if (mergedConfig.integrated_diff_required) {
105945
- 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");
105946
106328
  let hasDiff = false;
105947
106329
  try {
105948
106330
  const content = fs84.readFileSync(evidencePath, "utf-8");
@@ -106237,7 +106619,7 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
106237
106619
  let driftCheckEnabled = true;
106238
106620
  let driftHasSpecMd = false;
106239
106621
  try {
106240
- const specMdPath = path115.join(dir, ".swarm", "spec.md");
106622
+ const specMdPath = path116.join(dir, ".swarm", "spec.md");
106241
106623
  driftHasSpecMd = fs85.existsSync(specMdPath);
106242
106624
  const gatePlan = await loadPlan(dir);
106243
106625
  if (gatePlan) {
@@ -106258,7 +106640,7 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
106258
106640
  } else {
106259
106641
  let phaseType;
106260
106642
  try {
106261
- const planPath = path115.join(dir, ".swarm", "plan.json");
106643
+ const planPath = path116.join(dir, ".swarm", "plan.json");
106262
106644
  if (fs85.existsSync(planPath)) {
106263
106645
  const planRaw = fs85.readFileSync(planPath, "utf-8");
106264
106646
  const plan = JSON.parse(planRaw);
@@ -106270,7 +106652,7 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
106270
106652
  warnings.push(`Phase ${phase} is annotated as 'non-code'. Drift verification was skipped per phase type annotation.`);
106271
106653
  } else {
106272
106654
  try {
106273
- 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");
106274
106656
  let driftVerdictFound = false;
106275
106657
  let driftVerdictApproved = false;
106276
106658
  try {
@@ -106308,7 +106690,7 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
106308
106690
  let incompleteTaskCount = 0;
106309
106691
  let planParseable = false;
106310
106692
  try {
106311
- const planPath = path115.join(dir, ".swarm", "plan.json");
106693
+ const planPath = path116.join(dir, ".swarm", "plan.json");
106312
106694
  if (fs85.existsSync(planPath)) {
106313
106695
  const planRaw = fs85.readFileSync(planPath, "utf-8");
106314
106696
  const plan = JSON.parse(planRaw);
@@ -106375,7 +106757,7 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
106375
106757
  const overrides = session2?.qaGateSessionOverrides ?? {};
106376
106758
  const effective = getEffectiveGates(profile, overrides);
106377
106759
  if (effective.hallucination_guard === true) {
106378
- 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");
106379
106761
  let hgVerdictFound = false;
106380
106762
  let hgVerdictApproved = false;
106381
106763
  try {
@@ -106447,7 +106829,7 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
106447
106829
  const overrides = session2?.qaGateSessionOverrides ?? {};
106448
106830
  const effective = getEffectiveGates(profile, overrides);
106449
106831
  if (effective.mutation_test === true) {
106450
- 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");
106451
106833
  let mgVerdictFound = false;
106452
106834
  let mgVerdict;
106453
106835
  try {
@@ -106521,7 +106903,7 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
106521
106903
  const effective = getEffectiveGates(profile, overrides);
106522
106904
  if (effective.council_mode === true) {
106523
106905
  councilModeEnabled = true;
106524
- 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");
106525
106907
  let pcVerdictFound = false;
106526
106908
  let _pcVerdict;
106527
106909
  let pcQuorumSize;
@@ -106729,7 +107111,7 @@ Advisory notes: ${advisoryNotes.join("; ")}` : "";
106729
107111
  const effective = getEffectiveGates(profile, overrides);
106730
107112
  if (effective.final_council === true) {
106731
107113
  finalCouncilEnabled = true;
106732
- const fcPath = path115.join(dir, ".swarm", "evidence", "final-council.json");
107114
+ const fcPath = path116.join(dir, ".swarm", "evidence", "final-council.json");
106733
107115
  let fcVerdictFound = false;
106734
107116
  let _fcVerdict;
106735
107117
  try {
@@ -106917,7 +107299,7 @@ Advisory notes: ${advisoryNotes.join("; ")}` : "";
106917
107299
  }
106918
107300
  if (retroFound && retroEntry?.lessons_learned && retroEntry.lessons_learned.length > 0) {
106919
107301
  try {
106920
- const projectName = path115.basename(dir);
107302
+ const projectName = path116.basename(dir);
106921
107303
  const curationResult = await curateAndStoreSwarm(retroEntry.lessons_learned, projectName, { phase_number: phase }, dir, knowledgeConfig);
106922
107304
  if (curationResult) {
106923
107305
  const sessionState = swarmState.agentSessions.get(sessionID);
@@ -107287,7 +107669,7 @@ init_utils();
107287
107669
  init_bun_compat();
107288
107670
  init_create_tool();
107289
107671
  import * as fs86 from "node:fs";
107290
- import * as path116 from "node:path";
107672
+ import * as path117 from "node:path";
107291
107673
  var MAX_OUTPUT_BYTES5 = 52428800;
107292
107674
  var AUDIT_TIMEOUT_MS = 120000;
107293
107675
  function isValidEcosystem(value) {
@@ -107315,16 +107697,16 @@ function validateArgs3(args2) {
107315
107697
  function detectEcosystems(directory) {
107316
107698
  const ecosystems = [];
107317
107699
  const cwd = directory;
107318
- if (fs86.existsSync(path116.join(cwd, "package.json"))) {
107700
+ if (fs86.existsSync(path117.join(cwd, "package.json"))) {
107319
107701
  ecosystems.push("npm");
107320
107702
  }
107321
- 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"))) {
107322
107704
  ecosystems.push("pip");
107323
107705
  }
107324
- if (fs86.existsSync(path116.join(cwd, "Cargo.toml"))) {
107706
+ if (fs86.existsSync(path117.join(cwd, "Cargo.toml"))) {
107325
107707
  ecosystems.push("cargo");
107326
107708
  }
107327
- if (fs86.existsSync(path116.join(cwd, "go.mod"))) {
107709
+ if (fs86.existsSync(path117.join(cwd, "go.mod"))) {
107328
107710
  ecosystems.push("go");
107329
107711
  }
107330
107712
  try {
@@ -107333,13 +107715,13 @@ function detectEcosystems(directory) {
107333
107715
  ecosystems.push("dotnet");
107334
107716
  }
107335
107717
  } catch {}
107336
- 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"))) {
107337
107719
  ecosystems.push("ruby");
107338
107720
  }
107339
- if (fs86.existsSync(path116.join(cwd, "pubspec.yaml"))) {
107721
+ if (fs86.existsSync(path117.join(cwd, "pubspec.yaml"))) {
107340
107722
  ecosystems.push("dart");
107341
107723
  }
107342
- if (fs86.existsSync(path116.join(cwd, "composer.lock"))) {
107724
+ if (fs86.existsSync(path117.join(cwd, "composer.lock"))) {
107343
107725
  ecosystems.push("composer");
107344
107726
  }
107345
107727
  return ecosystems;
@@ -108475,7 +108857,7 @@ var pkg_audit = createSwarmTool({
108475
108857
  init_zod();
108476
108858
  init_manager2();
108477
108859
  import * as fs87 from "node:fs";
108478
- import * as path117 from "node:path";
108860
+ import * as path118 from "node:path";
108479
108861
  init_utils();
108480
108862
  init_create_tool();
108481
108863
  var MAX_FILE_SIZE = 1024 * 1024;
@@ -108598,7 +108980,7 @@ function isScaffoldFile(filePath) {
108598
108980
  if (SCAFFOLD_PATH_PATTERNS.some((pattern) => pattern.test(normalizedPath))) {
108599
108981
  return true;
108600
108982
  }
108601
- const filename = path117.basename(filePath);
108983
+ const filename = path118.basename(filePath);
108602
108984
  if (SCAFFOLD_FILENAME_PATTERNS.some((pattern) => pattern.test(filename))) {
108603
108985
  return true;
108604
108986
  }
@@ -108615,7 +108997,7 @@ function isAllowedByGlobs(filePath, allowGlobs) {
108615
108997
  if (regex.test(normalizedPath)) {
108616
108998
  return true;
108617
108999
  }
108618
- const filename = path117.basename(filePath);
109000
+ const filename = path118.basename(filePath);
108619
109001
  const filenameRegex = new RegExp(`^${regexPattern}$`, "i");
108620
109002
  if (filenameRegex.test(filename)) {
108621
109003
  return true;
@@ -108624,7 +109006,7 @@ function isAllowedByGlobs(filePath, allowGlobs) {
108624
109006
  return false;
108625
109007
  }
108626
109008
  function isParserSupported(filePath) {
108627
- const ext = path117.extname(filePath).toLowerCase();
109009
+ const ext = path118.extname(filePath).toLowerCase();
108628
109010
  return SUPPORTED_PARSER_EXTENSIONS.has(ext);
108629
109011
  }
108630
109012
  function isPlanFile(filePath) {
@@ -108871,9 +109253,9 @@ async function placeholderScan(input, directory) {
108871
109253
  let filesScanned = 0;
108872
109254
  const filesWithFindings = new Set;
108873
109255
  for (const filePath of changed_files) {
108874
- const fullPath = path117.isAbsolute(filePath) ? filePath : path117.resolve(directory, filePath);
108875
- const resolvedDirectory = path117.resolve(directory);
108876
- 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) {
108877
109259
  continue;
108878
109260
  }
108879
109261
  if (!fs87.existsSync(fullPath)) {
@@ -108882,7 +109264,7 @@ async function placeholderScan(input, directory) {
108882
109264
  if (isAllowedByGlobs(filePath, allow_globs)) {
108883
109265
  continue;
108884
109266
  }
108885
- const relativeFilePath = path117.relative(directory, fullPath).replace(/\\/g, "/");
109267
+ const relativeFilePath = path118.relative(directory, fullPath).replace(/\\/g, "/");
108886
109268
  if (FILE_ALLOWLIST.some((allowed) => relativeFilePath.endsWith(allowed))) {
108887
109269
  continue;
108888
109270
  }
@@ -108954,7 +109336,7 @@ var placeholder_scan = createSwarmTool({
108954
109336
  });
108955
109337
  // src/tools/pre-check-batch.ts
108956
109338
  import * as fs91 from "node:fs";
108957
- import * as path121 from "node:path";
109339
+ import * as path122 from "node:path";
108958
109340
  init_zod();
108959
109341
  init_manager2();
108960
109342
  init_utils();
@@ -109095,7 +109477,7 @@ init_zod();
109095
109477
  init_manager2();
109096
109478
  init_detector();
109097
109479
  import * as fs90 from "node:fs";
109098
- import * as path120 from "node:path";
109480
+ import * as path121 from "node:path";
109099
109481
  import { extname as extname20 } from "node:path";
109100
109482
 
109101
109483
  // src/sast/rules/c.ts
@@ -109811,7 +110193,7 @@ function executeRulesSync(filePath, content, language) {
109811
110193
  // src/sast/semgrep.ts
109812
110194
  import * as child_process9 from "node:child_process";
109813
110195
  import * as fs88 from "node:fs";
109814
- import * as path118 from "node:path";
110196
+ import * as path119 from "node:path";
109815
110197
  var semgrepAvailableCache = null;
109816
110198
  var DEFAULT_RULES_DIR = ".swarm/semgrep-rules";
109817
110199
  var DEFAULT_TIMEOUT_MS3 = 30000;
@@ -109998,7 +110380,7 @@ async function runSemgrep(options) {
109998
110380
  }
109999
110381
  function getRulesDirectory(projectRoot) {
110000
110382
  if (projectRoot) {
110001
- return path118.resolve(projectRoot, DEFAULT_RULES_DIR);
110383
+ return path119.resolve(projectRoot, DEFAULT_RULES_DIR);
110002
110384
  }
110003
110385
  return DEFAULT_RULES_DIR;
110004
110386
  }
@@ -110019,24 +110401,24 @@ init_create_tool();
110019
110401
  init_utils2();
110020
110402
  import * as crypto10 from "node:crypto";
110021
110403
  import * as fs89 from "node:fs";
110022
- import * as path119 from "node:path";
110404
+ import * as path120 from "node:path";
110023
110405
  var BASELINE_SCHEMA_VERSION = "1.0.0";
110024
110406
  var MAX_BASELINE_FINDINGS = 2000;
110025
110407
  var MAX_BASELINE_BYTES = 2 * 1048576;
110026
110408
  var LOCK_RETRY_DELAYS_MS = [50, 100, 200, 400, 800];
110027
110409
  function normalizeFindingPath(directory, file3) {
110028
- const resolved = path119.isAbsolute(file3) ? file3 : path119.resolve(directory, file3);
110029
- 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);
110030
110412
  return rel.replace(/\\/g, "/");
110031
110413
  }
110032
110414
  function baselineRelPath(phase) {
110033
- return path119.join("evidence", String(phase), "sast-baseline.json");
110415
+ return path120.join("evidence", String(phase), "sast-baseline.json");
110034
110416
  }
110035
110417
  function tempRelPath(phase) {
110036
- 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}`);
110037
110419
  }
110038
110420
  function lockRelPath(phase) {
110039
- return path119.join("evidence", String(phase), "sast-baseline.json.lock");
110421
+ return path120.join("evidence", String(phase), "sast-baseline.json.lock");
110040
110422
  }
110041
110423
  function getLine(lines, idx) {
110042
110424
  if (idx < 0 || idx >= lines.length)
@@ -110157,8 +110539,8 @@ async function captureOrMergeBaseline(directory, phase, findings, engine, scanne
110157
110539
  message: e instanceof Error ? e.message : "Path validation failed"
110158
110540
  };
110159
110541
  }
110160
- fs89.mkdirSync(path119.dirname(baselinePath), { recursive: true });
110161
- fs89.mkdirSync(path119.dirname(tempPath), { recursive: true });
110542
+ fs89.mkdirSync(path120.dirname(baselinePath), { recursive: true });
110543
+ fs89.mkdirSync(path120.dirname(tempPath), { recursive: true });
110162
110544
  const releaseLock = await acquireLock2(lockPath);
110163
110545
  try {
110164
110546
  let existing = null;
@@ -110431,9 +110813,9 @@ async function sastScan(input, directory, config3) {
110431
110813
  _filesSkipped++;
110432
110814
  continue;
110433
110815
  }
110434
- const resolvedPath = path120.isAbsolute(filePath) ? filePath : path120.resolve(directory, filePath);
110435
- const resolvedDirectory = path120.resolve(directory);
110436
- 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) {
110437
110819
  _filesSkipped++;
110438
110820
  continue;
110439
110821
  }
@@ -110748,18 +111130,18 @@ function validatePath(inputPath, baseDir, workspaceDir) {
110748
111130
  let resolved;
110749
111131
  const isWinAbs = isWindowsAbsolutePath(inputPath);
110750
111132
  if (isWinAbs) {
110751
- resolved = path121.win32.resolve(inputPath);
110752
- } else if (path121.isAbsolute(inputPath)) {
110753
- resolved = path121.resolve(inputPath);
111133
+ resolved = path122.win32.resolve(inputPath);
111134
+ } else if (path122.isAbsolute(inputPath)) {
111135
+ resolved = path122.resolve(inputPath);
110754
111136
  } else {
110755
- resolved = path121.resolve(baseDir, inputPath);
111137
+ resolved = path122.resolve(baseDir, inputPath);
110756
111138
  }
110757
- const workspaceResolved = path121.resolve(workspaceDir);
111139
+ const workspaceResolved = path122.resolve(workspaceDir);
110758
111140
  let relative25;
110759
111141
  if (isWinAbs) {
110760
- relative25 = path121.win32.relative(workspaceResolved, resolved);
111142
+ relative25 = path122.win32.relative(workspaceResolved, resolved);
110761
111143
  } else {
110762
- relative25 = path121.relative(workspaceResolved, resolved);
111144
+ relative25 = path122.relative(workspaceResolved, resolved);
110763
111145
  }
110764
111146
  if (relative25.startsWith("..")) {
110765
111147
  return "path traversal detected";
@@ -110824,7 +111206,7 @@ async function runLintOnFiles(linter, files, workspaceDir) {
110824
111206
  if (typeof file3 !== "string") {
110825
111207
  continue;
110826
111208
  }
110827
- const resolvedPath = path121.resolve(file3);
111209
+ const resolvedPath = path122.resolve(file3);
110828
111210
  const validationError = validatePath(resolvedPath, workspaceDir, workspaceDir);
110829
111211
  if (validationError) {
110830
111212
  continue;
@@ -110981,7 +111363,7 @@ async function runSecretscanWithFiles(files, directory) {
110981
111363
  skippedFiles++;
110982
111364
  continue;
110983
111365
  }
110984
- const resolvedPath = path121.resolve(file3);
111366
+ const resolvedPath = path122.resolve(file3);
110985
111367
  const validationError = validatePath(resolvedPath, directory, directory);
110986
111368
  if (validationError) {
110987
111369
  skippedFiles++;
@@ -110999,7 +111381,7 @@ async function runSecretscanWithFiles(files, directory) {
110999
111381
  };
111000
111382
  }
111001
111383
  for (const file3 of validatedFiles) {
111002
- const ext = path121.extname(file3).toLowerCase();
111384
+ const ext = path122.extname(file3).toLowerCase();
111003
111385
  if (DEFAULT_EXCLUDE_EXTENSIONS2.has(ext)) {
111004
111386
  skippedFiles++;
111005
111387
  continue;
@@ -111218,7 +111600,7 @@ function classifySastFindings(findings, changedLineRanges, directory) {
111218
111600
  const preexistingFindings = [];
111219
111601
  for (const finding of findings) {
111220
111602
  const filePath = finding.location.file;
111221
- const normalised = path121.relative(directory, filePath).replace(/\\/g, "/");
111603
+ const normalised = path122.relative(directory, filePath).replace(/\\/g, "/");
111222
111604
  const changedLines = changedLineRanges.get(normalised);
111223
111605
  if (changedLines?.has(finding.location.line)) {
111224
111606
  newFindings.push(finding);
@@ -111269,7 +111651,7 @@ async function runPreCheckBatch(input, workspaceDir, contextDir) {
111269
111651
  warn(`pre_check_batch: Invalid file path: ${file3}`);
111270
111652
  continue;
111271
111653
  }
111272
- changedFiles.push(path121.resolve(directory, file3));
111654
+ changedFiles.push(path122.resolve(directory, file3));
111273
111655
  }
111274
111656
  if (changedFiles.length === 0) {
111275
111657
  warn("pre_check_batch: No valid files after validation, skipping all tools (fail-closed)");
@@ -111470,9 +111852,9 @@ var pre_check_batch = createSwarmTool({
111470
111852
  };
111471
111853
  return JSON.stringify(errorResult, null, 2);
111472
111854
  }
111473
- const resolvedDirectory = path121.resolve(typedArgs.directory);
111474
- const workspaceAnchor = path121.resolve(directory);
111475
- 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)) {
111476
111858
  const subDirError = `directory "${typedArgs.directory}" is a subdirectory of the project root — pre_check_batch requires the project root directory "${workspaceAnchor}"`;
111477
111859
  const subDirResult = {
111478
111860
  gates_passed: false,
@@ -111523,7 +111905,7 @@ var pre_check_batch = createSwarmTool({
111523
111905
  });
111524
111906
  // src/tools/repo-map.ts
111525
111907
  init_zod();
111526
- import * as path122 from "node:path";
111908
+ import * as path123 from "node:path";
111527
111909
  init_path_security();
111528
111910
  init_create_tool();
111529
111911
  var VALID_ACTIONS = [
@@ -111548,7 +111930,7 @@ function validateFile(p) {
111548
111930
  return "file contains control characters";
111549
111931
  if (containsPathTraversal(p))
111550
111932
  return "file contains path traversal";
111551
- if (path122.isAbsolute(p) || /^[a-zA-Z]:[\\/]/.test(p)) {
111933
+ if (path123.isAbsolute(p) || /^[a-zA-Z]:[\\/]/.test(p)) {
111552
111934
  return "file must be a workspace-relative path, not absolute";
111553
111935
  }
111554
111936
  return null;
@@ -111571,8 +111953,8 @@ function ok(action, payload) {
111571
111953
  }
111572
111954
  function toRelativeGraphPath(input, workspaceRoot) {
111573
111955
  const normalized = input.replace(/\\/g, "/");
111574
- if (path122.isAbsolute(normalized)) {
111575
- const rel = path122.relative(workspaceRoot, normalized).replace(/\\/g, "/");
111956
+ if (path123.isAbsolute(normalized)) {
111957
+ const rel = path123.relative(workspaceRoot, normalized).replace(/\\/g, "/");
111576
111958
  return normalizeGraphPath2(rel);
111577
111959
  }
111578
111960
  return normalizeGraphPath2(normalized);
@@ -111717,7 +112099,7 @@ var repo_map = createSwarmTool({
111717
112099
  init_zod();
111718
112100
  init_create_tool();
111719
112101
  import * as fs92 from "node:fs";
111720
- import * as path123 from "node:path";
112102
+ import * as path124 from "node:path";
111721
112103
  var SPEC_FILE = ".swarm/spec.md";
111722
112104
  var EVIDENCE_DIR4 = ".swarm/evidence";
111723
112105
  var OBLIGATION_KEYWORDS = ["MUST", "SHOULD", "SHALL"];
@@ -111786,7 +112168,7 @@ function readTouchedFiles(evidenceDir, phase, cwd) {
111786
112168
  return [];
111787
112169
  }
111788
112170
  for (const entry of entries) {
111789
- const entryPath = path123.join(evidenceDir, entry);
112171
+ const entryPath = path124.join(evidenceDir, entry);
111790
112172
  try {
111791
112173
  const stat8 = fs92.statSync(entryPath);
111792
112174
  if (!stat8.isDirectory()) {
@@ -111802,11 +112184,11 @@ function readTouchedFiles(evidenceDir, phase, cwd) {
111802
112184
  if (entryPhase !== String(phase)) {
111803
112185
  continue;
111804
112186
  }
111805
- const evidenceFilePath = path123.join(entryPath, "evidence.json");
112187
+ const evidenceFilePath = path124.join(entryPath, "evidence.json");
111806
112188
  try {
111807
- const resolvedPath = path123.resolve(evidenceFilePath);
111808
- const evidenceDirResolved = path123.resolve(evidenceDir);
111809
- 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)) {
111810
112192
  continue;
111811
112193
  }
111812
112194
  const stat8 = fs92.lstatSync(evidenceFilePath);
@@ -111840,7 +112222,7 @@ function readTouchedFiles(evidenceDir, phase, cwd) {
111840
112222
  if (Array.isArray(diffEntry.files_changed)) {
111841
112223
  for (const file3 of diffEntry.files_changed) {
111842
112224
  if (typeof file3 === "string") {
111843
- touchedFiles.add(path123.resolve(cwd, file3));
112225
+ touchedFiles.add(path124.resolve(cwd, file3));
111844
112226
  }
111845
112227
  }
111846
112228
  }
@@ -111853,8 +112235,8 @@ function readTouchedFiles(evidenceDir, phase, cwd) {
111853
112235
  }
111854
112236
  function searchFileForKeywords(filePath, keywords, cwd) {
111855
112237
  try {
111856
- const resolvedPath = path123.resolve(filePath);
111857
- const cwdResolved = path123.resolve(cwd);
112238
+ const resolvedPath = path124.resolve(filePath);
112239
+ const cwdResolved = path124.resolve(cwd);
111858
112240
  if (!resolvedPath.startsWith(cwdResolved)) {
111859
112241
  return false;
111860
112242
  }
@@ -111988,7 +112370,7 @@ var req_coverage = createSwarmTool({
111988
112370
  }, null, 2);
111989
112371
  }
111990
112372
  const cwd = inputDirectory || directory;
111991
- const specPath = path123.join(cwd, SPEC_FILE);
112373
+ const specPath = path124.join(cwd, SPEC_FILE);
111992
112374
  let specContent;
111993
112375
  try {
111994
112376
  specContent = fs92.readFileSync(specPath, "utf-8");
@@ -112015,7 +112397,7 @@ var req_coverage = createSwarmTool({
112015
112397
  message: "No FR requirements found in spec.md"
112016
112398
  }, null, 2);
112017
112399
  }
112018
- const evidenceDir = path123.join(cwd, EVIDENCE_DIR4);
112400
+ const evidenceDir = path124.join(cwd, EVIDENCE_DIR4);
112019
112401
  const touchedFiles = readTouchedFiles(evidenceDir, phase, cwd);
112020
112402
  const analyzedRequirements = [];
112021
112403
  let coveredCount = 0;
@@ -112041,7 +112423,7 @@ var req_coverage = createSwarmTool({
112041
112423
  requirements: analyzedRequirements
112042
112424
  };
112043
112425
  const reportFilename = `req-coverage-phase-${phase}.json`;
112044
- const reportPath = path123.join(evidenceDir, reportFilename);
112426
+ const reportPath = path124.join(evidenceDir, reportFilename);
112045
112427
  try {
112046
112428
  if (!fs92.existsSync(evidenceDir)) {
112047
112429
  fs92.mkdirSync(evidenceDir, { recursive: true });
@@ -112129,7 +112511,7 @@ init_qa_gate_profile();
112129
112511
  init_file_locks();
112130
112512
  import * as crypto11 from "node:crypto";
112131
112513
  import * as fs93 from "node:fs";
112132
- import * as path124 from "node:path";
112514
+ import * as path125 from "node:path";
112133
112515
  init_ledger();
112134
112516
  init_manager();
112135
112517
  init_state();
@@ -112207,8 +112589,8 @@ async function executeSavePlan(args2, fallbackDir) {
112207
112589
  };
112208
112590
  }
112209
112591
  if (args2.working_directory && fallbackDir) {
112210
- const resolvedTarget = path124.resolve(args2.working_directory);
112211
- const resolvedRoot = path124.resolve(fallbackDir);
112592
+ const resolvedTarget = path125.resolve(args2.working_directory);
112593
+ const resolvedRoot = path125.resolve(fallbackDir);
112212
112594
  let fallbackExists = false;
112213
112595
  try {
112214
112596
  fs93.accessSync(resolvedRoot, fs93.constants.F_OK);
@@ -112217,7 +112599,7 @@ async function executeSavePlan(args2, fallbackDir) {
112217
112599
  fallbackExists = false;
112218
112600
  }
112219
112601
  if (fallbackExists) {
112220
- const isSubdirectory = resolvedTarget.startsWith(resolvedRoot + path124.sep);
112602
+ const isSubdirectory = resolvedTarget.startsWith(resolvedRoot + path125.sep);
112221
112603
  if (isSubdirectory) {
112222
112604
  return {
112223
112605
  success: false,
@@ -112233,7 +112615,7 @@ async function executeSavePlan(args2, fallbackDir) {
112233
112615
  let specMtime;
112234
112616
  let specHash;
112235
112617
  if (process.env.SWARM_SKIP_SPEC_GATE !== "1") {
112236
- const specPath = path124.join(targetWorkspace, ".swarm", "spec.md");
112618
+ const specPath = path125.join(targetWorkspace, ".swarm", "spec.md");
112237
112619
  try {
112238
112620
  const stat8 = await fs93.promises.stat(specPath);
112239
112621
  specMtime = stat8.mtime.toISOString();
@@ -112249,7 +112631,7 @@ async function executeSavePlan(args2, fallbackDir) {
112249
112631
  }
112250
112632
  }
112251
112633
  if (process.env.SWARM_SKIP_GATE_SELECTION !== "1") {
112252
- const contextPath = path124.join(targetWorkspace, ".swarm", "context.md");
112634
+ const contextPath = path125.join(targetWorkspace, ".swarm", "context.md");
112253
112635
  let contextContent = "";
112254
112636
  try {
112255
112637
  contextContent = await fs93.promises.readFile(contextPath, "utf8");
@@ -112506,7 +112888,7 @@ async function executeSavePlan(args2, fallbackDir) {
112506
112888
  }
112507
112889
  await writeCheckpoint(dir).catch(() => {});
112508
112890
  try {
112509
- const markerPath = path124.join(dir, ".swarm", ".plan-write-marker");
112891
+ const markerPath = path125.join(dir, ".swarm", ".plan-write-marker");
112510
112892
  const marker = JSON.stringify({
112511
112893
  source: "save_plan",
112512
112894
  timestamp: new Date().toISOString(),
@@ -112529,7 +112911,7 @@ async function executeSavePlan(args2, fallbackDir) {
112529
112911
  return {
112530
112912
  success: true,
112531
112913
  message: "Plan saved successfully",
112532
- plan_path: path124.join(dir, ".swarm", "plan.json"),
112914
+ plan_path: path125.join(dir, ".swarm", "plan.json"),
112533
112915
  phases_count: plan.phases.length,
112534
112916
  tasks_count: tasksCount,
112535
112917
  ...resolvedProfile !== undefined ? { execution_profile: resolvedProfile } : {},
@@ -112594,7 +112976,7 @@ var save_plan = createSwarmTool({
112594
112976
  init_zod();
112595
112977
  init_manager2();
112596
112978
  import * as fs94 from "node:fs";
112597
- import * as path125 from "node:path";
112979
+ import * as path126 from "node:path";
112598
112980
 
112599
112981
  // src/sbom/detectors/index.ts
112600
112982
  init_utils();
@@ -113444,7 +113826,7 @@ function findManifestFiles(rootDir) {
113444
113826
  try {
113445
113827
  const entries = fs94.readdirSync(dir, { withFileTypes: true });
113446
113828
  for (const entry of entries) {
113447
- const fullPath = path125.join(dir, entry.name);
113829
+ const fullPath = path126.join(dir, entry.name);
113448
113830
  if (entry.name.startsWith(".") || entry.name === "node_modules" || entry.name === "dist" || entry.name === "build" || entry.name === "target") {
113449
113831
  continue;
113450
113832
  }
@@ -113453,7 +113835,7 @@ function findManifestFiles(rootDir) {
113453
113835
  } else if (entry.isFile()) {
113454
113836
  for (const pattern of patterns) {
113455
113837
  if (simpleGlobToRegex(pattern).test(entry.name)) {
113456
- manifestFiles.push(path125.relative(rootDir, fullPath));
113838
+ manifestFiles.push(path126.relative(rootDir, fullPath));
113457
113839
  break;
113458
113840
  }
113459
113841
  }
@@ -113471,11 +113853,11 @@ function findManifestFilesInDirs(directories, workingDir) {
113471
113853
  try {
113472
113854
  const entries = fs94.readdirSync(dir, { withFileTypes: true });
113473
113855
  for (const entry of entries) {
113474
- const fullPath = path125.join(dir, entry.name);
113856
+ const fullPath = path126.join(dir, entry.name);
113475
113857
  if (entry.isFile()) {
113476
113858
  for (const pattern of patterns) {
113477
113859
  if (simpleGlobToRegex(pattern).test(entry.name)) {
113478
- found.push(path125.relative(workingDir, fullPath));
113860
+ found.push(path126.relative(workingDir, fullPath));
113479
113861
  break;
113480
113862
  }
113481
113863
  }
@@ -113488,11 +113870,11 @@ function findManifestFilesInDirs(directories, workingDir) {
113488
113870
  function getDirectoriesFromChangedFiles(changedFiles, workingDir) {
113489
113871
  const dirs = new Set;
113490
113872
  for (const file3 of changedFiles) {
113491
- let currentDir = path125.dirname(file3);
113873
+ let currentDir = path126.dirname(file3);
113492
113874
  while (true) {
113493
- if (currentDir && currentDir !== "." && currentDir !== path125.sep) {
113494
- dirs.add(path125.join(workingDir, currentDir));
113495
- 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);
113496
113878
  if (parent === currentDir)
113497
113879
  break;
113498
113880
  currentDir = parent;
@@ -113576,7 +113958,7 @@ var sbom_generate = createSwarmTool({
113576
113958
  const changedFiles = obj.changed_files;
113577
113959
  const relativeOutputDir = obj.output_dir || DEFAULT_OUTPUT_DIR;
113578
113960
  const workingDir = directory;
113579
- const outputDir = path125.isAbsolute(relativeOutputDir) ? relativeOutputDir : path125.join(workingDir, relativeOutputDir);
113961
+ const outputDir = path126.isAbsolute(relativeOutputDir) ? relativeOutputDir : path126.join(workingDir, relativeOutputDir);
113580
113962
  let manifestFiles = [];
113581
113963
  if (scope === "all") {
113582
113964
  manifestFiles = findManifestFiles(workingDir);
@@ -113599,7 +113981,7 @@ var sbom_generate = createSwarmTool({
113599
113981
  const processedFiles = [];
113600
113982
  for (const manifestFile of manifestFiles) {
113601
113983
  try {
113602
- const fullPath = path125.isAbsolute(manifestFile) ? manifestFile : path125.join(workingDir, manifestFile);
113984
+ const fullPath = path126.isAbsolute(manifestFile) ? manifestFile : path126.join(workingDir, manifestFile);
113603
113985
  if (!fs94.existsSync(fullPath)) {
113604
113986
  continue;
113605
113987
  }
@@ -113616,7 +113998,7 @@ var sbom_generate = createSwarmTool({
113616
113998
  const bom = generateCycloneDX(allComponents);
113617
113999
  const bomJson = serializeCycloneDX(bom);
113618
114000
  const filename = generateSbomFilename();
113619
- const outputPath = path125.join(outputDir, filename);
114001
+ const outputPath = path126.join(outputDir, filename);
113620
114002
  fs94.writeFileSync(outputPath, bomJson, "utf-8");
113621
114003
  const verdict = processedFiles.length > 0 ? "pass" : "pass";
113622
114004
  try {
@@ -113660,7 +114042,7 @@ var sbom_generate = createSwarmTool({
113660
114042
  init_zod();
113661
114043
  init_create_tool();
113662
114044
  import * as fs95 from "node:fs";
113663
- import * as path126 from "node:path";
114045
+ import * as path127 from "node:path";
113664
114046
  var SPEC_CANDIDATES = [
113665
114047
  "openapi.json",
113666
114048
  "openapi.yaml",
@@ -113692,12 +114074,12 @@ function normalizePath4(p) {
113692
114074
  }
113693
114075
  function discoverSpecFile(cwd, specFileArg) {
113694
114076
  if (specFileArg) {
113695
- const resolvedPath = path126.resolve(cwd, specFileArg);
113696
- 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;
113697
114079
  if (!resolvedPath.startsWith(normalizedCwd) && resolvedPath !== cwd) {
113698
114080
  throw new Error("Invalid spec_file: path traversal detected");
113699
114081
  }
113700
- const ext = path126.extname(resolvedPath).toLowerCase();
114082
+ const ext = path127.extname(resolvedPath).toLowerCase();
113701
114083
  if (!ALLOWED_EXTENSIONS.includes(ext)) {
113702
114084
  throw new Error(`Invalid spec_file: must end in .json, .yaml, or .yml, got ${ext}`);
113703
114085
  }
@@ -113711,7 +114093,7 @@ function discoverSpecFile(cwd, specFileArg) {
113711
114093
  return resolvedPath;
113712
114094
  }
113713
114095
  for (const candidate of SPEC_CANDIDATES) {
113714
- const candidatePath = path126.resolve(cwd, candidate);
114096
+ const candidatePath = path127.resolve(cwd, candidate);
113715
114097
  if (fs95.existsSync(candidatePath)) {
113716
114098
  const stats = fs95.statSync(candidatePath);
113717
114099
  if (stats.size <= MAX_SPEC_SIZE) {
@@ -113723,7 +114105,7 @@ function discoverSpecFile(cwd, specFileArg) {
113723
114105
  }
113724
114106
  function parseSpec(specFile) {
113725
114107
  const content = fs95.readFileSync(specFile, "utf-8");
113726
- const ext = path126.extname(specFile).toLowerCase();
114108
+ const ext = path127.extname(specFile).toLowerCase();
113727
114109
  if (ext === ".json") {
113728
114110
  return parseJsonSpec(content);
113729
114111
  }
@@ -113799,7 +114181,7 @@ function extractRoutes(cwd) {
113799
114181
  return;
113800
114182
  }
113801
114183
  for (const entry of entries) {
113802
- const fullPath = path126.join(dir, entry.name);
114184
+ const fullPath = path127.join(dir, entry.name);
113803
114185
  if (entry.isSymbolicLink()) {
113804
114186
  continue;
113805
114187
  }
@@ -113809,7 +114191,7 @@ function extractRoutes(cwd) {
113809
114191
  }
113810
114192
  walkDir(fullPath);
113811
114193
  } else if (entry.isFile()) {
113812
- const ext = path126.extname(entry.name).toLowerCase();
114194
+ const ext = path127.extname(entry.name).toLowerCase();
113813
114195
  const baseName = entry.name.toLowerCase();
113814
114196
  if (![".ts", ".js", ".mjs"].includes(ext)) {
113815
114197
  continue;
@@ -113977,7 +114359,7 @@ init_bun_compat();
113977
114359
  init_path_security();
113978
114360
  init_create_tool();
113979
114361
  import * as fs96 from "node:fs";
113980
- import * as path127 from "node:path";
114362
+ import * as path128 from "node:path";
113981
114363
  var DEFAULT_MAX_RESULTS = 100;
113982
114364
  var DEFAULT_MAX_LINES = 200;
113983
114365
  var REGEX_TIMEOUT_MS = 5000;
@@ -114013,11 +114395,11 @@ function containsWindowsAttacks3(str) {
114013
114395
  }
114014
114396
  function isPathInWorkspace3(filePath, workspace) {
114015
114397
  try {
114016
- const resolvedPath = path127.resolve(workspace, filePath);
114398
+ const resolvedPath = path128.resolve(workspace, filePath);
114017
114399
  const realWorkspace = fs96.realpathSync(workspace);
114018
114400
  const realResolvedPath = fs96.realpathSync(resolvedPath);
114019
- const relativePath = path127.relative(realWorkspace, realResolvedPath);
114020
- if (relativePath.startsWith("..") || path127.isAbsolute(relativePath)) {
114401
+ const relativePath = path128.relative(realWorkspace, realResolvedPath);
114402
+ if (relativePath.startsWith("..") || path128.isAbsolute(relativePath)) {
114021
114403
  return false;
114022
114404
  }
114023
114405
  return true;
@@ -114030,11 +114412,11 @@ function validatePathForRead2(filePath, workspace) {
114030
114412
  }
114031
114413
  function findRgInEnvPath() {
114032
114414
  const searchPath = process.env.PATH ?? "";
114033
- for (const dir of searchPath.split(path127.delimiter)) {
114415
+ for (const dir of searchPath.split(path128.delimiter)) {
114034
114416
  if (!dir)
114035
114417
  continue;
114036
114418
  const isWindows = process.platform === "win32";
114037
- const candidate = path127.join(dir, isWindows ? "rg.exe" : "rg");
114419
+ const candidate = path128.join(dir, isWindows ? "rg.exe" : "rg");
114038
114420
  if (fs96.existsSync(candidate))
114039
114421
  return candidate;
114040
114422
  }
@@ -114164,8 +114546,8 @@ function collectFiles(dir, workspace, includeGlobs, excludeGlobs) {
114164
114546
  try {
114165
114547
  const entries = fs96.readdirSync(dir, { withFileTypes: true });
114166
114548
  for (const entry of entries) {
114167
- const fullPath = path127.join(dir, entry.name);
114168
- const relativePath = path127.relative(workspace, fullPath);
114549
+ const fullPath = path128.join(dir, entry.name);
114550
+ const relativePath = path128.relative(workspace, fullPath);
114169
114551
  if (!validatePathForRead2(fullPath, workspace)) {
114170
114552
  continue;
114171
114553
  }
@@ -114206,7 +114588,7 @@ async function fallbackSearch(opts) {
114206
114588
  const matches = [];
114207
114589
  let total = 0;
114208
114590
  for (const file3 of files) {
114209
- const fullPath = path127.join(opts.workspace, file3);
114591
+ const fullPath = path128.join(opts.workspace, file3);
114210
114592
  if (!validatePathForRead2(fullPath, opts.workspace)) {
114211
114593
  continue;
114212
114594
  }
@@ -114574,7 +114956,7 @@ init_config();
114574
114956
  init_schema();
114575
114957
  init_create_tool();
114576
114958
  import { mkdir as mkdir21, rename as rename9, writeFile as writeFile16 } from "node:fs/promises";
114577
- import * as path128 from "node:path";
114959
+ import * as path129 from "node:path";
114578
114960
  var MAX_SPEC_BYTES = 256 * 1024;
114579
114961
  var spec_write = createSwarmTool({
114580
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.",
@@ -114615,8 +114997,8 @@ var spec_write = createSwarmTool({
114615
114997
  reason: 'spec must contain at least one top-level "# Heading"'
114616
114998
  }, null, 2);
114617
114999
  }
114618
- const target = path128.join(directory, ".swarm", "spec.md");
114619
- await mkdir21(path128.dirname(target), { recursive: true });
115000
+ const target = path129.join(directory, ".swarm", "spec.md");
115001
+ await mkdir21(path129.dirname(target), { recursive: true });
114620
115002
  const tmp = `${target}.tmp-${process.pid}-${Date.now()}`;
114621
115003
  let finalContent = content;
114622
115004
  if (mode === "append") {
@@ -114645,13 +115027,13 @@ init_zod();
114645
115027
  init_loader();
114646
115028
  import {
114647
115029
  existsSync as existsSync74,
114648
- mkdirSync as mkdirSync32,
115030
+ mkdirSync as mkdirSync33,
114649
115031
  readFileSync as readFileSync64,
114650
115032
  renameSync as renameSync20,
114651
115033
  unlinkSync as unlinkSync16,
114652
115034
  writeFileSync as writeFileSync24
114653
115035
  } from "node:fs";
114654
- import path129 from "node:path";
115036
+ import path130 from "node:path";
114655
115037
  init_create_tool();
114656
115038
  init_resolve_working_directory();
114657
115039
  var VerdictSchema2 = exports_external.object({
@@ -114781,7 +115163,7 @@ var submit_phase_council_verdicts = createSwarmTool({
114781
115163
  }
114782
115164
  });
114783
115165
  function getPhaseMutationGapFinding(phaseNumber, workingDir) {
114784
- 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");
114785
115167
  try {
114786
115168
  const raw = readFileSync64(mutationGatePath, "utf-8");
114787
115169
  const parsed = JSON.parse(raw);
@@ -114843,9 +115225,9 @@ function getPhaseMutationGapFinding(phaseNumber, workingDir) {
114843
115225
  }
114844
115226
  }
114845
115227
  function writePhaseCouncilEvidence(workingDir, synthesis) {
114846
- const evidenceDir = path129.join(workingDir, ".swarm", "evidence", String(synthesis.phaseNumber));
114847
- mkdirSync32(evidenceDir, { recursive: true });
114848
- 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");
114849
115231
  const evidenceBundle = {
114850
115232
  entries: [
114851
115233
  {
@@ -114998,16 +115380,20 @@ var swarm_memory_propose = createSwarmTool({
114998
115380
  }, {
114999
115381
  config: config3.memory
115000
115382
  });
115001
- const proposal = await gateway.propose(parsed.data);
115002
- return JSON.stringify({
115003
- success: proposal.status !== "rejected",
115004
- proposal_id: proposal.id,
115005
- status: proposal.status,
115006
- operation: proposal.operation,
115007
- memory_id: proposal.proposedRecord?.id,
115008
- rejection_reason: proposal.rejectionReason,
115009
- message: proposal.status === "pending" ? "Memory proposal created. Durable memory was not written." : "Memory proposal was captured with policy rejection metadata."
115010
- }, 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
+ }
115011
115397
  }
115012
115398
  });
115013
115399
  var _internals51 = {
@@ -115071,19 +115457,23 @@ var swarm_memory_recall = createSwarmTool({
115071
115457
  }, {
115072
115458
  config: config3.memory
115073
115459
  });
115074
- const bundle = await gateway.recall(parsed.data);
115075
- return JSON.stringify({
115076
- success: true,
115077
- bundle_id: bundle.id,
115078
- memory_ids: bundle.items.map((item) => item.record.id),
115079
- total: bundle.items.length,
115080
- token_estimate: bundle.tokenEstimate,
115081
- signals: bundle.items.map((item) => ({
115082
- memory_id: item.record.id,
115083
- ...item.signals
115084
- })),
115085
- prompt_block: bundle.promptBlock
115086
- }, 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
+ }
115087
115477
  }
115088
115478
  });
115089
115479
  var RecallArgsSchema = exports_external.object({
@@ -115106,7 +115496,7 @@ init_zod();
115106
115496
  init_path_security();
115107
115497
  init_create_tool();
115108
115498
  import * as fs97 from "node:fs";
115109
- import * as path130 from "node:path";
115499
+ import * as path131 from "node:path";
115110
115500
  var WINDOWS_RESERVED_NAMES4 = /^(con|prn|aux|nul|com[1-9]|lpt[1-9])(\.|:|$)/i;
115111
115501
  function containsWindowsAttacks4(str) {
115112
115502
  if (/:[^\\/]/.test(str))
@@ -115120,14 +115510,14 @@ function containsWindowsAttacks4(str) {
115120
115510
  }
115121
115511
  function isPathInWorkspace4(filePath, workspace) {
115122
115512
  try {
115123
- const resolvedPath = path130.resolve(workspace, filePath);
115513
+ const resolvedPath = path131.resolve(workspace, filePath);
115124
115514
  if (!fs97.existsSync(resolvedPath)) {
115125
115515
  return true;
115126
115516
  }
115127
115517
  const realWorkspace = fs97.realpathSync(workspace);
115128
115518
  const realResolvedPath = fs97.realpathSync(resolvedPath);
115129
- const relativePath = path130.relative(realWorkspace, realResolvedPath);
115130
- if (relativePath.startsWith("..") || path130.isAbsolute(relativePath)) {
115519
+ const relativePath = path131.relative(realWorkspace, realResolvedPath);
115520
+ if (relativePath.startsWith("..") || path131.isAbsolute(relativePath)) {
115131
115521
  return false;
115132
115522
  }
115133
115523
  return true;
@@ -115335,7 +115725,7 @@ var suggestPatch = createSwarmTool({
115335
115725
  });
115336
115726
  continue;
115337
115727
  }
115338
- const fullPath = path130.resolve(directory, change.file);
115728
+ const fullPath = path131.resolve(directory, change.file);
115339
115729
  if (!fs97.existsSync(fullPath)) {
115340
115730
  errors5.push({
115341
115731
  success: false,
@@ -115639,11 +116029,11 @@ var lean_turbo_acquire_locks = createSwarmTool({
115639
116029
  init_zod();
115640
116030
  init_constants();
115641
116031
  import * as fs99 from "node:fs";
115642
- import * as path132 from "node:path";
116032
+ import * as path133 from "node:path";
115643
116033
 
115644
116034
  // src/turbo/lean/conflicts.ts
115645
116035
  import * as fs98 from "node:fs";
115646
- import * as path131 from "node:path";
116036
+ import * as path132 from "node:path";
115647
116037
  var DEFAULT_GLOBAL_FILES = [
115648
116038
  "package.json",
115649
116039
  "package-lock.json",
@@ -115770,7 +116160,7 @@ function isProtectedPath2(normalizedPath) {
115770
116160
  return false;
115771
116161
  }
115772
116162
  function readTaskScopes(directory, taskId) {
115773
- const scopePath = path131.join(directory, ".swarm", "scopes", `scope-${taskId}.json`);
116163
+ const scopePath = path132.join(directory, ".swarm", "scopes", `scope-${taskId}.json`);
115774
116164
  try {
115775
116165
  if (!fs98.existsSync(scopePath)) {
115776
116166
  return null;
@@ -116158,7 +116548,7 @@ function createEmptyPlan(phaseNumber, planId) {
116158
116548
  // src/tools/lean-turbo-plan-lanes.ts
116159
116549
  init_create_tool();
116160
116550
  function readPlanJson(directory) {
116161
- const planPath = path132.join(directory, ".swarm", "plan.json");
116551
+ const planPath = path133.join(directory, ".swarm", "plan.json");
116162
116552
  if (!fs99.existsSync(planPath)) {
116163
116553
  return null;
116164
116554
  }
@@ -116213,7 +116603,7 @@ init_config();
116213
116603
  // src/turbo/lean/reviewer.ts
116214
116604
  init_state();
116215
116605
  import * as fs100 from "node:fs/promises";
116216
- import * as path133 from "node:path";
116606
+ import * as path134 from "node:path";
116217
116607
  init_state3();
116218
116608
  var DEFAULT_CONFIG3 = {
116219
116609
  reviewerAgent: "",
@@ -116329,9 +116719,9 @@ function parseReviewerVerdict(responseText) {
116329
116719
  return { verdict, reason };
116330
116720
  }
116331
116721
  async function writeReviewerEvidence(directory, phase, verdict, reason) {
116332
- const evidenceDir = path133.join(directory, ".swarm", "evidence", String(phase));
116722
+ const evidenceDir = path134.join(directory, ".swarm", "evidence", String(phase));
116333
116723
  await fs100.mkdir(evidenceDir, { recursive: true });
116334
- const evidencePath = path133.join(evidenceDir, "lean-turbo-reviewer.json");
116724
+ const evidencePath = path134.join(evidenceDir, "lean-turbo-reviewer.json");
116335
116725
  const content = JSON.stringify({
116336
116726
  phase,
116337
116727
  verdict,
@@ -117136,7 +117526,7 @@ var lean_turbo_status = createSwarmTool({
117136
117526
  init_spec_schema();
117137
117527
  init_create_tool();
117138
117528
  import * as fs101 from "node:fs";
117139
- import * as path134 from "node:path";
117529
+ import * as path135 from "node:path";
117140
117530
  var SPEC_FILE_NAME = "spec.md";
117141
117531
  var SWARM_DIR2 = ".swarm";
117142
117532
  var OBLIGATION_KEYWORDS2 = ["MUST", "SHALL", "SHOULD", "MAY"];
@@ -117189,7 +117579,7 @@ var lint_spec = createSwarmTool({
117189
117579
  async execute(_args, directory) {
117190
117580
  const errors5 = [];
117191
117581
  const warnings = [];
117192
- const specPath = path134.join(directory, SWARM_DIR2, SPEC_FILE_NAME);
117582
+ const specPath = path135.join(directory, SWARM_DIR2, SPEC_FILE_NAME);
117193
117583
  if (!fs101.existsSync(specPath)) {
117194
117584
  const result2 = {
117195
117585
  valid: false,
@@ -117260,12 +117650,12 @@ var lint_spec = createSwarmTool({
117260
117650
  // src/tools/mutation-test.ts
117261
117651
  init_zod();
117262
117652
  import * as fs102 from "node:fs";
117263
- import * as path136 from "node:path";
117653
+ import * as path137 from "node:path";
117264
117654
 
117265
117655
  // src/mutation/engine.ts
117266
117656
  import { spawnSync as spawnSync3 } from "node:child_process";
117267
117657
  import { unlinkSync as unlinkSync17, writeFileSync as writeFileSync25 } from "node:fs";
117268
- import * as path135 from "node:path";
117658
+ import * as path136 from "node:path";
117269
117659
 
117270
117660
  // src/mutation/equivalence.ts
117271
117661
  function isStaticallyEquivalent(originalCode, mutatedCode) {
@@ -117411,7 +117801,7 @@ async function executeMutation(patch, testCommand, _testFiles, workingDir) {
117411
117801
  let patchFile;
117412
117802
  try {
117413
117803
  const safeId2 = patch.id.replace(/[^a-zA-Z0-9_-]/g, "_");
117414
- patchFile = path135.join(workingDir, `.mutation_patch_${safeId2}.diff`);
117804
+ patchFile = path136.join(workingDir, `.mutation_patch_${safeId2}.diff`);
117415
117805
  try {
117416
117806
  writeFileSync25(patchFile, patch.patch);
117417
117807
  } catch (writeErr) {
@@ -117815,7 +118205,7 @@ var mutation_test = createSwarmTool({
117815
118205
  ];
117816
118206
  for (const filePath of uniquePaths) {
117817
118207
  try {
117818
- const resolvedPath = path136.resolve(cwd, filePath);
118208
+ const resolvedPath = path137.resolve(cwd, filePath);
117819
118209
  sourceFiles.set(filePath, fs102.readFileSync(resolvedPath, "utf-8"));
117820
118210
  } catch {}
117821
118211
  }
@@ -117835,7 +118225,7 @@ init_zod();
117835
118225
  init_manager2();
117836
118226
  init_detector();
117837
118227
  import * as fs103 from "node:fs";
117838
- import * as path137 from "node:path";
118228
+ import * as path138 from "node:path";
117839
118229
  init_create_tool();
117840
118230
  var MAX_FILE_SIZE2 = 2 * 1024 * 1024;
117841
118231
  var BINARY_CHECK_BYTES = 8192;
@@ -117901,7 +118291,7 @@ async function syntaxCheck(input, directory, config3) {
117901
118291
  if (languages?.length) {
117902
118292
  const lowerLangs = languages.map((l) => l.toLowerCase());
117903
118293
  filesToCheck = filesToCheck.filter((file3) => {
117904
- const ext = path137.extname(file3.path).toLowerCase();
118294
+ const ext = path138.extname(file3.path).toLowerCase();
117905
118295
  const langDef = getLanguageForExtension(ext);
117906
118296
  const fileProfile = getProfileForFile(file3.path);
117907
118297
  const langId = fileProfile?.id || langDef?.id;
@@ -117914,7 +118304,7 @@ async function syntaxCheck(input, directory, config3) {
117914
118304
  let skippedCount = 0;
117915
118305
  for (const fileInfo of filesToCheck) {
117916
118306
  const { path: filePath } = fileInfo;
117917
- const fullPath = path137.isAbsolute(filePath) ? filePath : path137.join(directory, filePath);
118307
+ const fullPath = path138.isAbsolute(filePath) ? filePath : path138.join(directory, filePath);
117918
118308
  const result = {
117919
118309
  path: filePath,
117920
118310
  language: "",
@@ -117963,7 +118353,7 @@ async function syntaxCheck(input, directory, config3) {
117963
118353
  results.push(result);
117964
118354
  continue;
117965
118355
  }
117966
- const ext = path137.extname(filePath).toLowerCase();
118356
+ const ext = path138.extname(filePath).toLowerCase();
117967
118357
  const langDef = getLanguageForExtension(ext);
117968
118358
  result.language = profile?.id || langDef?.id || "unknown";
117969
118359
  const errors5 = extractSyntaxErrors(parser, content);
@@ -118061,7 +118451,7 @@ init_utils();
118061
118451
  init_create_tool();
118062
118452
  init_path_security();
118063
118453
  import * as fs104 from "node:fs";
118064
- import * as path138 from "node:path";
118454
+ import * as path139 from "node:path";
118065
118455
  var MAX_TEXT_LENGTH = 200;
118066
118456
  var MAX_FILE_SIZE_BYTES11 = 1024 * 1024;
118067
118457
  var SUPPORTED_EXTENSIONS4 = new Set([
@@ -118127,9 +118517,9 @@ function validatePathsInput(paths, cwd) {
118127
118517
  return { error: "paths contains path traversal", resolvedPath: null };
118128
118518
  }
118129
118519
  try {
118130
- const resolvedPath = path138.resolve(paths);
118131
- const normalizedCwd = path138.resolve(cwd);
118132
- const normalizedResolved = path138.resolve(resolvedPath);
118520
+ const resolvedPath = path139.resolve(paths);
118521
+ const normalizedCwd = path139.resolve(cwd);
118522
+ const normalizedResolved = path139.resolve(resolvedPath);
118133
118523
  if (!normalizedResolved.startsWith(normalizedCwd)) {
118134
118524
  return {
118135
118525
  error: "paths must be within the current working directory",
@@ -118145,7 +118535,7 @@ function validatePathsInput(paths, cwd) {
118145
118535
  }
118146
118536
  }
118147
118537
  function isSupportedExtension(filePath) {
118148
- const ext = path138.extname(filePath).toLowerCase();
118538
+ const ext = path139.extname(filePath).toLowerCase();
118149
118539
  return SUPPORTED_EXTENSIONS4.has(ext);
118150
118540
  }
118151
118541
  function findSourceFiles3(dir, files = []) {
@@ -118160,7 +118550,7 @@ function findSourceFiles3(dir, files = []) {
118160
118550
  if (SKIP_DIRECTORIES5.has(entry)) {
118161
118551
  continue;
118162
118552
  }
118163
- const fullPath = path138.join(dir, entry);
118553
+ const fullPath = path139.join(dir, entry);
118164
118554
  let stat8;
118165
118555
  try {
118166
118556
  stat8 = fs104.statSync(fullPath);
@@ -118272,7 +118662,7 @@ var todo_extract = createSwarmTool({
118272
118662
  filesToScan.push(scanPath);
118273
118663
  } else {
118274
118664
  const errorResult = {
118275
- error: `unsupported file extension: ${path138.extname(scanPath)}`,
118665
+ error: `unsupported file extension: ${path139.extname(scanPath)}`,
118276
118666
  total: 0,
118277
118667
  byPriority: { high: 0, medium: 0, low: 0 },
118278
118668
  entries: []
@@ -118321,17 +118711,17 @@ init_schema();
118321
118711
  init_qa_gate_profile();
118322
118712
  init_gate_evidence();
118323
118713
  import * as fs108 from "node:fs";
118324
- import * as path142 from "node:path";
118714
+ import * as path143 from "node:path";
118325
118715
 
118326
118716
  // src/hooks/diff-scope.ts
118327
118717
  init_bun_compat();
118328
118718
  import * as fs106 from "node:fs";
118329
- import * as path140 from "node:path";
118719
+ import * as path141 from "node:path";
118330
118720
 
118331
118721
  // src/utils/gitignore-warning.ts
118332
118722
  init_bun_compat();
118333
118723
  import * as fs105 from "node:fs";
118334
- import * as path139 from "node:path";
118724
+ import * as path140 from "node:path";
118335
118725
  var _internals58 = { bunSpawn };
118336
118726
  var _swarmGitExcludedChecked = false;
118337
118727
  function fileCoversSwarm(content) {
@@ -118405,10 +118795,10 @@ async function ensureSwarmGitExcluded(directory, options = {}) {
118405
118795
  const excludeRelPath = excludePathRaw.trim();
118406
118796
  if (!excludeRelPath)
118407
118797
  return;
118408
- const excludePath = path139.isAbsolute(excludeRelPath) ? excludeRelPath : path139.join(directory, excludeRelPath);
118798
+ const excludePath = path140.isAbsolute(excludeRelPath) ? excludeRelPath : path140.join(directory, excludeRelPath);
118409
118799
  if (checkIgnoreExitCode !== 0) {
118410
118800
  try {
118411
- fs105.mkdirSync(path139.dirname(excludePath), { recursive: true });
118801
+ fs105.mkdirSync(path140.dirname(excludePath), { recursive: true });
118412
118802
  let existing = "";
118413
118803
  try {
118414
118804
  existing = fs105.readFileSync(excludePath, "utf8");
@@ -118452,7 +118842,7 @@ async function ensureSwarmGitExcluded(directory, options = {}) {
118452
118842
  var _internals59 = { bunSpawn };
118453
118843
  function getDeclaredScope(taskId, directory) {
118454
118844
  try {
118455
- const planPath = path140.join(directory, ".swarm", "plan.json");
118845
+ const planPath = path141.join(directory, ".swarm", "plan.json");
118456
118846
  if (!fs106.existsSync(planPath))
118457
118847
  return null;
118458
118848
  const raw = fs106.readFileSync(planPath, "utf-8");
@@ -118558,7 +118948,7 @@ init_telemetry();
118558
118948
  // src/turbo/lean/task-completion.ts
118559
118949
  init_file_locks();
118560
118950
  import * as fs107 from "node:fs";
118561
- import * as path141 from "node:path";
118951
+ import * as path142 from "node:path";
118562
118952
  var _internals60 = {
118563
118953
  listActiveLocks,
118564
118954
  verifyLeanTurboTaskCompletion
@@ -118577,7 +118967,7 @@ var TIER_3_PATTERNS = [
118577
118967
  ];
118578
118968
  function matchesTier3Pattern(files) {
118579
118969
  for (const file3 of files) {
118580
- const fileName = path141.basename(file3);
118970
+ const fileName = path142.basename(file3);
118581
118971
  for (const pattern of TIER_3_PATTERNS) {
118582
118972
  if (pattern.test(fileName)) {
118583
118973
  return true;
@@ -118589,7 +118979,7 @@ function matchesTier3Pattern(files) {
118589
118979
  function verifyLeanTurboTaskCompletion(directory, taskId, sessionID) {
118590
118980
  let persisted = null;
118591
118981
  try {
118592
- const statePath = path141.join(directory, ".swarm", "turbo-state.json");
118982
+ const statePath = path142.join(directory, ".swarm", "turbo-state.json");
118593
118983
  if (!fs107.existsSync(statePath)) {
118594
118984
  return {
118595
118985
  ok: false,
@@ -118673,11 +119063,11 @@ function verifyLeanTurboTaskCompletion(directory, taskId, sessionID) {
118673
119063
  };
118674
119064
  }
118675
119065
  const phase = runState.phase ?? 0;
118676
- const evidencePath = path141.join(directory, ".swarm", "evidence", String(phase), "lean-turbo", `${lane.laneId}.json`);
118677
- const expectedDir = path141.join(directory, ".swarm", "evidence", String(phase), "lean-turbo");
118678
- const resolvedPath = path141.resolve(evidencePath);
118679
- const resolvedDir = path141.resolve(expectedDir);
118680
- 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) {
118681
119071
  return {
118682
119072
  ok: false,
118683
119073
  reason: `Lane ID causes path traversal: ${lane.laneId}`,
@@ -118717,7 +119107,7 @@ function verifyLeanTurboTaskCompletion(directory, taskId, sessionID) {
118717
119107
  }
118718
119108
  let filesTouched = [];
118719
119109
  try {
118720
- const planPath = path141.join(directory, ".swarm", "plan.json");
119110
+ const planPath = path142.join(directory, ".swarm", "plan.json");
118721
119111
  const planRaw = fs107.readFileSync(planPath, "utf-8");
118722
119112
  const plan = JSON.parse(planRaw);
118723
119113
  for (const planPhase of plan.phases ?? []) {
@@ -118801,7 +119191,7 @@ var TIER_3_PATTERNS2 = [
118801
119191
  ];
118802
119192
  function matchesTier3Pattern2(files) {
118803
119193
  for (const file3 of files) {
118804
- const fileName = path142.basename(file3);
119194
+ const fileName = path143.basename(file3);
118805
119195
  for (const pattern of TIER_3_PATTERNS2) {
118806
119196
  if (pattern.test(fileName)) {
118807
119197
  return true;
@@ -118840,7 +119230,7 @@ function checkReviewerGate(taskId, workingDirectory, stageBParallelEnabled = fal
118840
119230
  if (!skipStandardTurboBypass && hasActiveTurboMode()) {
118841
119231
  const resolvedDir2 = workingDirectory;
118842
119232
  try {
118843
- const planPath = path142.join(resolvedDir2, ".swarm", "plan.json");
119233
+ const planPath = path143.join(resolvedDir2, ".swarm", "plan.json");
118844
119234
  const planRaw = fs108.readFileSync(planPath, "utf-8");
118845
119235
  const plan = JSON.parse(planRaw);
118846
119236
  for (const planPhase of plan.phases ?? []) {
@@ -118918,7 +119308,7 @@ function checkReviewerGate(taskId, workingDirectory, stageBParallelEnabled = fal
118918
119308
  }
118919
119309
  if (resolvedDir) {
118920
119310
  try {
118921
- const planPath = path142.join(resolvedDir, ".swarm", "plan.json");
119311
+ const planPath = path143.join(resolvedDir, ".swarm", "plan.json");
118922
119312
  const planRaw = fs108.readFileSync(planPath, "utf-8");
118923
119313
  const plan = JSON.parse(planRaw);
118924
119314
  for (const planPhase of plan.phases ?? []) {
@@ -119155,8 +119545,8 @@ async function executeUpdateTaskStatus(args2, fallbackDir, ctx) {
119155
119545
  };
119156
119546
  }
119157
119547
  }
119158
- normalizedDir = path142.normalize(args2.working_directory);
119159
- const pathParts = normalizedDir.split(path142.sep);
119548
+ normalizedDir = path143.normalize(args2.working_directory);
119549
+ const pathParts = normalizedDir.split(path143.sep);
119160
119550
  if (pathParts.includes("..")) {
119161
119551
  return {
119162
119552
  success: false,
@@ -119166,10 +119556,10 @@ async function executeUpdateTaskStatus(args2, fallbackDir, ctx) {
119166
119556
  ]
119167
119557
  };
119168
119558
  }
119169
- const resolvedDir = path142.resolve(normalizedDir);
119559
+ const resolvedDir = path143.resolve(normalizedDir);
119170
119560
  try {
119171
119561
  const realPath = fs108.realpathSync(resolvedDir);
119172
- const planPath = path142.join(realPath, ".swarm", "plan.json");
119562
+ const planPath = path143.join(realPath, ".swarm", "plan.json");
119173
119563
  if (!fs108.existsSync(planPath)) {
119174
119564
  return {
119175
119565
  success: false,
@@ -119200,9 +119590,9 @@ async function executeUpdateTaskStatus(args2, fallbackDir, ctx) {
119200
119590
  directory = fallbackDir;
119201
119591
  }
119202
119592
  if (fallbackDir && directory !== fallbackDir) {
119203
- const canonicalDir = fs108.realpathSync(path142.resolve(directory));
119204
- const canonicalRoot = fs108.realpathSync(path142.resolve(fallbackDir));
119205
- 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)) {
119206
119596
  return {
119207
119597
  success: false,
119208
119598
  message: `Invalid working_directory: "${directory}" is a subdirectory of ` + `the project root "${fallbackDir}". Pass the project root path or ` + `omit working_directory entirely.`,
@@ -119214,8 +119604,8 @@ async function executeUpdateTaskStatus(args2, fallbackDir, ctx) {
119214
119604
  }
119215
119605
  if (args2.status === "in_progress") {
119216
119606
  try {
119217
- const evidencePath = path142.join(directory, ".swarm", "evidence", `${args2.task_id}.json`);
119218
- 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 });
119219
119609
  const fd = fs108.openSync(evidencePath, "wx");
119220
119610
  let writeOk = false;
119221
119611
  try {
@@ -119239,7 +119629,7 @@ async function executeUpdateTaskStatus(args2, fallbackDir, ctx) {
119239
119629
  recoverTaskStateFromDelegations(args2.task_id, directory);
119240
119630
  let phaseRequiresReviewer = true;
119241
119631
  try {
119242
- const planPath = path142.join(directory, ".swarm", "plan.json");
119632
+ const planPath = path143.join(directory, ".swarm", "plan.json");
119243
119633
  const planRaw = fs108.readFileSync(planPath, "utf-8");
119244
119634
  const plan = JSON.parse(planRaw);
119245
119635
  const taskPhase = plan.phases.find((p) => p.tasks.some((t) => t.id === args2.task_id));
@@ -119551,7 +119941,7 @@ init_ledger();
119551
119941
  init_manager();
119552
119942
  init_create_tool();
119553
119943
  import fs109 from "node:fs";
119554
- import path143 from "node:path";
119944
+ import path144 from "node:path";
119555
119945
  function normalizeVerdict(verdict) {
119556
119946
  switch (verdict) {
119557
119947
  case "APPROVED":
@@ -119599,7 +119989,7 @@ async function executeWriteDriftEvidence(args2, directory) {
119599
119989
  entries: [evidenceEntry]
119600
119990
  };
119601
119991
  const filename = "drift-verifier.json";
119602
- const relativePath = path143.join("evidence", String(phase), filename);
119992
+ const relativePath = path144.join("evidence", String(phase), filename);
119603
119993
  let validatedPath;
119604
119994
  try {
119605
119995
  validatedPath = validateSwarmPath(directory, relativePath);
@@ -119610,10 +120000,10 @@ async function executeWriteDriftEvidence(args2, directory) {
119610
120000
  message: error93 instanceof Error ? error93.message : "Failed to validate path"
119611
120001
  }, null, 2);
119612
120002
  }
119613
- const evidenceDir = path143.dirname(validatedPath);
120003
+ const evidenceDir = path144.dirname(validatedPath);
119614
120004
  try {
119615
120005
  await fs109.promises.mkdir(evidenceDir, { recursive: true });
119616
- const tempPath = path143.join(evidenceDir, `.${filename}.tmp`);
120006
+ const tempPath = path144.join(evidenceDir, `.${filename}.tmp`);
119617
120007
  await fs109.promises.writeFile(tempPath, JSON.stringify(evidenceContent, null, 2), "utf-8");
119618
120008
  await fs109.promises.rename(tempPath, validatedPath);
119619
120009
  let snapshotInfo;
@@ -119709,7 +120099,7 @@ var write_drift_evidence = createSwarmTool({
119709
120099
  init_zod();
119710
120100
  init_loader();
119711
120101
  import fs110 from "node:fs";
119712
- import path144 from "node:path";
120102
+ import path145 from "node:path";
119713
120103
  init_utils2();
119714
120104
  init_manager();
119715
120105
  init_create_tool();
@@ -119797,7 +120187,7 @@ async function executeWriteFinalCouncilEvidence(args2, directory) {
119797
120187
  timestamp: synthesis.timestamp
119798
120188
  };
119799
120189
  const filename = "final-council.json";
119800
- const relativePath = path144.join("evidence", filename);
120190
+ const relativePath = path145.join("evidence", filename);
119801
120191
  let validatedPath;
119802
120192
  try {
119803
120193
  validatedPath = validateSwarmPath(directory, relativePath);
@@ -119811,10 +120201,10 @@ async function executeWriteFinalCouncilEvidence(args2, directory) {
119811
120201
  const evidenceContent = {
119812
120202
  entries: [evidenceEntry]
119813
120203
  };
119814
- const evidenceDir = path144.dirname(validatedPath);
120204
+ const evidenceDir = path145.dirname(validatedPath);
119815
120205
  try {
119816
120206
  await fs110.promises.mkdir(evidenceDir, { recursive: true });
119817
- const tempPath = path144.join(evidenceDir, `.${filename}.tmp`);
120207
+ const tempPath = path145.join(evidenceDir, `.${filename}.tmp`);
119818
120208
  await fs110.promises.writeFile(tempPath, JSON.stringify(evidenceContent, null, 2), "utf-8");
119819
120209
  await fs110.promises.rename(tempPath, validatedPath);
119820
120210
  return JSON.stringify({
@@ -119873,7 +120263,7 @@ init_zod();
119873
120263
  init_utils2();
119874
120264
  init_create_tool();
119875
120265
  import fs111 from "node:fs";
119876
- import path145 from "node:path";
120266
+ import path146 from "node:path";
119877
120267
  function normalizeVerdict2(verdict) {
119878
120268
  switch (verdict) {
119879
120269
  case "APPROVED":
@@ -119921,7 +120311,7 @@ async function executeWriteHallucinationEvidence(args2, directory) {
119921
120311
  entries: [evidenceEntry]
119922
120312
  };
119923
120313
  const filename = "hallucination-guard.json";
119924
- const relativePath = path145.join("evidence", String(phase), filename);
120314
+ const relativePath = path146.join("evidence", String(phase), filename);
119925
120315
  let validatedPath;
119926
120316
  try {
119927
120317
  validatedPath = validateSwarmPath(directory, relativePath);
@@ -119932,10 +120322,10 @@ async function executeWriteHallucinationEvidence(args2, directory) {
119932
120322
  message: error93 instanceof Error ? error93.message : "Failed to validate path"
119933
120323
  }, null, 2);
119934
120324
  }
119935
- const evidenceDir = path145.dirname(validatedPath);
120325
+ const evidenceDir = path146.dirname(validatedPath);
119936
120326
  try {
119937
120327
  await fs111.promises.mkdir(evidenceDir, { recursive: true });
119938
- const tempPath = path145.join(evidenceDir, `.${filename}.tmp`);
120328
+ const tempPath = path146.join(evidenceDir, `.${filename}.tmp`);
119939
120329
  await fs111.promises.writeFile(tempPath, JSON.stringify(evidenceContent, null, 2), "utf-8");
119940
120330
  await fs111.promises.rename(tempPath, validatedPath);
119941
120331
  return JSON.stringify({
@@ -119984,7 +120374,7 @@ init_zod();
119984
120374
  init_utils2();
119985
120375
  init_create_tool();
119986
120376
  import fs112 from "node:fs";
119987
- import path146 from "node:path";
120377
+ import path147 from "node:path";
119988
120378
  function normalizeVerdict3(verdict) {
119989
120379
  switch (verdict) {
119990
120380
  case "PASS":
@@ -120058,7 +120448,7 @@ async function executeWriteMutationEvidence(args2, directory) {
120058
120448
  entries: [evidenceEntry]
120059
120449
  };
120060
120450
  const filename = "mutation-gate.json";
120061
- const relativePath = path146.join("evidence", String(phase), filename);
120451
+ const relativePath = path147.join("evidence", String(phase), filename);
120062
120452
  let validatedPath;
120063
120453
  try {
120064
120454
  validatedPath = validateSwarmPath(directory, relativePath);
@@ -120069,10 +120459,10 @@ async function executeWriteMutationEvidence(args2, directory) {
120069
120459
  message: error93 instanceof Error ? error93.message : "Failed to validate path"
120070
120460
  }, null, 2);
120071
120461
  }
120072
- const evidenceDir = path146.dirname(validatedPath);
120462
+ const evidenceDir = path147.dirname(validatedPath);
120073
120463
  try {
120074
120464
  await fs112.promises.mkdir(evidenceDir, { recursive: true });
120075
- const tempPath = path146.join(evidenceDir, `.${filename}.tmp`);
120465
+ const tempPath = path147.join(evidenceDir, `.${filename}.tmp`);
120076
120466
  await fs112.promises.writeFile(tempPath, JSON.stringify(evidenceContent, null, 2), "utf-8");
120077
120467
  await fs112.promises.rename(tempPath, validatedPath);
120078
120468
  return JSON.stringify({
@@ -120422,7 +120812,7 @@ async function initializeOpenCodeSwarm(ctx) {
120422
120812
  const { PreflightTriggerManager: PTM } = await Promise.resolve().then(() => (init_trigger(), exports_trigger));
120423
120813
  preflightTriggerManager = new PTM(automationConfig);
120424
120814
  const { AutomationStatusArtifact: ASA } = await Promise.resolve().then(() => (init_status_artifact(), exports_status_artifact));
120425
- const swarmDir = path148.resolve(ctx.directory, ".swarm");
120815
+ const swarmDir = path149.resolve(ctx.directory, ".swarm");
120426
120816
  statusArtifact = new ASA(swarmDir);
120427
120817
  statusArtifact.updateConfig(automationConfig.mode, automationConfig.capabilities);
120428
120818
  if (automationConfig.capabilities?.evidence_auto_summaries === true) {
@@ -120601,30 +120991,29 @@ async function initializeOpenCodeSwarm(ctx) {
120601
120991
  swarm_command: createSwarmCommandTool(agentDefinitionMap)
120602
120992
  },
120603
120993
  config: async (opencodeConfig) => {
120604
- if (!opencodeConfig.agent || typeof opencodeConfig.agent !== "object") {
120605
- opencodeConfig.agent = {};
120606
- }
120607
- if (!opencodeConfig.agent) {
120608
- opencodeConfig.agent = { ...agents };
120609
- } else {
120610
- 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 = {};
120611
120998
  }
120999
+ const agentConfig = pluginConfig.agent;
121000
+ Object.assign(agentConfig, agents);
120612
121001
  const autoSelect = config3?.auto_select_architect;
120613
121002
  if (autoSelect) {
120614
121003
  const hasArchitect = Object.keys(agents).some((name2) => stripKnownSwarmPrefix(name2) === "architect");
120615
121004
  if (hasArchitect) {
120616
121005
  for (const builtin of ["build", "plan"]) {
120617
- const existing = opencodeConfig.agent?.[builtin];
120618
- if (existing && typeof existing === "object" && existing.disable === true) {
121006
+ const existing = agentConfig[builtin];
121007
+ if (isObjectRecord(existing) && existing.disable === true) {
120619
121008
  continue;
120620
121009
  }
120621
- opencodeConfig.agent[builtin] = {
120622
- ...existing && typeof existing === "object" ? existing : {},
121010
+ agentConfig[builtin] = {
121011
+ ...isObjectRecord(existing) ? existing : {},
120623
121012
  disable: true
120624
121013
  };
120625
121014
  }
120626
121015
  if (autoSelect === true) {
120627
- 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");
120628
121017
  if (primaryArchitects.length > 1) {
120629
121018
  const names = primaryArchitects.map(([n]) => n).join(", ");
120630
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.`);
@@ -120636,22 +121025,19 @@ async function initializeOpenCodeSwarm(ctx) {
120636
121025
  if (targetIsArchitect) {
120637
121026
  for (const [name2, cfg] of Object.entries(agents)) {
120638
121027
  if (stripKnownSwarmPrefix(name2) === "architect" && name2 !== targetName) {
120639
- if (opencodeConfig.agent && typeof opencodeConfig.agent === "object") {
120640
- opencodeConfig.agent[name2] = {
120641
- ...cfg && typeof cfg === "object" ? cfg : {},
120642
- mode: "subagent"
120643
- };
120644
- }
121028
+ agentConfig[name2] = {
121029
+ ...isObjectRecord(cfg) ? cfg : {},
121030
+ mode: "subagent"
121031
+ };
120645
121032
  }
120646
121033
  }
120647
- if (opencodeConfig.agent && typeof opencodeConfig.agent === "object") {
120648
- const targetExisting = opencodeConfig.agent[targetName];
120649
- opencodeConfig.agent[targetName] = {
120650
- ...targetExisting && typeof targetExisting === "object" ? targetExisting : {},
120651
- ...agents[targetName] && typeof agents[targetName] === "object" ? agents[targetName] : {},
120652
- mode: "primary"
120653
- };
120654
- }
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
+ };
120655
121041
  } else {
120656
121042
  addDeferredWarning(`[swarm] auto_select_architect is set to "${targetName}" but that is not a known architect agent. No architect demotion applied.`);
120657
121043
  }
@@ -121006,7 +121392,7 @@ ${promptRaw}`;
121006
121392
  "ci-failure-resolver": "CI/CD failure resolution"
121007
121393
  };
121008
121394
  const skillPaths = topSkills.map((s) => {
121009
- const dirName = path148.basename(path148.dirname(s.skillPath));
121395
+ const dirName = path149.basename(path149.dirname(s.skillPath));
121010
121396
  const desc = SKILL_DESCRIPTIONS[dirName] ?? dirName;
121011
121397
  return `file:${s.skillPath} (-- ${desc})`;
121012
121398
  }).join(", ");
@@ -121015,7 +121401,7 @@ ${promptRaw}`;
121015
121401
 
121016
121402
  ${promptRaw}`;
121017
121403
  argsRecord.prompt = newPrompt;
121018
- 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(", ");
121019
121405
  console.warn(`[skill-propagation-gate] Injected skills: ${skillNames}`);
121020
121406
  for (const skill of topSkills) {
121021
121407
  try {