opencode-swarm 7.19.0 → 7.19.1

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.1",
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") {
@@ -59956,6 +60101,25 @@ var init_context_budget_service = __esm(() => {
59956
60101
  });
59957
60102
 
59958
60103
  // src/services/status-service.ts
60104
+ import * as fsSync3 from "node:fs";
60105
+ import * as path54 from "node:path";
60106
+ function readSpecStalenessSnapshot(directory) {
60107
+ try {
60108
+ const p = path54.join(directory, ".swarm", "spec-staleness.json");
60109
+ if (!fsSync3.existsSync(p))
60110
+ return { stale: false };
60111
+ const raw = fsSync3.readFileSync(p, "utf-8");
60112
+ const parsed = JSON.parse(raw);
60113
+ return {
60114
+ stale: true,
60115
+ reason: typeof parsed?.reason === "string" ? parsed.reason : undefined,
60116
+ storedHash: typeof parsed?.specHash_plan === "string" ? parsed.specHash_plan : undefined,
60117
+ currentHash: typeof parsed?.specHash_current === "string" || parsed?.specHash_current === null ? parsed.specHash_current : undefined
60118
+ };
60119
+ } catch {
60120
+ return { stale: false };
60121
+ }
60122
+ }
59959
60123
  async function getStatusData(directory, agents) {
59960
60124
  const plan = await loadPlan(directory);
59961
60125
  let status;
@@ -60021,6 +60185,16 @@ async function getStatusData(directory, agents) {
60021
60185
  };
60022
60186
  }
60023
60187
  }
60188
+ const drift = readSpecStalenessSnapshot(directory);
60189
+ if (drift.stale) {
60190
+ status.specStale = true;
60191
+ status.specStaleReason = drift.reason;
60192
+ status.specStaleStoredHash = drift.storedHash;
60193
+ status.specStaleCurrentHash = drift.currentHash;
60194
+ } else if (plan && plan._specStale) {
60195
+ status.specStale = true;
60196
+ status.specStaleReason = plan._specStaleReason;
60197
+ }
60024
60198
  return enrichWithLeanTurbo(status, directory);
60025
60199
  }
