opencode-swarm 7.19.0 → 7.19.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -33,7 +33,7 @@ var package_default;
33
33
  var init_package = __esm(() => {
34
34
  package_default = {
35
35
  name: "opencode-swarm",
36
- version: "7.19.0",
36
+ version: "7.19.2",
37
37
  description: "Architect-centric agentic swarm plugin for OpenCode - hub-and-spoke orchestration with SME consultation, code generation, and QA review",
38
38
  main: "dist/index.js",
39
39
  types: "dist/index.d.ts",
@@ -17348,6 +17348,17 @@ function applyEventToPlan(plan, event) {
17348
17348
  return plan;
17349
17349
  case "task_added":
17350
17350
  return plan;
17351
+ case "task_removed":
17352
+ if (event.task_id) {
17353
+ for (const phase of plan.phases) {
17354
+ const idx = phase.tasks.findIndex((t) => t.id === event.task_id);
17355
+ if (idx !== -1) {
17356
+ phase.tasks.splice(idx, 1);
17357
+ break;
17358
+ }
17359
+ }
17360
+ }
17361
+ return plan;
17351
17362
  case "task_updated":
17352
17363
  return plan;
17353
17364
  case "plan_rebuilt":
@@ -17455,7 +17466,7 @@ async function loadLastApprovedPlan(directory, expectedPlanId) {
17455
17466
  }
17456
17467
  return null;
17457
17468
  }
17458
- var LEDGER_SCHEMA_VERSION = "1.0.0", LEDGER_FILENAME = "plan-ledger.jsonl", PLAN_JSON_FILENAME = "plan.json", LedgerStaleWriterError;
17469
+ var LEDGER_SCHEMA_VERSION = "1.1.0", LEDGER_FILENAME = "plan-ledger.jsonl", PLAN_JSON_FILENAME = "plan.json", LedgerStaleWriterError;
17459
17470
  var init_ledger = __esm(() => {
17460
17471
  init_plan_schema();
17461
17472
  LedgerStaleWriterError = class LedgerStaleWriterError extends Error {
@@ -17745,7 +17756,13 @@ async function loadPlan(directory) {
17745
17756
  const planMdContent2 = await readSwarmFileAsync(directory, "plan.md");
17746
17757
  if (planMdContent2 !== null) {
17747
17758
  const migrated = migrateLegacyPlan(planMdContent2);
17748
- await savePlan(directory, migrated);
17759
+ const { removedCount } = await savePlanWithAutoAcknowledgedRemovals(directory, migrated, "load_plan_migration_from_md", "migrate legacy plan.md to plan.json");
17760
+ if (removedCount > 0) {
17761
+ migrated._midLoadRemovals = {
17762
+ count: removedCount,
17763
+ source: "load_plan_migration_from_md"
17764
+ };
17765
+ }
17749
17766
  return migrated;
17750
17767
  }
17751
17768
  }
@@ -17774,7 +17791,13 @@ async function loadPlan(directory) {
17774
17791
  try {
17775
17792
  const rebuilt = await replayFromLedger(directory);
17776
17793
  if (rebuilt) {
17777
- await savePlan(directory, rebuilt);
17794
+ const { removedCount } = await savePlanWithAutoAcknowledgedRemovals(directory, rebuilt, "load_plan_rebuild_from_ledger", "rebuild plan from ledger replay");
17795
+ if (removedCount > 0) {
17796
+ rebuilt._midLoadRemovals = {
17797
+ count: removedCount,
17798
+ source: "load_plan_rebuild_from_ledger"
17799
+ };
17800
+ }
17778
17801
  return rebuilt;
17779
17802
  }
17780
17803
  try {
@@ -17788,7 +17811,13 @@ async function loadPlan(directory) {
17788
17811
  if (approved) {
17789
17812
  const approvedPhase = approved.approval && typeof approved.approval === "object" && "phase" in approved.approval ? approved.approval.phase : undefined;
17790
17813
  warn(`[loadPlan] Ledger replay returned no plan — recovered from critic-approved snapshot seq=${approved.seq} timestamp=${approved.timestamp} (approval phase=${approvedPhase ?? "unknown"}). This may roll the plan back to an earlier phase — verify before continuing.`);
17791
- await savePlan(directory, approved.plan);
17814
+ const { removedCount: snapshotRemovedCount } = await savePlanWithAutoAcknowledgedRemovals(directory, approved.plan, "load_plan_recovery_from_approved_snapshot", "restore from critic-approved snapshot");
17815
+ if (snapshotRemovedCount > 0) {
17816
+ approved.plan._midLoadRemovals = {
17817
+ count: snapshotRemovedCount,
17818
+ source: "load_plan_recovery_from_approved_snapshot"
17819
+ };
17820
+ }
17792
17821
  try {
17793
17822
  await takeSnapshotEvent(directory, approved.plan, {
17794
17823
  source: "recovery_from_approved_snapshot",
@@ -17809,6 +17838,28 @@ async function loadPlan(directory) {
17809
17838
  }
17810
17839
  return null;
17811
17840
  }
17841
+ async function savePlanWithAutoAcknowledgedRemovals(directory, plan, source, reason, options) {
17842
+ const existing = await _internals6.loadPlanJsonOnly(directory);
17843
+ const newIds = new Set;
17844
+ for (const phase of plan.phases) {
17845
+ for (const task of phase.tasks)
17846
+ newIds.add(task.id);
17847
+ }
17848
+ const removedIds = [];
17849
+ if (existing) {
17850
+ for (const phase of existing.phases) {
17851
+ for (const task of phase.tasks) {
17852
+ if (!newIds.has(task.id))
17853
+ removedIds.push(task.id);
17854
+ }
17855
+ }
17856
+ }
17857
+ await savePlan(directory, plan, {
17858
+ ...options ?? {},
17859
+ acknowledged_removals: { ids: removedIds, reason, source }
17860
+ });
17861
+ return { removedCount: removedIds.length };
17862
+ }
17812
17863
  async function savePlan(directory, plan, options) {
17813
17864
  if (directory === null || directory === undefined || typeof directory !== "string" || directory.trim().length === 0) {
17814
17865
  throw new Error(`Invalid directory: directory must be a non-empty string`);
@@ -17945,6 +17996,73 @@ async function savePlan(directory, plan, options) {
17945
17996
  oldTaskMap.set(task.id, { phase: task.phase, status: task.status });
17946
17997
  }
17947
17998
  }
17999
+ const newTaskIds = new Set;
18000
+ for (const phase of validated.phases) {
18001
+ for (const task of phase.tasks)
18002
+ newTaskIds.add(task.id);
18003
+ }
18004
+ const missingTasks = [];
18005
+ for (const [id, info2] of oldTaskMap.entries()) {
18006
+ if (!newTaskIds.has(id)) {
18007
+ missingTasks.push({ id, phase: info2.phase, status: info2.status });
18008
+ }
18009
+ }
18010
+ const ack = options?.acknowledged_removals;
18011
+ if (missingTasks.length > 0) {
18012
+ if (!ack) {
18013
+ throw new PlanTaskRemovalNotAcknowledgedError(missingTasks);
18014
+ }
18015
+ if (typeof ack.reason !== "string" || ack.reason.trim().length === 0) {
18016
+ throw new Error("PLAN_ACKNOWLEDGED_REMOVAL_INVALID: acknowledged_removals.reason must be a non-empty string.");
18017
+ }
18018
+ if (typeof ack.source !== "string" || ack.source.trim().length === 0) {
18019
+ throw new Error("PLAN_ACKNOWLEDGED_REMOVAL_INVALID: acknowledged_removals.source must be a non-empty string.");
18020
+ }
18021
+ const ackSet = new Set(ack.ids);
18022
+ const missingIdsSet = new Set(missingTasks.map((t) => t.id));
18023
+ const unacked = missingTasks.filter((t) => !ackSet.has(t.id));
18024
+ if (unacked.length > 0) {
18025
+ throw new PlanTaskRemovalNotAcknowledgedError(unacked);
18026
+ }
18027
+ for (const id of ack.ids) {
18028
+ if (!missingIdsSet.has(id)) {
18029
+ throw new Error(`PLAN_ACKNOWLEDGED_REMOVAL_INVALID: acknowledged_removals contains "${id}" but that task is not missing from the plan.`);
18030
+ }
18031
+ }
18032
+ try {
18033
+ for (const missing of missingTasks) {
18034
+ const eventInput = {
18035
+ plan_id: derivePlanId(validated),
18036
+ event_type: "task_removed",
18037
+ task_id: missing.id,
18038
+ phase_id: missing.phase,
18039
+ from_status: missing.status,
18040
+ source: ack.source,
18041
+ payload: { reason: ack.reason, source: ack.source }
18042
+ };
18043
+ const capturedTaskId = missing.id;
18044
+ await retryCasWithBackoff(directory, eventInput, {
18045
+ expectedHash: currentHash,
18046
+ planHashAfter: hashAfter,
18047
+ verifyValid: async () => {
18048
+ const onDisk = await _internals6.loadPlanJsonOnly(directory);
18049
+ if (!onDisk)
18050
+ return true;
18051
+ for (const p of onDisk.phases) {
18052
+ if (p.tasks.some((x) => x.id === capturedTaskId))
18053
+ return true;
18054
+ }
18055
+ return false;
18056
+ }
18057
+ });
18058
+ }
18059
+ } catch (error49) {
18060
+ if (error49 instanceof LedgerStaleWriterError) {
18061
+ throw new PlanConcurrentModificationError(`Concurrent plan modification detected after retries: ${error49.message}. Please retry the operation.`);
18062
+ }
18063
+ throw error49;
18064
+ }
18065
+ }
17948
18066
  try {
17949
18067
  for (const phase of validated.phases) {
17950
18068
  for (const task of phase.tasks) {
@@ -18411,7 +18529,7 @@ function migrateLegacyPlan(planContent, swarmId) {
18411
18529
  };
18412
18530
  return plan;
18413
18531
  }
18414
- var PlanConcurrentModificationError, startupLedgerCheckedWorkspaces, recoveryMutexes, _internals6, CAS_BACKOFF_START_MS = 5, CAS_BACKOFF_CAP_MS = 250, CAS_BACKOFF_JITTER = 0.25, CAS_MAX_RETRIES = 3;
18532
+ var PlanConcurrentModificationError, PlanTaskRemovalNotAcknowledgedError, startupLedgerCheckedWorkspaces, recoveryMutexes, _internals6, CAS_BACKOFF_START_MS = 5, CAS_BACKOFF_CAP_MS = 250, CAS_BACKOFF_JITTER = 0.25, CAS_MAX_RETRIES = 3;
18415
18533
  var init_manager = __esm(() => {
18416
18534
  init_plan_schema();
18417
18535
  init_utils2();
@@ -18426,6 +18544,15 @@ var init_manager = __esm(() => {
18426
18544
  this.name = "PlanConcurrentModificationError";
18427
18545
  }
18428
18546
  };
18547
+ PlanTaskRemovalNotAcknowledgedError = class PlanTaskRemovalNotAcknowledgedError extends Error {
18548
+ missingTasks;
18549
+ constructor(missingTasks) {
18550
+ const idList = missingTasks.map((t) => `${t.id}(${t.status})`).join(", ");
18551
+ super(`PLAN_TASK_REMOVAL_NOT_ACKNOWLEDGED: the following tasks were present in the prior plan but missing from the new save: ${idList}. Pass acknowledged_removals.ids covering all missing task IDs with a non-empty reason to proceed.`);
18552
+ this.name = "PlanTaskRemovalNotAcknowledgedError";
18553
+ this.missingTasks = missingTasks;
18554
+ }
18555
+ };
18429
18556
  startupLedgerCheckedWorkspaces = new Set;
18430
18557
  recoveryMutexes = new Map;
18431
18558
  _internals6 = {
@@ -24039,6 +24166,16 @@ var init_normalize_tool_name = __esm(() => {
24039
24166
  import * as fsSync2 from "node:fs";
24040
24167
  import * as fs8 from "node:fs/promises";
24041
24168
  import * as path10 from "node:path";
24169
+ function enforceSpecDriftGate(directory, toolName) {
24170
+ if (!directory)
24171
+ return;
24172
+ if (!SPEC_DRIFT_BLOCKED_TOOLS.has(toolName))
24173
+ return;
24174
+ const stalePath = path10.join(directory, ".swarm", "spec-staleness.json");
24175
+ if (fsSync2.existsSync(stalePath)) {
24176
+ throw new Error(`SPEC_DRIFT_BLOCK: tool "${toolName}" is blocked because .swarm/spec-staleness.json exists. ` + "Run /swarm clarify to update the spec, or /swarm acknowledge-spec-drift to dismiss, then retry.");
24177
+ }
24178
+ }
24042
24179
  function extractStatusCode(errorMsg) {
24043
24180
  const match = errorMsg.match(/\b(408|429|500|502|503|504|529)\b/);
24044
24181
  if (match) {
@@ -25043,6 +25180,7 @@ function createGuardrailsHooks(directory, directoryOrConfig, config2, authorityC
25043
25180
  await appendShellAuditLog(input.sessionID, input.tool, output.args);
25044
25181
  handleInterpreterGating(input.sessionID, input.tool);
25045
25182
  checkDestructiveCommand(input.tool, output.args);
25183
+ enforceSpecDriftGate(effectiveDirectory, input.tool);
25046
25184
  if (isArchitect(input.sessionID) && isWriteTool(input.tool)) {
25047
25185
  handlePlanAndScopeProtection(input.sessionID, input.tool, output.args);
25048
25186
  }
@@ -25891,7 +26029,7 @@ function checkFileAuthorityWithRules(agentName, filePath, cwd, effectiveRules, o
25891
26029
  }
25892
26030
  return { allowed: true };
25893
26031
  }
25894
- var import_picomatch, storedInputArgs, TRANSIENT_STATUS_CODES, TRANSIENT_MODEL_ERROR_PATTERN, DEGRADED_ERROR_PATTERN, CONTENT_FILTER_PATTERN, toolCallsSinceLastWrite, noOpWarningIssued, consecutiveNoToolTurns, DC_MAX_UNWRAP_DEPTH = 5, DC_SAFE_TARGETS, DC_BLOCKED_ABSOLUTE_PREFIXES, DC_FS_ROOTS, DC_REMOTE_PREFIXES, pathNormalizationCache, globMatcherCache, DEFAULT_AGENT_AUTHORITY_RULES;
26032
+ var import_picomatch, SPEC_DRIFT_BLOCKED_TOOLS, storedInputArgs, TRANSIENT_STATUS_CODES, TRANSIENT_MODEL_ERROR_PATTERN, DEGRADED_ERROR_PATTERN, CONTENT_FILTER_PATTERN, toolCallsSinceLastWrite, noOpWarningIssued, consecutiveNoToolTurns, DC_MAX_UNWRAP_DEPTH = 5, DC_SAFE_TARGETS, DC_BLOCKED_ABSOLUTE_PREFIXES, DC_FS_ROOTS, DC_REMOTE_PREFIXES, pathNormalizationCache, globMatcherCache, DEFAULT_AGENT_AUTHORITY_RULES;
25895
26033
  var init_guardrails = __esm(() => {
25896
26034
  init_quick_lru();
25897
26035
  init_agents2();
@@ -25911,6 +26049,13 @@ var init_guardrails = __esm(() => {
25911
26049
  init_model_limits();
25912
26050
  init_normalize_tool_name();
25913
26051
  import_picomatch = __toESM(require_picomatch2(), 1);
26052
+ SPEC_DRIFT_BLOCKED_TOOLS = new Set([
26053
+ "save_plan",
26054
+ "update_task_status",
26055
+ "phase_complete",
26056
+ "lean_turbo_run_phase",
26057
+ "lean_turbo_acquire_locks"
26058
+ ]);
25914
26059
  storedInputArgs = new Map;
25915
26060
  TRANSIENT_STATUS_CODES = new Set([408, 429, 500, 502, 503, 504, 529]);
25916
26061
  TRANSIENT_MODEL_ERROR_PATTERN = /rate.?limit|429|500|502|503|504|529|timeout|overloaded|model.?not.?found|temporarily.?unavailable|server.?error|connection.?(refused|reset|timeout)|bad.?gateway|gateway.?timeout|internal.?server.?error|service.?unavailable/i;
@@ -41986,7 +42131,7 @@ var init_event_bus = __esm(() => {
41986
42131
  });
41987
42132
 
41988
42133
  // src/hooks/knowledge-store.ts
41989
- import { existsSync as existsSync9 } from "node:fs";
42134
+ import { existsSync as existsSync10 } from "node:fs";
41990
42135
  import { appendFile as appendFile3, mkdir as mkdir3, readFile as readFile5, writeFile as writeFile3 } from "node:fs/promises";
41991
42136
  import * as os3 from "node:os";
41992
42137
  import * as path15 from "node:path";
@@ -42014,7 +42159,7 @@ function resolveHiveRejectedPath() {
42014
42159
  return path15.join(path15.dirname(hivePath), "shared-learnings-rejected.jsonl");
42015
42160
  }
42016
42161
  async function readKnowledge(filePath) {
42017
- if (!existsSync9(filePath))
42162
+ if (!existsSync10(filePath))
42018
42163
  return [];
42019
42164
  const content = await readFile5(filePath, "utf-8");
42020
42165
  const results = [];
@@ -42715,7 +42860,7 @@ __export(exports_skill_generator, {
42715
42860
  activateProposal: () => activateProposal,
42716
42861
  _internals: () => _internals12
42717
42862
  });
42718
- import { existsSync as existsSync10 } from "node:fs";
42863
+ import { existsSync as existsSync11 } from "node:fs";
42719
42864
  import { mkdir as mkdir5, readFile as readFile6, rename as rename3, writeFile as writeFile5 } from "node:fs/promises";
42720
42865
  import * as path17 from "node:path";
42721
42866
  function sanitizeSlug(input) {
@@ -42739,7 +42884,7 @@ function activeRepoRelativePath(slug) {
42739
42884
  async function selectCandidateEntries(directory, opts) {
42740
42885
  const swarm = await readKnowledge(resolveSwarmKnowledgePath(directory));
42741
42886
  const hivePath = resolveHiveKnowledgePath();
42742
- const hive = existsSync10(hivePath) ? await readKnowledge(hivePath) : [];
42887
+ const hive = existsSync11(hivePath) ? await readKnowledge(hivePath) : [];
42743
42888
  const all = [...swarm, ...hive];
42744
42889
  return all.filter((e) => {
42745
42890
  if (e.status === "archived")
@@ -42904,7 +43049,7 @@ async function generateSkills(req) {
42904
43049
  const idSet = new Set(req.sourceKnowledgeIds);
42905
43050
  const swarm = await readKnowledge(resolveSwarmKnowledgePath(req.directory));
42906
43051
  const hivePath = resolveHiveKnowledgePath();
42907
- const hive = existsSync10(hivePath) ? await readKnowledge(hivePath) : [];
43052
+ const hive = existsSync11(hivePath) ? await readKnowledge(hivePath) : [];
42908
43053
  pool = [...swarm, ...hive].filter((e) => idSet.has(e.id) && e.status !== "archived");
42909
43054
  } else {
42910
43055
  pool = candidates;
@@ -42941,7 +43086,7 @@ async function generateSkills(req) {
42941
43086
  continue;
42942
43087
  }
42943
43088
  let preserved = false;
42944
- if (req.mode === "active" && existsSync10(targetPath) && !req.force) {
43089
+ if (req.mode === "active" && existsSync11(targetPath) && !req.force) {
42945
43090
  const existing = await readFile6(targetPath, "utf-8");
42946
43091
  if (!existing.includes("generated by opencode-swarm skill-generator")) {
42947
43092
  preserved = true;
@@ -42986,7 +43131,7 @@ async function stampSourceEntries(directory, slug, ids) {
42986
43131
  if (touched)
42987
43132
  await rewriteKnowledge(swarmPath, swarm);
42988
43133
  const hivePath = resolveHiveKnowledgePath();
42989
- if (!existsSync10(hivePath))
43134
+ if (!existsSync11(hivePath))
42990
43135
  return;
42991
43136
  const hive = await readKnowledge(hivePath);
42992
43137
  let touchedHive = false;
@@ -43057,7 +43202,7 @@ async function activateProposal(directory, slug, force = false) {
43057
43202
  }
43058
43203
  const from = proposalPath(directory, cleanSlug);
43059
43204
  const to = activePath(directory, cleanSlug);
43060
- if (!existsSync10(from)) {
43205
+ if (!existsSync11(from)) {
43061
43206
  return {
43062
43207
  activated: false,
43063
43208
  from,
@@ -43065,7 +43210,7 @@ async function activateProposal(directory, slug, force = false) {
43065
43210
  reason: `proposal not found: ${from}`
43066
43211
  };
43067
43212
  }
43068
- if (existsSync10(to) && !force) {
43213
+ if (existsSync11(to) && !force) {
43069
43214
  const existing = await readFile6(to, "utf-8");
43070
43215
  if (!existing.includes("generated by opencode-swarm skill-generator")) {
43071
43216
  return {
@@ -43116,7 +43261,7 @@ async function listSkills(directory) {
43116
43261
  const proposalsDir = path17.join(directory, ".swarm", "skills", "proposals");
43117
43262
  const activeDir = path17.join(directory, ".opencode", "skills", "generated");
43118
43263
  const fs12 = await import("node:fs/promises");
43119
- if (existsSync10(proposalsDir)) {
43264
+ if (existsSync11(proposalsDir)) {
43120
43265
  const entries = await fs12.readdir(proposalsDir);
43121
43266
  for (const f of entries) {
43122
43267
  if (!f.endsWith(".md"))
@@ -43128,13 +43273,13 @@ async function listSkills(directory) {
43128
43273
  });
43129
43274
  }
43130
43275
  }
43131
- if (existsSync10(activeDir)) {
43276
+ if (existsSync11(activeDir)) {
43132
43277
  const entries = await fs12.readdir(activeDir, { withFileTypes: true });
43133
43278
  for (const e of entries) {
43134
43279
  if (!e.isDirectory())
43135
43280
  continue;
43136
43281
  const skillPath = path17.join(activeDir, e.name, "SKILL.md");
43137
- if (existsSync10(skillPath)) {
43282
+ if (existsSync11(skillPath)) {
43138
43283
  result.active.push({
43139
43284
  slug: e.name,
43140
43285
  path: skillPath
@@ -43154,7 +43299,7 @@ async function inspectSkill(directory, slug, prefer = "auto") {
43154
43299
  if (prefer === "proposal" || prefer === "auto")
43155
43300
  candidates.push({ p: proposalPath(directory, cleanSlug), m: "draft" });
43156
43301
  for (const c of candidates) {
43157
- if (existsSync10(c.p)) {
43302
+ if (existsSync11(c.p)) {
43158
43303
  const content = await readFile6(c.p, "utf-8");
43159
43304
  return { found: true, path: c.p, content, mode: c.m };
43160
43305
  }
@@ -44242,7 +44387,7 @@ var init_hive_promoter = __esm(() => {
44242
44387
  });
44243
44388
 
44244
44389
  // src/hooks/knowledge-reader.ts
44245
- import { existsSync as existsSync11 } from "node:fs";
44390
+ import { existsSync as existsSync12 } from "node:fs";
44246
44391
  import { mkdir as mkdir6, readFile as readFile7, writeFile as writeFile6 } from "node:fs/promises";
44247
44392
  import * as path20 from "node:path";
44248
44393
  function inferCategoriesFromPhase(phaseDescription) {
@@ -44292,7 +44437,7 @@ async function recordLessonsShown(directory, lessonIds, currentPhase) {
44292
44437
  const shownFile = path20.join(directory, ".swarm", ".knowledge-shown.json");
44293
44438
  try {
44294
44439
  let shownData = {};
44295
- if (existsSync11(shownFile)) {
44440
+ if (existsSync12(shownFile)) {
44296
44441
  const content = await readFile7(shownFile, "utf-8");
44297
44442
  shownData = JSON.parse(content);
44298
44443
  }
@@ -44400,7 +44545,7 @@ async function readMergedKnowledge(directory, config3, context) {
44400
44545
  async function updateRetrievalOutcome(directory, phaseInfo, phaseSucceeded) {
44401
44546
  const shownFile = path20.join(directory, ".swarm", ".knowledge-shown.json");
44402
44547
  try {
44403
- if (!existsSync11(shownFile)) {
44548
+ if (!existsSync12(shownFile)) {
44404
44549
  return;
44405
44550
  }
44406
44551
  const content = await readFile7(shownFile, "utf-8");
@@ -45017,7 +45162,7 @@ var init_skill_improver_llm_factory = __esm(() => {
45017
45162
  });
45018
45163
 
45019
45164
  // src/services/skill-improver-quota.ts
45020
- import { existsSync as existsSync12 } from "node:fs";
45165
+ import { existsSync as existsSync13 } from "node:fs";
45021
45166
  import { mkdir as mkdir7, readFile as readFile8, rename as rename4, writeFile as writeFile7 } from "node:fs/promises";
45022
45167
  import * as path21 from "node:path";
45023
45168
  async function acquireLock(dir) {
@@ -45049,7 +45194,7 @@ function todayKey(window2, now = new Date) {
45049
45194
  return `${yr}-${m}-${d}`;
45050
45195
  }
45051
45196
  async function readState(filePath) {
45052
- if (!existsSync12(filePath))
45197
+ if (!existsSync13(filePath))
45053
45198
  return null;
45054
45199
  try {
45055
45200
  const raw = await readFile8(filePath, "utf-8");
@@ -45151,7 +45296,7 @@ var init_skill_improver_quota = __esm(() => {
45151
45296
  });
45152
45297
 
45153
45298
  // src/services/skill-improver.ts
45154
- import { existsSync as existsSync13 } from "node:fs";
45299
+ import { existsSync as existsSync14 } from "node:fs";
45155
45300
  import { mkdir as mkdir8, rename as rename5, writeFile as writeFile8 } from "node:fs/promises";
45156
45301
  import * as path22 from "node:path";
45157
45302
  function timestampSlug(d) {
@@ -45166,7 +45311,7 @@ async function atomicWrite4(p, content) {
45166
45311
  async function gatherInventory(directory) {
45167
45312
  const swarm = await readKnowledge(resolveSwarmKnowledgePath(directory));
45168
45313
  const hivePath = resolveHiveKnowledgePath();
45169
- const hive = existsSync13(hivePath) ? await readKnowledge(hivePath) : [];
45314
+ const hive = existsSync14(hivePath) ? await readKnowledge(hivePath) : [];
45170
45315
  const archived = [...swarm, ...hive].filter((e) => e.status === "archived").length;
45171
45316
  const skills = await listSkills(directory);
45172
45317
  const matureCandidates = swarm.concat(hive).filter((e) => e.status !== "archived" && e.confidence >= 0.85 && !e.generated_skill_slug && (e.confirmed_by ?? []).length >= 2);
@@ -47154,7 +47299,7 @@ function getPluginCachePaths() {
47154
47299
  var init_cache_paths = () => {};
47155
47300
 
47156
47301
  // src/services/version-check.ts
47157
- import { existsSync as existsSync14, mkdirSync as mkdirSync10, readFileSync as readFileSync7, writeFileSync as writeFileSync4 } from "node:fs";
47302
+ import { existsSync as existsSync15, mkdirSync as mkdirSync10, readFileSync as readFileSync7, writeFileSync as writeFileSync4 } from "node:fs";
47158
47303
  import { homedir as homedir5 } from "node:os";
47159
47304
  import { join as join26 } from "node:path";
47160
47305
  function cacheDir() {
@@ -47168,7 +47313,7 @@ function cacheFile() {
47168
47313
  function readVersionCache() {
47169
47314
  try {
47170
47315
  const path28 = cacheFile();
47171
- if (!existsSync14(path28))
47316
+ if (!existsSync15(path28))
47172
47317
  return null;
47173
47318
  const raw = readFileSync7(path28, "utf-8");
47174
47319
  const parsed = JSON.parse(raw);
@@ -47267,7 +47412,7 @@ var init_version_check = __esm(() => {
47267
47412
 
47268
47413
  // src/services/diagnose-service.ts
47269
47414
  import * as child_process4 from "node:child_process";
47270
- import { existsSync as existsSync15, readdirSync as readdirSync4, readFileSync as readFileSync8, statSync as statSync7 } from "node:fs";
47415
+ import { existsSync as existsSync16, readdirSync as readdirSync4, readFileSync as readFileSync8, statSync as statSync7 } from "node:fs";
47271
47416
  import path28 from "node:path";
47272
47417
  import { fileURLToPath } from "node:url";
47273
47418
  function validateTaskDag(plan) {
@@ -47501,7 +47646,7 @@ async function checkConfigBackups(directory) {
47501
47646
  }
47502
47647
  async function checkGitRepository(directory) {
47503
47648
  try {
47504
- if (!existsSync15(directory) || !statSync7(directory).isDirectory()) {
47649
+ if (!existsSync16(directory) || !statSync7(directory).isDirectory()) {
47505
47650
  return {
47506
47651
  name: "Git Repository",
47507
47652
  status: "❌",
@@ -47566,7 +47711,7 @@ async function checkSpecStaleness(directory, plan) {
47566
47711
  }
47567
47712
  async function checkConfigParseability(directory) {
47568
47713
  const configPath = path28.join(directory, ".opencode/opencode-swarm.json");
47569
- if (!existsSync15(configPath)) {
47714
+ if (!existsSync16(configPath)) {
47570
47715
  return {
47571
47716
  name: "Config Parseability",
47572
47717
  status: "✅",
@@ -47621,11 +47766,11 @@ async function checkGrammarWasmFiles() {
47621
47766
  const thisDir = path28.dirname(fileURLToPath(import.meta.url));
47622
47767
  const grammarDir = resolveGrammarDir(thisDir);
47623
47768
  const missing = [];
47624
- if (!existsSync15(path28.join(grammarDir, "tree-sitter.wasm"))) {
47769
+ if (!existsSync16(path28.join(grammarDir, "tree-sitter.wasm"))) {
47625
47770
  missing.push("tree-sitter.wasm (core runtime)");
47626
47771
  }
47627
47772
  for (const file3 of grammarFiles) {
47628
- if (!existsSync15(path28.join(grammarDir, file3))) {
47773
+ if (!existsSync16(path28.join(grammarDir, file3))) {
47629
47774
  missing.push(file3);
47630
47775
  }
47631
47776
  }
@@ -47644,7 +47789,7 @@ async function checkGrammarWasmFiles() {
47644
47789
  }
47645
47790
  async function checkCheckpointManifest(directory) {
47646
47791
  const manifestPath = path28.join(directory, ".swarm/checkpoints.json");
47647
- if (!existsSync15(manifestPath)) {
47792
+ if (!existsSync16(manifestPath)) {
47648
47793
  return {
47649
47794
  name: "Checkpoint Manifest",
47650
47795
  status: "✅",
@@ -47696,7 +47841,7 @@ async function checkCheckpointManifest(directory) {
47696
47841
  }
47697
47842
  async function checkEventStreamIntegrity(directory) {
47698
47843
  const eventsPath = path28.join(directory, ".swarm/events.jsonl");
47699
- if (!existsSync15(eventsPath)) {
47844
+ if (!existsSync16(eventsPath)) {
47700
47845
  return {
47701
47846
  name: "Event Stream",
47702
47847
  status: "✅",
@@ -47737,7 +47882,7 @@ async function checkEventStreamIntegrity(directory) {
47737
47882
  }
47738
47883
  async function checkSteeringDirectives(directory) {
47739
47884
  const eventsPath = path28.join(directory, ".swarm/events.jsonl");
47740
- if (!existsSync15(eventsPath)) {
47885
+ if (!existsSync16(eventsPath)) {
47741
47886
  return {
47742
47887
  name: "Steering Directives",
47743
47888
  status: "✅",
@@ -47793,7 +47938,7 @@ async function checkCurator(directory) {
47793
47938
  };
47794
47939
  }
47795
47940
  const summaryPath = path28.join(directory, ".swarm/curator-summary.json");
47796
- if (!existsSync15(summaryPath)) {
47941
+ if (!existsSync16(summaryPath)) {
47797
47942
  return {
47798
47943
  name: "Curator",
47799
47944
  status: "✅",
@@ -47959,7 +48104,7 @@ async function getDiagnoseData(directory) {
47959
48104
  checks5.push(await checkCurator(directory));
47960
48105
  try {
47961
48106
  const evidenceDir = path28.join(directory, ".swarm", "evidence");
47962
- const snapshotFiles = existsSync15(evidenceDir) ? readdirSync4(evidenceDir).filter((f) => f.startsWith("agent-tools-") && f.endsWith(".json")) : [];
48107
+ const snapshotFiles = existsSync16(evidenceDir) ? readdirSync4(evidenceDir).filter((f) => f.startsWith("agent-tools-") && f.endsWith(".json")) : [];
47963
48108
  if (snapshotFiles.length > 0) {
47964
48109
  const latest = snapshotFiles.sort().pop();
47965
48110
  checks5.push({
@@ -47992,7 +48137,7 @@ async function getDiagnoseData(directory) {
47992
48137
  const cacheRows = [];
47993
48138
  for (const cachePath of cachePaths) {
47994
48139
  try {
47995
- if (!existsSync15(cachePath)) {
48140
+ if (!existsSync16(cachePath)) {
47996
48141
  cacheRows.push(`⬜ ${cachePath} — absent`);
47997
48142
  continue;
47998
48143
  }
@@ -52310,7 +52455,7 @@ var init_issue = __esm(() => {
52310
52455
 
52311
52456
  // src/hooks/knowledge-migrator.ts
52312
52457
  import { randomUUID as randomUUID3 } from "node:crypto";
52313
- import { existsSync as existsSync20, readFileSync as readFileSync13 } from "node:fs";
52458
+ import { existsSync as existsSync21, readFileSync as readFileSync13 } from "node:fs";
52314
52459
  import { mkdir as mkdir9, readFile as readFile10, writeFile as writeFile9 } from "node:fs/promises";
52315
52460
  import * as path34 from "node:path";
52316
52461
  async function migrateKnowledgeToExternal(_directory, _config) {
@@ -52326,7 +52471,7 @@ async function migrateContextToKnowledge(directory, config3) {
52326
52471
  const sentinelPath = path34.join(directory, ".swarm", ".knowledge-migrated");
52327
52472
  const contextPath = path34.join(directory, ".swarm", "context.md");
52328
52473
  const knowledgePath = resolveSwarmKnowledgePath(directory);
52329
- if (existsSync20(sentinelPath)) {
52474
+ if (existsSync21(sentinelPath)) {
52330
52475
  return {
52331
52476
  migrated: false,
52332
52477
  entriesMigrated: 0,
@@ -52335,7 +52480,7 @@ async function migrateContextToKnowledge(directory, config3) {
52335
52480
  skippedReason: "sentinel-exists"
52336
52481
  };
52337
52482
  }
52338
- if (!existsSync20(contextPath)) {
52483
+ if (!existsSync21(contextPath)) {
52339
52484
  return {
52340
52485
  migrated: false,
52341
52486
  entriesMigrated: 0,
@@ -52521,7 +52666,7 @@ function truncateLesson(text) {
52521
52666
  }
52522
52667
  function inferProjectName(directory) {
52523
52668
  const packageJsonPath = path34.join(directory, "package.json");
52524
- if (existsSync20(packageJsonPath)) {
52669
+ if (existsSync21(packageJsonPath)) {
52525
52670
  try {
52526
52671
  const pkg = JSON.parse(readFileSync13(packageJsonPath, "utf-8"));
52527
52672
  if (pkg.name && typeof pkg.name === "string") {
@@ -57145,7 +57290,7 @@ function analyzeFailures(workingDir) {
57145
57290
  } catch {}
57146
57291
  return report;
57147
57292
  }
57148
- var MAX_OUTPUT_BYTES3 = 512000, MAX_COMMAND_LENGTH2 = 500, DEFAULT_TIMEOUT_MS = 60000, MAX_TIMEOUT_MS = 300000, MAX_SAFE_TEST_FILES = 50, POWERSHELL_METACHARACTERS, DISPATCH_FRAMEWORK_MAP, COMPOUND_TEST_EXTENSIONS, TEST_DIRECTORY_NAMES, SOURCE_EXTENSIONS, SKIP_DIRECTORIES, test_runner;
57293
+ var MAX_OUTPUT_BYTES3 = 512000, MAX_COMMAND_LENGTH2 = 500, DEFAULT_TIMEOUT_MS = 60000, MAX_TIMEOUT_MS = 300000, MAX_SAFE_TEST_FILES = 50, MAX_SAFE_SOURCE_FILES = 1, POWERSHELL_METACHARACTERS, DISPATCH_FRAMEWORK_MAP, COMPOUND_TEST_EXTENSIONS, TEST_DIRECTORY_NAMES, SOURCE_EXTENSIONS, SKIP_DIRECTORIES, test_runner;
57149
57294
  var init_test_runner = __esm(() => {
57150
57295
  init_zod();
57151
57296
  init_discovery();
@@ -57332,8 +57477,8 @@ var init_test_runner = __esm(() => {
57332
57477
  success: false,
57333
57478
  framework: "none",
57334
57479
  scope: "all",
57335
- error: 'scope "all" is not allowed without explicit files. Use scope "convention" or "graph" with a files array to run targeted tests.',
57336
- message: 'Running the full test suite without file targeting is blocked. Provide scope "convention" or "graph" with specific source files in the files array. Example: { scope: "convention", files: ["src/tools/test-runner.ts"] }',
57480
+ error: 'scope "all" is blocked for agent use. Use scope "convention" with specific test files, or scope "graph" with exactly one source file.',
57481
+ message: 'The full test suite is blocked in agent context. Use scope "convention" with specific test files, or scope "graph" with exactly one source file. Example: { scope: "convention", files: ["src/tools/test-runner.ts"] }',
57337
57482
  outcome: "error"
57338
57483
  };
57339
57484
  return JSON.stringify(errorResult, null, 2);
@@ -57414,6 +57559,17 @@ var init_test_runner = __esm(() => {
57414
57559
  };
57415
57560
  return JSON.stringify(errorResult, null, 2);
57416
57561
  }
57562
+ if (sourceFiles.length > MAX_SAFE_SOURCE_FILES) {
57563
+ const errorResult = {
57564
+ success: false,
57565
+ framework,
57566
+ scope,
57567
+ error: `scope "convention" accepts at most ${MAX_SAFE_SOURCE_FILES} source file for discovery (got ${sourceFiles.length}). Treat this as SKIP without retry.`,
57568
+ message: `Too many source files for scope "convention" discovery (${sourceFiles.length} provided, limit is ${MAX_SAFE_SOURCE_FILES}). Call test_runner once per source file, or pass direct test file paths instead of source files.`,
57569
+ outcome: "scope_exceeded"
57570
+ };
57571
+ return JSON.stringify(errorResult, null, 2);
57572
+ }
57417
57573
  testFiles = [
57418
57574
  ...directTestFiles,
57419
57575
  ...getTestFilesFromConvention(sourceFiles, workingDir)
@@ -57437,6 +57593,17 @@ var init_test_runner = __esm(() => {
57437
57593
  };
57438
57594
  return JSON.stringify(errorResult, null, 2);
57439
57595
  }
57596
+ if (sourceFiles.length > MAX_SAFE_SOURCE_FILES) {
57597
+ const errorResult = {
57598
+ success: false,
57599
+ framework,
57600
+ scope,
57601
+ error: `scope "graph" accepts at most ${MAX_SAFE_SOURCE_FILES} source file (got ${sourceFiles.length}). Treat this as SKIP without retry.`,
57602
+ message: `Too many source files for scope "graph" (${sourceFiles.length} provided, limit is ${MAX_SAFE_SOURCE_FILES}). Call test_runner once per source file, or use scope "convention" with direct test file paths.`,
57603
+ outcome: "scope_exceeded"
57604
+ };
57605
+ return JSON.stringify(errorResult, null, 2);
57606
+ }
57440
57607
  const graphTestFiles = await getTestFilesFromGraph(sourceFiles, workingDir);
57441
57608
  if (graphTestFiles.length > 0) {
57442
57609
  testFiles = graphTestFiles;
@@ -57464,6 +57631,17 @@ var init_test_runner = __esm(() => {
57464
57631
  };
57465
57632
  return JSON.stringify(errorResult, null, 2);
57466
57633
  }
57634
+ if (sourceFiles.length > MAX_SAFE_SOURCE_FILES) {
57635
+ const errorResult = {
57636
+ success: false,
57637
+ framework,
57638
+ scope,
57639
+ error: `scope "impact" accepts at most ${MAX_SAFE_SOURCE_FILES} source file (got ${sourceFiles.length}). Treat this as SKIP without retry.`,
57640
+ message: `Too many source files for scope "impact" (${sourceFiles.length} provided, limit is ${MAX_SAFE_SOURCE_FILES}). Call test_runner once per source file, or use scope "convention" with direct test file paths.`,
57641
+ outcome: "scope_exceeded"
57642
+ };
57643
+ return JSON.stringify(errorResult, null, 2);
57644
+ }
57467
57645
  try {
57468
57646
  const impactResult = await analyzeImpact(sourceFiles, workingDir);
57469
57647
  if (impactResult.impactedTests.length > 0) {
@@ -59956,6 +60134,25 @@ var init_context_budget_service = __esm(() => {
59956
60134
  });
59957
60135
 
59958
60136
  // src/services/status-service.ts
60137
+ import * as fsSync3 from "node:fs";
60138
+ import * as path54 from "node:path";
60139
+ function readSpecStalenessSnapshot(directory) {
60140
+ try {
60141
+ const p = path54.join(directory, ".swarm", "spec-staleness.json");
60142
+ if (!fsSync3.existsSync(p))
60143
+ return { stale: false };
60144
+ const raw = fsSync3.readFileSync(p, "utf-8");
60145
+ const parsed = JSON.parse(raw);
60146
+ return {
60147
+ stale: true,
60148
+ reason: typeof parsed?.reason === "string" ? parsed.reason : undefined,
60149
+ storedHash: typeof parsed?.specHash_plan === "string" ? parsed.specHash_plan : undefined,
60150
+ currentHash: typeof parsed?.specHash_current === "string" || parsed?.specHash_current === null ? parsed.specHash_current : undefined
60151
+ };
60152
+ } catch {
60153
+ return { stale: false };
60154
+ }
60155
+ }
59959
60156
  async function getStatusData(directory, agents) {
59960
60157
  const plan = await loadPlan(directory);
59961
60158
  let status;
@@ -60021,6 +60218,16 @@ async function getStatusData(directory, agents) {
60021
60218
  };
60022
60219
  }
60023
60220
  }
60221
+ const drift = readSpecStalenessSnapshot(directory);
60222
+ if (drift.stale) {
60223
+ status.specStale = true;
60224
+ status.specStaleReason = drift.reason;
60225
+ status.specStaleStoredHash = drift.storedHash;
60226
+ status.specStaleCurrentHash = drift.currentHash;
60227
+ } else if (plan && plan._specStale) {
60228
+ status.specStale = true;
60229
+ status.specStaleReason = plan._specStaleReason;
60230
+ }
60024
60231
  return enrichWithLeanTurbo(status, directory);
60025
60232
  }
60026
60233
  function enrichWithLeanTurbo(status, directory) {
@@ -60087,6 +60294,12 @@ function formatStatusMarkdown(status) {
60087
60294
  `**Tasks**: ${status.completedTasks}/${status.totalTasks} complete`,
60088
60295
  `**Agents**: ${status.agentCount} registered`
60089
60296
  ];
60297
+ if (status.specStale) {
60298
+ const reason = status.specStaleReason ?? "spec.md changed since plan saved";
60299
+ const stored = status.specStaleStoredHash ?? "unknown";
60300
+ const current = status.specStaleCurrentHash ?? "(spec.md missing)";
60301
+ lines.push("", `**Spec drift detected**: ${reason} (stored: ${stored}, current: ${current})`, "Run `/swarm clarify` to update the spec or `/swarm acknowledge-spec-drift` to dismiss.");
60302
+ }
60090
60303
  if (status.turboStrategy && status.turboStrategy !== "off") {
60091
60304
  lines.push("");
60092
60305
  if (status.turboStrategy === "lean") {
@@ -60136,6 +60349,18 @@ function formatStatusMarkdown(status) {
60136
60349
  async function handleStatusCommand(directory, agents) {
60137
60350
  const statusData = await getStatusData(directory, agents);
60138
60351
  if (!statusData.hasPlan) {
60352
+ if (statusData.specStale) {
60353
+ const reason = statusData.specStaleReason ?? "spec.md changed since plan saved";
60354
+ const stored = statusData.specStaleStoredHash ?? "unknown";
60355
+ const current = statusData.specStaleCurrentHash ?? "(spec.md missing)";
60356
+ return [
60357
+ "No active swarm plan found.",
60358
+ "",
60359
+ `**Spec drift detected**: ${reason} (stored: ${stored}, current: ${current})`,
60360
+ "Run `/swarm clarify` to update the spec or `/swarm acknowledge-spec-drift` to dismiss."
60361
+ ].join(`
60362
+ `);
60363
+ }
60139
60364
  return "No active swarm plan found.";
60140
60365
  }
60141
60366
  return formatStatusMarkdown(statusData);
@@ -60439,7 +60664,7 @@ var init_write_retro2 = __esm(() => {
60439
60664
 
60440
60665
  // src/commands/command-dispatch.ts
60441
60666
  import fs36 from "node:fs";
60442
- import path54 from "node:path";
60667
+ import path55 from "node:path";
60443
60668
  function normalizeSwarmCommandInput(command, argumentText) {
60444
60669
  if (command !== "swarm" && !command.startsWith("swarm-")) {
60445
60670
  return { isSwarmCommand: false, tokens: [] };
@@ -60475,9 +60700,9 @@ ${similar.map((cmd) => ` - /swarm ${cmd}`).join(`
60475
60700
  `);
60476
60701
  }
60477
60702
  function maybeMarkFirstRun(directory) {
60478
- const sentinelPath = path54.join(directory, ".swarm", ".first-run-complete");
60703
+ const sentinelPath = path55.join(directory, ".swarm", ".first-run-complete");
60479
60704
  try {
60480
- const swarmDir = path54.join(directory, ".swarm");
60705
+ const swarmDir = path55.join(directory, ".swarm");
60481
60706
  fs36.mkdirSync(swarmDir, { recursive: true });
60482
60707
  fs36.writeFileSync(sentinelPath, `first-run-complete: ${new Date().toISOString()}
60483
60708
  `, { flag: "wx" });
@@ -61145,24 +61370,24 @@ function validateAliases() {
61145
61370
  }
61146
61371
  aliasTargets.get(target).push(name2);
61147
61372
  const visited = new Set;
61148
- const path55 = [];
61373
+ const path56 = [];
61149
61374
  let current = target;
61150
61375
  while (current) {
61151
61376
  const currentEntry = COMMAND_REGISTRY[current];
61152
61377
  if (!currentEntry)
61153
61378
  break;
61154
61379
  if (visited.has(current)) {
61155
- const cycleStart = path55.indexOf(current);
61380
+ const cycleStart = path56.indexOf(current);
61156
61381
  const fullChain = [
61157
61382
  name2,
61158
- ...path55.slice(0, cycleStart > 0 ? cycleStart : path55.length),
61383
+ ...path56.slice(0, cycleStart > 0 ? cycleStart : path56.length),
61159
61384
  current
61160
61385
  ].join(" → ");
61161
61386
  errors5.push(`Circular alias detected: ${fullChain}`);
61162
61387
  break;
61163
61388
  }
61164
61389
  visited.add(current);
61165
- path55.push(current);
61390
+ path56.push(current);
61166
61391
  current = currentEntry.aliasOf || "";
61167
61392
  }
61168
61393
  }
@@ -63375,6 +63600,18 @@ If resuming a project with an existing approved plan, CRITIC-GATE is already sat
63375
63600
  - Run /swarm clarify to update the spec and align it with the plan, OR
63376
63601
  - Run /swarm acknowledge-spec-drift to acknowledge the drift and suppress further warnings
63377
63602
  - Do NOT proceed with implementation until spec staleness is resolved.
63603
+ - When re-saving a plan in response to spec drift, save_plan REQUIRES that ANY task
63604
+ present in the prior plan but absent from the new args.phases be enumerated
63605
+ in removed_task_ids with a removal_reason. save_plan will reject the call
63606
+ otherwise (PLAN_TASK_REMOVAL_NOT_ACKNOWLEDGED). Tasks not yet finished
63607
+ (status: pending, in_progress, blocked) MUST NOT be removed without explicit
63608
+ user confirmation — surface the list to the user and ask before populating
63609
+ removed_task_ids.
63610
+ - While .swarm/spec-staleness.json exists, the runtime STRUCTURALLY BLOCKS the
63611
+ following tools (SPEC_DRIFT_BLOCKED_TOOLS): save_plan, update_task_status,
63612
+ phase_complete, lean_turbo_run_phase, lean_turbo_acquire_locks. If a call
63613
+ returns SPEC_DRIFT_BLOCK, do NOT retry; instead present the drift to the
63614
+ user and run /swarm clarify or /swarm acknowledge-spec-drift first.
63378
63615
 
63379
63616
  ### MODE: EXECUTE
63380
63617
  For each task (respecting dependencies):
@@ -65785,7 +66022,7 @@ COVERAGE REPORTING:
65785
66022
 
65786
66023
  // src/agents/index.ts
65787
66024
  import { mkdir as mkdir10, writeFile as writeFile10 } from "node:fs/promises";
65788
- import * as path55 from "node:path";
66025
+ import * as path56 from "node:path";
65789
66026
  function stripSwarmPrefix(agentName, swarmPrefix) {
65790
66027
  if (!swarmPrefix || !agentName)
65791
66028
  return agentName;
@@ -66181,14 +66418,14 @@ function getAgentConfigs(config3, directory, sessionId, projectContext) {
66181
66418
  }));
66182
66419
  if (directory) {
66183
66420
  const sid = sessionId ?? `init-${Date.now()}`;
66184
- const evidenceDir = path55.join(directory, ".swarm", "evidence");
66421
+ const evidenceDir = path56.join(directory, ".swarm", "evidence");
66185
66422
  const filename = `agent-tools-${sid}.json`;
66186
66423
  const snapshotData = JSON.stringify({
66187
66424
  sessionId: sid,
66188
66425
  generatedAt: new Date().toISOString(),
66189
66426
  agents: agentToolSnapshot
66190
66427
  }, null, 2);
66191
- mkdir10(evidenceDir, { recursive: true }).then(() => writeFile10(path55.join(evidenceDir, filename), snapshotData)).catch(() => {});
66428
+ mkdir10(evidenceDir, { recursive: true }).then(() => writeFile10(path56.join(evidenceDir, filename), snapshotData)).catch(() => {});
66192
66429
  }
66193
66430
  return result;
66194
66431
  }
@@ -66225,14 +66462,14 @@ __export(exports_evidence_summary_integration, {
66225
66462
  createEvidenceSummaryIntegration: () => createEvidenceSummaryIntegration,
66226
66463
  EvidenceSummaryIntegration: () => EvidenceSummaryIntegration
66227
66464
  });
66228
- import { existsSync as existsSync30, mkdirSync as mkdirSync16, writeFileSync as writeFileSync8 } from "node:fs";
66229
- import * as path56 from "node:path";
66465
+ import { existsSync as existsSync32, mkdirSync as mkdirSync16, writeFileSync as writeFileSync8 } from "node:fs";
66466
+ import * as path57 from "node:path";
66230
66467
  function persistSummary(projectDir, artifact, filename) {
66231
- const swarmPath = path56.join(projectDir, ".swarm");
66232
- if (!existsSync30(swarmPath)) {
66468
+ const swarmPath = path57.join(projectDir, ".swarm");
66469
+ if (!existsSync32(swarmPath)) {
66233
66470
  mkdirSync16(swarmPath, { recursive: true });
66234
66471
  }
66235
- const artifactPath = path56.join(swarmPath, filename);
66472
+ const artifactPath = path57.join(swarmPath, filename);
66236
66473
  const content = JSON.stringify(artifact, null, 2);
66237
66474
  writeFileSync8(artifactPath, content, "utf-8");
66238
66475
  log("[EvidenceSummaryIntegration] Summary persisted", {
@@ -66351,7 +66588,7 @@ __export(exports_status_artifact, {
66351
66588
  AutomationStatusArtifact: () => AutomationStatusArtifact
66352
66589
  });
66353
66590
  import * as fs38 from "node:fs";
66354
- import * as path58 from "node:path";
66591
+ import * as path59 from "node:path";
66355
66592
  function createEmptySnapshot(mode, capabilities) {
66356
66593
  return {
66357
66594
  timestamp: Date.now(),
@@ -66410,7 +66647,7 @@ class AutomationStatusArtifact {
66410
66647
  });
66411
66648
  }
66412
66649
  getFilePath() {
66413
- return path58.join(this.swarmDir, this.filename);
66650
+ return path59.join(this.swarmDir, this.filename);
66414
66651
  }
66415
66652
  load() {
66416
66653
  const filePath = this.getFilePath();
@@ -66823,12 +67060,12 @@ __export(exports_review_receipt, {
66823
67060
  });
66824
67061
  import * as crypto5 from "node:crypto";
66825
67062
  import * as fs44 from "node:fs";
66826
- import * as path61 from "node:path";
67063
+ import * as path62 from "node:path";
66827
67064
  function resolveReceiptsDir(directory) {
66828
- return path61.join(directory, ".swarm", "review-receipts");
67065
+ return path62.join(directory, ".swarm", "review-receipts");
66829
67066
  }
66830
67067
  function resolveReceiptIndexPath(directory) {
66831
- return path61.join(resolveReceiptsDir(directory), "index.json");
67068
+ return path62.join(resolveReceiptsDir(directory), "index.json");
66832
67069
  }
66833
67070
  function buildReceiptFilename(id, date9) {
66834
67071
  const dateStr = date9.toISOString().slice(0, 10);
@@ -66867,7 +67104,7 @@ async function readReceiptIndex(directory) {
66867
67104
  }
66868
67105
  async function writeReceiptIndex(directory, index) {
66869
67106
  const indexPath = resolveReceiptIndexPath(directory);
66870
- const dir = path61.dirname(indexPath);
67107
+ const dir = path62.dirname(indexPath);
66871
67108
  await fs44.promises.mkdir(dir, { recursive: true });
66872
67109
  const tmpPath = `${indexPath}.tmp.${Date.now()}.${Math.random().toString(36).slice(2)}`;
66873
67110
  await fs44.promises.writeFile(tmpPath, JSON.stringify(index, null, 2), "utf-8");
@@ -66878,7 +67115,7 @@ async function persistReviewReceipt(directory, receipt) {
66878
67115
  await fs44.promises.mkdir(receiptsDir, { recursive: true });
66879
67116
  const now = new Date(receipt.reviewed_at);
66880
67117
  const filename = buildReceiptFilename(receipt.id, now);
66881
- const receiptPath = path61.join(receiptsDir, filename);
67118
+ const receiptPath = path62.join(receiptsDir, filename);
66882
67119
  const tmpPath = `${receiptPath}.tmp.${Date.now()}.${Math.random().toString(36).slice(2)}`;
66883
67120
  await fs44.promises.writeFile(tmpPath, JSON.stringify(receipt, null, 2), "utf-8");
66884
67121
  fs44.renameSync(tmpPath, receiptPath);
@@ -66900,7 +67137,7 @@ async function readReceiptById(directory, receiptId) {
66900
67137
  const entry = index.entries.find((e) => e.id === receiptId);
66901
67138
  if (!entry)
66902
67139
  return null;
66903
- const receiptPath = path61.join(resolveReceiptsDir(directory), entry.filename);
67140
+ const receiptPath = path62.join(resolveReceiptsDir(directory), entry.filename);
66904
67141
  try {
66905
67142
  const content = await fs44.promises.readFile(receiptPath, "utf-8");
66906
67143
  return JSON.parse(content);
@@ -66913,7 +67150,7 @@ async function readReceiptsByScopeHash(directory, scopeHash) {
66913
67150
  const matching = index.entries.filter((e) => e.scope_hash === scopeHash).sort((a, b) => b.reviewed_at.localeCompare(a.reviewed_at));
66914
67151
  const receipts = [];
66915
67152
  for (const entry of matching) {
66916
- const receiptPath = path61.join(resolveReceiptsDir(directory), entry.filename);
67153
+ const receiptPath = path62.join(resolveReceiptsDir(directory), entry.filename);
66917
67154
  try {
66918
67155
  const content = await fs44.promises.readFile(receiptPath, "utf-8");
66919
67156
  receipts.push(JSON.parse(content));
@@ -66926,7 +67163,7 @@ async function readAllReceipts(directory) {
66926
67163
  const sorted = [...index.entries].sort((a, b) => b.reviewed_at.localeCompare(a.reviewed_at));
66927
67164
  const receipts = [];
66928
67165
  for (const entry of sorted) {
66929
- const receiptPath = path61.join(resolveReceiptsDir(directory), entry.filename);
67166
+ const receiptPath = path62.join(resolveReceiptsDir(directory), entry.filename);
66930
67167
  try {
66931
67168
  const content = await fs44.promises.readFile(receiptPath, "utf-8");
66932
67169
  receipts.push(JSON.parse(content));
@@ -68514,11 +68751,11 @@ ${JSON.stringify(symbolNames, null, 2)}`);
68514
68751
  throw toThrow;
68515
68752
  }, "quit_");
68516
68753
  var scriptDirectory = "";
68517
- function locateFile(path76) {
68754
+ function locateFile(path77) {
68518
68755
  if (Module["locateFile"]) {
68519
- return Module["locateFile"](path76, scriptDirectory);
68756
+ return Module["locateFile"](path77, scriptDirectory);
68520
68757
  }
68521
- return scriptDirectory + path76;
68758
+ return scriptDirectory + path77;
68522
68759
  }
68523
68760
  __name(locateFile, "locateFile");
68524
68761
  var readAsync, readBinary;
@@ -70268,12 +70505,12 @@ __export(exports_runtime, {
70268
70505
  clearParserCache: () => clearParserCache,
70269
70506
  _internals: () => _internals35
70270
70507
  });
70271
- import * as path76 from "node:path";
70508
+ import * as path77 from "node:path";
70272
70509
  import { fileURLToPath as fileURLToPath2 } from "node:url";
70273
70510
  async function initTreeSitter() {
70274
70511
  if (!treeSitterInitPromise) {
70275
70512
  treeSitterInitPromise = (async () => {
70276
- const thisDir = path76.dirname(fileURLToPath2(import.meta.url));
70513
+ const thisDir = path77.dirname(fileURLToPath2(import.meta.url));
70277
70514
  const isSource = thisDir.replace(/\\/g, "/").endsWith("/src/lang");
70278
70515
  if (isSource) {
70279
70516
  await _internals35.parserInit();
@@ -70281,7 +70518,7 @@ async function initTreeSitter() {
70281
70518
  const grammarsDir = getGrammarsDirAbsolute();
70282
70519
  await _internals35.parserInit({
70283
70520
  locateFile(scriptName) {
70284
- return path76.join(grammarsDir, scriptName);
70521
+ return path77.join(grammarsDir, scriptName);
70285
70522
  }
70286
70523
  });
70287
70524
  }
@@ -70307,11 +70544,11 @@ function getWasmFileName(languageId) {
70307
70544
  return `tree-sitter-${sanitized}.wasm`;
70308
70545
  }
70309
70546
  function getGrammarsDirAbsolute() {
70310
- const thisDir = path76.dirname(fileURLToPath2(import.meta.url));
70547
+ const thisDir = path77.dirname(fileURLToPath2(import.meta.url));
70311
70548
  const normalized = thisDir.replace(/\\/g, "/");
70312
70549
  const isSource = normalized.endsWith("/src/lang");
70313
70550
  const isCliBundle = normalized.endsWith("/cli");
70314
- return isSource ? path76.join(thisDir, "grammars") : isCliBundle ? path76.join(thisDir, "..", "lang", "grammars") : path76.join(thisDir, "lang", "grammars");
70551
+ return isSource ? path77.join(thisDir, "grammars") : isCliBundle ? path77.join(thisDir, "..", "lang", "grammars") : path77.join(thisDir, "lang", "grammars");
70315
70552
  }
70316
70553
  async function loadGrammar(languageId) {
70317
70554
  if (typeof languageId !== "string" || languageId.length > 100) {
@@ -70327,9 +70564,9 @@ async function loadGrammar(languageId) {
70327
70564
  await initTreeSitter();
70328
70565
  const parser = new Parser;
70329
70566
  const wasmFileName = getWasmFileName(normalizedId);
70330
- const wasmPath = path76.join(getGrammarsDirAbsolute(), wasmFileName);
70331
- const { existsSync: existsSync40 } = await import("node:fs");
70332
- if (!existsSync40(wasmPath)) {
70567
+ const wasmPath = path77.join(getGrammarsDirAbsolute(), wasmFileName);
70568
+ const { existsSync: existsSync42 } = await import("node:fs");
70569
+ if (!existsSync42(wasmPath)) {
70333
70570
  throw new Error(`Grammar file not found for ${languageId}: ${wasmPath}
70334
70571
  Make sure to run 'bun run build' to copy grammar files to dist/lang/grammars/`);
70335
70572
  }
@@ -70362,7 +70599,7 @@ async function isGrammarAvailable(languageId) {
70362
70599
  }
70363
70600
  try {
70364
70601
  const wasmFileName = getWasmFileName(normalizedId);
70365
- const wasmPath = path76.join(getGrammarsDirAbsolute(), wasmFileName);
70602
+ const wasmPath = path77.join(getGrammarsDirAbsolute(), wasmFileName);
70366
70603
  const { statSync: statSync20 } = await import("node:fs");
70367
70604
  statSync20(wasmPath);
70368
70605
  return true;
@@ -70431,13 +70668,13 @@ import {
70431
70668
  stat as stat6,
70432
70669
  writeFile as writeFile12
70433
70670
  } from "node:fs/promises";
70434
- import * as path78 from "node:path";
70671
+ import * as path79 from "node:path";
70435
70672
  function normalizeSeparators(filePath) {
70436
70673
  return filePath.replace(/\\/g, "/");
70437
70674
  }
70438
70675
  function matchesDocPattern(filePath, patterns) {
70439
70676
  const normalizedPath = normalizeSeparators(filePath);
70440
- const basename10 = path78.basename(filePath);
70677
+ const basename10 = path79.basename(filePath);
70441
70678
  for (const pattern of patterns) {
70442
70679
  if (!pattern.includes("/") && !pattern.includes("\\")) {
70443
70680
  if (basename10 === pattern) {
@@ -70493,7 +70730,7 @@ function stripMarkdown(text) {
70493
70730
  return text.replace(/\[([^\]]+)\]\([^)]+\)/g, "$1").replace(/\*\*([^*]+)\*\*/g, "$1").replace(/`([^`]+)`/g, "$1").replace(/^\s*[-*•]\s+/gm, "").replace(/^\s*\d+\.\s+/gm, "").trim();
70494
70731
  }
70495
70732
  async function scanDocIndex(directory) {
70496
- const manifestPath = path78.join(directory, ".swarm", "doc-manifest.json");
70733
+ const manifestPath = path79.join(directory, ".swarm", "doc-manifest.json");
70497
70734
  const defaultPatterns = DocsConfigSchema.parse({}).doc_patterns;
70498
70735
  const extraPatterns = [
70499
70736
  "ARCHITECTURE.md",
@@ -70510,7 +70747,7 @@ async function scanDocIndex(directory) {
70510
70747
  let cacheValid = true;
70511
70748
  for (const file3 of existingManifest.files) {
70512
70749
  try {
70513
- const fullPath = path78.join(directory, file3.path);
70750
+ const fullPath = path79.join(directory, file3.path);
70514
70751
  const stat7 = fs53.statSync(fullPath);
70515
70752
  if (stat7.mtimeMs > file3.mtime) {
70516
70753
  cacheValid = false;
@@ -70545,10 +70782,10 @@ async function scanDocIndex(directory) {
70545
70782
  let isFile = entry.isFile();
70546
70783
  if (entry.isSymbolicLink()) {
70547
70784
  try {
70548
- const symlinkPath = path78.join(dir, entry.name);
70785
+ const symlinkPath = path79.join(dir, entry.name);
70549
70786
  const resolved = await realpath2(symlinkPath);
70550
- const rel = path78.relative(resolvedDirectory, resolved);
70551
- if (rel.startsWith("..") || path78.isAbsolute(rel))
70787
+ const rel = path79.relative(resolvedDirectory, resolved);
70788
+ if (rel.startsWith("..") || path79.isAbsolute(rel))
70552
70789
  continue;
70553
70790
  const targetStat = await stat6(symlinkPath);
70554
70791
  isFile = targetStat.isFile();
@@ -70558,14 +70795,14 @@ async function scanDocIndex(directory) {
70558
70795
  }
70559
70796
  if (isDir) {
70560
70797
  if (!SKIP_DIRECTORIES3.has(entry.name)) {
70561
- await walkDir(path78.join(dir, entry.name));
70798
+ await walkDir(path79.join(dir, entry.name));
70562
70799
  }
70563
70800
  continue;
70564
70801
  }
70565
70802
  if (!isFile)
70566
70803
  continue;
70567
- const fullPath = path78.join(dir, entry.name);
70568
- const relPath = normalizeSeparators(path78.relative(directory, fullPath));
70804
+ const fullPath = path79.join(dir, entry.name);
70805
+ const relPath = normalizeSeparators(path79.relative(directory, fullPath));
70569
70806
  let skipThisFile = false;
70570
70807
  for (const pattern of SKIP_PATTERNS) {
70571
70808
  if (pattern.test(relPath)) {
@@ -70589,7 +70826,7 @@ async function scanDocIndex(directory) {
70589
70826
  } catch {
70590
70827
  continue;
70591
70828
  }
70592
- const { title, summary } = extractTitleAndSummary(content, path78.basename(relPath));
70829
+ const { title, summary } = extractTitleAndSummary(content, path79.basename(relPath));
70593
70830
  discoveredFiles.push({
70594
70831
  path: relPath,
70595
70832
  title,
@@ -70626,7 +70863,7 @@ async function scanDocIndex(directory) {
70626
70863
  files: discoveredFiles
70627
70864
  };
70628
70865
  try {
70629
- await mkdir13(path78.dirname(manifestPath), { recursive: true });
70866
+ await mkdir13(path79.dirname(manifestPath), { recursive: true });
70630
70867
  await writeFile12(manifestPath, JSON.stringify(manifest, null, 2), "utf-8");
70631
70868
  } catch {}
70632
70869
  return { manifest, cached: false };
@@ -70665,7 +70902,7 @@ function extractConstraintsFromContent(content) {
70665
70902
  return constraints;
70666
70903
  }
70667
70904
  async function extractDocConstraints(directory, taskFiles, taskDescription) {
70668
- const manifestPath = path78.join(directory, ".swarm", "doc-manifest.json");
70905
+ const manifestPath = path79.join(directory, ".swarm", "doc-manifest.json");
70669
70906
  let manifest;
70670
70907
  try {
70671
70908
  const content = await readFile12(manifestPath, "utf-8");
@@ -70691,7 +70928,7 @@ async function extractDocConstraints(directory, taskFiles, taskDescription) {
70691
70928
  }
70692
70929
  let fullContent;
70693
70930
  try {
70694
- fullContent = await readFile12(path78.join(directory, docFile.path), "utf-8");
70931
+ fullContent = await readFile12(path79.join(directory, docFile.path), "utf-8");
70695
70932
  } catch {
70696
70933
  skippedCount++;
70697
70934
  continue;
@@ -70714,7 +70951,7 @@ async function extractDocConstraints(directory, taskFiles, taskDescription) {
70714
70951
  tier: "swarm",
70715
70952
  lesson: constraint,
70716
70953
  category: "architecture",
70717
- tags: ["doc-scan", path78.basename(docFile.path)],
70954
+ tags: ["doc-scan", path79.basename(docFile.path)],
70718
70955
  scope: "global",
70719
70956
  confidence: 0.5,
70720
70957
  status: "candidate",
@@ -70793,7 +71030,7 @@ var init_doc_scan = __esm(() => {
70793
71030
  }
70794
71031
  } catch {}
70795
71032
  if (force) {
70796
- const manifestPath = path78.join(directory, ".swarm", "doc-manifest.json");
71033
+ const manifestPath = path79.join(directory, ".swarm", "doc-manifest.json");
70797
71034
  try {
70798
71035
  fs53.unlinkSync(manifestPath);
70799
71036
  } catch {}
@@ -70989,9 +71226,9 @@ __export(exports_curator_drift, {
70989
71226
  _internals: () => _internals38
70990
71227
  });
70991
71228
  import * as fs60 from "node:fs";
70992
- import * as path84 from "node:path";
71229
+ import * as path85 from "node:path";
70993
71230
  async function readPriorDriftReports(directory) {
70994
- const swarmDir = path84.join(directory, ".swarm");
71231
+ const swarmDir = path85.join(directory, ".swarm");
70995
71232
  const entries = await fs60.promises.readdir(swarmDir).catch(() => null);
70996
71233
  if (entries === null)
70997
71234
  return [];
@@ -71018,7 +71255,7 @@ async function readPriorDriftReports(directory) {
71018
71255
  async function writeDriftReport(directory, report) {
71019
71256
  const filename = `${DRIFT_REPORT_PREFIX}${report.phase}.json`;
71020
71257
  const filePath = validateSwarmPath(directory, filename);
71021
- const swarmDir = path84.dirname(filePath);
71258
+ const swarmDir = path85.dirname(filePath);
71022
71259
  await fs60.promises.mkdir(swarmDir, { recursive: true });
71023
71260
  try {
71024
71261
  await fs60.promises.writeFile(filePath, JSON.stringify(report, null, 2), "utf-8");
@@ -71164,7 +71401,7 @@ __export(exports_project_context, {
71164
71401
  LANG_BACKEND_DETECTION_TIMEOUT_MS: () => LANG_BACKEND_DETECTION_TIMEOUT_MS
71165
71402
  });
71166
71403
  import * as fs110 from "node:fs";
71167
- import * as path138 from "node:path";
71404
+ import * as path139 from "node:path";
71168
71405
  function detectFileExists2(directory, pattern) {
71169
71406
  if (pattern.includes("*") || pattern.includes("?")) {
71170
71407
  try {
@@ -71176,7 +71413,7 @@ function detectFileExists2(directory, pattern) {
71176
71413
  }
71177
71414
  }
71178
71415
  try {
71179
- fs110.accessSync(path138.join(directory, pattern));
71416
+ fs110.accessSync(path139.join(directory, pattern));
71180
71417
  return true;
71181
71418
  } catch {
71182
71419
  return false;
@@ -71185,7 +71422,7 @@ function detectFileExists2(directory, pattern) {
71185
71422
  function selectTestCommandFromScriptsTest(backend, directory) {
71186
71423
  let pkgRaw;
71187
71424
  try {
71188
- pkgRaw = fs110.readFileSync(path138.join(directory, "package.json"), "utf-8");
71425
+ pkgRaw = fs110.readFileSync(path139.join(directory, "package.json"), "utf-8");
71189
71426
  } catch {
71190
71427
  return null;
71191
71428
  }
@@ -71294,7 +71531,7 @@ var init_project_context = __esm(() => {
71294
71531
  init_package();
71295
71532
  init_agents2();
71296
71533
  init_critic();
71297
- import * as path139 from "node:path";
71534
+ import * as path140 from "node:path";
71298
71535
 
71299
71536
  // src/background/index.ts
71300
71537
  init_event_bus();
@@ -71305,7 +71542,7 @@ init_manager3();
71305
71542
  init_manager();
71306
71543
  init_utils();
71307
71544
  import * as fs37 from "node:fs";
71308
- import * as path57 from "node:path";
71545
+ import * as path58 from "node:path";
71309
71546
 
71310
71547
  class PlanSyncWorker {
71311
71548
  directory;
@@ -71329,10 +71566,10 @@ class PlanSyncWorker {
71329
71566
  this.onSyncComplete = options.onSyncComplete;
71330
71567
  }
71331
71568
  getSwarmDir() {
71332
- return path57.resolve(this.directory, ".swarm");
71569
+ return path58.resolve(this.directory, ".swarm");
71333
71570
  }
71334
71571
  getPlanJsonPath() {
71335
- return path57.join(this.getSwarmDir(), "plan.json");
71572
+ return path58.join(this.getSwarmDir(), "plan.json");
71336
71573
  }
71337
71574
  start() {
71338
71575
  if (this.disposed) {
@@ -71551,8 +71788,8 @@ class PlanSyncWorker {
71551
71788
  checkForUnauthorizedWrite() {
71552
71789
  try {
71553
71790
  const swarmDir = this.getSwarmDir();
71554
- const planJsonPath = path57.join(swarmDir, "plan.json");
71555
- const markerPath = path57.join(swarmDir, ".plan-write-marker");
71791
+ const planJsonPath = path58.join(swarmDir, "plan.json");
71792
+ const markerPath = path58.join(swarmDir, ".plan-write-marker");
71556
71793
  const planStats = fs37.statSync(planJsonPath);
71557
71794
  const planMtimeMs = Math.floor(planStats.mtimeMs);
71558
71795
  const markerContent = fs37.readFileSync(markerPath, "utf8");
@@ -71593,13 +71830,13 @@ init_constants();
71593
71830
  // src/config/project-init.ts
71594
71831
  init_constants();
71595
71832
  import * as fs39 from "node:fs";
71596
- import * as path59 from "node:path";
71833
+ import * as path60 from "node:path";
71597
71834
  var STARTER_CONTENT = `{}
71598
71835
  `;
71599
71836
  function writeProjectConfigIfNew(directory, quiet = false) {
71600
71837
  try {
71601
- const opencodeDir = path59.join(directory, ".opencode");
71602
- const dest = path59.join(opencodeDir, "opencode-swarm.json");
71838
+ const opencodeDir = path60.join(directory, ".opencode");
71839
+ const dest = path60.join(opencodeDir, "opencode-swarm.json");
71603
71840
  try {
71604
71841
  const stat4 = fs39.lstatSync(opencodeDir);
71605
71842
  if (stat4.isSymbolicLink())
@@ -71624,8 +71861,8 @@ function writeProjectConfigIfNew(directory, quiet = false) {
71624
71861
  }
71625
71862
  function writeSwarmConfigExampleIfNew(projectDirectory) {
71626
71863
  try {
71627
- const swarmDir = path59.join(projectDirectory, ".swarm");
71628
- const dest = path59.join(swarmDir, "config.example.json");
71864
+ const swarmDir = path60.join(projectDirectory, ".swarm");
71865
+ const dest = path60.join(swarmDir, "config.example.json");
71629
71866
  if (fs39.existsSync(dest))
71630
71867
  return;
71631
71868
  if (!fs39.existsSync(swarmDir)) {
@@ -71662,7 +71899,7 @@ init_state();
71662
71899
  init_logger();
71663
71900
  init_state2();
71664
71901
  import * as fs40 from "node:fs";
71665
- import * as path60 from "node:path";
71902
+ import * as path61 from "node:path";
71666
71903
  var oversightSequenceCounter = 0;
71667
71904
  var VALID_VERDICTS = [
71668
71905
  "APPROVED",
@@ -71836,10 +72073,10 @@ async function writeFullAutoOversightEvidence(directory, phase, event) {
71836
72073
  if (phase === undefined)
71837
72074
  return;
71838
72075
  try {
71839
- const evidenceDir = validateSwarmPath(directory, path60.posix.join("evidence", String(phase)));
72076
+ const evidenceDir = validateSwarmPath(directory, path61.posix.join("evidence", String(phase)));
71840
72077
  fs40.mkdirSync(evidenceDir, { recursive: true });
71841
72078
  const fileName = `full-auto-${event.oversight_sequence}.json`;
71842
- const filePath = validateSwarmPath(directory, path60.posix.join("evidence", String(phase), fileName));
72079
+ const filePath = validateSwarmPath(directory, path61.posix.join("evidence", String(phase), fileName));
71843
72080
  fs40.writeFileSync(filePath, `${JSON.stringify(event, null, 2)}
71844
72081
  `, "utf-8");
71845
72082
  return filePath;
@@ -72248,11 +72485,11 @@ async function doFlush(directory) {
72248
72485
  const activitySection = renderActivitySection();
72249
72486
  const updated = replaceOrAppendSection(existing, "## Agent Activity", activitySection);
72250
72487
  const flushedCount = swarmState.pendingEvents;
72251
- const path61 = nodePath2.join(directory, ".swarm", "context.md");
72252
- const tempPath = `${path61}.tmp`;
72488
+ const path62 = nodePath2.join(directory, ".swarm", "context.md");
72489
+ const tempPath = `${path62}.tmp`;
72253
72490
  try {
72254
72491
  await bunWrite(tempPath, updated);
72255
- renameSync13(tempPath, path61);
72492
+ renameSync13(tempPath, path62);
72256
72493
  } catch (writeError) {
72257
72494
  try {
72258
72495
  unlinkSync10(tempPath);
@@ -72495,7 +72732,7 @@ init_state();
72495
72732
  init_extractors();
72496
72733
  init_utils2();
72497
72734
  import * as fs41 from "node:fs";
72498
- import { join as join54 } from "node:path";
72735
+ import { join as join55 } from "node:path";
72499
72736
  function createCompactionCustomizerHook(config3, directory) {
72500
72737
  const enabled = config3.hooks?.compaction !== false;
72501
72738
  if (!enabled) {
@@ -72540,7 +72777,7 @@ function createCompactionCustomizerHook(config3, directory) {
72540
72777
  }
72541
72778
  }
72542
72779
  try {
72543
- const summariesDir = join54(directory, ".swarm", "summaries");
72780
+ const summariesDir = join55(directory, ".swarm", "summaries");
72544
72781
  const files = await fs41.promises.readdir(summariesDir);
72545
72782
  if (files.length > 0) {
72546
72783
  const count = files.length;
@@ -73920,7 +74157,7 @@ init_schema();
73920
74157
  init_manager();
73921
74158
  init_curator();
73922
74159
  init_utils2();
73923
- import * as path62 from "node:path";
74160
+ import * as path63 from "node:path";
73924
74161
  function createPhaseMonitorHook(directory, preflightManager, curatorRunner, delegateFactory) {
73925
74162
  let lastKnownPhase = null;
73926
74163
  const handler = async (input, _output) => {
@@ -73940,9 +74177,9 @@ function createPhaseMonitorHook(directory, preflightManager, curatorRunner, dele
73940
74177
  const llmDelegate = delegateFactory?.(sessionId);
73941
74178
  const initResult = await runner(directory, curatorConfig, llmDelegate);
73942
74179
  if (initResult.briefing) {
73943
- const briefingPath = path62.join(directory, ".swarm", "curator-briefing.md");
74180
+ const briefingPath = path63.join(directory, ".swarm", "curator-briefing.md");
73944
74181
  const { mkdir: mkdir11, writeFile: writeFile11 } = await import("node:fs/promises");
73945
- await mkdir11(path62.dirname(briefingPath), { recursive: true });
74182
+ await mkdir11(path63.dirname(briefingPath), { recursive: true });
73946
74183
  await writeFile11(briefingPath, initResult.briefing, "utf-8");
73947
74184
  const { buildApprovedReceipt: buildApprovedReceipt2, persistReviewReceipt: persistReviewReceipt2 } = await Promise.resolve().then(() => (init_review_receipt(), exports_review_receipt));
73948
74185
  const initReceipt = buildApprovedReceipt2({
@@ -74069,16 +74306,16 @@ ${originalText}`;
74069
74306
  // src/hooks/repo-graph-builder.ts
74070
74307
  init_constants();
74071
74308
  import { realpathSync as realpathSync8 } from "node:fs";
74072
- import * as path69 from "node:path";
74309
+ import * as path70 from "node:path";
74073
74310
 
74074
74311
  // src/tools/repo-graph/builder.ts
74075
74312
  init_logger();
74076
74313
  init_path_security();
74077
- import * as fsSync3 from "node:fs";
74078
- import { existsSync as existsSync36, realpathSync as realpathSync6 } from "node:fs";
74314
+ import * as fsSync4 from "node:fs";
74315
+ import { existsSync as existsSync38, realpathSync as realpathSync6 } from "node:fs";
74079
74316
  import * as fsPromises5 from "node:fs/promises";
74080
74317
  import * as os7 from "node:os";
74081
- import * as path65 from "node:path";
74318
+ import * as path66 from "node:path";
74082
74319
 
74083
74320
  // src/utils/timeout.ts
74084
74321
  async function withTimeout(promise3, ms, timeoutError) {
@@ -74110,7 +74347,7 @@ init_zod();
74110
74347
  init_create_tool();
74111
74348
  init_path_security();
74112
74349
  import * as fs45 from "node:fs";
74113
- import * as path63 from "node:path";
74350
+ import * as path64 from "node:path";
74114
74351
  var MAX_FILE_SIZE_BYTES2 = 1024 * 1024;
74115
74352
  var WINDOWS_RESERVED_NAMES = /^(con|prn|aux|nul|com[1-9]|lpt[1-9])(\.|:|$)/i;
74116
74353
  function containsWindowsAttacks(str) {
@@ -74127,11 +74364,11 @@ function containsWindowsAttacks(str) {
74127
74364
  }
74128
74365
  function isPathInWorkspace(filePath, workspace) {
74129
74366
  try {
74130
- const resolvedPath = path63.resolve(workspace, filePath);
74367
+ const resolvedPath = path64.resolve(workspace, filePath);
74131
74368
  const realWorkspace = fs45.realpathSync(workspace);
74132
74369
  const realResolvedPath = fs45.realpathSync(resolvedPath);
74133
- const relativePath = path63.relative(realWorkspace, realResolvedPath);
74134
- if (relativePath.startsWith("..") || path63.isAbsolute(relativePath)) {
74370
+ const relativePath = path64.relative(realWorkspace, realResolvedPath);
74371
+ if (relativePath.startsWith("..") || path64.isAbsolute(relativePath)) {
74135
74372
  return false;
74136
74373
  }
74137
74374
  return true;
@@ -74143,7 +74380,7 @@ function validatePathForRead(filePath, workspace) {
74143
74380
  return isPathInWorkspace(filePath, workspace);
74144
74381
  }
74145
74382
  function extractTSSymbols(filePath, cwd) {
74146
- const fullPath = path63.join(cwd, filePath);
74383
+ const fullPath = path64.join(cwd, filePath);
74147
74384
  if (!validatePathForRead(fullPath, cwd)) {
74148
74385
  return [];
74149
74386
  }
@@ -74295,7 +74532,7 @@ function extractTSSymbols(filePath, cwd) {
74295
74532
  });
74296
74533
  }
74297
74534
  function extractPythonSymbols(filePath, cwd) {
74298
- const fullPath = path63.join(cwd, filePath);
74535
+ const fullPath = path64.join(cwd, filePath);
74299
74536
  if (!validatePathForRead(fullPath, cwd)) {
74300
74537
  return [];
74301
74538
  }
@@ -74378,7 +74615,7 @@ var symbols = createSwarmTool({
74378
74615
  }, null, 2);
74379
74616
  }
74380
74617
  const cwd = directory;
74381
- const ext = path63.extname(file3);
74618
+ const ext = path64.extname(file3);
74382
74619
  if (containsControlChars(file3)) {
74383
74620
  return JSON.stringify({
74384
74621
  file: file3,
@@ -74439,16 +74676,16 @@ var symbols = createSwarmTool({
74439
74676
  });
74440
74677
 
74441
74678
  // src/tools/repo-graph/types.ts
74442
- import * as path64 from "node:path";
74679
+ import * as path65 from "node:path";
74443
74680
  var REPO_GRAPH_FILENAME = "repo-graph.json";
74444
74681
  var GRAPH_SCHEMA_VERSION = "1.0.0";
74445
74682
  function normalizeGraphPath(filePath) {
74446
- return path64.normalize(filePath).replace(/\\/g, "/");
74683
+ return path65.normalize(filePath).replace(/\\/g, "/");
74447
74684
  }
74448
74685
  function createEmptyGraph(workspaceRoot) {
74449
74686
  return {
74450
74687
  schema_version: GRAPH_SCHEMA_VERSION,
74451
- workspaceRoot: path64.normalize(workspaceRoot),
74688
+ workspaceRoot: path65.normalize(workspaceRoot),
74452
74689
  nodes: {},
74453
74690
  edges: [],
74454
74691
  metadata: {
@@ -74623,8 +74860,8 @@ function resolveModuleSpecifier(workspaceRoot, sourceFile, specifier) {
74623
74860
  }
74624
74861
  try {
74625
74862
  if (specifier.startsWith(".")) {
74626
- const sourceDir = path65.dirname(sourceFile);
74627
- let resolved = path65.resolve(sourceDir, specifier);
74863
+ const sourceDir = path66.dirname(sourceFile);
74864
+ let resolved = path66.resolve(sourceDir, specifier);
74628
74865
  let realResolved;
74629
74866
  try {
74630
74867
  realResolved = realpathSync6(resolved);
@@ -74635,9 +74872,9 @@ function resolveModuleSpecifier(workspaceRoot, sourceFile, specifier) {
74635
74872
  try {
74636
74873
  realRoot = realpathSync6(workspaceRoot);
74637
74874
  } catch {
74638
- realRoot = path65.normalize(workspaceRoot);
74875
+ realRoot = path66.normalize(workspaceRoot);
74639
74876
  }
74640
- if (!existsSync36(resolved)) {
74877
+ if (!existsSync38(resolved)) {
74641
74878
  const EXTENSIONS = [
74642
74879
  ".ts",
74643
74880
  ".tsx",
@@ -74651,7 +74888,7 @@ function resolveModuleSpecifier(workspaceRoot, sourceFile, specifier) {
74651
74888
  let found = null;
74652
74889
  for (const ext of EXTENSIONS) {
74653
74890
  const candidate = resolved + ext;
74654
- if (existsSync36(candidate)) {
74891
+ if (existsSync38(candidate)) {
74655
74892
  found = candidate;
74656
74893
  break;
74657
74894
  }
@@ -74667,9 +74904,9 @@ function resolveModuleSpecifier(workspaceRoot, sourceFile, specifier) {
74667
74904
  return null;
74668
74905
  }
74669
74906
  }
74670
- const normalizedResolved = path65.normalize(realResolved);
74671
- const normalizedRoot = path65.normalize(realRoot);
74672
- if (!normalizedResolved.startsWith(normalizedRoot + path65.sep) && normalizedResolved !== normalizedRoot) {
74907
+ const normalizedResolved = path66.normalize(realResolved);
74908
+ const normalizedRoot = path66.normalize(realRoot);
74909
+ if (!normalizedResolved.startsWith(normalizedRoot + path66.sep) && normalizedResolved !== normalizedRoot) {
74673
74910
  return null;
74674
74911
  }
74675
74912
  return resolved;
@@ -74684,12 +74921,12 @@ function isRefusedWorkspaceRoot(target) {
74684
74921
  try {
74685
74922
  resolved = realpathSync6(target);
74686
74923
  } catch {
74687
- resolved = path65.resolve(target);
74924
+ resolved = path66.resolve(target);
74688
74925
  }
74689
74926
  const refused = new Set;
74690
74927
  const add = (p) => {
74691
74928
  if (typeof p === "string" && p.length > 0) {
74692
- refused.add(path65.resolve(p));
74929
+ refused.add(path66.resolve(p));
74693
74930
  }
74694
74931
  };
74695
74932
  add(os7.homedir());
@@ -74799,7 +75036,7 @@ async function findSourceFilesAsync(dir, stats, options) {
74799
75036
  ctx.stats.skippedDirs++;
74800
75037
  continue;
74801
75038
  }
74802
- const fullPath = path65.join(current, entry.name);
75039
+ const fullPath = path66.join(current, entry.name);
74803
75040
  if (entry.isSymbolicLink() && !ctx.followSymlinks) {
74804
75041
  ctx.stats.skippedDirs++;
74805
75042
  continue;
@@ -74807,7 +75044,7 @@ async function findSourceFilesAsync(dir, stats, options) {
74807
75044
  if (entry.isDirectory()) {
74808
75045
  queue.push(fullPath);
74809
75046
  } else if (entry.isFile()) {
74810
- const ext = path65.extname(fullPath).toLowerCase();
75047
+ const ext = path66.extname(fullPath).toLowerCase();
74811
75048
  if (SUPPORTED_EXTENSIONS.includes(ext)) {
74812
75049
  files.push(fullPath);
74813
75050
  }
@@ -74824,11 +75061,11 @@ async function findSourceFilesAsync(dir, stats, options) {
74824
75061
  return files;
74825
75062
  }
74826
75063
  function toModuleName(filePath, workspaceRoot) {
74827
- const relative11 = path65.relative(workspaceRoot, filePath);
74828
- return relative11.split(path65.sep).join("/");
75064
+ const relative11 = path66.relative(workspaceRoot, filePath);
75065
+ return relative11.split(path66.sep).join("/");
74829
75066
  }
74830
75067
  function getLanguage(filePath) {
74831
- const ext = path65.extname(filePath).toLowerCase();
75068
+ const ext = path66.extname(filePath).toLowerCase();
74832
75069
  return EXTENSION_TO_LANGUAGE[ext] ?? "unknown";
74833
75070
  }
74834
75071
  function isBinaryContent(content) {
@@ -74841,26 +75078,26 @@ function scanFile(filePath, absoluteRoot, maxFileSize) {
74841
75078
  let content;
74842
75079
  let fileStats;
74843
75080
  try {
74844
- fileStats = fsSync3.statSync(filePath);
75081
+ fileStats = fsSync4.statSync(filePath);
74845
75082
  if (fileStats.size > maxFileSize) {
74846
75083
  return { node: null, edges: [] };
74847
75084
  }
74848
- content = fsSync3.readFileSync(filePath, "utf-8");
75085
+ content = fsSync4.readFileSync(filePath, "utf-8");
74849
75086
  } catch {
74850
75087
  return { node: null, edges: [] };
74851
75088
  }
74852
75089
  if (isBinaryContent(content)) {
74853
75090
  return { node: null, edges: [] };
74854
75091
  }
74855
- const ext = path65.extname(filePath).toLowerCase();
75092
+ const ext = path66.extname(filePath).toLowerCase();
74856
75093
  let exports = [];
74857
75094
  try {
74858
75095
  if ([".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs"].includes(ext)) {
74859
- const relativePath = path65.relative(absoluteRoot, filePath);
75096
+ const relativePath = path66.relative(absoluteRoot, filePath);
74860
75097
  const symbols2 = extractTSSymbols(relativePath, absoluteRoot);
74861
75098
  exports = symbols2.filter((s) => s.exported).map((s) => s.name);
74862
75099
  } else if (ext === ".py") {
74863
- const relativePath = path65.relative(absoluteRoot, filePath);
75100
+ const relativePath = path66.relative(absoluteRoot, filePath);
74864
75101
  const symbols2 = extractPythonSymbols(relativePath, absoluteRoot);
74865
75102
  exports = symbols2.filter((s) => s.exported).map((s) => s.name);
74866
75103
  }
@@ -74897,8 +75134,8 @@ async function buildWorkspaceGraphAsync(workspaceRoot, options) {
74897
75134
  const maxFiles = options?.maxFiles ?? DEFAULT_WALK_FILE_CAP;
74898
75135
  const walkBudgetMs = options?.walkBudgetMs ?? DEFAULT_WALK_BUDGET_MS;
74899
75136
  const followSymlinks = options?.followSymlinks ?? false;
74900
- const absoluteRoot = path65.resolve(workspaceRoot);
74901
- if (!existsSync36(absoluteRoot)) {
75137
+ const absoluteRoot = path66.resolve(workspaceRoot);
75138
+ if (!existsSync38(absoluteRoot)) {
74902
75139
  throw new Error(`Workspace directory does not exist: ${workspaceRoot}`);
74903
75140
  }
74904
75141
  if (isRefusedWorkspaceRoot(absoluteRoot)) {
@@ -74953,15 +75190,15 @@ async function buildWorkspaceGraphAsync(workspaceRoot, options) {
74953
75190
  return graph;
74954
75191
  }
74955
75192
  // src/tools/repo-graph/cache.ts
74956
- import * as path66 from "node:path";
75193
+ import * as path67 from "node:path";
74957
75194
  var graphCache = new Map;
74958
75195
  var dirtyFlags = new Map;
74959
75196
  var mtimeCache = new Map;
74960
75197
  function getCachedGraph(workspace) {
74961
- return graphCache.get(path66.normalize(workspace));
75198
+ return graphCache.get(path67.normalize(workspace));
74962
75199
  }
74963
75200
  function setCachedGraph(workspace, graph, mtime) {
74964
- const normalized = path66.normalize(workspace);
75201
+ const normalized = path67.normalize(workspace);
74965
75202
  graphCache.set(normalized, graph);
74966
75203
  dirtyFlags.set(normalized, false);
74967
75204
  if (mtime !== undefined) {
@@ -74969,30 +75206,30 @@ function setCachedGraph(workspace, graph, mtime) {
74969
75206
  }
74970
75207
  }
74971
75208
  function isDirty(workspace) {
74972
- return dirtyFlags.get(path66.normalize(workspace)) ?? false;
75209
+ return dirtyFlags.get(path67.normalize(workspace)) ?? false;
74973
75210
  }
74974
75211
  function clearCache(workspace) {
74975
- const normalized = path66.normalize(workspace);
75212
+ const normalized = path67.normalize(workspace);
74976
75213
  graphCache.delete(normalized);
74977
75214
  dirtyFlags.delete(normalized);
74978
75215
  mtimeCache.delete(normalized);
74979
75216
  }
74980
75217
  function getCachedMtime(workspace) {
74981
- return mtimeCache.get(path66.normalize(workspace));
75218
+ return mtimeCache.get(path67.normalize(workspace));
74982
75219
  }
74983
75220
  // src/tools/repo-graph/incremental.ts
74984
75221
  init_logger();
74985
- import { existsSync as existsSync38 } from "node:fs";
75222
+ import { existsSync as existsSync40 } from "node:fs";
74986
75223
  import * as fsPromises7 from "node:fs/promises";
74987
- import * as path68 from "node:path";
75224
+ import * as path69 from "node:path";
74988
75225
 
74989
75226
  // src/tools/repo-graph/storage.ts
74990
75227
  init_utils2();
74991
75228
  init_logger();
74992
75229
  init_path_security();
74993
- import { constants as constants4, existsSync as existsSync37, realpathSync as realpathSync7 } from "node:fs";
75230
+ import { constants as constants4, existsSync as existsSync39, realpathSync as realpathSync7 } from "node:fs";
74994
75231
  import * as fsPromises6 from "node:fs/promises";
74995
- import * as path67 from "node:path";
75232
+ import * as path68 from "node:path";
74996
75233
  var WINDOWS_RENAME_MAX_RETRIES2 = 3;
74997
75234
  var WINDOWS_RENAME_RETRY_DELAY_MS2 = 50;
74998
75235
  function getGraphPath(workspace) {
@@ -75003,12 +75240,12 @@ function getGraphPath(workspace) {
75003
75240
  }
75004
75241
  async function loadGraph(workspace) {
75005
75242
  validateWorkspace(workspace);
75006
- const normalized = path67.normalize(workspace);
75243
+ const normalized = path68.normalize(workspace);
75007
75244
  const cached3 = getCachedGraph(normalized);
75008
75245
  if (cached3 && !isDirty(normalized)) {
75009
75246
  try {
75010
75247
  const graphPath = getGraphPath(workspace);
75011
- if (existsSync37(graphPath)) {
75248
+ if (existsSync39(graphPath)) {
75012
75249
  const stats = await fsPromises6.stat(graphPath);
75013
75250
  const cachedMtime = getCachedMtime(normalized);
75014
75251
  if (cachedMtime !== undefined && stats.mtimeMs !== cachedMtime) {
@@ -75025,7 +75262,7 @@ async function loadGraph(workspace) {
75025
75262
  }
75026
75263
  try {
75027
75264
  const graphPath = getGraphPath(workspace);
75028
- if (!existsSync37(graphPath)) {
75265
+ if (!existsSync39(graphPath)) {
75029
75266
  return null;
75030
75267
  }
75031
75268
  const stats = await fsPromises6.stat(graphPath);
@@ -75097,28 +75334,28 @@ async function saveGraph(workspace, graph, options) {
75097
75334
  if (!Array.isArray(graph.edges)) {
75098
75335
  throw new Error("Graph must have edges array");
75099
75336
  }
75100
- const normalizedWorkspace = path67.normalize(workspace);
75337
+ const normalizedWorkspace = path68.normalize(workspace);
75101
75338
  let realWorkspace;
75102
75339
  try {
75103
75340
  realWorkspace = realpathSync7(workspace);
75104
75341
  } catch {
75105
75342
  realWorkspace = normalizedWorkspace;
75106
75343
  }
75107
- const normalizedGraphRoot = path67.normalize(graph.workspaceRoot);
75344
+ const normalizedGraphRoot = path68.normalize(graph.workspaceRoot);
75108
75345
  let realGraphRoot;
75109
75346
  try {
75110
75347
  realGraphRoot = realpathSync7(graph.workspaceRoot);
75111
75348
  } catch {
75112
75349
  realGraphRoot = normalizedGraphRoot;
75113
75350
  }
75114
- if (path67.normalize(realWorkspace) !== path67.normalize(realGraphRoot)) {
75351
+ if (path68.normalize(realWorkspace) !== path68.normalize(realGraphRoot)) {
75115
75352
  throw new Error(`Graph workspaceRoot mismatch: graph was built for "${graph.workspaceRoot}" but save was called for "${workspace}"`);
75116
75353
  }
75117
75354
  const normalized = normalizedWorkspace;
75118
75355
  const graphPath = getGraphPath(workspace);
75119
75356
  updateGraphMetadata(graph);
75120
75357
  const tempPath = `${graphPath}.tmp.${Date.now()}.${Math.floor(Math.random() * 1e9)}`;
75121
- await fsPromises6.mkdir(path67.dirname(tempPath), { recursive: true });
75358
+ await fsPromises6.mkdir(path68.dirname(tempPath), { recursive: true });
75122
75359
  let lastError = null;
75123
75360
  try {
75124
75361
  if (options?.createAtomic) {
@@ -75186,12 +75423,12 @@ async function updateGraphForFiles(workspaceRoot, filePaths, options) {
75186
75423
  return graph2;
75187
75424
  }
75188
75425
  const graph = existingGraph;
75189
- const absoluteRoot = path68.resolve(workspaceRoot);
75426
+ const absoluteRoot = path69.resolve(workspaceRoot);
75190
75427
  const maxFileSize = 1024 * 1024;
75191
75428
  const updatedPaths = new Set;
75192
75429
  for (const rawFilePath of filePaths) {
75193
75430
  const normalizedPath = normalizeGraphPath(rawFilePath);
75194
- const fileExists = existsSync38(rawFilePath);
75431
+ const fileExists = existsSync40(rawFilePath);
75195
75432
  if (fileExists) {
75196
75433
  graph.edges = graph.edges.filter((e) => normalizeGraphPath(e.source) !== normalizedPath);
75197
75434
  const result = scanFile(rawFilePath, absoluteRoot, maxFileSize);
@@ -75226,12 +75463,12 @@ async function updateGraphForFiles(workspaceRoot, filePaths, options) {
75226
75463
  await saveGraph(workspaceRoot, rebuiltGraph);
75227
75464
  return rebuiltGraph;
75228
75465
  }
75229
- const normalizedWorkspace = path68.normalize(workspaceRoot);
75466
+ const normalizedWorkspace = path69.normalize(workspaceRoot);
75230
75467
  const loadedMtime = getCachedMtime(normalizedWorkspace);
75231
75468
  if (loadedMtime !== undefined) {
75232
75469
  try {
75233
75470
  const graphPath = getGraphPath(workspaceRoot);
75234
- if (existsSync38(graphPath)) {
75471
+ if (existsSync40(graphPath)) {
75235
75472
  const currentStats = await fsPromises7.stat(graphPath);
75236
75473
  if (currentStats.mtimeMs !== loadedMtime) {
75237
75474
  warn(`[repo-graph] Concurrent modification detected — falling back to full rebuild`);
@@ -75324,7 +75561,7 @@ function createRepoGraphBuilderHook(workspaceRoot, deps) {
75324
75561
  return;
75325
75562
  if (!isSupportedSourceFile(filePath))
75326
75563
  return;
75327
- const absoluteFilePath = path69.isAbsolute(filePath) ? filePath : path69.resolve(workspaceRoot, filePath);
75564
+ const absoluteFilePath = path70.isAbsolute(filePath) ? filePath : path70.resolve(workspaceRoot, filePath);
75328
75565
  let realFilePath;
75329
75566
  try {
75330
75567
  realFilePath = realpathSync8(absoluteFilePath);
@@ -75351,7 +75588,7 @@ function createRepoGraphBuilderHook(workspaceRoot, deps) {
75351
75588
  try {
75352
75589
  await _updateGraphForFiles(workspaceRoot, [absoluteFilePath]);
75353
75590
  consecutiveFailures = 0;
75354
- log(`[repo-graph] Incremental update for ${path69.basename(filePath)}`);
75591
+ log(`[repo-graph] Incremental update for ${path70.basename(filePath)}`);
75355
75592
  } catch (error93) {
75356
75593
  const message = error93 instanceof Error ? error93.message : String(error93);
75357
75594
  consecutiveFailures++;
@@ -75374,14 +75611,14 @@ init_manager2();
75374
75611
  init_detector();
75375
75612
  init_manager();
75376
75613
  import * as fs54 from "node:fs";
75377
- import * as path79 from "node:path";
75614
+ import * as path80 from "node:path";
75378
75615
 
75379
75616
  // src/services/decision-drift-analyzer.ts
75380
75617
  init_utils2();
75381
75618
  init_manager();
75382
75619
  init_utils();
75383
75620
  import * as fs46 from "node:fs";
75384
- import * as path70 from "node:path";
75621
+ import * as path71 from "node:path";
75385
75622
  var DEFAULT_DRIFT_CONFIG = {
75386
75623
  staleThresholdPhases: 1,
75387
75624
  detectContradictions: true,
@@ -75535,7 +75772,7 @@ async function analyzeDecisionDrift(directory, config3 = {}) {
75535
75772
  currentPhase = legacyPhase;
75536
75773
  }
75537
75774
  }
75538
- const contextPath = path70.join(directory, ".swarm", "context.md");
75775
+ const contextPath = path71.join(directory, ".swarm", "context.md");
75539
75776
  let contextContent = "";
75540
75777
  try {
75541
75778
  if (fs46.existsSync(contextPath)) {
@@ -75674,7 +75911,7 @@ init_utils();
75674
75911
  init_constants();
75675
75912
  init_schema();
75676
75913
  import * as fs47 from "node:fs/promises";
75677
- import * as path71 from "node:path";
75914
+ import * as path72 from "node:path";
75678
75915
  function safeGet(obj, key) {
75679
75916
  if (!obj || !Object.hasOwn(obj, key))
75680
75917
  return;
@@ -75906,9 +76143,9 @@ async function handleDebuggingSpiral(match, taskId, directory) {
75906
76143
  let eventLogged = false;
75907
76144
  let checkpointCreated = false;
75908
76145
  try {
75909
- const swarmDir = path71.join(directory, ".swarm");
76146
+ const swarmDir = path72.join(directory, ".swarm");
75910
76147
  await fs47.mkdir(swarmDir, { recursive: true });
75911
- const eventsPath = path71.join(swarmDir, "events.jsonl");
76148
+ const eventsPath = path72.join(swarmDir, "events.jsonl");
75912
76149
  await fs47.appendFile(eventsPath, `${formatDebuggingSpiralEvent(match, taskId)}
75913
76150
  `);
75914
76151
  eventLogged = true;
@@ -76044,7 +76281,7 @@ import * as fs51 from "node:fs";
76044
76281
 
76045
76282
  // src/graph/graph-builder.ts
76046
76283
  import * as fs49 from "node:fs";
76047
- import * as path74 from "node:path";
76284
+ import * as path75 from "node:path";
76048
76285
 
76049
76286
  // node_modules/yocto-queue/index.js
76050
76287
  class Node {
@@ -76205,7 +76442,7 @@ function validateConcurrency(concurrency) {
76205
76442
  // src/graph/import-extractor.ts
76206
76443
  init_path_security();
76207
76444
  import * as fs48 from "node:fs";
76208
- import * as path72 from "node:path";
76445
+ import * as path73 from "node:path";
76209
76446
  var SOURCE_EXTENSIONS2 = [
76210
76447
  ".ts",
76211
76448
  ".tsx",
@@ -76250,14 +76487,14 @@ function getLanguageFromExtension(ext) {
76250
76487
  return null;
76251
76488
  }
76252
76489
  function toRelForwardSlash(absPath, root) {
76253
- return path72.relative(root, absPath).replace(/\\/g, "/");
76490
+ return path73.relative(root, absPath).replace(/\\/g, "/");
76254
76491
  }
76255
76492
  function tryResolveTSJS(rawModule, sourceFileAbs) {
76256
76493
  if (!rawModule.startsWith(".") && !rawModule.startsWith("/")) {
76257
76494
  return null;
76258
76495
  }
76259
- const sourceDir = path72.dirname(sourceFileAbs);
76260
- const baseAbs = path72.resolve(sourceDir, rawModule);
76496
+ const sourceDir = path73.dirname(sourceFileAbs);
76497
+ const baseAbs = path73.resolve(sourceDir, rawModule);
76261
76498
  const probe = (basePath) => {
76262
76499
  for (const ext of RESOLVE_EXTENSION_CANDIDATES) {
76263
76500
  const test = basePath + ext;
@@ -76268,7 +76505,7 @@ function tryResolveTSJS(rawModule, sourceFileAbs) {
76268
76505
  } catch {}
76269
76506
  }
76270
76507
  for (const indexFile of RESOLVE_INDEX_CANDIDATES) {
76271
- const test = path72.join(basePath, indexFile);
76508
+ const test = path73.join(basePath, indexFile);
76272
76509
  try {
76273
76510
  const stat6 = fs48.statSync(test);
76274
76511
  if (stat6.isFile())
@@ -76298,13 +76535,13 @@ function tryResolvePython(rawModule, sourceFileAbs, workspaceRoot) {
76298
76535
  }
76299
76536
  const remainder = rawModule.slice(leadingDots).replace(/\./g, "/");
76300
76537
  const upDirs = "../".repeat(Math.max(0, leadingDots - 1));
76301
- const sourceDir = path72.dirname(sourceFileAbs);
76302
- const baseAbs = path72.resolve(sourceDir, upDirs + remainder);
76538
+ const sourceDir = path73.dirname(sourceFileAbs);
76539
+ const baseAbs = path73.resolve(sourceDir, upDirs + remainder);
76303
76540
  const accept = (test) => {
76304
76541
  try {
76305
76542
  const stat6 = fs48.statSync(test);
76306
76543
  if (stat6.isFile()) {
76307
- const rel = path72.relative(workspaceRoot, test).replace(/\\/g, "/");
76544
+ const rel = path73.relative(workspaceRoot, test).replace(/\\/g, "/");
76308
76545
  if (rel.startsWith(".."))
76309
76546
  return null;
76310
76547
  return test;
@@ -76318,7 +76555,7 @@ function tryResolvePython(rawModule, sourceFileAbs, workspaceRoot) {
76318
76555
  return hit;
76319
76556
  }
76320
76557
  for (const indexFile of PY_INDEX_CANDIDATES) {
76321
- const hit = accept(path72.join(baseAbs, indexFile));
76558
+ const hit = accept(path73.join(baseAbs, indexFile));
76322
76559
  if (hit)
76323
76560
  return hit;
76324
76561
  }
@@ -76689,7 +76926,7 @@ function parseRustUses(content) {
76689
76926
  }
76690
76927
  function extractImports5(opts) {
76691
76928
  const { absoluteFilePath, workspaceRoot } = opts;
76692
- const ext = path72.extname(absoluteFilePath).toLowerCase();
76929
+ const ext = path73.extname(absoluteFilePath).toLowerCase();
76693
76930
  const language = getLanguageFromExtension(ext);
76694
76931
  if (!language)
76695
76932
  return [];
@@ -76740,9 +76977,9 @@ function extractImports5(opts) {
76740
76977
  }
76741
76978
 
76742
76979
  // src/graph/symbol-extractor.ts
76743
- import * as path73 from "node:path";
76980
+ import * as path74 from "node:path";
76744
76981
  function extractExportedSymbols(relativeFilePath, workspaceRoot) {
76745
- const ext = path73.extname(relativeFilePath).toLowerCase();
76982
+ const ext = path74.extname(relativeFilePath).toLowerCase();
76746
76983
  const language = getLanguageFromExtension(ext);
76747
76984
  if (!language)
76748
76985
  return [];
@@ -76831,15 +77068,15 @@ function findSourceFiles(workspaceRoot, skipDirs = DEFAULT_SKIP_DIRS) {
76831
77068
  if (entry.isDirectory()) {
76832
77069
  if (skipDirs.has(entry.name))
76833
77070
  continue;
76834
- stack.push(path74.join(dir, entry.name));
77071
+ stack.push(path75.join(dir, entry.name));
76835
77072
  continue;
76836
77073
  }
76837
77074
  if (!entry.isFile())
76838
77075
  continue;
76839
- const ext = path74.extname(entry.name).toLowerCase();
77076
+ const ext = path75.extname(entry.name).toLowerCase();
76840
77077
  if (!SOURCE_EXT_SET.has(ext))
76841
77078
  continue;
76842
- out2.push(path74.join(dir, entry.name));
77079
+ out2.push(path75.join(dir, entry.name));
76843
77080
  }
76844
77081
  }
76845
77082
  return out2;
@@ -76867,7 +77104,7 @@ async function buildRepoGraph(workspaceRoot, options = {}) {
76867
77104
  };
76868
77105
  }
76869
77106
  async function processFile(absoluteFilePath, workspaceRoot) {
76870
- const ext = path74.extname(absoluteFilePath).toLowerCase();
77107
+ const ext = path75.extname(absoluteFilePath).toLowerCase();
76871
77108
  const language = getLanguageFromExtension(ext);
76872
77109
  if (!language)
76873
77110
  return null;
@@ -76887,7 +77124,7 @@ async function processFile(absoluteFilePath, workspaceRoot) {
76887
77124
  } catch {
76888
77125
  return null;
76889
77126
  }
76890
- const relPath = path74.relative(workspaceRoot, absoluteFilePath).replace(/\\/g, "/");
77127
+ const relPath = path75.relative(workspaceRoot, absoluteFilePath).replace(/\\/g, "/");
76891
77128
  const imports = extractImports5({
76892
77129
  absoluteFilePath,
76893
77130
  workspaceRoot,
@@ -77129,10 +77366,10 @@ function formatSummary(opts) {
77129
77366
  // src/graph/graph-store.ts
77130
77367
  import * as crypto6 from "node:crypto";
77131
77368
  import * as fs50 from "node:fs";
77132
- import * as path75 from "node:path";
77369
+ import * as path76 from "node:path";
77133
77370
  var SWARM_DIR = ".swarm";
77134
77371
  function getGraphPath2(workspaceRoot) {
77135
- return path75.join(workspaceRoot, SWARM_DIR, REPO_GRAPH_FILENAME2);
77372
+ return path76.join(workspaceRoot, SWARM_DIR, REPO_GRAPH_FILENAME2);
77136
77373
  }
77137
77374
  function loadGraph2(workspaceRoot) {
77138
77375
  const file3 = getGraphPath2(workspaceRoot);
@@ -77154,7 +77391,7 @@ function loadGraph2(workspaceRoot) {
77154
77391
  }
77155
77392
  function saveGraph2(workspaceRoot, graph) {
77156
77393
  const file3 = getGraphPath2(workspaceRoot);
77157
- const dir = path75.dirname(file3);
77394
+ const dir = path76.dirname(file3);
77158
77395
  try {
77159
77396
  const stat6 = fs50.lstatSync(dir);
77160
77397
  if (stat6.isSymbolicLink()) {
@@ -77260,7 +77497,7 @@ function buildReviewerBlastRadiusBlock(directory, changedFiles) {
77260
77497
  // src/hooks/semantic-diff-injection.ts
77261
77498
  import * as child_process5 from "node:child_process";
77262
77499
  import * as fs52 from "node:fs";
77263
- import * as path77 from "node:path";
77500
+ import * as path78 from "node:path";
77264
77501
 
77265
77502
  // src/diff/ast-diff.ts
77266
77503
  init_tree_sitter();
@@ -78007,17 +78244,17 @@ async function buildSemanticDiffBlock(directory, changedFiles, maxFiles = 10) {
78007
78244
  const fileConsumers = {};
78008
78245
  if (graph) {
78009
78246
  for (const f of filesToProcess) {
78010
- const relativePath = path77.isAbsolute(f) ? path77.relative(directory, f) : f;
78247
+ const relativePath = path78.isAbsolute(f) ? path78.relative(directory, f) : f;
78011
78248
  const normalized = normalizeGraphPath2(relativePath);
78012
78249
  fileConsumers[normalized] = getImporters(graph, normalized).length;
78013
78250
  fileConsumers[f] = fileConsumers[normalized];
78014
78251
  }
78015
78252
  }
78016
78253
  for (const filePath of filesToProcess) {
78017
- const normalizedPath = path77.normalize(filePath);
78018
- const resolvedPath = path77.resolve(directory, normalizedPath);
78019
- const relativeToDir = path77.relative(directory, resolvedPath);
78020
- if (relativeToDir.startsWith("..") || path77.isAbsolute(relativeToDir)) {
78254
+ const normalizedPath = path78.normalize(filePath);
78255
+ const resolvedPath = path78.resolve(directory, normalizedPath);
78256
+ const relativeToDir = path78.relative(directory, resolvedPath);
78257
+ if (relativeToDir.startsWith("..") || path78.isAbsolute(relativeToDir)) {
78021
78258
  continue;
78022
78259
  }
78023
78260
  try {
@@ -78044,7 +78281,7 @@ async function buildSemanticDiffBlock(directory, changedFiles, maxFiles = 10) {
78044
78281
  stdio: "pipe",
78045
78282
  maxBuffer: 5 * 1024 * 1024
78046
78283
  }) : "";
78047
- const newContent = fs52.readFileSync(path77.join(directory, filePath), "utf-8");
78284
+ const newContent = fs52.readFileSync(path78.join(directory, filePath), "utf-8");
78048
78285
  const astResult = await computeASTDiff(filePath, oldContent, newContent);
78049
78286
  if (astResult && (astResult.changes.length > 0 || astResult.error !== undefined)) {
78050
78287
  astDiffs.push(astResult);
@@ -78071,6 +78308,49 @@ ${markdown}`;
78071
78308
 
78072
78309
  // src/hooks/system-enhancer.ts
78073
78310
  init_utils2();
78311
+ function buildSpecDriftAdvisory(args2) {
78312
+ const lines = [
78313
+ "[spec-drift]",
78314
+ `Reason: ${args2.reason}`,
78315
+ `Stored spec hash: ${args2.storedHash}`,
78316
+ `Current spec hash: ${args2.currentHash ?? "(spec.md missing)"}`,
78317
+ "Action: surface this warning to the user at your next user-facing reply. " + "Do NOT proceed with destructive plan operations (save_plan with removals, " + "update_task_status, phase_complete, lean_turbo_run_phase, " + "lean_turbo_acquire_locks) until the user runs /swarm clarify or " + "/swarm acknowledge-spec-drift."
78318
+ ];
78319
+ if (args2.midLoadRemovals) {
78320
+ lines.push(`Auto-removed during recovery: ${args2.midLoadRemovals.count} task(s) ` + `(source: ${args2.midLoadRemovals.source}). See ` + ".swarm/plan-ledger.jsonl for IDs.");
78321
+ }
78322
+ return lines.join(`
78323
+ `);
78324
+ }
78325
+ function readSpecStalenessSnapshot2(directory) {
78326
+ try {
78327
+ const p = path80.join(directory, ".swarm", "spec-staleness.json");
78328
+ if (!fs54.existsSync(p))
78329
+ return null;
78330
+ const raw = fs54.readFileSync(p, "utf-8");
78331
+ const parsed = JSON.parse(raw);
78332
+ if (typeof parsed?.specHash_plan === "string" && (typeof parsed?.specHash_current === "string" || parsed?.specHash_current === null)) {
78333
+ return {
78334
+ specHash_plan: parsed.specHash_plan,
78335
+ specHash_current: parsed.specHash_current
78336
+ };
78337
+ }
78338
+ } catch {}
78339
+ return null;
78340
+ }
78341
+ function maybeAppendSpecDriftAdvisory(output, directory, plan) {
78342
+ if (!plan?._specStale)
78343
+ return;
78344
+ const snap = readSpecStalenessSnapshot2(directory);
78345
+ const storedHash = snap?.specHash_plan ?? plan.specHash ?? "(unknown — plan missing specHash)";
78346
+ const currentHash = snap?.specHash_current ?? null;
78347
+ output.system.push(buildSpecDriftAdvisory({
78348
+ reason: plan._specStaleReason ?? "spec.md changed since plan was saved",
78349
+ currentHash,
78350
+ storedHash,
78351
+ midLoadRemovals: plan._midLoadRemovals
78352
+ }));
78353
+ }
78074
78354
  function extractAgentPrefix(fullAgentName) {
78075
78355
  if (!fullAgentName)
78076
78356
  return "";
@@ -78392,7 +78672,7 @@ function createSystemEnhancerHook(config3, directory) {
78392
78672
  await fs54.promises.writeFile(darkMatterPath, darkMatterReport, "utf-8");
78393
78673
  warn(`[system-enhancer] Dark matter scan complete: ${darkMatter.length} co-change patterns found`);
78394
78674
  try {
78395
- const projectName = path79.basename(path79.resolve(directory));
78675
+ const projectName = path80.basename(path80.resolve(directory));
78396
78676
  const knowledgeEntries = darkMatterToKnowledgeEntries2(darkMatter, projectName);
78397
78677
  const knowledgePath = resolveSwarmKnowledgePath(directory);
78398
78678
  const existingEntries = await readKnowledge(knowledgePath);
@@ -78433,6 +78713,7 @@ function createSystemEnhancerHook(config3, directory) {
78433
78713
  } catch (error93) {
78434
78714
  warn(`Failed to load plan: ${error93 instanceof Error ? error93.message : String(error93)}`);
78435
78715
  }
78716
+ maybeAppendSpecDriftAdvisory(output, directory, plan2);
78436
78717
  const mode = await detectArchitectMode(directory);
78437
78718
  let planContent = null;
78438
78719
  let phaseHeader = "";
@@ -78591,7 +78872,7 @@ ${lines.join(`
78591
78872
  try {
78592
78873
  const taskId_ccp = ccpSession?.currentTaskId;
78593
78874
  if (taskId_ccp && !taskId_ccp.includes("..") && !taskId_ccp.includes("/") && !taskId_ccp.includes("\\") && !taskId_ccp.includes("\x00")) {
78594
- const evidencePath = path79.join(directory, ".swarm", "evidence", `${taskId_ccp}.json`);
78875
+ const evidencePath = path80.join(directory, ".swarm", "evidence", `${taskId_ccp}.json`);
78595
78876
  if (fs54.existsSync(evidencePath)) {
78596
78877
  const evidenceContent = fs54.readFileSync(evidencePath, "utf-8");
78597
78878
  const evidenceData = JSON.parse(evidenceContent);
@@ -78806,6 +79087,7 @@ ${budgetWarning}`);
78806
79087
  } catch (error93) {
78807
79088
  warn(`Failed to load plan: ${error93 instanceof Error ? error93.message : String(error93)}`);
78808
79089
  }
79090
+ maybeAppendSpecDriftAdvisory(output, directory, plan);
78809
79091
  let currentPhase = null;
78810
79092
  let currentTask = null;
78811
79093
  if (plan && plan.migration_status !== "migration_failed") {
@@ -79754,7 +80036,7 @@ import * as fs56 from "node:fs";
79754
80036
  // src/full-auto/policy.ts
79755
80037
  init_constants();
79756
80038
  import * as fs55 from "node:fs";
79757
- import * as path80 from "node:path";
80039
+ import * as path81 from "node:path";
79758
80040
  var READ_ONLY_TOOLS = new Set([
79759
80041
  "check_gate_status",
79760
80042
  "completion_verify",
@@ -79949,11 +80231,11 @@ function normalizePath3(p) {
79949
80231
  function isWithinDirectory(target, root) {
79950
80232
  if (!target || !root)
79951
80233
  return false;
79952
- const resolvedTarget = path80.resolve(target);
79953
- const resolvedRoot = path80.resolve(root);
80234
+ const resolvedTarget = path81.resolve(target);
80235
+ const resolvedRoot = path81.resolve(root);
79954
80236
  if (resolvedTarget === resolvedRoot)
79955
80237
  return true;
79956
- const withSep = resolvedRoot.endsWith(path80.sep) ? resolvedRoot : resolvedRoot + path80.sep;
80238
+ const withSep = resolvedRoot.endsWith(path81.sep) ? resolvedRoot : resolvedRoot + path81.sep;
79957
80239
  if (process.platform === "win32") {
79958
80240
  return resolvedTarget.toLowerCase().startsWith(withSep.toLowerCase());
79959
80241
  }
@@ -80012,7 +80294,7 @@ function classifyPathRisk(filePath, context) {
80012
80294
  highRiskBuild: false
80013
80295
  };
80014
80296
  }
80015
- const absolute = path80.isAbsolute(filePath) ? filePath : path80.resolve(context.directory, filePath);
80297
+ const absolute = path81.isAbsolute(filePath) ? filePath : path81.resolve(context.directory, filePath);
80016
80298
  const resolvedAbsolute = (() => {
80017
80299
  try {
80018
80300
  let candidate = absolute;
@@ -80028,7 +80310,7 @@ function classifyPathRisk(filePath, context) {
80028
80310
  }
80029
80311
  return absolute;
80030
80312
  }
80031
- const parent = path80.dirname(candidate);
80313
+ const parent = path81.dirname(candidate);
80032
80314
  if (parent === candidate)
80033
80315
  break;
80034
80316
  candidate = parent;
@@ -80040,7 +80322,7 @@ function classifyPathRisk(filePath, context) {
80040
80322
  }
80041
80323
  })();
80042
80324
  const withinProjectRoot = isWithinDirectory(absolute, context.directory) && isWithinDirectory(resolvedAbsolute, context.directory);
80043
- const relative17 = path80.relative(context.directory, absolute).replace(/\\/g, "/");
80325
+ const relative17 = path81.relative(context.directory, absolute).replace(/\\/g, "/");
80044
80326
  let withinDeclaredScope = null;
80045
80327
  if (Array.isArray(context.declaredScope)) {
80046
80328
  withinDeclaredScope = context.declaredScope.length === 0 ? false : context.declaredScope.some((scope) => {
@@ -80350,7 +80632,7 @@ function classifyFullAutoToolAction(input) {
80350
80632
  recoverable: true
80351
80633
  };
80352
80634
  }
80353
- if (isProtectedPath(path80.relative(input.directory, path80.resolve(input.directory, p)), config3)) {
80635
+ if (isProtectedPath(path81.relative(input.directory, path81.resolve(input.directory, p)), config3)) {
80354
80636
  return {
80355
80637
  action: "escalate_critic",
80356
80638
  reason: `write to protected path requires critic approval: ${p}`,
@@ -81124,7 +81406,7 @@ init_hive_promoter();
81124
81406
 
81125
81407
  // src/hooks/incremental-verify.ts
81126
81408
  import * as fs58 from "node:fs";
81127
- import * as path81 from "node:path";
81409
+ import * as path82 from "node:path";
81128
81410
 
81129
81411
  // src/hooks/spawn-helper.ts
81130
81412
  import * as child_process6 from "node:child_process";
@@ -81202,18 +81484,18 @@ function spawnAsync(command, cwd, timeoutMs) {
81202
81484
  // src/hooks/incremental-verify.ts
81203
81485
  var emittedSkipAdvisories = new Set;
81204
81486
  function detectPackageManager(projectDir) {
81205
- if (fs58.existsSync(path81.join(projectDir, "bun.lockb")))
81487
+ if (fs58.existsSync(path82.join(projectDir, "bun.lockb")))
81206
81488
  return "bun";
81207
- if (fs58.existsSync(path81.join(projectDir, "pnpm-lock.yaml")))
81489
+ if (fs58.existsSync(path82.join(projectDir, "pnpm-lock.yaml")))
81208
81490
  return "pnpm";
81209
- if (fs58.existsSync(path81.join(projectDir, "yarn.lock")))
81491
+ if (fs58.existsSync(path82.join(projectDir, "yarn.lock")))
81210
81492
  return "yarn";
81211
- if (fs58.existsSync(path81.join(projectDir, "package-lock.json")))
81493
+ if (fs58.existsSync(path82.join(projectDir, "package-lock.json")))
81212
81494
  return "npm";
81213
81495
  return "bun";
81214
81496
  }
81215
81497
  function detectTypecheckCommand(projectDir) {
81216
- const pkgPath = path81.join(projectDir, "package.json");
81498
+ const pkgPath = path82.join(projectDir, "package.json");
81217
81499
  if (fs58.existsSync(pkgPath)) {
81218
81500
  try {
81219
81501
  const pkg = JSON.parse(fs58.readFileSync(pkgPath, "utf8"));
@@ -81230,8 +81512,8 @@ function detectTypecheckCommand(projectDir) {
81230
81512
  ...pkg.dependencies,
81231
81513
  ...pkg.devDependencies
81232
81514
  };
81233
- if (!deps?.typescript && !fs58.existsSync(path81.join(projectDir, "tsconfig.json"))) {}
81234
- const hasTSMarkers = deps?.typescript || fs58.existsSync(path81.join(projectDir, "tsconfig.json"));
81515
+ if (!deps?.typescript && !fs58.existsSync(path82.join(projectDir, "tsconfig.json"))) {}
81516
+ const hasTSMarkers = deps?.typescript || fs58.existsSync(path82.join(projectDir, "tsconfig.json"));
81235
81517
  if (hasTSMarkers) {
81236
81518
  return { command: ["npx", "tsc", "--noEmit"], language: "typescript" };
81237
81519
  }
@@ -81239,13 +81521,13 @@ function detectTypecheckCommand(projectDir) {
81239
81521
  return null;
81240
81522
  }
81241
81523
  }
81242
- if (fs58.existsSync(path81.join(projectDir, "go.mod"))) {
81524
+ if (fs58.existsSync(path82.join(projectDir, "go.mod"))) {
81243
81525
  return { command: ["go", "vet", "./..."], language: "go" };
81244
81526
  }
81245
- if (fs58.existsSync(path81.join(projectDir, "Cargo.toml"))) {
81527
+ if (fs58.existsSync(path82.join(projectDir, "Cargo.toml"))) {
81246
81528
  return { command: ["cargo", "check"], language: "rust" };
81247
81529
  }
81248
- if (fs58.existsSync(path81.join(projectDir, "pyproject.toml")) || fs58.existsSync(path81.join(projectDir, "requirements.txt")) || fs58.existsSync(path81.join(projectDir, "setup.py"))) {
81530
+ if (fs58.existsSync(path82.join(projectDir, "pyproject.toml")) || fs58.existsSync(path82.join(projectDir, "requirements.txt")) || fs58.existsSync(path82.join(projectDir, "setup.py"))) {
81249
81531
  return { command: null, language: "python" };
81250
81532
  }
81251
81533
  try {
@@ -81322,17 +81604,17 @@ init_schema();
81322
81604
  init_state();
81323
81605
  init_logger();
81324
81606
  import { appendFile as appendFile7, mkdir as mkdir15 } from "node:fs/promises";
81325
- import * as path83 from "node:path";
81607
+ import * as path84 from "node:path";
81326
81608
 
81327
81609
  // src/hooks/knowledge-application.ts
81328
81610
  init_logger();
81329
81611
  init_knowledge_store();
81330
81612
  var import_proper_lockfile7 = __toESM(require_proper_lockfile(), 1);
81331
- import { existsSync as existsSync43 } from "node:fs";
81613
+ import { existsSync as existsSync45 } from "node:fs";
81332
81614
  import { appendFile as appendFile6, mkdir as mkdir14, readFile as readFile13 } from "node:fs/promises";
81333
- import * as path82 from "node:path";
81615
+ import * as path83 from "node:path";
81334
81616
  function resolveApplicationLogPath(directory) {
81335
- return path82.join(directory, ".swarm", "knowledge-application.jsonl");
81617
+ return path83.join(directory, ".swarm", "knowledge-application.jsonl");
81336
81618
  }
81337
81619
  var ACK_PATTERN = /KNOWLEDGE_(APPLIED|IGNORED|VIOLATED)\s*:\s*([0-9a-fA-F-]{8,64})(?:\s+reason\s*=\s*([^\n\r]+?))?(?=$|[\n\r]|\s+KNOWLEDGE_)/g;
81338
81620
  function parseAcknowledgments(text) {
@@ -81350,7 +81632,7 @@ function parseAcknowledgments(text) {
81350
81632
  }
81351
81633
  async function appendAudit(directory, record3) {
81352
81634
  const filePath = resolveApplicationLogPath(directory);
81353
- await mkdir14(path82.dirname(filePath), { recursive: true });
81635
+ await mkdir14(path83.dirname(filePath), { recursive: true });
81354
81636
  await appendFile6(filePath, `${JSON.stringify(record3)}
81355
81637
  `, "utf-8");
81356
81638
  }
@@ -81394,7 +81676,7 @@ async function bumpCountersBatch(directory, bumps) {
81394
81676
  if (applyOne(swarm))
81395
81677
  await rewriteKnowledge(swarmPath, swarm);
81396
81678
  const hivePath = resolveHiveKnowledgePath();
81397
- if (existsSync43(hivePath)) {
81679
+ if (existsSync45(hivePath)) {
81398
81680
  const hive = await readKnowledge(hivePath);
81399
81681
  if (applyOne(hive))
81400
81682
  await rewriteKnowledge(hivePath, hive);
@@ -81516,8 +81798,8 @@ async function knowledgeApplicationGateBefore(directory, input, config3) {
81516
81798
  }).catch(() => {});
81517
81799
  }
81518
81800
  async function writeWarnEvent(directory, record3) {
81519
- const filePath = path83.join(directory, ".swarm", "events.jsonl");
81520
- await mkdir15(path83.dirname(filePath), { recursive: true });
81801
+ const filePath = path84.join(directory, ".swarm", "events.jsonl");
81802
+ await mkdir15(path84.dirname(filePath), { recursive: true });
81521
81803
  await appendFile7(filePath, `${JSON.stringify(record3)}
81522
81804
  `, "utf-8");
81523
81805
  }
@@ -82018,7 +82300,7 @@ init_scope_persistence();
82018
82300
  init_state();
82019
82301
  init_delegation_gate();
82020
82302
  init_normalize_tool_name();
82021
- import * as path85 from "node:path";
82303
+ import * as path86 from "node:path";
82022
82304
  var WRITE_TOOLS = new Set(WRITE_TOOL_NAMES);
82023
82305
  function createScopeGuardHook(config3, directory, injectAdvisory) {
82024
82306
  const enabled = config3.enabled ?? true;
@@ -82076,13 +82358,13 @@ function createScopeGuardHook(config3, directory, injectAdvisory) {
82076
82358
  }
82077
82359
  function isFileInScope(filePath, scopeEntries, directory) {
82078
82360
  const dir = directory ?? process.cwd();
82079
- const resolvedFile = path85.resolve(dir, filePath);
82361
+ const resolvedFile = path86.resolve(dir, filePath);
82080
82362
  return scopeEntries.some((scope) => {
82081
- const resolvedScope = path85.resolve(dir, scope);
82363
+ const resolvedScope = path86.resolve(dir, scope);
82082
82364
  if (resolvedFile === resolvedScope)
82083
82365
  return true;
82084
- const rel = path85.relative(resolvedScope, resolvedFile);
82085
- return rel.length > 0 && !rel.startsWith("..") && !path85.isAbsolute(rel);
82366
+ const rel = path86.relative(resolvedScope, resolvedFile);
82367
+ return rel.length > 0 && !rel.startsWith("..") && !path86.isAbsolute(rel);
82086
82368
  });
82087
82369
  }
82088
82370
 
@@ -82134,7 +82416,7 @@ function createSelfReviewHook(config3, injectAdvisory) {
82134
82416
 
82135
82417
  // src/hooks/slop-detector.ts
82136
82418
  import * as fs61 from "node:fs";
82137
- import * as path86 from "node:path";
82419
+ import * as path87 from "node:path";
82138
82420
  var WRITE_EDIT_TOOLS = new Set([
82139
82421
  "write",
82140
82422
  "edit",
@@ -82184,7 +82466,7 @@ function walkFiles(dir, exts, deadline) {
82184
82466
  break;
82185
82467
  if (entry.isSymbolicLink())
82186
82468
  continue;
82187
- const full = path86.join(dir, entry.name);
82469
+ const full = path87.join(dir, entry.name);
82188
82470
  if (entry.isDirectory()) {
82189
82471
  if (entry.name === "node_modules" || entry.name === ".git")
82190
82472
  continue;
@@ -82199,7 +82481,7 @@ function walkFiles(dir, exts, deadline) {
82199
82481
  return results;
82200
82482
  }
82201
82483
  function checkDeadExports(content, projectDir, startTime) {
82202
- const hasPackageJson = fs61.existsSync(path86.join(projectDir, "package.json"));
82484
+ const hasPackageJson = fs61.existsSync(path87.join(projectDir, "package.json"));
82203
82485
  if (!hasPackageJson)
82204
82486
  return null;
82205
82487
  const exportMatches = content.matchAll(/^\+(?:export)\s+(?:function|class|const|type|interface)\s+(\w{3,})/gm);
@@ -82313,14 +82595,14 @@ function checkDuplicateUtility(content, projectDir, startTime, targetFile) {
82313
82595
  for (const utilDir of utilityDirs) {
82314
82596
  if (Date.now() > deadline)
82315
82597
  break;
82316
- const utilPath = path86.join(projectDir, utilDir);
82598
+ const utilPath = path87.join(projectDir, utilDir);
82317
82599
  if (!fs61.existsSync(utilPath))
82318
82600
  continue;
82319
82601
  const files = walkFiles(utilPath, [".ts", ".tsx", ".js", ".jsx"], deadline);
82320
82602
  for (const file3 of files) {
82321
82603
  if (Date.now() > deadline)
82322
82604
  break;
82323
- if (targetFile && path86.resolve(file3) === path86.resolve(targetFile))
82605
+ if (targetFile && path87.resolve(file3) === path87.resolve(targetFile))
82324
82606
  continue;
82325
82607
  try {
82326
82608
  const text = fs61.readFileSync(file3, "utf-8");
@@ -82458,14 +82740,14 @@ function createSteeringConsumedHook(directory) {
82458
82740
  // src/hooks/trajectory-logger.ts
82459
82741
  init_manager2();
82460
82742
  import * as fs64 from "node:fs/promises";
82461
- import * as path88 from "node:path";
82743
+ import * as path89 from "node:path";
82462
82744
 
82463
82745
  // src/prm/trajectory-store.ts
82464
82746
  init_utils2();
82465
82747
  import * as fs63 from "node:fs/promises";
82466
- import * as path87 from "node:path";
82748
+ import * as path88 from "node:path";
82467
82749
  function getTrajectoryPath(sessionId, directory) {
82468
- const relativePath = path87.join("trajectories", `${sessionId}.jsonl`);
82750
+ const relativePath = path88.join("trajectories", `${sessionId}.jsonl`);
82469
82751
  return validateSwarmPath(directory, relativePath);
82470
82752
  }
82471
82753
  var _inMemoryTrajectoryCache = new Map;
@@ -82484,7 +82766,7 @@ async function appendTrajectoryEntry(sessionId, entry, directory, maxLines = 100
82484
82766
  _inMemoryTrajectoryCache.set(sessionId, cached3);
82485
82767
  }
82486
82768
  const trajectoryPath = getTrajectoryPath(sessionId, directory);
82487
- await fs63.mkdir(path87.dirname(trajectoryPath), { recursive: true });
82769
+ await fs63.mkdir(path88.dirname(trajectoryPath), { recursive: true });
82488
82770
  const line = `${JSON.stringify(entry)}
82489
82771
  `;
82490
82772
  await fs63.appendFile(trajectoryPath, line, "utf-8");
@@ -82523,7 +82805,7 @@ async function cleanupOldTrajectoryFiles(directory, maxAgeDays = 7) {
82523
82805
  for (const entry of entries) {
82524
82806
  if (!entry.isFile())
82525
82807
  continue;
82526
- const filePath = path87.join(dirPath, entry.name);
82808
+ const filePath = path88.join(dirPath, entry.name);
82527
82809
  try {
82528
82810
  const stat8 = await fs63.stat(filePath);
82529
82811
  if (now - stat8.mtimeMs > cutoffMs) {
@@ -82715,10 +82997,10 @@ function createTrajectoryLoggerHook(config3, _directory) {
82715
82997
  elapsed_ms
82716
82998
  };
82717
82999
  const sanitized = sanitizeTaskId2(taskId);
82718
- const relativePath = path88.join("evidence", sanitized, "trajectory.jsonl");
83000
+ const relativePath = path89.join("evidence", sanitized, "trajectory.jsonl");
82719
83001
  const trajectoryPath = validateSwarmPath(_directory, relativePath);
82720
83002
  try {
82721
- await fs64.mkdir(path88.dirname(trajectoryPath), { recursive: true });
83003
+ await fs64.mkdir(path89.dirname(trajectoryPath), { recursive: true });
82722
83004
  const line = `${JSON.stringify(entry)}
82723
83005
  `;
82724
83006
  await fs64.appendFile(trajectoryPath, line, "utf-8");
@@ -83269,16 +83551,16 @@ init_telemetry();
83269
83551
 
83270
83552
  // src/prm/replay.ts
83271
83553
  import { promises as fs65 } from "node:fs";
83272
- import path89 from "node:path";
83554
+ import path90 from "node:path";
83273
83555
  function isPathSafe2(targetPath, basePath) {
83274
- const resolvedTarget = path89.resolve(targetPath);
83275
- const resolvedBase = path89.resolve(basePath);
83276
- const rel = path89.relative(resolvedBase, resolvedTarget);
83277
- return !rel.startsWith("..") && !path89.isAbsolute(rel);
83556
+ const resolvedTarget = path90.resolve(targetPath);
83557
+ const resolvedBase = path90.resolve(basePath);
83558
+ const rel = path90.relative(resolvedBase, resolvedTarget);
83559
+ return !rel.startsWith("..") && !path90.isAbsolute(rel);
83278
83560
  }
83279
83561
  function isWithinReplaysDir(targetPath) {
83280
- const resolved = path89.resolve(targetPath);
83281
- const parts2 = resolved.split(path89.sep);
83562
+ const resolved = path90.resolve(targetPath);
83563
+ const parts2 = resolved.split(path90.sep);
83282
83564
  for (let i2 = 0;i2 < parts2.length - 1; i2++) {
83283
83565
  if (parts2[i2] === ".swarm" && parts2[i2 + 1] === "replays") {
83284
83566
  return true;
@@ -83291,10 +83573,10 @@ function sanitizeFilename(input) {
83291
83573
  }
83292
83574
  async function startReplayRecording(sessionID, directory) {
83293
83575
  try {
83294
- const replayDir = path89.join(directory, ".swarm", "replays");
83576
+ const replayDir = path90.join(directory, ".swarm", "replays");
83295
83577
  const safeSessionID = sanitizeFilename(sessionID);
83296
83578
  const filename = `${safeSessionID}-${Date.now()}.jsonl`;
83297
- const filepath = path89.join(replayDir, filename);
83579
+ const filepath = path90.join(replayDir, filename);
83298
83580
  if (!isPathSafe2(filepath, replayDir)) {
83299
83581
  console.warn(`[replay] Invalid path detected - path traversal attempt blocked for session ${sessionID}`);
83300
83582
  return null;
@@ -83668,7 +83950,7 @@ init_telemetry();
83668
83950
  init_dist();
83669
83951
  init_create_tool();
83670
83952
  import * as fs66 from "node:fs";
83671
- import * as path90 from "node:path";
83953
+ import * as path91 from "node:path";
83672
83954
  init_path_security();
83673
83955
  var WINDOWS_RESERVED_NAMES2 = /^(con|prn|aux|nul|com[1-9]|lpt[1-9])(\.|:|$)/i;
83674
83956
  function containsWindowsAttacks2(str) {
@@ -83685,14 +83967,14 @@ function containsWindowsAttacks2(str) {
83685
83967
  }
83686
83968
  function isPathInWorkspace2(filePath, workspace) {
83687
83969
  try {
83688
- const resolvedPath = path90.resolve(workspace, filePath);
83970
+ const resolvedPath = path91.resolve(workspace, filePath);
83689
83971
  if (!fs66.existsSync(resolvedPath)) {
83690
83972
  return true;
83691
83973
  }
83692
83974
  const realWorkspace = fs66.realpathSync(workspace);
83693
83975
  const realResolvedPath = fs66.realpathSync(resolvedPath);
83694
- const relativePath = path90.relative(realWorkspace, realResolvedPath);
83695
- if (relativePath.startsWith("..") || path90.isAbsolute(relativePath)) {
83976
+ const relativePath = path91.relative(realWorkspace, realResolvedPath);
83977
+ if (relativePath.startsWith("..") || path91.isAbsolute(relativePath)) {
83696
83978
  return false;
83697
83979
  }
83698
83980
  return true;
@@ -83701,7 +83983,7 @@ function isPathInWorkspace2(filePath, workspace) {
83701
83983
  }
83702
83984
  }
83703
83985
  function processFile2(file3, cwd, exportedOnly) {
83704
- const ext = path90.extname(file3);
83986
+ const ext = path91.extname(file3);
83705
83987
  if (containsControlChars(file3)) {
83706
83988
  return {
83707
83989
  file: file3,
@@ -83734,7 +84016,7 @@ function processFile2(file3, cwd, exportedOnly) {
83734
84016
  errorType: "path-outside-workspace"
83735
84017
  };
83736
84018
  }
83737
- const fullPath = path90.join(cwd, file3);
84019
+ const fullPath = path91.join(cwd, file3);
83738
84020
  if (!fs66.existsSync(fullPath)) {
83739
84021
  return {
83740
84022
  file: file3,
@@ -84026,15 +84308,15 @@ init_task_id();
84026
84308
  init_create_tool();
84027
84309
  init_resolve_working_directory();
84028
84310
  import * as fs67 from "node:fs";
84029
- import * as path91 from "node:path";
84311
+ import * as path92 from "node:path";
84030
84312
  var EVIDENCE_DIR = ".swarm/evidence";
84031
84313
  function isValidTaskId3(taskId) {
84032
84314
  return isStrictTaskId(taskId);
84033
84315
  }
84034
84316
  function isPathWithinSwarm(filePath, workspaceRoot) {
84035
- const normalizedWorkspace = path91.resolve(workspaceRoot);
84036
- const swarmPath = path91.join(normalizedWorkspace, ".swarm", "evidence");
84037
- const normalizedPath = path91.resolve(filePath);
84317
+ const normalizedWorkspace = path92.resolve(workspaceRoot);
84318
+ const swarmPath = path92.join(normalizedWorkspace, ".swarm", "evidence");
84319
+ const normalizedPath = path92.resolve(filePath);
84038
84320
  return normalizedPath.startsWith(swarmPath);
84039
84321
  }
84040
84322
  function readEvidenceFile(evidencePath) {
@@ -84115,7 +84397,7 @@ var check_gate_status = createSwarmTool({
84115
84397
  };
84116
84398
  return JSON.stringify(errorResult, null, 2);
84117
84399
  }
84118
- const evidencePath = path91.join(directory, EVIDENCE_DIR, `${taskIdInput}.json`);
84400
+ const evidencePath = path92.join(directory, EVIDENCE_DIR, `${taskIdInput}.json`);
84119
84401
  if (!isPathWithinSwarm(evidencePath, directory)) {
84120
84402
  const errorResult = {
84121
84403
  taskId: taskIdInput,
@@ -84212,7 +84494,7 @@ init_state();
84212
84494
  init_create_tool();
84213
84495
  init_resolve_working_directory();
84214
84496
  import * as fs68 from "node:fs";
84215
- import * as path92 from "node:path";
84497
+ import * as path93 from "node:path";
84216
84498
  function extractMatches(regex, text) {
84217
84499
  return Array.from(text.matchAll(regex));
84218
84500
  }
@@ -84364,10 +84646,10 @@ async function executeCompletionVerify(args2, directory) {
84364
84646
  let hasFileReadFailure = false;
84365
84647
  for (const filePath of fileTargets) {
84366
84648
  const normalizedPath = filePath.replace(/\\/g, "/");
84367
- const resolvedPath = path92.resolve(directory, normalizedPath);
84368
- const projectRoot = path92.resolve(directory);
84369
- const relative20 = path92.relative(projectRoot, resolvedPath);
84370
- const withinProject = relative20 === "" || !relative20.startsWith("..") && !path92.isAbsolute(relative20);
84649
+ const resolvedPath = path93.resolve(directory, normalizedPath);
84650
+ const projectRoot = path93.resolve(directory);
84651
+ const relative20 = path93.relative(projectRoot, resolvedPath);
84652
+ const withinProject = relative20 === "" || !relative20.startsWith("..") && !path93.isAbsolute(relative20);
84371
84653
  if (!withinProject) {
84372
84654
  blockedTasks.push({
84373
84655
  task_id: task.id,
@@ -84422,8 +84704,8 @@ async function executeCompletionVerify(args2, directory) {
84422
84704
  blockedTasks
84423
84705
  };
84424
84706
  try {
84425
- const evidenceDir = path92.join(directory, ".swarm", "evidence", `${phase}`);
84426
- const evidencePath = path92.join(evidenceDir, "completion-verify.json");
84707
+ const evidenceDir = path93.join(directory, ".swarm", "evidence", `${phase}`);
84708
+ const evidencePath = path93.join(evidenceDir, "completion-verify.json");
84427
84709
  fs68.mkdirSync(evidenceDir, { recursive: true });
84428
84710
  const evidenceBundle = {
84429
84711
  schema_version: "1.0.0",
@@ -84500,11 +84782,11 @@ var completion_verify = createSwarmTool({
84500
84782
  // src/tools/complexity-hotspots.ts
84501
84783
  init_zod();
84502
84784
  import * as fs70 from "node:fs";
84503
- import * as path94 from "node:path";
84785
+ import * as path95 from "node:path";
84504
84786
 
84505
84787
  // src/quality/metrics.ts
84506
84788
  import * as fs69 from "node:fs";
84507
- import * as path93 from "node:path";
84789
+ import * as path94 from "node:path";
84508
84790
  var MAX_FILE_SIZE_BYTES4 = 256 * 1024;
84509
84791
  var MIN_DUPLICATION_LINES = 10;
84510
84792
  function estimateCyclomaticComplexity(content) {
@@ -84556,7 +84838,7 @@ async function computeComplexityDelta(files, workingDir) {
84556
84838
  let totalComplexity = 0;
84557
84839
  const analyzedFiles = [];
84558
84840
  for (const file3 of files) {
84559
- const fullPath = path93.isAbsolute(file3) ? file3 : path93.join(workingDir, file3);
84841
+ const fullPath = path94.isAbsolute(file3) ? file3 : path94.join(workingDir, file3);
84560
84842
  if (!fs69.existsSync(fullPath)) {
84561
84843
  continue;
84562
84844
  }
@@ -84679,7 +84961,7 @@ function countGoExports(content) {
84679
84961
  function getExportCountForFile(filePath) {
84680
84962
  try {
84681
84963
  const content = fs69.readFileSync(filePath, "utf-8");
84682
- const ext = path93.extname(filePath).toLowerCase();
84964
+ const ext = path94.extname(filePath).toLowerCase();
84683
84965
  switch (ext) {
84684
84966
  case ".ts":
84685
84967
  case ".tsx":
@@ -84705,7 +84987,7 @@ async function computePublicApiDelta(files, workingDir) {
84705
84987
  let totalExports = 0;
84706
84988
  const analyzedFiles = [];
84707
84989
  for (const file3 of files) {
84708
- const fullPath = path93.isAbsolute(file3) ? file3 : path93.join(workingDir, file3);
84990
+ const fullPath = path94.isAbsolute(file3) ? file3 : path94.join(workingDir, file3);
84709
84991
  if (!fs69.existsSync(fullPath)) {
84710
84992
  continue;
84711
84993
  }
@@ -84739,7 +85021,7 @@ async function computeDuplicationRatio(files, workingDir) {
84739
85021
  let duplicateLines = 0;
84740
85022
  const analyzedFiles = [];
84741
85023
  for (const file3 of files) {
84742
- const fullPath = path93.isAbsolute(file3) ? file3 : path93.join(workingDir, file3);
85024
+ const fullPath = path94.isAbsolute(file3) ? file3 : path94.join(workingDir, file3);
84743
85025
  if (!fs69.existsSync(fullPath)) {
84744
85026
  continue;
84745
85027
  }
@@ -84772,8 +85054,8 @@ function countCodeLines(content) {
84772
85054
  return lines.length;
84773
85055
  }
84774
85056
  function isTestFile(filePath) {
84775
- const basename12 = path93.basename(filePath);
84776
- const _ext = path93.extname(filePath).toLowerCase();
85057
+ const basename12 = path94.basename(filePath);
85058
+ const _ext = path94.extname(filePath).toLowerCase();
84777
85059
  const testPatterns = [
84778
85060
  ".test.",
84779
85061
  ".spec.",
@@ -84854,8 +85136,8 @@ function matchGlobSegment(globSegments, pathSegments) {
84854
85136
  }
84855
85137
  return gIndex === globSegments.length && pIndex === pathSegments.length;
84856
85138
  }
84857
- function matchesGlobSegment(path94, glob) {
84858
- const normalizedPath = path94.replace(/\\/g, "/");
85139
+ function matchesGlobSegment(path95, glob) {
85140
+ const normalizedPath = path95.replace(/\\/g, "/");
84859
85141
  const normalizedGlob = glob.replace(/\\/g, "/");
84860
85142
  if (normalizedPath.includes("//")) {
84861
85143
  return false;
@@ -84886,8 +85168,8 @@ function simpleGlobToRegex2(glob) {
84886
85168
  function hasGlobstar(glob) {
84887
85169
  return glob.includes("**");
84888
85170
  }
84889
- function globMatches(path94, glob) {
84890
- const normalizedPath = path94.replace(/\\/g, "/");
85171
+ function globMatches(path95, glob) {
85172
+ const normalizedPath = path95.replace(/\\/g, "/");
84891
85173
  if (!glob || glob === "") {
84892
85174
  if (normalizedPath.includes("//")) {
84893
85175
  return false;
@@ -84923,7 +85205,7 @@ function shouldExcludeFile(filePath, excludeGlobs) {
84923
85205
  async function computeTestToCodeRatio(workingDir, enforceGlobs, excludeGlobs) {
84924
85206
  let testLines = 0;
84925
85207
  let codeLines = 0;
84926
- const srcDir = path93.join(workingDir, "src");
85208
+ const srcDir = path94.join(workingDir, "src");
84927
85209
  if (fs69.existsSync(srcDir)) {
84928
85210
  await scanDirectoryForLines(srcDir, enforceGlobs, excludeGlobs, false, (lines) => {
84929
85211
  codeLines += lines;
@@ -84931,14 +85213,14 @@ async function computeTestToCodeRatio(workingDir, enforceGlobs, excludeGlobs) {
84931
85213
  }
84932
85214
  const possibleSrcDirs = ["lib", "app", "source", "core"];
84933
85215
  for (const dir of possibleSrcDirs) {
84934
- const dirPath = path93.join(workingDir, dir);
85216
+ const dirPath = path94.join(workingDir, dir);
84935
85217
  if (fs69.existsSync(dirPath)) {
84936
85218
  await scanDirectoryForLines(dirPath, enforceGlobs, excludeGlobs, false, (lines) => {
84937
85219
  codeLines += lines;
84938
85220
  });
84939
85221
  }
84940
85222
  }
84941
- const testsDir = path93.join(workingDir, "tests");
85223
+ const testsDir = path94.join(workingDir, "tests");
84942
85224
  if (fs69.existsSync(testsDir)) {
84943
85225
  await scanDirectoryForLines(testsDir, ["**"], ["node_modules", "dist"], true, (lines) => {
84944
85226
  testLines += lines;
@@ -84946,7 +85228,7 @@ async function computeTestToCodeRatio(workingDir, enforceGlobs, excludeGlobs) {
84946
85228
  }
84947
85229
  const possibleTestDirs = ["test", "__tests__", "specs"];
84948
85230
  for (const dir of possibleTestDirs) {
84949
- const dirPath = path93.join(workingDir, dir);
85231
+ const dirPath = path94.join(workingDir, dir);
84950
85232
  if (fs69.existsSync(dirPath) && dirPath !== testsDir) {
84951
85233
  await scanDirectoryForLines(dirPath, ["**"], ["node_modules", "dist"], true, (lines) => {
84952
85234
  testLines += lines;
@@ -84961,7 +85243,7 @@ async function scanDirectoryForLines(dirPath, includeGlobs, excludeGlobs, isTest
84961
85243
  try {
84962
85244
  const entries = fs69.readdirSync(dirPath, { withFileTypes: true });
84963
85245
  for (const entry of entries) {
84964
- const fullPath = path93.join(dirPath, entry.name);
85246
+ const fullPath = path94.join(dirPath, entry.name);
84965
85247
  if (entry.isDirectory()) {
84966
85248
  if (entry.name === "node_modules" || entry.name === "dist" || entry.name === "build" || entry.name === ".git") {
84967
85249
  continue;
@@ -84969,7 +85251,7 @@ async function scanDirectoryForLines(dirPath, includeGlobs, excludeGlobs, isTest
84969
85251
  await scanDirectoryForLines(fullPath, includeGlobs, excludeGlobs, isTestScan, callback);
84970
85252
  } else if (entry.isFile()) {
84971
85253
  const relativePath = fullPath.replace(`${dirPath}/`, "");
84972
- const ext = path93.extname(entry.name).toLowerCase();
85254
+ const ext = path94.extname(entry.name).toLowerCase();
84973
85255
  const validExts = [
84974
85256
  ".ts",
84975
85257
  ".tsx",
@@ -85220,7 +85502,7 @@ async function analyzeHotspots(days, topN, extensions, directory) {
85220
85502
  const extSet = new Set(extensions.map((e) => e.startsWith(".") ? e : `.${e}`));
85221
85503
  const filteredChurn = new Map;
85222
85504
  for (const [file3, count] of churnMap) {
85223
- const ext = path94.extname(file3).toLowerCase();
85505
+ const ext = path95.extname(file3).toLowerCase();
85224
85506
  if (extSet.has(ext)) {
85225
85507
  filteredChurn.set(file3, count);
85226
85508
  }
@@ -85231,7 +85513,7 @@ async function analyzeHotspots(days, topN, extensions, directory) {
85231
85513
  for (const [file3, churnCount] of filteredChurn) {
85232
85514
  let fullPath = file3;
85233
85515
  if (!fs70.existsSync(fullPath)) {
85234
- fullPath = path94.join(cwd, file3);
85516
+ fullPath = path95.join(cwd, file3);
85235
85517
  }
85236
85518
  const complexity = getComplexityForFile2(fullPath);
85237
85519
  if (complexity !== null) {
@@ -85400,12 +85682,12 @@ ${body2}`);
85400
85682
  // src/council/council-evidence-writer.ts
85401
85683
  import {
85402
85684
  appendFileSync as appendFileSync9,
85403
- existsSync as existsSync49,
85685
+ existsSync as existsSync51,
85404
85686
  mkdirSync as mkdirSync22,
85405
- readFileSync as readFileSync41,
85687
+ readFileSync as readFileSync42,
85406
85688
  writeFileSync as writeFileSync15
85407
85689
  } from "node:fs";
85408
- import { join as join80 } from "node:path";
85690
+ import { join as join81 } from "node:path";
85409
85691
  var EVIDENCE_DIR2 = ".swarm/evidence";
85410
85692
  var VALID_TASK_ID = /^\d+\.\d+(\.\d+)*$/;
85411
85693
  var COUNCIL_GATE_NAME = "council";
@@ -85439,13 +85721,13 @@ function writeCouncilEvidence(workingDir, synthesis) {
85439
85721
  if (!VALID_TASK_ID.test(synthesis.taskId)) {
85440
85722
  throw new Error(`writeCouncilEvidence: invalid taskId "${synthesis.taskId}" — must match N.M or N.M.P format`);
85441
85723
  }
85442
- const dir = join80(workingDir, EVIDENCE_DIR2);
85724
+ const dir = join81(workingDir, EVIDENCE_DIR2);
85443
85725
  mkdirSync22(dir, { recursive: true });
85444
- const filePath = join80(dir, `${synthesis.taskId}.json`);
85726
+ const filePath = join81(dir, `${synthesis.taskId}.json`);
85445
85727
  const existingRoot = Object.create(null);
85446
- if (existsSync49(filePath)) {
85728
+ if (existsSync51(filePath)) {
85447
85729
  try {
85448
- const parsed = JSON.parse(readFileSync41(filePath, "utf-8"));
85730
+ const parsed = JSON.parse(readFileSync42(filePath, "utf-8"));
85449
85731
  if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
85450
85732
  safeAssignOwnProps(existingRoot, parsed);
85451
85733
  }
@@ -85475,7 +85757,7 @@ function writeCouncilEvidence(workingDir, synthesis) {
85475
85757
  updated.required_gates = [];
85476
85758
  writeFileSync15(filePath, JSON.stringify(updated, null, 2));
85477
85759
  try {
85478
- const councilDir = join80(workingDir, ".swarm", "council");
85760
+ const councilDir = join81(workingDir, ".swarm", "council");
85479
85761
  mkdirSync22(councilDir, { recursive: true });
85480
85762
  const auditLine = JSON.stringify({
85481
85763
  round: synthesis.roundNumber,
@@ -85483,7 +85765,7 @@ function writeCouncilEvidence(workingDir, synthesis) {
85483
85765
  timestamp: synthesis.timestamp,
85484
85766
  vetoedBy: synthesis.vetoedBy
85485
85767
  });
85486
- appendFileSync9(join80(councilDir, `${synthesis.taskId}.rounds.jsonl`), `${auditLine}
85768
+ appendFileSync9(join81(councilDir, `${synthesis.taskId}.rounds.jsonl`), `${auditLine}
85487
85769
  `);
85488
85770
  } catch (auditError) {
85489
85771
  console.warn(`writeCouncilEvidence: failed to append round-history audit log: ${auditError instanceof Error ? auditError.message : String(auditError)}`);
@@ -85805,25 +86087,25 @@ function buildFinalCouncilFeedback(projectSummary, verdict, vetoedBy, requiredFi
85805
86087
  }
85806
86088
 
85807
86089
  // src/council/criteria-store.ts
85808
- import { existsSync as existsSync50, mkdirSync as mkdirSync23, readFileSync as readFileSync42, writeFileSync as writeFileSync16 } from "node:fs";
85809
- import { join as join81 } from "node:path";
86090
+ import { existsSync as existsSync52, mkdirSync as mkdirSync23, readFileSync as readFileSync43, writeFileSync as writeFileSync16 } from "node:fs";
86091
+ import { join as join82 } from "node:path";
85810
86092
  var COUNCIL_DIR = ".swarm/council";
85811
86093
  function writeCriteria(workingDir, taskId, criteria) {
85812
- const dir = join81(workingDir, COUNCIL_DIR);
86094
+ const dir = join82(workingDir, COUNCIL_DIR);
85813
86095
  mkdirSync23(dir, { recursive: true });
85814
86096
  const payload = {
85815
86097
  taskId,
85816
86098
  criteria,
85817
86099
  declaredAt: new Date().toISOString()
85818
86100
  };
85819
- writeFileSync16(join81(dir, `${safeId(taskId)}.json`), JSON.stringify(payload, null, 2));
86101
+ writeFileSync16(join82(dir, `${safeId(taskId)}.json`), JSON.stringify(payload, null, 2));
85820
86102
  }
85821
86103
  function readCriteria(workingDir, taskId) {
85822
- const filePath = join81(workingDir, COUNCIL_DIR, `${safeId(taskId)}.json`);
85823
- if (!existsSync50(filePath))
86104
+ const filePath = join82(workingDir, COUNCIL_DIR, `${safeId(taskId)}.json`);
86105
+ if (!existsSync52(filePath))
85824
86106
  return null;
85825
86107
  try {
85826
- const parsed = JSON.parse(readFileSync42(filePath, "utf-8"));
86108
+ const parsed = JSON.parse(readFileSync43(filePath, "utf-8"));
85827
86109
  if (parsed && typeof parsed === "object" && typeof parsed.taskId === "string" && Array.isArray(parsed.criteria)) {
85828
86110
  return parsed;
85829
86111
  }
@@ -85972,7 +86254,7 @@ var submit_council_verdicts = createSwarmTool({
85972
86254
  init_zod();
85973
86255
  init_loader();
85974
86256
  import * as fs71 from "node:fs";
85975
- import * as path95 from "node:path";
86257
+ import * as path96 from "node:path";
85976
86258
 
85977
86259
  // src/council/general-council-advisory.ts
85978
86260
  var ADVISORY_HEADER = "[general_council] (advisory; not blocking)";
@@ -86400,10 +86682,10 @@ var convene_general_council = createSwarmTool({
86400
86682
  const round1 = input.round1Responses;
86401
86683
  const round2 = input.round2Responses ?? [];
86402
86684
  const result = synthesizeGeneralCouncil(input.question, input.mode, round1, round2);
86403
- const evidenceDir = path95.join(workingDir, ".swarm", "council", "general");
86685
+ const evidenceDir = path96.join(workingDir, ".swarm", "council", "general");
86404
86686
  const safeTimestamp = result.timestamp.replace(/[:.]/g, "-");
86405
86687
  const evidenceFile = `${safeTimestamp}-${input.mode}.json`;
86406
- const evidencePath = path95.join(evidenceDir, evidenceFile);
86688
+ const evidencePath = path96.join(evidenceDir, evidenceFile);
86407
86689
  try {
86408
86690
  await fs71.promises.mkdir(evidenceDir, { recursive: true });
86409
86691
  await fs71.promises.writeFile(evidencePath, JSON.stringify(result, null, 2));
@@ -86648,7 +86930,7 @@ init_state();
86648
86930
  init_task_id();
86649
86931
  init_create_tool();
86650
86932
  import * as fs72 from "node:fs";
86651
- import * as path96 from "node:path";
86933
+ import * as path97 from "node:path";
86652
86934
  function validateTaskIdFormat2(taskId) {
86653
86935
  return validateTaskIdFormat(taskId);
86654
86936
  }
@@ -86722,8 +87004,8 @@ async function executeDeclareScope(args2, fallbackDir) {
86722
87004
  };
86723
87005
  }
86724
87006
  }
86725
- normalizedDir = path96.normalize(args2.working_directory);
86726
- const pathParts = normalizedDir.split(path96.sep);
87007
+ normalizedDir = path97.normalize(args2.working_directory);
87008
+ const pathParts = normalizedDir.split(path97.sep);
86727
87009
  if (pathParts.includes("..")) {
86728
87010
  return {
86729
87011
  success: false,
@@ -86733,10 +87015,10 @@ async function executeDeclareScope(args2, fallbackDir) {
86733
87015
  ]
86734
87016
  };
86735
87017
  }
86736
- const resolvedDir = path96.resolve(normalizedDir);
87018
+ const resolvedDir = path97.resolve(normalizedDir);
86737
87019
  try {
86738
87020
  const realPath = fs72.realpathSync(resolvedDir);
86739
- const planPath2 = path96.join(realPath, ".swarm", "plan.json");
87021
+ const planPath2 = path97.join(realPath, ".swarm", "plan.json");
86740
87022
  if (!fs72.existsSync(planPath2)) {
86741
87023
  return {
86742
87024
  success: false,
@@ -86760,7 +87042,7 @@ async function executeDeclareScope(args2, fallbackDir) {
86760
87042
  console.warn("[declare-scope] fallbackDir is undefined, falling back to process.cwd()");
86761
87043
  }
86762
87044
  const directory = normalizedDir || fallbackDir;
86763
- const planPath = path96.resolve(directory, ".swarm", "plan.json");
87045
+ const planPath = path97.resolve(directory, ".swarm", "plan.json");
86764
87046
  if (!fs72.existsSync(planPath)) {
86765
87047
  return {
86766
87048
  success: false,
@@ -86800,8 +87082,8 @@ async function executeDeclareScope(args2, fallbackDir) {
86800
87082
  const normalizeErrors = [];
86801
87083
  const dir = normalizedDir || fallbackDir || process.cwd();
86802
87084
  const mergedFiles = rawMergedFiles.map((file3) => {
86803
- if (path96.isAbsolute(file3)) {
86804
- const relativePath = path96.relative(dir, file3).replace(/\\/g, "/");
87085
+ if (path97.isAbsolute(file3)) {
87086
+ const relativePath = path97.relative(dir, file3).replace(/\\/g, "/");
86805
87087
  if (relativePath.startsWith("..")) {
86806
87088
  normalizeErrors.push(`Path '${file3}' resolves outside the project directory`);
86807
87089
  return file3;
@@ -86862,7 +87144,7 @@ var declare_scope = createSwarmTool({
86862
87144
  init_zod();
86863
87145
  import * as child_process7 from "node:child_process";
86864
87146
  import * as fs73 from "node:fs";
86865
- import * as path97 from "node:path";
87147
+ import * as path98 from "node:path";
86866
87148
  init_create_tool();
86867
87149
  var MAX_DIFF_LINES = 500;
86868
87150
  var DIFF_TIMEOUT_MS = 30000;
@@ -86891,20 +87173,20 @@ function validateBase(base) {
86891
87173
  function validatePaths(paths) {
86892
87174
  if (!paths)
86893
87175
  return null;
86894
- for (const path98 of paths) {
86895
- if (!path98 || path98.length === 0) {
87176
+ for (const path99 of paths) {
87177
+ if (!path99 || path99.length === 0) {
86896
87178
  return "empty path not allowed";
86897
87179
  }
86898
- if (path98.length > MAX_PATH_LENGTH) {
87180
+ if (path99.length > MAX_PATH_LENGTH) {
86899
87181
  return `path exceeds maximum length of ${MAX_PATH_LENGTH}`;
86900
87182
  }
86901
- if (SHELL_METACHARACTERS2.test(path98)) {
87183
+ if (SHELL_METACHARACTERS2.test(path99)) {
86902
87184
  return "path contains shell metacharacters";
86903
87185
  }
86904
- if (path98.startsWith("-")) {
87186
+ if (path99.startsWith("-")) {
86905
87187
  return 'path cannot start with "-" (option-like arguments not allowed)';
86906
87188
  }
86907
- if (CONTROL_CHAR_PATTERN2.test(path98)) {
87189
+ if (CONTROL_CHAR_PATTERN2.test(path99)) {
86908
87190
  return "path contains control characters";
86909
87191
  }
86910
87192
  }
@@ -87012,8 +87294,8 @@ var diff = createSwarmTool({
87012
87294
  if (parts2.length >= 3) {
87013
87295
  const additions = parseInt(parts2[0], 10) || 0;
87014
87296
  const deletions = parseInt(parts2[1], 10) || 0;
87015
- const path98 = parts2[2];
87016
- files.push({ path: path98, additions, deletions });
87297
+ const path99 = parts2[2];
87298
+ files.push({ path: path99, additions, deletions });
87017
87299
  }
87018
87300
  }
87019
87301
  const contractChanges = [];
@@ -87053,7 +87335,7 @@ var diff = createSwarmTool({
87053
87335
  } else if (base === "unstaged") {
87054
87336
  const oldRef = `:${file3.path}`;
87055
87337
  oldContent = fileExistsInRef(oldRef) ? getContentFromRef(oldRef) : "";
87056
- newContent = fs73.readFileSync(path97.join(directory, file3.path), "utf-8");
87338
+ newContent = fs73.readFileSync(path98.join(directory, file3.path), "utf-8");
87057
87339
  } else {
87058
87340
  const oldRef = `${base}:${file3.path}`;
87059
87341
  oldContent = fileExistsInRef(oldRef) ? getContentFromRef(oldRef) : "";
@@ -87128,7 +87410,7 @@ var diff = createSwarmTool({
87128
87410
  init_zod();
87129
87411
  import * as child_process8 from "node:child_process";
87130
87412
  import * as fs74 from "node:fs";
87131
- import * as path98 from "node:path";
87413
+ import * as path99 from "node:path";
87132
87414
  init_create_tool();
87133
87415
  var diff_summary = createSwarmTool({
87134
87416
  description: "Generate a filtered semantic diff summary from AST analysis. Returns SemanticDiffSummary with optional filtering by classification or riskLevel.",
@@ -87176,7 +87458,7 @@ var diff_summary = createSwarmTool({
87176
87458
  }
87177
87459
  try {
87178
87460
  let oldContent;
87179
- const newContent = fs74.readFileSync(path98.join(workingDir, filePath), "utf-8");
87461
+ const newContent = fs74.readFileSync(path99.join(workingDir, filePath), "utf-8");
87180
87462
  if (fileExistsInHead) {
87181
87463
  oldContent = child_process8.execFileSync("git", ["show", `HEAD:${filePath}`], {
87182
87464
  encoding: "utf-8",
@@ -87405,7 +87687,7 @@ init_zod();
87405
87687
  init_create_tool();
87406
87688
  init_path_security();
87407
87689
  import * as fs75 from "node:fs";
87408
- import * as path99 from "node:path";
87690
+ import * as path100 from "node:path";
87409
87691
  var MAX_FILE_SIZE_BYTES6 = 1024 * 1024;
87410
87692
  var MAX_EVIDENCE_FILES = 1000;
87411
87693
  var EVIDENCE_DIR3 = ".swarm/evidence";
@@ -87432,9 +87714,9 @@ function validateRequiredTypes(input) {
87432
87714
  return null;
87433
87715
  }
87434
87716
  function isPathWithinSwarm2(filePath, cwd) {
87435
- const normalizedCwd = path99.resolve(cwd);
87436
- const swarmPath = path99.join(normalizedCwd, ".swarm");
87437
- const normalizedPath = path99.resolve(filePath);
87717
+ const normalizedCwd = path100.resolve(cwd);
87718
+ const swarmPath = path100.join(normalizedCwd, ".swarm");
87719
+ const normalizedPath = path100.resolve(filePath);
87438
87720
  return normalizedPath.startsWith(swarmPath);
87439
87721
  }
87440
87722
  function parseCompletedTasks(planContent) {
@@ -87464,10 +87746,10 @@ function readEvidenceFiles(evidenceDir, _cwd) {
87464
87746
  if (!VALID_EVIDENCE_FILENAME_REGEX.test(filename)) {
87465
87747
  continue;
87466
87748
  }
87467
- const filePath = path99.join(evidenceDir, filename);
87749
+ const filePath = path100.join(evidenceDir, filename);
87468
87750
  try {
87469
- const resolvedPath = path99.resolve(filePath);
87470
- const evidenceDirResolved = path99.resolve(evidenceDir);
87751
+ const resolvedPath = path100.resolve(filePath);
87752
+ const evidenceDirResolved = path100.resolve(evidenceDir);
87471
87753
  if (!resolvedPath.startsWith(evidenceDirResolved)) {
87472
87754
  continue;
87473
87755
  }
@@ -87585,7 +87867,7 @@ var evidence_check = createSwarmTool({
87585
87867
  return JSON.stringify(errorResult, null, 2);
87586
87868
  }
87587
87869
  const requiredTypes = requiredTypesValue.split(",").map((t) => t.trim()).filter((t) => t.length > 0).map(normalizeEvidenceType);
87588
- const planPath = path99.join(cwd, PLAN_FILE);
87870
+ const planPath = path100.join(cwd, PLAN_FILE);
87589
87871
  if (!isPathWithinSwarm2(planPath, cwd)) {
87590
87872
  const errorResult = {
87591
87873
  error: "plan file path validation failed",
@@ -87617,7 +87899,7 @@ var evidence_check = createSwarmTool({
87617
87899
  };
87618
87900
  return JSON.stringify(result2, null, 2);
87619
87901
  }
87620
- const evidenceDir = path99.join(cwd, EVIDENCE_DIR3);
87902
+ const evidenceDir = path100.join(cwd, EVIDENCE_DIR3);
87621
87903
  const evidence = readEvidenceFiles(evidenceDir, cwd);
87622
87904
  const { tasksWithFullEvidence, gaps } = analyzeGaps(completedTasks, evidence, requiredTypes);
87623
87905
  const completeness = completedTasks.length > 0 ? Math.round(tasksWithFullEvidence.length / completedTasks.length * 100) / 100 : 1;
@@ -87635,7 +87917,7 @@ var evidence_check = createSwarmTool({
87635
87917
  init_zod();
87636
87918
  init_create_tool();
87637
87919
  import * as fs76 from "node:fs";
87638
- import * as path100 from "node:path";
87920
+ import * as path101 from "node:path";
87639
87921
  var EXT_MAP = {
87640
87922
  python: ".py",
87641
87923
  py: ".py",
@@ -87716,12 +87998,12 @@ var extract_code_blocks = createSwarmTool({
87716
87998
  if (prefix) {
87717
87999
  filename = `${prefix}_${filename}`;
87718
88000
  }
87719
- let filepath = path100.join(targetDir, filename);
87720
- const base = path100.basename(filepath, path100.extname(filepath));
87721
- const ext = path100.extname(filepath);
88001
+ let filepath = path101.join(targetDir, filename);
88002
+ const base = path101.basename(filepath, path101.extname(filepath));
88003
+ const ext = path101.extname(filepath);
87722
88004
  let counter = 1;
87723
88005
  while (fs76.existsSync(filepath)) {
87724
- filepath = path100.join(targetDir, `${base}_${counter}${ext}`);
88006
+ filepath = path101.join(targetDir, `${base}_${counter}${ext}`);
87725
88007
  counter++;
87726
88008
  }
87727
88009
  try {
@@ -87979,7 +88261,7 @@ init_zod();
87979
88261
  init_create_tool();
87980
88262
  init_path_security();
87981
88263
  import * as fs77 from "node:fs";
87982
- import * as path101 from "node:path";
88264
+ import * as path102 from "node:path";
87983
88265
  var MAX_FILE_PATH_LENGTH2 = 500;
87984
88266
  var MAX_SYMBOL_LENGTH = 256;
87985
88267
  var MAX_FILE_SIZE_BYTES7 = 1024 * 1024;
@@ -88027,7 +88309,7 @@ function validateSymbolInput(symbol3) {
88027
88309
  return null;
88028
88310
  }
88029
88311
  function isBinaryFile2(filePath, buffer) {
88030
- const ext = path101.extname(filePath).toLowerCase();
88312
+ const ext = path102.extname(filePath).toLowerCase();
88031
88313
  if (ext === ".json" || ext === ".md" || ext === ".txt") {
88032
88314
  return false;
88033
88315
  }
@@ -88051,15 +88333,15 @@ function parseImports(content, targetFile, targetSymbol) {
88051
88333
  const imports = [];
88052
88334
  let _resolvedTarget;
88053
88335
  try {
88054
- _resolvedTarget = path101.resolve(targetFile);
88336
+ _resolvedTarget = path102.resolve(targetFile);
88055
88337
  } catch {
88056
88338
  _resolvedTarget = targetFile;
88057
88339
  }
88058
- const targetBasename = path101.basename(targetFile, path101.extname(targetFile));
88340
+ const targetBasename = path102.basename(targetFile, path102.extname(targetFile));
88059
88341
  const targetWithExt = targetFile;
88060
88342
  const targetWithoutExt = targetFile.replace(/\.(ts|tsx|js|jsx|mjs|cjs)$/i, "");
88061
- const normalizedTargetWithExt = path101.normalize(targetWithExt).replace(/\\/g, "/");
88062
- const normalizedTargetWithoutExt = path101.normalize(targetWithoutExt).replace(/\\/g, "/");
88343
+ const normalizedTargetWithExt = path102.normalize(targetWithExt).replace(/\\/g, "/");
88344
+ const normalizedTargetWithoutExt = path102.normalize(targetWithoutExt).replace(/\\/g, "/");
88063
88345
  const importRegex = /import\s+(?:\{[\s\S]*?\}|(?:\*\s+as\s+\w+)|\w+)\s+from\s+['"`]([^'"`]+)['"`]|import\s+['"`]([^'"`]+)['"`]|require\s*\(\s*['"`]([^'"`]+)['"`]\s*\)/g;
88064
88346
  for (let match = importRegex.exec(content);match !== null; match = importRegex.exec(content)) {
88065
88347
  const modulePath = match[1] || match[2] || match[3];
@@ -88082,9 +88364,9 @@ function parseImports(content, targetFile, targetSymbol) {
88082
88364
  }
88083
88365
  const _normalizedModule = modulePath.replace(/^\.\//, "").replace(/^\.\.\\/, "../");
88084
88366
  let isMatch = false;
88085
- const _targetDir = path101.dirname(targetFile);
88086
- const targetExt = path101.extname(targetFile);
88087
- const targetBasenameNoExt = path101.basename(targetFile, targetExt);
88367
+ const _targetDir = path102.dirname(targetFile);
88368
+ const targetExt = path102.extname(targetFile);
88369
+ const targetBasenameNoExt = path102.basename(targetFile, targetExt);
88088
88370
  const moduleNormalized = modulePath.replace(/\\/g, "/").replace(/^\.\//, "");
88089
88371
  const moduleName = modulePath.split(/[/\\]/).pop() || "";
88090
88372
  const moduleNameNoExt = moduleName.replace(/\.(ts|tsx|js|jsx|mjs|cjs)$/i, "");
@@ -88152,10 +88434,10 @@ function findSourceFiles2(dir, files = [], stats = { skippedDirs: [], skippedFil
88152
88434
  entries.sort((a, b) => a.toLowerCase().localeCompare(b.toLowerCase()));
88153
88435
  for (const entry of entries) {
88154
88436
  if (SKIP_DIRECTORIES4.has(entry)) {
88155
- stats.skippedDirs.push(path101.join(dir, entry));
88437
+ stats.skippedDirs.push(path102.join(dir, entry));
88156
88438
  continue;
88157
88439
  }
88158
- const fullPath = path101.join(dir, entry);
88440
+ const fullPath = path102.join(dir, entry);
88159
88441
  let stat8;
88160
88442
  try {
88161
88443
  stat8 = fs77.statSync(fullPath);
@@ -88169,7 +88451,7 @@ function findSourceFiles2(dir, files = [], stats = { skippedDirs: [], skippedFil
88169
88451
  if (stat8.isDirectory()) {
88170
88452
  findSourceFiles2(fullPath, files, stats);
88171
88453
  } else if (stat8.isFile()) {
88172
- const ext = path101.extname(fullPath).toLowerCase();
88454
+ const ext = path102.extname(fullPath).toLowerCase();
88173
88455
  if (SUPPORTED_EXTENSIONS3.includes(ext)) {
88174
88456
  files.push(fullPath);
88175
88457
  }
@@ -88226,7 +88508,7 @@ var imports = createSwarmTool({
88226
88508
  return JSON.stringify(errorResult, null, 2);
88227
88509
  }
88228
88510
  try {
88229
- const targetFile = path101.resolve(file3);
88511
+ const targetFile = path102.resolve(file3);
88230
88512
  if (!fs77.existsSync(targetFile)) {
88231
88513
  const errorResult = {
88232
88514
  error: `target file not found: ${file3}`,
@@ -88248,7 +88530,7 @@ var imports = createSwarmTool({
88248
88530
  };
88249
88531
  return JSON.stringify(errorResult, null, 2);
88250
88532
  }
88251
- const baseDir = path101.dirname(targetFile);
88533
+ const baseDir = path102.dirname(targetFile);
88252
88534
  const scanStats = {
88253
88535
  skippedDirs: [],
88254
88536
  skippedFiles: 0,
@@ -88539,7 +88821,7 @@ init_zod();
88539
88821
  init_config();
88540
88822
  init_knowledge_store();
88541
88823
  init_create_tool();
88542
- import { existsSync as existsSync55 } from "node:fs";
88824
+ import { existsSync as existsSync57 } from "node:fs";
88543
88825
  var DEFAULT_LIMIT = 10;
88544
88826
  var MAX_LESSON_LENGTH = 200;
88545
88827
  var VALID_CATEGORIES3 = [
@@ -88609,14 +88891,14 @@ function validateLimit(limit) {
88609
88891
  }
88610
88892
  async function readSwarmKnowledge(directory) {
88611
88893
  const swarmPath = resolveSwarmKnowledgePath(directory);
88612
- if (!existsSync55(swarmPath)) {
88894
+ if (!existsSync57(swarmPath)) {
88613
88895
  return [];
88614
88896
  }
88615
88897
  return readKnowledge(swarmPath);
88616
88898
  }
88617
88899
  async function readHiveKnowledge() {
88618
88900
  const hivePath = resolveHiveKnowledgePath();
88619
- if (!existsSync55(hivePath)) {
88901
+ if (!existsSync57(hivePath)) {
88620
88902
  return [];
88621
88903
  }
88622
88904
  return readKnowledge(hivePath);
@@ -88851,22 +89133,22 @@ init_schema();
88851
89133
  init_qa_gate_profile();
88852
89134
  init_manager2();
88853
89135
  import * as fs82 from "node:fs";
88854
- import * as path106 from "node:path";
89136
+ import * as path107 from "node:path";
88855
89137
 
88856
89138
  // src/full-auto/phase-approval.ts
88857
89139
  init_utils2();
88858
89140
  init_logger();
88859
89141
  init_state2();
88860
89142
  import * as fs78 from "node:fs";
88861
- import * as path102 from "node:path";
89143
+ import * as path103 from "node:path";
88862
89144
  var APPROVAL_TTL_MS = 24 * 60 * 60 * 1000;
88863
89145
  function readEvidenceDir(directory, phase) {
88864
89146
  try {
88865
- const dirPath = validateSwarmPath(directory, path102.posix.join("evidence", String(phase)));
89147
+ const dirPath = validateSwarmPath(directory, path103.posix.join("evidence", String(phase)));
88866
89148
  if (!fs78.existsSync(dirPath))
88867
89149
  return [];
88868
89150
  const entries = fs78.readdirSync(dirPath);
88869
- return entries.filter((e) => e.startsWith("full-auto-") && e.endsWith(".json")).map((e) => path102.join(dirPath, e));
89151
+ return entries.filter((e) => e.startsWith("full-auto-") && e.endsWith(".json")).map((e) => path103.join(dirPath, e));
88870
89152
  } catch {
88871
89153
  return [];
88872
89154
  }
@@ -89005,16 +89287,16 @@ init_plan_schema();
89005
89287
  init_ledger();
89006
89288
  init_manager();
89007
89289
  import * as fs79 from "node:fs";
89008
- import * as path103 from "node:path";
89290
+ import * as path104 from "node:path";
89009
89291
  async function writeCheckpoint(directory) {
89010
89292
  try {
89011
89293
  const plan = await loadPlan(directory);
89012
89294
  if (!plan)
89013
89295
  return;
89014
- const swarmDir = path103.join(directory, ".swarm");
89296
+ const swarmDir = path104.join(directory, ".swarm");
89015
89297
  fs79.mkdirSync(swarmDir, { recursive: true });
89016
- const jsonPath = path103.join(swarmDir, "SWARM_PLAN.json");
89017
- const mdPath = path103.join(swarmDir, "SWARM_PLAN.md");
89298
+ const jsonPath = path104.join(swarmDir, "SWARM_PLAN.json");
89299
+ const mdPath = path104.join(swarmDir, "SWARM_PLAN.md");
89018
89300
  fs79.writeFileSync(jsonPath, JSON.stringify(plan, null, 2), "utf8");
89019
89301
  const md = derivePlanMarkdown(plan);
89020
89302
  fs79.writeFileSync(mdPath, md, "utf8");
@@ -89033,15 +89315,15 @@ init_telemetry();
89033
89315
  // src/turbo/lean/phase-ready.ts
89034
89316
  init_file_locks();
89035
89317
  import * as fs81 from "node:fs";
89036
- import * as path105 from "node:path";
89318
+ import * as path106 from "node:path";
89037
89319
 
89038
89320
  // src/turbo/lean/evidence.ts
89039
89321
  init_bun_compat();
89040
89322
  import { rmSync as rmSync5 } from "node:fs";
89041
89323
  import * as fs80 from "node:fs/promises";
89042
- import * as path104 from "node:path";
89324
+ import * as path105 from "node:path";
89043
89325
  function leanTurboEvidenceDir(directory, phase) {
89044
- return path104.join(directory, ".swarm", "evidence", String(phase), "lean-turbo");
89326
+ return path105.join(directory, ".swarm", "evidence", String(phase), "lean-turbo");
89045
89327
  }
89046
89328
  function validateLaneId(laneId) {
89047
89329
  if (laneId.length === 0) {
@@ -89063,16 +89345,16 @@ function validateLaneId(laneId) {
89063
89345
  function laneEvidencePath(directory, phase, laneId) {
89064
89346
  validateLaneId(laneId);
89065
89347
  const expectedDir = leanTurboEvidenceDir(directory, phase);
89066
- const resolvedPath = path104.resolve(path104.join(expectedDir, `${laneId}.json`));
89067
- const resolvedDir = path104.resolve(expectedDir);
89068
- if (!resolvedPath.startsWith(resolvedDir + path104.sep) && resolvedPath !== resolvedDir) {
89348
+ const resolvedPath = path105.resolve(path105.join(expectedDir, `${laneId}.json`));
89349
+ const resolvedDir = path105.resolve(expectedDir);
89350
+ if (!resolvedPath.startsWith(resolvedDir + path105.sep) && resolvedPath !== resolvedDir) {
89069
89351
  throw new Error(`Invalid laneId: path traversal detected (got "${laneId}")`);
89070
89352
  }
89071
89353
  return resolvedPath;
89072
89354
  }
89073
89355
  async function atomicWriteJson(filePath, data) {
89074
89356
  const content = JSON.stringify(data, null, 2);
89075
- const dir = path104.dirname(filePath);
89357
+ const dir = path105.dirname(filePath);
89076
89358
  await fs80.mkdir(dir, { recursive: true });
89077
89359
  const tempPath = `${filePath}.tmp.${process.pid}.${Date.now()}.${Math.random().toString(36).slice(2)}`;
89078
89360
  try {
@@ -89086,7 +89368,7 @@ async function atomicWriteJson(filePath, data) {
89086
89368
  }
89087
89369
  }
89088
89370
  function phaseEvidencePath(directory, phase) {
89089
- return path104.join(leanTurboEvidenceDir(directory, phase), "lean-turbo-phase.json");
89371
+ return path105.join(leanTurboEvidenceDir(directory, phase), "lean-turbo-phase.json");
89090
89372
  }
89091
89373
  async function writeLaneEvidence(directory, phase, evidence) {
89092
89374
  const targetPath = laneEvidencePath(directory, phase, evidence.laneId);
@@ -89130,7 +89412,7 @@ async function listLaneEvidence(directory, phase) {
89130
89412
  if (entry === "lean-turbo-phase.json") {
89131
89413
  continue;
89132
89414
  }
89133
- const filePath = path104.join(evidenceDir, entry);
89415
+ const filePath = path105.join(evidenceDir, entry);
89134
89416
  let content;
89135
89417
  try {
89136
89418
  content = await fs80.readFile(filePath, "utf-8");
@@ -89154,7 +89436,7 @@ var DEFAULT_CONFIG2 = {
89154
89436
  };
89155
89437
  function defaultReadPlanJson(dir) {
89156
89438
  try {
89157
- const planPath = path105.join(dir, ".swarm", "plan.json");
89439
+ const planPath = path106.join(dir, ".swarm", "plan.json");
89158
89440
  if (!fs81.existsSync(planPath))
89159
89441
  return null;
89160
89442
  const raw = fs81.readFileSync(planPath, "utf-8");
@@ -89169,7 +89451,7 @@ function defaultReadPlanJson(dir) {
89169
89451
  }
89170
89452
  function readReviewerEvidenceFromFile(directory, phase) {
89171
89453
  try {
89172
- const evidencePath = path105.join(directory, ".swarm", "evidence", String(phase), "lean-turbo-reviewer.json");
89454
+ const evidencePath = path106.join(directory, ".swarm", "evidence", String(phase), "lean-turbo-reviewer.json");
89173
89455
  if (!fs81.existsSync(evidencePath)) {
89174
89456
  return null;
89175
89457
  }
@@ -89189,7 +89471,7 @@ function readReviewerEvidenceFromFile(directory, phase) {
89189
89471
  }
89190
89472
  function readCriticEvidenceFromFile(directory, phase) {
89191
89473
  try {
89192
- const evidencePath = path105.join(directory, ".swarm", "evidence", String(phase), "lean-turbo-critic.json");
89474
+ const evidencePath = path106.join(directory, ".swarm", "evidence", String(phase), "lean-turbo-critic.json");
89193
89475
  if (!fs81.existsSync(evidencePath)) {
89194
89476
  return null;
89195
89477
  }
@@ -89208,7 +89490,7 @@ function readCriticEvidenceFromFile(directory, phase) {
89208
89490
  }
89209
89491
  }
89210
89492
  function listLaneEvidenceSync(directory, phase) {
89211
- const evidenceDir = path105.join(directory, ".swarm", "evidence", String(phase), "lean-turbo");
89493
+ const evidenceDir = path106.join(directory, ".swarm", "evidence", String(phase), "lean-turbo");
89212
89494
  let entries;
89213
89495
  try {
89214
89496
  entries = fs81.readdirSync(evidenceDir);
@@ -89278,7 +89560,7 @@ function verifyLeanTurboPhaseReady(directory, phase, sessionIDOrConfig, config3)
89278
89560
  ...DEFAULT_CONFIG2,
89279
89561
  ...actualConfig
89280
89562
  };
89281
- const statePath = path105.join(directory, ".swarm", "turbo-state.json");
89563
+ const statePath = path106.join(directory, ".swarm", "turbo-state.json");
89282
89564
  if (!fs81.existsSync(statePath)) {
89283
89565
  return {
89284
89566
  ok: false,
@@ -89466,7 +89748,7 @@ function verifyLeanTurboPhaseReady(directory, phase, sessionIDOrConfig, config3)
89466
89748
  }
89467
89749
  }
89468
89750
  if (mergedConfig.integrated_diff_required) {
89469
- const evidencePath = path105.join(directory, ".swarm", "evidence", String(phase), "lean-turbo-phase.json");
89751
+ const evidencePath = path106.join(directory, ".swarm", "evidence", String(phase), "lean-turbo-phase.json");
89470
89752
  let hasDiff = false;
89471
89753
  try {
89472
89754
  const content = fs81.readFileSync(evidencePath, "utf-8");
@@ -89739,7 +90021,7 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
89739
90021
  let driftCheckEnabled = true;
89740
90022
  let driftHasSpecMd = false;
89741
90023
  try {
89742
- const specMdPath = path106.join(dir, ".swarm", "spec.md");
90024
+ const specMdPath = path107.join(dir, ".swarm", "spec.md");
89743
90025
  driftHasSpecMd = fs82.existsSync(specMdPath);
89744
90026
  const gatePlan = await loadPlan(dir);
89745
90027
  if (gatePlan) {
@@ -89761,7 +90043,7 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
89761
90043
  } else {
89762
90044
  let phaseType;
89763
90045
  try {
89764
- const planPath = path106.join(dir, ".swarm", "plan.json");
90046
+ const planPath = path107.join(dir, ".swarm", "plan.json");
89765
90047
  if (fs82.existsSync(planPath)) {
89766
90048
  const planRaw = fs82.readFileSync(planPath, "utf-8");
89767
90049
  const plan = JSON.parse(planRaw);
@@ -89774,7 +90056,7 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
89774
90056
  warnings.push(`Phase ${phase} is annotated as 'non-code'. Drift verification was skipped per phase type annotation.`);
89775
90057
  } else {
89776
90058
  try {
89777
- const driftEvidencePath = path106.join(dir, ".swarm", "evidence", String(phase), "drift-verifier.json");
90059
+ const driftEvidencePath = path107.join(dir, ".swarm", "evidence", String(phase), "drift-verifier.json");
89778
90060
  let driftVerdictFound = false;
89779
90061
  let driftVerdictApproved = false;
89780
90062
  try {
@@ -89812,7 +90094,7 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
89812
90094
  let incompleteTaskCount = 0;
89813
90095
  let planParseable = false;
89814
90096
  try {
89815
- const planPath = path106.join(dir, ".swarm", "plan.json");
90097
+ const planPath = path107.join(dir, ".swarm", "plan.json");
89816
90098
  if (fs82.existsSync(planPath)) {
89817
90099
  const planRaw = fs82.readFileSync(planPath, "utf-8");
89818
90100
  const plan = JSON.parse(planRaw);
@@ -89879,7 +90161,7 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
89879
90161
  const overrides = session2?.qaGateSessionOverrides ?? {};
89880
90162
  const effective = getEffectiveGates(profile, overrides);
89881
90163
  if (effective.hallucination_guard === true) {
89882
- const hgPath = path106.join(dir, ".swarm", "evidence", String(phase), "hallucination-guard.json");
90164
+ const hgPath = path107.join(dir, ".swarm", "evidence", String(phase), "hallucination-guard.json");
89883
90165
  let hgVerdictFound = false;
89884
90166
  let hgVerdictApproved = false;
89885
90167
  try {
@@ -89951,7 +90233,7 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
89951
90233
  const overrides = session2?.qaGateSessionOverrides ?? {};
89952
90234
  const effective = getEffectiveGates(profile, overrides);
89953
90235
  if (effective.mutation_test === true) {
89954
- const mgPath = path106.join(dir, ".swarm", "evidence", String(phase), "mutation-gate.json");
90236
+ const mgPath = path107.join(dir, ".swarm", "evidence", String(phase), "mutation-gate.json");
89955
90237
  let mgVerdictFound = false;
89956
90238
  let mgVerdict;
89957
90239
  try {
@@ -90025,7 +90307,7 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
90025
90307
  const effective = getEffectiveGates(profile, overrides);
90026
90308
  if (effective.council_mode === true) {
90027
90309
  councilModeEnabled = true;
90028
- const pcPath = path106.join(dir, ".swarm", "evidence", String(phase), "phase-council.json");
90310
+ const pcPath = path107.join(dir, ".swarm", "evidence", String(phase), "phase-council.json");
90029
90311
  let pcVerdictFound = false;
90030
90312
  let _pcVerdict;
90031
90313
  let pcQuorumSize;
@@ -90233,7 +90515,7 @@ Advisory notes: ${advisoryNotes.join("; ")}` : "";
90233
90515
  const effective = getEffectiveGates(profile, overrides);
90234
90516
  if (effective.final_council === true) {
90235
90517
  finalCouncilEnabled = true;
90236
- const fcPath = path106.join(dir, ".swarm", "evidence", "final-council.json");
90518
+ const fcPath = path107.join(dir, ".swarm", "evidence", "final-council.json");
90237
90519
  let fcVerdictFound = false;
90238
90520
  let _fcVerdict;
90239
90521
  try {
@@ -90421,7 +90703,7 @@ Advisory notes: ${advisoryNotes.join("; ")}` : "";
90421
90703
  }
90422
90704
  if (retroFound && retroEntry?.lessons_learned && retroEntry.lessons_learned.length > 0) {
90423
90705
  try {
90424
- const projectName = path106.basename(dir);
90706
+ const projectName = path107.basename(dir);
90425
90707
  const curationResult = await curateAndStoreSwarm(retroEntry.lessons_learned, projectName, { phase_number: phase }, dir, knowledgeConfig);
90426
90708
  if (curationResult) {
90427
90709
  const sessionState = swarmState.agentSessions.get(sessionID);
@@ -90672,7 +90954,7 @@ Advisory notes: ${advisoryNotes.join("; ")}` : "";
90672
90954
  const phaseObj = rebuilt.phases.find((p) => p.id === phase);
90673
90955
  if (phaseObj) {
90674
90956
  phaseObj.status = "complete";
90675
- await savePlan(dir, rebuilt);
90957
+ await savePlanWithAutoAcknowledgedRemovals(dir, rebuilt, "phase_complete_rebuild_from_ledger", "phase-complete rebuild from ledger");
90676
90958
  try {
90677
90959
  await takeSnapshotEvent(dir, rebuilt).catch(() => {});
90678
90960
  } catch {}
@@ -90714,7 +90996,7 @@ Advisory notes: ${advisoryNotes.join("; ")}` : "";
90714
90996
  const phaseObj = rebuilt.phases.find((p) => p.id === phase);
90715
90997
  if (phaseObj) {
90716
90998
  phaseObj.status = "complete";
90717
- await savePlan(dir, rebuilt);
90999
+ await savePlanWithAutoAcknowledgedRemovals(dir, rebuilt, "phase_complete_rebuild_from_ledger", "phase-complete rebuild from ledger");
90718
91000
  try {
90719
91001
  await takeSnapshotEvent(dir, rebuilt).catch(() => {});
90720
91002
  } catch {}
@@ -90791,7 +91073,7 @@ init_utils();
90791
91073
  init_bun_compat();
90792
91074
  init_create_tool();
90793
91075
  import * as fs83 from "node:fs";
90794
- import * as path107 from "node:path";
91076
+ import * as path108 from "node:path";
90795
91077
  var MAX_OUTPUT_BYTES5 = 52428800;
90796
91078
  var AUDIT_TIMEOUT_MS = 120000;
90797
91079
  function isValidEcosystem(value) {
@@ -90819,16 +91101,16 @@ function validateArgs3(args2) {
90819
91101
  function detectEcosystems(directory) {
90820
91102
  const ecosystems = [];
90821
91103
  const cwd = directory;
90822
- if (fs83.existsSync(path107.join(cwd, "package.json"))) {
91104
+ if (fs83.existsSync(path108.join(cwd, "package.json"))) {
90823
91105
  ecosystems.push("npm");
90824
91106
  }
90825
- if (fs83.existsSync(path107.join(cwd, "pyproject.toml")) || fs83.existsSync(path107.join(cwd, "requirements.txt"))) {
91107
+ if (fs83.existsSync(path108.join(cwd, "pyproject.toml")) || fs83.existsSync(path108.join(cwd, "requirements.txt"))) {
90826
91108
  ecosystems.push("pip");
90827
91109
  }
90828
- if (fs83.existsSync(path107.join(cwd, "Cargo.toml"))) {
91110
+ if (fs83.existsSync(path108.join(cwd, "Cargo.toml"))) {
90829
91111
  ecosystems.push("cargo");
90830
91112
  }
90831
- if (fs83.existsSync(path107.join(cwd, "go.mod"))) {
91113
+ if (fs83.existsSync(path108.join(cwd, "go.mod"))) {
90832
91114
  ecosystems.push("go");
90833
91115
  }
90834
91116
  try {
@@ -90837,13 +91119,13 @@ function detectEcosystems(directory) {
90837
91119
  ecosystems.push("dotnet");
90838
91120
  }
90839
91121
  } catch {}
90840
- if (fs83.existsSync(path107.join(cwd, "Gemfile")) || fs83.existsSync(path107.join(cwd, "Gemfile.lock"))) {
91122
+ if (fs83.existsSync(path108.join(cwd, "Gemfile")) || fs83.existsSync(path108.join(cwd, "Gemfile.lock"))) {
90841
91123
  ecosystems.push("ruby");
90842
91124
  }
90843
- if (fs83.existsSync(path107.join(cwd, "pubspec.yaml"))) {
91125
+ if (fs83.existsSync(path108.join(cwd, "pubspec.yaml"))) {
90844
91126
  ecosystems.push("dart");
90845
91127
  }
90846
- if (fs83.existsSync(path107.join(cwd, "composer.lock"))) {
91128
+ if (fs83.existsSync(path108.join(cwd, "composer.lock"))) {
90847
91129
  ecosystems.push("composer");
90848
91130
  }
90849
91131
  return ecosystems;
@@ -91979,7 +92261,7 @@ var pkg_audit = createSwarmTool({
91979
92261
  init_zod();
91980
92262
  init_manager2();
91981
92263
  import * as fs84 from "node:fs";
91982
- import * as path108 from "node:path";
92264
+ import * as path109 from "node:path";
91983
92265
  init_utils();
91984
92266
  init_create_tool();
91985
92267
  var MAX_FILE_SIZE = 1024 * 1024;
@@ -92102,7 +92384,7 @@ function isScaffoldFile(filePath) {
92102
92384
  if (SCAFFOLD_PATH_PATTERNS.some((pattern) => pattern.test(normalizedPath))) {
92103
92385
  return true;
92104
92386
  }
92105
- const filename = path108.basename(filePath);
92387
+ const filename = path109.basename(filePath);
92106
92388
  if (SCAFFOLD_FILENAME_PATTERNS.some((pattern) => pattern.test(filename))) {
92107
92389
  return true;
92108
92390
  }
@@ -92119,7 +92401,7 @@ function isAllowedByGlobs(filePath, allowGlobs) {
92119
92401
  if (regex.test(normalizedPath)) {
92120
92402
  return true;
92121
92403
  }
92122
- const filename = path108.basename(filePath);
92404
+ const filename = path109.basename(filePath);
92123
92405
  const filenameRegex = new RegExp(`^${regexPattern}$`, "i");
92124
92406
  if (filenameRegex.test(filename)) {
92125
92407
  return true;
@@ -92128,7 +92410,7 @@ function isAllowedByGlobs(filePath, allowGlobs) {
92128
92410
  return false;
92129
92411
  }
92130
92412
  function isParserSupported(filePath) {
92131
- const ext = path108.extname(filePath).toLowerCase();
92413
+ const ext = path109.extname(filePath).toLowerCase();
92132
92414
  return SUPPORTED_PARSER_EXTENSIONS.has(ext);
92133
92415
  }
92134
92416
  function isPlanFile(filePath) {
@@ -92375,9 +92657,9 @@ async function placeholderScan(input, directory) {
92375
92657
  let filesScanned = 0;
92376
92658
  const filesWithFindings = new Set;
92377
92659
  for (const filePath of changed_files) {
92378
- const fullPath = path108.isAbsolute(filePath) ? filePath : path108.resolve(directory, filePath);
92379
- const resolvedDirectory = path108.resolve(directory);
92380
- if (!fullPath.startsWith(resolvedDirectory + path108.sep) && fullPath !== resolvedDirectory) {
92660
+ const fullPath = path109.isAbsolute(filePath) ? filePath : path109.resolve(directory, filePath);
92661
+ const resolvedDirectory = path109.resolve(directory);
92662
+ if (!fullPath.startsWith(resolvedDirectory + path109.sep) && fullPath !== resolvedDirectory) {
92381
92663
  continue;
92382
92664
  }
92383
92665
  if (!fs84.existsSync(fullPath)) {
@@ -92386,7 +92668,7 @@ async function placeholderScan(input, directory) {
92386
92668
  if (isAllowedByGlobs(filePath, allow_globs)) {
92387
92669
  continue;
92388
92670
  }
92389
- const relativeFilePath = path108.relative(directory, fullPath).replace(/\\/g, "/");
92671
+ const relativeFilePath = path109.relative(directory, fullPath).replace(/\\/g, "/");
92390
92672
  if (FILE_ALLOWLIST.some((allowed) => relativeFilePath.endsWith(allowed))) {
92391
92673
  continue;
92392
92674
  }
@@ -92458,7 +92740,7 @@ var placeholder_scan = createSwarmTool({
92458
92740
  });
92459
92741
  // src/tools/pre-check-batch.ts
92460
92742
  import * as fs88 from "node:fs";
92461
- import * as path112 from "node:path";
92743
+ import * as path113 from "node:path";
92462
92744
  init_zod();
92463
92745
  init_manager2();
92464
92746
  init_utils();
@@ -92599,7 +92881,7 @@ init_zod();
92599
92881
  init_manager2();
92600
92882
  init_detector();
92601
92883
  import * as fs87 from "node:fs";
92602
- import * as path111 from "node:path";
92884
+ import * as path112 from "node:path";
92603
92885
  import { extname as extname19 } from "node:path";
92604
92886
 
92605
92887
  // src/sast/rules/c.ts
@@ -93315,7 +93597,7 @@ function executeRulesSync(filePath, content, language) {
93315
93597
  // src/sast/semgrep.ts
93316
93598
  import * as child_process9 from "node:child_process";
93317
93599
  import * as fs85 from "node:fs";
93318
- import * as path109 from "node:path";
93600
+ import * as path110 from "node:path";
93319
93601
  var semgrepAvailableCache = null;
93320
93602
  var DEFAULT_RULES_DIR = ".swarm/semgrep-rules";
93321
93603
  var DEFAULT_TIMEOUT_MS3 = 30000;
@@ -93502,7 +93784,7 @@ async function runSemgrep(options) {
93502
93784
  }
93503
93785
  function getRulesDirectory(projectRoot) {
93504
93786
  if (projectRoot) {
93505
- return path109.resolve(projectRoot, DEFAULT_RULES_DIR);
93787
+ return path110.resolve(projectRoot, DEFAULT_RULES_DIR);
93506
93788
  }
93507
93789
  return DEFAULT_RULES_DIR;
93508
93790
  }
@@ -93523,24 +93805,24 @@ init_create_tool();
93523
93805
  init_utils2();
93524
93806
  import * as crypto9 from "node:crypto";
93525
93807
  import * as fs86 from "node:fs";
93526
- import * as path110 from "node:path";
93808
+ import * as path111 from "node:path";
93527
93809
  var BASELINE_SCHEMA_VERSION = "1.0.0";
93528
93810
  var MAX_BASELINE_FINDINGS = 2000;
93529
93811
  var MAX_BASELINE_BYTES = 2 * 1048576;
93530
93812
  var LOCK_RETRY_DELAYS_MS = [50, 100, 200, 400, 800];
93531
93813
  function normalizeFindingPath(directory, file3) {
93532
- const resolved = path110.isAbsolute(file3) ? file3 : path110.resolve(directory, file3);
93533
- const rel = path110.relative(path110.resolve(directory), resolved);
93814
+ const resolved = path111.isAbsolute(file3) ? file3 : path111.resolve(directory, file3);
93815
+ const rel = path111.relative(path111.resolve(directory), resolved);
93534
93816
  return rel.replace(/\\/g, "/");
93535
93817
  }
93536
93818
  function baselineRelPath(phase) {
93537
- return path110.join("evidence", String(phase), "sast-baseline.json");
93819
+ return path111.join("evidence", String(phase), "sast-baseline.json");
93538
93820
  }
93539
93821
  function tempRelPath(phase) {
93540
- return path110.join("evidence", String(phase), `sast-baseline.json.tmp.${Date.now()}.${process.pid}`);
93822
+ return path111.join("evidence", String(phase), `sast-baseline.json.tmp.${Date.now()}.${process.pid}`);
93541
93823
  }
93542
93824
  function lockRelPath(phase) {
93543
- return path110.join("evidence", String(phase), "sast-baseline.json.lock");
93825
+ return path111.join("evidence", String(phase), "sast-baseline.json.lock");
93544
93826
  }
93545
93827
  function getLine(lines, idx) {
93546
93828
  if (idx < 0 || idx >= lines.length)
@@ -93661,8 +93943,8 @@ async function captureOrMergeBaseline(directory, phase, findings, engine, scanne
93661
93943
  message: e instanceof Error ? e.message : "Path validation failed"
93662
93944
  };
93663
93945
  }
93664
- fs86.mkdirSync(path110.dirname(baselinePath), { recursive: true });
93665
- fs86.mkdirSync(path110.dirname(tempPath), { recursive: true });
93946
+ fs86.mkdirSync(path111.dirname(baselinePath), { recursive: true });
93947
+ fs86.mkdirSync(path111.dirname(tempPath), { recursive: true });
93666
93948
  const releaseLock = await acquireLock2(lockPath);
93667
93949
  try {
93668
93950
  let existing = null;
@@ -93935,9 +94217,9 @@ async function sastScan(input, directory, config3) {
93935
94217
  _filesSkipped++;
93936
94218
  continue;
93937
94219
  }
93938
- const resolvedPath = path111.isAbsolute(filePath) ? filePath : path111.resolve(directory, filePath);
93939
- const resolvedDirectory = path111.resolve(directory);
93940
- if (!resolvedPath.startsWith(resolvedDirectory + path111.sep) && resolvedPath !== resolvedDirectory) {
94220
+ const resolvedPath = path112.isAbsolute(filePath) ? filePath : path112.resolve(directory, filePath);
94221
+ const resolvedDirectory = path112.resolve(directory);
94222
+ if (!resolvedPath.startsWith(resolvedDirectory + path112.sep) && resolvedPath !== resolvedDirectory) {
93941
94223
  _filesSkipped++;
93942
94224
  continue;
93943
94225
  }
@@ -94252,18 +94534,18 @@ function validatePath(inputPath, baseDir, workspaceDir) {
94252
94534
  let resolved;
94253
94535
  const isWinAbs = isWindowsAbsolutePath(inputPath);
94254
94536
  if (isWinAbs) {
94255
- resolved = path112.win32.resolve(inputPath);
94256
- } else if (path112.isAbsolute(inputPath)) {
94257
- resolved = path112.resolve(inputPath);
94537
+ resolved = path113.win32.resolve(inputPath);
94538
+ } else if (path113.isAbsolute(inputPath)) {
94539
+ resolved = path113.resolve(inputPath);
94258
94540
  } else {
94259
- resolved = path112.resolve(baseDir, inputPath);
94541
+ resolved = path113.resolve(baseDir, inputPath);
94260
94542
  }
94261
- const workspaceResolved = path112.resolve(workspaceDir);
94543
+ const workspaceResolved = path113.resolve(workspaceDir);
94262
94544
  let relative24;
94263
94545
  if (isWinAbs) {
94264
- relative24 = path112.win32.relative(workspaceResolved, resolved);
94546
+ relative24 = path113.win32.relative(workspaceResolved, resolved);
94265
94547
  } else {
94266
- relative24 = path112.relative(workspaceResolved, resolved);
94548
+ relative24 = path113.relative(workspaceResolved, resolved);
94267
94549
  }
94268
94550
  if (relative24.startsWith("..")) {
94269
94551
  return "path traversal detected";
@@ -94328,7 +94610,7 @@ async function runLintOnFiles(linter, files, workspaceDir) {
94328
94610
  if (typeof file3 !== "string") {
94329
94611
  continue;
94330
94612
  }
94331
- const resolvedPath = path112.resolve(file3);
94613
+ const resolvedPath = path113.resolve(file3);
94332
94614
  const validationError = validatePath(resolvedPath, workspaceDir, workspaceDir);
94333
94615
  if (validationError) {
94334
94616
  continue;
@@ -94485,7 +94767,7 @@ async function runSecretscanWithFiles(files, directory) {
94485
94767
  skippedFiles++;
94486
94768
  continue;
94487
94769
  }
94488
- const resolvedPath = path112.resolve(file3);
94770
+ const resolvedPath = path113.resolve(file3);
94489
94771
  const validationError = validatePath(resolvedPath, directory, directory);
94490
94772
  if (validationError) {
94491
94773
  skippedFiles++;
@@ -94503,7 +94785,7 @@ async function runSecretscanWithFiles(files, directory) {
94503
94785
  };
94504
94786
  }
94505
94787
  for (const file3 of validatedFiles) {
94506
- const ext = path112.extname(file3).toLowerCase();
94788
+ const ext = path113.extname(file3).toLowerCase();
94507
94789
  if (DEFAULT_EXCLUDE_EXTENSIONS2.has(ext)) {
94508
94790
  skippedFiles++;
94509
94791
  continue;
@@ -94722,7 +95004,7 @@ function classifySastFindings(findings, changedLineRanges, directory) {
94722
95004
  const preexistingFindings = [];
94723
95005
  for (const finding of findings) {
94724
95006
  const filePath = finding.location.file;
94725
- const normalised = path112.relative(directory, filePath).replace(/\\/g, "/");
95007
+ const normalised = path113.relative(directory, filePath).replace(/\\/g, "/");
94726
95008
  const changedLines = changedLineRanges.get(normalised);
94727
95009
  if (changedLines?.has(finding.location.line)) {
94728
95010
  newFindings.push(finding);
@@ -94773,7 +95055,7 @@ async function runPreCheckBatch(input, workspaceDir, contextDir) {
94773
95055
  warn(`pre_check_batch: Invalid file path: ${file3}`);
94774
95056
  continue;
94775
95057
  }
94776
- changedFiles.push(path112.resolve(directory, file3));
95058
+ changedFiles.push(path113.resolve(directory, file3));
94777
95059
  }
94778
95060
  if (changedFiles.length === 0) {
94779
95061
  warn("pre_check_batch: No valid files after validation, skipping all tools (fail-closed)");
@@ -94974,7 +95256,7 @@ var pre_check_batch = createSwarmTool({
94974
95256
  };
94975
95257
  return JSON.stringify(errorResult, null, 2);
94976
95258
  }
94977
- const resolvedDirectory = path112.resolve(typedArgs.directory);
95259
+ const resolvedDirectory = path113.resolve(typedArgs.directory);
94978
95260
  const workspaceAnchor = resolvedDirectory;
94979
95261
  const dirError = validateDirectory2(resolvedDirectory, workspaceAnchor);
94980
95262
  if (dirError) {
@@ -95015,7 +95297,7 @@ var pre_check_batch = createSwarmTool({
95015
95297
  });
95016
95298
  // src/tools/repo-map.ts
95017
95299
  init_zod();
95018
- import * as path113 from "node:path";
95300
+ import * as path114 from "node:path";
95019
95301
  init_path_security();
95020
95302
  init_create_tool();
95021
95303
  var VALID_ACTIONS = [
@@ -95040,7 +95322,7 @@ function validateFile(p) {
95040
95322
  return "file contains control characters";
95041
95323
  if (containsPathTraversal(p))
95042
95324
  return "file contains path traversal";
95043
- if (path113.isAbsolute(p) || /^[a-zA-Z]:[\\/]/.test(p)) {
95325
+ if (path114.isAbsolute(p) || /^[a-zA-Z]:[\\/]/.test(p)) {
95044
95326
  return "file must be a workspace-relative path, not absolute";
95045
95327
  }
95046
95328
  return null;
@@ -95063,8 +95345,8 @@ function ok(action, payload) {
95063
95345
  }
95064
95346
  function toRelativeGraphPath(input, workspaceRoot) {
95065
95347
  const normalized = input.replace(/\\/g, "/");
95066
- if (path113.isAbsolute(normalized)) {
95067
- const rel = path113.relative(workspaceRoot, normalized).replace(/\\/g, "/");
95348
+ if (path114.isAbsolute(normalized)) {
95349
+ const rel = path114.relative(workspaceRoot, normalized).replace(/\\/g, "/");
95068
95350
  return normalizeGraphPath2(rel);
95069
95351
  }
95070
95352
  return normalizeGraphPath2(normalized);
@@ -95209,7 +95491,7 @@ var repo_map = createSwarmTool({
95209
95491
  init_zod();
95210
95492
  init_create_tool();
95211
95493
  import * as fs89 from "node:fs";
95212
- import * as path114 from "node:path";
95494
+ import * as path115 from "node:path";
95213
95495
  var SPEC_FILE = ".swarm/spec.md";
95214
95496
  var EVIDENCE_DIR4 = ".swarm/evidence";
95215
95497
  var OBLIGATION_KEYWORDS = ["MUST", "SHOULD", "SHALL"];
@@ -95278,7 +95560,7 @@ function readTouchedFiles(evidenceDir, phase, cwd) {
95278
95560
  return [];
95279
95561
  }
95280
95562
  for (const entry of entries) {
95281
- const entryPath = path114.join(evidenceDir, entry);
95563
+ const entryPath = path115.join(evidenceDir, entry);
95282
95564
  try {
95283
95565
  const stat8 = fs89.statSync(entryPath);
95284
95566
  if (!stat8.isDirectory()) {
@@ -95294,11 +95576,11 @@ function readTouchedFiles(evidenceDir, phase, cwd) {
95294
95576
  if (entryPhase !== String(phase)) {
95295
95577
  continue;
95296
95578
  }
95297
- const evidenceFilePath = path114.join(entryPath, "evidence.json");
95579
+ const evidenceFilePath = path115.join(entryPath, "evidence.json");
95298
95580
  try {
95299
- const resolvedPath = path114.resolve(evidenceFilePath);
95300
- const evidenceDirResolved = path114.resolve(evidenceDir);
95301
- if (!resolvedPath.startsWith(evidenceDirResolved + path114.sep)) {
95581
+ const resolvedPath = path115.resolve(evidenceFilePath);
95582
+ const evidenceDirResolved = path115.resolve(evidenceDir);
95583
+ if (!resolvedPath.startsWith(evidenceDirResolved + path115.sep)) {
95302
95584
  continue;
95303
95585
  }
95304
95586
  const stat8 = fs89.lstatSync(evidenceFilePath);
@@ -95332,7 +95614,7 @@ function readTouchedFiles(evidenceDir, phase, cwd) {
95332
95614
  if (Array.isArray(diffEntry.files_changed)) {
95333
95615
  for (const file3 of diffEntry.files_changed) {
95334
95616
  if (typeof file3 === "string") {
95335
- touchedFiles.add(path114.resolve(cwd, file3));
95617
+ touchedFiles.add(path115.resolve(cwd, file3));
95336
95618
  }
95337
95619
  }
95338
95620
  }
@@ -95345,8 +95627,8 @@ function readTouchedFiles(evidenceDir, phase, cwd) {
95345
95627
  }
95346
95628
  function searchFileForKeywords(filePath, keywords, cwd) {
95347
95629
  try {
95348
- const resolvedPath = path114.resolve(filePath);
95349
- const cwdResolved = path114.resolve(cwd);
95630
+ const resolvedPath = path115.resolve(filePath);
95631
+ const cwdResolved = path115.resolve(cwd);
95350
95632
  if (!resolvedPath.startsWith(cwdResolved)) {
95351
95633
  return false;
95352
95634
  }
@@ -95480,7 +95762,7 @@ var req_coverage = createSwarmTool({
95480
95762
  }, null, 2);
95481
95763
  }
95482
95764
  const cwd = inputDirectory || directory;
95483
- const specPath = path114.join(cwd, SPEC_FILE);
95765
+ const specPath = path115.join(cwd, SPEC_FILE);
95484
95766
  let specContent;
95485
95767
  try {
95486
95768
  specContent = fs89.readFileSync(specPath, "utf-8");
@@ -95507,7 +95789,7 @@ var req_coverage = createSwarmTool({
95507
95789
  message: "No FR requirements found in spec.md"
95508
95790
  }, null, 2);
95509
95791
  }
95510
- const evidenceDir = path114.join(cwd, EVIDENCE_DIR4);
95792
+ const evidenceDir = path115.join(cwd, EVIDENCE_DIR4);
95511
95793
  const touchedFiles = readTouchedFiles(evidenceDir, phase, cwd);
95512
95794
  const analyzedRequirements = [];
95513
95795
  let coveredCount = 0;
@@ -95533,7 +95815,7 @@ var req_coverage = createSwarmTool({
95533
95815
  requirements: analyzedRequirements
95534
95816
  };
95535
95817
  const reportFilename = `req-coverage-phase-${phase}.json`;
95536
- const reportPath = path114.join(evidenceDir, reportFilename);
95818
+ const reportPath = path115.join(evidenceDir, reportFilename);
95537
95819
  try {
95538
95820
  if (!fs89.existsSync(evidenceDir)) {
95539
95821
  fs89.mkdirSync(evidenceDir, { recursive: true });
@@ -95621,7 +95903,7 @@ init_qa_gate_profile();
95621
95903
  init_file_locks();
95622
95904
  import * as crypto10 from "node:crypto";
95623
95905
  import * as fs90 from "node:fs";
95624
- import * as path115 from "node:path";
95906
+ import * as path116 from "node:path";
95625
95907
  init_ledger();
95626
95908
  init_manager();
95627
95909
  init_state();
@@ -95699,8 +95981,8 @@ async function executeSavePlan(args2, fallbackDir) {
95699
95981
  };
95700
95982
  }
95701
95983
  if (args2.working_directory && fallbackDir) {
95702
- const resolvedTarget = path115.resolve(args2.working_directory);
95703
- const resolvedRoot = path115.resolve(fallbackDir);
95984
+ const resolvedTarget = path116.resolve(args2.working_directory);
95985
+ const resolvedRoot = path116.resolve(fallbackDir);
95704
95986
  let fallbackExists = false;
95705
95987
  try {
95706
95988
  fs90.accessSync(resolvedRoot, fs90.constants.F_OK);
@@ -95709,7 +95991,7 @@ async function executeSavePlan(args2, fallbackDir) {
95709
95991
  fallbackExists = false;
95710
95992
  }
95711
95993
  if (fallbackExists) {
95712
- const isSubdirectory = resolvedTarget.startsWith(resolvedRoot + path115.sep);
95994
+ const isSubdirectory = resolvedTarget.startsWith(resolvedRoot + path116.sep);
95713
95995
  if (isSubdirectory) {
95714
95996
  return {
95715
95997
  success: false,
@@ -95725,7 +96007,7 @@ async function executeSavePlan(args2, fallbackDir) {
95725
96007
  let specMtime;
95726
96008
  let specHash;
95727
96009
  if (process.env.SWARM_SKIP_SPEC_GATE !== "1") {
95728
- const specPath = path115.join(targetWorkspace, ".swarm", "spec.md");
96010
+ const specPath = path116.join(targetWorkspace, ".swarm", "spec.md");
95729
96011
  try {
95730
96012
  const stat8 = await fs90.promises.stat(specPath);
95731
96013
  specMtime = stat8.mtime.toISOString();
@@ -95741,7 +96023,7 @@ async function executeSavePlan(args2, fallbackDir) {
95741
96023
  }
95742
96024
  }
95743
96025
  if (process.env.SWARM_SKIP_GATE_SELECTION !== "1") {
95744
- const contextPath = path115.join(targetWorkspace, ".swarm", "context.md");
96026
+ const contextPath = path116.join(targetWorkspace, ".swarm", "context.md");
95745
96027
  let contextContent = "";
95746
96028
  try {
95747
96029
  contextContent = await fs90.promises.readFile(contextPath, "utf8");
@@ -95771,6 +96053,7 @@ async function executeSavePlan(args2, fallbackDir) {
95771
96053
  }
95772
96054
  const dir = targetWorkspace;
95773
96055
  const existingStatusMap = new Map;
96056
+ const priorTaskIds = new Set;
95774
96057
  let preservedExecutionProfile;
95775
96058
  {
95776
96059
  let existing = null;
@@ -95778,6 +96061,10 @@ async function executeSavePlan(args2, fallbackDir) {
95778
96061
  existing = await loadPlanJsonOnly(dir);
95779
96062
  } catch {}
95780
96063
  if (existing) {
96064
+ for (const phase of existing.phases) {
96065
+ for (const task of phase.tasks)
96066
+ priorTaskIds.add(task.id);
96067
+ }
95781
96068
  if (!args2.reset_statuses) {
95782
96069
  for (const phase of existing.phases) {
95783
96070
  for (const task of phase.tasks) {
@@ -95819,6 +96106,98 @@ async function executeSavePlan(args2, fallbackDir) {
95819
96106
  }
95820
96107
  resolvedProfile = parsed.data;
95821
96108
  }
96109
+ const incomingTaskIds = new Set;
96110
+ for (const phase of args2.phases) {
96111
+ for (const task of phase.tasks)
96112
+ incomingTaskIds.add(task.id);
96113
+ }
96114
+ const missingTaskIds = [];
96115
+ for (const id of priorTaskIds) {
96116
+ if (!incomingTaskIds.has(id))
96117
+ missingTaskIds.push(id);
96118
+ }
96119
+ const rawRemovedIds = args2.removed_task_ids ?? [];
96120
+ if (rawRemovedIds.length > 0) {
96121
+ const seen = new Set;
96122
+ for (const id of rawRemovedIds) {
96123
+ if (seen.has(id)) {
96124
+ return {
96125
+ success: false,
96126
+ message: "PLAN_TASK_REMOVAL_INVALID: removed_task_ids contains duplicate entries",
96127
+ errors: [`Duplicate id in removed_task_ids: "${id}"`],
96128
+ recovery_guidance: "Deduplicate removed_task_ids and retry save_plan."
96129
+ };
96130
+ }
96131
+ seen.add(id);
96132
+ }
96133
+ for (const id of rawRemovedIds) {
96134
+ if (incomingTaskIds.has(id)) {
96135
+ return {
96136
+ success: false,
96137
+ message: "PLAN_TASK_REMOVAL_INVALID: removed_task_ids contains a task that also appears in args.phases",
96138
+ errors: [
96139
+ `Task "${id}" appears in both removed_task_ids and args.phases — these are contradictory`
96140
+ ],
96141
+ recovery_guidance: "A task cannot be both kept and removed in the same save_plan call. Either drop it from args.phases or remove it from removed_task_ids."
96142
+ };
96143
+ }
96144
+ }
96145
+ for (const id of rawRemovedIds) {
96146
+ if (!priorTaskIds.has(id)) {
96147
+ return {
96148
+ success: false,
96149
+ message: "PLAN_TASK_REMOVAL_INVALID: removed_task_ids contains an id that was not in the prior plan",
96150
+ errors: [
96151
+ `Task "${id}" is in removed_task_ids but not present in the prior plan`
96152
+ ],
96153
+ recovery_guidance: "Re-read the prior plan and update removed_task_ids to only list tasks that actually existed."
96154
+ };
96155
+ }
96156
+ }
96157
+ }
96158
+ let resolvedRemovedIds = [...rawRemovedIds];
96159
+ let resolvedRemovalReason = args2.removal_reason;
96160
+ if (args2.reset_statuses === true && missingTaskIds.length > 0) {
96161
+ if (args2.confirm_destructive_reset !== true) {
96162
+ return {
96163
+ success: false,
96164
+ message: "PLAN_DESTRUCTIVE_RESET_NOT_CONFIRMED: reset_statuses with missing tasks requires confirm_destructive_reset: true",
96165
+ errors: [
96166
+ `reset_statuses: true would drop ${missingTaskIds.length} task(s) from the prior plan: ${missingTaskIds.join(", ")}`
96167
+ ],
96168
+ recovery_guidance: "Surface the list of dropped tasks to the user and confirm intent before retrying. " + "Pass confirm_destructive_reset: true (with reset_statuses: true) to acknowledge the destructive reset, " + "or list removed_task_ids explicitly with a removal_reason."
96169
+ };
96170
+ }
96171
+ if (rawRemovedIds.length === 0) {
96172
+ resolvedRemovedIds = [...missingTaskIds];
96173
+ resolvedRemovalReason = "destructive reset acknowledged";
96174
+ }
96175
+ }
96176
+ if (resolvedRemovedIds.length > 0) {
96177
+ const reason = (resolvedRemovalReason ?? "").trim();
96178
+ if (reason.length === 0) {
96179
+ return {
96180
+ success: false,
96181
+ message: "PLAN_TASK_REMOVAL_INVALID: removal_reason is required when removed_task_ids is non-empty",
96182
+ errors: ["removal_reason must be a non-empty, non-whitespace string"],
96183
+ recovery_guidance: "Provide a removal_reason describing why these tasks are being dropped."
96184
+ };
96185
+ }
96186
+ }
96187
+ if (missingTaskIds.length > 0) {
96188
+ const ackSet = new Set(resolvedRemovedIds);
96189
+ const unacked = missingTaskIds.filter((id) => !ackSet.has(id));
96190
+ if (unacked.length > 0) {
96191
+ return {
96192
+ success: false,
96193
+ message: "PLAN_TASK_REMOVAL_NOT_ACKNOWLEDGED: this save would silently drop tasks from the prior plan",
96194
+ errors: [
96195
+ `The following prior tasks are missing from the new save and were not listed in removed_task_ids: ${unacked.join(", ")}`
96196
+ ],
96197
+ recovery_guidance: "Re-read the current plan, then retry save_plan with " + `removed_task_ids: ${JSON.stringify(unacked)} and a non-empty removal_reason. ` + "Tasks not yet finished (status pending/in_progress/blocked) MUST NOT be removed without explicit user confirmation."
96198
+ };
96199
+ }
96200
+ }
95822
96201
  const plan = {
95823
96202
  schema_version: "1.0.0",
95824
96203
  title: args2.title,
@@ -95865,7 +96244,14 @@ async function executeSavePlan(args2, fallbackDir) {
95865
96244
  }
95866
96245
  try {
95867
96246
  await savePlan(dir, plan, {
95868
- preserveCompletedStatuses: !args2.reset_statuses
96247
+ preserveCompletedStatuses: !args2.reset_statuses,
96248
+ ...resolvedRemovedIds.length > 0 ? {
96249
+ acknowledged_removals: {
96250
+ ids: resolvedRemovedIds,
96251
+ reason: (resolvedRemovalReason ?? "").trim(),
96252
+ source: "save_plan_tool"
96253
+ }
96254
+ } : {}
95869
96255
  });
95870
96256
  const savedPlan = await loadPlanJsonOnly(dir);
95871
96257
  if (savedPlan) {
@@ -95894,7 +96280,7 @@ async function executeSavePlan(args2, fallbackDir) {
95894
96280
  }
95895
96281
  await writeCheckpoint(dir).catch(() => {});
95896
96282
  try {
95897
- const markerPath = path115.join(dir, ".swarm", ".plan-write-marker");
96283
+ const markerPath = path116.join(dir, ".swarm", ".plan-write-marker");
95898
96284
  const marker = JSON.stringify({
95899
96285
  source: "save_plan",
95900
96286
  timestamp: new Date().toISOString(),
@@ -95917,7 +96303,7 @@ async function executeSavePlan(args2, fallbackDir) {
95917
96303
  return {
95918
96304
  success: true,
95919
96305
  message: "Plan saved successfully",
95920
- plan_path: path115.join(dir, ".swarm", "plan.json"),
96306
+ plan_path: path116.join(dir, ".swarm", "plan.json"),
95921
96307
  phases_count: plan.phases.length,
95922
96308
  tasks_count: tasksCount,
95923
96309
  ...resolvedProfile !== undefined ? { execution_profile: resolvedProfile } : {},
@@ -95929,6 +96315,15 @@ async function executeSavePlan(args2, fallbackDir) {
95929
96315
  }
95930
96316
  }
95931
96317
  } catch (error93) {
96318
+ if (error93 instanceof PlanTaskRemovalNotAcknowledgedError) {
96319
+ const ids = error93.missingTasks.map((t) => t.id);
96320
+ return {
96321
+ success: false,
96322
+ message: "PLAN_TASK_REMOVAL_NOT_ACKNOWLEDGED: this save would silently drop tasks from the prior plan",
96323
+ errors: [error93.message],
96324
+ recovery_guidance: "Re-read the current plan, then retry save_plan with " + `removed_task_ids: ${JSON.stringify(ids)} and a non-empty removal_reason.`
96325
+ };
96326
+ }
95932
96327
  return {
95933
96328
  success: false,
95934
96329
  message: "Failed to save plan: retry with save_plan after resolving the error above",
@@ -95955,6 +96350,9 @@ var save_plan = createSwarmTool({
95955
96350
  })).min(1).describe("Implementation phases"),
95956
96351
  working_directory: exports_external.string().optional().describe("Working directory (explicit path, required - no fallback)"),
95957
96352
  reset_statuses: exports_external.boolean().optional().describe("When true, reset ALL task statuses to pending regardless of prior completion state. " + "Use only when deliberately re-planning a phase from scratch. " + "Default false (preserves existing task statuses across plan revisions)."),
96353
+ removed_task_ids: exports_external.array(exports_external.string()).optional().describe("Task IDs that are present in the prior plan but intentionally being " + "removed by this save. Every task missing from `phases` MUST be enumerated " + "here, otherwise save_plan rejects with PLAN_TASK_REMOVAL_NOT_ACKNOWLEDGED. " + "Tasks not yet finished (status pending/in_progress/blocked) MUST NOT be " + "removed without explicit user confirmation."),
96354
+ removal_reason: exports_external.string().optional().describe("Required when removed_task_ids is non-empty. Human-readable reason recorded " + "on each task_removed ledger event."),
96355
+ confirm_destructive_reset: exports_external.boolean().optional().describe("Required when reset_statuses is true AND at least one task is missing from " + "the new plan. Set true to acknowledge that the destructive reset drops " + "unfinished work. When set together with reset_statuses, save_plan auto-" + "populates removed_task_ids from the missing set."),
95958
96356
  execution_profile: exports_external.object({
95959
96357
  parallelization_enabled: exports_external.boolean().optional().describe("When true, enables parallel task dispatch for this plan. Default false (serial)."),
95960
96358
  max_concurrent_tasks: exports_external.number().int().min(1).max(64).optional().describe("Maximum tasks that may run concurrently when parallelization is enabled. Default 1."),
@@ -95970,7 +96368,7 @@ var save_plan = createSwarmTool({
95970
96368
  init_zod();
95971
96369
  init_manager2();
95972
96370
  import * as fs91 from "node:fs";
95973
- import * as path116 from "node:path";
96371
+ import * as path117 from "node:path";
95974
96372
 
95975
96373
  // src/sbom/detectors/index.ts
95976
96374
  init_utils();
@@ -96820,7 +97218,7 @@ function findManifestFiles(rootDir) {
96820
97218
  try {
96821
97219
  const entries = fs91.readdirSync(dir, { withFileTypes: true });
96822
97220
  for (const entry of entries) {
96823
- const fullPath = path116.join(dir, entry.name);
97221
+ const fullPath = path117.join(dir, entry.name);
96824
97222
  if (entry.name.startsWith(".") || entry.name === "node_modules" || entry.name === "dist" || entry.name === "build" || entry.name === "target") {
96825
97223
  continue;
96826
97224
  }
@@ -96829,7 +97227,7 @@ function findManifestFiles(rootDir) {
96829
97227
  } else if (entry.isFile()) {
96830
97228
  for (const pattern of patterns) {
96831
97229
  if (simpleGlobToRegex(pattern).test(entry.name)) {
96832
- manifestFiles.push(path116.relative(rootDir, fullPath));
97230
+ manifestFiles.push(path117.relative(rootDir, fullPath));
96833
97231
  break;
96834
97232
  }
96835
97233
  }
@@ -96847,11 +97245,11 @@ function findManifestFilesInDirs(directories, workingDir) {
96847
97245
  try {
96848
97246
  const entries = fs91.readdirSync(dir, { withFileTypes: true });
96849
97247
  for (const entry of entries) {
96850
- const fullPath = path116.join(dir, entry.name);
97248
+ const fullPath = path117.join(dir, entry.name);
96851
97249
  if (entry.isFile()) {
96852
97250
  for (const pattern of patterns) {
96853
97251
  if (simpleGlobToRegex(pattern).test(entry.name)) {
96854
- found.push(path116.relative(workingDir, fullPath));
97252
+ found.push(path117.relative(workingDir, fullPath));
96855
97253
  break;
96856
97254
  }
96857
97255
  }
@@ -96864,11 +97262,11 @@ function findManifestFilesInDirs(directories, workingDir) {
96864
97262
  function getDirectoriesFromChangedFiles(changedFiles, workingDir) {
96865
97263
  const dirs = new Set;
96866
97264
  for (const file3 of changedFiles) {
96867
- let currentDir = path116.dirname(file3);
97265
+ let currentDir = path117.dirname(file3);
96868
97266
  while (true) {
96869
- if (currentDir && currentDir !== "." && currentDir !== path116.sep) {
96870
- dirs.add(path116.join(workingDir, currentDir));
96871
- const parent = path116.dirname(currentDir);
97267
+ if (currentDir && currentDir !== "." && currentDir !== path117.sep) {
97268
+ dirs.add(path117.join(workingDir, currentDir));
97269
+ const parent = path117.dirname(currentDir);
96872
97270
  if (parent === currentDir)
96873
97271
  break;
96874
97272
  currentDir = parent;
@@ -96952,7 +97350,7 @@ var sbom_generate = createSwarmTool({
96952
97350
  const changedFiles = obj.changed_files;
96953
97351
  const relativeOutputDir = obj.output_dir || DEFAULT_OUTPUT_DIR;
96954
97352
  const workingDir = directory;
96955
- const outputDir = path116.isAbsolute(relativeOutputDir) ? relativeOutputDir : path116.join(workingDir, relativeOutputDir);
97353
+ const outputDir = path117.isAbsolute(relativeOutputDir) ? relativeOutputDir : path117.join(workingDir, relativeOutputDir);
96956
97354
  let manifestFiles = [];
96957
97355
  if (scope === "all") {
96958
97356
  manifestFiles = findManifestFiles(workingDir);
@@ -96975,7 +97373,7 @@ var sbom_generate = createSwarmTool({
96975
97373
  const processedFiles = [];
96976
97374
  for (const manifestFile of manifestFiles) {
96977
97375
  try {
96978
- const fullPath = path116.isAbsolute(manifestFile) ? manifestFile : path116.join(workingDir, manifestFile);
97376
+ const fullPath = path117.isAbsolute(manifestFile) ? manifestFile : path117.join(workingDir, manifestFile);
96979
97377
  if (!fs91.existsSync(fullPath)) {
96980
97378
  continue;
96981
97379
  }
@@ -96992,7 +97390,7 @@ var sbom_generate = createSwarmTool({
96992
97390
  const bom = generateCycloneDX(allComponents);
96993
97391
  const bomJson = serializeCycloneDX(bom);
96994
97392
  const filename = generateSbomFilename();
96995
- const outputPath = path116.join(outputDir, filename);
97393
+ const outputPath = path117.join(outputDir, filename);
96996
97394
  fs91.writeFileSync(outputPath, bomJson, "utf-8");
96997
97395
  const verdict = processedFiles.length > 0 ? "pass" : "pass";
96998
97396
  try {
@@ -97036,7 +97434,7 @@ var sbom_generate = createSwarmTool({
97036
97434
  init_zod();
97037
97435
  init_create_tool();
97038
97436
  import * as fs92 from "node:fs";
97039
- import * as path117 from "node:path";
97437
+ import * as path118 from "node:path";
97040
97438
  var SPEC_CANDIDATES = [
97041
97439
  "openapi.json",
97042
97440
  "openapi.yaml",
@@ -97068,12 +97466,12 @@ function normalizePath4(p) {
97068
97466
  }
97069
97467
  function discoverSpecFile(cwd, specFileArg) {
97070
97468
  if (specFileArg) {
97071
- const resolvedPath = path117.resolve(cwd, specFileArg);
97072
- const normalizedCwd = cwd.endsWith(path117.sep) ? cwd : cwd + path117.sep;
97469
+ const resolvedPath = path118.resolve(cwd, specFileArg);
97470
+ const normalizedCwd = cwd.endsWith(path118.sep) ? cwd : cwd + path118.sep;
97073
97471
  if (!resolvedPath.startsWith(normalizedCwd) && resolvedPath !== cwd) {
97074
97472
  throw new Error("Invalid spec_file: path traversal detected");
97075
97473
  }
97076
- const ext = path117.extname(resolvedPath).toLowerCase();
97474
+ const ext = path118.extname(resolvedPath).toLowerCase();
97077
97475
  if (!ALLOWED_EXTENSIONS.includes(ext)) {
97078
97476
  throw new Error(`Invalid spec_file: must end in .json, .yaml, or .yml, got ${ext}`);
97079
97477
  }
@@ -97087,7 +97485,7 @@ function discoverSpecFile(cwd, specFileArg) {
97087
97485
  return resolvedPath;
97088
97486
  }
97089
97487
  for (const candidate of SPEC_CANDIDATES) {
97090
- const candidatePath = path117.resolve(cwd, candidate);
97488
+ const candidatePath = path118.resolve(cwd, candidate);
97091
97489
  if (fs92.existsSync(candidatePath)) {
97092
97490
  const stats = fs92.statSync(candidatePath);
97093
97491
  if (stats.size <= MAX_SPEC_SIZE) {
@@ -97099,7 +97497,7 @@ function discoverSpecFile(cwd, specFileArg) {
97099
97497
  }
97100
97498
  function parseSpec(specFile) {
97101
97499
  const content = fs92.readFileSync(specFile, "utf-8");
97102
- const ext = path117.extname(specFile).toLowerCase();
97500
+ const ext = path118.extname(specFile).toLowerCase();
97103
97501
  if (ext === ".json") {
97104
97502
  return parseJsonSpec(content);
97105
97503
  }
@@ -97175,7 +97573,7 @@ function extractRoutes(cwd) {
97175
97573
  return;
97176
97574
  }
97177
97575
  for (const entry of entries) {
97178
- const fullPath = path117.join(dir, entry.name);
97576
+ const fullPath = path118.join(dir, entry.name);
97179
97577
  if (entry.isSymbolicLink()) {
97180
97578
  continue;
97181
97579
  }
@@ -97185,7 +97583,7 @@ function extractRoutes(cwd) {
97185
97583
  }
97186
97584
  walkDir(fullPath);
97187
97585
  } else if (entry.isFile()) {
97188
- const ext = path117.extname(entry.name).toLowerCase();
97586
+ const ext = path118.extname(entry.name).toLowerCase();
97189
97587
  const baseName = entry.name.toLowerCase();
97190
97588
  if (![".ts", ".js", ".mjs"].includes(ext)) {
97191
97589
  continue;
@@ -97353,7 +97751,7 @@ init_bun_compat();
97353
97751
  init_path_security();
97354
97752
  init_create_tool();
97355
97753
  import * as fs93 from "node:fs";
97356
- import * as path118 from "node:path";
97754
+ import * as path119 from "node:path";
97357
97755
  var DEFAULT_MAX_RESULTS = 100;
97358
97756
  var DEFAULT_MAX_LINES = 200;
97359
97757
  var REGEX_TIMEOUT_MS = 5000;
@@ -97389,11 +97787,11 @@ function containsWindowsAttacks3(str) {
97389
97787
  }
97390
97788
  function isPathInWorkspace3(filePath, workspace) {
97391
97789
  try {
97392
- const resolvedPath = path118.resolve(workspace, filePath);
97790
+ const resolvedPath = path119.resolve(workspace, filePath);
97393
97791
  const realWorkspace = fs93.realpathSync(workspace);
97394
97792
  const realResolvedPath = fs93.realpathSync(resolvedPath);
97395
- const relativePath = path118.relative(realWorkspace, realResolvedPath);
97396
- if (relativePath.startsWith("..") || path118.isAbsolute(relativePath)) {
97793
+ const relativePath = path119.relative(realWorkspace, realResolvedPath);
97794
+ if (relativePath.startsWith("..") || path119.isAbsolute(relativePath)) {
97397
97795
  return false;
97398
97796
  }
97399
97797
  return true;
@@ -97406,11 +97804,11 @@ function validatePathForRead2(filePath, workspace) {
97406
97804
  }
97407
97805
  function findRgInEnvPath() {
97408
97806
  const searchPath = process.env.PATH ?? "";
97409
- for (const dir of searchPath.split(path118.delimiter)) {
97807
+ for (const dir of searchPath.split(path119.delimiter)) {
97410
97808
  if (!dir)
97411
97809
  continue;
97412
97810
  const isWindows = process.platform === "win32";
97413
- const candidate = path118.join(dir, isWindows ? "rg.exe" : "rg");
97811
+ const candidate = path119.join(dir, isWindows ? "rg.exe" : "rg");
97414
97812
  if (fs93.existsSync(candidate))
97415
97813
  return candidate;
97416
97814
  }
@@ -97540,8 +97938,8 @@ function collectFiles(dir, workspace, includeGlobs, excludeGlobs) {
97540
97938
  try {
97541
97939
  const entries = fs93.readdirSync(dir, { withFileTypes: true });
97542
97940
  for (const entry of entries) {
97543
- const fullPath = path118.join(dir, entry.name);
97544
- const relativePath = path118.relative(workspace, fullPath);
97941
+ const fullPath = path119.join(dir, entry.name);
97942
+ const relativePath = path119.relative(workspace, fullPath);
97545
97943
  if (!validatePathForRead2(fullPath, workspace)) {
97546
97944
  continue;
97547
97945
  }
@@ -97582,7 +97980,7 @@ async function fallbackSearch(opts) {
97582
97980
  const matches = [];
97583
97981
  let total = 0;
97584
97982
  for (const file3 of files) {
97585
- const fullPath = path118.join(opts.workspace, file3);
97983
+ const fullPath = path119.join(opts.workspace, file3);
97586
97984
  if (!validatePathForRead2(fullPath, opts.workspace)) {
97587
97985
  continue;
97588
97986
  }
@@ -97950,7 +98348,7 @@ init_config();
97950
98348
  init_schema();
97951
98349
  init_create_tool();
97952
98350
  import { mkdir as mkdir19, rename as rename8, writeFile as writeFile15 } from "node:fs/promises";
97953
- import * as path119 from "node:path";
98351
+ import * as path120 from "node:path";
97954
98352
  var MAX_SPEC_BYTES = 256 * 1024;
97955
98353
  var spec_write = createSwarmTool({
97956
98354
  description: "Write the canonical project spec to .swarm/spec.md. Atomic write, size-bounded (256 KiB), heading-required. Honors spec_writer.allow_spec_write.",
@@ -97991,8 +98389,8 @@ var spec_write = createSwarmTool({
97991
98389
  reason: 'spec must contain at least one top-level "# Heading"'
97992
98390
  }, null, 2);
97993
98391
  }
97994
- const target = path119.join(directory, ".swarm", "spec.md");
97995
- await mkdir19(path119.dirname(target), { recursive: true });
98392
+ const target = path120.join(directory, ".swarm", "spec.md");
98393
+ await mkdir19(path120.dirname(target), { recursive: true });
97996
98394
  const tmp = `${target}.tmp-${process.pid}-${Date.now()}`;
97997
98395
  let finalContent = content;
97998
98396
  if (mode === "append") {
@@ -98020,14 +98418,14 @@ ${content}
98020
98418
  init_zod();
98021
98419
  init_loader();
98022
98420
  import {
98023
- existsSync as existsSync68,
98421
+ existsSync as existsSync70,
98024
98422
  mkdirSync as mkdirSync29,
98025
- readFileSync as readFileSync60,
98423
+ readFileSync as readFileSync61,
98026
98424
  renameSync as renameSync19,
98027
98425
  unlinkSync as unlinkSync15,
98028
98426
  writeFileSync as writeFileSync23
98029
98427
  } from "node:fs";
98030
- import path120 from "node:path";
98428
+ import path121 from "node:path";
98031
98429
  init_create_tool();
98032
98430
  init_resolve_working_directory();
98033
98431
  var VerdictSchema2 = exports_external.object({
@@ -98157,9 +98555,9 @@ var submit_phase_council_verdicts = createSwarmTool({
98157
98555
  }
98158
98556
  });
98159
98557
  function getPhaseMutationGapFinding(phaseNumber, workingDir) {
98160
- const mutationGatePath = path120.join(workingDir, ".swarm", "evidence", String(phaseNumber), "mutation-gate.json");
98558
+ const mutationGatePath = path121.join(workingDir, ".swarm", "evidence", String(phaseNumber), "mutation-gate.json");
98161
98559
  try {
98162
- const raw = readFileSync60(mutationGatePath, "utf-8");
98560
+ const raw = readFileSync61(mutationGatePath, "utf-8");
98163
98561
  const parsed = JSON.parse(raw);
98164
98562
  const gateEntry = (parsed.entries ?? []).find((entry) => entry?.type === "mutation-gate");
98165
98563
  if (!gateEntry) {
@@ -98219,9 +98617,9 @@ function getPhaseMutationGapFinding(phaseNumber, workingDir) {
98219
98617
  }
98220
98618
  }
98221
98619
  function writePhaseCouncilEvidence(workingDir, synthesis) {
98222
- const evidenceDir = path120.join(workingDir, ".swarm", "evidence", String(synthesis.phaseNumber));
98620
+ const evidenceDir = path121.join(workingDir, ".swarm", "evidence", String(synthesis.phaseNumber));
98223
98621
  mkdirSync29(evidenceDir, { recursive: true });
98224
- const evidenceFile = path120.join(evidenceDir, "phase-council.json");
98622
+ const evidenceFile = path121.join(evidenceDir, "phase-council.json");
98225
98623
  const evidenceBundle = {
98226
98624
  entries: [
98227
98625
  {
@@ -98257,7 +98655,7 @@ function writePhaseCouncilEvidence(workingDir, synthesis) {
98257
98655
  writeFileSync23(tempFile, JSON.stringify(evidenceBundle, null, 2), "utf-8");
98258
98656
  renameSync19(tempFile, evidenceFile);
98259
98657
  } finally {
98260
- if (existsSync68(tempFile)) {
98658
+ if (existsSync70(tempFile)) {
98261
98659
  unlinkSync15(tempFile);
98262
98660
  }
98263
98661
  }
@@ -98307,7 +98705,7 @@ init_zod();
98307
98705
  init_path_security();
98308
98706
  init_create_tool();
98309
98707
  import * as fs94 from "node:fs";
98310
- import * as path121 from "node:path";
98708
+ import * as path122 from "node:path";
98311
98709
  var WINDOWS_RESERVED_NAMES4 = /^(con|prn|aux|nul|com[1-9]|lpt[1-9])(\.|:|$)/i;
98312
98710
  function containsWindowsAttacks4(str) {
98313
98711
  if (/:[^\\/]/.test(str))
@@ -98321,14 +98719,14 @@ function containsWindowsAttacks4(str) {
98321
98719
  }
98322
98720
  function isPathInWorkspace4(filePath, workspace) {
98323
98721
  try {
98324
- const resolvedPath = path121.resolve(workspace, filePath);
98722
+ const resolvedPath = path122.resolve(workspace, filePath);
98325
98723
  if (!fs94.existsSync(resolvedPath)) {
98326
98724
  return true;
98327
98725
  }
98328
98726
  const realWorkspace = fs94.realpathSync(workspace);
98329
98727
  const realResolvedPath = fs94.realpathSync(resolvedPath);
98330
- const relativePath = path121.relative(realWorkspace, realResolvedPath);
98331
- if (relativePath.startsWith("..") || path121.isAbsolute(relativePath)) {
98728
+ const relativePath = path122.relative(realWorkspace, realResolvedPath);
98729
+ if (relativePath.startsWith("..") || path122.isAbsolute(relativePath)) {
98332
98730
  return false;
98333
98731
  }
98334
98732
  return true;
@@ -98536,7 +98934,7 @@ var suggestPatch = createSwarmTool({
98536
98934
  });
98537
98935
  continue;
98538
98936
  }
98539
- const fullPath = path121.resolve(directory, change.file);
98937
+ const fullPath = path122.resolve(directory, change.file);
98540
98938
  if (!fs94.existsSync(fullPath)) {
98541
98939
  errors5.push({
98542
98940
  success: false,
@@ -98840,11 +99238,11 @@ var lean_turbo_acquire_locks = createSwarmTool({
98840
99238
  init_zod();
98841
99239
  init_constants();
98842
99240
  import * as fs96 from "node:fs";
98843
- import * as path123 from "node:path";
99241
+ import * as path124 from "node:path";
98844
99242
 
98845
99243
  // src/turbo/lean/conflicts.ts
98846
99244
  import * as fs95 from "node:fs";
98847
- import * as path122 from "node:path";
99245
+ import * as path123 from "node:path";
98848
99246
  var DEFAULT_GLOBAL_FILES = [
98849
99247
  "package.json",
98850
99248
  "package-lock.json",
@@ -98971,7 +99369,7 @@ function isProtectedPath2(normalizedPath) {
98971
99369
  return false;
98972
99370
  }
98973
99371
  function readTaskScopes(directory, taskId) {
98974
- const scopePath = path122.join(directory, ".swarm", "scopes", `scope-${taskId}.json`);
99372
+ const scopePath = path123.join(directory, ".swarm", "scopes", `scope-${taskId}.json`);
98975
99373
  try {
98976
99374
  if (!fs95.existsSync(scopePath)) {
98977
99375
  return null;
@@ -99359,7 +99757,7 @@ function createEmptyPlan(phaseNumber, planId) {
99359
99757
  // src/tools/lean-turbo-plan-lanes.ts
99360
99758
  init_create_tool();
99361
99759
  function readPlanJson(directory) {
99362
- const planPath = path123.join(directory, ".swarm", "plan.json");
99760
+ const planPath = path124.join(directory, ".swarm", "plan.json");
99363
99761
  if (!fs96.existsSync(planPath)) {
99364
99762
  return null;
99365
99763
  }
@@ -99414,7 +99812,7 @@ init_config();
99414
99812
  // src/turbo/lean/reviewer.ts
99415
99813
  init_state();
99416
99814
  import * as fs97 from "node:fs/promises";
99417
- import * as path124 from "node:path";
99815
+ import * as path125 from "node:path";
99418
99816
  init_state3();
99419
99817
  var DEFAULT_CONFIG3 = {
99420
99818
  reviewerAgent: "",
@@ -99530,9 +99928,9 @@ function parseReviewerVerdict(responseText) {
99530
99928
  return { verdict, reason };
99531
99929
  }
99532
99930
  async function writeReviewerEvidence(directory, phase, verdict, reason) {
99533
- const evidenceDir = path124.join(directory, ".swarm", "evidence", String(phase));
99931
+ const evidenceDir = path125.join(directory, ".swarm", "evidence", String(phase));
99534
99932
  await fs97.mkdir(evidenceDir, { recursive: true });
99535
- const evidencePath = path124.join(evidenceDir, "lean-turbo-reviewer.json");
99933
+ const evidencePath = path125.join(evidenceDir, "lean-turbo-reviewer.json");
99536
99934
  const content = JSON.stringify({
99537
99935
  phase,
99538
99936
  verdict,
@@ -100337,7 +100735,7 @@ var lean_turbo_status = createSwarmTool({
100337
100735
  init_spec_schema();
100338
100736
  init_create_tool();
100339
100737
  import * as fs98 from "node:fs";
100340
- import * as path125 from "node:path";
100738
+ import * as path126 from "node:path";
100341
100739
  var SPEC_FILE_NAME = "spec.md";
100342
100740
  var SWARM_DIR2 = ".swarm";
100343
100741
  var OBLIGATION_KEYWORDS2 = ["MUST", "SHALL", "SHOULD", "MAY"];
@@ -100390,7 +100788,7 @@ var lint_spec = createSwarmTool({
100390
100788
  async execute(_args, directory) {
100391
100789
  const errors5 = [];
100392
100790
  const warnings = [];
100393
- const specPath = path125.join(directory, SWARM_DIR2, SPEC_FILE_NAME);
100791
+ const specPath = path126.join(directory, SWARM_DIR2, SPEC_FILE_NAME);
100394
100792
  if (!fs98.existsSync(specPath)) {
100395
100793
  const result2 = {
100396
100794
  valid: false,
@@ -100461,12 +100859,12 @@ var lint_spec = createSwarmTool({
100461
100859
  // src/tools/mutation-test.ts
100462
100860
  init_zod();
100463
100861
  import * as fs99 from "node:fs";
100464
- import * as path127 from "node:path";
100862
+ import * as path128 from "node:path";
100465
100863
 
100466
100864
  // src/mutation/engine.ts
100467
100865
  import { spawnSync as spawnSync3 } from "node:child_process";
100468
100866
  import { unlinkSync as unlinkSync16, writeFileSync as writeFileSync24 } from "node:fs";
100469
- import * as path126 from "node:path";
100867
+ import * as path127 from "node:path";
100470
100868
 
100471
100869
  // src/mutation/equivalence.ts
100472
100870
  function isStaticallyEquivalent(originalCode, mutatedCode) {
@@ -100606,7 +101004,7 @@ async function executeMutation(patch, testCommand, _testFiles, workingDir) {
100606
101004
  let patchFile;
100607
101005
  try {
100608
101006
  const safeId2 = patch.id.replace(/[^a-zA-Z0-9_-]/g, "_");
100609
- patchFile = path126.join(workingDir, `.mutation_patch_${safeId2}.diff`);
101007
+ patchFile = path127.join(workingDir, `.mutation_patch_${safeId2}.diff`);
100610
101008
  try {
100611
101009
  writeFileSync24(patchFile, patch.patch);
100612
101010
  } catch (writeErr) {
@@ -101005,7 +101403,7 @@ var mutation_test = createSwarmTool({
101005
101403
  ];
101006
101404
  for (const filePath of uniquePaths) {
101007
101405
  try {
101008
- const resolvedPath = path127.resolve(cwd, filePath);
101406
+ const resolvedPath = path128.resolve(cwd, filePath);
101009
101407
  sourceFiles.set(filePath, fs99.readFileSync(resolvedPath, "utf-8"));
101010
101408
  } catch {}
101011
101409
  }
@@ -101025,7 +101423,7 @@ init_zod();
101025
101423
  init_manager2();
101026
101424
  init_detector();
101027
101425
  import * as fs100 from "node:fs";
101028
- import * as path128 from "node:path";
101426
+ import * as path129 from "node:path";
101029
101427
  init_create_tool();
101030
101428
  var MAX_FILE_SIZE2 = 2 * 1024 * 1024;
101031
101429
  var BINARY_CHECK_BYTES = 8192;
@@ -101091,7 +101489,7 @@ async function syntaxCheck(input, directory, config3) {
101091
101489
  if (languages?.length) {
101092
101490
  const lowerLangs = languages.map((l) => l.toLowerCase());
101093
101491
  filesToCheck = filesToCheck.filter((file3) => {
101094
- const ext = path128.extname(file3.path).toLowerCase();
101492
+ const ext = path129.extname(file3.path).toLowerCase();
101095
101493
  const langDef = getLanguageForExtension(ext);
101096
101494
  const fileProfile = getProfileForFile(file3.path);
101097
101495
  const langId = fileProfile?.id || langDef?.id;
@@ -101104,7 +101502,7 @@ async function syntaxCheck(input, directory, config3) {
101104
101502
  let skippedCount = 0;
101105
101503
  for (const fileInfo of filesToCheck) {
101106
101504
  const { path: filePath } = fileInfo;
101107
- const fullPath = path128.isAbsolute(filePath) ? filePath : path128.join(directory, filePath);
101505
+ const fullPath = path129.isAbsolute(filePath) ? filePath : path129.join(directory, filePath);
101108
101506
  const result = {
101109
101507
  path: filePath,
101110
101508
  language: "",
@@ -101153,7 +101551,7 @@ async function syntaxCheck(input, directory, config3) {
101153
101551
  results.push(result);
101154
101552
  continue;
101155
101553
  }
101156
- const ext = path128.extname(filePath).toLowerCase();
101554
+ const ext = path129.extname(filePath).toLowerCase();
101157
101555
  const langDef = getLanguageForExtension(ext);
101158
101556
  result.language = profile?.id || langDef?.id || "unknown";
101159
101557
  const errors5 = extractSyntaxErrors(parser, content);
@@ -101246,7 +101644,7 @@ init_utils();
101246
101644
  init_create_tool();
101247
101645
  init_path_security();
101248
101646
  import * as fs101 from "node:fs";
101249
- import * as path129 from "node:path";
101647
+ import * as path130 from "node:path";
101250
101648
  var MAX_TEXT_LENGTH = 200;
101251
101649
  var MAX_FILE_SIZE_BYTES11 = 1024 * 1024;
101252
101650
  var SUPPORTED_EXTENSIONS4 = new Set([
@@ -101312,9 +101710,9 @@ function validatePathsInput(paths, cwd) {
101312
101710
  return { error: "paths contains path traversal", resolvedPath: null };
101313
101711
  }
101314
101712
  try {
101315
- const resolvedPath = path129.resolve(paths);
101316
- const normalizedCwd = path129.resolve(cwd);
101317
- const normalizedResolved = path129.resolve(resolvedPath);
101713
+ const resolvedPath = path130.resolve(paths);
101714
+ const normalizedCwd = path130.resolve(cwd);
101715
+ const normalizedResolved = path130.resolve(resolvedPath);
101318
101716
  if (!normalizedResolved.startsWith(normalizedCwd)) {
101319
101717
  return {
101320
101718
  error: "paths must be within the current working directory",
@@ -101330,7 +101728,7 @@ function validatePathsInput(paths, cwd) {
101330
101728
  }
101331
101729
  }
101332
101730
  function isSupportedExtension(filePath) {
101333
- const ext = path129.extname(filePath).toLowerCase();
101731
+ const ext = path130.extname(filePath).toLowerCase();
101334
101732
  return SUPPORTED_EXTENSIONS4.has(ext);
101335
101733
  }
101336
101734
  function findSourceFiles3(dir, files = []) {
@@ -101345,7 +101743,7 @@ function findSourceFiles3(dir, files = []) {
101345
101743
  if (SKIP_DIRECTORIES5.has(entry)) {
101346
101744
  continue;
101347
101745
  }
101348
- const fullPath = path129.join(dir, entry);
101746
+ const fullPath = path130.join(dir, entry);
101349
101747
  let stat8;
101350
101748
  try {
101351
101749
  stat8 = fs101.statSync(fullPath);
@@ -101457,7 +101855,7 @@ var todo_extract = createSwarmTool({
101457
101855
  filesToScan.push(scanPath);
101458
101856
  } else {
101459
101857
  const errorResult = {
101460
- error: `unsupported file extension: ${path129.extname(scanPath)}`,
101858
+ error: `unsupported file extension: ${path130.extname(scanPath)}`,
101461
101859
  total: 0,
101462
101860
  byPriority: { high: 0, medium: 0, low: 0 },
101463
101861
  entries: []
@@ -101506,17 +101904,17 @@ init_schema();
101506
101904
  init_qa_gate_profile();
101507
101905
  init_gate_evidence();
101508
101906
  import * as fs105 from "node:fs";
101509
- import * as path133 from "node:path";
101907
+ import * as path134 from "node:path";
101510
101908
 
101511
101909
  // src/hooks/diff-scope.ts
101512
101910
  init_bun_compat();
101513
101911
  import * as fs103 from "node:fs";
101514
- import * as path131 from "node:path";
101912
+ import * as path132 from "node:path";
101515
101913
 
101516
101914
  // src/utils/gitignore-warning.ts
101517
101915
  init_bun_compat();
101518
101916
  import * as fs102 from "node:fs";
101519
- import * as path130 from "node:path";
101917
+ import * as path131 from "node:path";
101520
101918
  var _internals48 = { bunSpawn };
101521
101919
  var _swarmGitExcludedChecked = false;
101522
101920
  function fileCoversSwarm(content) {
@@ -101590,10 +101988,10 @@ async function ensureSwarmGitExcluded(directory, options = {}) {
101590
101988
  const excludeRelPath = excludePathRaw.trim();
101591
101989
  if (!excludeRelPath)
101592
101990
  return;
101593
- const excludePath = path130.isAbsolute(excludeRelPath) ? excludeRelPath : path130.join(directory, excludeRelPath);
101991
+ const excludePath = path131.isAbsolute(excludeRelPath) ? excludeRelPath : path131.join(directory, excludeRelPath);
101594
101992
  if (checkIgnoreExitCode !== 0) {
101595
101993
  try {
101596
- fs102.mkdirSync(path130.dirname(excludePath), { recursive: true });
101994
+ fs102.mkdirSync(path131.dirname(excludePath), { recursive: true });
101597
101995
  let existing = "";
101598
101996
  try {
101599
101997
  existing = fs102.readFileSync(excludePath, "utf8");
@@ -101637,7 +102035,7 @@ async function ensureSwarmGitExcluded(directory, options = {}) {
101637
102035
  var _internals49 = { bunSpawn };
101638
102036
  function getDeclaredScope(taskId, directory) {
101639
102037
  try {
101640
- const planPath = path131.join(directory, ".swarm", "plan.json");
102038
+ const planPath = path132.join(directory, ".swarm", "plan.json");
101641
102039
  if (!fs103.existsSync(planPath))
101642
102040
  return null;
101643
102041
  const raw = fs103.readFileSync(planPath, "utf-8");
@@ -101743,7 +102141,7 @@ init_telemetry();
101743
102141
  // src/turbo/lean/task-completion.ts
101744
102142
  init_file_locks();
101745
102143
  import * as fs104 from "node:fs";
101746
- import * as path132 from "node:path";
102144
+ import * as path133 from "node:path";
101747
102145
  var _internals50 = {
101748
102146
  listActiveLocks,
101749
102147
  verifyLeanTurboTaskCompletion
@@ -101762,7 +102160,7 @@ var TIER_3_PATTERNS = [
101762
102160
  ];
101763
102161
  function matchesTier3Pattern(files) {
101764
102162
  for (const file3 of files) {
101765
- const fileName = path132.basename(file3);
102163
+ const fileName = path133.basename(file3);
101766
102164
  for (const pattern of TIER_3_PATTERNS) {
101767
102165
  if (pattern.test(fileName)) {
101768
102166
  return true;
@@ -101774,7 +102172,7 @@ function matchesTier3Pattern(files) {
101774
102172
  function verifyLeanTurboTaskCompletion(directory, taskId, sessionID) {
101775
102173
  let persisted = null;
101776
102174
  try {
101777
- const statePath = path132.join(directory, ".swarm", "turbo-state.json");
102175
+ const statePath = path133.join(directory, ".swarm", "turbo-state.json");
101778
102176
  if (!fs104.existsSync(statePath)) {
101779
102177
  return {
101780
102178
  ok: false,
@@ -101858,11 +102256,11 @@ function verifyLeanTurboTaskCompletion(directory, taskId, sessionID) {
101858
102256
  };
101859
102257
  }
101860
102258
  const phase = runState.phase ?? 0;
101861
- const evidencePath = path132.join(directory, ".swarm", "evidence", String(phase), "lean-turbo", `${lane.laneId}.json`);
101862
- const expectedDir = path132.join(directory, ".swarm", "evidence", String(phase), "lean-turbo");
101863
- const resolvedPath = path132.resolve(evidencePath);
101864
- const resolvedDir = path132.resolve(expectedDir);
101865
- if (!resolvedPath.startsWith(resolvedDir + path132.sep) && resolvedPath !== resolvedDir) {
102259
+ const evidencePath = path133.join(directory, ".swarm", "evidence", String(phase), "lean-turbo", `${lane.laneId}.json`);
102260
+ const expectedDir = path133.join(directory, ".swarm", "evidence", String(phase), "lean-turbo");
102261
+ const resolvedPath = path133.resolve(evidencePath);
102262
+ const resolvedDir = path133.resolve(expectedDir);
102263
+ if (!resolvedPath.startsWith(resolvedDir + path133.sep) && resolvedPath !== resolvedDir) {
101866
102264
  return {
101867
102265
  ok: false,
101868
102266
  reason: `Lane ID causes path traversal: ${lane.laneId}`,
@@ -101902,7 +102300,7 @@ function verifyLeanTurboTaskCompletion(directory, taskId, sessionID) {
101902
102300
  }
101903
102301
  let filesTouched = [];
101904
102302
  try {
101905
- const planPath = path132.join(directory, ".swarm", "plan.json");
102303
+ const planPath = path133.join(directory, ".swarm", "plan.json");
101906
102304
  const planRaw = fs104.readFileSync(planPath, "utf-8");
101907
102305
  const plan = JSON.parse(planRaw);
101908
102306
  for (const planPhase of plan.phases ?? []) {
@@ -101985,7 +102383,7 @@ var TIER_3_PATTERNS2 = [
101985
102383
  ];
101986
102384
  function matchesTier3Pattern2(files) {
101987
102385
  for (const file3 of files) {
101988
- const fileName = path133.basename(file3);
102386
+ const fileName = path134.basename(file3);
101989
102387
  for (const pattern of TIER_3_PATTERNS2) {
101990
102388
  if (pattern.test(fileName)) {
101991
102389
  return true;
@@ -102017,7 +102415,7 @@ function checkReviewerGate(taskId, workingDirectory, stageBParallelEnabled = fal
102017
102415
  if (!skipStandardTurboBypass && hasActiveTurboMode()) {
102018
102416
  const resolvedDir2 = workingDirectory;
102019
102417
  try {
102020
- const planPath = path133.join(resolvedDir2, ".swarm", "plan.json");
102418
+ const planPath = path134.join(resolvedDir2, ".swarm", "plan.json");
102021
102419
  const planRaw = fs105.readFileSync(planPath, "utf-8");
102022
102420
  const plan = JSON.parse(planRaw);
102023
102421
  for (const planPhase of plan.phases ?? []) {
@@ -102084,7 +102482,7 @@ function checkReviewerGate(taskId, workingDirectory, stageBParallelEnabled = fal
102084
102482
  }
102085
102483
  try {
102086
102484
  const resolvedDir2 = workingDirectory;
102087
- const planPath = path133.join(resolvedDir2, ".swarm", "plan.json");
102485
+ const planPath = path134.join(resolvedDir2, ".swarm", "plan.json");
102088
102486
  const planRaw = fs105.readFileSync(planPath, "utf-8");
102089
102487
  const plan = JSON.parse(planRaw);
102090
102488
  for (const planPhase of plan.phases ?? []) {
@@ -102269,8 +102667,8 @@ async function executeUpdateTaskStatus(args2, fallbackDir, ctx) {
102269
102667
  };
102270
102668
  }
102271
102669
  }
102272
- normalizedDir = path133.normalize(args2.working_directory);
102273
- const pathParts = normalizedDir.split(path133.sep);
102670
+ normalizedDir = path134.normalize(args2.working_directory);
102671
+ const pathParts = normalizedDir.split(path134.sep);
102274
102672
  if (pathParts.includes("..")) {
102275
102673
  return {
102276
102674
  success: false,
@@ -102280,10 +102678,10 @@ async function executeUpdateTaskStatus(args2, fallbackDir, ctx) {
102280
102678
  ]
102281
102679
  };
102282
102680
  }
102283
- const resolvedDir = path133.resolve(normalizedDir);
102681
+ const resolvedDir = path134.resolve(normalizedDir);
102284
102682
  try {
102285
102683
  const realPath = fs105.realpathSync(resolvedDir);
102286
- const planPath = path133.join(realPath, ".swarm", "plan.json");
102684
+ const planPath = path134.join(realPath, ".swarm", "plan.json");
102287
102685
  if (!fs105.existsSync(planPath)) {
102288
102686
  return {
102289
102687
  success: false,
@@ -102315,8 +102713,8 @@ async function executeUpdateTaskStatus(args2, fallbackDir, ctx) {
102315
102713
  }
102316
102714
  if (args2.status === "in_progress") {
102317
102715
  try {
102318
- const evidencePath = path133.join(directory, ".swarm", "evidence", `${args2.task_id}.json`);
102319
- fs105.mkdirSync(path133.dirname(evidencePath), { recursive: true });
102716
+ const evidencePath = path134.join(directory, ".swarm", "evidence", `${args2.task_id}.json`);
102717
+ fs105.mkdirSync(path134.dirname(evidencePath), { recursive: true });
102320
102718
  const fd = fs105.openSync(evidencePath, "wx");
102321
102719
  let writeOk = false;
102322
102720
  try {
@@ -102340,7 +102738,7 @@ async function executeUpdateTaskStatus(args2, fallbackDir, ctx) {
102340
102738
  recoverTaskStateFromDelegations(args2.task_id);
102341
102739
  let phaseRequiresReviewer = true;
102342
102740
  try {
102343
- const planPath = path133.join(directory, ".swarm", "plan.json");
102741
+ const planPath = path134.join(directory, ".swarm", "plan.json");
102344
102742
  const planRaw = fs105.readFileSync(planPath, "utf-8");
102345
102743
  const plan = JSON.parse(planRaw);
102346
102744
  const taskPhase = plan.phases.find((p) => p.tasks.some((t) => t.id === args2.task_id));
@@ -102652,7 +103050,7 @@ init_ledger();
102652
103050
  init_manager();
102653
103051
  init_create_tool();
102654
103052
  import fs106 from "node:fs";
102655
- import path134 from "node:path";
103053
+ import path135 from "node:path";
102656
103054
  function normalizeVerdict(verdict) {
102657
103055
  switch (verdict) {
102658
103056
  case "APPROVED":
@@ -102700,7 +103098,7 @@ async function executeWriteDriftEvidence(args2, directory) {
102700
103098
  entries: [evidenceEntry]
102701
103099
  };
102702
103100
  const filename = "drift-verifier.json";
102703
- const relativePath = path134.join("evidence", String(phase), filename);
103101
+ const relativePath = path135.join("evidence", String(phase), filename);
102704
103102
  let validatedPath;
102705
103103
  try {
102706
103104
  validatedPath = validateSwarmPath(directory, relativePath);
@@ -102711,10 +103109,10 @@ async function executeWriteDriftEvidence(args2, directory) {
102711
103109
  message: error93 instanceof Error ? error93.message : "Failed to validate path"
102712
103110
  }, null, 2);
102713
103111
  }
102714
- const evidenceDir = path134.dirname(validatedPath);
103112
+ const evidenceDir = path135.dirname(validatedPath);
102715
103113
  try {
102716
103114
  await fs106.promises.mkdir(evidenceDir, { recursive: true });
102717
- const tempPath = path134.join(evidenceDir, `.${filename}.tmp`);
103115
+ const tempPath = path135.join(evidenceDir, `.${filename}.tmp`);
102718
103116
  await fs106.promises.writeFile(tempPath, JSON.stringify(evidenceContent, null, 2), "utf-8");
102719
103117
  await fs106.promises.rename(tempPath, validatedPath);
102720
103118
  let snapshotInfo;
@@ -102810,7 +103208,7 @@ var write_drift_evidence = createSwarmTool({
102810
103208
  init_zod();
102811
103209
  init_loader();
102812
103210
  import fs107 from "node:fs";
102813
- import path135 from "node:path";
103211
+ import path136 from "node:path";
102814
103212
  init_utils2();
102815
103213
  init_manager();
102816
103214
  init_create_tool();
@@ -102898,7 +103296,7 @@ async function executeWriteFinalCouncilEvidence(args2, directory) {
102898
103296
  timestamp: synthesis.timestamp
102899
103297
  };
102900
103298
  const filename = "final-council.json";
102901
- const relativePath = path135.join("evidence", filename);
103299
+ const relativePath = path136.join("evidence", filename);
102902
103300
  let validatedPath;
102903
103301
  try {
102904
103302
  validatedPath = validateSwarmPath(directory, relativePath);
@@ -102912,10 +103310,10 @@ async function executeWriteFinalCouncilEvidence(args2, directory) {
102912
103310
  const evidenceContent = {
102913
103311
  entries: [evidenceEntry]
102914
103312
  };
102915
- const evidenceDir = path135.dirname(validatedPath);
103313
+ const evidenceDir = path136.dirname(validatedPath);
102916
103314
  try {
102917
103315
  await fs107.promises.mkdir(evidenceDir, { recursive: true });
102918
- const tempPath = path135.join(evidenceDir, `.${filename}.tmp`);
103316
+ const tempPath = path136.join(evidenceDir, `.${filename}.tmp`);
102919
103317
  await fs107.promises.writeFile(tempPath, JSON.stringify(evidenceContent, null, 2), "utf-8");
102920
103318
  await fs107.promises.rename(tempPath, validatedPath);
102921
103319
  return JSON.stringify({
@@ -102974,7 +103372,7 @@ init_zod();
102974
103372
  init_utils2();
102975
103373
  init_create_tool();
102976
103374
  import fs108 from "node:fs";
102977
- import path136 from "node:path";
103375
+ import path137 from "node:path";
102978
103376
  function normalizeVerdict2(verdict) {
102979
103377
  switch (verdict) {
102980
103378
  case "APPROVED":
@@ -103022,7 +103420,7 @@ async function executeWriteHallucinationEvidence(args2, directory) {
103022
103420
  entries: [evidenceEntry]
103023
103421
  };
103024
103422
  const filename = "hallucination-guard.json";
103025
- const relativePath = path136.join("evidence", String(phase), filename);
103423
+ const relativePath = path137.join("evidence", String(phase), filename);
103026
103424
  let validatedPath;
103027
103425
  try {
103028
103426
  validatedPath = validateSwarmPath(directory, relativePath);
@@ -103033,10 +103431,10 @@ async function executeWriteHallucinationEvidence(args2, directory) {
103033
103431
  message: error93 instanceof Error ? error93.message : "Failed to validate path"
103034
103432
  }, null, 2);
103035
103433
  }
103036
- const evidenceDir = path136.dirname(validatedPath);
103434
+ const evidenceDir = path137.dirname(validatedPath);
103037
103435
  try {
103038
103436
  await fs108.promises.mkdir(evidenceDir, { recursive: true });
103039
- const tempPath = path136.join(evidenceDir, `.${filename}.tmp`);
103437
+ const tempPath = path137.join(evidenceDir, `.${filename}.tmp`);
103040
103438
  await fs108.promises.writeFile(tempPath, JSON.stringify(evidenceContent, null, 2), "utf-8");
103041
103439
  await fs108.promises.rename(tempPath, validatedPath);
103042
103440
  return JSON.stringify({
@@ -103085,7 +103483,7 @@ init_zod();
103085
103483
  init_utils2();
103086
103484
  init_create_tool();
103087
103485
  import fs109 from "node:fs";
103088
- import path137 from "node:path";
103486
+ import path138 from "node:path";
103089
103487
  function normalizeVerdict3(verdict) {
103090
103488
  switch (verdict) {
103091
103489
  case "PASS":
@@ -103159,7 +103557,7 @@ async function executeWriteMutationEvidence(args2, directory) {
103159
103557
  entries: [evidenceEntry]
103160
103558
  };
103161
103559
  const filename = "mutation-gate.json";
103162
- const relativePath = path137.join("evidence", String(phase), filename);
103560
+ const relativePath = path138.join("evidence", String(phase), filename);
103163
103561
  let validatedPath;
103164
103562
  try {
103165
103563
  validatedPath = validateSwarmPath(directory, relativePath);
@@ -103170,10 +103568,10 @@ async function executeWriteMutationEvidence(args2, directory) {
103170
103568
  message: error93 instanceof Error ? error93.message : "Failed to validate path"
103171
103569
  }, null, 2);
103172
103570
  }
103173
- const evidenceDir = path137.dirname(validatedPath);
103571
+ const evidenceDir = path138.dirname(validatedPath);
103174
103572
  try {
103175
103573
  await fs109.promises.mkdir(evidenceDir, { recursive: true });
103176
- const tempPath = path137.join(evidenceDir, `.${filename}.tmp`);
103574
+ const tempPath = path138.join(evidenceDir, `.${filename}.tmp`);
103177
103575
  await fs109.promises.writeFile(tempPath, JSON.stringify(evidenceContent, null, 2), "utf-8");
103178
103576
  await fs109.promises.rename(tempPath, validatedPath);
103179
103577
  return JSON.stringify({
@@ -103518,7 +103916,7 @@ async function initializeOpenCodeSwarm(ctx) {
103518
103916
  const { PreflightTriggerManager: PTM } = await Promise.resolve().then(() => (init_trigger(), exports_trigger));
103519
103917
  preflightTriggerManager = new PTM(automationConfig);
103520
103918
  const { AutomationStatusArtifact: ASA } = await Promise.resolve().then(() => (init_status_artifact(), exports_status_artifact));
103521
- const swarmDir = path139.resolve(ctx.directory, ".swarm");
103919
+ const swarmDir = path140.resolve(ctx.directory, ".swarm");
103522
103920
  statusArtifact = new ASA(swarmDir);
103523
103921
  statusArtifact.updateConfig(automationConfig.mode, automationConfig.capabilities);
103524
103922
  if (automationConfig.capabilities?.evidence_auto_summaries === true) {