opencode-swarm 6.29.0 → 6.29.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -14217,7 +14217,7 @@ var init_evidence_schema = __esm(() => {
14217
14217
  });
14218
14218
  RetrospectiveEvidenceSchema = BaseEvidenceSchema.extend({
14219
14219
  type: exports_external.literal("retrospective"),
14220
- phase_number: exports_external.number().int().min(0).max(99),
14220
+ phase_number: exports_external.number().int().min(1).max(99),
14221
14221
  total_tool_calls: exports_external.number().int().min(0).max(9999),
14222
14222
  coder_revisions: exports_external.number().int().min(0).max(999),
14223
14223
  reviewer_rejections: exports_external.number().int().min(0).max(999),
@@ -14882,7 +14882,7 @@ var init_schema = __esm(() => {
14882
14882
  });
14883
14883
  IncrementalVerifyConfigSchema = exports_external.object({
14884
14884
  enabled: exports_external.boolean().default(true),
14885
- command: exports_external.string().nullable().default(null),
14885
+ command: exports_external.union([exports_external.string(), exports_external.array(exports_external.string())]).nullable().default(null),
14886
14886
  timeoutMs: exports_external.number().int().min(1000).max(300000).default(30000),
14887
14887
  triggerAgents: exports_external.array(exports_external.string()).default(["coder"])
14888
14888
  });
@@ -35942,7 +35942,7 @@ __export(exports_gate_evidence, {
35942
35942
  DEFAULT_REQUIRED_GATES: () => DEFAULT_REQUIRED_GATES
35943
35943
  });
35944
35944
  import { mkdirSync as mkdirSync8, readFileSync as readFileSync13, renameSync as renameSync7, unlinkSync as unlinkSync4 } from "fs";
35945
- import * as path28 from "path";
35945
+ import * as path29 from "path";
35946
35946
  function isValidTaskId2(taskId) {
35947
35947
  if (!taskId)
35948
35948
  return false;
@@ -35989,10 +35989,10 @@ function expandRequiredGates(existingGates, newAgentType) {
35989
35989
  return combined.sort();
35990
35990
  }
35991
35991
  function getEvidenceDir(directory) {
35992
- return path28.join(directory, ".swarm", "evidence");
35992
+ return path29.join(directory, ".swarm", "evidence");
35993
35993
  }
35994
35994
  function getEvidencePath(directory, taskId) {
35995
- return path28.join(getEvidenceDir(directory), `${taskId}.json`);
35995
+ return path29.join(getEvidenceDir(directory), `${taskId}.json`);
35996
35996
  }
35997
35997
  function readExisting(evidencePath) {
35998
35998
  try {
@@ -36106,10 +36106,10 @@ function createPreflightIntegration(config3) {
36106
36106
  });
36107
36107
  const report = await runPreflight(directory, request.currentPhase, preflightConfig);
36108
36108
  if (statusArtifact) {
36109
- const state = report.overall === "pass" ? "success" : "failure";
36110
- statusArtifact.recordOutcome(state, request.currentPhase, report.message);
36109
+ const state2 = report.overall === "pass" ? "success" : "failure";
36110
+ statusArtifact.recordOutcome(state2, request.currentPhase, report.message);
36111
36111
  console.log("[PreflightIntegration] Status artifact updated", {
36112
- state,
36112
+ state: state2,
36113
36113
  phase: request.currentPhase,
36114
36114
  message: report.message
36115
36115
  });
@@ -37601,11 +37601,11 @@ ${JSON.stringify(symbolNames, null, 2)}`);
37601
37601
  throw toThrow;
37602
37602
  }, "quit_");
37603
37603
  var scriptDirectory = "";
37604
- function locateFile(path45) {
37604
+ function locateFile(path46) {
37605
37605
  if (Module["locateFile"]) {
37606
- return Module["locateFile"](path45, scriptDirectory);
37606
+ return Module["locateFile"](path46, scriptDirectory);
37607
37607
  }
37608
- return scriptDirectory + path45;
37608
+ return scriptDirectory + path46;
37609
37609
  }
37610
37610
  __name(locateFile, "locateFile");
37611
37611
  var readAsync, readBinary;
@@ -39353,7 +39353,7 @@ var init_runtime = __esm(() => {
39353
39353
  });
39354
39354
 
39355
39355
  // src/index.ts
39356
- import * as path55 from "path";
39356
+ import * as path56 from "path";
39357
39357
 
39358
39358
  // src/agents/index.ts
39359
39359
  init_config();
@@ -39418,7 +39418,8 @@ function startAgentSession(sessionId, agentName, staleDurationMs = 7200000, dire
39418
39418
  scopeViolationDetected: false,
39419
39419
  modifiedFilesThisCoderTask: [],
39420
39420
  turboMode: false,
39421
- loopDetectionWindow: []
39421
+ loopDetectionWindow: [],
39422
+ pendingAdvisoryMessages: []
39422
39423
  };
39423
39424
  swarmState.agentSessions.set(sessionId, sessionState);
39424
39425
  swarmState.activeAgent.set(sessionId, agentName);
@@ -39523,6 +39524,9 @@ function ensureAgentSession(sessionId, agentName, directory) {
39523
39524
  if (session.loopDetectionWindow === undefined) {
39524
39525
  session.loopDetectionWindow = [];
39525
39526
  }
39527
+ if (session.pendingAdvisoryMessages === undefined) {
39528
+ session.pendingAdvisoryMessages = [];
39529
+ }
39526
39530
  session.lastToolCallTime = now;
39527
39531
  return session;
39528
39532
  }
@@ -40179,6 +40183,7 @@ Activates when: user asks to "specify", "define requirements", "write a spec", o
40179
40183
  - Refine \u2192 delegate to MODE: CLARIFY-SPEC
40180
40184
  - If NO: proceed to generation (step 2)
40181
40185
  - If this is called from the stale spec archival path (MODE: PLAN option 1) \u2014 archival was already completed; skip this check and proceed directly to generation (step 2)
40186
+ 1b. Run CODEBASE REALITY CHECK for any codebase references mentioned by the user or implied by the feature. Skip if work is purely greenfield (no existing codebase to check). Report discrepancies before proceeding to explorer.
40182
40187
  2. Delegate to \`{{AGENT_PREFIX}}explorer\` to scan the codebase for relevant context (existing patterns, related code, affected areas).
40183
40188
  3. Delegate to \`{{AGENT_PREFIX}}sme\` for domain research on the feature area to surface known constraints, best practices, and integration concerns.
40184
40189
  4. Generate \`.swarm/spec.md\` capturing:
@@ -40205,22 +40210,23 @@ Each requirement must be independently testable.
40205
40210
  Prefer informed defaults over asking the user \u2014 use \`[NEEDS CLARIFICATION]\` only when uncertainty could change scope, security, or core behavior.
40206
40211
 
40207
40212
  EXTERNAL PLAN IMPORT PATH \u2014 when the user provides an existing implementation plan (markdown content, pasted text, or a reference to a file):
40208
- 1. Read and parse the provided plan content.
40209
- 2. Reverse-engineer \`.swarm/spec.md\` from the plan:
40213
+ 1. Run CODEBASE REALITY CHECK scoped to every file, function, API, and behavioral assumption in the provided plan. Report discrepancies to user before proceeding.
40214
+ 2. Read and parse the provided plan content.
40215
+ 3. Reverse-engineer \`.swarm/spec.md\` from the plan:
40210
40216
  - Derive FR-### functional requirements from task descriptions
40211
40217
  - Derive SC-### success criteria from acceptance criteria in tasks
40212
40218
  - Identify user scenarios from the plan's phase/feature groupings
40213
40219
  - Surface implicit assumptions as \`[NEEDS CLARIFICATION]\` markers
40214
- 3. Validate the provided plan against swarm task format requirements:
40220
+ 4. Validate the provided plan against swarm task format requirements:
40215
40221
  - Every task should have FILE, TASK, CONSTRAINT, and ACCEPTANCE fields
40216
40222
  - No task should touch more than 2 files
40217
40223
  - No compound verbs in TASK lines ("implement X and add Y" = 2 tasks)
40218
40224
  - Dependencies should be declared explicitly
40219
40225
  - Phase structure should match \`.swarm/plan.md\` format
40220
- 4. Report gaps, format issues, and improvement suggestions to the user.
40221
- 5. Ask: "Should I also flesh out any areas that seem underspecified?"
40226
+ 5. Report gaps, format issues, and improvement suggestions to the user.
40227
+ 6. Ask: "Should I also flesh out any areas that seem underspecified?"
40222
40228
  - If yes: delegate to \`{{AGENT_PREFIX}}sme\` for targeted research on weak areas, then propose specific improvements.
40223
- 6. Output: both a \`.swarm/spec.md\` (extracted from the plan) and a validated version of the user's plan.
40229
+ 7. Output: both a \`.swarm/spec.md\` (extracted from the plan) and a validated version of the user's plan.
40224
40230
 
40225
40231
  EXTERNAL PLAN RULES:
40226
40232
  - Surface ALL changes as suggestions \u2014 do not silently rewrite the user's plan.
@@ -40323,6 +40329,34 @@ User directives carried forward: {list any persistent directives}
40323
40329
 
40324
40330
  This briefing is a HARD REQUIREMENT for ALL phases. Skipping it is a process violation.
40325
40331
 
40332
+ ### CODEBASE REALITY CHECK (Required Before Speccing or Planning)
40333
+
40334
+ Before any spec generation, plan creation, or plan ingestion begins, the Architect must dispatch the Explorer agent in targeted, scoped chunks \u2014 one per logical area of the codebase referenced by the work (e.g., per module, per hook, per config surface). Each chunk must be explored with full depth rather than a broad surface pass.
40335
+
40336
+ For each scoped chunk, Explorer must determine:
40337
+ - Does this file/module/function already exist?
40338
+ - If it exists, what is its current state? Does it already implement any part of what the plan or spec describes?
40339
+ - Is the plan's or user's assumption about the current state accurate? Flag any discrepancy between what is expected and what actually exists.
40340
+ - Has any portion of this work already been applied (partially or fully) in a prior session or commit?
40341
+
40342
+ Explorer outputs a CODEBASE REALITY REPORT before any other agent proceeds. The report must list every referenced item with one of:
40343
+ NOT STARTED | PARTIALLY DONE | ALREADY COMPLETE | ASSUMPTION INCORRECT
40344
+
40345
+ Format:
40346
+ REALITY CHECK: [N] references verified, [M] discrepancies found.
40347
+ \u2713 src/hooks/incremental-verify.ts \u2014 exists, line 69 confirmed Bun.spawn
40348
+ \u2717 src/services/status-service.ts \u2014 ASSUMPTION INCORRECT: compactionCount is no longer hardcoded (fixed in v6.29.1)
40349
+ \u2713 src/config/evidence-schema.ts:107 \u2014 confirmed phase_number min(0)
40350
+
40351
+ No implementation agent (coder, reviewer, test-engineer) may begin until this report is finalized.
40352
+
40353
+ This check fires automatically in:
40354
+ - MODE: SPECIFY \u2014 before explorer dispatch for context (step 2)
40355
+ - MODE: PLAN \u2014 before plan generation or validation
40356
+ - EXTERNAL PLAN IMPORT PATH \u2014 before parsing the provided plan
40357
+
40358
+ GREENFIELD EXEMPTION: If the work is purely greenfield (new project, no existing codebase references), skip this check.
40359
+
40326
40360
  ### MODE: PLAN
40327
40361
 
40328
40362
  SPEC GATE (soft \u2014 check before planning):
@@ -40352,6 +40386,8 @@ SPEC GATE (soft \u2014 check before planning):
40352
40386
 
40353
40387
  This is a SOFT gate. When the user chooses "Skip and plan directly", proceed to the steps below exactly as before \u2014 do NOT modify any planning behavior.
40354
40388
 
40389
+ Run CODEBASE REALITY CHECK scoped to codebase elements referenced in spec.md or user constraints. Discrepancies must be reflected in the generated plan.
40390
+
40355
40391
  Use the \`save_plan\` tool to create the implementation plan. Required parameters:
40356
40392
  - \`title\`: The real project name from the spec (NOT a placeholder like [Project])
40357
40393
  - \`swarm_id\`: The swarm identifier (e.g. "mega", "local", "paid")
@@ -47608,6 +47644,97 @@ No plan content available. Start by creating a .swarm/plan.md file.
47608
47644
  init_utils2();
47609
47645
  init_manager2();
47610
47646
 
47647
+ // src/services/compaction-service.ts
47648
+ import * as fs15 from "fs";
47649
+ import * as path27 from "path";
47650
+ function makeInitialState() {
47651
+ return {
47652
+ lastObservationAt: 0,
47653
+ lastReflectionAt: 0,
47654
+ lastEmergencyAt: 0,
47655
+ observationCount: 0,
47656
+ reflectionCount: 0,
47657
+ emergencyCount: 0,
47658
+ lastSnapshotAt: null
47659
+ };
47660
+ }
47661
+ var state = makeInitialState();
47662
+ function appendSnapshot(directory, tier, budgetPct, message) {
47663
+ try {
47664
+ const snapshotPath = path27.join(directory, ".swarm", "context-snapshot.md");
47665
+ const timestamp = new Date().toISOString();
47666
+ const entry = `
47667
+ ## [${tier.toUpperCase()}] ${timestamp} \u2014 ${budgetPct.toFixed(1)}% used
47668
+ ${message}
47669
+ `;
47670
+ fs15.appendFileSync(snapshotPath, entry, "utf-8");
47671
+ } catch {}
47672
+ }
47673
+ function buildObservationMessage(budgetPct) {
47674
+ return `[CONTEXT COMPACTION \u2014 OBSERVATION TIER]
47675
+ ` + `Context window is ${budgetPct.toFixed(1)}% used. Initiating observation compaction.
47676
+ ` + `INSTRUCTIONS: Summarise the key decisions made so far, files changed, errors resolved, ` + `and the current task state. Discard verbose tool outputs and raw file reads. ` + `Preserve: plan task ID, agent verdicts, file paths touched, unresolved blockers.
47677
+ ` + `[/CONTEXT COMPACTION]`;
47678
+ }
47679
+ function buildReflectionMessage(budgetPct) {
47680
+ return `[CONTEXT COMPACTION \u2014 REFLECTION TIER]
47681
+ ` + `Context window is ${budgetPct.toFixed(1)}% used. Initiating reflection compaction.
47682
+ ` + `INSTRUCTIONS: Re-summarise into a tighter format. Discard completed task details ` + `and resolved errors. Retain ONLY: current phase tasks remaining, open blockers, ` + `last 3 reviewer/test verdicts, and active file scope.
47683
+ ` + `[/CONTEXT COMPACTION]`;
47684
+ }
47685
+ function buildEmergencyMessage(budgetPct, preserveLastN) {
47686
+ return `[CONTEXT COMPACTION \u2014 EMERGENCY TIER]
47687
+ ` + `Context window is ${budgetPct.toFixed(1)}% used. EMERGENCY compaction required.
47688
+ ` + `INSTRUCTIONS: Retain ONLY the system prompt, the current task context, and the ` + `last ${preserveLastN} conversation turns. Discard everything else. ` + `If you cannot complete the current task in the remaining context, escalate to the user.
47689
+ ` + `[/CONTEXT COMPACTION]`;
47690
+ }
47691
+ function createCompactionService(config3, directory, injectMessage) {
47692
+ return {
47693
+ toolAfter: async (_input, _output) => {
47694
+ if (!config3.enabled)
47695
+ return;
47696
+ const budgetPct = swarmState.lastBudgetPct ?? 0;
47697
+ if (budgetPct <= 0)
47698
+ return;
47699
+ const sessionId = _input.sessionID;
47700
+ try {
47701
+ if (budgetPct >= config3.emergencyThreshold && budgetPct > state.lastEmergencyAt + 5) {
47702
+ state.lastEmergencyAt = budgetPct;
47703
+ state.emergencyCount++;
47704
+ const msg = buildEmergencyMessage(budgetPct, config3.preserveLastNTurns);
47705
+ appendSnapshot(directory, "emergency", budgetPct, msg);
47706
+ state.lastSnapshotAt = new Date().toISOString();
47707
+ injectMessage(sessionId, msg);
47708
+ return;
47709
+ }
47710
+ if (budgetPct >= config3.reflectionThreshold && budgetPct > state.lastReflectionAt + 5) {
47711
+ state.lastReflectionAt = budgetPct;
47712
+ state.reflectionCount++;
47713
+ const msg = buildReflectionMessage(budgetPct);
47714
+ appendSnapshot(directory, "reflection", budgetPct, msg);
47715
+ state.lastSnapshotAt = new Date().toISOString();
47716
+ injectMessage(sessionId, msg);
47717
+ return;
47718
+ }
47719
+ if (budgetPct >= config3.observationThreshold && budgetPct > state.lastObservationAt + 5) {
47720
+ state.lastObservationAt = budgetPct;
47721
+ state.observationCount++;
47722
+ const msg = buildObservationMessage(budgetPct);
47723
+ appendSnapshot(directory, "observation", budgetPct, msg);
47724
+ state.lastSnapshotAt = new Date().toISOString();
47725
+ injectMessage(sessionId, msg);
47726
+ }
47727
+ } catch {}
47728
+ }
47729
+ };
47730
+ }
47731
+ function getCompactionMetrics() {
47732
+ return {
47733
+ compactionCount: state.observationCount + state.reflectionCount + state.emergencyCount,
47734
+ lastSnapshotAt: state.lastSnapshotAt
47735
+ };
47736
+ }
47737
+
47611
47738
  // src/services/context-budget-service.ts
47612
47739
  init_utils2();
47613
47740
  function validateDirectory(directory) {
@@ -47650,9 +47777,9 @@ async function readBudgetState(directory) {
47650
47777
  return null;
47651
47778
  }
47652
47779
  }
47653
- async function writeBudgetState(directory, state) {
47780
+ async function writeBudgetState(directory, state2) {
47654
47781
  const resolvedPath = validateSwarmPath(directory, "session/budget-state.json");
47655
- const content = JSON.stringify(state, null, 2);
47782
+ const content = JSON.stringify(state2, null, 2);
47656
47783
  await Bun.write(resolvedPath, content);
47657
47784
  }
47658
47785
  async function countEvents(directory) {
@@ -47741,25 +47868,25 @@ async function formatBudgetWarning(report, directory, config3) {
47741
47868
  return formatWarningMessage(report);
47742
47869
  }
47743
47870
  const budgetState = await readBudgetState(directory);
47744
- const state = budgetState || {
47871
+ const state2 = budgetState || {
47745
47872
  warningFiredAtTurn: null,
47746
47873
  criticalFiredAtTurn: null,
47747
47874
  lastInjectedAtTurn: null
47748
47875
  };
47749
47876
  const currentTurn = report.estimatedTurnCount;
47750
47877
  if (report.status === "warning") {
47751
- if (config3.warningMode === "once" && state.warningFiredAtTurn !== null) {
47878
+ if (config3.warningMode === "once" && state2.warningFiredAtTurn !== null) {
47752
47879
  return null;
47753
47880
  }
47754
- if (config3.warningMode === "interval" && state.warningFiredAtTurn !== null && currentTurn - state.warningFiredAtTurn < config3.warningIntervalTurns) {
47881
+ if (config3.warningMode === "interval" && state2.warningFiredAtTurn !== null && currentTurn - state2.warningFiredAtTurn < config3.warningIntervalTurns) {
47755
47882
  return null;
47756
47883
  }
47757
- state.warningFiredAtTurn = currentTurn;
47758
- state.lastInjectedAtTurn = currentTurn;
47759
- await writeBudgetState(directory, state);
47884
+ state2.warningFiredAtTurn = currentTurn;
47885
+ state2.lastInjectedAtTurn = currentTurn;
47886
+ await writeBudgetState(directory, state2);
47760
47887
  } else if (report.status === "critical") {
47761
- state.criticalFiredAtTurn = currentTurn;
47762
- state.lastInjectedAtTurn = currentTurn;
47888
+ state2.criticalFiredAtTurn = currentTurn;
47889
+ state2.lastInjectedAtTurn = currentTurn;
47763
47890
  }
47764
47891
  return formatWarningMessage(report);
47765
47892
  }
@@ -47788,6 +47915,7 @@ async function getStatusData(directory, agents) {
47788
47915
  }
47789
47916
  }
47790
47917
  const agentCount2 = Object.keys(agents).length;
47918
+ const metrics2 = getCompactionMetrics();
47791
47919
  return {
47792
47920
  hasPlan: true,
47793
47921
  currentPhase: currentPhase2,
@@ -47797,12 +47925,13 @@ async function getStatusData(directory, agents) {
47797
47925
  isLegacy: false,
47798
47926
  turboMode: hasActiveTurboMode(),
47799
47927
  contextBudgetPct: swarmState.lastBudgetPct > 0 ? swarmState.lastBudgetPct : null,
47800
- compactionCount: 0,
47801
- lastSnapshotAt: null
47928
+ compactionCount: metrics2.compactionCount,
47929
+ lastSnapshotAt: metrics2.lastSnapshotAt
47802
47930
  };
47803
47931
  }
47804
47932
  const planContent = await readSwarmFileAsync(directory, "plan.md");
47805
47933
  if (!planContent) {
47934
+ const metrics2 = getCompactionMetrics();
47806
47935
  return {
47807
47936
  hasPlan: false,
47808
47937
  currentPhase: "Unknown",
@@ -47812,8 +47941,8 @@ async function getStatusData(directory, agents) {
47812
47941
  isLegacy: true,
47813
47942
  turboMode: hasActiveTurboMode(),
47814
47943
  contextBudgetPct: swarmState.lastBudgetPct > 0 ? swarmState.lastBudgetPct : null,
47815
- compactionCount: 0,
47816
- lastSnapshotAt: null
47944
+ compactionCount: metrics2.compactionCount,
47945
+ lastSnapshotAt: metrics2.lastSnapshotAt
47817
47946
  };
47818
47947
  }
47819
47948
  const currentPhase = extractCurrentPhase(planContent) || "Unknown";
@@ -47821,6 +47950,7 @@ async function getStatusData(directory, agents) {
47821
47950
  const incompleteTasks = (planContent.match(/^- \[ \]/gm) || []).length;
47822
47951
  const totalTasks = completedTasks + incompleteTasks;
47823
47952
  const agentCount = Object.keys(agents).length;
47953
+ const metrics = getCompactionMetrics();
47824
47954
  return {
47825
47955
  hasPlan: true,
47826
47956
  currentPhase,
@@ -47830,8 +47960,8 @@ async function getStatusData(directory, agents) {
47830
47960
  isLegacy: true,
47831
47961
  turboMode: hasActiveTurboMode(),
47832
47962
  contextBudgetPct: swarmState.lastBudgetPct > 0 ? swarmState.lastBudgetPct : null,
47833
- compactionCount: 0,
47834
- lastSnapshotAt: null
47963
+ compactionCount: metrics.compactionCount,
47964
+ lastSnapshotAt: metrics.lastSnapshotAt
47835
47965
  };
47836
47966
  }
47837
47967
  function formatStatusMarkdown(status) {
@@ -48461,11 +48591,11 @@ async function doFlush(directory) {
48461
48591
  const activitySection = renderActivitySection();
48462
48592
  const updated = replaceOrAppendSection(existing, "## Agent Activity", activitySection);
48463
48593
  const flushedCount = swarmState.pendingEvents;
48464
- const path27 = `${directory}/.swarm/context.md`;
48465
- const tempPath = `${path27}.tmp`;
48594
+ const path28 = `${directory}/.swarm/context.md`;
48595
+ const tempPath = `${path28}.tmp`;
48466
48596
  try {
48467
48597
  await Bun.write(tempPath, updated);
48468
- renameSync6(tempPath, path27);
48598
+ renameSync6(tempPath, path28);
48469
48599
  } catch (writeError) {
48470
48600
  try {
48471
48601
  unlinkSync3(tempPath);
@@ -49035,14 +49165,14 @@ function maskToolOutput(msg, _threshold) {
49035
49165
  }
49036
49166
  // src/hooks/delegation-gate.ts
49037
49167
  init_schema();
49038
- import * as fs15 from "fs";
49039
- import * as path29 from "path";
49168
+ import * as fs16 from "fs";
49169
+ import * as path30 from "path";
49040
49170
 
49041
49171
  // src/hooks/guardrails.ts
49042
49172
  init_constants();
49043
49173
  init_schema();
49044
49174
  init_manager2();
49045
- import * as path27 from "path";
49175
+ import * as path28 from "path";
49046
49176
  init_utils();
49047
49177
 
49048
49178
  // src/hooks/loop-detector.ts
@@ -49135,10 +49265,10 @@ function isArchitect(sessionId) {
49135
49265
  function isOutsideSwarmDir(filePath, directory) {
49136
49266
  if (!filePath)
49137
49267
  return false;
49138
- const swarmDir = path27.resolve(directory, ".swarm");
49139
- const resolved = path27.resolve(directory, filePath);
49140
- const relative4 = path27.relative(swarmDir, resolved);
49141
- return relative4.startsWith("..") || path27.isAbsolute(relative4);
49268
+ const swarmDir = path28.resolve(directory, ".swarm");
49269
+ const resolved = path28.resolve(directory, filePath);
49270
+ const relative4 = path28.relative(swarmDir, resolved);
49271
+ return relative4.startsWith("..") || path28.isAbsolute(relative4);
49142
49272
  }
49143
49273
  function isSourceCodePath(filePath) {
49144
49274
  if (!filePath)
@@ -49205,13 +49335,13 @@ function getCurrentTaskId(sessionId) {
49205
49335
  return session?.currentTaskId ?? `${sessionId}:unknown`;
49206
49336
  }
49207
49337
  function isInDeclaredScope(filePath, scopeEntries) {
49208
- const resolvedFile = path27.resolve(filePath);
49338
+ const resolvedFile = path28.resolve(filePath);
49209
49339
  return scopeEntries.some((scope) => {
49210
- const resolvedScope = path27.resolve(scope);
49340
+ const resolvedScope = path28.resolve(scope);
49211
49341
  if (resolvedFile === resolvedScope)
49212
49342
  return true;
49213
- const rel = path27.relative(resolvedScope, resolvedFile);
49214
- return rel.length > 0 && !rel.startsWith("..") && !path27.isAbsolute(rel);
49343
+ const rel = path28.relative(resolvedScope, resolvedFile);
49344
+ return rel.length > 0 && !rel.startsWith("..") && !path28.isAbsolute(rel);
49215
49345
  });
49216
49346
  }
49217
49347
  function createGuardrailsHooks(directoryOrConfig, config3) {
@@ -49298,9 +49428,9 @@ function createGuardrailsHooks(directoryOrConfig, config3) {
49298
49428
  const args2 = output.args;
49299
49429
  const targetPath = args2?.filePath ?? args2?.path ?? args2?.file ?? args2?.target;
49300
49430
  if (typeof targetPath === "string" && targetPath.length > 0) {
49301
- const resolvedTarget = path27.resolve(directory, targetPath).toLowerCase();
49302
- const planMdPath = path27.resolve(directory, ".swarm", "plan.md").toLowerCase();
49303
- const planJsonPath = path27.resolve(directory, ".swarm", "plan.json").toLowerCase();
49431
+ const resolvedTarget = path28.resolve(directory, targetPath).toLowerCase();
49432
+ const planMdPath = path28.resolve(directory, ".swarm", "plan.md").toLowerCase();
49433
+ const planJsonPath = path28.resolve(directory, ".swarm", "plan.json").toLowerCase();
49304
49434
  if (resolvedTarget === planMdPath || resolvedTarget === planJsonPath) {
49305
49435
  throw new Error("PLAN STATE VIOLATION: Direct writes to .swarm/plan.md and .swarm/plan.json are blocked. " + "plan.md is auto-regenerated from plan.json by PlanSyncWorker. " + "Use update_task_status() to mark tasks complete, " + "phase_complete() for phase transitions, or " + "save_plan to create/restructure plans.");
49306
49436
  }
@@ -49349,9 +49479,9 @@ function createGuardrailsHooks(directoryOrConfig, config3) {
49349
49479
  }
49350
49480
  }
49351
49481
  for (const p of paths) {
49352
- const resolvedP = path27.resolve(directory, p);
49353
- const planMdPath = path27.resolve(directory, ".swarm", "plan.md").toLowerCase();
49354
- const planJsonPath = path27.resolve(directory, ".swarm", "plan.json").toLowerCase();
49482
+ const resolvedP = path28.resolve(directory, p);
49483
+ const planMdPath = path28.resolve(directory, ".swarm", "plan.md").toLowerCase();
49484
+ const planJsonPath = path28.resolve(directory, ".swarm", "plan.json").toLowerCase();
49355
49485
  if (resolvedP.toLowerCase() === planMdPath || resolvedP.toLowerCase() === planJsonPath) {
49356
49486
  throw new Error("PLAN STATE VIOLATION: Direct writes to .swarm/plan.md and .swarm/plan.json are blocked. " + "plan.md is auto-regenerated from plan.json by PlanSyncWorker. " + "Use update_task_status() to mark tasks complete, " + "phase_complete() for phase transitions, or " + "save_plan to create/restructure plans.");
49357
49487
  }
@@ -49371,7 +49501,7 @@ function createGuardrailsHooks(directoryOrConfig, config3) {
49371
49501
  }
49372
49502
  }
49373
49503
  }
49374
- if (typeof targetPath === "string" && targetPath.length > 0 && isOutsideSwarmDir(targetPath, directory) && isSourceCodePath(path27.relative(directory, path27.resolve(directory, targetPath)))) {
49504
+ if (typeof targetPath === "string" && targetPath.length > 0 && isOutsideSwarmDir(targetPath, directory) && isSourceCodePath(path28.relative(directory, path28.resolve(directory, targetPath)))) {
49375
49505
  const session2 = swarmState.agentSessions.get(input.sessionID);
49376
49506
  if (session2) {
49377
49507
  session2.architectWriteCount++;
@@ -49653,6 +49783,30 @@ ${pending.message}
49653
49783
  }
49654
49784
  }
49655
49785
  }
49786
+ if (isArchitectSession && (session?.pendingAdvisoryMessages?.length ?? 0) > 0) {
49787
+ const advisories = session.pendingAdvisoryMessages;
49788
+ let targetMsg = systemMessages[0];
49789
+ if (!targetMsg) {
49790
+ const newMsg = {
49791
+ info: { role: "system" },
49792
+ parts: [{ type: "text", text: "" }]
49793
+ };
49794
+ messages.unshift(newMsg);
49795
+ targetMsg = newMsg;
49796
+ }
49797
+ const textPart2 = (targetMsg.parts ?? []).find((part) => part.type === "text" && typeof part.text === "string");
49798
+ if (textPart2) {
49799
+ const joined = advisories.join(`
49800
+ ---
49801
+ `);
49802
+ textPart2.text = `[ADVISORIES]
49803
+ ${joined}
49804
+ [/ADVISORIES]
49805
+
49806
+ ` + textPart2.text;
49807
+ }
49808
+ session.pendingAdvisoryMessages = [];
49809
+ }
49656
49810
  if (isArchitectSession && session && session.architectWriteCount > session.selfCodingWarnedAtCount) {
49657
49811
  let targetSystemMessage = systemMessages[0];
49658
49812
  if (!targetSystemMessage) {
@@ -49880,13 +50034,13 @@ function getEvidenceTaskId(session, directory) {
49880
50034
  if (typeof directory !== "string" || directory.length === 0) {
49881
50035
  return null;
49882
50036
  }
49883
- const resolvedDirectory = path29.resolve(directory);
49884
- const planPath = path29.join(resolvedDirectory, ".swarm", "plan.json");
49885
- const resolvedPlanPath = path29.resolve(planPath);
49886
- if (!resolvedPlanPath.startsWith(resolvedDirectory + path29.sep) && resolvedPlanPath !== resolvedDirectory) {
50037
+ const resolvedDirectory = path30.resolve(directory);
50038
+ const planPath = path30.join(resolvedDirectory, ".swarm", "plan.json");
50039
+ const resolvedPlanPath = path30.resolve(planPath);
50040
+ if (!resolvedPlanPath.startsWith(resolvedDirectory + path30.sep) && resolvedPlanPath !== resolvedDirectory) {
49887
50041
  return null;
49888
50042
  }
49889
- const planContent = fs15.readFileSync(resolvedPlanPath, "utf-8");
50043
+ const planContent = fs16.readFileSync(resolvedPlanPath, "utf-8");
49890
50044
  const plan = JSON.parse(planContent);
49891
50045
  if (!plan || !Array.isArray(plan.phases)) {
49892
50046
  return null;
@@ -49944,23 +50098,23 @@ function createDelegationGateHook(config3, directory) {
49944
50098
  if (targetAgent === "test_engineer")
49945
50099
  hasTestEngineer = true;
49946
50100
  if (targetAgent === "reviewer" && session.taskWorkflowStates) {
49947
- for (const [taskId, state] of session.taskWorkflowStates) {
49948
- if (state === "coder_delegated" || state === "pre_check_passed") {
50101
+ for (const [taskId, state2] of session.taskWorkflowStates) {
50102
+ if (state2 === "coder_delegated" || state2 === "pre_check_passed") {
49949
50103
  try {
49950
50104
  advanceTaskState(session, taskId, "reviewer_run");
49951
50105
  } catch (err2) {
49952
- console.warn(`[delegation-gate] toolAfter: could not advance ${taskId} (${state}) \u2192 reviewer_run: ${err2 instanceof Error ? err2.message : String(err2)}`);
50106
+ console.warn(`[delegation-gate] toolAfter: could not advance ${taskId} (${state2}) \u2192 reviewer_run: ${err2 instanceof Error ? err2.message : String(err2)}`);
49953
50107
  }
49954
50108
  }
49955
50109
  }
49956
50110
  }
49957
50111
  if (targetAgent === "test_engineer" && session.taskWorkflowStates) {
49958
- for (const [taskId, state] of session.taskWorkflowStates) {
49959
- if (state === "reviewer_run") {
50112
+ for (const [taskId, state2] of session.taskWorkflowStates) {
50113
+ if (state2 === "reviewer_run") {
49960
50114
  try {
49961
50115
  advanceTaskState(session, taskId, "tests_run");
49962
50116
  } catch (err2) {
49963
- console.warn(`[delegation-gate] toolAfter: could not advance ${taskId} (${state}) \u2192 tests_run: ${err2 instanceof Error ? err2.message : String(err2)}`);
50117
+ console.warn(`[delegation-gate] toolAfter: could not advance ${taskId} (${state2}) \u2192 tests_run: ${err2 instanceof Error ? err2.message : String(err2)}`);
49964
50118
  }
49965
50119
  }
49966
50120
  }
@@ -49976,12 +50130,12 @@ function createDelegationGateHook(config3, directory) {
49976
50130
  if (seedTaskId && !otherSession.taskWorkflowStates.has(seedTaskId)) {
49977
50131
  otherSession.taskWorkflowStates.set(seedTaskId, "coder_delegated");
49978
50132
  }
49979
- for (const [taskId, state] of otherSession.taskWorkflowStates) {
49980
- if (state === "coder_delegated" || state === "pre_check_passed") {
50133
+ for (const [taskId, state2] of otherSession.taskWorkflowStates) {
50134
+ if (state2 === "coder_delegated" || state2 === "pre_check_passed") {
49981
50135
  try {
49982
50136
  advanceTaskState(otherSession, taskId, "reviewer_run");
49983
50137
  } catch (err2) {
49984
- console.warn(`[delegation-gate] toolAfter cross-session: could not advance ${taskId} (${state}) \u2192 reviewer_run: ${err2 instanceof Error ? err2.message : String(err2)}`);
50138
+ console.warn(`[delegation-gate] toolAfter cross-session: could not advance ${taskId} (${state2}) \u2192 reviewer_run: ${err2 instanceof Error ? err2.message : String(err2)}`);
49985
50139
  }
49986
50140
  }
49987
50141
  }
@@ -49991,12 +50145,12 @@ function createDelegationGateHook(config3, directory) {
49991
50145
  if (seedTaskId && !otherSession.taskWorkflowStates.has(seedTaskId)) {
49992
50146
  otherSession.taskWorkflowStates.set(seedTaskId, "reviewer_run");
49993
50147
  }
49994
- for (const [taskId, state] of otherSession.taskWorkflowStates) {
49995
- if (state === "reviewer_run") {
50148
+ for (const [taskId, state2] of otherSession.taskWorkflowStates) {
50149
+ if (state2 === "reviewer_run") {
49996
50150
  try {
49997
50151
  advanceTaskState(otherSession, taskId, "tests_run");
49998
50152
  } catch (err2) {
49999
- console.warn(`[delegation-gate] toolAfter cross-session: could not advance ${taskId} (${state}) \u2192 tests_run: ${err2 instanceof Error ? err2.message : String(err2)}`);
50153
+ console.warn(`[delegation-gate] toolAfter cross-session: could not advance ${taskId} (${state2}) \u2192 tests_run: ${err2 instanceof Error ? err2.message : String(err2)}`);
50000
50154
  }
50001
50155
  }
50002
50156
  }
@@ -50060,23 +50214,23 @@ function createDelegationGateHook(config3, directory) {
50060
50214
  session.qaSkipTaskIds = [];
50061
50215
  }
50062
50216
  if (hasReviewer && session.taskWorkflowStates) {
50063
- for (const [taskId, state] of session.taskWorkflowStates) {
50064
- if (state === "coder_delegated" || state === "pre_check_passed") {
50217
+ for (const [taskId, state2] of session.taskWorkflowStates) {
50218
+ if (state2 === "coder_delegated" || state2 === "pre_check_passed") {
50065
50219
  try {
50066
50220
  advanceTaskState(session, taskId, "reviewer_run");
50067
50221
  } catch (err2) {
50068
- console.warn(`[delegation-gate] fallback: could not advance ${taskId} (${state}) \u2192 reviewer_run: ${err2 instanceof Error ? err2.message : String(err2)}`);
50222
+ console.warn(`[delegation-gate] fallback: could not advance ${taskId} (${state2}) \u2192 reviewer_run: ${err2 instanceof Error ? err2.message : String(err2)}`);
50069
50223
  }
50070
50224
  }
50071
50225
  }
50072
50226
  }
50073
50227
  if (hasReviewer && hasTestEngineer && session.taskWorkflowStates) {
50074
- for (const [taskId, state] of session.taskWorkflowStates) {
50075
- if (state === "reviewer_run") {
50228
+ for (const [taskId, state2] of session.taskWorkflowStates) {
50229
+ if (state2 === "reviewer_run") {
50076
50230
  try {
50077
50231
  advanceTaskState(session, taskId, "tests_run");
50078
50232
  } catch (err2) {
50079
- console.warn(`[delegation-gate] fallback: could not advance ${taskId} (${state}) \u2192 tests_run: ${err2 instanceof Error ? err2.message : String(err2)}`);
50233
+ console.warn(`[delegation-gate] fallback: could not advance ${taskId} (${state2}) \u2192 tests_run: ${err2 instanceof Error ? err2.message : String(err2)}`);
50080
50234
  }
50081
50235
  }
50082
50236
  }
@@ -50091,12 +50245,12 @@ function createDelegationGateHook(config3, directory) {
50091
50245
  if (seedTaskId && !otherSession.taskWorkflowStates.has(seedTaskId)) {
50092
50246
  otherSession.taskWorkflowStates.set(seedTaskId, "coder_delegated");
50093
50247
  }
50094
- for (const [taskId, state] of otherSession.taskWorkflowStates) {
50095
- if (state === "coder_delegated" || state === "pre_check_passed") {
50248
+ for (const [taskId, state2] of otherSession.taskWorkflowStates) {
50249
+ if (state2 === "coder_delegated" || state2 === "pre_check_passed") {
50096
50250
  try {
50097
50251
  advanceTaskState(otherSession, taskId, "reviewer_run");
50098
50252
  } catch (err2) {
50099
- console.warn(`[delegation-gate] fallback cross-session: could not advance ${taskId} (${state}) \u2192 reviewer_run: ${err2 instanceof Error ? err2.message : String(err2)}`);
50253
+ console.warn(`[delegation-gate] fallback cross-session: could not advance ${taskId} (${state2}) \u2192 reviewer_run: ${err2 instanceof Error ? err2.message : String(err2)}`);
50100
50254
  }
50101
50255
  }
50102
50256
  }
@@ -50112,12 +50266,12 @@ function createDelegationGateHook(config3, directory) {
50112
50266
  if (seedTaskId && !otherSession.taskWorkflowStates.has(seedTaskId)) {
50113
50267
  otherSession.taskWorkflowStates.set(seedTaskId, "reviewer_run");
50114
50268
  }
50115
- for (const [taskId, state] of otherSession.taskWorkflowStates) {
50116
- if (state === "reviewer_run") {
50269
+ for (const [taskId, state2] of otherSession.taskWorkflowStates) {
50270
+ if (state2 === "reviewer_run") {
50117
50271
  try {
50118
50272
  advanceTaskState(otherSession, taskId, "tests_run");
50119
50273
  } catch (err2) {
50120
- console.warn(`[delegation-gate] fallback cross-session: could not advance ${taskId} (${state}) \u2192 tests_run: ${err2 instanceof Error ? err2.message : String(err2)}`);
50274
+ console.warn(`[delegation-gate] fallback cross-session: could not advance ${taskId} (${state2}) \u2192 tests_run: ${err2 instanceof Error ? err2.message : String(err2)}`);
50121
50275
  }
50122
50276
  }
50123
50277
  }
@@ -50363,7 +50517,7 @@ ${warningLines.join(`
50363
50517
  }
50364
50518
  // src/hooks/delegation-sanitizer.ts
50365
50519
  init_utils2();
50366
- import * as fs16 from "fs";
50520
+ import * as fs17 from "fs";
50367
50521
  var SANITIZATION_PATTERNS = [
50368
50522
  /\b\d+(st|nd|rd|th)\s+(attempt|try|time)\b/gi,
50369
50523
  /\b(5th|fifth|final|last)\s+attempt\b/gi,
@@ -50434,7 +50588,7 @@ function createDelegationSanitizerHook(directory) {
50434
50588
  stripped_patterns: result.stripped,
50435
50589
  timestamp: new Date().toISOString()
50436
50590
  };
50437
- fs16.appendFileSync(eventsPath, `${JSON.stringify(event)}
50591
+ fs17.appendFileSync(eventsPath, `${JSON.stringify(event)}
50438
50592
  `, "utf-8");
50439
50593
  } catch {}
50440
50594
  }
@@ -50684,13 +50838,13 @@ init_schema();
50684
50838
  init_manager();
50685
50839
  init_detector();
50686
50840
  init_manager2();
50687
- import * as fs18 from "fs";
50841
+ import * as fs19 from "fs";
50688
50842
 
50689
50843
  // src/services/decision-drift-analyzer.ts
50690
50844
  init_utils2();
50691
50845
  init_manager2();
50692
- import * as fs17 from "fs";
50693
- import * as path30 from "path";
50846
+ import * as fs18 from "fs";
50847
+ import * as path31 from "path";
50694
50848
  var DEFAULT_DRIFT_CONFIG = {
50695
50849
  staleThresholdPhases: 1,
50696
50850
  detectContradictions: true,
@@ -50844,11 +50998,11 @@ async function analyzeDecisionDrift(directory, config3 = {}) {
50844
50998
  currentPhase = legacyPhase;
50845
50999
  }
50846
51000
  }
50847
- const contextPath = path30.join(directory, ".swarm", "context.md");
51001
+ const contextPath = path31.join(directory, ".swarm", "context.md");
50848
51002
  let contextContent = "";
50849
51003
  try {
50850
- if (fs17.existsSync(contextPath)) {
50851
- contextContent = fs17.readFileSync(contextPath, "utf-8");
51004
+ if (fs18.existsSync(contextPath)) {
51005
+ contextContent = fs18.readFileSync(contextPath, "utf-8");
50852
51006
  }
50853
51007
  } catch {
50854
51008
  return {
@@ -51342,11 +51496,11 @@ function createSystemEnhancerHook(config3, directory) {
51342
51496
  if (handoffContent) {
51343
51497
  const handoffPath = validateSwarmPath(directory, "handoff.md");
51344
51498
  const consumedPath = validateSwarmPath(directory, "handoff-consumed.md");
51345
- if (fs18.existsSync(consumedPath)) {
51499
+ if (fs19.existsSync(consumedPath)) {
51346
51500
  warn("Duplicate handoff detected: handoff-consumed.md already exists");
51347
- fs18.unlinkSync(consumedPath);
51501
+ fs19.unlinkSync(consumedPath);
51348
51502
  }
51349
- fs18.renameSync(handoffPath, consumedPath);
51503
+ fs19.renameSync(handoffPath, consumedPath);
51350
51504
  const handoffBlock = `## HANDOFF \u2014 Resuming from model switch
51351
51505
  The previous model's session ended. Here is your starting context:
51352
51506
 
@@ -51626,11 +51780,11 @@ ${budgetWarning}`);
51626
51780
  if (handoffContent) {
51627
51781
  const handoffPath = validateSwarmPath(directory, "handoff.md");
51628
51782
  const consumedPath = validateSwarmPath(directory, "handoff-consumed.md");
51629
- if (fs18.existsSync(consumedPath)) {
51783
+ if (fs19.existsSync(consumedPath)) {
51630
51784
  warn("Duplicate handoff detected: handoff-consumed.md already exists");
51631
- fs18.unlinkSync(consumedPath);
51785
+ fs19.unlinkSync(consumedPath);
51632
51786
  }
51633
- fs18.renameSync(handoffPath, consumedPath);
51787
+ fs19.renameSync(handoffPath, consumedPath);
51634
51788
  const handoffBlock = `## HANDOFF \u2014 Resuming from model switch
51635
51789
  The previous model's session ended. Here is your starting context:
51636
51790
 
@@ -52308,55 +52462,112 @@ function createDarkMatterDetectorHook(directory) {
52308
52462
  }
52309
52463
 
52310
52464
  // src/hooks/incremental-verify.ts
52311
- import * as fs19 from "fs";
52312
- import * as path31 from "path";
52465
+ import * as fs20 from "fs";
52466
+ import * as path32 from "path";
52467
+
52468
+ // src/hooks/spawn-helper.ts
52469
+ import { spawn } from "child_process";
52470
+ function spawnAsync(command, cwd, timeoutMs) {
52471
+ return new Promise((resolve11) => {
52472
+ try {
52473
+ const [cmd, ...args2] = command;
52474
+ const proc = spawn(cmd, args2, { cwd, stdio: ["ignore", "pipe", "pipe"] });
52475
+ let stdout = "";
52476
+ let stderr = "";
52477
+ let done = false;
52478
+ proc.stdout.on("data", (d) => {
52479
+ stdout += d;
52480
+ });
52481
+ proc.stderr.on("data", (d) => {
52482
+ stderr += d;
52483
+ });
52484
+ const timer = setTimeout(() => {
52485
+ if (done)
52486
+ return;
52487
+ done = true;
52488
+ try {
52489
+ proc.stdout.destroy();
52490
+ } catch {}
52491
+ try {
52492
+ proc.stderr.destroy();
52493
+ } catch {}
52494
+ try {
52495
+ proc.kill();
52496
+ } catch {}
52497
+ resolve11(null);
52498
+ }, timeoutMs);
52499
+ proc.on("close", (code) => {
52500
+ if (done)
52501
+ return;
52502
+ done = true;
52503
+ clearTimeout(timer);
52504
+ resolve11({ exitCode: code ?? 1, stdout, stderr });
52505
+ });
52506
+ proc.on("error", () => {
52507
+ if (done)
52508
+ return;
52509
+ done = true;
52510
+ clearTimeout(timer);
52511
+ resolve11(null);
52512
+ });
52513
+ } catch {
52514
+ resolve11(null);
52515
+ }
52516
+ });
52517
+ }
52518
+
52519
+ // src/hooks/incremental-verify.ts
52520
+ var emittedSkipAdvisories = new Set;
52313
52521
  function detectTypecheckCommand(projectDir) {
52314
- const pkgPath = path31.join(projectDir, "package.json");
52315
- if (!fs19.existsSync(pkgPath))
52316
- return null;
52317
- try {
52318
- const pkg = JSON.parse(fs19.readFileSync(pkgPath, "utf8"));
52319
- const scripts = pkg.scripts;
52320
- if (scripts?.typecheck)
52321
- return ["bun", "run", "typecheck"];
52322
- if (scripts?.["type-check"])
52323
- return ["bun", "run", "type-check"];
52324
- const deps = {
52325
- ...pkg.dependencies,
52326
- ...pkg.devDependencies
52327
- };
52328
- if (!deps?.typescript && !fs19.existsSync(path31.join(projectDir, "tsconfig.json"))) {
52522
+ const pkgPath = path32.join(projectDir, "package.json");
52523
+ if (fs20.existsSync(pkgPath)) {
52524
+ try {
52525
+ const pkg = JSON.parse(fs20.readFileSync(pkgPath, "utf8"));
52526
+ const scripts = pkg.scripts;
52527
+ if (scripts?.typecheck)
52528
+ return { command: ["bun", "run", "typecheck"], language: "typescript" };
52529
+ if (scripts?.["type-check"])
52530
+ return {
52531
+ command: ["bun", "run", "type-check"],
52532
+ language: "typescript"
52533
+ };
52534
+ const deps = {
52535
+ ...pkg.dependencies,
52536
+ ...pkg.devDependencies
52537
+ };
52538
+ if (!deps?.typescript && !fs20.existsSync(path32.join(projectDir, "tsconfig.json"))) {
52539
+ return null;
52540
+ }
52541
+ return { command: ["npx", "tsc", "--noEmit"], language: "typescript" };
52542
+ } catch {
52329
52543
  return null;
52330
52544
  }
52331
- return ["npx", "tsc", "--noEmit"];
52332
- } catch {
52333
- return null;
52334
52545
  }
52335
- }
52336
- async function runWithTimeout(command, cwd, timeoutMs) {
52546
+ if (fs20.existsSync(path32.join(projectDir, "go.mod"))) {
52547
+ return { command: ["go", "vet", "./..."], language: "go" };
52548
+ }
52549
+ if (fs20.existsSync(path32.join(projectDir, "Cargo.toml"))) {
52550
+ return { command: ["cargo", "check"], language: "rust" };
52551
+ }
52552
+ if (fs20.existsSync(path32.join(projectDir, "pyproject.toml")) || fs20.existsSync(path32.join(projectDir, "requirements.txt")) || fs20.existsSync(path32.join(projectDir, "setup.py"))) {
52553
+ return { command: null, language: "python" };
52554
+ }
52337
52555
  try {
52338
- const proc = Bun.spawn(command, {
52339
- cwd,
52340
- stdout: "pipe",
52341
- stderr: "pipe"
52342
- });
52343
- const timeoutHandle = setTimeout(() => {
52344
- try {
52345
- proc.kill();
52346
- } catch {}
52347
- }, timeoutMs);
52348
- try {
52349
- const [exitCode, stderr] = await Promise.all([
52350
- proc.exited,
52351
- new Response(proc.stderr).text()
52352
- ]);
52353
- return { exitCode, stderr };
52354
- } finally {
52355
- clearTimeout(timeoutHandle);
52556
+ const entries = fs20.readdirSync(projectDir);
52557
+ if (entries.some((f) => f.endsWith(".csproj") || f.endsWith(".sln"))) {
52558
+ return {
52559
+ command: ["dotnet", "build", "--no-restore"],
52560
+ language: "csharp"
52561
+ };
52356
52562
  }
52357
- } catch {
52563
+ } catch {}
52564
+ return null;
52565
+ }
52566
+ async function runWithTimeout(command, cwd, timeoutMs) {
52567
+ const result = await spawnAsync(command, cwd, timeoutMs);
52568
+ if (result === null)
52358
52569
  return null;
52359
- }
52570
+ return { exitCode: result.exitCode, stderr: result.stderr };
52360
52571
  }
52361
52572
  function createIncrementalVerifyHook(config3, projectDir, injectMessage) {
52362
52573
  return {
@@ -52371,10 +52582,27 @@ function createIncrementalVerifyHook(config3, projectDir, injectMessage) {
52371
52582
  if (!config3.triggerAgents.includes(agentName) && !config3.triggerAgents.includes(subagentType)) {
52372
52583
  return;
52373
52584
  }
52374
- const command = config3.command != null ? config3.command.split(" ") : detectTypecheckCommand(projectDir);
52375
- if (!command)
52585
+ let commandToRun = null;
52586
+ if (config3.command != null) {
52587
+ commandToRun = Array.isArray(config3.command) ? config3.command : config3.command.split(" ");
52588
+ } else {
52589
+ const detected = detectTypecheckCommand(projectDir);
52590
+ if (detected === null) {
52591
+ return;
52592
+ }
52593
+ if (detected.command === null) {
52594
+ const dedupKey = `${input.sessionID}:${detected.language}`;
52595
+ if (!emittedSkipAdvisories.has(dedupKey)) {
52596
+ emittedSkipAdvisories.add(dedupKey);
52597
+ injectMessage(input.sessionID, `POST-CODER CHECK SKIPPED: ${detected.language} project detected but no default checker available. Set incremental_verify.command in .swarm/config.json to enable.`);
52598
+ }
52599
+ return;
52600
+ }
52601
+ commandToRun = detected.command;
52602
+ }
52603
+ if (commandToRun === null)
52376
52604
  return;
52377
- const result = await runWithTimeout(command, projectDir, config3.timeoutMs);
52605
+ const result = await runWithTimeout(commandToRun, projectDir, config3.timeoutMs);
52378
52606
  if (result === null) {
52379
52607
  return;
52380
52608
  }
@@ -52392,7 +52620,7 @@ ${errorSummary}`);
52392
52620
  // src/hooks/knowledge-reader.ts
52393
52621
  import { existsSync as existsSync19 } from "fs";
52394
52622
  import { mkdir as mkdir4, readFile as readFile5, writeFile as writeFile4 } from "fs/promises";
52395
- import * as path32 from "path";
52623
+ import * as path33 from "path";
52396
52624
  var JACCARD_THRESHOLD = 0.6;
52397
52625
  var HIVE_TIER_BOOST = 0.05;
52398
52626
  var SAME_PROJECT_PENALTY = -0.05;
@@ -52440,7 +52668,7 @@ function inferCategoriesFromPhase(phaseDescription) {
52440
52668
  return ["process", "tooling"];
52441
52669
  }
52442
52670
  async function recordLessonsShown(directory, lessonIds, currentPhase) {
52443
- const shownFile = path32.join(directory, ".swarm", ".knowledge-shown.json");
52671
+ const shownFile = path33.join(directory, ".swarm", ".knowledge-shown.json");
52444
52672
  try {
52445
52673
  let shownData = {};
52446
52674
  if (existsSync19(shownFile)) {
@@ -52448,7 +52676,7 @@ async function recordLessonsShown(directory, lessonIds, currentPhase) {
52448
52676
  shownData = JSON.parse(content);
52449
52677
  }
52450
52678
  shownData[currentPhase] = lessonIds;
52451
- await mkdir4(path32.dirname(shownFile), { recursive: true });
52679
+ await mkdir4(path33.dirname(shownFile), { recursive: true });
52452
52680
  await writeFile4(shownFile, JSON.stringify(shownData, null, 2), "utf-8");
52453
52681
  } catch {
52454
52682
  console.warn("[swarm] Knowledge: failed to record shown lessons");
@@ -52543,7 +52771,7 @@ async function readMergedKnowledge(directory, config3, context) {
52543
52771
  return topN;
52544
52772
  }
52545
52773
  async function updateRetrievalOutcome(directory, phaseInfo, phaseSucceeded) {
52546
- const shownFile = path32.join(directory, ".swarm", ".knowledge-shown.json");
52774
+ const shownFile = path33.join(directory, ".swarm", ".knowledge-shown.json");
52547
52775
  try {
52548
52776
  if (!existsSync19(shownFile)) {
52549
52777
  return;
@@ -53015,12 +53243,12 @@ Use this data to avoid repeating known failure patterns.`;
53015
53243
  // src/hooks/curator-drift.ts
53016
53244
  init_event_bus();
53017
53245
  init_utils2();
53018
- import * as fs20 from "fs";
53019
- import * as path33 from "path";
53246
+ import * as fs21 from "fs";
53247
+ import * as path34 from "path";
53020
53248
  var DRIFT_REPORT_PREFIX = "drift-report-phase-";
53021
53249
  async function readPriorDriftReports(directory) {
53022
- const swarmDir = path33.join(directory, ".swarm");
53023
- const entries = await fs20.promises.readdir(swarmDir).catch(() => null);
53250
+ const swarmDir = path34.join(directory, ".swarm");
53251
+ const entries = await fs21.promises.readdir(swarmDir).catch(() => null);
53024
53252
  if (entries === null)
53025
53253
  return [];
53026
53254
  const reportFiles = entries.filter((name2) => name2.startsWith(DRIFT_REPORT_PREFIX) && name2.endsWith(".json")).sort();
@@ -53046,10 +53274,10 @@ async function readPriorDriftReports(directory) {
53046
53274
  async function writeDriftReport(directory, report) {
53047
53275
  const filename = `${DRIFT_REPORT_PREFIX}${report.phase}.json`;
53048
53276
  const filePath = validateSwarmPath(directory, filename);
53049
- const swarmDir = path33.dirname(filePath);
53050
- await fs20.promises.mkdir(swarmDir, { recursive: true });
53277
+ const swarmDir = path34.dirname(filePath);
53278
+ await fs21.promises.mkdir(swarmDir, { recursive: true });
53051
53279
  try {
53052
- await fs20.promises.writeFile(filePath, JSON.stringify(report, null, 2), "utf-8");
53280
+ await fs21.promises.writeFile(filePath, JSON.stringify(report, null, 2), "utf-8");
53053
53281
  } catch (err2) {
53054
53282
  throw new Error(`[curator-drift] Failed to write drift report to ${filePath}: ${String(err2)}`);
53055
53283
  }
@@ -53300,6 +53528,8 @@ ${cachedInjectionText}`;
53300
53528
  }
53301
53529
 
53302
53530
  // src/hooks/slop-detector.ts
53531
+ import * as fs22 from "fs";
53532
+ import * as path35 from "path";
53303
53533
  var WRITE_EDIT_TOOLS = new Set([
53304
53534
  "write",
53305
53535
  "edit",
@@ -53310,7 +53540,7 @@ function countMatches(text, pattern) {
53310
53540
  return (text.match(pattern) ?? []).length;
53311
53541
  }
53312
53542
  function checkAbstractionBloat(content, threshold) {
53313
- const newClasses = countMatches(content, /^\+.*\bclass\s+\w+/gm);
53543
+ const newClasses = countMatches(content, /^\+.*\b(?:class|struct|impl)\s+\w+/gm);
53314
53544
  if (newClasses >= threshold) {
53315
53545
  return {
53316
53546
  type: "abstraction_bloat",
@@ -53320,8 +53550,8 @@ function checkAbstractionBloat(content, threshold) {
53320
53550
  return null;
53321
53551
  }
53322
53552
  function checkCommentStrip(content, threshold) {
53323
- const removedComments = countMatches(content, /^-\s*\/[/*]/gm);
53324
- const addedComments = countMatches(content, /^\+\s*\/[/*]/gm);
53553
+ const removedComments = countMatches(content, /^-\s*(?:\/[/*]|#|--)/gm);
53554
+ const addedComments = countMatches(content, /^\+\s*(?:\/[/*]|#|--)/gm);
53325
53555
  if (removedComments >= threshold && addedComments === 0) {
53326
53556
  return {
53327
53557
  type: "comment_strip",
@@ -53341,8 +53571,33 @@ function checkBoilerplateExplosion(content, taskDescription, threshold) {
53341
53571
  }
53342
53572
  return null;
53343
53573
  }
53344
- async function checkDeadExports(content, projectDir, startTime) {
53345
- const exportMatches = content.matchAll(/^(?:export)\s+(?:function|class|const|type|interface)\s+(\w{3,})/gm);
53574
+ function walkFiles(dir, exts, deadline) {
53575
+ const results = [];
53576
+ try {
53577
+ for (const entry of fs22.readdirSync(dir, { withFileTypes: true })) {
53578
+ if (deadline !== undefined && Date.now() > deadline)
53579
+ break;
53580
+ if (entry.isSymbolicLink())
53581
+ continue;
53582
+ const full = path35.join(dir, entry.name);
53583
+ if (entry.isDirectory()) {
53584
+ if (entry.name === "node_modules" || entry.name === ".git")
53585
+ continue;
53586
+ results.push(...walkFiles(full, exts, deadline));
53587
+ } else if (entry.isFile()) {
53588
+ if (exts.some((ext) => entry.name.endsWith(ext))) {
53589
+ results.push(full);
53590
+ }
53591
+ }
53592
+ }
53593
+ } catch {}
53594
+ return results;
53595
+ }
53596
+ function checkDeadExports(content, projectDir, startTime) {
53597
+ const hasPackageJson = fs22.existsSync(path35.join(projectDir, "package.json"));
53598
+ if (!hasPackageJson)
53599
+ return null;
53600
+ const exportMatches = content.matchAll(/^\+(?:export)\s+(?:function|class|const|type|interface)\s+(\w{3,})/gm);
53346
53601
  const newExports = [];
53347
53602
  for (const match of exportMatches) {
53348
53603
  if (match[1])
@@ -53350,19 +53605,19 @@ async function checkDeadExports(content, projectDir, startTime) {
53350
53605
  }
53351
53606
  if (newExports.length === 0)
53352
53607
  return null;
53608
+ const files = walkFiles(projectDir, [".ts", ".tsx", ".js", ".jsx"], startTime + 480);
53353
53609
  const deadExports = [];
53354
53610
  for (const name2 of newExports) {
53355
53611
  if (Date.now() - startTime > 480)
53356
53612
  break;
53357
53613
  try {
53358
53614
  const importPattern = new RegExp(`\\bimport\\b[^;]*\\b${name2}\\b`, "g");
53359
- const glob = new Bun.Glob(`src/**/*.ts`);
53360
53615
  let found = false;
53361
- for await (const file3 of glob.scan(projectDir)) {
53616
+ for (const file3 of files) {
53362
53617
  if (found || Date.now() - startTime > 480)
53363
53618
  break;
53364
53619
  try {
53365
- const text = await Bun.file(`${projectDir}/${file3}`).text();
53620
+ const text = fs22.readFileSync(file3, "utf-8");
53366
53621
  if (importPattern.test(text))
53367
53622
  found = true;
53368
53623
  importPattern.lastIndex = 0;
@@ -53416,7 +53671,7 @@ function createSlopDetectorHook(config3, projectDir, injectSystemMessage) {
53416
53671
  } catch {}
53417
53672
  if (Date.now() - startTime < 400) {
53418
53673
  try {
53419
- const dead = await checkDeadExports(content, projectDir, startTime);
53674
+ const dead = checkDeadExports(content, projectDir, startTime);
53420
53675
  if (dead)
53421
53676
  findings.push(dead);
53422
53677
  } catch {}
@@ -53435,7 +53690,7 @@ Review before proceeding.`;
53435
53690
 
53436
53691
  // src/hooks/steering-consumed.ts
53437
53692
  init_utils2();
53438
- import * as fs21 from "fs";
53693
+ import * as fs23 from "fs";
53439
53694
  function recordSteeringConsumed(directory, directiveId) {
53440
53695
  try {
53441
53696
  const eventsPath = validateSwarmPath(directory, "events.jsonl");
@@ -53444,7 +53699,7 @@ function recordSteeringConsumed(directory, directiveId) {
53444
53699
  directiveId,
53445
53700
  timestamp: new Date().toISOString()
53446
53701
  };
53447
- fs21.appendFileSync(eventsPath, `${JSON.stringify(event)}
53702
+ fs23.appendFileSync(eventsPath, `${JSON.stringify(event)}
53448
53703
  `, "utf-8");
53449
53704
  } catch {}
53450
53705
  }
@@ -53484,93 +53739,12 @@ function createSteeringConsumedHook(directory) {
53484
53739
  return safeHook(hook);
53485
53740
  }
53486
53741
 
53487
- // src/services/compaction-service.ts
53488
- import * as fs22 from "fs";
53489
- import * as path34 from "path";
53490
- function makeInitialState() {
53491
- return {
53492
- lastObservationAt: 0,
53493
- lastReflectionAt: 0,
53494
- lastEmergencyAt: 0,
53495
- observationCount: 0,
53496
- reflectionCount: 0,
53497
- emergencyCount: 0
53498
- };
53499
- }
53500
- function appendSnapshot(directory, tier, budgetPct, message) {
53501
- try {
53502
- const snapshotPath = path34.join(directory, ".swarm", "context-snapshot.md");
53503
- const timestamp = new Date().toISOString();
53504
- const entry = `
53505
- ## [${tier.toUpperCase()}] ${timestamp} \u2014 ${budgetPct.toFixed(1)}% used
53506
- ${message}
53507
- `;
53508
- fs22.appendFileSync(snapshotPath, entry, "utf-8");
53509
- } catch {}
53510
- }
53511
- function buildObservationMessage(budgetPct) {
53512
- return `[CONTEXT COMPACTION \u2014 OBSERVATION TIER]
53513
- ` + `Context window is ${budgetPct.toFixed(1)}% used. Initiating observation compaction.
53514
- ` + `INSTRUCTIONS: Summarise the key decisions made so far, files changed, errors resolved, ` + `and the current task state. Discard verbose tool outputs and raw file reads. ` + `Preserve: plan task ID, agent verdicts, file paths touched, unresolved blockers.
53515
- ` + `[/CONTEXT COMPACTION]`;
53516
- }
53517
- function buildReflectionMessage(budgetPct) {
53518
- return `[CONTEXT COMPACTION \u2014 REFLECTION TIER]
53519
- ` + `Context window is ${budgetPct.toFixed(1)}% used. Initiating reflection compaction.
53520
- ` + `INSTRUCTIONS: Re-summarise into a tighter format. Discard completed task details ` + `and resolved errors. Retain ONLY: current phase tasks remaining, open blockers, ` + `last 3 reviewer/test verdicts, and active file scope.
53521
- ` + `[/CONTEXT COMPACTION]`;
53522
- }
53523
- function buildEmergencyMessage(budgetPct, preserveLastN) {
53524
- return `[CONTEXT COMPACTION \u2014 EMERGENCY TIER]
53525
- ` + `Context window is ${budgetPct.toFixed(1)}% used. EMERGENCY compaction required.
53526
- ` + `INSTRUCTIONS: Retain ONLY the system prompt, the current task context, and the ` + `last ${preserveLastN} conversation turns. Discard everything else. ` + `If you cannot complete the current task in the remaining context, escalate to the user.
53527
- ` + `[/CONTEXT COMPACTION]`;
53528
- }
53529
- function createCompactionService(config3, directory, injectMessage) {
53530
- const state = makeInitialState();
53531
- return {
53532
- toolAfter: async (_input, _output) => {
53533
- if (!config3.enabled)
53534
- return;
53535
- const budgetPct = swarmState.lastBudgetPct ?? 0;
53536
- if (budgetPct <= 0)
53537
- return;
53538
- const sessionId = _input.sessionID;
53539
- try {
53540
- if (budgetPct >= config3.emergencyThreshold && budgetPct > state.lastEmergencyAt + 5) {
53541
- state.lastEmergencyAt = budgetPct;
53542
- state.emergencyCount++;
53543
- const msg = buildEmergencyMessage(budgetPct, config3.preserveLastNTurns);
53544
- appendSnapshot(directory, "emergency", budgetPct, msg);
53545
- injectMessage(sessionId, msg);
53546
- return;
53547
- }
53548
- if (budgetPct >= config3.reflectionThreshold && budgetPct > state.lastReflectionAt + 5) {
53549
- state.lastReflectionAt = budgetPct;
53550
- state.reflectionCount++;
53551
- const msg = buildReflectionMessage(budgetPct);
53552
- appendSnapshot(directory, "reflection", budgetPct, msg);
53553
- injectMessage(sessionId, msg);
53554
- return;
53555
- }
53556
- if (budgetPct >= config3.observationThreshold && budgetPct > state.lastObservationAt + 5) {
53557
- state.lastObservationAt = budgetPct;
53558
- state.observationCount++;
53559
- const msg = buildObservationMessage(budgetPct);
53560
- appendSnapshot(directory, "observation", budgetPct, msg);
53561
- injectMessage(sessionId, msg);
53562
- }
53563
- } catch {}
53564
- }
53565
- };
53566
- }
53567
-
53568
53742
  // src/index.ts
53569
53743
  init_config_doctor();
53570
53744
 
53571
53745
  // src/session/snapshot-reader.ts
53572
53746
  init_utils2();
53573
- import path35 from "path";
53747
+ import path36 from "path";
53574
53748
  var VALID_TASK_WORKFLOW_STATES = [
53575
53749
  "idle",
53576
53750
  "coder_delegated",
@@ -53695,7 +53869,7 @@ function rehydrateState(snapshot) {
53695
53869
  async function reconcileTaskStatesFromPlan(directory) {
53696
53870
  let raw;
53697
53871
  try {
53698
- raw = await Bun.file(path35.join(directory, ".swarm/plan.json")).text();
53872
+ raw = await Bun.file(path36.join(directory, ".swarm/plan.json")).text();
53699
53873
  } catch {
53700
53874
  return;
53701
53875
  }
@@ -53917,8 +54091,8 @@ var build_check = createSwarmTool({
53917
54091
  // src/tools/check-gate-status.ts
53918
54092
  init_dist();
53919
54093
  init_create_tool();
53920
- import * as fs23 from "fs";
53921
- import * as path36 from "path";
54094
+ import * as fs24 from "fs";
54095
+ import * as path37 from "path";
53922
54096
  var EVIDENCE_DIR = ".swarm/evidence";
53923
54097
  var TASK_ID_PATTERN2 = /^\d+\.\d+(\.\d+)*$/;
53924
54098
  function isValidTaskId3(taskId) {
@@ -53935,18 +54109,18 @@ function isValidTaskId3(taskId) {
53935
54109
  return TASK_ID_PATTERN2.test(taskId);
53936
54110
  }
53937
54111
  function isPathWithinSwarm(filePath, workspaceRoot) {
53938
- const normalizedWorkspace = path36.resolve(workspaceRoot);
53939
- const swarmPath = path36.join(normalizedWorkspace, ".swarm", "evidence");
53940
- const normalizedPath = path36.resolve(filePath);
54112
+ const normalizedWorkspace = path37.resolve(workspaceRoot);
54113
+ const swarmPath = path37.join(normalizedWorkspace, ".swarm", "evidence");
54114
+ const normalizedPath = path37.resolve(filePath);
53941
54115
  return normalizedPath.startsWith(swarmPath);
53942
54116
  }
53943
54117
  function readEvidenceFile(evidencePath) {
53944
- if (!fs23.existsSync(evidencePath)) {
54118
+ if (!fs24.existsSync(evidencePath)) {
53945
54119
  return null;
53946
54120
  }
53947
54121
  let content;
53948
54122
  try {
53949
- content = fs23.readFileSync(evidencePath, "utf-8");
54123
+ content = fs24.readFileSync(evidencePath, "utf-8");
53950
54124
  } catch {
53951
54125
  return null;
53952
54126
  }
@@ -53998,7 +54172,7 @@ var check_gate_status = createSwarmTool({
53998
54172
  };
53999
54173
  return JSON.stringify(errorResult, null, 2);
54000
54174
  }
54001
- const evidencePath = path36.join(directory, EVIDENCE_DIR, `${taskIdInput}.json`);
54175
+ const evidencePath = path37.join(directory, EVIDENCE_DIR, `${taskIdInput}.json`);
54002
54176
  if (!isPathWithinSwarm(evidencePath, directory)) {
54003
54177
  const errorResult = {
54004
54178
  taskId: taskIdInput,
@@ -54058,8 +54232,8 @@ var check_gate_status = createSwarmTool({
54058
54232
  init_tool();
54059
54233
  init_create_tool();
54060
54234
  import { spawnSync } from "child_process";
54061
- import * as fs24 from "fs";
54062
- import * as path37 from "path";
54235
+ import * as fs25 from "fs";
54236
+ import * as path38 from "path";
54063
54237
  var CHECKPOINT_LOG_PATH = ".swarm/checkpoints.json";
54064
54238
  var MAX_LABEL_LENGTH = 100;
54065
54239
  var GIT_TIMEOUT_MS = 30000;
@@ -54110,13 +54284,13 @@ function validateLabel(label) {
54110
54284
  return null;
54111
54285
  }
54112
54286
  function getCheckpointLogPath(directory) {
54113
- return path37.join(directory, CHECKPOINT_LOG_PATH);
54287
+ return path38.join(directory, CHECKPOINT_LOG_PATH);
54114
54288
  }
54115
54289
  function readCheckpointLog(directory) {
54116
54290
  const logPath = getCheckpointLogPath(directory);
54117
54291
  try {
54118
- if (fs24.existsSync(logPath)) {
54119
- const content = fs24.readFileSync(logPath, "utf-8");
54292
+ if (fs25.existsSync(logPath)) {
54293
+ const content = fs25.readFileSync(logPath, "utf-8");
54120
54294
  const parsed = JSON.parse(content);
54121
54295
  if (!parsed.checkpoints || !Array.isArray(parsed.checkpoints)) {
54122
54296
  return { version: 1, checkpoints: [] };
@@ -54128,13 +54302,13 @@ function readCheckpointLog(directory) {
54128
54302
  }
54129
54303
  function writeCheckpointLog(log2, directory) {
54130
54304
  const logPath = getCheckpointLogPath(directory);
54131
- const dir = path37.dirname(logPath);
54132
- if (!fs24.existsSync(dir)) {
54133
- fs24.mkdirSync(dir, { recursive: true });
54305
+ const dir = path38.dirname(logPath);
54306
+ if (!fs25.existsSync(dir)) {
54307
+ fs25.mkdirSync(dir, { recursive: true });
54134
54308
  }
54135
54309
  const tempPath = `${logPath}.tmp`;
54136
- fs24.writeFileSync(tempPath, JSON.stringify(log2, null, 2), "utf-8");
54137
- fs24.renameSync(tempPath, logPath);
54310
+ fs25.writeFileSync(tempPath, JSON.stringify(log2, null, 2), "utf-8");
54311
+ fs25.renameSync(tempPath, logPath);
54138
54312
  }
54139
54313
  function gitExec(args2) {
54140
54314
  const result = spawnSync("git", args2, {
@@ -54335,8 +54509,8 @@ var checkpoint = createSwarmTool({
54335
54509
  // src/tools/complexity-hotspots.ts
54336
54510
  init_dist();
54337
54511
  init_create_tool();
54338
- import * as fs25 from "fs";
54339
- import * as path38 from "path";
54512
+ import * as fs26 from "fs";
54513
+ import * as path39 from "path";
54340
54514
  var MAX_FILE_SIZE_BYTES2 = 256 * 1024;
54341
54515
  var DEFAULT_DAYS = 90;
54342
54516
  var DEFAULT_TOP_N = 20;
@@ -54465,11 +54639,11 @@ function estimateComplexity(content) {
54465
54639
  }
54466
54640
  function getComplexityForFile(filePath) {
54467
54641
  try {
54468
- const stat2 = fs25.statSync(filePath);
54642
+ const stat2 = fs26.statSync(filePath);
54469
54643
  if (stat2.size > MAX_FILE_SIZE_BYTES2) {
54470
54644
  return null;
54471
54645
  }
54472
- const content = fs25.readFileSync(filePath, "utf-8");
54646
+ const content = fs26.readFileSync(filePath, "utf-8");
54473
54647
  return estimateComplexity(content);
54474
54648
  } catch {
54475
54649
  return null;
@@ -54480,7 +54654,7 @@ async function analyzeHotspots(days, topN, extensions, directory) {
54480
54654
  const extSet = new Set(extensions.map((e) => e.startsWith(".") ? e : `.${e}`));
54481
54655
  const filteredChurn = new Map;
54482
54656
  for (const [file3, count] of churnMap) {
54483
- const ext = path38.extname(file3).toLowerCase();
54657
+ const ext = path39.extname(file3).toLowerCase();
54484
54658
  if (extSet.has(ext)) {
54485
54659
  filteredChurn.set(file3, count);
54486
54660
  }
@@ -54490,8 +54664,8 @@ async function analyzeHotspots(days, topN, extensions, directory) {
54490
54664
  let analyzedFiles = 0;
54491
54665
  for (const [file3, churnCount] of filteredChurn) {
54492
54666
  let fullPath = file3;
54493
- if (!fs25.existsSync(fullPath)) {
54494
- fullPath = path38.join(cwd, file3);
54667
+ if (!fs26.existsSync(fullPath)) {
54668
+ fullPath = path39.join(cwd, file3);
54495
54669
  }
54496
54670
  const complexity = getComplexityForFile(fullPath);
54497
54671
  if (complexity !== null) {
@@ -54638,8 +54812,8 @@ var complexity_hotspots = createSwarmTool({
54638
54812
  });
54639
54813
  // src/tools/declare-scope.ts
54640
54814
  init_tool();
54641
- import * as fs26 from "fs";
54642
- import * as path39 from "path";
54815
+ import * as fs27 from "fs";
54816
+ import * as path40 from "path";
54643
54817
  init_create_tool();
54644
54818
  function validateTaskIdFormat(taskId) {
54645
54819
  const taskIdPattern = /^\d+\.\d+(\.\d+)*$/;
@@ -54718,8 +54892,8 @@ async function executeDeclareScope(args2, fallbackDir) {
54718
54892
  };
54719
54893
  }
54720
54894
  }
54721
- normalizedDir = path39.normalize(args2.working_directory);
54722
- const pathParts = normalizedDir.split(path39.sep);
54895
+ normalizedDir = path40.normalize(args2.working_directory);
54896
+ const pathParts = normalizedDir.split(path40.sep);
54723
54897
  if (pathParts.includes("..")) {
54724
54898
  return {
54725
54899
  success: false,
@@ -54729,11 +54903,11 @@ async function executeDeclareScope(args2, fallbackDir) {
54729
54903
  ]
54730
54904
  };
54731
54905
  }
54732
- const resolvedDir = path39.resolve(normalizedDir);
54906
+ const resolvedDir = path40.resolve(normalizedDir);
54733
54907
  try {
54734
- const realPath = fs26.realpathSync(resolvedDir);
54735
- const planPath2 = path39.join(realPath, ".swarm", "plan.json");
54736
- if (!fs26.existsSync(planPath2)) {
54908
+ const realPath = fs27.realpathSync(resolvedDir);
54909
+ const planPath2 = path40.join(realPath, ".swarm", "plan.json");
54910
+ if (!fs27.existsSync(planPath2)) {
54737
54911
  return {
54738
54912
  success: false,
54739
54913
  message: `Invalid working_directory: plan not found in "${realPath}"`,
@@ -54753,8 +54927,8 @@ async function executeDeclareScope(args2, fallbackDir) {
54753
54927
  }
54754
54928
  }
54755
54929
  const directory = normalizedDir ?? fallbackDir ?? process.cwd();
54756
- const planPath = path39.resolve(directory, ".swarm", "plan.json");
54757
- if (!fs26.existsSync(planPath)) {
54930
+ const planPath = path40.resolve(directory, ".swarm", "plan.json");
54931
+ if (!fs27.existsSync(planPath)) {
54758
54932
  return {
54759
54933
  success: false,
54760
54934
  message: "No plan found",
@@ -54763,7 +54937,7 @@ async function executeDeclareScope(args2, fallbackDir) {
54763
54937
  }
54764
54938
  let planContent;
54765
54939
  try {
54766
- planContent = JSON.parse(fs26.readFileSync(planPath, "utf-8"));
54940
+ planContent = JSON.parse(fs27.readFileSync(planPath, "utf-8"));
54767
54941
  } catch {
54768
54942
  return {
54769
54943
  success: false,
@@ -54843,20 +55017,20 @@ function validateBase(base) {
54843
55017
  function validatePaths(paths) {
54844
55018
  if (!paths)
54845
55019
  return null;
54846
- for (const path40 of paths) {
54847
- if (!path40 || path40.length === 0) {
55020
+ for (const path41 of paths) {
55021
+ if (!path41 || path41.length === 0) {
54848
55022
  return "empty path not allowed";
54849
55023
  }
54850
- if (path40.length > MAX_PATH_LENGTH) {
55024
+ if (path41.length > MAX_PATH_LENGTH) {
54851
55025
  return `path exceeds maximum length of ${MAX_PATH_LENGTH}`;
54852
55026
  }
54853
- if (SHELL_METACHARACTERS2.test(path40)) {
55027
+ if (SHELL_METACHARACTERS2.test(path41)) {
54854
55028
  return "path contains shell metacharacters";
54855
55029
  }
54856
- if (path40.startsWith("-")) {
55030
+ if (path41.startsWith("-")) {
54857
55031
  return 'path cannot start with "-" (option-like arguments not allowed)';
54858
55032
  }
54859
- if (CONTROL_CHAR_PATTERN2.test(path40)) {
55033
+ if (CONTROL_CHAR_PATTERN2.test(path41)) {
54860
55034
  return "path contains control characters";
54861
55035
  }
54862
55036
  }
@@ -54936,8 +55110,8 @@ var diff = tool({
54936
55110
  if (parts2.length >= 3) {
54937
55111
  const additions = parseInt(parts2[0], 10) || 0;
54938
55112
  const deletions = parseInt(parts2[1], 10) || 0;
54939
- const path40 = parts2[2];
54940
- files.push({ path: path40, additions, deletions });
55113
+ const path41 = parts2[2];
55114
+ files.push({ path: path41, additions, deletions });
54941
55115
  }
54942
55116
  }
54943
55117
  const contractChanges = [];
@@ -55166,8 +55340,8 @@ Use these as DOMAIN values when delegating to @sme.`;
55166
55340
  // src/tools/evidence-check.ts
55167
55341
  init_dist();
55168
55342
  init_create_tool();
55169
- import * as fs27 from "fs";
55170
- import * as path40 from "path";
55343
+ import * as fs28 from "fs";
55344
+ import * as path41 from "path";
55171
55345
  var MAX_FILE_SIZE_BYTES3 = 1024 * 1024;
55172
55346
  var MAX_EVIDENCE_FILES = 1000;
55173
55347
  var EVIDENCE_DIR2 = ".swarm/evidence";
@@ -55197,9 +55371,9 @@ function validateRequiredTypes(input) {
55197
55371
  return null;
55198
55372
  }
55199
55373
  function isPathWithinSwarm2(filePath, cwd) {
55200
- const normalizedCwd = path40.resolve(cwd);
55201
- const swarmPath = path40.join(normalizedCwd, ".swarm");
55202
- const normalizedPath = path40.resolve(filePath);
55374
+ const normalizedCwd = path41.resolve(cwd);
55375
+ const swarmPath = path41.join(normalizedCwd, ".swarm");
55376
+ const normalizedPath = path41.resolve(filePath);
55203
55377
  return normalizedPath.startsWith(swarmPath);
55204
55378
  }
55205
55379
  function parseCompletedTasks(planContent) {
@@ -55215,12 +55389,12 @@ function parseCompletedTasks(planContent) {
55215
55389
  }
55216
55390
  function readEvidenceFiles(evidenceDir, _cwd) {
55217
55391
  const evidence = [];
55218
- if (!fs27.existsSync(evidenceDir) || !fs27.statSync(evidenceDir).isDirectory()) {
55392
+ if (!fs28.existsSync(evidenceDir) || !fs28.statSync(evidenceDir).isDirectory()) {
55219
55393
  return evidence;
55220
55394
  }
55221
55395
  let files;
55222
55396
  try {
55223
- files = fs27.readdirSync(evidenceDir);
55397
+ files = fs28.readdirSync(evidenceDir);
55224
55398
  } catch {
55225
55399
  return evidence;
55226
55400
  }
@@ -55229,14 +55403,14 @@ function readEvidenceFiles(evidenceDir, _cwd) {
55229
55403
  if (!VALID_EVIDENCE_FILENAME_REGEX.test(filename)) {
55230
55404
  continue;
55231
55405
  }
55232
- const filePath = path40.join(evidenceDir, filename);
55406
+ const filePath = path41.join(evidenceDir, filename);
55233
55407
  try {
55234
- const resolvedPath = path40.resolve(filePath);
55235
- const evidenceDirResolved = path40.resolve(evidenceDir);
55408
+ const resolvedPath = path41.resolve(filePath);
55409
+ const evidenceDirResolved = path41.resolve(evidenceDir);
55236
55410
  if (!resolvedPath.startsWith(evidenceDirResolved)) {
55237
55411
  continue;
55238
55412
  }
55239
- const stat2 = fs27.lstatSync(filePath);
55413
+ const stat2 = fs28.lstatSync(filePath);
55240
55414
  if (!stat2.isFile()) {
55241
55415
  continue;
55242
55416
  }
@@ -55245,7 +55419,7 @@ function readEvidenceFiles(evidenceDir, _cwd) {
55245
55419
  }
55246
55420
  let fileStat;
55247
55421
  try {
55248
- fileStat = fs27.statSync(filePath);
55422
+ fileStat = fs28.statSync(filePath);
55249
55423
  if (fileStat.size > MAX_FILE_SIZE_BYTES3) {
55250
55424
  continue;
55251
55425
  }
@@ -55254,7 +55428,7 @@ function readEvidenceFiles(evidenceDir, _cwd) {
55254
55428
  }
55255
55429
  let content;
55256
55430
  try {
55257
- content = fs27.readFileSync(filePath, "utf-8");
55431
+ content = fs28.readFileSync(filePath, "utf-8");
55258
55432
  } catch {
55259
55433
  continue;
55260
55434
  }
@@ -55350,7 +55524,7 @@ var evidence_check = createSwarmTool({
55350
55524
  return JSON.stringify(errorResult, null, 2);
55351
55525
  }
55352
55526
  const requiredTypes = requiredTypesValue.split(",").map((t) => t.trim()).filter((t) => t.length > 0).map(normalizeEvidenceType);
55353
- const planPath = path40.join(cwd, PLAN_FILE);
55527
+ const planPath = path41.join(cwd, PLAN_FILE);
55354
55528
  if (!isPathWithinSwarm2(planPath, cwd)) {
55355
55529
  const errorResult = {
55356
55530
  error: "plan file path validation failed",
@@ -55364,7 +55538,7 @@ var evidence_check = createSwarmTool({
55364
55538
  }
55365
55539
  let planContent;
55366
55540
  try {
55367
- planContent = fs27.readFileSync(planPath, "utf-8");
55541
+ planContent = fs28.readFileSync(planPath, "utf-8");
55368
55542
  } catch {
55369
55543
  const result2 = {
55370
55544
  message: "No completed tasks found in plan.",
@@ -55382,7 +55556,7 @@ var evidence_check = createSwarmTool({
55382
55556
  };
55383
55557
  return JSON.stringify(result2, null, 2);
55384
55558
  }
55385
- const evidenceDir = path40.join(cwd, EVIDENCE_DIR2);
55559
+ const evidenceDir = path41.join(cwd, EVIDENCE_DIR2);
55386
55560
  const evidence = readEvidenceFiles(evidenceDir, cwd);
55387
55561
  const { tasksWithFullEvidence, gaps } = analyzeGaps(completedTasks, evidence, requiredTypes);
55388
55562
  const completeness = completedTasks.length > 0 ? Math.round(tasksWithFullEvidence.length / completedTasks.length * 100) / 100 : 1;
@@ -55399,8 +55573,8 @@ var evidence_check = createSwarmTool({
55399
55573
  // src/tools/file-extractor.ts
55400
55574
  init_tool();
55401
55575
  init_create_tool();
55402
- import * as fs28 from "fs";
55403
- import * as path41 from "path";
55576
+ import * as fs29 from "fs";
55577
+ import * as path42 from "path";
55404
55578
  var EXT_MAP = {
55405
55579
  python: ".py",
55406
55580
  py: ".py",
@@ -55462,8 +55636,8 @@ var extract_code_blocks = createSwarmTool({
55462
55636
  execute: async (args2, directory) => {
55463
55637
  const { content, output_dir, prefix } = args2;
55464
55638
  const targetDir = output_dir || directory;
55465
- if (!fs28.existsSync(targetDir)) {
55466
- fs28.mkdirSync(targetDir, { recursive: true });
55639
+ if (!fs29.existsSync(targetDir)) {
55640
+ fs29.mkdirSync(targetDir, { recursive: true });
55467
55641
  }
55468
55642
  if (!content) {
55469
55643
  return "Error: content is required";
@@ -55481,16 +55655,16 @@ var extract_code_blocks = createSwarmTool({
55481
55655
  if (prefix) {
55482
55656
  filename = `${prefix}_${filename}`;
55483
55657
  }
55484
- let filepath = path41.join(targetDir, filename);
55485
- const base = path41.basename(filepath, path41.extname(filepath));
55486
- const ext = path41.extname(filepath);
55658
+ let filepath = path42.join(targetDir, filename);
55659
+ const base = path42.basename(filepath, path42.extname(filepath));
55660
+ const ext = path42.extname(filepath);
55487
55661
  let counter = 1;
55488
- while (fs28.existsSync(filepath)) {
55489
- filepath = path41.join(targetDir, `${base}_${counter}${ext}`);
55662
+ while (fs29.existsSync(filepath)) {
55663
+ filepath = path42.join(targetDir, `${base}_${counter}${ext}`);
55490
55664
  counter++;
55491
55665
  }
55492
55666
  try {
55493
- fs28.writeFileSync(filepath, code.trim(), "utf-8");
55667
+ fs29.writeFileSync(filepath, code.trim(), "utf-8");
55494
55668
  savedFiles.push(filepath);
55495
55669
  } catch (error93) {
55496
55670
  errors5.push(`Failed to save ${filename}: ${error93 instanceof Error ? error93.message : String(error93)}`);
@@ -55603,8 +55777,8 @@ var gitingest = tool({
55603
55777
  });
55604
55778
  // src/tools/imports.ts
55605
55779
  init_dist();
55606
- import * as fs29 from "fs";
55607
- import * as path42 from "path";
55780
+ import * as fs30 from "fs";
55781
+ import * as path43 from "path";
55608
55782
  var MAX_FILE_PATH_LENGTH2 = 500;
55609
55783
  var MAX_SYMBOL_LENGTH = 256;
55610
55784
  var MAX_FILE_SIZE_BYTES4 = 1024 * 1024;
@@ -55658,7 +55832,7 @@ function validateSymbolInput(symbol3) {
55658
55832
  return null;
55659
55833
  }
55660
55834
  function isBinaryFile2(filePath, buffer) {
55661
- const ext = path42.extname(filePath).toLowerCase();
55835
+ const ext = path43.extname(filePath).toLowerCase();
55662
55836
  if (ext === ".json" || ext === ".md" || ext === ".txt") {
55663
55837
  return false;
55664
55838
  }
@@ -55682,15 +55856,15 @@ function parseImports(content, targetFile, targetSymbol) {
55682
55856
  const imports = [];
55683
55857
  let _resolvedTarget;
55684
55858
  try {
55685
- _resolvedTarget = path42.resolve(targetFile);
55859
+ _resolvedTarget = path43.resolve(targetFile);
55686
55860
  } catch {
55687
55861
  _resolvedTarget = targetFile;
55688
55862
  }
55689
- const targetBasename = path42.basename(targetFile, path42.extname(targetFile));
55863
+ const targetBasename = path43.basename(targetFile, path43.extname(targetFile));
55690
55864
  const targetWithExt = targetFile;
55691
55865
  const targetWithoutExt = targetFile.replace(/\.(ts|tsx|js|jsx|mjs|cjs)$/i, "");
55692
- const normalizedTargetWithExt = path42.normalize(targetWithExt).replace(/\\/g, "/");
55693
- const normalizedTargetWithoutExt = path42.normalize(targetWithoutExt).replace(/\\/g, "/");
55866
+ const normalizedTargetWithExt = path43.normalize(targetWithExt).replace(/\\/g, "/");
55867
+ const normalizedTargetWithoutExt = path43.normalize(targetWithoutExt).replace(/\\/g, "/");
55694
55868
  const importRegex = /import\s+(?:\{[\s\S]*?\}|(?:\*\s+as\s+\w+)|\w+)\s+from\s+['"`]([^'"`]+)['"`]|import\s+['"`]([^'"`]+)['"`]|require\s*\(\s*['"`]([^'"`]+)['"`]\s*\)/g;
55695
55869
  for (let match = importRegex.exec(content);match !== null; match = importRegex.exec(content)) {
55696
55870
  const modulePath = match[1] || match[2] || match[3];
@@ -55713,9 +55887,9 @@ function parseImports(content, targetFile, targetSymbol) {
55713
55887
  }
55714
55888
  const _normalizedModule = modulePath.replace(/^\.\//, "").replace(/^\.\.\\/, "../");
55715
55889
  let isMatch = false;
55716
- const _targetDir = path42.dirname(targetFile);
55717
- const targetExt = path42.extname(targetFile);
55718
- const targetBasenameNoExt = path42.basename(targetFile, targetExt);
55890
+ const _targetDir = path43.dirname(targetFile);
55891
+ const targetExt = path43.extname(targetFile);
55892
+ const targetBasenameNoExt = path43.basename(targetFile, targetExt);
55719
55893
  const moduleNormalized = modulePath.replace(/\\/g, "/").replace(/^\.\//, "");
55720
55894
  const moduleName = modulePath.split(/[/\\]/).pop() || "";
55721
55895
  const moduleNameNoExt = moduleName.replace(/\.(ts|tsx|js|jsx|mjs|cjs)$/i, "");
@@ -55772,7 +55946,7 @@ var SKIP_DIRECTORIES2 = new Set([
55772
55946
  function findSourceFiles(dir, files = [], stats = { skippedDirs: [], skippedFiles: 0, fileErrors: [] }) {
55773
55947
  let entries;
55774
55948
  try {
55775
- entries = fs29.readdirSync(dir);
55949
+ entries = fs30.readdirSync(dir);
55776
55950
  } catch (e) {
55777
55951
  stats.fileErrors.push({
55778
55952
  path: dir,
@@ -55783,13 +55957,13 @@ function findSourceFiles(dir, files = [], stats = { skippedDirs: [], skippedFile
55783
55957
  entries.sort((a, b) => a.toLowerCase().localeCompare(b.toLowerCase()));
55784
55958
  for (const entry of entries) {
55785
55959
  if (SKIP_DIRECTORIES2.has(entry)) {
55786
- stats.skippedDirs.push(path42.join(dir, entry));
55960
+ stats.skippedDirs.push(path43.join(dir, entry));
55787
55961
  continue;
55788
55962
  }
55789
- const fullPath = path42.join(dir, entry);
55963
+ const fullPath = path43.join(dir, entry);
55790
55964
  let stat2;
55791
55965
  try {
55792
- stat2 = fs29.statSync(fullPath);
55966
+ stat2 = fs30.statSync(fullPath);
55793
55967
  } catch (e) {
55794
55968
  stats.fileErrors.push({
55795
55969
  path: fullPath,
@@ -55800,7 +55974,7 @@ function findSourceFiles(dir, files = [], stats = { skippedDirs: [], skippedFile
55800
55974
  if (stat2.isDirectory()) {
55801
55975
  findSourceFiles(fullPath, files, stats);
55802
55976
  } else if (stat2.isFile()) {
55803
- const ext = path42.extname(fullPath).toLowerCase();
55977
+ const ext = path43.extname(fullPath).toLowerCase();
55804
55978
  if (SUPPORTED_EXTENSIONS.includes(ext)) {
55805
55979
  files.push(fullPath);
55806
55980
  }
@@ -55856,8 +56030,8 @@ var imports = tool({
55856
56030
  return JSON.stringify(errorResult, null, 2);
55857
56031
  }
55858
56032
  try {
55859
- const targetFile = path42.resolve(file3);
55860
- if (!fs29.existsSync(targetFile)) {
56033
+ const targetFile = path43.resolve(file3);
56034
+ if (!fs30.existsSync(targetFile)) {
55861
56035
  const errorResult = {
55862
56036
  error: `target file not found: ${file3}`,
55863
56037
  target: file3,
@@ -55867,7 +56041,7 @@ var imports = tool({
55867
56041
  };
55868
56042
  return JSON.stringify(errorResult, null, 2);
55869
56043
  }
55870
- const targetStat = fs29.statSync(targetFile);
56044
+ const targetStat = fs30.statSync(targetFile);
55871
56045
  if (!targetStat.isFile()) {
55872
56046
  const errorResult = {
55873
56047
  error: "target must be a file, not a directory",
@@ -55878,7 +56052,7 @@ var imports = tool({
55878
56052
  };
55879
56053
  return JSON.stringify(errorResult, null, 2);
55880
56054
  }
55881
- const baseDir = path42.dirname(targetFile);
56055
+ const baseDir = path43.dirname(targetFile);
55882
56056
  const scanStats = {
55883
56057
  skippedDirs: [],
55884
56058
  skippedFiles: 0,
@@ -55893,12 +56067,12 @@ var imports = tool({
55893
56067
  if (consumers.length >= MAX_CONSUMERS)
55894
56068
  break;
55895
56069
  try {
55896
- const stat2 = fs29.statSync(filePath);
56070
+ const stat2 = fs30.statSync(filePath);
55897
56071
  if (stat2.size > MAX_FILE_SIZE_BYTES4) {
55898
56072
  skippedFileCount++;
55899
56073
  continue;
55900
56074
  }
55901
- const buffer = fs29.readFileSync(filePath);
56075
+ const buffer = fs30.readFileSync(filePath);
55902
56076
  if (isBinaryFile2(filePath, buffer)) {
55903
56077
  skippedFileCount++;
55904
56078
  continue;
@@ -55963,7 +56137,7 @@ var imports = tool({
55963
56137
  });
55964
56138
  // src/tools/knowledge-query.ts
55965
56139
  init_dist();
55966
- import { existsSync as existsSync27 } from "fs";
56140
+ import { existsSync as existsSync28 } from "fs";
55967
56141
  init_create_tool();
55968
56142
  var DEFAULT_LIMIT = 10;
55969
56143
  var MAX_LESSON_LENGTH = 200;
@@ -56033,14 +56207,14 @@ function validateLimit(limit) {
56033
56207
  }
56034
56208
  async function readSwarmKnowledge(directory) {
56035
56209
  const swarmPath = resolveSwarmKnowledgePath(directory);
56036
- if (!existsSync27(swarmPath)) {
56210
+ if (!existsSync28(swarmPath)) {
56037
56211
  return [];
56038
56212
  }
56039
56213
  return readKnowledge(swarmPath);
56040
56214
  }
56041
56215
  async function readHiveKnowledge() {
56042
56216
  const hivePath = resolveHiveKnowledgePath();
56043
- if (!existsSync27(hivePath)) {
56217
+ if (!existsSync28(hivePath)) {
56044
56218
  return [];
56045
56219
  }
56046
56220
  return readKnowledge(hivePath);
@@ -56199,8 +56373,8 @@ init_dist();
56199
56373
  init_config();
56200
56374
  init_schema();
56201
56375
  init_manager();
56202
- import * as fs30 from "fs";
56203
- import * as path43 from "path";
56376
+ import * as fs31 from "fs";
56377
+ import * as path44 from "path";
56204
56378
  init_utils2();
56205
56379
  init_create_tool();
56206
56380
  function safeWarn(message, error93) {
@@ -56395,7 +56569,7 @@ async function executePhaseComplete(args2, workingDirectory) {
56395
56569
  }
56396
56570
  if (retroFound && retroEntry?.lessons_learned && retroEntry.lessons_learned.length > 0) {
56397
56571
  try {
56398
- const projectName = path43.basename(dir);
56572
+ const projectName = path44.basename(dir);
56399
56573
  const knowledgeConfig = {
56400
56574
  enabled: true,
56401
56575
  swarm_max_entries: 100,
@@ -56443,7 +56617,7 @@ async function executePhaseComplete(args2, workingDirectory) {
56443
56617
  if (agentsMissing.length > 0) {
56444
56618
  try {
56445
56619
  const planPath = validateSwarmPath(dir, "plan.json");
56446
- const planRaw = fs30.readFileSync(planPath, "utf-8");
56620
+ const planRaw = fs31.readFileSync(planPath, "utf-8");
56447
56621
  const plan = JSON.parse(planRaw);
56448
56622
  const targetPhase = plan.phases.find((p) => p.id === phase);
56449
56623
  if (targetPhase && targetPhase.tasks.length > 0 && targetPhase.tasks.every((t) => t.status === "completed")) {
@@ -56484,7 +56658,7 @@ async function executePhaseComplete(args2, workingDirectory) {
56484
56658
  };
56485
56659
  try {
56486
56660
  const eventsPath = validateSwarmPath(dir, "events.jsonl");
56487
- fs30.appendFileSync(eventsPath, `${JSON.stringify(event)}
56661
+ fs31.appendFileSync(eventsPath, `${JSON.stringify(event)}
56488
56662
  `, "utf-8");
56489
56663
  } catch (writeError) {
56490
56664
  warnings.push(`Warning: failed to write phase complete event: ${writeError instanceof Error ? writeError.message : String(writeError)}`);
@@ -56503,12 +56677,12 @@ async function executePhaseComplete(args2, workingDirectory) {
56503
56677
  }
56504
56678
  try {
56505
56679
  const planPath = validateSwarmPath(dir, "plan.json");
56506
- const planJson = fs30.readFileSync(planPath, "utf-8");
56680
+ const planJson = fs31.readFileSync(planPath, "utf-8");
56507
56681
  const plan = JSON.parse(planJson);
56508
56682
  const phaseObj = plan.phases.find((p) => p.id === phase);
56509
56683
  if (phaseObj) {
56510
56684
  phaseObj.status = "completed";
56511
- fs30.writeFileSync(planPath, `${JSON.stringify(plan, null, 2)}
56685
+ fs31.writeFileSync(planPath, `${JSON.stringify(plan, null, 2)}
56512
56686
  `, "utf-8");
56513
56687
  }
56514
56688
  } catch (error93) {
@@ -56558,8 +56732,8 @@ init_dist();
56558
56732
  init_discovery();
56559
56733
  init_utils();
56560
56734
  init_create_tool();
56561
- import * as fs31 from "fs";
56562
- import * as path44 from "path";
56735
+ import * as fs32 from "fs";
56736
+ import * as path45 from "path";
56563
56737
  var MAX_OUTPUT_BYTES5 = 52428800;
56564
56738
  var AUDIT_TIMEOUT_MS = 120000;
56565
56739
  function isValidEcosystem(value) {
@@ -56577,28 +56751,28 @@ function validateArgs3(args2) {
56577
56751
  function detectEcosystems(directory) {
56578
56752
  const ecosystems = [];
56579
56753
  const cwd = directory;
56580
- if (fs31.existsSync(path44.join(cwd, "package.json"))) {
56754
+ if (fs32.existsSync(path45.join(cwd, "package.json"))) {
56581
56755
  ecosystems.push("npm");
56582
56756
  }
56583
- if (fs31.existsSync(path44.join(cwd, "pyproject.toml")) || fs31.existsSync(path44.join(cwd, "requirements.txt"))) {
56757
+ if (fs32.existsSync(path45.join(cwd, "pyproject.toml")) || fs32.existsSync(path45.join(cwd, "requirements.txt"))) {
56584
56758
  ecosystems.push("pip");
56585
56759
  }
56586
- if (fs31.existsSync(path44.join(cwd, "Cargo.toml"))) {
56760
+ if (fs32.existsSync(path45.join(cwd, "Cargo.toml"))) {
56587
56761
  ecosystems.push("cargo");
56588
56762
  }
56589
- if (fs31.existsSync(path44.join(cwd, "go.mod"))) {
56763
+ if (fs32.existsSync(path45.join(cwd, "go.mod"))) {
56590
56764
  ecosystems.push("go");
56591
56765
  }
56592
56766
  try {
56593
- const files = fs31.readdirSync(cwd);
56767
+ const files = fs32.readdirSync(cwd);
56594
56768
  if (files.some((f) => f.endsWith(".csproj") || f.endsWith(".sln"))) {
56595
56769
  ecosystems.push("dotnet");
56596
56770
  }
56597
56771
  } catch {}
56598
- if (fs31.existsSync(path44.join(cwd, "Gemfile")) || fs31.existsSync(path44.join(cwd, "Gemfile.lock"))) {
56772
+ if (fs32.existsSync(path45.join(cwd, "Gemfile")) || fs32.existsSync(path45.join(cwd, "Gemfile.lock"))) {
56599
56773
  ecosystems.push("ruby");
56600
56774
  }
56601
- if (fs31.existsSync(path44.join(cwd, "pubspec.yaml"))) {
56775
+ if (fs32.existsSync(path45.join(cwd, "pubspec.yaml"))) {
56602
56776
  ecosystems.push("dart");
56603
56777
  }
56604
56778
  return ecosystems;
@@ -57660,8 +57834,8 @@ var SUPPORTED_PARSER_EXTENSIONS = new Set([
57660
57834
  ]);
57661
57835
  // src/tools/pre-check-batch.ts
57662
57836
  init_dist();
57663
- import * as fs34 from "fs";
57664
- import * as path47 from "path";
57837
+ import * as fs35 from "fs";
57838
+ import * as path48 from "path";
57665
57839
 
57666
57840
  // node_modules/yocto-queue/index.js
57667
57841
  class Node2 {
@@ -57828,8 +58002,8 @@ init_lint();
57828
58002
  init_manager();
57829
58003
 
57830
58004
  // src/quality/metrics.ts
57831
- import * as fs32 from "fs";
57832
- import * as path45 from "path";
58005
+ import * as fs33 from "fs";
58006
+ import * as path46 from "path";
57833
58007
  var MAX_FILE_SIZE_BYTES5 = 256 * 1024;
57834
58008
  var MIN_DUPLICATION_LINES = 10;
57835
58009
  function estimateCyclomaticComplexity(content) {
@@ -57867,11 +58041,11 @@ function estimateCyclomaticComplexity(content) {
57867
58041
  }
57868
58042
  function getComplexityForFile2(filePath) {
57869
58043
  try {
57870
- const stat2 = fs32.statSync(filePath);
58044
+ const stat2 = fs33.statSync(filePath);
57871
58045
  if (stat2.size > MAX_FILE_SIZE_BYTES5) {
57872
58046
  return null;
57873
58047
  }
57874
- const content = fs32.readFileSync(filePath, "utf-8");
58048
+ const content = fs33.readFileSync(filePath, "utf-8");
57875
58049
  return estimateCyclomaticComplexity(content);
57876
58050
  } catch {
57877
58051
  return null;
@@ -57881,8 +58055,8 @@ async function computeComplexityDelta(files, workingDir) {
57881
58055
  let totalComplexity = 0;
57882
58056
  const analyzedFiles = [];
57883
58057
  for (const file3 of files) {
57884
- const fullPath = path45.isAbsolute(file3) ? file3 : path45.join(workingDir, file3);
57885
- if (!fs32.existsSync(fullPath)) {
58058
+ const fullPath = path46.isAbsolute(file3) ? file3 : path46.join(workingDir, file3);
58059
+ if (!fs33.existsSync(fullPath)) {
57886
58060
  continue;
57887
58061
  }
57888
58062
  const complexity = getComplexityForFile2(fullPath);
@@ -58003,8 +58177,8 @@ function countGoExports(content) {
58003
58177
  }
58004
58178
  function getExportCountForFile(filePath) {
58005
58179
  try {
58006
- const content = fs32.readFileSync(filePath, "utf-8");
58007
- const ext = path45.extname(filePath).toLowerCase();
58180
+ const content = fs33.readFileSync(filePath, "utf-8");
58181
+ const ext = path46.extname(filePath).toLowerCase();
58008
58182
  switch (ext) {
58009
58183
  case ".ts":
58010
58184
  case ".tsx":
@@ -58030,8 +58204,8 @@ async function computePublicApiDelta(files, workingDir) {
58030
58204
  let totalExports = 0;
58031
58205
  const analyzedFiles = [];
58032
58206
  for (const file3 of files) {
58033
- const fullPath = path45.isAbsolute(file3) ? file3 : path45.join(workingDir, file3);
58034
- if (!fs32.existsSync(fullPath)) {
58207
+ const fullPath = path46.isAbsolute(file3) ? file3 : path46.join(workingDir, file3);
58208
+ if (!fs33.existsSync(fullPath)) {
58035
58209
  continue;
58036
58210
  }
58037
58211
  const exports = getExportCountForFile(fullPath);
@@ -58064,16 +58238,16 @@ async function computeDuplicationRatio(files, workingDir) {
58064
58238
  let duplicateLines = 0;
58065
58239
  const analyzedFiles = [];
58066
58240
  for (const file3 of files) {
58067
- const fullPath = path45.isAbsolute(file3) ? file3 : path45.join(workingDir, file3);
58068
- if (!fs32.existsSync(fullPath)) {
58241
+ const fullPath = path46.isAbsolute(file3) ? file3 : path46.join(workingDir, file3);
58242
+ if (!fs33.existsSync(fullPath)) {
58069
58243
  continue;
58070
58244
  }
58071
58245
  try {
58072
- const stat2 = fs32.statSync(fullPath);
58246
+ const stat2 = fs33.statSync(fullPath);
58073
58247
  if (stat2.size > MAX_FILE_SIZE_BYTES5) {
58074
58248
  continue;
58075
58249
  }
58076
- const content = fs32.readFileSync(fullPath, "utf-8");
58250
+ const content = fs33.readFileSync(fullPath, "utf-8");
58077
58251
  const lines = content.split(`
58078
58252
  `).filter((line) => line.trim().length > 0);
58079
58253
  if (lines.length < MIN_DUPLICATION_LINES) {
@@ -58097,8 +58271,8 @@ function countCodeLines(content) {
58097
58271
  return lines.length;
58098
58272
  }
58099
58273
  function isTestFile(filePath) {
58100
- const basename8 = path45.basename(filePath);
58101
- const _ext = path45.extname(filePath).toLowerCase();
58274
+ const basename8 = path46.basename(filePath);
58275
+ const _ext = path46.extname(filePath).toLowerCase();
58102
58276
  const testPatterns = [
58103
58277
  ".test.",
58104
58278
  ".spec.",
@@ -58179,8 +58353,8 @@ function matchGlobSegment(globSegments, pathSegments) {
58179
58353
  }
58180
58354
  return gIndex === globSegments.length && pIndex === pathSegments.length;
58181
58355
  }
58182
- function matchesGlobSegment(path46, glob) {
58183
- const normalizedPath = path46.replace(/\\/g, "/");
58356
+ function matchesGlobSegment(path47, glob) {
58357
+ const normalizedPath = path47.replace(/\\/g, "/");
58184
58358
  const normalizedGlob = glob.replace(/\\/g, "/");
58185
58359
  if (normalizedPath.includes("//")) {
58186
58360
  return false;
@@ -58211,8 +58385,8 @@ function simpleGlobToRegex2(glob) {
58211
58385
  function hasGlobstar(glob) {
58212
58386
  return glob.includes("**");
58213
58387
  }
58214
- function globMatches(path46, glob) {
58215
- const normalizedPath = path46.replace(/\\/g, "/");
58388
+ function globMatches(path47, glob) {
58389
+ const normalizedPath = path47.replace(/\\/g, "/");
58216
58390
  if (!glob || glob === "") {
58217
58391
  if (normalizedPath.includes("//")) {
58218
58392
  return false;
@@ -58248,31 +58422,31 @@ function shouldExcludeFile(filePath, excludeGlobs) {
58248
58422
  async function computeTestToCodeRatio(workingDir, enforceGlobs, excludeGlobs) {
58249
58423
  let testLines = 0;
58250
58424
  let codeLines = 0;
58251
- const srcDir = path45.join(workingDir, "src");
58252
- if (fs32.existsSync(srcDir)) {
58425
+ const srcDir = path46.join(workingDir, "src");
58426
+ if (fs33.existsSync(srcDir)) {
58253
58427
  await scanDirectoryForLines(srcDir, enforceGlobs, excludeGlobs, false, (lines) => {
58254
58428
  codeLines += lines;
58255
58429
  });
58256
58430
  }
58257
58431
  const possibleSrcDirs = ["lib", "app", "source", "core"];
58258
58432
  for (const dir of possibleSrcDirs) {
58259
- const dirPath = path45.join(workingDir, dir);
58260
- if (fs32.existsSync(dirPath)) {
58433
+ const dirPath = path46.join(workingDir, dir);
58434
+ if (fs33.existsSync(dirPath)) {
58261
58435
  await scanDirectoryForLines(dirPath, enforceGlobs, excludeGlobs, false, (lines) => {
58262
58436
  codeLines += lines;
58263
58437
  });
58264
58438
  }
58265
58439
  }
58266
- const testsDir = path45.join(workingDir, "tests");
58267
- if (fs32.existsSync(testsDir)) {
58440
+ const testsDir = path46.join(workingDir, "tests");
58441
+ if (fs33.existsSync(testsDir)) {
58268
58442
  await scanDirectoryForLines(testsDir, ["**"], ["node_modules", "dist"], true, (lines) => {
58269
58443
  testLines += lines;
58270
58444
  });
58271
58445
  }
58272
58446
  const possibleTestDirs = ["test", "__tests__", "specs"];
58273
58447
  for (const dir of possibleTestDirs) {
58274
- const dirPath = path45.join(workingDir, dir);
58275
- if (fs32.existsSync(dirPath) && dirPath !== testsDir) {
58448
+ const dirPath = path46.join(workingDir, dir);
58449
+ if (fs33.existsSync(dirPath) && dirPath !== testsDir) {
58276
58450
  await scanDirectoryForLines(dirPath, ["**"], ["node_modules", "dist"], true, (lines) => {
58277
58451
  testLines += lines;
58278
58452
  });
@@ -58284,9 +58458,9 @@ async function computeTestToCodeRatio(workingDir, enforceGlobs, excludeGlobs) {
58284
58458
  }
58285
58459
  async function scanDirectoryForLines(dirPath, includeGlobs, excludeGlobs, isTestScan, callback) {
58286
58460
  try {
58287
- const entries = fs32.readdirSync(dirPath, { withFileTypes: true });
58461
+ const entries = fs33.readdirSync(dirPath, { withFileTypes: true });
58288
58462
  for (const entry of entries) {
58289
- const fullPath = path45.join(dirPath, entry.name);
58463
+ const fullPath = path46.join(dirPath, entry.name);
58290
58464
  if (entry.isDirectory()) {
58291
58465
  if (entry.name === "node_modules" || entry.name === "dist" || entry.name === "build" || entry.name === ".git") {
58292
58466
  continue;
@@ -58294,7 +58468,7 @@ async function scanDirectoryForLines(dirPath, includeGlobs, excludeGlobs, isTest
58294
58468
  await scanDirectoryForLines(fullPath, includeGlobs, excludeGlobs, isTestScan, callback);
58295
58469
  } else if (entry.isFile()) {
58296
58470
  const relativePath = fullPath.replace(`${process.cwd()}/`, "");
58297
- const ext = path45.extname(entry.name).toLowerCase();
58471
+ const ext = path46.extname(entry.name).toLowerCase();
58298
58472
  const validExts = [
58299
58473
  ".ts",
58300
58474
  ".tsx",
@@ -58330,7 +58504,7 @@ async function scanDirectoryForLines(dirPath, includeGlobs, excludeGlobs, isTest
58330
58504
  continue;
58331
58505
  }
58332
58506
  try {
58333
- const content = fs32.readFileSync(fullPath, "utf-8");
58507
+ const content = fs33.readFileSync(fullPath, "utf-8");
58334
58508
  const lines = countCodeLines(content);
58335
58509
  callback(lines);
58336
58510
  } catch {}
@@ -58544,8 +58718,8 @@ async function qualityBudget(input, directory) {
58544
58718
  init_dist();
58545
58719
  init_manager();
58546
58720
  init_detector();
58547
- import * as fs33 from "fs";
58548
- import * as path46 from "path";
58721
+ import * as fs34 from "fs";
58722
+ import * as path47 from "path";
58549
58723
  import { extname as extname9 } from "path";
58550
58724
 
58551
58725
  // src/sast/rules/c.ts
@@ -59229,7 +59403,7 @@ function executeRulesSync(filePath, content, language) {
59229
59403
  }
59230
59404
 
59231
59405
  // src/sast/semgrep.ts
59232
- import { execFile as execFile2, execFileSync as execFileSync2, spawn } from "child_process";
59406
+ import { execFile as execFile2, execFileSync as execFileSync2, spawn as spawn2 } from "child_process";
59233
59407
  import { promisify as promisify2 } from "util";
59234
59408
  var _execFileAsync = promisify2(execFile2);
59235
59409
  var semgrepAvailableCache = null;
@@ -59294,7 +59468,7 @@ function mapSemgrepSeverity(severity) {
59294
59468
  }
59295
59469
  async function executeWithTimeout(command, args2, options) {
59296
59470
  return new Promise((resolve15) => {
59297
- const child = spawn(command, args2, {
59471
+ const child = spawn2(command, args2, {
59298
59472
  shell: false,
59299
59473
  cwd: options.cwd
59300
59474
  });
@@ -59412,17 +59586,17 @@ var SEVERITY_ORDER = {
59412
59586
  };
59413
59587
  function shouldSkipFile(filePath) {
59414
59588
  try {
59415
- const stats = fs33.statSync(filePath);
59589
+ const stats = fs34.statSync(filePath);
59416
59590
  if (stats.size > MAX_FILE_SIZE_BYTES6) {
59417
59591
  return { skip: true, reason: "file too large" };
59418
59592
  }
59419
59593
  if (stats.size === 0) {
59420
59594
  return { skip: true, reason: "empty file" };
59421
59595
  }
59422
- const fd = fs33.openSync(filePath, "r");
59596
+ const fd = fs34.openSync(filePath, "r");
59423
59597
  const buffer = Buffer.alloc(8192);
59424
- const bytesRead = fs33.readSync(fd, buffer, 0, 8192, 0);
59425
- fs33.closeSync(fd);
59598
+ const bytesRead = fs34.readSync(fd, buffer, 0, 8192, 0);
59599
+ fs34.closeSync(fd);
59426
59600
  if (bytesRead > 0) {
59427
59601
  let nullCount = 0;
59428
59602
  for (let i2 = 0;i2 < bytesRead; i2++) {
@@ -59461,7 +59635,7 @@ function countBySeverity(findings) {
59461
59635
  }
59462
59636
  function scanFileWithTierA(filePath, language) {
59463
59637
  try {
59464
- const content = fs33.readFileSync(filePath, "utf-8");
59638
+ const content = fs34.readFileSync(filePath, "utf-8");
59465
59639
  const findings = executeRulesSync(filePath, content, language);
59466
59640
  return findings.map((f) => ({
59467
59641
  rule_id: f.rule_id,
@@ -59508,8 +59682,8 @@ async function sastScan(input, directory, config3) {
59508
59682
  _filesSkipped++;
59509
59683
  continue;
59510
59684
  }
59511
- const resolvedPath = path46.isAbsolute(filePath) ? filePath : path46.resolve(directory, filePath);
59512
- if (!fs33.existsSync(resolvedPath)) {
59685
+ const resolvedPath = path47.isAbsolute(filePath) ? filePath : path47.resolve(directory, filePath);
59686
+ if (!fs34.existsSync(resolvedPath)) {
59513
59687
  _filesSkipped++;
59514
59688
  continue;
59515
59689
  }
@@ -59707,18 +59881,18 @@ function validatePath(inputPath, baseDir, workspaceDir) {
59707
59881
  let resolved;
59708
59882
  const isWinAbs = isWindowsAbsolutePath(inputPath);
59709
59883
  if (isWinAbs) {
59710
- resolved = path47.win32.resolve(inputPath);
59711
- } else if (path47.isAbsolute(inputPath)) {
59712
- resolved = path47.resolve(inputPath);
59884
+ resolved = path48.win32.resolve(inputPath);
59885
+ } else if (path48.isAbsolute(inputPath)) {
59886
+ resolved = path48.resolve(inputPath);
59713
59887
  } else {
59714
- resolved = path47.resolve(baseDir, inputPath);
59888
+ resolved = path48.resolve(baseDir, inputPath);
59715
59889
  }
59716
- const workspaceResolved = path47.resolve(workspaceDir);
59890
+ const workspaceResolved = path48.resolve(workspaceDir);
59717
59891
  let relative5;
59718
59892
  if (isWinAbs) {
59719
- relative5 = path47.win32.relative(workspaceResolved, resolved);
59893
+ relative5 = path48.win32.relative(workspaceResolved, resolved);
59720
59894
  } else {
59721
- relative5 = path47.relative(workspaceResolved, resolved);
59895
+ relative5 = path48.relative(workspaceResolved, resolved);
59722
59896
  }
59723
59897
  if (relative5.startsWith("..")) {
59724
59898
  return "path traversal detected";
@@ -59779,13 +59953,13 @@ async function runLintWrapped(files, directory, _config) {
59779
59953
  }
59780
59954
  async function runLintOnFiles(linter, files, workspaceDir) {
59781
59955
  const isWindows = process.platform === "win32";
59782
- const binDir = path47.join(workspaceDir, "node_modules", ".bin");
59956
+ const binDir = path48.join(workspaceDir, "node_modules", ".bin");
59783
59957
  const validatedFiles = [];
59784
59958
  for (const file3 of files) {
59785
59959
  if (typeof file3 !== "string") {
59786
59960
  continue;
59787
59961
  }
59788
- const resolvedPath = path47.resolve(file3);
59962
+ const resolvedPath = path48.resolve(file3);
59789
59963
  const validationError = validatePath(resolvedPath, workspaceDir, workspaceDir);
59790
59964
  if (validationError) {
59791
59965
  continue;
@@ -59803,10 +59977,10 @@ async function runLintOnFiles(linter, files, workspaceDir) {
59803
59977
  }
59804
59978
  let command;
59805
59979
  if (linter === "biome") {
59806
- const biomeBin = isWindows ? path47.join(binDir, "biome.EXE") : path47.join(binDir, "biome");
59980
+ const biomeBin = isWindows ? path48.join(binDir, "biome.EXE") : path48.join(binDir, "biome");
59807
59981
  command = [biomeBin, "check", ...validatedFiles];
59808
59982
  } else {
59809
- const eslintBin = isWindows ? path47.join(binDir, "eslint.cmd") : path47.join(binDir, "eslint");
59983
+ const eslintBin = isWindows ? path48.join(binDir, "eslint.cmd") : path48.join(binDir, "eslint");
59810
59984
  command = [eslintBin, ...validatedFiles];
59811
59985
  }
59812
59986
  try {
@@ -59943,7 +60117,7 @@ async function runSecretscanWithFiles(files, directory) {
59943
60117
  skippedFiles++;
59944
60118
  continue;
59945
60119
  }
59946
- const resolvedPath = path47.resolve(file3);
60120
+ const resolvedPath = path48.resolve(file3);
59947
60121
  const validationError = validatePath(resolvedPath, directory, directory);
59948
60122
  if (validationError) {
59949
60123
  skippedFiles++;
@@ -59961,14 +60135,14 @@ async function runSecretscanWithFiles(files, directory) {
59961
60135
  };
59962
60136
  }
59963
60137
  for (const file3 of validatedFiles) {
59964
- const ext = path47.extname(file3).toLowerCase();
60138
+ const ext = path48.extname(file3).toLowerCase();
59965
60139
  if (DEFAULT_EXCLUDE_EXTENSIONS2.has(ext)) {
59966
60140
  skippedFiles++;
59967
60141
  continue;
59968
60142
  }
59969
60143
  let stat2;
59970
60144
  try {
59971
- stat2 = fs34.statSync(file3);
60145
+ stat2 = fs35.statSync(file3);
59972
60146
  } catch {
59973
60147
  skippedFiles++;
59974
60148
  continue;
@@ -59979,7 +60153,7 @@ async function runSecretscanWithFiles(files, directory) {
59979
60153
  }
59980
60154
  let content;
59981
60155
  try {
59982
- const buffer = fs34.readFileSync(file3);
60156
+ const buffer = fs35.readFileSync(file3);
59983
60157
  if (buffer.includes(0)) {
59984
60158
  skippedFiles++;
59985
60159
  continue;
@@ -60120,7 +60294,7 @@ async function runPreCheckBatch(input, workspaceDir) {
60120
60294
  warn(`pre_check_batch: Invalid file path: ${file3}`);
60121
60295
  continue;
60122
60296
  }
60123
- changedFiles.push(path47.resolve(directory, file3));
60297
+ changedFiles.push(path48.resolve(directory, file3));
60124
60298
  }
60125
60299
  if (changedFiles.length === 0) {
60126
60300
  warn("pre_check_batch: No valid files after validation, skipping all tools (fail-closed)");
@@ -60271,7 +60445,7 @@ var pre_check_batch = createSwarmTool({
60271
60445
  };
60272
60446
  return JSON.stringify(errorResult, null, 2);
60273
60447
  }
60274
- const resolvedDirectory = path47.resolve(typedArgs.directory);
60448
+ const resolvedDirectory = path48.resolve(typedArgs.directory);
60275
60449
  const workspaceAnchor = resolvedDirectory;
60276
60450
  const dirError = validateDirectory3(resolvedDirectory, workspaceAnchor);
60277
60451
  if (dirError) {
@@ -60378,8 +60552,8 @@ ${paginatedContent}`;
60378
60552
  init_tool();
60379
60553
  init_manager2();
60380
60554
  init_create_tool();
60381
- import * as fs35 from "fs";
60382
- import * as path48 from "path";
60555
+ import * as fs36 from "fs";
60556
+ import * as path49 from "path";
60383
60557
  function detectPlaceholderContent(args2) {
60384
60558
  const issues = [];
60385
60559
  const placeholderPattern = /^\[\w[\w\s]*\]$/;
@@ -60483,19 +60657,19 @@ async function executeSavePlan(args2, fallbackDir) {
60483
60657
  try {
60484
60658
  await savePlan(dir, plan);
60485
60659
  try {
60486
- const markerPath = path48.join(dir, ".swarm", ".plan-write-marker");
60660
+ const markerPath = path49.join(dir, ".swarm", ".plan-write-marker");
60487
60661
  const marker = JSON.stringify({
60488
60662
  source: "save_plan",
60489
60663
  timestamp: new Date().toISOString(),
60490
60664
  phases_count: plan.phases.length,
60491
60665
  tasks_count: tasksCount
60492
60666
  });
60493
- await fs35.promises.writeFile(markerPath, marker, "utf8");
60667
+ await fs36.promises.writeFile(markerPath, marker, "utf8");
60494
60668
  } catch {}
60495
60669
  return {
60496
60670
  success: true,
60497
60671
  message: "Plan saved successfully",
60498
- plan_path: path48.join(dir, ".swarm", "plan.json"),
60672
+ plan_path: path49.join(dir, ".swarm", "plan.json"),
60499
60673
  phases_count: plan.phases.length,
60500
60674
  tasks_count: tasksCount
60501
60675
  };
@@ -60533,8 +60707,8 @@ var save_plan = createSwarmTool({
60533
60707
  // src/tools/sbom-generate.ts
60534
60708
  init_dist();
60535
60709
  init_manager();
60536
- import * as fs36 from "fs";
60537
- import * as path49 from "path";
60710
+ import * as fs37 from "fs";
60711
+ import * as path50 from "path";
60538
60712
 
60539
60713
  // src/sbom/detectors/index.ts
60540
60714
  init_utils();
@@ -61228,8 +61402,8 @@ function parsePackageResolved(content) {
61228
61402
  const pins = resolved.pins || [];
61229
61403
  for (const pin of pins) {
61230
61404
  const identity = pin.identity || pin.package || "";
61231
- const state = pin.state || {};
61232
- const version3 = state.version || state.revision || "";
61405
+ const state2 = pin.state || {};
61406
+ const version3 = state2.version || state2.revision || "";
61233
61407
  let org = "";
61234
61408
  const location = pin.location || "";
61235
61409
  const orgMatch = location.match(/github\.com\/([^/]+)\//);
@@ -61380,9 +61554,9 @@ function findManifestFiles(rootDir) {
61380
61554
  const patterns = [...new Set(allDetectors.flatMap((d) => d.patterns))];
61381
61555
  function searchDir(dir) {
61382
61556
  try {
61383
- const entries = fs36.readdirSync(dir, { withFileTypes: true });
61557
+ const entries = fs37.readdirSync(dir, { withFileTypes: true });
61384
61558
  for (const entry of entries) {
61385
- const fullPath = path49.join(dir, entry.name);
61559
+ const fullPath = path50.join(dir, entry.name);
61386
61560
  if (entry.name.startsWith(".") || entry.name === "node_modules" || entry.name === "dist" || entry.name === "build" || entry.name === "target") {
61387
61561
  continue;
61388
61562
  }
@@ -61391,7 +61565,7 @@ function findManifestFiles(rootDir) {
61391
61565
  } else if (entry.isFile()) {
61392
61566
  for (const pattern of patterns) {
61393
61567
  if (simpleGlobToRegex(pattern).test(entry.name)) {
61394
- manifestFiles.push(path49.relative(rootDir, fullPath));
61568
+ manifestFiles.push(path50.relative(rootDir, fullPath));
61395
61569
  break;
61396
61570
  }
61397
61571
  }
@@ -61407,13 +61581,13 @@ function findManifestFilesInDirs(directories, workingDir) {
61407
61581
  const patterns = [...new Set(allDetectors.flatMap((d) => d.patterns))];
61408
61582
  for (const dir of directories) {
61409
61583
  try {
61410
- const entries = fs36.readdirSync(dir, { withFileTypes: true });
61584
+ const entries = fs37.readdirSync(dir, { withFileTypes: true });
61411
61585
  for (const entry of entries) {
61412
- const fullPath = path49.join(dir, entry.name);
61586
+ const fullPath = path50.join(dir, entry.name);
61413
61587
  if (entry.isFile()) {
61414
61588
  for (const pattern of patterns) {
61415
61589
  if (simpleGlobToRegex(pattern).test(entry.name)) {
61416
- found.push(path49.relative(workingDir, fullPath));
61590
+ found.push(path50.relative(workingDir, fullPath));
61417
61591
  break;
61418
61592
  }
61419
61593
  }
@@ -61426,11 +61600,11 @@ function findManifestFilesInDirs(directories, workingDir) {
61426
61600
  function getDirectoriesFromChangedFiles(changedFiles, workingDir) {
61427
61601
  const dirs = new Set;
61428
61602
  for (const file3 of changedFiles) {
61429
- let currentDir = path49.dirname(file3);
61603
+ let currentDir = path50.dirname(file3);
61430
61604
  while (true) {
61431
- if (currentDir && currentDir !== "." && currentDir !== path49.sep) {
61432
- dirs.add(path49.join(workingDir, currentDir));
61433
- const parent = path49.dirname(currentDir);
61605
+ if (currentDir && currentDir !== "." && currentDir !== path50.sep) {
61606
+ dirs.add(path50.join(workingDir, currentDir));
61607
+ const parent = path50.dirname(currentDir);
61434
61608
  if (parent === currentDir)
61435
61609
  break;
61436
61610
  currentDir = parent;
@@ -61444,7 +61618,7 @@ function getDirectoriesFromChangedFiles(changedFiles, workingDir) {
61444
61618
  }
61445
61619
  function ensureOutputDir(outputDir) {
61446
61620
  try {
61447
- fs36.mkdirSync(outputDir, { recursive: true });
61621
+ fs37.mkdirSync(outputDir, { recursive: true });
61448
61622
  } catch (error93) {
61449
61623
  if (!error93 || error93.code !== "EEXIST") {
61450
61624
  throw error93;
@@ -61514,7 +61688,7 @@ var sbom_generate = createSwarmTool({
61514
61688
  const changedFiles = obj.changed_files;
61515
61689
  const relativeOutputDir = obj.output_dir || DEFAULT_OUTPUT_DIR;
61516
61690
  const workingDir = directory;
61517
- const outputDir = path49.isAbsolute(relativeOutputDir) ? relativeOutputDir : path49.join(workingDir, relativeOutputDir);
61691
+ const outputDir = path50.isAbsolute(relativeOutputDir) ? relativeOutputDir : path50.join(workingDir, relativeOutputDir);
61518
61692
  let manifestFiles = [];
61519
61693
  if (scope === "all") {
61520
61694
  manifestFiles = findManifestFiles(workingDir);
@@ -61537,11 +61711,11 @@ var sbom_generate = createSwarmTool({
61537
61711
  const processedFiles = [];
61538
61712
  for (const manifestFile of manifestFiles) {
61539
61713
  try {
61540
- const fullPath = path49.isAbsolute(manifestFile) ? manifestFile : path49.join(workingDir, manifestFile);
61541
- if (!fs36.existsSync(fullPath)) {
61714
+ const fullPath = path50.isAbsolute(manifestFile) ? manifestFile : path50.join(workingDir, manifestFile);
61715
+ if (!fs37.existsSync(fullPath)) {
61542
61716
  continue;
61543
61717
  }
61544
- const content = fs36.readFileSync(fullPath, "utf-8");
61718
+ const content = fs37.readFileSync(fullPath, "utf-8");
61545
61719
  const components = detectComponents(manifestFile, content);
61546
61720
  processedFiles.push(manifestFile);
61547
61721
  if (components.length > 0) {
@@ -61554,8 +61728,8 @@ var sbom_generate = createSwarmTool({
61554
61728
  const bom = generateCycloneDX(allComponents);
61555
61729
  const bomJson = serializeCycloneDX(bom);
61556
61730
  const filename = generateSbomFilename();
61557
- const outputPath = path49.join(outputDir, filename);
61558
- fs36.writeFileSync(outputPath, bomJson, "utf-8");
61731
+ const outputPath = path50.join(outputDir, filename);
61732
+ fs37.writeFileSync(outputPath, bomJson, "utf-8");
61559
61733
  const verdict = processedFiles.length > 0 ? "pass" : "pass";
61560
61734
  try {
61561
61735
  const timestamp = new Date().toISOString();
@@ -61597,8 +61771,8 @@ var sbom_generate = createSwarmTool({
61597
61771
  // src/tools/schema-drift.ts
61598
61772
  init_dist();
61599
61773
  init_create_tool();
61600
- import * as fs37 from "fs";
61601
- import * as path50 from "path";
61774
+ import * as fs38 from "fs";
61775
+ import * as path51 from "path";
61602
61776
  var SPEC_CANDIDATES = [
61603
61777
  "openapi.json",
61604
61778
  "openapi.yaml",
@@ -61630,28 +61804,28 @@ function normalizePath2(p) {
61630
61804
  }
61631
61805
  function discoverSpecFile(cwd, specFileArg) {
61632
61806
  if (specFileArg) {
61633
- const resolvedPath = path50.resolve(cwd, specFileArg);
61634
- const normalizedCwd = cwd.endsWith(path50.sep) ? cwd : cwd + path50.sep;
61807
+ const resolvedPath = path51.resolve(cwd, specFileArg);
61808
+ const normalizedCwd = cwd.endsWith(path51.sep) ? cwd : cwd + path51.sep;
61635
61809
  if (!resolvedPath.startsWith(normalizedCwd) && resolvedPath !== cwd) {
61636
61810
  throw new Error("Invalid spec_file: path traversal detected");
61637
61811
  }
61638
- const ext = path50.extname(resolvedPath).toLowerCase();
61812
+ const ext = path51.extname(resolvedPath).toLowerCase();
61639
61813
  if (!ALLOWED_EXTENSIONS.includes(ext)) {
61640
61814
  throw new Error(`Invalid spec_file: must end in .json, .yaml, or .yml, got ${ext}`);
61641
61815
  }
61642
- const stats = fs37.statSync(resolvedPath);
61816
+ const stats = fs38.statSync(resolvedPath);
61643
61817
  if (stats.size > MAX_SPEC_SIZE) {
61644
61818
  throw new Error(`Invalid spec_file: file exceeds ${MAX_SPEC_SIZE / 1024 / 1024}MB limit`);
61645
61819
  }
61646
- if (!fs37.existsSync(resolvedPath)) {
61820
+ if (!fs38.existsSync(resolvedPath)) {
61647
61821
  throw new Error(`Spec file not found: ${resolvedPath}`);
61648
61822
  }
61649
61823
  return resolvedPath;
61650
61824
  }
61651
61825
  for (const candidate of SPEC_CANDIDATES) {
61652
- const candidatePath = path50.resolve(cwd, candidate);
61653
- if (fs37.existsSync(candidatePath)) {
61654
- const stats = fs37.statSync(candidatePath);
61826
+ const candidatePath = path51.resolve(cwd, candidate);
61827
+ if (fs38.existsSync(candidatePath)) {
61828
+ const stats = fs38.statSync(candidatePath);
61655
61829
  if (stats.size <= MAX_SPEC_SIZE) {
61656
61830
  return candidatePath;
61657
61831
  }
@@ -61660,8 +61834,8 @@ function discoverSpecFile(cwd, specFileArg) {
61660
61834
  return null;
61661
61835
  }
61662
61836
  function parseSpec(specFile) {
61663
- const content = fs37.readFileSync(specFile, "utf-8");
61664
- const ext = path50.extname(specFile).toLowerCase();
61837
+ const content = fs38.readFileSync(specFile, "utf-8");
61838
+ const ext = path51.extname(specFile).toLowerCase();
61665
61839
  if (ext === ".json") {
61666
61840
  return parseJsonSpec(content);
61667
61841
  }
@@ -61732,12 +61906,12 @@ function extractRoutes(cwd) {
61732
61906
  function walkDir(dir) {
61733
61907
  let entries;
61734
61908
  try {
61735
- entries = fs37.readdirSync(dir, { withFileTypes: true });
61909
+ entries = fs38.readdirSync(dir, { withFileTypes: true });
61736
61910
  } catch {
61737
61911
  return;
61738
61912
  }
61739
61913
  for (const entry of entries) {
61740
- const fullPath = path50.join(dir, entry.name);
61914
+ const fullPath = path51.join(dir, entry.name);
61741
61915
  if (entry.isSymbolicLink()) {
61742
61916
  continue;
61743
61917
  }
@@ -61747,7 +61921,7 @@ function extractRoutes(cwd) {
61747
61921
  }
61748
61922
  walkDir(fullPath);
61749
61923
  } else if (entry.isFile()) {
61750
- const ext = path50.extname(entry.name).toLowerCase();
61924
+ const ext = path51.extname(entry.name).toLowerCase();
61751
61925
  const baseName = entry.name.toLowerCase();
61752
61926
  if (![".ts", ".js", ".mjs"].includes(ext)) {
61753
61927
  continue;
@@ -61765,7 +61939,7 @@ function extractRoutes(cwd) {
61765
61939
  }
61766
61940
  function extractRoutesFromFile(filePath) {
61767
61941
  const routes = [];
61768
- const content = fs37.readFileSync(filePath, "utf-8");
61942
+ const content = fs38.readFileSync(filePath, "utf-8");
61769
61943
  const lines = content.split(/\r?\n/);
61770
61944
  const expressRegex = /(?:app|router|server|express)\.(get|post|put|patch|delete|options|head)\s*\(\s*['"`]([^'"`]+)['"`]/g;
61771
61945
  const flaskRegex = /@(?:app|blueprint|bp)\.route\s*\(\s*['"]([^'"]+)['"]/g;
@@ -61916,8 +62090,8 @@ init_secretscan();
61916
62090
  // src/tools/symbols.ts
61917
62091
  init_tool();
61918
62092
  init_create_tool();
61919
- import * as fs38 from "fs";
61920
- import * as path51 from "path";
62093
+ import * as fs39 from "fs";
62094
+ import * as path52 from "path";
61921
62095
  var MAX_FILE_SIZE_BYTES7 = 1024 * 1024;
61922
62096
  var WINDOWS_RESERVED_NAMES = /^(con|prn|aux|nul|com[1-9]|lpt[1-9])(\.|:|$)/i;
61923
62097
  function containsControlCharacters(str) {
@@ -61946,11 +62120,11 @@ function containsWindowsAttacks(str) {
61946
62120
  }
61947
62121
  function isPathInWorkspace(filePath, workspace) {
61948
62122
  try {
61949
- const resolvedPath = path51.resolve(workspace, filePath);
61950
- const realWorkspace = fs38.realpathSync(workspace);
61951
- const realResolvedPath = fs38.realpathSync(resolvedPath);
61952
- const relativePath = path51.relative(realWorkspace, realResolvedPath);
61953
- if (relativePath.startsWith("..") || path51.isAbsolute(relativePath)) {
62123
+ const resolvedPath = path52.resolve(workspace, filePath);
62124
+ const realWorkspace = fs39.realpathSync(workspace);
62125
+ const realResolvedPath = fs39.realpathSync(resolvedPath);
62126
+ const relativePath = path52.relative(realWorkspace, realResolvedPath);
62127
+ if (relativePath.startsWith("..") || path52.isAbsolute(relativePath)) {
61954
62128
  return false;
61955
62129
  }
61956
62130
  return true;
@@ -61962,17 +62136,17 @@ function validatePathForRead(filePath, workspace) {
61962
62136
  return isPathInWorkspace(filePath, workspace);
61963
62137
  }
61964
62138
  function extractTSSymbols(filePath, cwd) {
61965
- const fullPath = path51.join(cwd, filePath);
62139
+ const fullPath = path52.join(cwd, filePath);
61966
62140
  if (!validatePathForRead(fullPath, cwd)) {
61967
62141
  return [];
61968
62142
  }
61969
62143
  let content;
61970
62144
  try {
61971
- const stats = fs38.statSync(fullPath);
62145
+ const stats = fs39.statSync(fullPath);
61972
62146
  if (stats.size > MAX_FILE_SIZE_BYTES7) {
61973
62147
  throw new Error(`File too large: ${stats.size} bytes (max: ${MAX_FILE_SIZE_BYTES7})`);
61974
62148
  }
61975
- content = fs38.readFileSync(fullPath, "utf-8");
62149
+ content = fs39.readFileSync(fullPath, "utf-8");
61976
62150
  } catch {
61977
62151
  return [];
61978
62152
  }
@@ -62114,17 +62288,17 @@ function extractTSSymbols(filePath, cwd) {
62114
62288
  });
62115
62289
  }
62116
62290
  function extractPythonSymbols(filePath, cwd) {
62117
- const fullPath = path51.join(cwd, filePath);
62291
+ const fullPath = path52.join(cwd, filePath);
62118
62292
  if (!validatePathForRead(fullPath, cwd)) {
62119
62293
  return [];
62120
62294
  }
62121
62295
  let content;
62122
62296
  try {
62123
- const stats = fs38.statSync(fullPath);
62297
+ const stats = fs39.statSync(fullPath);
62124
62298
  if (stats.size > MAX_FILE_SIZE_BYTES7) {
62125
62299
  throw new Error(`File too large: ${stats.size} bytes (max: ${MAX_FILE_SIZE_BYTES7})`);
62126
62300
  }
62127
- content = fs38.readFileSync(fullPath, "utf-8");
62301
+ content = fs39.readFileSync(fullPath, "utf-8");
62128
62302
  } catch {
62129
62303
  return [];
62130
62304
  }
@@ -62197,7 +62371,7 @@ var symbols = createSwarmTool({
62197
62371
  }, null, 2);
62198
62372
  }
62199
62373
  const cwd = directory;
62200
- const ext = path51.extname(file3);
62374
+ const ext = path52.extname(file3);
62201
62375
  if (containsControlCharacters(file3)) {
62202
62376
  return JSON.stringify({
62203
62377
  file: file3,
@@ -62268,8 +62442,8 @@ init_test_runner();
62268
62442
  init_dist();
62269
62443
  init_utils();
62270
62444
  init_create_tool();
62271
- import * as fs39 from "fs";
62272
- import * as path52 from "path";
62445
+ import * as fs40 from "fs";
62446
+ import * as path53 from "path";
62273
62447
  var MAX_TEXT_LENGTH = 200;
62274
62448
  var MAX_FILE_SIZE_BYTES8 = 1024 * 1024;
62275
62449
  var SUPPORTED_EXTENSIONS2 = new Set([
@@ -62340,9 +62514,9 @@ function validatePathsInput(paths, cwd) {
62340
62514
  return { error: "paths contains path traversal", resolvedPath: null };
62341
62515
  }
62342
62516
  try {
62343
- const resolvedPath = path52.resolve(paths);
62344
- const normalizedCwd = path52.resolve(cwd);
62345
- const normalizedResolved = path52.resolve(resolvedPath);
62517
+ const resolvedPath = path53.resolve(paths);
62518
+ const normalizedCwd = path53.resolve(cwd);
62519
+ const normalizedResolved = path53.resolve(resolvedPath);
62346
62520
  if (!normalizedResolved.startsWith(normalizedCwd)) {
62347
62521
  return {
62348
62522
  error: "paths must be within the current working directory",
@@ -62358,13 +62532,13 @@ function validatePathsInput(paths, cwd) {
62358
62532
  }
62359
62533
  }
62360
62534
  function isSupportedExtension(filePath) {
62361
- const ext = path52.extname(filePath).toLowerCase();
62535
+ const ext = path53.extname(filePath).toLowerCase();
62362
62536
  return SUPPORTED_EXTENSIONS2.has(ext);
62363
62537
  }
62364
62538
  function findSourceFiles2(dir, files = []) {
62365
62539
  let entries;
62366
62540
  try {
62367
- entries = fs39.readdirSync(dir);
62541
+ entries = fs40.readdirSync(dir);
62368
62542
  } catch {
62369
62543
  return files;
62370
62544
  }
@@ -62373,10 +62547,10 @@ function findSourceFiles2(dir, files = []) {
62373
62547
  if (SKIP_DIRECTORIES3.has(entry)) {
62374
62548
  continue;
62375
62549
  }
62376
- const fullPath = path52.join(dir, entry);
62550
+ const fullPath = path53.join(dir, entry);
62377
62551
  let stat2;
62378
62552
  try {
62379
- stat2 = fs39.statSync(fullPath);
62553
+ stat2 = fs40.statSync(fullPath);
62380
62554
  } catch {
62381
62555
  continue;
62382
62556
  }
@@ -62469,7 +62643,7 @@ var todo_extract = createSwarmTool({
62469
62643
  return JSON.stringify(errorResult, null, 2);
62470
62644
  }
62471
62645
  const scanPath = resolvedPath;
62472
- if (!fs39.existsSync(scanPath)) {
62646
+ if (!fs40.existsSync(scanPath)) {
62473
62647
  const errorResult = {
62474
62648
  error: `path not found: ${pathsInput}`,
62475
62649
  total: 0,
@@ -62479,13 +62653,13 @@ var todo_extract = createSwarmTool({
62479
62653
  return JSON.stringify(errorResult, null, 2);
62480
62654
  }
62481
62655
  const filesToScan = [];
62482
- const stat2 = fs39.statSync(scanPath);
62656
+ const stat2 = fs40.statSync(scanPath);
62483
62657
  if (stat2.isFile()) {
62484
62658
  if (isSupportedExtension(scanPath)) {
62485
62659
  filesToScan.push(scanPath);
62486
62660
  } else {
62487
62661
  const errorResult = {
62488
- error: `unsupported file extension: ${path52.extname(scanPath)}`,
62662
+ error: `unsupported file extension: ${path53.extname(scanPath)}`,
62489
62663
  total: 0,
62490
62664
  byPriority: { high: 0, medium: 0, low: 0 },
62491
62665
  entries: []
@@ -62498,11 +62672,11 @@ var todo_extract = createSwarmTool({
62498
62672
  const allEntries = [];
62499
62673
  for (const filePath of filesToScan) {
62500
62674
  try {
62501
- const fileStat = fs39.statSync(filePath);
62675
+ const fileStat = fs40.statSync(filePath);
62502
62676
  if (fileStat.size > MAX_FILE_SIZE_BYTES8) {
62503
62677
  continue;
62504
62678
  }
62505
- const content = fs39.readFileSync(filePath, "utf-8");
62679
+ const content = fs40.readFileSync(filePath, "utf-8");
62506
62680
  const entries = parseTodoComments(content, filePath, tagsSet);
62507
62681
  allEntries.push(...entries);
62508
62682
  } catch {}
@@ -62530,18 +62704,18 @@ var todo_extract = createSwarmTool({
62530
62704
  // src/tools/update-task-status.ts
62531
62705
  init_tool();
62532
62706
  init_schema();
62533
- import * as fs41 from "fs";
62534
- import * as path54 from "path";
62707
+ import * as fs42 from "fs";
62708
+ import * as path55 from "path";
62535
62709
 
62536
62710
  // src/hooks/diff-scope.ts
62537
- import * as fs40 from "fs";
62538
- import * as path53 from "path";
62711
+ import * as fs41 from "fs";
62712
+ import * as path54 from "path";
62539
62713
  function getDeclaredScope(taskId, directory) {
62540
62714
  try {
62541
- const planPath = path53.join(directory, ".swarm", "plan.json");
62542
- if (!fs40.existsSync(planPath))
62715
+ const planPath = path54.join(directory, ".swarm", "plan.json");
62716
+ if (!fs41.existsSync(planPath))
62543
62717
  return null;
62544
- const raw = fs40.readFileSync(planPath, "utf-8");
62718
+ const raw = fs41.readFileSync(planPath, "utf-8");
62545
62719
  const plan = JSON.parse(raw);
62546
62720
  for (const phase of plan.phases ?? []) {
62547
62721
  for (const task of phase.tasks ?? []) {
@@ -62653,7 +62827,7 @@ var TIER_3_PATTERNS = [
62653
62827
  ];
62654
62828
  function matchesTier3Pattern(files) {
62655
62829
  for (const file3 of files) {
62656
- const fileName = path54.basename(file3);
62830
+ const fileName = path55.basename(file3);
62657
62831
  for (const pattern of TIER_3_PATTERNS) {
62658
62832
  if (pattern.test(fileName)) {
62659
62833
  return true;
@@ -62675,8 +62849,8 @@ function checkReviewerGate(taskId, workingDirectory) {
62675
62849
  if (hasActiveTurboMode2()) {
62676
62850
  const resolvedDir2 = workingDirectory ?? process.cwd();
62677
62851
  try {
62678
- const planPath = path54.join(resolvedDir2, ".swarm", "plan.json");
62679
- const planRaw = fs41.readFileSync(planPath, "utf-8");
62852
+ const planPath = path55.join(resolvedDir2, ".swarm", "plan.json");
62853
+ const planRaw = fs42.readFileSync(planPath, "utf-8");
62680
62854
  const plan = JSON.parse(planRaw);
62681
62855
  for (const planPhase of plan.phases ?? []) {
62682
62856
  for (const task of planPhase.tasks ?? []) {
@@ -62695,8 +62869,8 @@ function checkReviewerGate(taskId, workingDirectory) {
62695
62869
  }
62696
62870
  const resolvedDir = workingDirectory ?? process.cwd();
62697
62871
  try {
62698
- const evidencePath = path54.join(resolvedDir, ".swarm", "evidence", `${taskId}.json`);
62699
- const raw = fs41.readFileSync(evidencePath, "utf-8");
62872
+ const evidencePath = path55.join(resolvedDir, ".swarm", "evidence", `${taskId}.json`);
62873
+ const raw = fs42.readFileSync(evidencePath, "utf-8");
62700
62874
  const evidence = JSON.parse(raw);
62701
62875
  if (evidence?.required_gates && Array.isArray(evidence.required_gates) && evidence?.gates) {
62702
62876
  const allGatesMet = evidence.required_gates.every((gate) => evidence.gates[gate] != null);
@@ -62719,8 +62893,8 @@ function checkReviewerGate(taskId, workingDirectory) {
62719
62893
  continue;
62720
62894
  }
62721
62895
  validSessionCount++;
62722
- const state = getTaskState(session, taskId);
62723
- if (state === "tests_run" || state === "complete") {
62896
+ const state2 = getTaskState(session, taskId);
62897
+ if (state2 === "tests_run" || state2 === "complete") {
62724
62898
  return { blocked: false, reason: "" };
62725
62899
  }
62726
62900
  }
@@ -62731,13 +62905,13 @@ function checkReviewerGate(taskId, workingDirectory) {
62731
62905
  for (const [sessionId, session] of swarmState.agentSessions) {
62732
62906
  if (!(session.taskWorkflowStates instanceof Map))
62733
62907
  continue;
62734
- const state = getTaskState(session, taskId);
62735
- stateEntries.push(`${sessionId}: ${state}`);
62908
+ const state2 = getTaskState(session, taskId);
62909
+ stateEntries.push(`${sessionId}: ${state2}`);
62736
62910
  }
62737
62911
  try {
62738
62912
  const resolvedDir2 = workingDirectory ?? process.cwd();
62739
- const planPath = path54.join(resolvedDir2, ".swarm", "plan.json");
62740
- const planRaw = fs41.readFileSync(planPath, "utf-8");
62913
+ const planPath = path55.join(resolvedDir2, ".swarm", "plan.json");
62914
+ const planRaw = fs42.readFileSync(planPath, "utf-8");
62741
62915
  const plan = JSON.parse(planRaw);
62742
62916
  for (const planPhase of plan.phases ?? []) {
62743
62917
  for (const task of planPhase.tasks ?? []) {
@@ -62918,8 +63092,8 @@ async function executeUpdateTaskStatus(args2, fallbackDir) {
62918
63092
  };
62919
63093
  }
62920
63094
  }
62921
- normalizedDir = path54.normalize(args2.working_directory);
62922
- const pathParts = normalizedDir.split(path54.sep);
63095
+ normalizedDir = path55.normalize(args2.working_directory);
63096
+ const pathParts = normalizedDir.split(path55.sep);
62923
63097
  if (pathParts.includes("..")) {
62924
63098
  return {
62925
63099
  success: false,
@@ -62929,11 +63103,11 @@ async function executeUpdateTaskStatus(args2, fallbackDir) {
62929
63103
  ]
62930
63104
  };
62931
63105
  }
62932
- const resolvedDir = path54.resolve(normalizedDir);
63106
+ const resolvedDir = path55.resolve(normalizedDir);
62933
63107
  try {
62934
- const realPath = fs41.realpathSync(resolvedDir);
62935
- const planPath = path54.join(realPath, ".swarm", "plan.json");
62936
- if (!fs41.existsSync(planPath)) {
63108
+ const realPath = fs42.realpathSync(resolvedDir);
63109
+ const planPath = path55.join(realPath, ".swarm", "plan.json");
63110
+ if (!fs42.existsSync(planPath)) {
62937
63111
  return {
62938
63112
  success: false,
62939
63113
  message: `Invalid working_directory: plan not found in "${realPath}"`,
@@ -63085,16 +63259,24 @@ var OpenCodeSwarm = async (ctx) => {
63085
63259
  classThreshold: 3,
63086
63260
  commentStripThreshold: 5,
63087
63261
  diffLineThreshold: 200
63088
- }, ctx.directory, (_sessionId, message) => {
63089
- console.warn(`[slop-detector] ${message}`);
63262
+ }, ctx.directory, (sessionId, message) => {
63263
+ const s = swarmState.agentSessions.get(sessionId);
63264
+ if (s) {
63265
+ s.pendingAdvisoryMessages ??= [];
63266
+ s.pendingAdvisoryMessages.push(message);
63267
+ }
63090
63268
  }) : null;
63091
63269
  const incrementalVerifyHook = config3.incremental_verify?.enabled !== false ? createIncrementalVerifyHook(config3.incremental_verify ?? {
63092
63270
  enabled: true,
63093
63271
  command: null,
63094
63272
  timeoutMs: 30000,
63095
63273
  triggerAgents: ["coder"]
63096
- }, ctx.directory, (_sessionId, message) => {
63097
- console.warn(`[incremental-verify] ${message}`);
63274
+ }, ctx.directory, (sessionId, message) => {
63275
+ const s = swarmState.agentSessions.get(sessionId);
63276
+ if (s) {
63277
+ s.pendingAdvisoryMessages ??= [];
63278
+ s.pendingAdvisoryMessages.push(message);
63279
+ }
63098
63280
  }) : null;
63099
63281
  const compactionServiceHook = config3.compaction_service?.enabled !== false ? createCompactionService(config3.compaction_service ?? {
63100
63282
  enabled: true,
@@ -63102,8 +63284,12 @@ var OpenCodeSwarm = async (ctx) => {
63102
63284
  reflectionThreshold: 60,
63103
63285
  emergencyThreshold: 80,
63104
63286
  preserveLastNTurns: 5
63105
- }, ctx.directory, (_sessionId, message) => {
63106
- console.warn(`[compaction-service] ${message}`);
63287
+ }, ctx.directory, (sessionId, message) => {
63288
+ const s = swarmState.agentSessions.get(sessionId);
63289
+ if (s) {
63290
+ s.pendingAdvisoryMessages ??= [];
63291
+ s.pendingAdvisoryMessages.push(message);
63292
+ }
63107
63293
  }) : null;
63108
63294
  const snapshotWriterHook = createSnapshotWriterHook(ctx.directory);
63109
63295
  const automationConfig = AutomationConfigSchema.parse(config3.automation ?? {});
@@ -63115,7 +63301,7 @@ var OpenCodeSwarm = async (ctx) => {
63115
63301
  const { PreflightTriggerManager: PTM } = await Promise.resolve().then(() => (init_trigger(), exports_trigger));
63116
63302
  preflightTriggerManager = new PTM(automationConfig);
63117
63303
  const { AutomationStatusArtifact: ASA } = await Promise.resolve().then(() => (init_status_artifact(), exports_status_artifact));
63118
- const swarmDir = path55.resolve(ctx.directory, ".swarm");
63304
+ const swarmDir = path56.resolve(ctx.directory, ".swarm");
63119
63305
  statusArtifact = new ASA(swarmDir);
63120
63306
  statusArtifact.updateConfig(automationConfig.mode, automationConfig.capabilities);
63121
63307
  if (automationConfig.capabilities?.evidence_auto_summaries === true) {
@@ -63381,7 +63567,8 @@ var OpenCodeSwarm = async (ctx) => {
63381
63567
  const pressureSession = ensureAgentSession(input.sessionID, swarmState.activeAgent.get(input.sessionID) ?? ORCHESTRATOR_NAME);
63382
63568
  if (!pressureSession.contextPressureWarningSent) {
63383
63569
  pressureSession.contextPressureWarningSent = true;
63384
- console.warn(`[context-pressure] CONTEXT PRESSURE: ${swarmState.lastBudgetPct.toFixed(1)}% of context window estimated used. Prioritize completing the current task.`);
63570
+ pressureSession.pendingAdvisoryMessages ??= [];
63571
+ pressureSession.pendingAdvisoryMessages.push(`CONTEXT PRESSURE: ${swarmState.lastBudgetPct.toFixed(1)}% of context window used. Prioritize completing the current task before starting new work.`);
63385
63572
  }
63386
63573
  }
63387
63574
  await safeHook(activityHooks.toolBefore)(input, output);