60026
60200
  function enrichWithLeanTurbo(status, directory) {
@@ -60087,6 +60261,12 @@ function formatStatusMarkdown(status) {
60087
60261
  `**Tasks**: ${status.completedTasks}/${status.totalTasks} complete`,
60088
60262
  `**Agents**: ${status.agentCount} registered`
60089
60263
  ];
60264
+ if (status.specStale) {
60265
+ const reason = status.specStaleReason ?? "spec.md changed since plan saved";
60266
+ const stored = status.specStaleStoredHash ?? "unknown";
60267
+ const current = status.specStaleCurrentHash ?? "(spec.md missing)";
60268
+ lines.push("", `**Spec drift detected**: ${reason} (stored: ${stored}, current: ${current})`, "Run `/swarm clarify` to update the spec or `/swarm acknowledge-spec-drift` to dismiss.");
60269
+ }
60090
60270
  if (status.turboStrategy && status.turboStrategy !== "off") {
60091
60271
  lines.push("");
60092
60272
  if (status.turboStrategy === "lean") {
@@ -60136,6 +60316,18 @@ function formatStatusMarkdown(status) {
60136
60316
  async function handleStatusCommand(directory, agents) {
60137
60317
  const statusData = await getStatusData(directory, agents);
60138
60318
  if (!statusData.hasPlan) {
60319
+ if (statusData.specStale) {
60320
+ const reason = statusData.specStaleReason ?? "spec.md changed since plan saved";
60321
+ const stored = statusData.specStaleStoredHash ?? "unknown";
60322
+ const current = statusData.specStaleCurrentHash ?? "(spec.md missing)";
60323
+ return [
60324
+ "No active swarm plan found.",
60325
+ "",
60326
+ `**Spec drift detected**: ${reason} (stored: ${stored}, current: ${current})`,
60327
+ "Run `/swarm clarify` to update the spec or `/swarm acknowledge-spec-drift` to dismiss."
60328
+ ].join(`
60329
+ `);
60330
+ }
60139
60331
  return "No active swarm plan found.";
60140
60332
  }
60141
60333
  return formatStatusMarkdown(statusData);
@@ -60439,7 +60631,7 @@ var init_write_retro2 = __esm(() => {
60439
60631
 
60440
60632
  // src/commands/command-dispatch.ts
60441
60633
  import fs36 from "node:fs";
60442
- import path54 from "node:path";
60634
+ import path55 from "node:path";
60443
60635
  function normalizeSwarmCommandInput(command, argumentText) {
60444
60636
  if (command !== "swarm" && !command.startsWith("swarm-")) {
60445
60637
  return { isSwarmCommand: false, tokens: [] };
@@ -60475,9 +60667,9 @@ ${similar.map((cmd) => ` - /swarm ${cmd}`).join(`
60475
60667
  `);
60476
60668
  }
60477
60669
  function maybeMarkFirstRun(directory) {
60478
- const sentinelPath = path54.join(directory, ".swarm", ".first-run-complete");
60670
+ const sentinelPath = path55.join(directory, ".swarm", ".first-run-complete");
60479
60671
  try {
60480
- const swarmDir = path54.join(directory, ".swarm");
60672
+ const swarmDir = path55.join(directory, ".swarm");
60481
60673
  fs36.mkdirSync(swarmDir, { recursive: true });
60482
60674
  fs36.writeFileSync(sentinelPath, `first-run-complete: ${new Date().toISOString()}
60483
60675
  `, { flag: "wx" });
@@ -61145,24 +61337,24 @@ function validateAliases() {
61145
61337
  }
61146
61338
  aliasTargets.get(target).push(name2);
61147
61339
  const visited = new Set;
61148
- const path55 = [];
61340
+ const path56 = [];
61149
61341
  let current = target;
61150
61342
  while (current) {
61151
61343
  const currentEntry = COMMAND_REGISTRY[current];
61152
61344
  if (!currentEntry)
61153
61345
  break;
61154
61346
  if (visited.has(current)) {
61155
- const cycleStart = path55.indexOf(current);
61347
+ const cycleStart = path56.indexOf(current);
61156
61348
  const fullChain = [
61157
61349
  name2,
61158
- ...path55.slice(0, cycleStart > 0 ? cycleStart : path55.length),
61350
+ ...path56.slice(0, cycleStart > 0 ? cycleStart : path56.length),
61159
61351
  current
61160
61352
  ].join(" → ");
61161
61353
  errors5.push(`Circular alias detected: ${fullChain}`);
61162
61354
  break;
61163
61355
  }
61164
61356
  visited.add(current);
61165
- path55.push(current);
61357
+ path56.push(current);
61166
61358
  current = currentEntry.aliasOf || "";
61167
61359
  }
61168
61360
  }
@@ -63375,6 +63567,18 @@ If resuming a project with an existing approved plan, CRITIC-GATE is already sat
63375
63567
  - Run /swarm clarify to update the spec and align it with the plan, OR
63376
63568
  - Run /swarm acknowledge-spec-drift to acknowledge the drift and suppress further warnings
63377
63569
  - Do NOT proceed with implementation until spec staleness is resolved.
63570
+ - When re-saving a plan in response to spec drift, save_plan REQUIRES that ANY task
63571
+ present in the prior plan but absent from the new args.phases be enumerated
63572
+ in removed_task_ids with a removal_reason. save_plan will reject the call
63573
+ otherwise (PLAN_TASK_REMOVAL_NOT_ACKNOWLEDGED). Tasks not yet finished
63574
+ (status: pending, in_progress, blocked) MUST NOT be removed without explicit
63575
+ user confirmation — surface the list to the user and ask before populating
63576
+ removed_task_ids.
63577
+ - While .swarm/spec-staleness.json exists, the runtime STRUCTURALLY BLOCKS the
63578
+ following tools (SPEC_DRIFT_BLOCKED_TOOLS): save_plan, update_task_status,
63579
+ phase_complete, lean_turbo_run_phase, lean_turbo_acquire_locks. If a call
63580
+ returns SPEC_DRIFT_BLOCK, do NOT retry; instead present the drift to the
63581
+ user and run /swarm clarify or /swarm acknowledge-spec-drift first.
63378
63582
 
63379
63583
  ### MODE: EXECUTE
63380
63584
  For each task (respecting dependencies):
@@ -65785,7 +65989,7 @@ COVERAGE REPORTING:
65785
65989
 
65786
65990
  // src/agents/index.ts
65787
65991
  import { mkdir as mkdir10, writeFile as writeFile10 } from "node:fs/promises";
65788
- import * as path55 from "node:path";
65992
+ import * as path56 from "node:path";
65789
65993
  function stripSwarmPrefix(agentName, swarmPrefix) {
65790
65994
  if (!swarmPrefix || !agentName)
65791
65995
  return agentName;
@@ -66181,14 +66385,14 @@ function getAgentConfigs(config3, directory, sessionId, projectContext) {
66181
66385
  }));
66182
66386
  if (directory) {
66183
66387
  const sid = sessionId ?? `init-${Date.now()}`;
66184
- const evidenceDir = path55.join(directory, ".swarm", "evidence");
66388
+ const evidenceDir = path56.join(directory, ".swarm", "evidence");
66185
66389
  const filename = `agent-tools-${sid}.json`;
66186
66390
  const snapshotData = JSON.stringify({
66187
66391
  sessionId: sid,
66188
66392
  generatedAt: new Date().toISOString(),
66189
66393
  agents: agentToolSnapshot
66190
66394
  }, null, 2);
66191
- mkdir10(evidenceDir, { recursive: true }).then(() => writeFile10(path55.join(evidenceDir, filename), snapshotData)).catch(() => {});
66395
+ mkdir10(evidenceDir, { recursive: true }).then(() => writeFile10(path56.join(evidenceDir, filename), snapshotData)).catch(() => {});
66192
66396
  }
66193
66397
  return result;
66194
66398
  }
@@ -66225,14 +66429,14 @@ __export(exports_evidence_summary_integration, {
66225
66429
  createEvidenceSummaryIntegration: () => createEvidenceSummaryIntegration,
66226
66430
  EvidenceSummaryIntegration: () => EvidenceSummaryIntegration
66227
66431
  });
66228
- import { existsSync as existsSync30, mkdirSync as mkdirSync16, writeFileSync as writeFileSync8 } from "node:fs";
66229
- import * as path56 from "node:path";
66432
+ import { existsSync as existsSync32, mkdirSync as mkdirSync16, writeFileSync as writeFileSync8 } from "node:fs";
66433
+ import * as path57 from "node:path";
66230
66434
  function persistSummary(projectDir, artifact, filename) {
66231
- const swarmPath = path56.join(projectDir, ".swarm");
66232
- if (!existsSync30(swarmPath)) {
66435
+ const swarmPath = path57.join(projectDir, ".swarm");
66436
+ if (!existsSync32(swarmPath)) {
66233
66437
  mkdirSync16(swarmPath, { recursive: true });
66234
66438
  }
66235
- const artifactPath = path56.join(swarmPath, filename);
66439
+ const artifactPath = path57.join(swarmPath, filename);
66236
66440
  const content = JSON.stringify(artifact, null, 2);
66237
66441
  writeFileSync8(artifactPath, content, "utf-8");
66238
66442
  log("[EvidenceSummaryIntegration] Summary persisted", {
@@ -66351,7 +66555,7 @@ __export(exports_status_artifact, {
66351
66555
  AutomationStatusArtifact: () => AutomationStatusArtifact
66352
66556
  });
66353
66557
  import * as fs38 from "node:fs";
66354
- import * as path58 from "node:path";
66558
+ import * as path59 from "node:path";
66355
66559
  function createEmptySnapshot(mode, capabilities) {
66356
66560
  return {
66357
66561
  timestamp: Date.now(),
@@ -66410,7 +66614,7 @@ class AutomationStatusArtifact {
66410
66614
  });
66411
66615
  }
66412
66616
  getFilePath() {
66413
- return path58.join(this.swarmDir, this.filename);
66617
+ return path59.join(this.swarmDir, this.filename);
66414
66618
  }
66415
66619
  load() {
66416
66620
  const filePath = this.getFilePath();
@@ -66823,12 +67027,12 @@ __export(exports_review_receipt, {
66823
67027
  });
66824
67028
  import * as crypto5 from "node:crypto";
66825
67029
  import * as fs44 from "node:fs";
66826
- import * as path61 from "node:path";
67030
+ import * as path62 from "node:path";
66827
67031
  function resolveReceiptsDir(directory) {
66828
- return path61.join(directory, ".swarm", "review-receipts");
67032
+ return path62.join(directory, ".swarm", "review-receipts");
66829
67033
  }
66830
67034
  function resolveReceiptIndexPath(directory) {
66831
- return path61.join(resolveReceiptsDir(directory), "index.json");
67035
+ return path62.join(resolveReceiptsDir(directory), "index.json");
66832
67036
  }
66833
67037
  function buildReceiptFilename(id, date9) {
66834
67038
  const dateStr = date9.toISOString().slice(0, 10);
@@ -66867,7 +67071,7 @@ async function readReceiptIndex(directory) {
66867
67071
  }
66868
67072
  async function writeReceiptIndex(directory, index) {
66869
67073
  const indexPath = resolveReceiptIndexPath(directory);
66870
- const dir = path61.dirname(indexPath);
67074
+ const dir = path62.dirname(indexPath);
66871
67075
  await fs44.promises.mkdir(dir, { recursive: true });
66872
67076
  const tmpPath = `${indexPath}.tmp.${Date.now()}.${Math.random().toString(36).slice(2)}`;
66873
67077
  await fs44.promises.writeFile(tmpPath, JSON.stringify(index, null, 2), "utf-8");
@@ -66878,7 +67082,7 @@ async function persistReviewReceipt(directory, receipt) {
66878
67082
  await fs44.promises.mkdir(receiptsDir, { recursive: true });
66879
67083
  const now = new Date(receipt.reviewed_at);
66880
67084
  const filename = buildReceiptFilename(receipt.id, now);
66881
- const receiptPath = path61.join(receiptsDir, filename);
67085
+ const receiptPath = path62.join(receiptsDir, filename);
66882
67086
  const tmpPath = `${receiptPath}.tmp.${Date.now()}.${Math.random().toString(36).slice(2)}`;
66883
67087
  await fs44.promises.writeFile(tmpPath, JSON.stringify(receipt, null, 2), "utf-8");
66884
67088
  fs44.renameSync(tmpPath, receiptPath);
@@ -66900,7 +67104,7 @@ async function readReceiptById(directory, receiptId) {
66900
67104
  const entry = index.entries.find((e) => e.id === receiptId);
66901
67105
  if (!entry)
66902
67106
  return null;
66903
- const receiptPath = path61.join(resolveReceiptsDir(directory), entry.filename);
67107
+ const receiptPath = path62.join(resolveReceiptsDir(directory), entry.filename);
66904
67108
  try {
66905
67109
  const content = await fs44.promises.readFile(receiptPath, "utf-8");
66906
67110
  return JSON.parse(content);
@@ -66913,7 +67117,7 @@ async function readReceiptsByScopeHash(directory, scopeHash) {
66913
67117
  const matching = index.entries.filter((e) => e.scope_hash === scopeHash).sort((a, b) => b.reviewed_at.localeCompare(a.reviewed_at));
66914
67118
  const receipts = [];
66915
67119
  for (const entry of matching) {
66916
- const receiptPath = path61.join(resolveReceiptsDir(directory), entry.filename);
67120
+ const receiptPath = path62.join(resolveReceiptsDir(directory), entry.filename);
66917
67121
  try {
66918
67122
  const content = await fs44.promises.readFile(receiptPath, "utf-8");
66919
67123
  receipts.push(JSON.parse(content));
@@ -66926,7 +67130,7 @@ async function readAllReceipts(directory) {
66926
67130
  const sorted = [...index.entries].sort((a, b) => b.reviewed_at.localeCompare(a.reviewed_at));
66927
67131
  const receipts = [];
66928
67132
  for (const entry of sorted) {
66929
- const receiptPath = path61.join(resolveReceiptsDir(directory), entry.filename);
67133
+ const receiptPath = path62.join(resolveReceiptsDir(directory), entry.filename);
66930
67134
  try {
66931
67135
  const content = await fs44.promises.readFile(receiptPath, "utf-8");
66932
67136
  receipts.push(JSON.parse(content));
@@ -68514,11 +68718,11 @@ ${JSON.stringify(symbolNames, null, 2)}`);
68514
68718
  throw toThrow;
68515
68719
  }, "quit_");
68516
68720
  var scriptDirectory = "";
68517
- function locateFile(path76) {
68721
+ function locateFile(path77) {
68518
68722
  if (Module["locateFile"]) {
68519
- return Module["locateFile"](path76, scriptDirectory);
68723
+ return Module["locateFile"](path77, scriptDirectory);
68520
68724
  }
68521
- return scriptDirectory + path76;
68725
+ return scriptDirectory + path77;
68522
68726
  }
68523
68727
  __name(locateFile, "locateFile");
68524
68728
  var readAsync, readBinary;
@@ -70268,12 +70472,12 @@ __export(exports_runtime, {
70268
70472
  clearParserCache: () => clearParserCache,
70269
70473
  _internals: () => _internals35
70270
70474
  });
70271
- import * as path76 from "node:path";
70475
+ import * as path77 from "node:path";
70272
70476
  import { fileURLToPath as fileURLToPath2 } from "node:url";
70273
70477
  async function initTreeSitter() {
70274
70478
  if (!treeSitterInitPromise) {
70275
70479
  treeSitterInitPromise = (async () => {
70276
- const thisDir = path76.dirname(fileURLToPath2(import.meta.url));
70480
+ const thisDir = path77.dirname(fileURLToPath2(import.meta.url));
70277
70481
  const isSource = thisDir.replace(/\\/g, "/").endsWith("/src/lang");
70278
70482
  if (isSource) {
70279
70483
  await _internals35.parserInit();
@@ -70281,7 +70485,7 @@ async function initTreeSitter() {
70281
70485
  const grammarsDir = getGrammarsDirAbsolute();
70282
70486
  await _internals35.parserInit({
70283
70487
  locateFile(scriptName) {
70284
- return path76.join(grammarsDir, scriptName);
70488
+ return path77.join(grammarsDir, scriptName);
70285
70489
  }
70286
70490
  });
70287
70491
  }
@@ -70307,11 +70511,11 @@ function getWasmFileName(languageId) {
70307
70511
  return `tree-sitter-${sanitized}.wasm`;
70308
70512
  }
70309
70513
  function getGrammarsDirAbsolute() {
70310
- const thisDir = path76.dirname(fileURLToPath2(import.meta.url));
70514
+ const thisDir = path77.dirname(fileURLToPath2(import.meta.url));
70311
70515
  const normalized = thisDir.replace(/\\/g, "/");
70312
70516
  const isSource = normalized.endsWith("/src/lang");
70313
70517
  const isCliBundle = normalized.endsWith("/cli");
70314
- return isSource ? path76.join(thisDir, "grammars") : isCliBundle ? path76.join(thisDir, "..", "lang", "grammars") : path76.join(thisDir, "lang", "grammars");
70518
+ return isSource ? path77.join(thisDir, "grammars") : isCliBundle ? path77.join(thisDir, "..", "lang", "grammars") : path77.join(thisDir, "lang", "grammars");
70315
70519
  }
70316
70520
  async function loadGrammar(languageId) {
70317
70521
  if (typeof languageId !== "string" || languageId.length > 100) {
@@ -70327,9 +70531,9 @@ async function loadGrammar(languageId) {
70327
70531
  await initTreeSitter();
70328
70532
  const parser = new Parser;
70329
70533
  const wasmFileName = getWasmFileName(normalizedId);
70330
- const wasmPath = path76.join(getGrammarsDirAbsolute(), wasmFileName);
70331
- const { existsSync: existsSync40 } = await import("node:fs");
70332
- if (!existsSync40(wasmPath)) {
70534
+ const wasmPath = path77.join(getGrammarsDirAbsolute(), wasmFileName);
70535
+ const { existsSync: existsSync42 } = await import("node:fs");
70536
+ if (!existsSync42(wasmPath)) {
70333
70537
  throw new Error(`Grammar file not found for ${languageId}: ${wasmPath}
70334
70538
  Make sure to run 'bun run build' to copy grammar files to dist/lang/grammars/`);
70335
70539
  }
@@ -70362,7 +70566,7 @@ async function isGrammarAvailable(languageId) {
70362
70566
  }
70363
70567
  try {
70364
70568
  const wasmFileName = getWasmFileName(normalizedId);
70365
- const wasmPath = path76.join(getGrammarsDirAbsolute(), wasmFileName);
70569
+ const wasmPath = path77.join(getGrammarsDirAbsolute(), wasmFileName);
70366
70570
  const { statSync: statSync20 } = await import("node:fs");
70367
70571
  statSync20(wasmPath);
70368
70572
  return true;
@@ -70431,13 +70635,13 @@ import {
70431
70635
  stat as stat6,
70432
70636
  writeFile as writeFile12
70433
70637
  } from "node:fs/promises";
70434
- import * as path78 from "node:path";
70638
+ import * as path79 from "node:path";
70435
70639
  function normalizeSeparators(filePath) {
70436
70640
  return filePath.replace(/\\/g, "/");
70437
70641
  }
70438
70642
  function matchesDocPattern(filePath, patterns) {
70439
70643
  const normalizedPath = normalizeSeparators(filePath);
70440
- const basename10 = path78.basename(filePath);
70644
+ const basename10 = path79.basename(filePath);
70441
70645
  for (const pattern of patterns) {
70442
70646
  if (!pattern.includes("/") && !pattern.includes("\\")) {
70443
70647
  if (basename10 === pattern) {
@@ -70493,7 +70697,7 @@ function stripMarkdown(text) {
70493
70697
  return text.replace(/\[([^\]]+)\]\([^)]+\)/g, "$1").replace(/\*\*([^*]+)\*\*/g, "$1").replace(/`([^`]+)`/g, "$1").replace(/^\s*[-*•]\s+/gm, "").replace(/^\s*\d+\.\s+/gm, "").trim();
70494
70698
  }
70495
70699
  async function scanDocIndex(directory) {
70496
- const manifestPath = path78.join(directory, ".swarm", "doc-manifest.json");
70700
+ const manifestPath = path79.join(directory, ".swarm", "doc-manifest.json");
70497
70701
  const defaultPatterns = DocsConfigSchema.parse({}).doc_patterns;
70498
70702
  const extraPatterns = [
70499
70703
  "ARCHITECTURE.md",
@@ -70510,7 +70714,7 @@ async function scanDocIndex(directory) {
70510
70714
  let cacheValid = true;
70511
70715
  for (const file3 of existingManifest.files) {
70512
70716
  try {
70513
- const fullPath = path78.join(directory, file3.path);
70717
+ const fullPath = path79.join(directory, file3.path);
70514
70718
  const stat7 = fs53.statSync(fullPath);
70515
70719
  if (stat7.mtimeMs > file3.mtime) {
70516
70720
  cacheValid = false;
@@ -70545,10 +70749,10 @@ async function scanDocIndex(directory) {
70545
70749
  let isFile = entry.isFile();
70546
70750
  if (entry.isSymbolicLink()) {
70547
70751
  try {
70548
- const symlinkPath = path78.join(dir, entry.name);
70752
+ const symlinkPath = path79.join(dir, entry.name);
70549
70753
  const resolved = await realpath2(symlinkPath);
70550
- const rel = path78.relative(resolvedDirectory, resolved);
70551
- if (rel.startsWith("..") || path78.isAbsolute(rel))
70754
+ const rel = path79.relative(resolvedDirectory, resolved);
70755
+ if (rel.startsWith("..") || path79.isAbsolute(rel))
70552
70756
  continue;
70553
70757
  const targetStat = await stat6(symlinkPath);
70554
70758
  isFile = targetStat.isFile();
@@ -70558,14 +70762,14 @@ async function scanDocIndex(directory) {
70558
70762
  }
70559
70763
  if (isDir) {
70560
70764
  if (!SKIP_DIRECTORIES3.has(entry.name)) {
70561
- await walkDir(path78.join(dir, entry.name));
70765
+ await walkDir(path79.join(dir, entry.name));
70562
70766
  }
70563
70767
  continue;
70564
70768
  }
70565
70769
  if (!isFile)
70566
70770
  continue;
70567
- const fullPath = path78.join(dir, entry.name);
70568
- const relPath = normalizeSeparators(path78.relative(directory, fullPath));
70771
+ const fullPath = path79.join(dir, entry.name);
70772
+ const relPath = normalizeSeparators(path79.relative(directory, fullPath));
70569
70773
  let skipThisFile = false;
70570
70774
  for (const pattern of SKIP_PATTERNS) {
70571
70775
  if (pattern.test(relPath)) {
@@ -70589,7 +70793,7 @@ async function scanDocIndex(directory) {
70589
70793
  } catch {
70590
70794
  continue;
70591
70795
  }
70592
- const { title, summary } = extractTitleAndSummary(content, path78.basename(relPath));
70796
+ const { title, summary } = extractTitleAndSummary(content, path79.basename(relPath));
70593
70797
  discoveredFiles.push({
70594
70798
  path: relPath,
70595
70799
  title,
@@ -70626,7 +70830,7 @@ async function scanDocIndex(directory) {
70626
70830
  files: discoveredFiles
70627
70831
  };
70628
70832
  try {
70629
- await mkdir13(path78.dirname(manifestPath), { recursive: true });
70833
+ await mkdir13(path79.dirname(manifestPath), { recursive: true });
70630
70834
  await writeFile12(manifestPath, JSON.stringify(manifest, null, 2), "utf-8");
70631
70835
  } catch {}
70632
70836
  return { manifest, cached: false };
@@ -70665,7 +70869,7 @@ function extractConstraintsFromContent(content) {
70665
70869
  return constraints;
70666
70870
  }
70667
70871
  async function extractDocConstraints(directory, taskFiles, taskDescription) {
70668
- const manifestPath = path78.join(directory, ".swarm", "doc-manifest.json");
70872
+ const manifestPath = path79.join(directory, ".swarm", "doc-manifest.json");
70669
70873
  let manifest;
70670
70874
  try {
70671
70875
  const content = await readFile12(manifestPath, "utf-8");
@@ -70691,7 +70895,7 @@ async function extractDocConstraints(directory, taskFiles, taskDescription) {
70691
70895
  }
70692
70896
  let fullContent;
70693
70897
  try {
70694
- fullContent = await readFile12(path78.join(directory, docFile.path), "utf-8");
70898
+ fullContent = await readFile12(path79.join(directory, docFile.path), "utf-8");
70695
70899
  } catch {
70696
70900
  skippedCount++;
70697
70901
  continue;
@@ -70714,7 +70918,7 @@ async function extractDocConstraints(directory, taskFiles, taskDescription) {
70714
70918
  tier: "swarm",
70715
70919
  lesson: constraint,
70716
70920
  category: "architecture",
70717
- tags: ["doc-scan", path78.basename(docFile.path)],
70921
+ tags: ["doc-scan", path79.basename(docFile.path)],
70718
70922
  scope: "global",
70719
70923
  confidence: 0.5,
70720
70924
  status: "candidate",
@@ -70793,7 +70997,7 @@ var init_doc_scan = __esm(() => {
70793
70997
  }
70794
70998
  } catch {}
70795
70999
  if (force) {
70796
- const manifestPath = path78.join(directory, ".swarm", "doc-manifest.json");
71000
+ const manifestPath = path79.join(directory, ".swarm", "doc-manifest.json");
70797
71001
  try {
70798
71002
  fs53.unlinkSync(manifestPath);
70799
71003
  } catch {}
@@ -70989,9 +71193,9 @@ __export(exports_curator_drift, {
70989
71193
  _internals: () => _internals38
70990
71194
  });
70991
71195
  import * as fs60 from "node:fs";
70992
- import * as path84 from "node:path";
71196
+ import * as path85 from "node:path";
70993
71197
  async function readPriorDriftReports(directory) {
70994
- const swarmDir = path84.join(directory, ".swarm");
71198
+ const swarmDir = path85.join(directory, ".swarm");
70995
71199
  const entries = await fs60.promises.readdir(swarmDir).catch(() => null);
70996
71200
  if (entries === null)
70997
71201
  return [];
@@ -71018,7 +71222,7 @@ async function readPriorDriftReports(directory) {
71018
71222
  async function writeDriftReport(directory, report) {
71019
71223
  const filename = `${DRIFT_REPORT_PREFIX}${report.phase}.json`;
71020
71224
  const filePath = validateSwarmPath(directory, filename);
71021
- const swarmDir = path84.dirname(filePath);
71225
+ const swarmDir = path85.dirname(filePath);
71022
71226
  await fs60.promises.mkdir(swarmDir, { recursive: true });
71023
71227
  try {
71024
71228
  await fs60.promises.writeFile(filePath, JSON.stringify(report, null, 2), "utf-8");
@@ -71164,7 +71368,7 @@ __export(exports_project_context, {
71164
71368
  LANG_BACKEND_DETECTION_TIMEOUT_MS: () => LANG_BACKEND_DETECTION_TIMEOUT_MS
71165
71369
  });
71166
71370
  import * as fs110 from "node:fs";
71167
- import * as path138 from "node:path";
71371
+ import * as path139 from "node:path";
71168
71372
  function detectFileExists2(directory, pattern) {
71169
71373
  if (pattern.includes("*") || pattern.includes("?")) {
71170
71374
  try {
@@ -71176,7 +71380,7 @@ function detectFileExists2(directory, pattern) {
71176
71380
  }
71177
71381
  }
71178
71382
  try {
71179
- fs110.accessSync(path138.join(directory, pattern));
71383
+ fs110.accessSync(path139.join(directory, pattern));
71180
71384
  return true;
71181
71385
  } catch {
71182
71386
  return false;
@@ -71185,7 +71389,7 @@ function detectFileExists2(directory, pattern) {
71185
71389
  function selectTestCommandFromScriptsTest(backend, directory) {
71186
71390
  let pkgRaw;
71187
71391
  try {
71188
- pkgRaw = fs110.readFileSync(path138.join(directory, "package.json"), "utf-8");
71392
+ pkgRaw = fs110.readFileSync(path139.join(directory, "package.json"), "utf-8");
71189
71393
  } catch {
71190
71394
  return null;
71191
71395
  }
@@ -71294,7 +71498,7 @@ var init_project_context = __esm(() => {
71294
71498
  init_package();
71295
71499
  init_agents2();
71296
71500
  init_critic();
71297
- import * as path139 from "node:path";
71501
+ import * as path140 from "node:path";
71298
71502
 
71299
71503
  // src/background/index.ts
71300
71504
  init_event_bus();
@@ -71305,7 +71509,7 @@ init_manager3();
71305
71509
  init_manager();
71306
71510
  init_utils();
71307
71511
  import * as fs37 from "node:fs";
71308
- import * as path57 from "node:path";
71512
+ import * as path58 from "node:path";
71309
71513
 
71310
71514
  class PlanSyncWorker {
71311
71515
  directory;
@@ -71329,10 +71533,10 @@ class PlanSyncWorker {
71329
71533
  this.onSyncComplete = options.onSyncComplete;
71330
71534
  }
71331
71535
  getSwarmDir() {
71332
- return path57.resolve(this.directory, ".swarm");
71536
+ return path58.resolve(this.directory, ".swarm");
71333
71537
  }
71334
71538
  getPlanJsonPath() {
71335
- return path57.join(this.getSwarmDir(), "plan.json");
71539
+ return path58.join(this.getSwarmDir(), "plan.json");
71336
71540
  }
71337
71541
  start() {
71338
71542
  if (this.disposed) {
@@ -71551,8 +71755,8 @@ class PlanSyncWorker {
71551
71755
  checkForUnauthorizedWrite() {
71552
71756
  try {
71553
71757
  const swarmDir = this.getSwarmDir();
71554
- const planJsonPath = path57.join(swarmDir, "plan.json");
71555
- const markerPath = path57.join(swarmDir, ".plan-write-marker");
71758
+ const planJsonPath = path58.join(swarmDir, "plan.json");
71759
+ const markerPath = path58.join(swarmDir, ".plan-write-marker");
71556
71760
  const planStats = fs37.statSync(planJsonPath);
71557
71761
  const planMtimeMs = Math.floor(planStats.mtimeMs);
71558
71762
  const markerContent = fs37.readFileSync(markerPath, "utf8");
@@ -71593,13 +71797,13 @@ init_constants();
71593
71797
  // src/config/project-init.ts
71594
71798
  init_constants();
71595
71799
  import * as fs39 from "node:fs";
71596
- import * as path59 from "node:path";
71800
+ import * as path60 from "node:path";
71597
71801
  var STARTER_CONTENT = `{}
71598
71802
  `;
71599
71803
  function writeProjectConfigIfNew(directory, quiet = false) {
71600
71804
  try {
71601
- const opencodeDir = path59.join(directory, ".opencode");
71602
- const dest = path59.join(opencodeDir, "opencode-swarm.json");
71805
+ const opencodeDir = path60.join(directory, ".opencode");
71806
+ const dest = path60.join(opencodeDir, "opencode-swarm.json");
71603
71807
  try {
71604
71808
  const stat4 = fs39.lstatSync(opencodeDir);
71605
71809
  if (stat4.isSymbolicLink())
@@ -71624,8 +71828,8 @@ function writeProjectConfigIfNew(directory, quiet = false) {
71624
71828
  }
71625
71829
  function writeSwarmConfigExampleIfNew(projectDirectory) {
71626
71830
  try {
71627
- const swarmDir = path59.join(projectDirectory, ".swarm");
71628
- const dest = path59.join(swarmDir, "config.example.json");
71831
+ const swarmDir = path60.join(projectDirectory, ".swarm");
71832
+ const dest = path60.join(swarmDir, "config.example.json");
71629
71833
  if (fs39.existsSync(dest))
71630
71834
  return;
71631
71835
  if (!fs39.existsSync(swarmDir)) {
@@ -71662,7 +71866,7 @@ init_state();
71662
71866
  init_logger();
71663
71867
  init_state2();
71664
71868
  import * as fs40 from "node:fs";
71665
- import * as path60 from "node:path";
71869
+ import * as path61 from "node:path";
71666
71870
  var oversightSequenceCounter = 0;
71667
71871
  var VALID_VERDICTS = [
71668
71872
  "APPROVED",
@@ -71836,10 +72040,10 @@ async function writeFullAutoOversightEvidence(directory, phase, event) {
71836
72040
  if (phase === undefined)
71837
72041
  return;
71838
72042
  try {
71839
- const evidenceDir = validateSwarmPath(directory, path60.posix.join("evidence", String(phase)));
72043
+ const evidenceDir = validateSwarmPath(directory, path61.posix.join("evidence", String(phase)));
71840
72044
  fs40.mkdirSync(evidenceDir, { recursive: true });
71841
72045
  const fileName = `full-auto-${event.oversight_sequence}.json`;
71842
- const filePath = validateSwarmPath(directory, path60.posix.join("evidence", String(phase), fileName));
72046
+ const filePath = validateSwarmPath(directory, path61.posix.join("evidence", String(phase), fileName));
71843
72047
  fs40.writeFileSync(filePath, `${JSON.stringify(event, null, 2)}
71844
72048
  `, "utf-8");
71845
72049
  return filePath;
@@ -72248,11 +72452,11 @@ async function doFlush(directory) {
72248
72452
  const activitySection = renderActivitySection();
72249
72453
  const updated = replaceOrAppendSection(existing, "## Agent Activity", activitySection);
72250
72454
  const flushedCount = swarmState.pendingEvents;
72251
- const path61 = nodePath2.join(directory, ".swarm", "context.md");
72252
- const tempPath = `${path61}.tmp`;
72455
+ const path62 = nodePath2.join(directory, ".swarm", "context.md");
72456
+ const tempPath = `${path62}.tmp`;
72253
72457
  try {
72254
72458
  await bunWrite(tempPath, updated);
72255
- renameSync13(tempPath, path61);
72459
+ renameSync13(tempPath, path62);
72256
72460
  } catch (writeError) {
72257
72461
  try {
72258
72462
  unlinkSync10(tempPath);
@@ -72495,7 +72699,7 @@ init_state();
72495
72699
  init_extractors();
72496
72700
  init_utils2();
72497
72701
  import * as fs41 from "node:fs";
72498
- import { join as join54 } from "node:path";
72702
+ import { join as join55 } from "node:path";
72499
72703
  function createCompactionCustomizerHook(config3, directory) {
72500
72704
  const enabled = config3.hooks?.compaction !== false;
72501
72705
  if (!enabled) {
@@ -72540,7 +72744,7 @@ function createCompactionCustomizerHook(config3, directory) {
72540
72744
  }
72541
72745
  }
72542
72746
  try {
72543
- const summariesDir = join54(directory, ".swarm", "summaries");
72747
+ const summariesDir = join55(directory, ".swarm", "summaries");
72544
72748
  const files = await fs41.promises.readdir(summariesDir);
72545
72749
  if (files.length > 0) {
72546
72750
  const count = files.length;
@@ -73920,7 +74124,7 @@ init_schema();
73920
74124
  init_manager();
73921
74125
  init_curator();
73922
74126
  init_utils2();
73923
- import * as path62 from "node:path";
74127
+ import * as path63 from "node:path";
73924
74128
  function createPhaseMonitorHook(directory, preflightManager, curatorRunner, delegateFactory) {
73925
74129
  let lastKnownPhase = null;
73926
74130
  const handler = async (input, _output) => {
@@ -73940,9 +74144,9 @@ function createPhaseMonitorHook(directory, preflightManager, curatorRunner, dele
73940
74144
  const llmDelegate = delegateFactory?.(sessionId);
73941
74145
  const initResult = await runner(directory, curatorConfig, llmDelegate);
73942
74146
  if (initResult.briefing) {
73943
- const briefingPath = path62.join(directory, ".swarm", "curator-briefing.md");
74147
+ const briefingPath = path63.join(directory, ".swarm", "curator-briefing.md");
73944
74148
  const { mkdir: mkdir11, writeFile: writeFile11 } = await import("node:fs/promises");
73945
- await mkdir11(path62.dirname(briefingPath), { recursive: true });
74149
+ await mkdir11(path63.dirname(briefingPath), { recursive: true });
73946
74150
  await writeFile11(briefingPath, initResult.briefing, "utf-8");
73947
74151
  const { buildApprovedReceipt: buildApprovedReceipt2, persistReviewReceipt: persistReviewReceipt2 } = await Promise.resolve().then(() => (init_review_receipt(), exports_review_receipt));
73948
74152
  const initReceipt = buildApprovedReceipt2({
@@ -74069,16 +74273,16 @@ ${originalText}`;
74069
74273
  // src/hooks/repo-graph-builder.ts
74070
74274
  init_constants();
74071
74275
  import { realpathSync as realpathSync8 } from "node:fs";
74072
- import * as path69 from "node:path";
74276
+ import * as path70 from "node:path";
74073
74277
 
74074
74278
  // src/tools/repo-graph/builder.ts
74075
74279
  init_logger();
74076
74280
  init_path_security();
74077
- import * as fsSync3 from "node:fs";
74078
- import { existsSync as existsSync36, realpathSync as realpathSync6 } from "node:fs";
74281
+ import * as fsSync4 from "node:fs";
74282
+ import { existsSync as existsSync38, realpathSync as realpathSync6 } from "node:fs";
74079
74283
  import * as fsPromises5 from "node:fs/promises";
74080
74284
  import * as os7 from "node:os";
74081
- import * as path65 from "node:path";
74285
+ import * as path66 from "node:path";
74082
74286
 
74083
74287
  // src/utils/timeout.ts
74084
74288
  async function withTimeout(promise3, ms, timeoutError) {
@@ -74110,7 +74314,7 @@ init_zod();
74110
74314
  init_create_tool();
74111
74315
  init_path_security();
74112
74316
  import * as fs45 from "node:fs";
74113
- import * as path63 from "node:path";
74317
+ import * as path64 from "node:path";
74114
74318
  var MAX_FILE_SIZE_BYTES2 = 1024 * 1024;
74115
74319
  var WINDOWS_RESERVED_NAMES = /^(con|prn|aux|nul|com[1-9]|lpt[1-9])(\.|:|$)/i;
74116
74320
  function containsWindowsAttacks(str) {
@@ -74127,11 +74331,11 @@ function containsWindowsAttacks(str) {
74127
74331
  }
74128
74332
  function isPathInWorkspace(filePath, workspace) {
74129
74333
  try {
74130
- const resolvedPath = path63.resolve(workspace, filePath);
74334
+ const resolvedPath = path64.resolve(workspace, filePath);
74131
74335
  const realWorkspace = fs45.realpathSync(workspace);
74132
74336
  const realResolvedPath = fs45.realpathSync(resolvedPath);
74133
- const relativePath = path63.relative(realWorkspace, realResolvedPath);
74134
- if (relativePath.startsWith("..") || path63.isAbsolute(relativePath)) {
74337
+ const relativePath = path64.relative(realWorkspace, realResolvedPath);
74338
+ if (relativePath.startsWith("..") || path64.isAbsolute(relativePath)) {
74135
74339
  return false;
74136
74340
  }
74137
74341
  return true;
@@ -74143,7 +74347,7 @@ function validatePathForRead(filePath, workspace) {
74143
74347
  return isPathInWorkspace(filePath, workspace);
74144
74348
  }
74145
74349
  function extractTSSymbols(filePath, cwd) {
74146
- const fullPath = path63.join(cwd, filePath);
74350
+ const fullPath = path64.join(cwd, filePath);
74147
74351
  if (!validatePathForRead(fullPath, cwd)) {
74148
74352
  return [];
74149
74353
  }
@@ -74295,7 +74499,7 @@ function extractTSSymbols(filePath, cwd) {
74295
74499
  });
74296
74500
  }
74297
74501
  function extractPythonSymbols(filePath, cwd) {
74298
- const fullPath = path63.join(cwd, filePath);
74502
+ const fullPath = path64.join(cwd, filePath);
74299
74503
  if (!validatePathForRead(fullPath, cwd)) {
74300
74504
  return [];
74301
74505
  }
@@ -74378,7 +74582,7 @@ var symbols = createSwarmTool({
74378
74582
  }, null, 2);
74379
74583
  }
74380
74584
  const cwd = directory;
74381
- const ext = path63.extname(file3);
74585
+ const ext = path64.extname(file3);
74382
74586
  if (containsControlChars(file3)) {
74383
74587
  return JSON.stringify({
74384
74588
  file: file3,
@@ -74439,16 +74643,16 @@ var symbols = createSwarmTool({
74439
74643
  });
74440
74644
 
74441
74645
  // src/tools/repo-graph/types.ts
74442
- import * as path64 from "node:path";
74646
+ import * as path65 from "node:path";
74443
74647
  var REPO_GRAPH_FILENAME = "repo-graph.json";
74444
74648
  var GRAPH_SCHEMA_VERSION = "1.0.0";
74445
74649
  function normalizeGraphPath(filePath) {
74446
- return path64.normalize(filePath).replace(/\\/g, "/");
74650
+ return path65.normalize(filePath).replace(/\\/g, "/");
74447
74651
  }
74448
74652
  function createEmptyGraph(workspaceRoot) {
74449
74653
  return {
74450
74654
  schema_version: GRAPH_SCHEMA_VERSION,
74451
- workspaceRoot: path64.normalize(workspaceRoot),
74655
+ workspaceRoot: path65.normalize(workspaceRoot),
74452
74656
  nodes: {},
74453
74657
  edges: [],
74454
74658
  metadata: {
@@ -74623,8 +74827,8 @@ function resolveModuleSpecifier(workspaceRoot, sourceFile, specifier) {
74623
74827
  }
74624
74828
  try {
74625
74829
  if (specifier.startsWith(".")) {
74626
- const sourceDir = path65.dirname(sourceFile);
74627
- let resolved = path65.resolve(sourceDir, specifier);
74830
+ const sourceDir = path66.dirname(sourceFile);
74831
+ let resolved = path66.resolve(sourceDir, specifier);
74628
74832
  let realResolved;
74629
74833
  try {
74630
74834
  realResolved = realpathSync6(resolved);
@@ -74635,9 +74839,9 @@ function resolveModuleSpecifier(workspaceRoot, sourceFile, specifier) {
74635
74839
  try {
74636
74840
  realRoot = realpathSync6(workspaceRoot);
74637
74841
  } catch {
74638
- realRoot = path65.normalize(workspaceRoot);
74842
+ realRoot = path66.normalize(workspaceRoot);
74639
74843
  }
74640
- if (!existsSync36(resolved)) {
74844
+ if (!existsSync38(resolved)) {
74641
74845
  const EXTENSIONS = [
74642
74846
  ".ts",
74643
74847
  ".tsx",
@@ -74651,7 +74855,7 @@ function resolveModuleSpecifier(workspaceRoot, sourceFile, specifier) {
74651
74855
  let found = null;
74652
74856
  for (const ext of EXTENSIONS) {
74653
74857
  const candidate = resolved + ext;
74654
- if (existsSync36(candidate)) {
74858
+ if (existsSync38(candidate)) {
74655
74859
  found = candidate;
74656
74860
  break;
74657
74861
  }
@@ -74667,9 +74871,9 @@ function resolveModuleSpecifier(workspaceRoot, sourceFile, specifier) {
74667
74871
  return null;
74668
74872
  }
74669
74873
  }
74670
- const normalizedResolved = path65.normalize(realResolved);
74671
- const normalizedRoot = path65.normalize(realRoot);
74672
- if (!normalizedResolved.startsWith(normalizedRoot + path65.sep) && normalizedResolved !== normalizedRoot) {
74874
+ const normalizedResolved = path66.normalize(realResolved);
74875
+ const normalizedRoot = path66.normalize(realRoot);
74876
+ if (!normalizedResolved.startsWith(normalizedRoot + path66.sep) && normalizedResolved !== normalizedRoot) {
74673
74877
  return null;
74674
74878
  }
74675
74879
  return resolved;
@@ -74684,12 +74888,12 @@ function isRefusedWorkspaceRoot(target) {
74684
74888
  try {
74685
74889
  resolved = realpathSync6(target);
74686
74890
  } catch {
74687
- resolved = path65.resolve(target);
74891
+ resolved = path66.resolve(target);
74688
74892
  }
74689
74893
  const refused = new Set;
74690
74894
  const add = (p) => {
74691
74895
  if (typeof p === "string" && p.length > 0) {
74692
- refused.add(path65.resolve(p));
74896
+ refused.add(path66.resolve(p));
74693
74897
  }
74694
74898
  };
74695
74899
  add(os7.homedir());
@@ -74799,7 +75003,7 @@ async function findSourceFilesAsync(dir, stats, options) {
74799
75003
  ctx.stats.skippedDirs++;
74800
75004
  continue;
74801
75005
  }
74802
- const fullPath = path65.join(current, entry.name);
75006
+ const fullPath = path66.join(current, entry.name);
74803
75007
  if (entry.isSymbolicLink() && !ctx.followSymlinks) {
74804
75008
  ctx.stats.skippedDirs++;
74805
75009
  continue;
@@ -74807,7 +75011,7 @@ async function findSourceFilesAsync(dir, stats, options) {
74807
75011
  if (entry.isDirectory()) {
74808
75012
  queue.push(fullPath);
74809
75013
  } else if (entry.isFile()) {
74810
- const ext = path65.extname(fullPath).toLowerCase();
75014
+ const ext = path66.extname(fullPath).toLowerCase();
74811
75015
  if (SUPPORTED_EXTENSIONS.includes(ext)) {
74812
75016
  files.push(fullPath);
74813
75017
  }
@@ -74824,11 +75028,11 @@ async function findSourceFilesAsync(dir, stats, options) {
74824
75028
  return files;
74825
75029
  }
74826
75030
  function toModuleName(filePath, workspaceRoot) {
74827
- const relative11 = path65.relative(workspaceRoot, filePath);
74828
- return relative11.split(path65.sep).join("/");
75031
+ const relative11 = path66.relative(workspaceRoot, filePath);
75032
+ return relative11.split(path66.sep).join("/");
74829
75033
  }
74830
75034
  function getLanguage(filePath) {
74831
- const ext = path65.extname(filePath).toLowerCase();
75035
+ const ext = path66.extname(filePath).toLowerCase();
74832
75036
  return EXTENSION_TO_LANGUAGE[ext] ?? "unknown";
74833
75037
  }
74834
75038
  function isBinaryContent(content) {
@@ -74841,26 +75045,26 @@ function scanFile(filePath, absoluteRoot, maxFileSize) {
74841
75045
  let content;
74842
75046
  let fileStats;
74843
75047
  try {
74844
- fileStats = fsSync3.statSync(filePath);
75048
+ fileStats = fsSync4.statSync(filePath);
74845
75049
  if (fileStats.size > maxFileSize) {
74846
75050
  return { node: null, edges: [] };
74847
75051
  }
74848
- content = fsSync3.readFileSync(filePath, "utf-8");
75052
+ content = fsSync4.readFileSync(filePath, "utf-8");
74849
75053
  } catch {
74850
75054
  return { node: null, edges: [] };
74851
75055
  }
74852
75056
  if (isBinaryContent(content)) {
74853
75057
  return { node: null, edges: [] };
74854
75058
  }
74855
- const ext = path65.extname(filePath).toLowerCase();
75059
+ const ext = path66.extname(filePath).toLowerCase();
74856
75060
  let exports = [];
74857
75061
  try {
74858
75062
  if ([".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs"].includes(ext)) {
74859
- const relativePath = path65.relative(absoluteRoot, filePath);
75063
+ const relativePath = path66.relative(absoluteRoot, filePath);
74860
75064
  const symbols2 = extractTSSymbols(relativePath, absoluteRoot);
74861
75065
  exports = symbols2.filter((s) => s.exported).map((s) => s.name);
74862
75066
  } else if (ext === ".py") {
74863
- const relativePath = path65.relative(absoluteRoot, filePath);
75067
+ const relativePath = path66.relative(absoluteRoot, filePath);
74864
75068
  const symbols2 = extractPythonSymbols(relativePath, absoluteRoot);
74865
75069
  exports = symbols2.filter((s) => s.exported).map((s) => s.name);
74866
75070
  }
@@ -74897,8 +75101,8 @@ async function buildWorkspaceGraphAsync(workspaceRoot, options) {
74897
75101
  const maxFiles = options?.maxFiles ?? DEFAULT_WALK_FILE_CAP;
74898
75102
  const walkBudgetMs = options?.walkBudgetMs ?? DEFAULT_WALK_BUDGET_MS;
74899
75103
  const followSymlinks = options?.followSymlinks ?? false;
74900
- const absoluteRoot = path65.resolve(workspaceRoot);
74901
- if (!existsSync36(absoluteRoot)) {
75104
+ const absoluteRoot = path66.resolve(workspaceRoot);
75105
+ if (!existsSync38(absoluteRoot)) {
74902
75106
  throw new Error(`Workspace directory does not exist: ${workspaceRoot}`);
74903
75107
  }
74904
75108
  if (isRefusedWorkspaceRoot(absoluteRoot)) {
@@ -74953,15 +75157,15 @@ async function buildWorkspaceGraphAsync(workspaceRoot, options) {
74953
75157
  return graph;
74954
75158
  }
74955
75159
  // src/tools/repo-graph/cache.ts
74956
- import * as path66 from "node:path";
75160
+ import * as path67 from "node:path";
74957
75161
  var graphCache = new Map;
74958
75162
  var dirtyFlags = new Map;
74959
75163
  var mtimeCache = new Map;
74960
75164
  function getCachedGraph(workspace) {
74961
- return graphCache.get(path66.normalize(workspace));
75165
+ return graphCache.get(path67.normalize(workspace));
74962
75166
  }
74963
75167
  function setCachedGraph(workspace, graph, mtime) {
74964
- const normalized = path66.normalize(workspace);
75168
+ const normalized = path67.normalize(workspace);
74965
75169
  graphCache.set(normalized, graph);
74966
75170
  dirtyFlags.set(normalized, false);
74967
75171
  if (mtime !== undefined) {
@@ -74969,30 +75173,30 @@ function setCachedGraph(workspace, graph, mtime) {
74969
75173
  }
74970
75174
  }
74971
75175
  function isDirty(workspace) {
74972
- return dirtyFlags.get(path66.normalize(workspace)) ?? false;
75176
+ return dirtyFlags.get(path67.normalize(workspace)) ?? false;
74973
75177
  }
74974
75178
  function clearCache(workspace) {
74975
- const normalized = path66.normalize(workspace);
75179
+ const normalized = path67.normalize(workspace);
74976
75180
  graphCache.delete(normalized);
74977
75181
  dirtyFlags.delete(normalized);
74978
75182
  mtimeCache.delete(normalized);
74979
75183
  }
74980
75184
  function getCachedMtime(workspace) {
74981
- return mtimeCache.get(path66.normalize(workspace));
75185
+ return mtimeCache.get(path67.normalize(workspace));
74982
75186
  }
74983
75187
  // src/tools/repo-graph/incremental.ts
74984
75188
  init_logger();
74985
- import { existsSync as existsSync38 } from "node:fs";
75189
+ import { existsSync as existsSync40 } from "node:fs";
74986
75190
  import * as fsPromises7 from "node:fs/promises";
74987
- import * as path68 from "node:path";
75191
+ import * as path69 from "node:path";
74988
75192
 
74989
75193
  // src/tools/repo-graph/storage.ts
74990
75194
  init_utils2();
74991
75195
  init_logger();
74992
75196
  init_path_security();
74993
- import { constants as constants4, existsSync as existsSync37, realpathSync as realpathSync7 } from "node:fs";
75197
+ import { constants as constants4, existsSync as existsSync39, realpathSync as realpathSync7 } from "node:fs";
74994
75198
  import * as fsPromises6 from "node:fs/promises";
74995
- import * as path67 from "node:path";
75199
+ import * as path68 from "node:path";
74996
75200
  var WINDOWS_RENAME_MAX_RETRIES2 = 3;
74997
75201
  var WINDOWS_RENAME_RETRY_DELAY_MS2 = 50;
74998
75202
  function getGraphPath(workspace) {
@@ -75003,12 +75207,12 @@ function getGraphPath(workspace) {
75003
75207
  }
75004
75208
  async function loadGraph(workspace) {
75005
75209
  validateWorkspace(workspace);
75006
- const normalized = path67.normalize(workspace);
75210
+ const normalized = path68.normalize(workspace);
75007
75211
  const cached3 = getCachedGraph(normalized);
75008
75212
  if (cached3 && !isDirty(normalized)) {
75009
75213
  try {
75010
75214
  const graphPath = getGraphPath(workspace);
75011
- if (existsSync37(graphPath)) {
75215
+ if (existsSync39(graphPath)) {
75012
75216
  const stats = await fsPromises6.stat(graphPath);
75013
75217
  const cachedMtime = getCachedMtime(normalized);
75014
75218
  if (cachedMtime !== undefined && stats.mtimeMs !== cachedMtime) {
@@ -75025,7 +75229,7 @@ async function loadGraph(workspace) {
75025
75229
  }
75026
75230
  try {
75027
75231
  const graphPath = getGraphPath(workspace);
75028
- if (!existsSync37(graphPath)) {
75232
+ if (!existsSync39(graphPath)) {
75029
75233
  return null;
75030
75234
  }
75031
75235
  const stats = await fsPromises6.stat(graphPath);
@@ -75097,28 +75301,28 @@ async function saveGraph(workspace, graph, options) {
75097
75301
  if (!Array.isArray(graph.edges)) {
75098
75302
  throw new Error("Graph must have edges array");
75099
75303
  }
75100
- const normalizedWorkspace = path67.normalize(workspace);
75304
+ const normalizedWorkspace = path68.normalize(workspace);
75101
75305
  let realWorkspace;
75102
75306
  try {
75103
75307
  realWorkspace = realpathSync7(workspace);
75104
75308
  } catch {
75105
75309
  realWorkspace = normalizedWorkspace;
75106
75310
  }
75107
- const normalizedGraphRoot = path67.normalize(graph.workspaceRoot);
75311
+ const normalizedGraphRoot = path68.normalize(graph.workspaceRoot);
75108
75312
  let realGraphRoot;
75109
75313
  try {
75110
75314
  realGraphRoot = realpathSync7(graph.workspaceRoot);
75111
75315
  } catch {
75112
75316
  realGraphRoot = normalizedGraphRoot;
75113
75317
  }
75114
- if (path67.normalize(realWorkspace) !== path67.normalize(realGraphRoot)) {
75318
+ if (path68.normalize(realWorkspace) !== path68.normalize(realGraphRoot)) {
75115
75319
  throw new Error(`Graph workspaceRoot mismatch: graph was built for "${graph.workspaceRoot}" but save was called for "${workspace}"`);
75116
75320
  }
75117
75321
  const normalized = normalizedWorkspace;
75118
75322
  const graphPath = getGraphPath(workspace);
75119
75323
  updateGraphMetadata(graph);
75120
75324
  const tempPath = `${graphPath}.tmp.${Date.now()}.${Math.floor(Math.random() * 1e9)}`;
75121
- await fsPromises6.mkdir(path67.dirname(tempPath), { recursive: true });
75325
+ await fsPromises6.mkdir(path68.dirname(tempPath), { recursive: true });
75122
75326
  let lastError = null;
75123
75327
  try {
75124
75328
  if (options?.createAtomic) {
@@ -75186,12 +75390,12 @@ async function updateGraphForFiles(workspaceRoot, filePaths, options) {
75186
75390
  return graph2;
75187
75391
  }
75188
75392
  const graph = existingGraph;
75189
- const absoluteRoot = path68.resolve(workspaceRoot);
75393
+ const absoluteRoot = path69.resolve(workspaceRoot);
75190
75394
  const maxFileSize = 1024 * 1024;
75191
75395
  const updatedPaths = new Set;
75192
75396
  for (const rawFilePath of filePaths) {
75193
75397
  const normalizedPath = normalizeGraphPath(rawFilePath);
75194
- const fileExists = existsSync38(rawFilePath);
75398
+ const fileExists = existsSync40(rawFilePath);
75195
75399
  if (fileExists) {
75196
75400
  graph.edges = graph.edges.filter((e) => normalizeGraphPath(e.source) !== normalizedPath);
75197
75401
  const result = scanFile(rawFilePath, absoluteRoot, maxFileSize);
@@ -75226,12 +75430,12 @@ async function updateGraphForFiles(workspaceRoot, filePaths, options) {
75226
75430
  await saveGraph(workspaceRoot, rebuiltGraph);
75227
75431
  return rebuiltGraph;
75228
75432
  }
75229
- const normalizedWorkspace = path68.normalize(workspaceRoot);
75433
+ const normalizedWorkspace = path69.normalize(workspaceRoot);
75230
75434
  const loadedMtime = getCachedMtime(normalizedWorkspace);
75231
75435
  if (loadedMtime !== undefined) {
75232
75436
  try {
75233
75437
  const graphPath = getGraphPath(workspaceRoot);
75234
- if (existsSync38(graphPath)) {
75438
+ if (existsSync40(graphPath)) {
75235
75439
  const currentStats = await fsPromises7.stat(graphPath);
75236
75440
  if (currentStats.mtimeMs !== loadedMtime) {
75237
75441
  warn(`[repo-graph] Concurrent modification detected — falling back to full rebuild`);
@@ -75324,7 +75528,7 @@ function createRepoGraphBuilderHook(workspaceRoot, deps) {
75324
75528
  return;
75325
75529
  if (!isSupportedSourceFile(filePath))
75326
75530
  return;
75327
- const absoluteFilePath = path69.isAbsolute(filePath) ? filePath : path69.resolve(workspaceRoot, filePath);
75531
+ const absoluteFilePath = path70.isAbsolute(filePath) ? filePath : path70.resolve(workspaceRoot, filePath);
75328
75532
  let realFilePath;
75329
75533
  try {
75330
75534
  realFilePath = realpathSync8(absoluteFilePath);
@@ -75351,7 +75555,7 @@ function createRepoGraphBuilderHook(workspaceRoot, deps) {
75351
75555
  try {
75352
75556
  await _updateGraphForFiles(workspaceRoot, [absoluteFilePath]);
75353
75557
  consecutiveFailures = 0;
75354
- log(`[repo-graph] Incremental update for ${path69.basename(filePath)}`);
75558
+ log(`[repo-graph] Incremental update for ${path70.basename(filePath)}`);
75355
75559
  } catch (error93) {
75356
75560
  const message = error93 instanceof Error ? error93.message : String(error93);
75357
75561
  consecutiveFailures++;
@@ -75374,14 +75578,14 @@ init_manager2();
75374
75578
  init_detector();
75375
75579
  init_manager();
75376
75580
  import * as fs54 from "node:fs";
75377
- import * as path79 from "node:path";
75581
+ import * as path80 from "node:path";
75378
75582
 
75379
75583
  // src/services/decision-drift-analyzer.ts
75380
75584
  init_utils2();
75381
75585
  init_manager();
75382
75586
  init_utils();
75383
75587
  import * as fs46 from "node:fs";
75384
- import * as path70 from "node:path";
75588
+ import * as path71 from "node:path";
75385
75589
  var DEFAULT_DRIFT_CONFIG = {
75386
75590
  staleThresholdPhases: 1,
75387
75591
  detectContradictions: true,
@@ -75535,7 +75739,7 @@ async function analyzeDecisionDrift(directory, config3 = {}) {
75535
75739
  currentPhase = legacyPhase;
75536
75740
  }
75537
75741
  }
75538
- const contextPath = path70.join(directory, ".swarm", "context.md");
75742
+ const contextPath = path71.join(directory, ".swarm", "context.md");
75539
75743
  let contextContent = "";
75540
75744
  try {
75541
75745
  if (fs46.existsSync(contextPath)) {
@@ -75674,7 +75878,7 @@ init_utils();
75674
75878
  init_constants();
75675
75879
  init_schema();
75676
75880
  import * as fs47 from "node:fs/promises";
75677
- import * as path71 from "node:path";
75881
+ import * as path72 from "node:path";
75678
75882
  function safeGet(obj, key) {
75679
75883
  if (!obj || !Object.hasOwn(obj, key))
75680
75884
  return;
@@ -75906,9 +76110,9 @@ async function handleDebuggingSpiral(match, taskId, directory) {
75906
76110
  let eventLogged = false;
75907
76111
  let checkpointCreated = false;
75908
76112
  try {
75909
- const swarmDir = path71.join(directory, ".swarm");
76113
+ const swarmDir = path72.join(directory, ".swarm");
75910
76114
  await fs47.mkdir(swarmDir, { recursive: true });
75911
- const eventsPath = path71.join(swarmDir, "events.jsonl");
76115
+ const eventsPath = path72.join(swarmDir, "events.jsonl");
75912
76116
  await fs47.appendFile(eventsPath, `${formatDebuggingSpiralEvent(match, taskId)}
75913
76117
  `);
75914
76118
  eventLogged = true;
@@ -76044,7 +76248,7 @@ import * as fs51 from "node:fs";
76044
76248
 
76045
76249
  // src/graph/graph-builder.ts
76046
76250
  import * as fs49 from "node:fs";
76047
- import * as path74 from "node:path";
76251
+ import * as path75 from "node:path";
76048
76252
 
76049
76253
  // node_modules/yocto-queue/index.js
76050
76254
  class Node {
@@ -76205,7 +76409,7 @@ function validateConcurrency(concurrency) {
76205
76409
  // src/graph/import-extractor.ts
76206
76410
  init_path_security();
76207
76411
  import * as fs48 from "node:fs";
76208
- import * as path72 from "node:path";
76412
+ import * as path73 from "node:path";
76209
76413
  var SOURCE_EXTENSIONS2 = [
76210
76414
  ".ts",
76211
76415
  ".tsx",
@@ -76250,14 +76454,14 @@ function getLanguageFromExtension(ext) {
76250
76454
  return null;
76251
76455
  }
76252
76456
  function toRelForwardSlash(absPath, root) {
76253
- return path72.relative(root, absPath).replace(/\\/g, "/");
76457
+ return path73.relative(root, absPath).replace(/\\/g, "/");
76254
76458
  }
76255
76459
  function tryResolveTSJS(rawModule, sourceFileAbs) {
76256
76460
  if (!rawModule.startsWith(".") && !rawModule.startsWith("/")) {
76257
76461
  return null;
76258
76462
  }
76259
- const sourceDir = path72.dirname(sourceFileAbs);
76260
- const baseAbs = path72.resolve(sourceDir, rawModule);
76463
+ const sourceDir = path73.dirname(sourceFileAbs);
76464
+ const baseAbs = path73.resolve(sourceDir, rawModule);
76261
76465
  const probe = (basePath) => {
76262
76466
  for (const ext of RESOLVE_EXTENSION_CANDIDATES) {
76263
76467
  const test = basePath + ext;
@@ -76268,7 +76472,7 @@ function tryResolveTSJS(rawModule, sourceFileAbs) {
76268
76472
  } catch {}
76269
76473
  }
76270
76474
  for (const indexFile of RESOLVE_INDEX_CANDIDATES) {
76271
- const test = path72.join(basePath, indexFile);
76475
+ const test = path73.join(basePath, indexFile);
76272
76476
  try {
76273
76477
  const stat6 = fs48.statSync(test);
76274
76478
  if (stat6.isFile())
@@ -76298,13 +76502,13 @@ function tryResolvePython(rawModule, sourceFileAbs, workspaceRoot) {
76298
76502
  }
76299
76503
  const remainder = rawModule.slice(leadingDots).replace(/\./g, "/");
76300
76504
  const upDirs = "../".repeat(Math.max(0, leadingDots - 1));
76301
- const sourceDir = path72.dirname(sourceFileAbs);
76302
- const baseAbs = path72.resolve(sourceDir, upDirs + remainder);
76505
+ const sourceDir = path73.dirname(sourceFileAbs);
76506
+ const baseAbs = path73.resolve(sourceDir, upDirs + remainder);
76303
76507
  const accept = (test) => {
76304
76508
  try {
76305
76509
  const stat6 = fs48.statSync(test);
76306
76510
  if (stat6.isFile()) {
76307
- const rel = path72.relative(workspaceRoot, test).replace(/\\/g, "/");
76511
+ const rel = path73.relative(workspaceRoot, test).replace(/\\/g, "/");
76308
76512
  if (rel.startsWith(".."))
76309
76513
  return null;
76310
76514
  return test;
@@ -76318,7 +76522,7 @@ function tryResolvePython(rawModule, sourceFileAbs, workspaceRoot) {
76318
76522
  return hit;
76319
76523
  }
76320
76524
  for (const indexFile of PY_INDEX_CANDIDATES) {
76321
- const hit = accept(path72.join(baseAbs, indexFile));
76525
+ const hit = accept(path73.join(baseAbs, indexFile));
76322
76526
  if (hit)
76323
76527
  return hit;
76324
76528
  }
@@ -76689,7 +76893,7 @@ function parseRustUses(content) {
76689
76893
  }
76690
76894
  function extractImports5(opts) {
76691
76895
  const { absoluteFilePath, workspaceRoot } = opts;
76692
- const ext = path72.extname(absoluteFilePath).toLowerCase();
76896
+ const ext = path73.extname(absoluteFilePath).toLowerCase();
76693
76897
  const language = getLanguageFromExtension(ext);
76694
76898
  if (!language)
76695
76899
  return [];
@@ -76740,9 +76944,9 @@ function extractImports5(opts) {
76740
76944
  }
76741
76945
 
76742
76946
  // src/graph/symbol-extractor.ts
76743
- import * as path73 from "node:path";
76947
+ import * as path74 from "node:path";
76744
76948
  function extractExportedSymbols(relativeFilePath, workspaceRoot) {
76745
- const ext = path73.extname(relativeFilePath).toLowerCase();
76949
+ const ext = path74.extname(relativeFilePath).toLowerCase();
76746
76950
  const language = getLanguageFromExtension(ext);
76747
76951
  if (!language)
76748
76952
  return [];
@@ -76831,15 +77035,15 @@ function findSourceFiles(workspaceRoot, skipDirs = DEFAULT_SKIP_DIRS) {
76831
77035
  if (entry.isDirectory()) {
76832
77036
  if (skipDirs.has(entry.name))
76833
77037
  continue;
76834
- stack.push(path74.join(dir, entry.name));
77038
+ stack.push(path75.join(dir, entry.name));
76835
77039
  continue;
76836
77040
  }
76837
77041
  if (!entry.isFile())
76838
77042
  continue;
76839
- const ext = path74.extname(entry.name).toLowerCase();
77043
+ const ext = path75.extname(entry.name).toLowerCase();
76840
77044
  if (!SOURCE_EXT_SET.has(ext))
76841
77045
  continue;
76842
- out2.push(path74.join(dir, entry.name));
77046
+ out2.push(path75.join(dir, entry.name));
76843
77047
  }
76844
77048
  }
76845
77049
  return out2;
@@ -76867,7 +77071,7 @@ async function buildRepoGraph(workspaceRoot, options = {}) {
76867
77071
  };
76868
77072
  }
76869
77073
  async function processFile(absoluteFilePath, workspaceRoot) {
76870
- const ext = path74.extname(absoluteFilePath).toLowerCase();
77074
+ const ext = path75.extname(absoluteFilePath).toLowerCase();
76871
77075
  const language = getLanguageFromExtension(ext);
76872
77076
  if (!language)
76873
77077
  return null;
@@ -76887,7 +77091,7 @@ async function processFile(absoluteFilePath, workspaceRoot) {
76887
77091
  } catch {
76888
77092
  return null;
76889
77093
  }
76890
- const relPath = path74.relative(workspaceRoot, absoluteFilePath).replace(/\\/g, "/");
77094
+ const relPath = path75.relative(workspaceRoot, absoluteFilePath).replace(/\\/g, "/");
76891
77095
  const imports = extractImports5({
76892
77096
  absoluteFilePath,
76893
77097
  workspaceRoot,
@@ -77129,10 +77333,10 @@ function formatSummary(opts) {
77129
77333
  // src/graph/graph-store.ts
77130
77334
  import * as crypto6 from "node:crypto";
77131
77335
  import * as fs50 from "node:fs";
77132
- import * as path75 from "node:path";
77336
+ import * as path76 from "node:path";
77133
77337
  var SWARM_DIR = ".swarm";
77134
77338
  function getGraphPath2(workspaceRoot) {
77135
- return path75.join(workspaceRoot, SWARM_DIR, REPO_GRAPH_FILENAME2);
77339
+ return path76.join(workspaceRoot, SWARM_DIR, REPO_GRAPH_FILENAME2);
77136
77340
  }
77137
77341
  function loadGraph2(workspaceRoot) {
77138
77342
  const file3 = getGraphPath2(workspaceRoot);
@@ -77154,7 +77358,7 @@ function loadGraph2(workspaceRoot) {
77154
77358
  }
77155
77359
  function saveGraph2(workspaceRoot, graph) {
77156
77360
  const file3 = getGraphPath2(workspaceRoot);
77157
- const dir = path75.dirname(file3);
77361
+ const dir = path76.dirname(file3);
77158
77362
  try {
77159
77363
  const stat6 = fs50.lstatSync(dir);
77160
77364
  if (stat6.isSymbolicLink()) {
@@ -77260,7 +77464,7 @@ function buildReviewerBlastRadiusBlock(directory, changedFiles) {
77260
77464
  // src/hooks/semantic-diff-injection.ts
77261
77465
  import * as child_process5 from "node:child_process";
77262
77466
  import * as fs52 from "node:fs";
77263
- import * as path77 from "node:path";
77467
+ import * as path78 from "node:path";
77264
77468
 
77265
77469
  // src/diff/ast-diff.ts
77266
77470
  init_tree_sitter();
@@ -78007,17 +78211,17 @@ async function buildSemanticDiffBlock(directory, changedFiles, maxFiles = 10) {
78007
78211
  const fileConsumers = {};
78008
78212
  if (graph) {
78009
78213
  for (const f of filesToProcess) {
78010
- const relativePath = path77.isAbsolute(f) ? path77.relative(directory, f) : f;
78214
+ const relativePath = path78.isAbsolute(f) ? path78.relative(directory, f) : f;
78011
78215
  const normalized = normalizeGraphPath2(relativePath);
78012
78216
  fileConsumers[normalized] = getImporters(graph, normalized).length;
78013
78217
  fileConsumers[f] = fileConsumers[normalized];
78014
78218
  }
78015
78219
  }
78016
78220
  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)) {
78221
+ const normalizedPath = path78.normalize(filePath);
78222
+ const resolvedPath = path78.resolve(directory, normalizedPath);
78223
+ const relativeToDir = path78.relative(directory, resolvedPath);
78224
+ if (relativeToDir.startsWith("..") || path78.isAbsolute(relativeToDir)) {
78021
78225
  continue;
78022
78226
  }
78023
78227
  try {
@@ -78044,7 +78248,7 @@ async function buildSemanticDiffBlock(directory, changedFiles, maxFiles = 10) {
78044
78248
  stdio: "pipe",
78045
78249
  maxBuffer: 5 * 1024 * 1024
78046
78250
  }) : "";
78047
- const newContent = fs52.readFileSync(path77.join(directory, filePath), "utf-8");
78251
+ const newContent = fs52.readFileSync(path78.join(directory, filePath), "utf-8");
78048
78252
  const astResult = await computeASTDiff(filePath, oldContent, newContent);
78049
78253
  if (astResult && (astResult.changes.length > 0 || astResult.error !== undefined)) {
78050
78254
  astDiffs.push(astResult);
@@ -78071,6 +78275,49 @@ ${markdown}`;
78071
78275
 
78072
78276
  // src/hooks/system-enhancer.ts
78073
78277
  init_utils2();
78278
+ function buildSpecDriftAdvisory(args2) {
78279
+ const lines = [
78280
+ "[spec-drift]",
78281
+ `Reason: ${args2.reason}`,
78282
+ `Stored spec hash: ${args2.storedHash}`,
78283
+ `Current spec hash: ${args2.currentHash ?? "(spec.md missing)"}`,
78284
+ "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."
78285
+ ];
78286
+ if (args2.midLoadRemovals) {
78287
+ lines.push(`Auto-removed during recovery: ${args2.midLoadRemovals.count} task(s) ` + `(source: ${args2.midLoadRemovals.source}). See ` + ".swarm/plan-ledger.jsonl for IDs.");
78288
+ }
78289
+ return lines.join(`
78290
+ `);
78291
+ }
78292
+ function readSpecStalenessSnapshot2(directory) {
78293
+ try {
78294
+ const p = path80.join(directory, ".swarm", "spec-staleness.json");
78295
+ if (!fs54.existsSync(p))
78296
+ return null;
78297
+ const raw = fs54.readFileSync(p, "utf-8");
78298
+ const parsed = JSON.parse(raw);
78299
+ if (typeof parsed?.specHash_plan === "string" && (typeof parsed?.specHash_current === "string" || parsed?.specHash_current === null)) {
78300
+ return {
78301
+ specHash_plan: parsed.specHash_plan,
78302
+ specHash_current: parsed.specHash_current
78303
+ };
78304
+ }
78305
+ } catch {}
78306
+ return null;
78307
+ }
78308
+ function maybeAppendSpecDriftAdvisory(output, directory, plan) {
78309
+ if (!plan?._specStale)
78310
+ return;
78311
+ const snap = readSpecStalenessSnapshot2(directory);
78312
+ const storedHash = snap?.specHash_plan ?? plan.specHash ?? "(unknown — plan missing specHash)";
78313
+ const currentHash = snap?.specHash_current ?? null;
78314
+ output.system.push(buildSpecDriftAdvisory({
78315
+ reason: plan._specStaleReason ?? "spec.md changed since plan was saved",
78316
+ currentHash,
78317
+ storedHash,
78318
+ midLoadRemovals: plan._midLoadRemovals
78319
+ }));
78320
+ }
78074
78321
  function extractAgentPrefix(fullAgentName) {
78075
78322
  if (!fullAgentName)
78076
78323
  return "";
@@ -78392,7 +78639,7 @@ function createSystemEnhancerHook(config3, directory) {
78392
78639
  await fs54.promises.writeFile(darkMatterPath, darkMatterReport, "utf-8");
78393
78640
  warn(`[system-enhancer] Dark matter scan complete: ${darkMatter.length} co-change patterns found`);
78394
78641
  try {
78395
- const projectName = path79.basename(path79.resolve(directory));
78642
+ const projectName = path80.basename(path80.resolve(directory));
78396
78643
  const knowledgeEntries = darkMatterToKnowledgeEntries2(darkMatter, projectName);
78397
78644
  const knowledgePath = resolveSwarmKnowledgePath(directory);
78398
78645
  const existingEntries = await readKnowledge(knowledgePath);
@@ -78433,6 +78680,7 @@ function createSystemEnhancerHook(config3, directory) {
78433
78680
  } catch (error93) {
78434
78681
  warn(`Failed to load plan: ${error93 instanceof Error ? error93.message : String(error93)}`);
78435
78682
  }
78683
+ maybeAppendSpecDriftAdvisory(output, directory, plan2);
78436
78684
  const mode = await detectArchitectMode(directory);
78437
78685
  let planContent = null;
78438
78686
  let phaseHeader = "";
@@ -78591,7 +78839,7 @@ ${lines.join(`
78591
78839
  try {
78592
78840
  const taskId_ccp = ccpSession?.currentTaskId;
78593
78841
  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`);
78842
+ const evidencePath = path80.join(directory, ".swarm", "evidence", `${taskId_ccp}.json`);
78595
78843
  if (fs54.existsSync(evidencePath)) {
78596
78844
  const evidenceContent = fs54.readFileSync(evidencePath, "utf-8");
78597
78845
  const evidenceData = JSON.parse(evidenceContent);
@@ -78806,6 +79054,7 @@ ${budgetWarning}`);
78806
79054
  } catch (error93) {
78807
79055
  warn(`Failed to load plan: ${error93 instanceof Error ? error93.message : String(error93)}`);
78808
79056
  }
79057
+ maybeAppendSpecDriftAdvisory(output, directory, plan);
78809
79058
  let currentPhase = null;
78810
79059
  let currentTask = null;
78811
79060
  if (plan && plan.migration_status !== "migration_failed") {
@@ -79754,7 +80003,7 @@ import * as fs56 from "node:fs";
79754
80003
  // src/full-auto/policy.ts
79755
80004
  init_constants();
79756
80005
  import * as fs55 from "node:fs";
79757
- import * as path80 from "node:path";
80006
+ import * as path81 from "node:path";
79758
80007
  var READ_ONLY_TOOLS = new Set([
79759
80008
  "check_gate_status",
79760
80009
  "completion_verify",
@@ -79949,11 +80198,11 @@ function normalizePath3(p) {
79949
80198
  function isWithinDirectory(target, root) {
79950
80199
  if (!target || !root)
79951
80200
  return false;
79952
- const resolvedTarget = path80.resolve(target);
79953
- const resolvedRoot = path80.resolve(root);
80201
+ const resolvedTarget = path81.resolve(target);
80202
+ const resolvedRoot = path81.resolve(root);
79954
80203
  if (resolvedTarget === resolvedRoot)
79955
80204
  return true;
79956
- const withSep = resolvedRoot.endsWith(path80.sep) ? resolvedRoot : resolvedRoot + path80.sep;
80205
+ const withSep = resolvedRoot.endsWith(path81.sep) ? resolvedRoot : resolvedRoot + path81.sep;
79957
80206
  if (process.platform === "win32") {
79958
80207
  return resolvedTarget.toLowerCase().startsWith(withSep.toLowerCase());
79959
80208
  }
@@ -80012,7 +80261,7 @@ function classifyPathRisk(filePath, context) {
80012
80261
  highRiskBuild: false
80013
80262
  };
80014
80263
  }
80015
- const absolute = path80.isAbsolute(filePath) ? filePath : path80.resolve(context.directory, filePath);
80264
+ const absolute = path81.isAbsolute(filePath) ? filePath : path81.resolve(context.directory, filePath);
80016
80265
  const resolvedAbsolute = (() => {
80017
80266
  try {
80018
80267
  let candidate = absolute;
@@ -80028,7 +80277,7 @@ function classifyPathRisk(filePath, context) {
80028
80277
  }
80029
80278
  return absolute;
80030
80279
  }
80031
- const parent = path80.dirname(candidate);
80280
+ const parent = path81.dirname(candidate);
80032
80281
  if (parent === candidate)
80033
80282
  break;
80034
80283
  candidate = parent;
@@ -80040,7 +80289,7 @@ function classifyPathRisk(filePath, context) {
80040
80289
  }
80041
80290
  })();
80042
80291
  const withinProjectRoot = isWithinDirectory(absolute, context.directory) && isWithinDirectory(resolvedAbsolute, context.directory);
80043
- const relative17 = path80.relative(context.directory, absolute).replace(/\\/g, "/");
80292
+ const relative17 = path81.relative(context.directory, absolute).replace(/\\/g, "/");
80044
80293
  let withinDeclaredScope = null;
80045
80294
  if (Array.isArray(context.declaredScope)) {
80046
80295
  withinDeclaredScope = context.declaredScope.length === 0 ? false : context.declaredScope.some((scope) => {
@@ -80350,7 +80599,7 @@ function classifyFullAutoToolAction(input) {
80350
80599
  recoverable: true
80351
80600
  };
80352
80601
  }
80353
- if (isProtectedPath(path80.relative(input.directory, path80.resolve(input.directory, p)), config3)) {
80602
+ if (isProtectedPath(path81.relative(input.directory, path81.resolve(input.directory, p)), config3)) {
80354
80603
  return {
80355
80604
  action: "escalate_critic",
80356
80605
  reason: `write to protected path requires critic approval: ${p}`,
@@ -81124,7 +81373,7 @@ init_hive_promoter();
81124
81373
 
81125
81374
  // src/hooks/incremental-verify.ts
81126
81375
  import * as fs58 from "node:fs";
81127
- import * as path81 from "node:path";
81376
+ import * as path82 from "node:path";
81128
81377
 
81129
81378
  // src/hooks/spawn-helper.ts
81130
81379
  import * as child_process6 from "node:child_process";
@@ -81202,18 +81451,18 @@ function spawnAsync(command, cwd, timeoutMs) {
81202
81451
  // src/hooks/incremental-verify.ts
81203
81452
  var emittedSkipAdvisories = new Set;
81204
81453
  function detectPackageManager(projectDir) {
81205
- if (fs58.existsSync(path81.join(projectDir, "bun.lockb")))
81454
+ if (fs58.existsSync(path82.join(projectDir, "bun.lockb")))
81206
81455
  return "bun";
81207
- if (fs58.existsSync(path81.join(projectDir, "pnpm-lock.yaml")))
81456
+ if (fs58.existsSync(path82.join(projectDir, "pnpm-lock.yaml")))
81208
81457
  return "pnpm";
81209
- if (fs58.existsSync(path81.join(projectDir, "yarn.lock")))
81458
+ if (fs58.existsSync(path82.join(projectDir, "yarn.lock")))
81210
81459
  return "yarn";
81211
- if (fs58.existsSync(path81.join(projectDir, "package-lock.json")))
81460
+ if (fs58.existsSync(path82.join(projectDir, "package-lock.json")))
81212
81461
  return "npm";
81213
81462
  return "bun";
81214
81463
  }
81215
81464
  function detectTypecheckCommand(projectDir) {
81216
- const pkgPath = path81.join(projectDir, "package.json");
81465
+ const pkgPath = path82.join(projectDir, "package.json");
81217
81466
  if (fs58.existsSync(pkgPath)) {
81218
81467
  try {
81219
81468
  const pkg = JSON.parse(fs58.readFileSync(pkgPath, "utf8"));
@@ -81230,8 +81479,8 @@ function detectTypecheckCommand(projectDir) {
81230
81479
  ...pkg.dependencies,
81231
81480
  ...pkg.devDependencies
81232
81481
  };
81233
- if (!deps?.typescript && !fs58.existsSync(path81.join(projectDir, "tsconfig.json"))) {}
81234
- const hasTSMarkers = deps?.typescript || fs58.existsSync(path81.join(projectDir, "tsconfig.json"));
81482
+ if (!deps?.typescript && !fs58.existsSync(path82.join(projectDir, "tsconfig.json"))) {}
81483
+ const hasTSMarkers = deps?.typescript || fs58.existsSync(path82.join(projectDir, "tsconfig.json"));
81235
81484
  if (hasTSMarkers) {
81236
81485
  return { command: ["npx", "tsc", "--noEmit"], language: "typescript" };
81237
81486
  }
@@ -81239,13 +81488,13 @@ function detectTypecheckCommand(projectDir) {
81239
81488
  return null;
81240
81489
  }
81241
81490
  }
81242
- if (fs58.existsSync(path81.join(projectDir, "go.mod"))) {
81491
+ if (fs58.existsSync(path82.join(projectDir, "go.mod"))) {
81243
81492
  return { command: ["go", "vet", "./..."], language: "go" };
81244
81493
  }
81245
- if (fs58.existsSync(path81.join(projectDir, "Cargo.toml"))) {
81494
+ if (fs58.existsSync(path82.join(projectDir, "Cargo.toml"))) {
81246
81495
  return { command: ["cargo", "check"], language: "rust" };
81247
81496
  }
81248
- if (fs58.existsSync(path81.join(projectDir, "pyproject.toml")) || fs58.existsSync(path81.join(projectDir, "requirements.txt")) || fs58.existsSync(path81.join(projectDir, "setup.py"))) {
81497
+ if (fs58.existsSync(path82.join(projectDir, "pyproject.toml")) || fs58.existsSync(path82.join(projectDir, "requirements.txt")) || fs58.existsSync(path82.join(projectDir, "setup.py"))) {
81249
81498
  return { command: null, language: "python" };
81250
81499
  }
81251
81500
  try {
@@ -81322,17 +81571,17 @@ init_schema();
81322
81571
  init_state();
81323
81572
  init_logger();
81324
81573
  import { appendFile as appendFile7, mkdir as mkdir15 } from "node:fs/promises";
81325
- import * as path83 from "node:path";
81574
+ import * as path84 from "node:path";
81326
81575
 
81327
81576
  // src/hooks/knowledge-application.ts
81328
81577
  init_logger();
81329
81578
  init_knowledge_store();
81330
81579
  var import_proper_lockfile7 = __toESM(require_proper_lockfile(), 1);
81331
- import { existsSync as existsSync43 } from "node:fs";
81580
+ import { existsSync as existsSync45 } from "node:fs";
81332
81581
  import { appendFile as appendFile6, mkdir as mkdir14, readFile as readFile13 } from "node:fs/promises";
81333
- import * as path82 from "node:path";
81582
+ import * as path83 from "node:path";
81334
81583
  function resolveApplicationLogPath(directory) {
81335
- return path82.join(directory, ".swarm", "knowledge-application.jsonl");
81584
+ return path83.join(directory, ".swarm", "knowledge-application.jsonl");
81336
81585
  }
81337
81586
  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
81587
  function parseAcknowledgments(text) {
@@ -81350,7 +81599,7 @@ function parseAcknowledgments(text) {
81350
81599
  }
81351
81600
  async function appendAudit(directory, record3) {
81352
81601
  const filePath = resolveApplicationLogPath(directory);
81353
- await mkdir14(path82.dirname(filePath), { recursive: true });
81602
+ await mkdir14(path83.dirname(filePath), { recursive: true });
81354
81603
  await appendFile6(filePath, `${JSON.stringify(record3)}
81355
81604
  `, "utf-8");
81356
81605
  }
@@ -81394,7 +81643,7 @@ async function bumpCountersBatch(directory, bumps) {
81394
81643
  if (applyOne(swarm))
81395
81644
  await rewriteKnowledge(swarmPath, swarm);
81396
81645
  const hivePath = resolveHiveKnowledgePath();
81397
- if (existsSync43(hivePath)) {
81646
+ if (existsSync45(hivePath)) {
81398
81647
  const hive = await readKnowledge(hivePath);
81399
81648
  if (applyOne(hive))
81400
81649
  await rewriteKnowledge(hivePath, hive);
@@ -81516,8 +81765,8 @@ async function knowledgeApplicationGateBefore(directory, input, config3) {
81516
81765
  }).catch(() => {});
81517
81766
  }
81518
81767
  async function writeWarnEvent(directory, record3) {
81519
- const filePath = path83.join(directory, ".swarm", "events.jsonl");
81520
- await mkdir15(path83.dirname(filePath), { recursive: true });
81768
+ const filePath = path84.join(directory, ".swarm", "events.jsonl");
81769
+ await mkdir15(path84.dirname(filePath), { recursive: true });
81521
81770
  await appendFile7(filePath, `${JSON.stringify(record3)}
81522
81771
  `, "utf-8");
81523
81772
  }
@@ -82018,7 +82267,7 @@ init_scope_persistence();
82018
82267
  init_state();
82019
82268
  init_delegation_gate();
82020
82269
  init_normalize_tool_name();
82021
- import * as path85 from "node:path";
82270
+ import * as path86 from "node:path";
82022
82271
  var WRITE_TOOLS = new Set(WRITE_TOOL_NAMES);
82023
82272
  function createScopeGuardHook(config3, directory, injectAdvisory) {
82024
82273
  const enabled = config3.enabled ?? true;
@@ -82076,13 +82325,13 @@ function createScopeGuardHook(config3, directory, injectAdvisory) {
82076
82325
  }
82077
82326
  function isFileInScope(filePath, scopeEntries, directory) {
82078
82327
  const dir = directory ?? process.cwd();
82079
- const resolvedFile = path85.resolve(dir, filePath);
82328
+ const resolvedFile = path86.resolve(dir, filePath);
82080
82329
  return scopeEntries.some((scope) => {
82081
- const resolvedScope = path85.resolve(dir, scope);
82330
+ const resolvedScope = path86.resolve(dir, scope);
82082
82331
  if (resolvedFile === resolvedScope)
82083
82332
  return true;
82084
- const rel = path85.relative(resolvedScope, resolvedFile);
82085
- return rel.length > 0 && !rel.startsWith("..") && !path85.isAbsolute(rel);
82333
+ const rel = path86.relative(resolvedScope, resolvedFile);
82334
+ return rel.length > 0 && !rel.startsWith("..") && !path86.isAbsolute(rel);
82086
82335
  });
82087
82336
  }
82088
82337
 
@@ -82134,7 +82383,7 @@ function createSelfReviewHook(config3, injectAdvisory) {
82134
82383
 
82135
82384
  // src/hooks/slop-detector.ts
82136
82385
  import * as fs61 from "node:fs";
82137
- import * as path86 from "node:path";
82386
+ import * as path87 from "node:path";
82138
82387
  var WRITE_EDIT_TOOLS = new Set([
82139
82388
  "write",
82140
82389
  "edit",
@@ -82184,7 +82433,7 @@ function walkFiles(dir, exts, deadline) {
82184
82433
  break;
82185
82434
  if (entry.isSymbolicLink())
82186
82435
  continue;
82187
- const full = path86.join(dir, entry.name);
82436
+ const full = path87.join(dir, entry.name);
82188
82437
  if (entry.isDirectory()) {
82189
82438
  if (entry.name === "node_modules" || entry.name === ".git")
82190
82439
  continue;
@@ -82199,7 +82448,7 @@ function walkFiles(dir, exts, deadline) {
82199
82448
  return results;
82200
82449
  }
82201
82450
  function checkDeadExports(content, projectDir, startTime) {
82202
- const hasPackageJson = fs61.existsSync(path86.join(projectDir, "package.json"));
82451
+ const hasPackageJson = fs61.existsSync(path87.join(projectDir, "package.json"));
82203
82452
  if (!hasPackageJson)
82204
82453
  return null;
82205
82454
  const exportMatches = content.matchAll(/^\+(?:export)\s+(?:function|class|const|type|interface)\s+(\w{3,})/gm);
@@ -82313,14 +82562,14 @@ function checkDuplicateUtility(content, projectDir, startTime, targetFile) {
82313
82562
  for (const utilDir of utilityDirs) {
82314
82563
  if (Date.now() > deadline)
82315
82564
  break;
82316
- const utilPath = path86.join(projectDir, utilDir);
82565
+ const utilPath = path87.join(projectDir, utilDir);
82317
82566
  if (!fs61.existsSync(utilPath))
82318
82567
  continue;
82319
82568
  const files = walkFiles(utilPath, [".ts", ".tsx", ".js", ".jsx"], deadline);
82320
82569
  for (const file3 of files) {
82321
82570
  if (Date.now() > deadline)
82322
82571
  break;
82323
- if (targetFile && path86.resolve(file3) === path86.resolve(targetFile))
82572
+ if (targetFile && path87.resolve(file3) === path87.resolve(targetFile))
82324
82573
  continue;
82325
82574
  try {
82326
82575
  const text = fs61.readFileSync(file3, "utf-8");
@@ -82458,14 +82707,14 @@ function createSteeringConsumedHook(directory) {
82458
82707
  // src/hooks/trajectory-logger.ts
82459
82708
  init_manager2();
82460
82709
  import * as fs64 from "node:fs/promises";
82461
- import * as path88 from "node:path";
82710
+ import * as path89 from "node:path";
82462
82711
 
82463
82712
  // src/prm/trajectory-store.ts
82464
82713
  init_utils2();
82465
82714
  import * as fs63 from "node:fs/promises";
82466
- import * as path87 from "node:path";
82715
+ import * as path88 from "node:path";
82467
82716
  function getTrajectoryPath(sessionId, directory) {
82468
- const relativePath = path87.join("trajectories", `${sessionId}.jsonl`);
82717
+ const relativePath = path88.join("trajectories", `${sessionId}.jsonl`);
82469
82718
  return validateSwarmPath(directory, relativePath);
82470
82719
  }
82471
82720
  var _inMemoryTrajectoryCache = new Map;
@@ -82484,7 +82733,7 @@ async function appendTrajectoryEntry(sessionId, entry, directory, maxLines = 100
82484
82733
  _inMemoryTrajectoryCache.set(sessionId, cached3);
82485
82734
  }
82486
82735
  const trajectoryPath = getTrajectoryPath(sessionId, directory);
82487
- await fs63.mkdir(path87.dirname(trajectoryPath), { recursive: true });
82736
+ await fs63.mkdir(path88.dirname(trajectoryPath), { recursive: true });
82488
82737
  const line = `${JSON.stringify(entry)}
82489
82738
  `;
82490
82739
  await fs63.appendFile(trajectoryPath, line, "utf-8");
@@ -82523,7 +82772,7 @@ async function cleanupOldTrajectoryFiles(directory, maxAgeDays = 7) {
82523
82772
  for (const entry of entries) {
82524
82773
  if (!entry.isFile())
82525
82774
  continue;
82526
- const filePath = path87.join(dirPath, entry.name);
82775
+ const filePath = path88.join(dirPath, entry.name);
82527
82776
  try {
82528
82777
  const stat8 = await fs63.stat(filePath);
82529
82778
  if (now - stat8.mtimeMs > cutoffMs) {
@@ -82715,10 +82964,10 @@ function createTrajectoryLoggerHook(config3, _directory) {
82715
82964
  elapsed_ms
82716
82965
  };
82717
82966
  const sanitized = sanitizeTaskId2(taskId);
82718
- const relativePath = path88.join("evidence", sanitized, "trajectory.jsonl");
82967
+ const relativePath = path89.join("evidence", sanitized, "trajectory.jsonl");
82719
82968
  const trajectoryPath = validateSwarmPath(_directory, relativePath);
82720
82969
  try {
82721
- await fs64.mkdir(path88.dirname(trajectoryPath), { recursive: true });
82970
+ await fs64.mkdir(path89.dirname(trajectoryPath), { recursive: true });
82722
82971
  const line = `${JSON.stringify(entry)}
82723
82972
  `;
82724
82973
  await fs64.appendFile(trajectoryPath, line, "utf-8");
@@ -83269,16 +83518,16 @@ init_telemetry();
83269
83518
 
83270
83519
  // src/prm/replay.ts
83271
83520
  import { promises as fs65 } from "node:fs";
83272
- import path89 from "node:path";
83521
+ import path90 from "node:path";
83273
83522
  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);
83523
+ const resolvedTarget = path90.resolve(targetPath);
83524
+ const resolvedBase = path90.resolve(basePath);
83525
+ const rel = path90.relative(resolvedBase, resolvedTarget);
83526
+ return !rel.startsWith("..") && !path90.isAbsolute(rel);
83278
83527
  }
83279
83528
  function isWithinReplaysDir(targetPath) {
83280
- const resolved = path89.resolve(targetPath);
83281
- const parts2 = resolved.split(path89.sep);
83529
+ const resolved = path90.resolve(targetPath);
83530
+ const parts2 = resolved.split(path90.sep);
83282
83531
  for (let i2 = 0;i2 < parts2.length - 1; i2++) {
83283
83532
  if (parts2[i2] === ".swarm" && parts2[i2 + 1] === "replays") {
83284
83533
  return true;
@@ -83291,10 +83540,10 @@ function sanitizeFilename(input) {
83291
83540
  }
83292
83541
  async function startReplayRecording(sessionID, directory) {
83293
83542
  try {
83294
- const replayDir = path89.join(directory, ".swarm", "replays");
83543
+ const replayDir = path90.join(directory, ".swarm", "replays");
83295
83544
  const safeSessionID = sanitizeFilename(sessionID);
83296
83545
  const filename = `${safeSessionID}-${Date.now()}.jsonl`;
83297
- const filepath = path89.join(replayDir, filename);
83546
+ const filepath = path90.join(replayDir, filename);
83298
83547
  if (!isPathSafe2(filepath, replayDir)) {
83299
83548
  console.warn(`[replay] Invalid path detected - path traversal attempt blocked for session ${sessionID}`);
83300
83549
  return null;
@@ -83668,7 +83917,7 @@ init_telemetry();
83668
83917
  init_dist();
83669
83918
  init_create_tool();
83670
83919
  import * as fs66 from "node:fs";
83671
- import * as path90 from "node:path";
83920
+ import * as path91 from "node:path";
83672
83921
  init_path_security();
83673
83922
  var WINDOWS_RESERVED_NAMES2 = /^(con|prn|aux|nul|com[1-9]|lpt[1-9])(\.|:|$)/i;
83674
83923
  function containsWindowsAttacks2(str) {
@@ -83685,14 +83934,14 @@ function containsWindowsAttacks2(str) {
83685
83934
  }
83686
83935
  function isPathInWorkspace2(filePath, workspace) {
83687
83936
  try {
83688
- const resolvedPath = path90.resolve(workspace, filePath);
83937
+ const resolvedPath = path91.resolve(workspace, filePath);
83689
83938
  if (!fs66.existsSync(resolvedPath)) {
83690
83939
  return true;
83691
83940
  }
83692
83941
  const realWorkspace = fs66.realpathSync(workspace);
83693
83942
  const realResolvedPath = fs66.realpathSync(resolvedPath);
83694
- const relativePath = path90.relative(realWorkspace, realResolvedPath);
83695
- if (relativePath.startsWith("..") || path90.isAbsolute(relativePath)) {
83943
+ const relativePath = path91.relative(realWorkspace, realResolvedPath);
83944
+ if (relativePath.startsWith("..") || path91.isAbsolute(relativePath)) {
83696
83945
  return false;
83697
83946
  }
83698
83947
  return true;
@@ -83701,7 +83950,7 @@ function isPathInWorkspace2(filePath, workspace) {
83701
83950
  }
83702
83951
  }
83703
83952
  function processFile2(file3, cwd, exportedOnly) {
83704
- const ext = path90.extname(file3);
83953
+ const ext = path91.extname(file3);
83705
83954
  if (containsControlChars(file3)) {
83706
83955
  return {
83707
83956
  file: file3,
@@ -83734,7 +83983,7 @@ function processFile2(file3, cwd, exportedOnly) {
83734
83983
  errorType: "path-outside-workspace"
83735
83984
  };
83736
83985
  }
83737
- const fullPath = path90.join(cwd, file3);
83986
+ const fullPath = path91.join(cwd, file3);
83738
83987
  if (!fs66.existsSync(fullPath)) {
83739
83988
  return {
83740
83989
  file: file3,
@@ -84026,15 +84275,15 @@ init_task_id();
84026
84275
  init_create_tool();
84027
84276
  init_resolve_working_directory();
84028
84277
  import * as fs67 from "node:fs";
84029
- import * as path91 from "node:path";
84278
+ import * as path92 from "node:path";
84030
84279
  var EVIDENCE_DIR = ".swarm/evidence";
84031
84280
  function isValidTaskId3(taskId) {
84032
84281
  return isStrictTaskId(taskId);
84033
84282
  }
84034
84283
  function isPathWithinSwarm(filePath, workspaceRoot) {
84035
- const normalizedWorkspace = path91.resolve(workspaceRoot);
84036
- const swarmPath = path91.join(normalizedWorkspace, ".swarm", "evidence");
84037
- const normalizedPath = path91.resolve(filePath);
84284
+ const normalizedWorkspace = path92.resolve(workspaceRoot);
84285
+ const swarmPath = path92.join(normalizedWorkspace, ".swarm", "evidence");
84286
+ const normalizedPath = path92.resolve(filePath);
84038
84287
  return normalizedPath.startsWith(swarmPath);
84039
84288
  }
84040
84289
  function readEvidenceFile(evidencePath) {
@@ -84115,7 +84364,7 @@ var check_gate_status = createSwarmTool({
84115
84364
  };
84116
84365
  return JSON.stringify(errorResult, null, 2);
84117
84366
  }
84118
- const evidencePath = path91.join(directory, EVIDENCE_DIR, `${taskIdInput}.json`);
84367
+ const evidencePath = path92.join(directory, EVIDENCE_DIR, `${taskIdInput}.json`);
84119
84368
  if (!isPathWithinSwarm(evidencePath, directory)) {
84120
84369
  const errorResult = {
84121
84370
  taskId: taskIdInput,
@@ -84212,7 +84461,7 @@ init_state();
84212
84461
  init_create_tool();
84213
84462
  init_resolve_working_directory();
84214
84463
  import * as fs68 from "node:fs";
84215
- import * as path92 from "node:path";
84464
+ import * as path93 from "node:path";
84216
84465
  function extractMatches(regex, text) {
84217
84466
  return Array.from(text.matchAll(regex));
84218
84467
  }
@@ -84364,10 +84613,10 @@ async function executeCompletionVerify(args2, directory) {
84364
84613
  let hasFileReadFailure = false;
84365
84614
  for (const filePath of fileTargets) {
84366
84615
  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);
84616
+ const resolvedPath = path93.resolve(directory, normalizedPath);
84617
+ const projectRoot = path93.resolve(directory);
84618
+ const relative20 = path93.relative(projectRoot, resolvedPath);
84619
+ const withinProject = relative20 === "" || !relative20.startsWith("..") && !path93.isAbsolute(relative20);
84371
84620
  if (!withinProject) {
84372
84621
  blockedTasks.push({
84373
84622
  task_id: task.id,
@@ -84422,8 +84671,8 @@ async function executeCompletionVerify(args2, directory) {
84422
84671
  blockedTasks
84423
84672
  };
84424
84673
  try {
84425
- const evidenceDir = path92.join(directory, ".swarm", "evidence", `${phase}`);
84426
- const evidencePath = path92.join(evidenceDir, "completion-verify.json");
84674
+ const evidenceDir = path93.join(directory, ".swarm", "evidence", `${phase}`);
84675
+ const evidencePath = path93.join(evidenceDir, "completion-verify.json");
84427
84676
  fs68.mkdirSync(evidenceDir, { recursive: true });
84428
84677
  const evidenceBundle = {
84429
84678
  schema_version: "1.0.0",
@@ -84500,11 +84749,11 @@ var completion_verify = createSwarmTool({
84500
84749
  // src/tools/complexity-hotspots.ts
84501
84750
  init_zod();
84502
84751
  import * as fs70 from "node:fs";
84503
- import * as path94 from "node:path";
84752
+ import * as path95 from "node:path";
84504
84753
 
84505
84754
  // src/quality/metrics.ts
84506
84755
  import * as fs69 from "node:fs";
84507
- import * as path93 from "node:path";
84756
+ import * as path94 from "node:path";
84508
84757
  var MAX_FILE_SIZE_BYTES4 = 256 * 1024;
84509
84758
  var MIN_DUPLICATION_LINES = 10;
84510
84759
  function estimateCyclomaticComplexity(content) {
@@ -84556,7 +84805,7 @@ async function computeComplexityDelta(files, workingDir) {
84556
84805
  let totalComplexity = 0;
84557
84806
  const analyzedFiles = [];
84558
84807
  for (const file3 of files) {
84559
- const fullPath = path93.isAbsolute(file3) ? file3 : path93.join(workingDir, file3);
84808
+ const fullPath = path94.isAbsolute(file3) ? file3 : path94.join(workingDir, file3);
84560
84809
  if (!fs69.existsSync(fullPath)) {
84561
84810
  continue;
84562
84811
  }
@@ -84679,7 +84928,7 @@ function countGoExports(content) {
84679
84928
  function getExportCountForFile(filePath) {
84680
84929
  try {
84681
84930
  const content = fs69.readFileSync(filePath, "utf-8");
84682
- const ext = path93.extname(filePath).toLowerCase();
84931
+ const ext = path94.extname(filePath).toLowerCase();
84683
84932
  switch (ext) {
84684
84933
  case ".ts":
84685
84934
  case ".tsx":
@@ -84705,7 +84954,7 @@ async function computePublicApiDelta(files, workingDir) {
84705
84954
  let totalExports = 0;
84706
84955
  const analyzedFiles = [];
84707
84956
  for (const file3 of files) {
84708
- const fullPath = path93.isAbsolute(file3) ? file3 : path93.join(workingDir, file3);
84957
+ const fullPath = path94.isAbsolute(file3) ? file3 : path94.join(workingDir, file3);
84709
84958
  if (!fs69.existsSync(fullPath)) {
84710
84959
  continue;
84711
84960
  }
@@ -84739,7 +84988,7 @@ async function computeDuplicationRatio(files, workingDir) {
84739
84988
  let duplicateLines = 0;
84740
84989
  const analyzedFiles = [];
84741
84990
  for (const file3 of files) {
84742
- const fullPath = path93.isAbsolute(file3) ? file3 : path93.join(workingDir, file3);
84991
+ const fullPath = path94.isAbsolute(file3) ? file3 : path94.join(workingDir, file3);
84743
84992
  if (!fs69.existsSync(fullPath)) {
84744
84993
  continue;
84745
84994
  }
@@ -84772,8 +85021,8 @@ function countCodeLines(content) {
84772
85021
  return lines.length;
84773
85022
  }
84774
85023
  function isTestFile(filePath) {
84775
- const basename12 = path93.basename(filePath);
84776
- const _ext = path93.extname(filePath).toLowerCase();
85024
+ const basename12 = path94.basename(filePath);
85025
+ const _ext = path94.extname(filePath).toLowerCase();
84777
85026
  const testPatterns = [
84778
85027
  ".test.",
84779
85028
  ".spec.",
@@ -84854,8 +85103,8 @@ function matchGlobSegment(globSegments, pathSegments) {
84854
85103
  }
84855
85104
  return gIndex === globSegments.length && pIndex === pathSegments.length;
84856
85105
  }
84857
- function matchesGlobSegment(path94, glob) {
84858
- const normalizedPath = path94.replace(/\\/g, "/");
85106
+ function matchesGlobSegment(path95, glob) {
85107
+ const normalizedPath = path95.replace(/\\/g, "/");
84859
85108
  const normalizedGlob = glob.replace(/\\/g, "/");
84860
85109
  if (normalizedPath.includes("//")) {
84861
85110
  return false;
@@ -84886,8 +85135,8 @@ function simpleGlobToRegex2(glob) {
84886
85135
  function hasGlobstar(glob) {
84887
85136
  return glob.includes("**");
84888
85137
  }
84889
- function globMatches(path94, glob) {
84890
- const normalizedPath = path94.replace(/\\/g, "/");
85138
+ function globMatches(path95, glob) {
85139
+ const normalizedPath = path95.replace(/\\/g, "/");
84891
85140
  if (!glob || glob === "") {
84892
85141
  if (normalizedPath.includes("//")) {
84893
85142
  return false;
@@ -84923,7 +85172,7 @@ function shouldExcludeFile(filePath, excludeGlobs) {
84923
85172
  async function computeTestToCodeRatio(workingDir, enforceGlobs, excludeGlobs) {
84924
85173
  let testLines = 0;
84925
85174
  let codeLines = 0;
84926
- const srcDir = path93.join(workingDir, "src");
85175
+ const srcDir = path94.join(workingDir, "src");
84927
85176
  if (fs69.existsSync(srcDir)) {
84928
85177
  await scanDirectoryForLines(srcDir, enforceGlobs, excludeGlobs, false, (lines) => {
84929
85178
  codeLines += lines;
@@ -84931,14 +85180,14 @@ async function computeTestToCodeRatio(workingDir, enforceGlobs, excludeGlobs) {
84931
85180
  }
84932
85181
  const possibleSrcDirs = ["lib", "app", "source", "core"];
84933
85182
  for (const dir of possibleSrcDirs) {
84934
- const dirPath = path93.join(workingDir, dir);
85183
+ const dirPath = path94.join(workingDir, dir);
84935
85184
  if (fs69.existsSync(dirPath)) {
84936
85185
  await scanDirectoryForLines(dirPath, enforceGlobs, excludeGlobs, false, (lines) => {
84937
85186
  codeLines += lines;
84938
85187
  });
84939
85188
  }
84940
85189
  }
84941
- const testsDir = path93.join(workingDir, "tests");
85190
+ const testsDir = path94.join(workingDir, "tests");
84942
85191
  if (fs69.existsSync(testsDir)) {
84943
85192
  await scanDirectoryForLines(testsDir, ["**"], ["node_modules", "dist"], true, (lines) => {
84944
85193
  testLines += lines;
@@ -84946,7 +85195,7 @@ async function computeTestToCodeRatio(workingDir, enforceGlobs, excludeGlobs) {
84946
85195
  }
84947
85196
  const possibleTestDirs = ["test", "__tests__", "specs"];
84948
85197
  for (const dir of possibleTestDirs) {
84949
- const dirPath = path93.join(workingDir, dir);
85198
+ const dirPath = path94.join(workingDir, dir);
84950
85199
  if (fs69.existsSync(dirPath) && dirPath !== testsDir) {
84951
85200
  await scanDirectoryForLines(dirPath, ["**"], ["node_modules", "dist"], true, (lines) => {
84952
85201
  testLines += lines;
@@ -84961,7 +85210,7 @@ async function scanDirectoryForLines(dirPath, includeGlobs, excludeGlobs, isTest
84961
85210
  try {
84962
85211
  const entries = fs69.readdirSync(dirPath, { withFileTypes: true });
84963
85212
  for (const entry of entries) {
84964
- const fullPath = path93.join(dirPath, entry.name);
85213
+ const fullPath = path94.join(dirPath, entry.name);
84965
85214
  if (entry.isDirectory()) {
84966
85215
  if (entry.name === "node_modules" || entry.name === "dist" || entry.name === "build" || entry.name === ".git") {
84967
85216
  continue;
@@ -84969,7 +85218,7 @@ async function scanDirectoryForLines(dirPath, includeGlobs, excludeGlobs, isTest
84969
85218
  await scanDirectoryForLines(fullPath, includeGlobs, excludeGlobs, isTestScan, callback);
84970
85219
  } else if (entry.isFile()) {
84971
85220
  const relativePath = fullPath.replace(`${dirPath}/`, "");
84972
- const ext = path93.extname(entry.name).toLowerCase();
85221
+ const ext = path94.extname(entry.name).toLowerCase();
84973
85222
  const validExts = [
84974
85223
  ".ts",
84975
85224
  ".tsx",
@@ -85220,7 +85469,7 @@ async function analyzeHotspots(days, topN, extensions, directory) {
85220
85469
  const extSet = new Set(extensions.map((e) => e.startsWith(".") ? e : `.${e}`));
85221
85470
  const filteredChurn = new Map;
85222
85471
  for (const [file3, count] of churnMap) {
85223
- const ext = path94.extname(file3).toLowerCase();
85472
+ const ext = path95.extname(file3).toLowerCase();
85224
85473
  if (extSet.has(ext)) {
85225
85474
  filteredChurn.set(file3, count);
85226
85475
  }
@@ -85231,7 +85480,7 @@ async function analyzeHotspots(days, topN, extensions, directory) {
85231
85480
  for (const [file3, churnCount] of filteredChurn) {
85232
85481
  let fullPath = file3;
85233
85482
  if (!fs70.existsSync(fullPath)) {
85234
- fullPath = path94.join(cwd, file3);
85483
+ fullPath = path95.join(cwd, file3);
85235
85484
  }
85236
85485
  const complexity = getComplexityForFile2(fullPath);
85237
85486
  if (complexity !== null) {
@@ -85400,12 +85649,12 @@ ${body2}`);
85400
85649
  // src/council/council-evidence-writer.ts
85401
85650
  import {
85402
85651
  appendFileSync as appendFileSync9,
85403
- existsSync as existsSync49,
85652
+ existsSync as existsSync51,
85404
85653
  mkdirSync as mkdirSync22,
85405
- readFileSync as readFileSync41,
85654
+ readFileSync as readFileSync42,
85406
85655
  writeFileSync as writeFileSync15
85407
85656
  } from "node:fs";
85408
- import { join as join80 } from "node:path";
85657
+ import { join as join81 } from "node:path";
85409
85658
  var EVIDENCE_DIR2 = ".swarm/evidence";
85410
85659
  var VALID_TASK_ID = /^\d+\.\d+(\.\d+)*$/;
85411
85660
  var COUNCIL_GATE_NAME = "council";
@@ -85439,13 +85688,13 @@ function writeCouncilEvidence(workingDir, synthesis) {
85439
85688
  if (!VALID_TASK_ID.test(synthesis.taskId)) {
85440
85689
  throw new Error(`writeCouncilEvidence: invalid taskId "${synthesis.taskId}" — must match N.M or N.M.P format`);
85441
85690
  }
85442
- const dir = join80(workingDir, EVIDENCE_DIR2);
85691
+ const dir = join81(workingDir, EVIDENCE_DIR2);
85443
85692
  mkdirSync22(dir, { recursive: true });
85444
- const filePath = join80(dir, `${synthesis.taskId}.json`);
85693
+ const filePath = join81(dir, `${synthesis.taskId}.json`);
85445
85694
  const existingRoot = Object.create(null);
85446
- if (existsSync49(filePath)) {
85695
+ if (existsSync51(filePath)) {
85447
85696
  try {
85448
- const parsed = JSON.parse(readFileSync41(filePath, "utf-8"));
85697
+ const parsed = JSON.parse(readFileSync42(filePath, "utf-8"));
85449
85698
  if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
85450
85699
  safeAssignOwnProps(existingRoot, parsed);
85451
85700
  }
@@ -85475,7 +85724,7 @@ function writeCouncilEvidence(workingDir, synthesis) {
85475
85724
  updated.required_gates = [];
85476
85725
  writeFileSync15(filePath, JSON.stringify(updated, null, 2));
85477
85726
  try {
85478
- const councilDir = join80(workingDir, ".swarm", "council");
85727
+ const councilDir = join81(workingDir, ".swarm", "council");
85479
85728
  mkdirSync22(councilDir, { recursive: true });
85480
85729
  const auditLine = JSON.stringify({
85481
85730
  round: synthesis.roundNumber,
@@ -85483,7 +85732,7 @@ function writeCouncilEvidence(workingDir, synthesis) {
85483
85732
  timestamp: synthesis.timestamp,
85484
85733
  vetoedBy: synthesis.vetoedBy
85485
85734
  });
85486
- appendFileSync9(join80(councilDir, `${synthesis.taskId}.rounds.jsonl`), `${auditLine}
85735
+ appendFileSync9(join81(councilDir, `${synthesis.taskId}.rounds.jsonl`), `${auditLine}
85487
85736
  `);
85488
85737
  } catch (auditError) {
85489
85738
  console.warn(`writeCouncilEvidence: failed to append round-history audit log: ${auditError instanceof Error ? auditError.message : String(auditError)}`);
@@ -85805,25 +86054,25 @@ function buildFinalCouncilFeedback(projectSummary, verdict, vetoedBy, requiredFi
85805
86054
  }
85806
86055
 
85807
86056
  // 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";
86057
+ import { existsSync as existsSync52, mkdirSync as mkdirSync23, readFileSync as readFileSync43, writeFileSync as writeFileSync16 } from "node:fs";
86058
+ import { join as join82 } from "node:path";
85810
86059
  var COUNCIL_DIR = ".swarm/council";
85811
86060
  function writeCriteria(workingDir, taskId, criteria) {
85812
- const dir = join81(workingDir, COUNCIL_DIR);
86061
+ const dir = join82(workingDir, COUNCIL_DIR);
85813
86062
  mkdirSync23(dir, { recursive: true });
85814
86063
  const payload = {
85815
86064
  taskId,
85816
86065
  criteria,
85817
86066
  declaredAt: new Date().toISOString()
85818
86067
  };
85819
- writeFileSync16(join81(dir, `${safeId(taskId)}.json`), JSON.stringify(payload, null, 2));
86068
+ writeFileSync16(join82(dir, `${safeId(taskId)}.json`), JSON.stringify(payload, null, 2));
85820
86069
  }
85821
86070
  function readCriteria(workingDir, taskId) {
85822
- const filePath = join81(workingDir, COUNCIL_DIR, `${safeId(taskId)}.json`);
85823
- if (!existsSync50(filePath))
86071
+ const filePath = join82(workingDir, COUNCIL_DIR, `${safeId(taskId)}.json`);
86072
+ if (!existsSync52(filePath))
85824
86073
  return null;
85825
86074
  try {
85826
- const parsed = JSON.parse(readFileSync42(filePath, "utf-8"));
86075
+ const parsed = JSON.parse(readFileSync43(filePath, "utf-8"));
85827
86076
  if (parsed && typeof parsed === "object" && typeof parsed.taskId === "string" && Array.isArray(parsed.criteria)) {
85828
86077
  return parsed;
85829
86078
  }
@@ -85972,7 +86221,7 @@ var submit_council_verdicts = createSwarmTool({
85972
86221
  init_zod();
85973
86222
  init_loader();
85974
86223
  import * as fs71 from "node:fs";
85975
- import * as path95 from "node:path";
86224
+ import * as path96 from "node:path";
85976
86225
 
85977
86226
  // src/council/general-council-advisory.ts
85978
86227
  var ADVISORY_HEADER = "[general_council] (advisory; not blocking)";
@@ -86400,10 +86649,10 @@ var convene_general_council = createSwarmTool({
86400
86649
  const round1 = input.round1Responses;
86401
86650
  const round2 = input.round2Responses ?? [];
86402
86651
  const result = synthesizeGeneralCouncil(input.question, input.mode, round1, round2);
86403
- const evidenceDir = path95.join(workingDir, ".swarm", "council", "general");
86652
+ const evidenceDir = path96.join(workingDir, ".swarm", "council", "general");
86404
86653
  const safeTimestamp = result.timestamp.replace(/[:.]/g, "-");
86405
86654
  const evidenceFile = `${safeTimestamp}-${input.mode}.json`;
86406
- const evidencePath = path95.join(evidenceDir, evidenceFile);
86655
+ const evidencePath = path96.join(evidenceDir, evidenceFile);
86407
86656
  try {
86408
86657
  await fs71.promises.mkdir(evidenceDir, { recursive: true });
86409
86658
  await fs71.promises.writeFile(evidencePath, JSON.stringify(result, null, 2));
@@ -86648,7 +86897,7 @@ init_state();
86648
86897
  init_task_id();
86649
86898
  init_create_tool();
86650
86899
  import * as fs72 from "node:fs";
86651
- import * as path96 from "node:path";
86900
+ import * as path97 from "node:path";
86652
86901
  function validateTaskIdFormat2(taskId) {
86653
86902
  return validateTaskIdFormat(taskId);
86654
86903
  }
@@ -86722,8 +86971,8 @@ async function executeDeclareScope(args2, fallbackDir) {
86722
86971
  };
86723
86972
  }
86724
86973
  }
86725
- normalizedDir = path96.normalize(args2.working_directory);
86726
- const pathParts = normalizedDir.split(path96.sep);
86974
+ normalizedDir = path97.normalize(args2.working_directory);
86975
+ const pathParts = normalizedDir.split(path97.sep);
86727
86976
  if (pathParts.includes("..")) {
86728
86977
  return {
86729
86978
  success: false,
@@ -86733,10 +86982,10 @@ async function executeDeclareScope(args2, fallbackDir) {
86733
86982
  ]
86734
86983
  };
86735
86984
  }
86736
- const resolvedDir = path96.resolve(normalizedDir);
86985
+ const resolvedDir = path97.resolve(normalizedDir);
86737
86986
  try {
86738
86987
  const realPath = fs72.realpathSync(resolvedDir);
86739
- const planPath2 = path96.join(realPath, ".swarm", "plan.json");
86988
+ const planPath2 = path97.join(realPath, ".swarm", "plan.json");
86740
86989
  if (!fs72.existsSync(planPath2)) {
86741
86990
  return {
86742
86991
  success: false,
@@ -86760,7 +87009,7 @@ async function executeDeclareScope(args2, fallbackDir) {
86760
87009
  console.warn("[declare-scope] fallbackDir is undefined, falling back to process.cwd()");
86761
87010
  }
86762
87011
  const directory = normalizedDir || fallbackDir;
86763
- const planPath = path96.resolve(directory, ".swarm", "plan.json");
87012
+ const planPath = path97.resolve(directory, ".swarm", "plan.json");
86764
87013
  if (!fs72.existsSync(planPath)) {
86765
87014
  return {
86766
87015
  success: false,
@@ -86800,8 +87049,8 @@ async function executeDeclareScope(args2, fallbackDir) {
86800
87049
  const normalizeErrors = [];
86801
87050
  const dir = normalizedDir || fallbackDir || process.cwd();
86802
87051
  const mergedFiles = rawMergedFiles.map((file3) => {
86803
- if (path96.isAbsolute(file3)) {
86804
- const relativePath = path96.relative(dir, file3).replace(/\\/g, "/");
87052
+ if (path97.isAbsolute(file3)) {
87053
+ const relativePath = path97.relative(dir, file3).replace(/\\/g, "/");
86805
87054
  if (relativePath.startsWith("..")) {
86806
87055
  normalizeErrors.push(`Path '${file3}' resolves outside the project directory`);
86807
87056
  return file3;
@@ -86862,7 +87111,7 @@ var declare_scope = createSwarmTool({
86862
87111
  init_zod();
86863
87112
  import * as child_process7 from "node:child_process";
86864
87113
  import * as fs73 from "node:fs";
86865
- import * as path97 from "node:path";
87114
+ import * as path98 from "node:path";
86866
87115
  init_create_tool();
86867
87116
  var MAX_DIFF_LINES = 500;
86868
87117
  var DIFF_TIMEOUT_MS = 30000;
@@ -86891,20 +87140,20 @@ function validateBase(base) {
86891
87140
  function validatePaths(paths) {
86892
87141
  if (!paths)
86893
87142
  return null;
86894
- for (const path98 of paths) {
86895
- if (!path98 || path98.length === 0) {
87143
+ for (const path99 of paths) {
87144
+ if (!path99 || path99.length === 0) {
86896
87145
  return "empty path not allowed";
86897
87146
  }
86898
- if (path98.length > MAX_PATH_LENGTH) {
87147
+ if (path99.length > MAX_PATH_LENGTH) {
86899
87148
  return `path exceeds maximum length of ${MAX_PATH_LENGTH}`;
86900
87149
  }
86901
- if (SHELL_METACHARACTERS2.test(path98)) {
87150
+ if (SHELL_METACHARACTERS2.test(path99)) {
86902
87151
  return "path contains shell metacharacters";
86903
87152
  }
86904
- if (path98.startsWith("-")) {
87153
+ if (path99.startsWith("-")) {
86905
87154
  return 'path cannot start with "-" (option-like arguments not allowed)';
86906
87155
  }
86907
- if (CONTROL_CHAR_PATTERN2.test(path98)) {
87156
+ if (CONTROL_CHAR_PATTERN2.test(path99)) {
86908
87157
  return "path contains control characters";
86909
87158
  }
86910
87159
  }
@@ -87012,8 +87261,8 @@ var diff = createSwarmTool({
87012
87261
  if (parts2.length >= 3) {
87013
87262
  const additions = parseInt(parts2[0], 10) || 0;
87014
87263
  const deletions = parseInt(parts2[1], 10) || 0;
87015
- const path98 = parts2[2];
87016
- files.push({ path: path98, additions, deletions });
87264
+ const path99 = parts2[2];
87265
+ files.push({ path: path99, additions, deletions });
87017
87266
  }
87018
87267
  }
87019
87268
  const contractChanges = [];
@@ -87053,7 +87302,7 @@ var diff = createSwarmTool({
87053
87302
  } else if (base === "unstaged") {
87054
87303
  const oldRef = `:${file3.path}`;
87055
87304
  oldContent = fileExistsInRef(oldRef) ? getContentFromRef(oldRef) : "";
87056
- newContent = fs73.readFileSync(path97.join(directory, file3.path), "utf-8");
87305
+ newContent = fs73.readFileSync(path98.join(directory, file3.path), "utf-8");
87057
87306
  } else {
87058
87307
  const oldRef = `${base}:${file3.path}`;
87059
87308
  oldContent = fileExistsInRef(oldRef) ? getContentFromRef(oldRef) : "";
@@ -87128,7 +87377,7 @@ var diff = createSwarmTool({
87128
87377
  init_zod();
87129
87378
  import * as child_process8 from "node:child_process";
87130
87379
  import * as fs74 from "node:fs";
87131
- import * as path98 from "node:path";
87380
+ import * as path99 from "node:path";
87132
87381
  init_create_tool();
87133
87382
  var diff_summary = createSwarmTool({
87134
87383
  description: "Generate a filtered semantic diff summary from AST analysis. Returns SemanticDiffSummary with optional filtering by classification or riskLevel.",
@@ -87176,7 +87425,7 @@ var diff_summary = createSwarmTool({
87176
87425
  }
87177
87426
  try {
87178
87427
  let oldContent;
87179
- const newContent = fs74.readFileSync(path98.join(workingDir, filePath), "utf-8");
87428
+ const newContent = fs74.readFileSync(path99.join(workingDir, filePath), "utf-8");
87180
87429
  if (fileExistsInHead) {
87181
87430
  oldContent = child_process8.execFileSync("git", ["show", `HEAD:${filePath}`], {
87182
87431
  encoding: "utf-8",
@@ -87405,7 +87654,7 @@ init_zod();
87405
87654
  init_create_tool();
87406
87655
  init_path_security();
87407
87656
  import * as fs75 from "node:fs";
87408
- import * as path99 from "node:path";
87657
+ import * as path100 from "node:path";
87409
87658
  var MAX_FILE_SIZE_BYTES6 = 1024 * 1024;
87410
87659
  var MAX_EVIDENCE_FILES = 1000;
87411
87660
  var EVIDENCE_DIR3 = ".swarm/evidence";
@@ -87432,9 +87681,9 @@ function validateRequiredTypes(input) {
87432
87681
  return null;
87433
87682
  }
87434
87683
  function isPathWithinSwarm2(filePath, cwd) {
87435
- const normalizedCwd = path99.resolve(cwd);
87436
- const swarmPath = path99.join(normalizedCwd, ".swarm");
87437
- const normalizedPath = path99.resolve(filePath);
87684
+ const normalizedCwd = path100.resolve(cwd);
87685
+ const swarmPath = path100.join(normalizedCwd, ".swarm");
87686
+ const normalizedPath = path100.resolve(filePath);
87438
87687
  return normalizedPath.startsWith(swarmPath);
87439
87688
  }
87440
87689
  function parseCompletedTasks(planContent) {
@@ -87464,10 +87713,10 @@ function readEvidenceFiles(evidenceDir, _cwd) {
87464
87713
  if (!VALID_EVIDENCE_FILENAME_REGEX.test(filename)) {
87465
87714
  continue;
87466
87715
  }
87467
- const filePath = path99.join(evidenceDir, filename);
87716
+ const filePath = path100.join(evidenceDir, filename);
87468
87717
  try {
87469
- const resolvedPath = path99.resolve(filePath);
87470
- const evidenceDirResolved = path99.resolve(evidenceDir);
87718
+ const resolvedPath = path100.resolve(filePath);
87719
+ const evidenceDirResolved = path100.resolve(evidenceDir);
87471
87720
  if (!resolvedPath.startsWith(evidenceDirResolved)) {
87472
87721
  continue;
87473
87722
  }
@@ -87585,7 +87834,7 @@ var evidence_check = createSwarmTool({
87585
87834
  return JSON.stringify(errorResult, null, 2);
87586
87835
  }
87587
87836
  const requiredTypes = requiredTypesValue.split(",").map((t) => t.trim()).filter((t) => t.length > 0).map(normalizeEvidenceType);
87588
- const planPath = path99.join(cwd, PLAN_FILE);
87837
+ const planPath = path100.join(cwd, PLAN_FILE);
87589
87838
  if (!isPathWithinSwarm2(planPath, cwd)) {
87590
87839
  const errorResult = {
87591
87840
  error: "plan file path validation failed",
@@ -87617,7 +87866,7 @@ var evidence_check = createSwarmTool({
87617
87866
  };
87618
87867
  return JSON.stringify(result2, null, 2);
87619
87868
  }
87620
- const evidenceDir = path99.join(cwd, EVIDENCE_DIR3);
87869
+ const evidenceDir = path100.join(cwd, EVIDENCE_DIR3);
87621
87870
  const evidence = readEvidenceFiles(evidenceDir, cwd);
87622
87871
  const { tasksWithFullEvidence, gaps } = analyzeGaps(completedTasks, evidence, requiredTypes);
87623
87872
  const completeness = completedTasks.length > 0 ? Math.round(tasksWithFullEvidence.length / completedTasks.length * 100) / 100 : 1;
@@ -87635,7 +87884,7 @@ var evidence_check = createSwarmTool({
87635
87884
  init_zod();
87636
87885
  init_create_tool();
87637
87886
  import * as fs76 from "node:fs";
87638
- import * as path100 from "node:path";
87887
+ import * as path101 from "node:path";
87639
87888
  var EXT_MAP = {
87640
87889
  python: ".py",
87641
87890
  py: ".py",
@@ -87716,12 +87965,12 @@ var extract_code_blocks = createSwarmTool({
87716
87965
  if (prefix) {
87717
87966
  filename = `${prefix}_${filename}`;
87718
87967
  }
87719
- let filepath = path100.join(targetDir, filename);
87720
- const base = path100.basename(filepath, path100.extname(filepath));
87721
- const ext = path100.extname(filepath);
87968
+ let filepath = path101.join(targetDir, filename);
87969
+ const base = path101.basename(filepath, path101.extname(filepath));
87970
+ const ext = path101.extname(filepath);
87722
87971
  let counter = 1;
87723
87972
  while (fs76.existsSync(filepath)) {
87724
- filepath = path100.join(targetDir, `${base}_${counter}${ext}`);
87973
+ filepath = path101.join(targetDir, `${base}_${counter}${ext}`);
87725
87974
  counter++;
87726
87975
  }
87727
87976
  try {
@@ -87979,7 +88228,7 @@ init_zod();
87979
88228
  init_create_tool();
87980
88229
  init_path_security();
87981
88230
  import * as fs77 from "node:fs";
87982
- import * as path101 from "node:path";
88231
+ import * as path102 from "node:path";
87983
88232
  var MAX_FILE_PATH_LENGTH2 = 500;
87984
88233
  var MAX_SYMBOL_LENGTH = 256;
87985
88234
  var MAX_FILE_SIZE_BYTES7 = 1024 * 1024;
@@ -88027,7 +88276,7 @@ function validateSymbolInput(symbol3) {
88027
88276
  return null;
88028
88277
  }
88029
88278
  function isBinaryFile2(filePath, buffer) {
88030
- const ext = path101.extname(filePath).toLowerCase();
88279
+ const ext = path102.extname(filePath).toLowerCase();
88031
88280
  if (ext === ".json" || ext === ".md" || ext === ".txt") {
88032
88281
  return false;
88033
88282
  }
@@ -88051,15 +88300,15 @@ function parseImports(content, targetFile, targetSymbol) {
88051
88300
  const imports = [];
88052
88301
  let _resolvedTarget;
88053
88302
  try {
88054
- _resolvedTarget = path101.resolve(targetFile);
88303
+ _resolvedTarget = path102.resolve(targetFile);
88055
88304
  } catch {
88056
88305
  _resolvedTarget = targetFile;
88057
88306
  }
88058
- const targetBasename = path101.basename(targetFile, path101.extname(targetFile));
88307
+ const targetBasename = path102.basename(targetFile, path102.extname(targetFile));
88059
88308
  const targetWithExt = targetFile;
88060
88309
  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, "/");
88310
+ const normalizedTargetWithExt = path102.normalize(targetWithExt).replace(/\\/g, "/");
88311
+ const normalizedTargetWithoutExt = path102.normalize(targetWithoutExt).replace(/\\/g, "/");
88063
88312
  const importRegex = /import\s+(?:\{[\s\S]*?\}|(?:\*\s+as\s+\w+)|\w+)\s+from\s+['"`]([^'"`]+)['"`]|import\s+['"`]([^'"`]+)['"`]|require\s*\(\s*['"`]([^'"`]+)['"`]\s*\)/g;
88064
88313
  for (let match = importRegex.exec(content);match !== null; match = importRegex.exec(content)) {
88065
88314
  const modulePath = match[1] || match[2] || match[3];
@@ -88082,9 +88331,9 @@ function parseImports(content, targetFile, targetSymbol) {
88082
88331
  }
88083
88332
  const _normalizedModule = modulePath.replace(/^\.\//, "").replace(/^\.\.\\/, "../");
88084
88333
  let isMatch = false;
88085
- const _targetDir = path101.dirname(targetFile);
88086
- const targetExt = path101.extname(targetFile);
88087
- const targetBasenameNoExt = path101.basename(targetFile, targetExt);
88334
+ const _targetDir = path102.dirname(targetFile);
88335
+ const targetExt = path102.extname(targetFile);
88336
+ const targetBasenameNoExt = path102.basename(targetFile, targetExt);
88088
88337
  const moduleNormalized = modulePath.replace(/\\/g, "/").replace(/^\.\//, "");
88089
88338
  const moduleName = modulePath.split(/[/\\]/).pop() || "";
88090
88339
  const moduleNameNoExt = moduleName.replace(/\.(ts|tsx|js|jsx|mjs|cjs)$/i, "");
@@ -88152,10 +88401,10 @@ function findSourceFiles2(dir, files = [], stats = { skippedDirs: [], skippedFil
88152
88401
  entries.sort((a, b) => a.toLowerCase().localeCompare(b.toLowerCase()));
88153
88402
  for (const entry of entries) {
88154
88403
  if (SKIP_DIRECTORIES4.has(entry)) {
88155
- stats.skippedDirs.push(path101.join(dir, entry));
88404
+ stats.skippedDirs.push(path102.join(dir, entry));
88156
88405
  continue;
88157
88406
  }
88158
- const fullPath = path101.join(dir, entry);
88407
+ const fullPath = path102.join(dir, entry);
88159
88408
  let stat8;
88160
88409
  try {
88161
88410
  stat8 = fs77.statSync(fullPath);
@@ -88169,7 +88418,7 @@ function findSourceFiles2(dir, files = [], stats = { skippedDirs: [], skippedFil
88169
88418
  if (stat8.isDirectory()) {
88170
88419
  findSourceFiles2(fullPath, files, stats);
88171
88420
  } else if (stat8.isFile()) {
88172
- const ext = path101.extname(fullPath).toLowerCase();
88421
+ const ext = path102.extname(fullPath).toLowerCase();
88173
88422
  if (SUPPORTED_EXTENSIONS3.includes(ext)) {
88174
88423
  files.push(fullPath);
88175
88424
  }
@@ -88226,7 +88475,7 @@ var imports = createSwarmTool({
88226
88475
  return JSON.stringify(errorResult, null, 2);
88227
88476
  }
88228
88477
  try {
88229
- const targetFile = path101.resolve(file3);
88478
+ const targetFile = path102.resolve(file3);
88230
88479
  if (!fs77.existsSync(targetFile)) {
88231
88480
  const errorResult = {
88232
88481
  error: `target file not found: ${file3}`,
@@ -88248,7 +88497,7 @@ var imports = createSwarmTool({
88248
88497
  };
88249
88498
  return JSON.stringify(errorResult, null, 2);
88250
88499
  }
88251
- const baseDir = path101.dirname(targetFile);
88500
+ const baseDir = path102.dirname(targetFile);
88252
88501
  const scanStats = {
88253
88502
  skippedDirs: [],
88254
88503
  skippedFiles: 0,
@@ -88539,7 +88788,7 @@ init_zod();
88539
88788
  init_config();
88540
88789
  init_knowledge_store();
88541
88790
  init_create_tool();
88542
- import { existsSync as existsSync55 } from "node:fs";
88791
+ import { existsSync as existsSync57 } from "node:fs";
88543
88792
  var DEFAULT_LIMIT = 10;
88544
88793
  var MAX_LESSON_LENGTH = 200;
88545
88794
  var VALID_CATEGORIES3 = [
@@ -88609,14 +88858,14 @@ function validateLimit(limit) {
88609
88858
  }
88610
88859
  async function readSwarmKnowledge(directory) {
88611
88860
  const swarmPath = resolveSwarmKnowledgePath(directory);
88612
- if (!existsSync55(swarmPath)) {
88861
+ if (!existsSync57(swarmPath)) {
88613
88862
  return [];
88614
88863
  }
88615
88864
  return readKnowledge(swarmPath);
88616
88865
  }
88617
88866
  async function readHiveKnowledge() {
88618
88867
  const hivePath = resolveHiveKnowledgePath();
88619
- if (!existsSync55(hivePath)) {
88868
+ if (!existsSync57(hivePath)) {
88620
88869
  return [];
88621
88870
  }
88622
88871
  return readKnowledge(hivePath);
@@ -88851,22 +89100,22 @@ init_schema();
88851
89100
  init_qa_gate_profile();
88852
89101
  init_manager2();
88853
89102
  import * as fs82 from "node:fs";
88854
- import * as path106 from "node:path";
89103
+ import * as path107 from "node:path";
88855
89104
 
88856
89105
  // src/full-auto/phase-approval.ts
88857
89106
  init_utils2();
88858
89107
  init_logger();
88859
89108
  init_state2();
88860
89109
  import * as fs78 from "node:fs";
88861
- import * as path102 from "node:path";
89110
+ import * as path103 from "node:path";
88862
89111
  var APPROVAL_TTL_MS = 24 * 60 * 60 * 1000;
88863
89112
  function readEvidenceDir(directory, phase) {
88864
89113
  try {
88865
- const dirPath = validateSwarmPath(directory, path102.posix.join("evidence", String(phase)));
89114
+ const dirPath = validateSwarmPath(directory, path103.posix.join("evidence", String(phase)));
88866
89115
  if (!fs78.existsSync(dirPath))
88867
89116
  return [];
88868
89117
  const entries = fs78.readdirSync(dirPath);
88869
- return entries.filter((e) => e.startsWith("full-auto-") && e.endsWith(".json")).map((e) => path102.join(dirPath, e));
89118
+ return entries.filter((e) => e.startsWith("full-auto-") && e.endsWith(".json")).map((e) => path103.join(dirPath, e));
88870
89119
  } catch {
88871
89120
  return [];
88872
89121
  }
@@ -89005,16 +89254,16 @@ init_plan_schema();
89005
89254
  init_ledger();
89006
89255
  init_manager();
89007
89256
  import * as fs79 from "node:fs";
89008
- import * as path103 from "node:path";
89257
+ import * as path104 from "node:path";
89009
89258
  async function writeCheckpoint(directory) {
89010
89259
  try {
89011
89260
  const plan = await loadPlan(directory);
89012
89261
  if (!plan)
89013
89262
  return;
89014
- const swarmDir = path103.join(directory, ".swarm");
89263
+ const swarmDir = path104.join(directory, ".swarm");
89015
89264
  fs79.mkdirSync(swarmDir, { recursive: true });
89016
- const jsonPath = path103.join(swarmDir, "SWARM_PLAN.json");
89017
- const mdPath = path103.join(swarmDir, "SWARM_PLAN.md");
89265
+ const jsonPath = path104.join(swarmDir, "SWARM_PLAN.json");
89266
+ const mdPath = path104.join(swarmDir, "SWARM_PLAN.md");
89018
89267
  fs79.writeFileSync(jsonPath, JSON.stringify(plan, null, 2), "utf8");
89019
89268
  const md = derivePlanMarkdown(plan);
89020
89269
  fs79.writeFileSync(mdPath, md, "utf8");
@@ -89033,15 +89282,15 @@ init_telemetry();
89033
89282
  // src/turbo/lean/phase-ready.ts
89034
89283
  init_file_locks();
89035
89284
  import * as fs81 from "node:fs";
89036
- import * as path105 from "node:path";
89285
+ import * as path106 from "node:path";
89037
89286
 
89038
89287
  // src/turbo/lean/evidence.ts
89039
89288
  init_bun_compat();
89040
89289
  import { rmSync as rmSync5 } from "node:fs";
89041
89290
  import * as fs80 from "node:fs/promises";
89042
- import * as path104 from "node:path";
89291
+ import * as path105 from "node:path";
89043
89292
  function leanTurboEvidenceDir(directory, phase) {
89044
- return path104.join(directory, ".swarm", "evidence", String(phase), "lean-turbo");
89293
+ return path105.join(directory, ".swarm", "evidence", String(phase), "lean-turbo");
89045
89294
  }
89046
89295
  function validateLaneId(laneId) {
89047
89296
  if (laneId.length === 0) {
@@ -89063,16 +89312,16 @@ function validateLaneId(laneId) {
89063
89312
  function laneEvidencePath(directory, phase, laneId) {
89064
89313
  validateLaneId(laneId);
89065
89314
  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) {
89315
+ const resolvedPath = path105.resolve(path105.join(expectedDir, `${laneId}.json`));
89316
+ const resolvedDir = path105.resolve(expectedDir);
89317
+ if (!resolvedPath.startsWith(resolvedDir + path105.sep) && resolvedPath !== resolvedDir) {
89069
89318
  throw new Error(`Invalid laneId: path traversal detected (got "${laneId}")`);
89070
89319
  }
89071
89320
  return resolvedPath;
89072
89321
  }
89073
89322
  async function atomicWriteJson(filePath, data) {
89074
89323
  const content = JSON.stringify(data, null, 2);
89075
- const dir = path104.dirname(filePath);
89324
+ const dir = path105.dirname(filePath);
89076
89325
  await fs80.mkdir(dir, { recursive: true });
89077
89326
  const tempPath = `${filePath}.tmp.${process.pid}.${Date.now()}.${Math.random().toString(36).slice(2)}`;
89078
89327
  try {
@@ -89086,7 +89335,7 @@ async function atomicWriteJson(filePath, data) {
89086
89335
  }
89087
89336
  }
89088
89337
  function phaseEvidencePath(directory, phase) {
89089
- return path104.join(leanTurboEvidenceDir(directory, phase), "lean-turbo-phase.json");
89338
+ return path105.join(leanTurboEvidenceDir(directory, phase), "lean-turbo-phase.json");
89090
89339
  }
89091
89340
  async function writeLaneEvidence(directory, phase, evidence) {
89092
89341
  const targetPath = laneEvidencePath(directory, phase, evidence.laneId);
@@ -89130,7 +89379,7 @@ async function listLaneEvidence(directory, phase) {
89130
89379
  if (entry === "lean-turbo-phase.json") {
89131
89380
  continue;
89132
89381
  }
89133
- const filePath = path104.join(evidenceDir, entry);
89382
+ const filePath = path105.join(evidenceDir, entry);
89134
89383
  let content;
89135
89384
  try {
89136
89385
  content = await fs80.readFile(filePath, "utf-8");
@@ -89154,7 +89403,7 @@ var DEFAULT_CONFIG2 = {
89154
89403
  };
89155
89404
  function defaultReadPlanJson(dir) {
89156
89405
  try {
89157
- const planPath = path105.join(dir, ".swarm", "plan.json");
89406
+ const planPath = path106.join(dir, ".swarm", "plan.json");
89158
89407
  if (!fs81.existsSync(planPath))
89159
89408
  return null;
89160
89409
  const raw = fs81.readFileSync(planPath, "utf-8");
@@ -89169,7 +89418,7 @@ function defaultReadPlanJson(dir) {
89169
89418
  }
89170
89419
  function readReviewerEvidenceFromFile(directory, phase) {
89171
89420
  try {
89172
- const evidencePath = path105.join(directory, ".swarm", "evidence", String(phase), "lean-turbo-reviewer.json");
89421
+ const evidencePath = path106.join(directory, ".swarm", "evidence", String(phase), "lean-turbo-reviewer.json");
89173
89422
  if (!fs81.existsSync(evidencePath)) {
89174
89423
  return null;
89175
89424
  }
@@ -89189,7 +89438,7 @@ function readReviewerEvidenceFromFile(directory, phase) {
89189
89438
  }
89190
89439
  function readCriticEvidenceFromFile(directory, phase) {
89191
89440
  try {
89192
- const evidencePath = path105.join(directory, ".swarm", "evidence", String(phase), "lean-turbo-critic.json");
89441
+ const evidencePath = path106.join(directory, ".swarm", "evidence", String(phase), "lean-turbo-critic.json");
89193
89442
  if (!fs81.existsSync(evidencePath)) {
89194
89443
  return null;
89195
89444
  }
@@ -89208,7 +89457,7 @@ function readCriticEvidenceFromFile(directory, phase) {
89208
89457
  }
89209
89458
  }
89210
89459
  function listLaneEvidenceSync(directory, phase) {
89211
- const evidenceDir = path105.join(directory, ".swarm", "evidence", String(phase), "lean-turbo");
89460
+ const evidenceDir = path106.join(directory, ".swarm", "evidence", String(phase), "lean-turbo");
89212
89461
  let entries;
89213
89462
  try {
89214
89463
  entries = fs81.readdirSync(evidenceDir);
@@ -89278,7 +89527,7 @@ function verifyLeanTurboPhaseReady(directory, phase, sessionIDOrConfig, config3)
89278
89527
  ...DEFAULT_CONFIG2,
89279
89528
  ...actualConfig
89280
89529
  };
89281
- const statePath = path105.join(directory, ".swarm", "turbo-state.json");
89530
+ const statePath = path106.join(directory, ".swarm", "turbo-state.json");
89282
89531
  if (!fs81.existsSync(statePath)) {
89283
89532
  return {
89284
89533
  ok: false,
@@ -89466,7 +89715,7 @@ function verifyLeanTurboPhaseReady(directory, phase, sessionIDOrConfig, config3)
89466
89715
  }
89467
89716
  }
89468
89717
  if (mergedConfig.integrated_diff_required) {
89469
- const evidencePath = path105.join(directory, ".swarm", "evidence", String(phase), "lean-turbo-phase.json");
89718
+ const evidencePath = path106.join(directory, ".swarm", "evidence", String(phase), "lean-turbo-phase.json");
89470
89719
  let hasDiff = false;
89471
89720
  try {
89472
89721
  const content = fs81.readFileSync(evidencePath, "utf-8");
@@ -89739,7 +89988,7 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
89739
89988
  let driftCheckEnabled = true;
89740
89989
  let driftHasSpecMd = false;
89741
89990
  try {
89742
- const specMdPath = path106.join(dir, ".swarm", "spec.md");
89991
+ const specMdPath = path107.join(dir, ".swarm", "spec.md");
89743
89992
  driftHasSpecMd = fs82.existsSync(specMdPath);
89744
89993
  const gatePlan = await loadPlan(dir);
89745
89994
  if (gatePlan) {
@@ -89761,7 +90010,7 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
89761
90010
  } else {
89762
90011
  let phaseType;
89763
90012
  try {
89764
- const planPath = path106.join(dir, ".swarm", "plan.json");
90013
+ const planPath = path107.join(dir, ".swarm", "plan.json");
89765
90014
  if (fs82.existsSync(planPath)) {
89766
90015
  const planRaw = fs82.readFileSync(planPath, "utf-8");
89767
90016
  const plan = JSON.parse(planRaw);
@@ -89774,7 +90023,7 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
89774
90023
  warnings.push(`Phase ${phase} is annotated as 'non-code'. Drift verification was skipped per phase type annotation.`);
89775
90024
  } else {
89776
90025
  try {
89777
- const driftEvidencePath = path106.join(dir, ".swarm", "evidence", String(phase), "drift-verifier.json");
90026
+ const driftEvidencePath = path107.join(dir, ".swarm", "evidence", String(phase), "drift-verifier.json");
89778
90027
  let driftVerdictFound = false;
89779
90028
  let driftVerdictApproved = false;
89780
90029
  try {
@@ -89812,7 +90061,7 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
89812
90061
  let incompleteTaskCount = 0;
89813
90062
  let planParseable = false;
89814
90063
  try {
89815
- const planPath = path106.join(dir, ".swarm", "plan.json");
90064
+ const planPath = path107.join(dir, ".swarm", "plan.json");
89816
90065
  if (fs82.existsSync(planPath)) {
89817
90066
  const planRaw = fs82.readFileSync(planPath, "utf-8");
89818
90067
  const plan = JSON.parse(planRaw);
@@ -89879,7 +90128,7 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
89879
90128
  const overrides = session2?.qaGateSessionOverrides ?? {};
89880
90129
  const effective = getEffectiveGates(profile, overrides);
89881
90130
  if (effective.hallucination_guard === true) {
89882
- const hgPath = path106.join(dir, ".swarm", "evidence", String(phase), "hallucination-guard.json");
90131
+ const hgPath = path107.join(dir, ".swarm", "evidence", String(phase), "hallucination-guard.json");
89883
90132
  let hgVerdictFound = false;
89884
90133
  let hgVerdictApproved = false;
89885
90134
  try {
@@ -89951,7 +90200,7 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
89951
90200
  const overrides = session2?.qaGateSessionOverrides ?? {};
89952
90201
  const effective = getEffectiveGates(profile, overrides);
89953
90202
  if (effective.mutation_test === true) {
89954
- const mgPath = path106.join(dir, ".swarm", "evidence", String(phase), "mutation-gate.json");
90203
+ const mgPath = path107.join(dir, ".swarm", "evidence", String(phase), "mutation-gate.json");
89955
90204
  let mgVerdictFound = false;
89956
90205
  let mgVerdict;
89957
90206
  try {
@@ -90025,7 +90274,7 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
90025
90274
  const effective = getEffectiveGates(profile, overrides);
90026
90275
  if (effective.council_mode === true) {
90027
90276
  councilModeEnabled = true;
90028
- const pcPath = path106.join(dir, ".swarm", "evidence", String(phase), "phase-council.json");
90277
+ const pcPath = path107.join(dir, ".swarm", "evidence", String(phase), "phase-council.json");
90029
90278
  let pcVerdictFound = false;
90030
90279
  let _pcVerdict;
90031
90280
  let pcQuorumSize;
@@ -90233,7 +90482,7 @@ Advisory notes: ${advisoryNotes.join("; ")}` : "";
90233
90482
  const effective = getEffectiveGates(profile, overrides);
90234
90483
  if (effective.final_council === true) {
90235
90484
  finalCouncilEnabled = true;
90236
- const fcPath = path106.join(dir, ".swarm", "evidence", "final-council.json");
90485
+ const fcPath = path107.join(dir, ".swarm", "evidence", "final-council.json");
90237
90486
  let fcVerdictFound = false;
90238
90487
  let _fcVerdict;
90239
90488
  try {
@@ -90421,7 +90670,7 @@ Advisory notes: ${advisoryNotes.join("; ")}` : "";
90421
90670
  }
90422
90671
  if (retroFound && retroEntry?.lessons_learned && retroEntry.lessons_learned.length > 0) {
90423
90672
  try {
90424
- const projectName = path106.basename(dir);
90673
+ const projectName = path107.basename(dir);
90425
90674
  const curationResult = await curateAndStoreSwarm(retroEntry.lessons_learned, projectName, { phase_number: phase }, dir, knowledgeConfig);
90426
90675
  if (curationResult) {
90427
90676
  const sessionState = swarmState.agentSessions.get(sessionID);
@@ -90672,7 +90921,7 @@ Advisory notes: ${advisoryNotes.join("; ")}` : "";
90672
90921
  const phaseObj = rebuilt.phases.find((p) => p.id === phase);
90673
90922
  if (phaseObj) {
90674
90923
  phaseObj.status = "complete";
90675
- await savePlan(dir, rebuilt);
90924
+ await savePlanWithAutoAcknowledgedRemovals(dir, rebuilt, "phase_complete_rebuild_from_ledger", "phase-complete rebuild from ledger");
90676
90925
  try {
90677
90926
  await takeSnapshotEvent(dir, rebuilt).catch(() => {});
90678
90927
  } catch {}
@@ -90714,7 +90963,7 @@ Advisory notes: ${advisoryNotes.join("; ")}` : "";
90714
90963
  const phaseObj = rebuilt.phases.find((p) => p.id === phase);
90715
90964
  if (phaseObj) {
90716
90965
  phaseObj.status = "complete";
90717
- await savePlan(dir, rebuilt);
90966
+ await savePlanWithAutoAcknowledgedRemovals(dir, rebuilt, "phase_complete_rebuild_from_ledger", "phase-complete rebuild from ledger");
90718
90967
  try {
90719
90968
  await takeSnapshotEvent(dir, rebuilt).catch(() => {});
90720
90969
  } catch {}
@@ -90791,7 +91040,7 @@ init_utils();
90791
91040
  init_bun_compat();
90792
91041
  init_create_tool();
90793
91042
  import * as fs83 from "node:fs";
90794
- import * as path107 from "node:path";
91043
+ import * as path108 from "node:path";
90795
91044
  var MAX_OUTPUT_BYTES5 = 52428800;
90796
91045
  var AUDIT_TIMEOUT_MS = 120000;
90797
91046
  function isValidEcosystem(value) {
@@ -90819,16 +91068,16 @@ function validateArgs3(args2) {
90819
91068
  function detectEcosystems(directory) {
90820
91069
  const ecosystems = [];
90821
91070
  const cwd = directory;
90822
- if (fs83.existsSync(path107.join(cwd, "package.json"))) {
91071
+ if (fs83.existsSync(path108.join(cwd, "package.json"))) {
90823
91072
  ecosystems.push("npm");
90824
91073
  }
90825
- if (fs83.existsSync(path107.join(cwd, "pyproject.toml")) || fs83.existsSync(path107.join(cwd, "requirements.txt"))) {
91074
+ if (fs83.existsSync(path108.join(cwd, "pyproject.toml")) || fs83.existsSync(path108.join(cwd, "requirements.txt"))) {
90826
91075
  ecosystems.push("pip");
90827
91076
  }
90828
- if (fs83.existsSync(path107.join(cwd, "Cargo.toml"))) {
91077
+ if (fs83.existsSync(path108.join(cwd, "Cargo.toml"))) {
90829
91078
  ecosystems.push("cargo");
90830
91079
  }
90831
- if (fs83.existsSync(path107.join(cwd, "go.mod"))) {
91080
+ if (fs83.existsSync(path108.join(cwd, "go.mod"))) {
90832
91081
  ecosystems.push("go");
90833
91082
  }
90834
91083
  try {
@@ -90837,13 +91086,13 @@ function detectEcosystems(directory) {
90837
91086
  ecosystems.push("dotnet");
90838
91087
  }
90839
91088
  } catch {}
90840
- if (fs83.existsSync(path107.join(cwd, "Gemfile")) || fs83.existsSync(path107.join(cwd, "Gemfile.lock"))) {
91089
+ if (fs83.existsSync(path108.join(cwd, "Gemfile")) || fs83.existsSync(path108.join(cwd, "Gemfile.lock"))) {
90841
91090
  ecosystems.push("ruby");
90842
91091
  }
90843
- if (fs83.existsSync(path107.join(cwd, "pubspec.yaml"))) {
91092
+ if (fs83.existsSync(path108.join(cwd, "pubspec.yaml"))) {
90844
91093
  ecosystems.push("dart");
90845
91094
  }
90846
- if (fs83.existsSync(path107.join(cwd, "composer.lock"))) {
91095
+ if (fs83.existsSync(path108.join(cwd, "composer.lock"))) {
90847
91096
  ecosystems.push("composer");
90848
91097
  }
90849
91098
  return ecosystems;
@@ -91979,7 +92228,7 @@ var pkg_audit = createSwarmTool({
91979
92228
  init_zod();
91980
92229
  init_manager2();
91981
92230
  import * as fs84 from "node:fs";
91982
- import * as path108 from "node:path";
92231
+ import * as path109 from "node:path";
91983
92232
  init_utils();
91984
92233
  init_create_tool();
91985
92234
  var MAX_FILE_SIZE = 1024 * 1024;
@@ -92102,7 +92351,7 @@ function isScaffoldFile(filePath) {
92102
92351
  if (SCAFFOLD_PATH_PATTERNS.some((pattern) => pattern.test(normalizedPath))) {
92103
92352
  return true;
92104
92353
  }
92105
- const filename = path108.basename(filePath);
92354
+ const filename = path109.basename(filePath);
92106
92355
  if (SCAFFOLD_FILENAME_PATTERNS.some((pattern) => pattern.test(filename))) {
92107
92356
  return true;
92108
92357
  }
@@ -92119,7 +92368,7 @@ function isAllowedByGlobs(filePath, allowGlobs) {
92119
92368
  if (regex.test(normalizedPath)) {
92120
92369
  return true;
92121
92370
  }
92122
- const filename = path108.basename(filePath);
92371
+ const filename = path109.basename(filePath);
92123
92372
  const filenameRegex = new RegExp(`^${regexPattern}$`, "i");
92124
92373
  if (filenameRegex.test(filename)) {
92125
92374
  return true;
@@ -92128,7 +92377,7 @@ function isAllowedByGlobs(filePath, allowGlobs) {
92128
92377
  return false;
92129
92378
  }
92130
92379
  function isParserSupported(filePath) {
92131
- const ext = path108.extname(filePath).toLowerCase();
92380
+ const ext = path109.extname(filePath).toLowerCase();
92132
92381
  return SUPPORTED_PARSER_EXTENSIONS.has(ext);
92133
92382
  }
92134
92383
  function isPlanFile(filePath) {
@@ -92375,9 +92624,9 @@ async function placeholderScan(input, directory) {
92375
92624
  let filesScanned = 0;
92376
92625
  const filesWithFindings = new Set;
92377
92626
  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) {
92627
+ const fullPath = path109.isAbsolute(filePath) ? filePath : path109.resolve(directory, filePath);
92628
+ const resolvedDirectory = path109.resolve(directory);
92629
+ if (!fullPath.startsWith(resolvedDirectory + path109.sep) && fullPath !== resolvedDirectory) {
92381
92630
  continue;
92382
92631
  }
92383
92632
  if (!fs84.existsSync(fullPath)) {
@@ -92386,7 +92635,7 @@ async function placeholderScan(input, directory) {
92386
92635
  if (isAllowedByGlobs(filePath, allow_globs)) {
92387
92636
  continue;
92388
92637
  }
92389
- const relativeFilePath = path108.relative(directory, fullPath).replace(/\\/g, "/");
92638
+ const relativeFilePath = path109.relative(directory, fullPath).replace(/\\/g, "/");
92390
92639
  if (FILE_ALLOWLIST.some((allowed) => relativeFilePath.endsWith(allowed))) {
92391
92640
  continue;
92392
92641
  }
@@ -92458,7 +92707,7 @@ var placeholder_scan = createSwarmTool({
92458
92707
  });
92459
92708
  // src/tools/pre-check-batch.ts
92460
92709
  import * as fs88 from "node:fs";
92461
- import * as path112 from "node:path";
92710
+ import * as path113 from "node:path";
92462
92711
  init_zod();
92463
92712
  init_manager2();
92464
92713
  init_utils();
@@ -92599,7 +92848,7 @@ init_zod();
92599
92848
  init_manager2();
92600
92849
  init_detector();
92601
92850
  import * as fs87 from "node:fs";
92602
- import * as path111 from "node:path";
92851
+ import * as path112 from "node:path";
92603
92852
  import { extname as extname19 } from "node:path";
92604
92853
 
92605
92854
  // src/sast/rules/c.ts
@@ -93315,7 +93564,7 @@ function executeRulesSync(filePath, content, language) {
93315
93564
  // src/sast/semgrep.ts
93316
93565
  import * as child_process9 from "node:child_process";
93317
93566
  import * as fs85 from "node:fs";
93318
- import * as path109 from "node:path";
93567
+ import * as path110 from "node:path";
93319
93568
  var semgrepAvailableCache = null;
93320
93569
  var DEFAULT_RULES_DIR = ".swarm/semgrep-rules";
93321
93570
  var DEFAULT_TIMEOUT_MS3 = 30000;
@@ -93502,7 +93751,7 @@ async function runSemgrep(options) {
93502
93751
  }
93503
93752
  function getRulesDirectory(projectRoot) {
93504
93753
  if (projectRoot) {
93505
- return path109.resolve(projectRoot, DEFAULT_RULES_DIR);
93754
+ return path110.resolve(projectRoot, DEFAULT_RULES_DIR);
93506
93755
  }
93507
93756
  return DEFAULT_RULES_DIR;
93508
93757
  }
@@ -93523,24 +93772,24 @@ init_create_tool();
93523
93772
  init_utils2();
93524
93773
  import * as crypto9 from "node:crypto";
93525
93774
  import * as fs86 from "node:fs";
93526
- import * as path110 from "node:path";
93775
+ import * as path111 from "node:path";
93527
93776
  var BASELINE_SCHEMA_VERSION = "1.0.0";
93528
93777
  var MAX_BASELINE_FINDINGS = 2000;
93529
93778
  var MAX_BASELINE_BYTES = 2 * 1048576;
93530
93779
  var LOCK_RETRY_DELAYS_MS = [50, 100, 200, 400, 800];
93531
93780
  function normalizeFindingPath(directory, file3) {
93532
- const resolved = path110.isAbsolute(file3) ? file3 : path110.resolve(directory, file3);
93533
- const rel = path110.relative(path110.resolve(directory), resolved);
93781
+ const resolved = path111.isAbsolute(file3) ? file3 : path111.resolve(directory, file3);
93782
+ const rel = path111.relative(path111.resolve(directory), resolved);
93534
93783
  return rel.replace(/\\/g, "/");
93535
93784
  }
93536
93785
  function baselineRelPath(phase) {
93537
- return path110.join("evidence", String(phase), "sast-baseline.json");
93786
+ return path111.join("evidence", String(phase), "sast-baseline.json");
93538
93787
  }
93539
93788
  function tempRelPath(phase) {
93540
- return path110.join("evidence", String(phase), `sast-baseline.json.tmp.${Date.now()}.${process.pid}`);
93789
+ return path111.join("evidence", String(phase), `sast-baseline.json.tmp.${Date.now()}.${process.pid}`);
93541
93790
  }
93542
93791
  function lockRelPath(phase) {
93543
- return path110.join("evidence", String(phase), "sast-baseline.json.lock");
93792
+ return path111.join("evidence", String(phase), "sast-baseline.json.lock");
93544
93793
  }
93545
93794
  function getLine(lines, idx) {
93546
93795
  if (idx < 0 || idx >= lines.length)
@@ -93661,8 +93910,8 @@ async function captureOrMergeBaseline(directory, phase, findings, engine, scanne
93661
93910
  message: e instanceof Error ? e.message : "Path validation failed"
93662
93911
  };
93663
93912
  }
93664
- fs86.mkdirSync(path110.dirname(baselinePath), { recursive: true });
93665
- fs86.mkdirSync(path110.dirname(tempPath), { recursive: true });
93913
+ fs86.mkdirSync(path111.dirname(baselinePath), { recursive: true });
93914
+ fs86.mkdirSync(path111.dirname(tempPath), { recursive: true });
93666
93915
  const releaseLock = await acquireLock2(lockPath);
93667
93916
  try {
93668
93917
  let existing = null;
@@ -93935,9 +94184,9 @@ async function sastScan(input, directory, config3) {
93935
94184
  _filesSkipped++;
93936
94185
  continue;
93937
94186
  }
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) {
94187
+ const resolvedPath = path112.isAbsolute(filePath) ? filePath : path112.resolve(directory, filePath);
94188
+ const resolvedDirectory = path112.resolve(directory);
94189
+ if (!resolvedPath.startsWith(resolvedDirectory + path112.sep) && resolvedPath !== resolvedDirectory) {
93941
94190
  _filesSkipped++;
93942
94191
  continue;
93943
94192
  }
@@ -94252,18 +94501,18 @@ function validatePath(inputPath, baseDir, workspaceDir) {
94252
94501
  let resolved;
94253
94502
  const isWinAbs = isWindowsAbsolutePath(inputPath);
94254
94503
  if (isWinAbs) {
94255
- resolved = path112.win32.resolve(inputPath);
94256
- } else if (path112.isAbsolute(inputPath)) {
94257
- resolved = path112.resolve(inputPath);
94504
+ resolved = path113.win32.resolve(inputPath);
94505
+ } else if (path113.isAbsolute(inputPath)) {
94506
+ resolved = path113.resolve(inputPath);
94258
94507
  } else {
94259
- resolved = path112.resolve(baseDir, inputPath);
94508
+ resolved = path113.resolve(baseDir, inputPath);
94260
94509
  }
94261
- const workspaceResolved = path112.resolve(workspaceDir);
94510
+ const workspaceResolved = path113.resolve(workspaceDir);
94262
94511
  let relative24;
94263
94512
  if (isWinAbs) {
94264
- relative24 = path112.win32.relative(workspaceResolved, resolved);
94513
+ relative24 = path113.win32.relative(workspaceResolved, resolved);
94265
94514
  } else {
94266
- relative24 = path112.relative(workspaceResolved, resolved);
94515
+ relative24 = path113.relative(workspaceResolved, resolved);
94267
94516
  }
94268
94517
  if (relative24.startsWith("..")) {
94269
94518
  return "path traversal detected";
@@ -94328,7 +94577,7 @@ async function runLintOnFiles(linter, files, workspaceDir) {
94328
94577
  if (typeof file3 !== "string") {
94329
94578
  continue;
94330
94579
  }
94331
- const resolvedPath = path112.resolve(file3);
94580
+ const resolvedPath = path113.resolve(file3);
94332
94581
  const validationError = validatePath(resolvedPath, workspaceDir, workspaceDir);
94333
94582
  if (validationError) {
94334
94583
  continue;
@@ -94485,7 +94734,7 @@ async function runSecretscanWithFiles(files, directory) {
94485
94734
  skippedFiles++;
94486
94735
  continue;
94487
94736
  }
94488
- const resolvedPath = path112.resolve(file3);
94737
+ const resolvedPath = path113.resolve(file3);
94489
94738
  const validationError = validatePath(resolvedPath, directory, directory);
94490
94739
  if (validationError) {
94491
94740
  skippedFiles++;
@@ -94503,7 +94752,7 @@ async function runSecretscanWithFiles(files, directory) {
94503
94752
  };
94504
94753
  }
94505
94754
  for (const file3 of validatedFiles) {
94506
- const ext = path112.extname(file3).toLowerCase();
94755
+ const ext = path113.extname(file3).toLowerCase();
94507
94756
  if (DEFAULT_EXCLUDE_EXTENSIONS2.has(ext)) {
94508
94757
  skippedFiles++;
94509
94758
  continue;
@@ -94722,7 +94971,7 @@ function classifySastFindings(findings, changedLineRanges, directory) {
94722
94971
  const preexistingFindings = [];
94723
94972
  for (const finding of findings) {
94724
94973
  const filePath = finding.location.file;
94725
- const normalised = path112.relative(directory, filePath).replace(/\\/g, "/");
94974
+ const normalised = path113.relative(directory, filePath).replace(/\\/g, "/");
94726
94975
  const changedLines = changedLineRanges.get(normalised);
94727
94976
  if (changedLines?.has(finding.location.line)) {
94728
94977
  newFindings.push(finding);
@@ -94773,7 +95022,7 @@ async function runPreCheckBatch(input, workspaceDir, contextDir) {
94773
95022
  warn(`pre_check_batch: Invalid file path: ${file3}`);
94774
95023
  continue;
94775
95024
  }
94776
- changedFiles.push(path112.resolve(directory, file3));
95025
+ changedFiles.push(path113.resolve(directory, file3));
94777
95026
  }
94778
95027
  if (changedFiles.length === 0) {
94779
95028
  warn("pre_check_batch: No valid files after validation, skipping all tools (fail-closed)");
@@ -94974,7 +95223,7 @@ var pre_check_batch = createSwarmTool({
94974
95223
  };
94975
95224
  return JSON.stringify(errorResult, null, 2);
94976
95225
  }
94977
- const resolvedDirectory = path112.resolve(typedArgs.directory);
95226
+ const resolvedDirectory = path113.resolve(typedArgs.directory);
94978
95227
  const workspaceAnchor = resolvedDirectory;
94979
95228
  const dirError = validateDirectory2(resolvedDirectory, workspaceAnchor);
94980
95229
  if (dirError) {
@@ -95015,7 +95264,7 @@ var pre_check_batch = createSwarmTool({
95015
95264
  });
95016
95265
  // src/tools/repo-map.ts
95017
95266
  init_zod();
95018
- import * as path113 from "node:path";
95267
+ import * as path114 from "node:path";
95019
95268
  init_path_security();
95020
95269
  init_create_tool();
95021
95270
  var VALID_ACTIONS = [
@@ -95040,7 +95289,7 @@ function validateFile(p) {
95040
95289
  return "file contains control characters";
95041
95290
  if (containsPathTraversal(p))
95042
95291
  return "file contains path traversal";
95043
- if (path113.isAbsolute(p) || /^[a-zA-Z]:[\\/]/.test(p)) {
95292
+ if (path114.isAbsolute(p) || /^[a-zA-Z]:[\\/]/.test(p)) {
95044
95293
  return "file must be a workspace-relative path, not absolute";
95045
95294
  }
95046
95295
  return null;
@@ -95063,8 +95312,8 @@ function ok(action, payload) {
95063
95312
  }
95064
95313
  function toRelativeGraphPath(input, workspaceRoot) {
95065
95314
  const normalized = input.replace(/\\/g, "/");
95066
- if (path113.isAbsolute(normalized)) {
95067
- const rel = path113.relative(workspaceRoot, normalized).replace(/\\/g, "/");
95315
+ if (path114.isAbsolute(normalized)) {
95316
+ const rel = path114.relative(workspaceRoot, normalized).replace(/\\/g, "/");
95068
95317
  return normalizeGraphPath2(rel);
95069
95318
  }
95070
95319
  return normalizeGraphPath2(normalized);
@@ -95209,7 +95458,7 @@ var repo_map = createSwarmTool({
95209
95458
  init_zod();
95210
95459
  init_create_tool();
95211
95460
  import * as fs89 from "node:fs";
95212
- import * as path114 from "node:path";
95461
+ import * as path115 from "node:path";
95213
95462
  var SPEC_FILE = ".swarm/spec.md";
95214
95463
  var EVIDENCE_DIR4 = ".swarm/evidence";
95215
95464
  var OBLIGATION_KEYWORDS = ["MUST", "SHOULD", "SHALL"];
@@ -95278,7 +95527,7 @@ function readTouchedFiles(evidenceDir, phase, cwd) {
95278
95527
  return [];
95279
95528
  }
95280
95529
  for (const entry of entries) {
95281
- const entryPath = path114.join(evidenceDir, entry);
95530
+ const entryPath = path115.join(evidenceDir, entry);
95282
95531
  try {
95283
95532
  const stat8 = fs89.statSync(entryPath);
95284
95533
  if (!stat8.isDirectory()) {
@@ -95294,11 +95543,11 @@ function readTouchedFiles(evidenceDir, phase, cwd) {
95294
95543
  if (entryPhase !== String(phase)) {
95295
95544
  continue;
95296
95545
  }
95297
- const evidenceFilePath = path114.join(entryPath, "evidence.json");
95546
+ const evidenceFilePath = path115.join(entryPath, "evidence.json");
95298
95547
  try {
95299
- const resolvedPath = path114.resolve(evidenceFilePath);
95300
- const evidenceDirResolved = path114.resolve(evidenceDir);
95301
- if (!resolvedPath.startsWith(evidenceDirResolved + path114.sep)) {
95548
+ const resolvedPath = path115.resolve(evidenceFilePath);
95549
+ const evidenceDirResolved = path115.resolve(evidenceDir);
95550
+ if (!resolvedPath.startsWith(evidenceDirResolved + path115.sep)) {
95302
95551
  continue;
95303
95552
  }
95304
95553
  const stat8 = fs89.lstatSync(evidenceFilePath);
@@ -95332,7 +95581,7 @@ function readTouchedFiles(evidenceDir, phase, cwd) {
95332
95581
  if (Array.isArray(diffEntry.files_changed)) {
95333
95582
  for (const file3 of diffEntry.files_changed) {
95334
95583
  if (typeof file3 === "string") {
95335
- touchedFiles.add(path114.resolve(cwd, file3));
95584
+ touchedFiles.add(path115.resolve(cwd, file3));
95336
95585
  }
95337
95586
  }
95338
95587
  }
@@ -95345,8 +95594,8 @@ function readTouchedFiles(evidenceDir, phase, cwd) {
95345
95594
  }
95346
95595
  function searchFileForKeywords(filePath, keywords, cwd) {
95347
95596
  try {
95348
- const resolvedPath = path114.resolve(filePath);
95349
- const cwdResolved = path114.resolve(cwd);
95597
+ const resolvedPath = path115.resolve(filePath);
95598
+ const cwdResolved = path115.resolve(cwd);
95350
95599
  if (!resolvedPath.startsWith(cwdResolved)) {
95351
95600
  return false;
95352
95601
  }
@@ -95480,7 +95729,7 @@ var req_coverage = createSwarmTool({
95480
95729
  }, null, 2);
95481
95730
  }
95482
95731
  const cwd = inputDirectory || directory;
95483
- const specPath = path114.join(cwd, SPEC_FILE);
95732
+ const specPath = path115.join(cwd, SPEC_FILE);
95484
95733
  let specContent;
95485
95734
  try {
95486
95735
  specContent = fs89.readFileSync(specPath, "utf-8");
@@ -95507,7 +95756,7 @@ var req_coverage = createSwarmTool({
95507
95756
  message: "No FR requirements found in spec.md"
95508
95757
  }, null, 2);
95509
95758
  }
95510
- const evidenceDir = path114.join(cwd, EVIDENCE_DIR4);
95759
+ const evidenceDir = path115.join(cwd, EVIDENCE_DIR4);
95511
95760
  const touchedFiles = readTouchedFiles(evidenceDir, phase, cwd);
95512
95761
  const analyzedRequirements = [];
95513
95762
  let coveredCount = 0;
@@ -95533,7 +95782,7 @@ var req_coverage = createSwarmTool({
95533
95782
  requirements: analyzedRequirements
95534
95783
  };
95535
95784
  const reportFilename = `req-coverage-phase-${phase}.json`;
95536
- const reportPath = path114.join(evidenceDir, reportFilename);
95785
+ const reportPath = path115.join(evidenceDir, reportFilename);
95537
95786
  try {
95538
95787
  if (!fs89.existsSync(evidenceDir)) {
95539
95788
  fs89.mkdirSync(evidenceDir, { recursive: true });
@@ -95621,7 +95870,7 @@ init_qa_gate_profile();
95621
95870
  init_file_locks();
95622
95871
  import * as crypto10 from "node:crypto";
95623
95872
  import * as fs90 from "node:fs";
95624
- import * as path115 from "node:path";
95873
+ import * as path116 from "node:path";
95625
95874
  init_ledger();
95626
95875
  init_manager();
95627
95876
  init_state();
@@ -95699,8 +95948,8 @@ async function executeSavePlan(args2, fallbackDir) {
95699
95948
  };
95700
95949
  }
95701
95950
  if (args2.working_directory && fallbackDir) {
95702
- const resolvedTarget = path115.resolve(args2.working_directory);
95703
- const resolvedRoot = path115.resolve(fallbackDir);
95951
+ const resolvedTarget = path116.resolve(args2.working_directory);
95952
+ const resolvedRoot = path116.resolve(fallbackDir);
95704
95953
  let fallbackExists = false;
95705
95954
  try {
95706
95955
  fs90.accessSync(resolvedRoot, fs90.constants.F_OK);
@@ -95709,7 +95958,7 @@ async function executeSavePlan(args2, fallbackDir) {
95709
95958
  fallbackExists = false;
95710
95959
  }
95711
95960
  if (fallbackExists) {
95712
- const isSubdirectory = resolvedTarget.startsWith(resolvedRoot + path115.sep);
95961
+ const isSubdirectory = resolvedTarget.startsWith(resolvedRoot + path116.sep);
95713
95962
  if (isSubdirectory) {
95714
95963
  return {
95715
95964
  success: false,
@@ -95725,7 +95974,7 @@ async function executeSavePlan(args2, fallbackDir) {
95725
95974
  let specMtime;
95726
95975
  let specHash;
95727
95976
  if (process.env.SWARM_SKIP_SPEC_GATE !== "1") {
95728
- const specPath = path115.join(targetWorkspace, ".swarm", "spec.md");
95977
+ const specPath = path116.join(targetWorkspace, ".swarm", "spec.md");
95729
95978
  try {
95730
95979
  const stat8 = await fs90.promises.stat(specPath);
95731
95980
  specMtime = stat8.mtime.toISOString();
@@ -95741,7 +95990,7 @@ async function executeSavePlan(args2, fallbackDir) {
95741
95990
  }
95742
95991
  }
95743
95992
  if (process.env.SWARM_SKIP_GATE_SELECTION !== "1") {
95744
- const contextPath = path115.join(targetWorkspace, ".swarm", "context.md");
95993
+ const contextPath = path116.join(targetWorkspace, ".swarm", "context.md");
95745
95994
  let contextContent = "";
95746
95995
  try {
95747
95996
  contextContent = await fs90.promises.readFile(contextPath, "utf8");
@@ -95771,6 +96020,7 @@ async function executeSavePlan(args2, fallbackDir) {
95771
96020
  }
95772
96021
  const dir = targetWorkspace;
95773
96022
  const existingStatusMap = new Map;
96023
+ const priorTaskIds = new Set;
95774
96024
  let preservedExecutionProfile;
95775
96025
  {
95776
96026
  let existing = null;
@@ -95778,6 +96028,10 @@ async function executeSavePlan(args2, fallbackDir) {
95778
96028
  existing = await loadPlanJsonOnly(dir);
95779
96029
  } catch {}
95780
96030
  if (existing) {
96031
+ for (const phase of existing.phases) {
96032
+ for (const task of phase.tasks)
96033
+ priorTaskIds.add(task.id);
96034
+ }
95781
96035
  if (!args2.reset_statuses) {
95782
96036
  for (const phase of existing.phases) {
95783
96037
  for (const task of phase.tasks) {
@@ -95819,6 +96073,98 @@ async function executeSavePlan(args2, fallbackDir) {
95819
96073
  }
95820
96074
  resolvedProfile = parsed.data;
95821
96075
  }
96076
+ const incomingTaskIds = new Set;
96077
+ for (const phase of args2.phases) {
96078
+ for (const task of phase.tasks)
96079
+ incomingTaskIds.add(task.id);
96080
+ }
96081
+ const missingTaskIds = [];
96082
+ for (const id of priorTaskIds) {
96083
+ if (!incomingTaskIds.has(id))
96084
+ missingTaskIds.push(id);
96085
+ }
96086
+ const rawRemovedIds = args2.removed_task_ids ?? [];
96087
+ if (rawRemovedIds.length > 0) {
96088
+ const seen = new Set;
96089
+ for (const id of rawRemovedIds) {
96090
+ if (seen.has(id)) {
96091
+ return {
96092
+ success: false,
96093
+ message: "PLAN_TASK_REMOVAL_INVALID: removed_task_ids contains duplicate entries",
96094
+ errors: [`Duplicate id in removed_task_ids: "${id}"`],
96095
+ recovery_guidance: "Deduplicate removed_task_ids and retry save_plan."
96096
+ };
96097
+ }
96098
+ seen.add(id);
96099
+ }
96100
+ for (const id of rawRemovedIds) {
96101
+ if (incomingTaskIds.has(id)) {
96102
+ return {
96103
+ success: false,
96104
+ message: "PLAN_TASK_REMOVAL_INVALID: removed_task_ids contains a task that also appears in args.phases",
96105
+ errors: [
96106
+ `Task "${id}" appears in both removed_task_ids and args.phases — these are contradictory`
96107
+ ],
96108
+ 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."
96109
+ };
96110
+ }
96111
+ }
96112
+ for (const id of rawRemovedIds) {
96113
+ if (!priorTaskIds.has(id)) {
96114
+ return {
96115
+ success: false,
96116
+ message: "PLAN_TASK_REMOVAL_INVALID: removed_task_ids contains an id that was not in the prior plan",
96117
+ errors: [
96118
+ `Task "${id}" is in removed_task_ids but not present in the prior plan`
96119
+ ],
96120
+ recovery_guidance: "Re-read the prior plan and update removed_task_ids to only list tasks that actually existed."
96121
+ };
96122
+ }
96123
+ }
96124
+ }
96125
+ let resolvedRemovedIds = [...rawRemovedIds];
96126
+ let resolvedRemovalReason = args2.removal_reason;
96127
+ if (args2.reset_statuses === true && missingTaskIds.length > 0) {
96128
+ if (args2.confirm_destructive_reset !== true) {
96129
+ return {
96130
+ success: false,
96131
+ message: "PLAN_DESTRUCTIVE_RESET_NOT_CONFIRMED: reset_statuses with missing tasks requires confirm_destructive_reset: true",
96132
+ errors: [
96133
+ `reset_statuses: true would drop ${missingTaskIds.length} task(s) from the prior plan: ${missingTaskIds.join(", ")}`
96134
+ ],
96135
+ 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."
96136
+ };
96137
+ }
96138
+ if (rawRemovedIds.length === 0) {
96139
+ resolvedRemovedIds = [...missingTaskIds];
96140
+ resolvedRemovalReason = "destructive reset acknowledged";
96141
+ }
96142
+ }
96143
+ if (resolvedRemovedIds.length > 0) {
96144
+ const reason = (resolvedRemovalReason ?? "").trim();
96145
+ if (reason.length === 0) {
96146
+ return {
96147
+ success: false,
96148
+ message: "PLAN_TASK_REMOVAL_INVALID: removal_reason is required when removed_task_ids is non-empty",
96149
+ errors: ["removal_reason must be a non-empty, non-whitespace string"],
96150
+ recovery_guidance: "Provide a removal_reason describing why these tasks are being dropped."
96151
+ };
96152
+ }
96153
+ }
96154
+ if (missingTaskIds.length > 0) {
96155
+ const ackSet = new Set(resolvedRemovedIds);
96156
+ const unacked = missingTaskIds.filter((id) => !ackSet.has(id));
96157
+ if (unacked.length > 0) {
96158
+ return {
96159
+ success: false,
96160
+ message: "PLAN_TASK_REMOVAL_NOT_ACKNOWLEDGED: this save would silently drop tasks from the prior plan",
96161
+ errors: [
96162
+ `The following prior tasks are missing from the new save and were not listed in removed_task_ids: ${unacked.join(", ")}`
96163
+ ],
96164
+ 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."
96165
+ };
96166
+ }
96167
+ }
95822
96168
  const plan = {
95823
96169
  schema_version: "1.0.0",
95824
96170
  title: args2.title,
@@ -95865,7 +96211,14 @@ async function executeSavePlan(args2, fallbackDir) {
95865
96211
  }
95866
96212
  try {
95867
96213
  await savePlan(dir, plan, {
95868
- preserveCompletedStatuses: !args2.reset_statuses
96214
+ preserveCompletedStatuses: !args2.reset_statuses,
96215
+ ...resolvedRemovedIds.length > 0 ? {
96216
+ acknowledged_removals: {
96217
+ ids: resolvedRemovedIds,
96218
+ reason: (resolvedRemovalReason ?? "").trim(),
96219
+ source: "save_plan_tool"
96220
+ }
96221
+ } : {}
95869
96222
  });
95870
96223
  const savedPlan = await loadPlanJsonOnly(dir);
95871
96224
  if (savedPlan) {
@@ -95894,7 +96247,7 @@ async function executeSavePlan(args2, fallbackDir) {
95894
96247
  }
95895
96248
  await writeCheckpoint(dir).catch(() => {});
95896
96249
  try {
95897
- const markerPath = path115.join(dir, ".swarm", ".plan-write-marker");
96250
+ const markerPath = path116.join(dir, ".swarm", ".plan-write-marker");
95898
96251
  const marker = JSON.stringify({
95899
96252
  source: "save_plan",
95900
96253
  timestamp: new Date().toISOString(),
@@ -95917,7 +96270,7 @@ async function executeSavePlan(args2, fallbackDir) {
95917
96270
  return {
95918
96271
  success: true,
95919
96272
  message: "Plan saved successfully",
95920
- plan_path: path115.join(dir, ".swarm", "plan.json"),
96273
+ plan_path: path116.join(dir, ".swarm", "plan.json"),
95921
96274
  phases_count: plan.phases.length,
95922
96275
  tasks_count: tasksCount,
95923
96276
  ...resolvedProfile !== undefined ? { execution_profile: resolvedProfile } : {},
@@ -95929,6 +96282,15 @@ async function executeSavePlan(args2, fallbackDir) {
95929
96282
  }
95930
96283
  }
95931
96284
  } catch (error93) {
96285
+ if (error93 instanceof PlanTaskRemovalNotAcknowledgedError) {
96286
+ const ids = error93.missingTasks.map((t) => t.id);
96287
+ return {
96288
+ success: false,
96289
+ message: "PLAN_TASK_REMOVAL_NOT_ACKNOWLEDGED: this save would silently drop tasks from the prior plan",
96290
+ errors: [error93.message],
96291
+ recovery_guidance: "Re-read the current plan, then retry save_plan with " + `removed_task_ids: ${JSON.stringify(ids)} and a non-empty removal_reason.`
96292
+ };
96293
+ }
95932
96294
  return {
95933
96295
  success: false,
95934
96296
  message: "Failed to save plan: retry with save_plan after resolving the error above",
@@ -95955,6 +96317,9 @@ var save_plan = createSwarmTool({
95955
96317
  })).min(1).describe("Implementation phases"),
95956
96318
  working_directory: exports_external.string().optional().describe("Working directory (explicit path, required - no fallback)"),
95957
96319
  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)."),
96320
+ 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."),
96321
+ 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."),
96322
+ 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
96323
  execution_profile: exports_external.object({
95959
96324
  parallelization_enabled: exports_external.boolean().optional().describe("When true, enables parallel task dispatch for this plan. Default false (serial)."),
95960
96325
  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 +96335,7 @@ var save_plan = createSwarmTool({
95970
96335
  init_zod();
95971
96336
  init_manager2();
95972
96337
  import * as fs91 from "node:fs";
95973
- import * as path116 from "node:path";
96338
+ import * as path117 from "node:path";
95974
96339
 
95975
96340
  // src/sbom/detectors/index.ts
95976
96341
  init_utils();
@@ -96820,7 +97185,7 @@ function findManifestFiles(rootDir) {
96820
97185
  try {
96821
97186
  const entries = fs91.readdirSync(dir, { withFileTypes: true });
96822
97187
  for (const entry of entries) {
96823
- const fullPath = path116.join(dir, entry.name);
97188
+ const fullPath = path117.join(dir, entry.name);
96824
97189
  if (entry.name.startsWith(".") || entry.name === "node_modules" || entry.name === "dist" || entry.name === "build" || entry.name === "target") {
96825
97190
  continue;
96826
97191
  }
@@ -96829,7 +97194,7 @@ function findManifestFiles(rootDir) {
96829
97194
  } else if (entry.isFile()) {
96830
97195
  for (const pattern of patterns) {
96831
97196
  if (simpleGlobToRegex(pattern).test(entry.name)) {
96832
- manifestFiles.push(path116.relative(rootDir, fullPath));
97197
+ manifestFiles.push(path117.relative(rootDir, fullPath));
96833
97198
  break;
96834
97199
  }
96835
97200
  }
@@ -96847,11 +97212,11 @@ function findManifestFilesInDirs(directories, workingDir) {
96847
97212
  try {
96848
97213
  const entries = fs91.readdirSync(dir, { withFileTypes: true });
96849
97214
  for (const entry of entries) {
96850
- const fullPath = path116.join(dir, entry.name);
97215
+ const fullPath = path117.join(dir, entry.name);
96851
97216
  if (entry.isFile()) {
96852
97217
  for (const pattern of patterns) {
96853
97218
  if (simpleGlobToRegex(pattern).test(entry.name)) {
96854
- found.push(path116.relative(workingDir, fullPath));
97219
+ found.push(path117.relative(workingDir, fullPath));
96855
97220
  break;
96856
97221
  }
96857
97222
  }
@@ -96864,11 +97229,11 @@ function findManifestFilesInDirs(directories, workingDir) {
96864
97229
  function getDirectoriesFromChangedFiles(changedFiles, workingDir) {
96865
97230
  const dirs = new Set;
96866
97231
  for (const file3 of changedFiles) {
96867
- let currentDir = path116.dirname(file3);
97232
+ let currentDir = path117.dirname(file3);
96868
97233
  while (true) {
96869
- if (currentDir && currentDir !== "." && currentDir !== path116.sep) {
96870
- dirs.add(path116.join(workingDir, currentDir));
96871
- const parent = path116.dirname(currentDir);
97234
+ if (currentDir && currentDir !== "." && currentDir !== path117.sep) {
97235
+ dirs.add(path117.join(workingDir, currentDir));
97236
+ const parent = path117.dirname(currentDir);
96872
97237
  if (parent === currentDir)
96873
97238
  break;
96874
97239
  currentDir = parent;
@@ -96952,7 +97317,7 @@ var sbom_generate = createSwarmTool({
96952
97317
  const changedFiles = obj.changed_files;
96953
97318
  const relativeOutputDir = obj.output_dir || DEFAULT_OUTPUT_DIR;
96954
97319
  const workingDir = directory;
96955
- const outputDir = path116.isAbsolute(relativeOutputDir) ? relativeOutputDir : path116.join(workingDir, relativeOutputDir);
97320
+ const outputDir = path117.isAbsolute(relativeOutputDir) ? relativeOutputDir : path117.join(workingDir, relativeOutputDir);
96956
97321
  let manifestFiles = [];
96957
97322
  if (scope === "all") {
96958
97323
  manifestFiles = findManifestFiles(workingDir);
@@ -96975,7 +97340,7 @@ var sbom_generate = createSwarmTool({
96975
97340
  const processedFiles = [];
96976
97341
  for (const manifestFile of manifestFiles) {
96977
97342
  try {
96978
- const fullPath = path116.isAbsolute(manifestFile) ? manifestFile : path116.join(workingDir, manifestFile);
97343
+ const fullPath = path117.isAbsolute(manifestFile) ? manifestFile : path117.join(workingDir, manifestFile);
96979
97344
  if (!fs91.existsSync(fullPath)) {
96980
97345
  continue;
96981
97346
  }
@@ -96992,7 +97357,7 @@ var sbom_generate = createSwarmTool({
96992
97357
  const bom = generateCycloneDX(allComponents);
96993
97358
  const bomJson = serializeCycloneDX(bom);
96994
97359
  const filename = generateSbomFilename();
96995
- const outputPath = path116.join(outputDir, filename);
97360
+ const outputPath = path117.join(outputDir, filename);
96996
97361
  fs91.writeFileSync(outputPath, bomJson, "utf-8");
96997
97362
  const verdict = processedFiles.length > 0 ? "pass" : "pass";
96998
97363
  try {
@@ -97036,7 +97401,7 @@ var sbom_generate = createSwarmTool({
97036
97401
  init_zod();
97037
97402
  init_create_tool();
97038
97403
  import * as fs92 from "node:fs";
97039
- import * as path117 from "node:path";
97404
+ import * as path118 from "node:path";
97040
97405
  var SPEC_CANDIDATES = [
97041
97406
  "openapi.json",
97042
97407
  "openapi.yaml",
@@ -97068,12 +97433,12 @@ function normalizePath4(p) {
97068
97433
  }
97069
97434
  function discoverSpecFile(cwd, specFileArg) {
97070
97435
  if (specFileArg) {
97071
- const resolvedPath = path117.resolve(cwd, specFileArg);
97072
- const normalizedCwd = cwd.endsWith(path117.sep) ? cwd : cwd + path117.sep;
97436
+ const resolvedPath = path118.resolve(cwd, specFileArg);
97437
+ const normalizedCwd = cwd.endsWith(path118.sep) ? cwd : cwd + path118.sep;
97073
97438
  if (!resolvedPath.startsWith(normalizedCwd) && resolvedPath !== cwd) {
97074
97439
  throw new Error("Invalid spec_file: path traversal detected");
97075
97440
  }
97076
- const ext = path117.extname(resolvedPath).toLowerCase();
97441
+ const ext = path118.extname(resolvedPath).toLowerCase();
97077
97442
  if (!ALLOWED_EXTENSIONS.includes(ext)) {
97078
97443
  throw new Error(`Invalid spec_file: must end in .json, .yaml, or .yml, got ${ext}`);
97079
97444
  }
@@ -97087,7 +97452,7 @@ function discoverSpecFile(cwd, specFileArg) {
97087
97452
  return resolvedPath;
97088
97453
  }
97089
97454
  for (const candidate of SPEC_CANDIDATES) {
97090
- const candidatePath = path117.resolve(cwd, candidate);
97455
+ const candidatePath = path118.resolve(cwd, candidate);
97091
97456
  if (fs92.existsSync(candidatePath)) {
97092
97457
  const stats = fs92.statSync(candidatePath);
97093
97458
  if (stats.size <= MAX_SPEC_SIZE) {
@@ -97099,7 +97464,7 @@ function discoverSpecFile(cwd, specFileArg) {
97099
97464
  }
97100
97465
  function parseSpec(specFile) {
97101
97466
  const content = fs92.readFileSync(specFile, "utf-8");
97102
- const ext = path117.extname(specFile).toLowerCase();
97467
+ const ext = path118.extname(specFile).toLowerCase();
97103
97468
  if (ext === ".json") {
97104
97469
  return parseJsonSpec(content);
97105
97470
  }
@@ -97175,7 +97540,7 @@ function extractRoutes(cwd) {
97175
97540
  return;
97176
97541
  }
97177
97542
  for (const entry of entries) {
97178
- const fullPath = path117.join(dir, entry.name);
97543
+ const fullPath = path118.join(dir, entry.name);
97179
97544
  if (entry.isSymbolicLink()) {
97180
97545
  continue;
97181
97546
  }
@@ -97185,7 +97550,7 @@ function extractRoutes(cwd) {
97185
97550
  }
97186
97551
  walkDir(fullPath);
97187
97552
  } else if (entry.isFile()) {
97188
- const ext = path117.extname(entry.name).toLowerCase();
97553
+ const ext = path118.extname(entry.name).toLowerCase();
97189
97554
  const baseName = entry.name.toLowerCase();
97190
97555
  if (![".ts", ".js", ".mjs"].includes(ext)) {
97191
97556
  continue;
@@ -97353,7 +97718,7 @@ init_bun_compat();
97353
97718
  init_path_security();
97354
97719
  init_create_tool();
97355
97720
  import * as fs93 from "node:fs";
97356
- import * as path118 from "node:path";
97721
+ import * as path119 from "node:path";
97357
97722
  var DEFAULT_MAX_RESULTS = 100;
97358
97723
  var DEFAULT_MAX_LINES = 200;
97359
97724
  var REGEX_TIMEOUT_MS = 5000;
@@ -97389,11 +97754,11 @@ function containsWindowsAttacks3(str) {
97389
97754
  }
97390
97755
  function isPathInWorkspace3(filePath, workspace) {
97391
97756
  try {
97392
- const resolvedPath = path118.resolve(workspace, filePath);
97757
+ const resolvedPath = path119.resolve(workspace, filePath);
97393
97758
  const realWorkspace = fs93.realpathSync(workspace);
97394
97759
  const realResolvedPath = fs93.realpathSync(resolvedPath);
97395
- const relativePath = path118.relative(realWorkspace, realResolvedPath);
97396
- if (relativePath.startsWith("..") || path118.isAbsolute(relativePath)) {
97760
+ const relativePath = path119.relative(realWorkspace, realResolvedPath);
97761
+ if (relativePath.startsWith("..") || path119.isAbsolute(relativePath)) {
97397
97762
  return false;
97398
97763
  }
97399
97764
  return true;
@@ -97406,11 +97771,11 @@ function validatePathForRead2(filePath, workspace) {
97406
97771
  }
97407
97772
  function findRgInEnvPath() {
97408
97773
  const searchPath = process.env.PATH ?? "";
97409
- for (const dir of searchPath.split(path118.delimiter)) {
97774
+ for (const dir of searchPath.split(path119.delimiter)) {
97410
97775
  if (!dir)
97411
97776
  continue;
97412
97777
  const isWindows = process.platform === "win32";
97413
- const candidate = path118.join(dir, isWindows ? "rg.exe" : "rg");
97778
+ const candidate = path119.join(dir, isWindows ? "rg.exe" : "rg");
97414
97779
  if (fs93.existsSync(candidate))
97415
97780
  return candidate;
97416
97781
  }
@@ -97540,8 +97905,8 @@ function collectFiles(dir, workspace, includeGlobs, excludeGlobs) {
97540
97905
  try {
97541
97906
  const entries = fs93.readdirSync(dir, { withFileTypes: true });
97542
97907
  for (const entry of entries) {
97543
- const fullPath = path118.join(dir, entry.name);
97544
- const relativePath = path118.relative(workspace, fullPath);
97908
+ const fullPath = path119.join(dir, entry.name);
97909
+ const relativePath = path119.relative(workspace, fullPath);
97545
97910
  if (!validatePathForRead2(fullPath, workspace)) {
97546
97911
  continue;
97547
97912
  }
@@ -97582,7 +97947,7 @@ async function fallbackSearch(opts) {
97582
97947
  const matches = [];
97583
97948
  let total = 0;
97584
97949
  for (const file3 of files) {
97585
- const fullPath = path118.join(opts.workspace, file3);
97950
+ const fullPath = path119.join(opts.workspace, file3);
97586
97951
  if (!validatePathForRead2(fullPath, opts.workspace)) {
97587
97952
  continue;
97588
97953
  }
@@ -97950,7 +98315,7 @@ init_config();
97950
98315
  init_schema();
97951
98316
  init_create_tool();
97952
98317
  import { mkdir as mkdir19, rename as rename8, writeFile as writeFile15 } from "node:fs/promises";
97953
- import * as path119 from "node:path";
98318
+ import * as path120 from "node:path";
97954
98319
  var MAX_SPEC_BYTES = 256 * 1024;
97955
98320
  var spec_write = createSwarmTool({
97956
98321
  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 +98356,8 @@ var spec_write = createSwarmTool({
97991
98356
  reason: 'spec must contain at least one top-level "# Heading"'
97992
98357
  }, null, 2);
97993
98358
  }
97994
- const target = path119.join(directory, ".swarm", "spec.md");
97995
- await mkdir19(path119.dirname(target), { recursive: true });
98359
+ const target = path120.join(directory, ".swarm", "spec.md");
98360
+ await mkdir19(path120.dirname(target), { recursive: true });
97996
98361
  const tmp = `${target}.tmp-${process.pid}-${Date.now()}`;
97997
98362
  let finalContent = content;
97998
98363
  if (mode === "append") {
@@ -98020,14 +98385,14 @@ ${content}
98020
98385
  init_zod();
98021
98386
  init_loader();
98022
98387
  import {
98023
- existsSync as existsSync68,
98388
+ existsSync as existsSync70,
98024
98389
  mkdirSync as mkdirSync29,
98025
- readFileSync as readFileSync60,
98390
+ readFileSync as readFileSync61,
98026
98391
  renameSync as renameSync19,
98027
98392
  unlinkSync as unlinkSync15,
98028
98393
  writeFileSync as writeFileSync23
98029
98394
  } from "node:fs";
98030
- import path120 from "node:path";
98395
+ import path121 from "node:path";
98031
98396
  init_create_tool();
98032
98397
  init_resolve_working_directory();
98033
98398
  var VerdictSchema2 = exports_external.object({
@@ -98157,9 +98522,9 @@ var submit_phase_council_verdicts = createSwarmTool({
98157
98522
  }
98158
98523
  });
98159
98524
  function getPhaseMutationGapFinding(phaseNumber, workingDir) {
98160
- const mutationGatePath = path120.join(workingDir, ".swarm", "evidence", String(phaseNumber), "mutation-gate.json");
98525
+ const mutationGatePath = path121.join(workingDir, ".swarm", "evidence", String(phaseNumber), "mutation-gate.json");
98161
98526
  try {
98162
- const raw = readFileSync60(mutationGatePath, "utf-8");
98527
+ const raw = readFileSync61(mutationGatePath, "utf-8");
98163
98528
  const parsed = JSON.parse(raw);
98164
98529
  const gateEntry = (parsed.entries ?? []).find((entry) => entry?.type === "mutation-gate");
98165
98530
  if (!gateEntry) {
@@ -98219,9 +98584,9 @@ function getPhaseMutationGapFinding(phaseNumber, workingDir) {
98219
98584
  }
98220
98585
  }
98221
98586
  function writePhaseCouncilEvidence(workingDir, synthesis) {
98222
- const evidenceDir = path120.join(workingDir, ".swarm", "evidence", String(synthesis.phaseNumber));
98587
+ const evidenceDir = path121.join(workingDir, ".swarm", "evidence", String(synthesis.phaseNumber));
98223
98588
  mkdirSync29(evidenceDir, { recursive: true });
98224
- const evidenceFile = path120.join(evidenceDir, "phase-council.json");
98589
+ const evidenceFile = path121.join(evidenceDir, "phase-council.json");
98225
98590
  const evidenceBundle = {
98226
98591
  entries: [
98227
98592
  {
@@ -98257,7 +98622,7 @@ function writePhaseCouncilEvidence(workingDir, synthesis) {
98257
98622
  writeFileSync23(tempFile, JSON.stringify(evidenceBundle, null, 2), "utf-8");
98258
98623
  renameSync19(tempFile, evidenceFile);
98259
98624
  } finally {
98260
- if (existsSync68(tempFile)) {
98625
+ if (existsSync70(tempFile)) {
98261
98626
  unlinkSync15(tempFile);
98262
98627
  }
98263
98628
  }
@@ -98307,7 +98672,7 @@ init_zod();
98307
98672
  init_path_security();
98308
98673
  init_create_tool();
98309
98674
  import * as fs94 from "node:fs";
98310
- import * as path121 from "node:path";
98675
+ import * as path122 from "node:path";
98311
98676
  var WINDOWS_RESERVED_NAMES4 = /^(con|prn|aux|nul|com[1-9]|lpt[1-9])(\.|:|$)/i;
98312
98677
  function containsWindowsAttacks4(str) {
98313
98678
  if (/:[^\\/]/.test(str))
@@ -98321,14 +98686,14 @@ function containsWindowsAttacks4(str) {
98321
98686
  }
98322
98687
  function isPathInWorkspace4(filePath, workspace) {
98323
98688
  try {
98324
- const resolvedPath = path121.resolve(workspace, filePath);
98689
+ const resolvedPath = path122.resolve(workspace, filePath);
98325
98690
  if (!fs94.existsSync(resolvedPath)) {
98326
98691
  return true;
98327
98692
  }
98328
98693
  const realWorkspace = fs94.realpathSync(workspace);
98329
98694
  const realResolvedPath = fs94.realpathSync(resolvedPath);
98330
- const relativePath = path121.relative(realWorkspace, realResolvedPath);
98331
- if (relativePath.startsWith("..") || path121.isAbsolute(relativePath)) {
98695
+ const relativePath = path122.relative(realWorkspace, realResolvedPath);
98696
+ if (relativePath.startsWith("..") || path122.isAbsolute(relativePath)) {
98332
98697
  return false;
98333
98698
  }
98334
98699
  return true;
@@ -98536,7 +98901,7 @@ var suggestPatch = createSwarmTool({
98536
98901
  });
98537
98902
  continue;
98538
98903
  }
98539
- const fullPath = path121.resolve(directory, change.file);
98904
+ const fullPath = path122.resolve(directory, change.file);
98540
98905
  if (!fs94.existsSync(fullPath)) {
98541
98906
  errors5.push({
98542
98907
  success: false,
@@ -98840,11 +99205,11 @@ var lean_turbo_acquire_locks = createSwarmTool({
98840
99205
  init_zod();
98841
99206
  init_constants();
98842
99207
  import * as fs96 from "node:fs";
98843
- import * as path123 from "node:path";
99208
+ import * as path124 from "node:path";
98844
99209
 
98845
99210
  // src/turbo/lean/conflicts.ts
98846
99211
  import * as fs95 from "node:fs";
98847
- import * as path122 from "node:path";
99212
+ import * as path123 from "node:path";
98848
99213
  var DEFAULT_GLOBAL_FILES = [
98849
99214
  "package.json",
98850
99215
  "package-lock.json",
@@ -98971,7 +99336,7 @@ function isProtectedPath2(normalizedPath) {
98971
99336
  return false;
98972
99337
  }
98973
99338
  function readTaskScopes(directory, taskId) {
98974
- const scopePath = path122.join(directory, ".swarm", "scopes", `scope-${taskId}.json`);
99339
+ const scopePath = path123.join(directory, ".swarm", "scopes", `scope-${taskId}.json`);
98975
99340
  try {
98976
99341
  if (!fs95.existsSync(scopePath)) {
98977
99342
  return null;
@@ -99359,7 +99724,7 @@ function createEmptyPlan(phaseNumber, planId) {
99359
99724
  // src/tools/lean-turbo-plan-lanes.ts
99360
99725
  init_create_tool();
99361
99726
  function readPlanJson(directory) {
99362
- const planPath = path123.join(directory, ".swarm", "plan.json");
99727
+ const planPath = path124.join(directory, ".swarm", "plan.json");
99363
99728
  if (!fs96.existsSync(planPath)) {
99364
99729
  return null;
99365
99730
  }
@@ -99414,7 +99779,7 @@ init_config();
99414
99779
  // src/turbo/lean/reviewer.ts
99415
99780
  init_state();
99416
99781
  import * as fs97 from "node:fs/promises";
99417
- import * as path124 from "node:path";
99782
+ import * as path125 from "node:path";
99418
99783
  init_state3();
99419
99784
  var DEFAULT_CONFIG3 = {
99420
99785
  reviewerAgent: "",
@@ -99530,9 +99895,9 @@ function parseReviewerVerdict(responseText) {
99530
99895
  return { verdict, reason };
99531
99896
  }
99532
99897
  async function writeReviewerEvidence(directory, phase, verdict, reason) {
99533
- const evidenceDir = path124.join(directory, ".swarm", "evidence", String(phase));
99898
+ const evidenceDir = path125.join(directory, ".swarm", "evidence", String(phase));
99534
99899
  await fs97.mkdir(evidenceDir, { recursive: true });
99535
- const evidencePath = path124.join(evidenceDir, "lean-turbo-reviewer.json");
99900
+ const evidencePath = path125.join(evidenceDir, "lean-turbo-reviewer.json");
99536
99901
  const content = JSON.stringify({
99537
99902
  phase,
99538
99903
  verdict,
@@ -100337,7 +100702,7 @@ var lean_turbo_status = createSwarmTool({
100337
100702
  init_spec_schema();
100338
100703
  init_create_tool();
100339
100704
  import * as fs98 from "node:fs";
100340
- import * as path125 from "node:path";
100705
+ import * as path126 from "node:path";
100341
100706
  var SPEC_FILE_NAME = "spec.md";
100342
100707
  var SWARM_DIR2 = ".swarm";
100343
100708
  var OBLIGATION_KEYWORDS2 = ["MUST", "SHALL", "SHOULD", "MAY"];
@@ -100390,7 +100755,7 @@ var lint_spec = createSwarmTool({
100390
100755
  async execute(_args, directory) {
100391
100756
  const errors5 = [];
100392
100757
  const warnings = [];
100393
- const specPath = path125.join(directory, SWARM_DIR2, SPEC_FILE_NAME);
100758
+ const specPath = path126.join(directory, SWARM_DIR2, SPEC_FILE_NAME);
100394
100759
  if (!fs98.existsSync(specPath)) {
100395
100760
  const result2 = {
100396
100761
  valid: false,
@@ -100461,12 +100826,12 @@ var lint_spec = createSwarmTool({
100461
100826
  // src/tools/mutation-test.ts
100462
100827
  init_zod();
100463
100828
  import * as fs99 from "node:fs";
100464
- import * as path127 from "node:path";
100829
+ import * as path128 from "node:path";
100465
100830
 
100466
100831
  // src/mutation/engine.ts
100467
100832
  import { spawnSync as spawnSync3 } from "node:child_process";
100468
100833
  import { unlinkSync as unlinkSync16, writeFileSync as writeFileSync24 } from "node:fs";
100469
- import * as path126 from "node:path";
100834
+ import * as path127 from "node:path";
100470
100835
 
100471
100836
  // src/mutation/equivalence.ts
100472
100837
  function isStaticallyEquivalent(originalCode, mutatedCode) {
@@ -100606,7 +100971,7 @@ async function executeMutation(patch, testCommand, _testFiles, workingDir) {
100606
100971
  let patchFile;
100607
100972
  try {
100608
100973
  const safeId2 = patch.id.replace(/[^a-zA-Z0-9_-]/g, "_");
100609
- patchFile = path126.join(workingDir, `.mutation_patch_${safeId2}.diff`);
100974
+ patchFile = path127.join(workingDir, `.mutation_patch_${safeId2}.diff`);
100610
100975
  try {
100611
100976
  writeFileSync24(patchFile, patch.patch);
100612
100977
  } catch (writeErr) {
@@ -101005,7 +101370,7 @@ var mutation_test = createSwarmTool({
101005
101370
  ];
101006
101371
  for (const filePath of uniquePaths) {
101007
101372
  try {
101008
- const resolvedPath = path127.resolve(cwd, filePath);
101373
+ const resolvedPath = path128.resolve(cwd, filePath);
101009
101374
  sourceFiles.set(filePath, fs99.readFileSync(resolvedPath, "utf-8"));
101010
101375
  } catch {}
101011
101376
  }
@@ -101025,7 +101390,7 @@ init_zod();
101025
101390
  init_manager2();
101026
101391
  init_detector();
101027
101392
  import * as fs100 from "node:fs";
101028
- import * as path128 from "node:path";
101393
+ import * as path129 from "node:path";
101029
101394
  init_create_tool();
101030
101395
  var MAX_FILE_SIZE2 = 2 * 1024 * 1024;
101031
101396
  var BINARY_CHECK_BYTES = 8192;
@@ -101091,7 +101456,7 @@ async function syntaxCheck(input, directory, config3) {
101091
101456
  if (languages?.length) {
101092
101457
  const lowerLangs = languages.map((l) => l.toLowerCase());
101093
101458
  filesToCheck = filesToCheck.filter((file3) => {
101094
- const ext = path128.extname(file3.path).toLowerCase();
101459
+ const ext = path129.extname(file3.path).toLowerCase();
101095
101460
  const langDef = getLanguageForExtension(ext);
101096
101461
  const fileProfile = getProfileForFile(file3.path);
101097
101462
  const langId = fileProfile?.id || langDef?.id;
@@ -101104,7 +101469,7 @@ async function syntaxCheck(input, directory, config3) {
101104
101469
  let skippedCount = 0;
101105
101470
  for (const fileInfo of filesToCheck) {
101106
101471
  const { path: filePath } = fileInfo;
101107
- const fullPath = path128.isAbsolute(filePath) ? filePath : path128.join(directory, filePath);
101472
+ const fullPath = path129.isAbsolute(filePath) ? filePath : path129.join(directory, filePath);
101108
101473
  const result = {
101109
101474
  path: filePath,
101110
101475
  language: "",
@@ -101153,7 +101518,7 @@ async function syntaxCheck(input, directory, config3) {
101153
101518
  results.push(result);
101154
101519
  continue;
101155
101520
  }
101156
- const ext = path128.extname(filePath).toLowerCase();
101521
+ const ext = path129.extname(filePath).toLowerCase();
101157
101522
  const langDef = getLanguageForExtension(ext);
101158
101523
  result.language = profile?.id || langDef?.id || "unknown";
101159
101524
  const errors5 = extractSyntaxErrors(parser, content);
@@ -101246,7 +101611,7 @@ init_utils();
101246
101611
  init_create_tool();
101247
101612
  init_path_security();
101248
101613
  import * as fs101 from "node:fs";
101249
- import * as path129 from "node:path";
101614
+ import * as path130 from "node:path";
101250
101615
  var MAX_TEXT_LENGTH = 200;
101251
101616
  var MAX_FILE_SIZE_BYTES11 = 1024 * 1024;
101252
101617
  var SUPPORTED_EXTENSIONS4 = new Set([
@@ -101312,9 +101677,9 @@ function validatePathsInput(paths, cwd) {
101312
101677
  return { error: "paths contains path traversal", resolvedPath: null };
101313
101678
  }
101314
101679
  try {
101315
- const resolvedPath = path129.resolve(paths);
101316
- const normalizedCwd = path129.resolve(cwd);
101317
- const normalizedResolved = path129.resolve(resolvedPath);
101680
+ const resolvedPath = path130.resolve(paths);
101681
+ const normalizedCwd = path130.resolve(cwd);
101682
+ const normalizedResolved = path130.resolve(resolvedPath);
101318
101683
  if (!normalizedResolved.startsWith(normalizedCwd)) {
101319
101684
  return {
101320
101685
  error: "paths must be within the current working directory",
@@ -101330,7 +101695,7 @@ function validatePathsInput(paths, cwd) {
101330
101695
  }
101331
101696
  }
101332
101697
  function isSupportedExtension(filePath) {
101333
- const ext = path129.extname(filePath).toLowerCase();
101698
+ const ext = path130.extname(filePath).toLowerCase();
101334
101699
  return SUPPORTED_EXTENSIONS4.has(ext);
101335
101700
  }
101336
101701
  function findSourceFiles3(dir, files = []) {
@@ -101345,7 +101710,7 @@ function findSourceFiles3(dir, files = []) {
101345
101710
  if (SKIP_DIRECTORIES5.has(entry)) {
101346
101711
  continue;
101347
101712
  }
101348
- const fullPath = path129.join(dir, entry);
101713
+ const fullPath = path130.join(dir, entry);
101349
101714
  let stat8;
101350
101715
  try {
101351
101716
  stat8 = fs101.statSync(fullPath);
@@ -101457,7 +101822,7 @@ var todo_extract = createSwarmTool({
101457
101822
  filesToScan.push(scanPath);
101458
101823
  } else {
101459
101824
  const errorResult = {
101460
- error: `unsupported file extension: ${path129.extname(scanPath)}`,
101825
+ error: `unsupported file extension: ${path130.extname(scanPath)}`,
101461
101826
  total: 0,
101462
101827
  byPriority: { high: 0, medium: 0, low: 0 },
101463
101828
  entries: []
@@ -101506,17 +101871,17 @@ init_schema();
101506
101871
  init_qa_gate_profile();
101507
101872
  init_gate_evidence();
101508
101873
  import * as fs105 from "node:fs";
101509
- import * as path133 from "node:path";
101874
+ import * as path134 from "node:path";
101510
101875
 
101511
101876
  // src/hooks/diff-scope.ts
101512
101877
  init_bun_compat();
101513
101878
  import * as fs103 from "node:fs";
101514
- import * as path131 from "node:path";
101879
+ import * as path132 from "node:path";
101515
101880
 
101516
101881
  // src/utils/gitignore-warning.ts
101517
101882
  init_bun_compat();
101518
101883
  import * as fs102 from "node:fs";
101519
- import * as path130 from "node:path";
101884
+ import * as path131 from "node:path";
101520
101885
  var _internals48 = { bunSpawn };
101521
101886
  var _swarmGitExcludedChecked = false;
101522
101887
  function fileCoversSwarm(content) {
@@ -101590,10 +101955,10 @@ async function ensureSwarmGitExcluded(directory, options = {}) {
101590
101955
  const excludeRelPath = excludePathRaw.trim();
101591
101956
  if (!excludeRelPath)
101592
101957
  return;
101593
- const excludePath = path130.isAbsolute(excludeRelPath) ? excludeRelPath : path130.join(directory, excludeRelPath);
101958
+ const excludePath = path131.isAbsolute(excludeRelPath) ? excludeRelPath : path131.join(directory, excludeRelPath);
101594
101959
  if (checkIgnoreExitCode !== 0) {
101595
101960
  try {
101596
- fs102.mkdirSync(path130.dirname(excludePath), { recursive: true });
101961
+ fs102.mkdirSync(path131.dirname(excludePath), { recursive: true });
101597
101962
  let existing = "";
101598
101963
  try {
101599
101964
  existing = fs102.readFileSync(excludePath, "utf8");
@@ -101637,7 +102002,7 @@ async function ensureSwarmGitExcluded(directory, options = {}) {
101637
102002
  var _internals49 = { bunSpawn };
101638
102003
  function getDeclaredScope(taskId, directory) {
101639
102004
  try {
101640
- const planPath = path131.join(directory, ".swarm", "plan.json");
102005
+ const planPath = path132.join(directory, ".swarm", "plan.json");
101641
102006
  if (!fs103.existsSync(planPath))
101642
102007
  return null;
101643
102008
  const raw = fs103.readFileSync(planPath, "utf-8");
@@ -101743,7 +102108,7 @@ init_telemetry();
101743
102108
  // src/turbo/lean/task-completion.ts
101744
102109
  init_file_locks();
101745
102110
  import * as fs104 from "node:fs";
101746
- import * as path132 from "node:path";
102111
+ import * as path133 from "node:path";
101747
102112
  var _internals50 = {
101748
102113
  listActiveLocks,
101749
102114
  verifyLeanTurboTaskCompletion
@@ -101762,7 +102127,7 @@ var TIER_3_PATTERNS = [
101762
102127
  ];
101763
102128
  function matchesTier3Pattern(files) {
101764
102129
  for (const file3 of files) {
101765
- const fileName = path132.basename(file3);
102130
+ const fileName = path133.basename(file3);
101766
102131
  for (const pattern of TIER_3_PATTERNS) {
101767
102132
  if (pattern.test(fileName)) {
101768
102133
  return true;
@@ -101774,7 +102139,7 @@ function matchesTier3Pattern(files) {
101774
102139
  function verifyLeanTurboTaskCompletion(directory, taskId, sessionID) {
101775
102140
  let persisted = null;
101776
102141
  try {
101777
- const statePath = path132.join(directory, ".swarm", "turbo-state.json");
102142
+ const statePath = path133.join(directory, ".swarm", "turbo-state.json");
101778
102143
  if (!fs104.existsSync(statePath)) {
101779
102144
  return {
101780
102145
  ok: false,
@@ -101858,11 +102223,11 @@ function verifyLeanTurboTaskCompletion(directory, taskId, sessionID) {
101858
102223
  };
101859
102224
  }
101860
102225
  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) {
102226
+ const evidencePath = path133.join(directory, ".swarm", "evidence", String(phase), "lean-turbo", `${lane.laneId}.json`);
102227
+ const expectedDir = path133.join(directory, ".swarm", "evidence", String(phase), "lean-turbo");
102228
+ const resolvedPath = path133.resolve(evidencePath);
102229
+ const resolvedDir = path133.resolve(expectedDir);
102230
+ if (!resolvedPath.startsWith(resolvedDir + path133.sep) && resolvedPath !== resolvedDir) {
101866
102231
  return {
101867
102232
  ok: false,
101868
102233
  reason: `Lane ID causes path traversal: ${lane.laneId}`,
@@ -101902,7 +102267,7 @@ function verifyLeanTurboTaskCompletion(directory, taskId, sessionID) {
101902
102267
  }
101903
102268
  let filesTouched = [];
101904
102269
  try {
101905
- const planPath = path132.join(directory, ".swarm", "plan.json");
102270
+ const planPath = path133.join(directory, ".swarm", "plan.json");
101906
102271
  const planRaw = fs104.readFileSync(planPath, "utf-8");
101907
102272
  const plan = JSON.parse(planRaw);
101908
102273
  for (const planPhase of plan.phases ?? []) {
@@ -101985,7 +102350,7 @@ var TIER_3_PATTERNS2 = [
101985
102350
  ];
101986
102351
  function matchesTier3Pattern2(files) {
101987
102352
  for (const file3 of files) {
101988
- const fileName = path133.basename(file3);
102353
+ const fileName = path134.basename(file3);
101989
102354
  for (const pattern of TIER_3_PATTERNS2) {
101990
102355
  if (pattern.test(fileName)) {
101991
102356
  return true;
@@ -102017,7 +102382,7 @@ function checkReviewerGate(taskId, workingDirectory, stageBParallelEnabled = fal
102017
102382
  if (!skipStandardTurboBypass && hasActiveTurboMode()) {
102018
102383
  const resolvedDir2 = workingDirectory;
102019
102384
  try {
102020
- const planPath = path133.join(resolvedDir2, ".swarm", "plan.json");
102385
+ const planPath = path134.join(resolvedDir2, ".swarm", "plan.json");
102021
102386
  const planRaw = fs105.readFileSync(planPath, "utf-8");
102022
102387
  const plan = JSON.parse(planRaw);
102023
102388
  for (const planPhase of plan.phases ?? []) {
@@ -102084,7 +102449,7 @@ function checkReviewerGate(taskId, workingDirectory, stageBParallelEnabled = fal
102084
102449
  }
102085
102450
  try {
102086
102451
  const resolvedDir2 = workingDirectory;
102087
- const planPath = path133.join(resolvedDir2, ".swarm", "plan.json");
102452
+ const planPath = path134.join(resolvedDir2, ".swarm", "plan.json");
102088
102453
  const planRaw = fs105.readFileSync(planPath, "utf-8");
102089
102454
  const plan = JSON.parse(planRaw);
102090
102455
  for (const planPhase of plan.phases ?? []) {
@@ -102269,8 +102634,8 @@ async function executeUpdateTaskStatus(args2, fallbackDir, ctx) {
102269
102634
  };
102270
102635
  }
102271
102636
  }
102272
- normalizedDir = path133.normalize(args2.working_directory);
102273
- const pathParts = normalizedDir.split(path133.sep);
102637
+ normalizedDir = path134.normalize(args2.working_directory);
102638
+ const pathParts = normalizedDir.split(path134.sep);
102274
102639
  if (pathParts.includes("..")) {
102275
102640
  return {
102276
102641
  success: false,
@@ -102280,10 +102645,10 @@ async function executeUpdateTaskStatus(args2, fallbackDir, ctx) {
102280
102645
  ]
102281
102646
  };
102282
102647
  }
102283
- const resolvedDir = path133.resolve(normalizedDir);
102648
+ const resolvedDir = path134.resolve(normalizedDir);
102284
102649
  try {
102285
102650
  const realPath = fs105.realpathSync(resolvedDir);
102286
- const planPath = path133.join(realPath, ".swarm", "plan.json");
102651
+ const planPath = path134.join(realPath, ".swarm", "plan.json");
102287
102652
  if (!fs105.existsSync(planPath)) {
102288
102653
  return {
102289
102654
  success: false,
@@ -102315,8 +102680,8 @@ async function executeUpdateTaskStatus(args2, fallbackDir, ctx) {
102315
102680
  }
102316
102681
  if (args2.status === "in_progress") {
102317
102682
  try {
102318
- const evidencePath = path133.join(directory, ".swarm", "evidence", `${args2.task_id}.json`);
102319
- fs105.mkdirSync(path133.dirname(evidencePath), { recursive: true });
102683
+ const evidencePath = path134.join(directory, ".swarm", "evidence", `${args2.task_id}.json`);
102684
+ fs105.mkdirSync(path134.dirname(evidencePath), { recursive: true });
102320
102685
  const fd = fs105.openSync(evidencePath, "wx");
102321
102686
  let writeOk = false;
102322
102687
  try {
@@ -102340,7 +102705,7 @@ async function executeUpdateTaskStatus(args2, fallbackDir, ctx) {
102340
102705
  recoverTaskStateFromDelegations(args2.task_id);
102341
102706
  let phaseRequiresReviewer = true;
102342
102707
  try {
102343
- const planPath = path133.join(directory, ".swarm", "plan.json");
102708
+ const planPath = path134.join(directory, ".swarm", "plan.json");
102344
102709
  const planRaw = fs105.readFileSync(planPath, "utf-8");
102345
102710
  const plan = JSON.parse(planRaw);
102346
102711
  const taskPhase = plan.phases.find((p) => p.tasks.some((t) => t.id === args2.task_id));
@@ -102652,7 +103017,7 @@ init_ledger();
102652
103017
  init_manager();
102653
103018
  init_create_tool();
102654
103019
  import fs106 from "node:fs";
102655
- import path134 from "node:path";
103020
+ import path135 from "node:path";
102656
103021
  function normalizeVerdict(verdict) {
102657
103022
  switch (verdict) {
102658
103023
  case "APPROVED":
@@ -102700,7 +103065,7 @@ async function executeWriteDriftEvidence(args2, directory) {
102700
103065
  entries: [evidenceEntry]
102701
103066
  };
102702
103067
  const filename = "drift-verifier.json";
102703
- const relativePath = path134.join("evidence", String(phase), filename);
103068
+ const relativePath = path135.join("evidence", String(phase), filename);
102704
103069
  let validatedPath;
102705
103070
  try {
102706
103071
  validatedPath = validateSwarmPath(directory, relativePath);
@@ -102711,10 +103076,10 @@ async function executeWriteDriftEvidence(args2, directory) {
102711
103076
  message: error93 instanceof Error ? error93.message : "Failed to validate path"
102712
103077
  }, null, 2);
102713
103078
  }
102714
- const evidenceDir = path134.dirname(validatedPath);
103079
+ const evidenceDir = path135.dirname(validatedPath);
102715
103080
  try {
102716
103081
  await fs106.promises.mkdir(evidenceDir, { recursive: true });
102717
- const tempPath = path134.join(evidenceDir, `.${filename}.tmp`);
103082
+ const tempPath = path135.join(evidenceDir, `.${filename}.tmp`);
102718
103083
  await fs106.promises.writeFile(tempPath, JSON.stringify(evidenceContent, null, 2), "utf-8");
102719
103084
  await fs106.promises.rename(tempPath, validatedPath);
102720
103085
  let snapshotInfo;
@@ -102810,7 +103175,7 @@ var write_drift_evidence = createSwarmTool({
102810
103175
  init_zod();
102811
103176
  init_loader();
102812
103177
  import fs107 from "node:fs";
102813
- import path135 from "node:path";
103178
+ import path136 from "node:path";
102814
103179
  init_utils2();
102815
103180
  init_manager();
102816
103181
  init_create_tool();
@@ -102898,7 +103263,7 @@ async function executeWriteFinalCouncilEvidence(args2, directory) {
102898
103263
  timestamp: synthesis.timestamp
102899
103264
  };
102900
103265
  const filename = "final-council.json";
102901
- const relativePath = path135.join("evidence", filename);
103266
+ const relativePath = path136.join("evidence", filename);
102902
103267
  let validatedPath;
102903
103268
  try {
102904
103269
  validatedPath = validateSwarmPath(directory, relativePath);
@@ -102912,10 +103277,10 @@ async function executeWriteFinalCouncilEvidence(args2, directory) {
102912
103277
  const evidenceContent = {
102913
103278
  entries: [evidenceEntry]
102914
103279
  };
102915
- const evidenceDir = path135.dirname(validatedPath);
103280
+ const evidenceDir = path136.dirname(validatedPath);
102916
103281
  try {
102917
103282
  await fs107.promises.mkdir(evidenceDir, { recursive: true });
102918
- const tempPath = path135.join(evidenceDir, `.${filename}.tmp`);
103283
+ const tempPath = path136.join(evidenceDir, `.${filename}.tmp`);
102919
103284
  await fs107.promises.writeFile(tempPath, JSON.stringify(evidenceContent, null, 2), "utf-8");
102920
103285
  await fs107.promises.rename(tempPath, validatedPath);
102921
103286
  return JSON.stringify({
@@ -102974,7 +103339,7 @@ init_zod();
102974
103339
  init_utils2();
102975
103340
  init_create_tool();
102976
103341
  import fs108 from "node:fs";
102977
- import path136 from "node:path";
103342
+ import path137 from "node:path";
102978
103343
  function normalizeVerdict2(verdict) {
102979
103344
  switch (verdict) {
102980
103345
  case "APPROVED":
@@ -103022,7 +103387,7 @@ async function executeWriteHallucinationEvidence(args2, directory) {
103022
103387
  entries: [evidenceEntry]
103023
103388
  };
103024
103389
  const filename = "hallucination-guard.json";
103025
- const relativePath = path136.join("evidence", String(phase), filename);
103390
+ const relativePath = path137.join("evidence", String(phase), filename);
103026
103391
  let validatedPath;
103027
103392
  try {
103028
103393
  validatedPath = validateSwarmPath(directory, relativePath);
@@ -103033,10 +103398,10 @@ async function executeWriteHallucinationEvidence(args2, directory) {
103033
103398
  message: error93 instanceof Error ? error93.message : "Failed to validate path"
103034
103399
  }, null, 2);
103035
103400
  }
103036
- const evidenceDir = path136.dirname(validatedPath);
103401
+ const evidenceDir = path137.dirname(validatedPath);
103037
103402
  try {
103038
103403
  await fs108.promises.mkdir(evidenceDir, { recursive: true });
103039
- const tempPath = path136.join(evidenceDir, `.${filename}.tmp`);
103404
+ const tempPath = path137.join(evidenceDir, `.${filename}.tmp`);
103040
103405
  await fs108.promises.writeFile(tempPath, JSON.stringify(evidenceContent, null, 2), "utf-8");
103041
103406
  await fs108.promises.rename(tempPath, validatedPath);
103042
103407
  return JSON.stringify({
@@ -103085,7 +103450,7 @@ init_zod();
103085
103450
  init_utils2();
103086
103451
  init_create_tool();
103087
103452
  import fs109 from "node:fs";
103088
- import path137 from "node:path";
103453
+ import path138 from "node:path";
103089
103454
  function normalizeVerdict3(verdict) {
103090
103455
  switch (verdict) {
103091
103456
  case "PASS":
@@ -103159,7 +103524,7 @@ async function executeWriteMutationEvidence(args2, directory) {
103159
103524
  entries: [evidenceEntry]
103160
103525
  };
103161
103526
  const filename = "mutation-gate.json";
103162
- const relativePath = path137.join("evidence", String(phase), filename);
103527
+ const relativePath = path138.join("evidence", String(phase), filename);
103163
103528
  let validatedPath;
103164
103529
  try {
103165
103530
  validatedPath = validateSwarmPath(directory, relativePath);
@@ -103170,10 +103535,10 @@ async function executeWriteMutationEvidence(args2, directory) {
103170
103535
  message: error93 instanceof Error ? error93.message : "Failed to validate path"
103171
103536
  }, null, 2);
103172
103537
  }
103173
- const evidenceDir = path137.dirname(validatedPath);
103538
+ const evidenceDir = path138.dirname(validatedPath);
103174
103539
  try {
103175
103540
  await fs109.promises.mkdir(evidenceDir, { recursive: true });
103176
- const tempPath = path137.join(evidenceDir, `.${filename}.tmp`);
103541
+ const tempPath = path138.join(evidenceDir, `.${filename}.tmp`);
103177
103542
  await fs109.promises.writeFile(tempPath, JSON.stringify(evidenceContent, null, 2), "utf-8");
103178
103543
  await fs109.promises.rename(tempPath, validatedPath);
103179
103544
  return JSON.stringify({
@@ -103518,7 +103883,7 @@ async function initializeOpenCodeSwarm(ctx) {
103518
103883
  const { PreflightTriggerManager: PTM } = await Promise.resolve().then(() => (init_trigger(), exports_trigger));
103519
103884
  preflightTriggerManager = new PTM(automationConfig);
103520
103885
  const { AutomationStatusArtifact: ASA } = await Promise.resolve().then(() => (init_status_artifact(), exports_status_artifact));
103521
- const swarmDir = path139.resolve(ctx.directory, ".swarm");
103886
+ const swarmDir = path140.resolve(ctx.directory, ".swarm");
103522
103887
  statusArtifact = new ASA(swarmDir);
103523
103888
  statusArtifact.updateConfig(automationConfig.mode, automationConfig.capabilities);
103524
103889
  if (automationConfig.capabilities?.evidence_auto_summaries === true) {