opencode-swarm 7.33.0 → 7.33.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli/index.js CHANGED
@@ -34,7 +34,7 @@ var package_default;
34
34
  var init_package = __esm(() => {
35
35
  package_default = {
36
36
  name: "opencode-swarm",
37
- version: "7.33.0",
37
+ version: "7.33.1",
38
38
  description: "Architect-centric agentic swarm plugin for OpenCode - hub-and-spoke orchestration with SME consultation, code generation, and QA review",
39
39
  main: "dist/index.js",
40
40
  types: "dist/index.d.ts",
@@ -14580,9 +14580,138 @@ function emit(event, data) {
14580
14580
  }
14581
14581
  } catch {}
14582
14582
  }
14583
- var _writeStream = null, _listeners, _disabled = false;
14583
+ var _writeStream = null, _listeners, _disabled = false, telemetry, _internals2;
14584
14584
  var init_telemetry = __esm(() => {
14585
14585
  _listeners = [];
14586
+ telemetry = {
14587
+ sessionStarted(sessionId, agentName) {
14588
+ _internals2.emit("session_started", { sessionId, agentName });
14589
+ },
14590
+ sessionEnded(sessionId, reason) {
14591
+ _internals2.emit("session_ended", { sessionId, reason });
14592
+ },
14593
+ agentActivated(sessionId, agentName, oldName) {
14594
+ _internals2.emit("agent_activated", { sessionId, agentName, oldName });
14595
+ },
14596
+ delegationBegin(sessionId, agentName, taskId) {
14597
+ _internals2.emit("delegation_begin", { sessionId, agentName, taskId });
14598
+ },
14599
+ delegationEnd(sessionId, agentName, taskId, result) {
14600
+ _internals2.emit("delegation_end", { sessionId, agentName, taskId, result });
14601
+ },
14602
+ taskStateChanged(sessionId, taskId, newState, oldState) {
14603
+ _internals2.emit("task_state_changed", {
14604
+ sessionId,
14605
+ taskId,
14606
+ newState,
14607
+ oldState
14608
+ });
14609
+ },
14610
+ gatePassed(sessionId, gate, taskId) {
14611
+ _internals2.emit("gate_passed", { sessionId, gate, taskId });
14612
+ },
14613
+ gateParseError(taskId, error49) {
14614
+ _internals2.emit("gate_parse_error", {
14615
+ taskId,
14616
+ errorName: error49.name,
14617
+ errorMessage: error49.message.slice(0, 200)
14618
+ });
14619
+ },
14620
+ gateFailed(sessionId, gate, taskId, reason) {
14621
+ _internals2.emit("gate_failed", { sessionId, gate, taskId, reason });
14622
+ },
14623
+ phaseChanged(sessionId, oldPhase, newPhase) {
14624
+ _internals2.emit("phase_changed", { sessionId, oldPhase, newPhase });
14625
+ },
14626
+ budgetUpdated(sessionId, budgetPct, agentName) {
14627
+ _internals2.emit("budget_updated", { sessionId, budgetPct, agentName });
14628
+ },
14629
+ modelFallback(sessionId, agentName, fromModel, toModel, reason) {
14630
+ _internals2.emit("model_fallback", {
14631
+ sessionId,
14632
+ agentName,
14633
+ fromModel,
14634
+ toModel,
14635
+ reason
14636
+ });
14637
+ },
14638
+ hardLimitHit(sessionId, agentName, limitType, value) {
14639
+ _internals2.emit("hard_limit_hit", {
14640
+ sessionId,
14641
+ agentName,
14642
+ limitType,
14643
+ value
14644
+ });
14645
+ },
14646
+ revisionLimitHit(sessionId, agentName) {
14647
+ _internals2.emit("revision_limit_hit", { sessionId, agentName });
14648
+ },
14649
+ loopDetected(sessionId, agentName, loopType) {
14650
+ _internals2.emit("loop_detected", { sessionId, agentName, loopType });
14651
+ },
14652
+ scopeViolation(sessionId, agentName, file2, reason) {
14653
+ _internals2.emit("scope_violation", { sessionId, agentName, file: file2, reason });
14654
+ },
14655
+ qaSkipViolation(sessionId, agentName, skipCount) {
14656
+ _internals2.emit("qa_skip_violation", { sessionId, agentName, skipCount });
14657
+ },
14658
+ heartbeat(sessionId) {
14659
+ _internals2.emit("heartbeat", { sessionId });
14660
+ },
14661
+ turboModeChanged(sessionId, enabled, agentName) {
14662
+ _internals2.emit("turbo_mode_changed", { sessionId, enabled, agentName });
14663
+ },
14664
+ autoOversightEscalation(sessionId, reason, interactionCount, deadlockCount, phase) {
14665
+ _internals2.emit("auto_oversight_escalation", {
14666
+ sessionId,
14667
+ reason,
14668
+ interactionCount,
14669
+ deadlockCount,
14670
+ phase
14671
+ });
14672
+ },
14673
+ environmentDetected(sessionId, hostOS, shellFamily, executionMode) {
14674
+ _internals2.emit("environment_detected", {
14675
+ sessionId,
14676
+ hostOS,
14677
+ shellFamily,
14678
+ executionMode
14679
+ });
14680
+ },
14681
+ prmPatternDetected(sessionId, pattern, severity, category, stepRange) {
14682
+ _internals2.emit("prm_pattern_detected", {
14683
+ sessionId,
14684
+ pattern,
14685
+ severity,
14686
+ category,
14687
+ stepRange
14688
+ });
14689
+ },
14690
+ prmCourseCorrectionInjected(sessionId, pattern, level) {
14691
+ _internals2.emit("prm_course_correction_injected", {
14692
+ sessionId,
14693
+ pattern,
14694
+ level
14695
+ });
14696
+ },
14697
+ prmEscalationTriggered(sessionId, pattern, level, occurrenceCount) {
14698
+ _internals2.emit("prm_escalation_triggered", {
14699
+ sessionId,
14700
+ pattern,
14701
+ level,
14702
+ occurrenceCount
14703
+ });
14704
+ },
14705
+ prmHardStop(sessionId, pattern, level, occurrenceCount) {
14706
+ _internals2.emit("prm_hard_stop", {
14707
+ sessionId,
14708
+ pattern,
14709
+ level,
14710
+ occurrenceCount
14711
+ });
14712
+ }
14713
+ };
14714
+ _internals2 = { telemetry, emit };
14586
14715
  });
14587
14716
 
14588
14717
  // src/utils/spec-hash.ts
@@ -14603,7 +14732,7 @@ async function computeSpecHash(directory) {
14603
14732
  return hash2;
14604
14733
  }
14605
14734
  async function isSpecStale(directory, plan) {
14606
- const currentHash = await _internals2.computeSpecHash(directory);
14735
+ const currentHash = await _internals3.computeSpecHash(directory);
14607
14736
  if (!plan.specHash) {
14608
14737
  return { stale: false };
14609
14738
  }
@@ -14623,9 +14752,9 @@ async function isSpecStale(directory, plan) {
14623
14752
  }
14624
14753
  return { stale: false };
14625
14754
  }
14626
- var _internals2;
14755
+ var _internals3;
14627
14756
  var init_spec_hash = __esm(() => {
14628
- _internals2 = {
14757
+ _internals3 = {
14629
14758
  computeSpecHash,
14630
14759
  isSpecStale
14631
14760
  };
@@ -14815,6 +14944,32 @@ async function appendLedgerEvent(directory, eventInput, options) {
14815
14944
  fs.renameSync(tempPath, ledgerPath);
14816
14945
  return event;
14817
14946
  }
14947
+ async function takeSnapshotWithRetry(directory, plan, options) {
14948
+ const MAX_RETRIES = 3;
14949
+ const TOTAL_ATTEMPTS = 1 + MAX_RETRIES;
14950
+ const telemetrySource = options?.source ?? "save_plan_tool";
14951
+ const snapshotOptions = { planHashAfter: options?.planHashAfter };
14952
+ let lastError;
14953
+ for (let attempt = 1;attempt <= TOTAL_ATTEMPTS; attempt++) {
14954
+ try {
14955
+ await takeSnapshotEvent(directory, plan, snapshotOptions);
14956
+ return;
14957
+ } catch (err) {
14958
+ lastError = err instanceof Error ? err : new Error(String(err));
14959
+ if (attempt < TOTAL_ATTEMPTS) {
14960
+ await new Promise((r) => setTimeout(r, 10 * 2 ** (attempt - 1)));
14961
+ }
14962
+ }
14963
+ }
14964
+ console.warn(`[takeSnapshotWithRetry] Snapshot failed after ${MAX_RETRIES} retries (${TOTAL_ATTEMPTS} attempts): ${lastError.message}`);
14965
+ try {
14966
+ emit("snapshot_failed", {
14967
+ error: lastError.message,
14968
+ retries: MAX_RETRIES,
14969
+ source: telemetrySource
14970
+ });
14971
+ } catch {}
14972
+ }
14818
14973
  async function takeSnapshotEvent(directory, plan, options) {
14819
14974
  const payloadHash = computePlanHash(plan);
14820
14975
  const snapshotPayload = {
@@ -15048,6 +15203,7 @@ async function loadLastApprovedPlan(directory, expectedPlanId) {
15048
15203
  var LEDGER_SCHEMA_VERSION = "1.1.0", LEDGER_FILENAME = "plan-ledger.jsonl", PLAN_JSON_FILENAME = "plan.json", LedgerStaleWriterError;
15049
15204
  var init_ledger = __esm(() => {
15050
15205
  init_plan_schema();
15206
+ init_telemetry();
15051
15207
  LedgerStaleWriterError = class LedgerStaleWriterError extends Error {
15052
15208
  constructor(message) {
15053
15209
  super(message);
@@ -15219,7 +15375,7 @@ async function loadPlan(directory) {
15219
15375
  const inSync = await isPlanMdInSync(directory, validated);
15220
15376
  if (!inSync) {
15221
15377
  try {
15222
- await _internals3.regeneratePlanMarkdown(directory, validated);
15378
+ await _internals4.regeneratePlanMarkdown(directory, validated);
15223
15379
  } catch (regenError) {
15224
15380
  warn(`Failed to regenerate plan.md: ${regenError instanceof Error ? regenError.message : String(regenError)}. Proceeding with plan.json only.`);
15225
15381
  }
@@ -15241,7 +15397,9 @@ async function loadPlan(directory) {
15241
15397
  try {
15242
15398
  const rebuilt = await replayFromLedger(directory);
15243
15399
  if (rebuilt) {
15244
- await rebuildPlan(directory, rebuilt);
15400
+ await rebuildPlan(directory, rebuilt, {
15401
+ reason: "ledger_hash_mismatch_recovery"
15402
+ });
15245
15403
  warn("[loadPlan] Rebuilt plan from ledger. Checkpoint available at .swarm/SWARM_PLAN.md if it exists.");
15246
15404
  return rebuilt;
15247
15405
  }
@@ -15249,7 +15407,9 @@ async function loadPlan(directory) {
15249
15407
  try {
15250
15408
  const approved = await loadLastApprovedPlan(directory, currentPlanId);
15251
15409
  if (approved) {
15252
- await rebuildPlan(directory, approved.plan);
15410
+ await rebuildPlan(directory, approved.plan, {
15411
+ reason: "approved_snapshot_fallback"
15412
+ });
15253
15413
  try {
15254
15414
  await takeSnapshotEvent(directory, approved.plan, {
15255
15415
  source: "recovery_from_approved_snapshot",
@@ -15326,7 +15486,9 @@ async function loadPlan(directory) {
15326
15486
  } else if (catchFirstEvent !== null && rawPlanId !== null) {
15327
15487
  const rebuilt = await replayFromLedger(directory);
15328
15488
  if (rebuilt) {
15329
- await rebuildPlan(directory, rebuilt);
15489
+ await rebuildPlan(directory, rebuilt, {
15490
+ reason: "validation_failure_recovery"
15491
+ });
15330
15492
  warn("[loadPlan] Rebuilt plan from ledger after validation failure. Projection was stale.");
15331
15493
  return rebuilt;
15332
15494
  }
@@ -15358,7 +15520,7 @@ async function loadPlan(directory) {
15358
15520
  const existingMutex = recoveryMutexes.get(resolvedDir);
15359
15521
  if (existingMutex) {
15360
15522
  await existingMutex;
15361
- const postRecoveryPlan = await _internals3.loadPlanJsonOnly(directory);
15523
+ const postRecoveryPlan = await _internals4.loadPlanJsonOnly(directory);
15362
15524
  if (postRecoveryPlan)
15363
15525
  return postRecoveryPlan;
15364
15526
  }
@@ -15418,7 +15580,7 @@ async function loadPlan(directory) {
15418
15580
  return null;
15419
15581
  }
15420
15582
  async function savePlanWithAutoAcknowledgedRemovals(directory, plan, source, reason, options) {
15421
- const existing = await _internals3.loadPlanJsonOnly(directory);
15583
+ const existing = await _internals4.loadPlanJsonOnly(directory);
15422
15584
  const newIds = new Set;
15423
15585
  for (const phase of plan.phases) {
15424
15586
  for (const task of phase.tasks)
@@ -15446,7 +15608,7 @@ async function savePlan(directory, plan, options) {
15446
15608
  const validated = PlanSchema.parse(plan);
15447
15609
  if (options?.preserveCompletedStatuses !== false) {
15448
15610
  try {
15449
- const currentPlan2 = await _internals3.loadPlanJsonOnly(directory);
15611
+ const currentPlan2 = await _internals4.loadPlanJsonOnly(directory);
15450
15612
  if (currentPlan2) {
15451
15613
  const completedTaskIds = new Set;
15452
15614
  for (const phase of currentPlan2.phases) {
@@ -15479,7 +15641,7 @@ async function savePlan(directory, plan, options) {
15479
15641
  phase.status = "pending";
15480
15642
  }
15481
15643
  }
15482
- const currentPlan = await _internals3.loadPlanJsonOnly(directory);
15644
+ const currentPlan = await _internals4.loadPlanJsonOnly(directory);
15483
15645
  const planId = derivePlanId(validated);
15484
15646
  const planHashForInit = computePlanHash(validated);
15485
15647
  if (!await ledgerExists(directory)) {
@@ -15624,7 +15786,7 @@ async function savePlan(directory, plan, options) {
15624
15786
  expectedHash: currentHash,
15625
15787
  planHashAfter: hashAfter,
15626
15788
  verifyValid: async () => {
15627
- const onDisk = await _internals3.loadPlanJsonOnly(directory);
15789
+ const onDisk = await _internals4.loadPlanJsonOnly(directory);
15628
15790
  if (!onDisk)
15629
15791
  return true;
15630
15792
  for (const p of onDisk.phases) {
@@ -15662,7 +15824,7 @@ async function savePlan(directory, plan, options) {
15662
15824
  expectedHash: currentHash,
15663
15825
  planHashAfter: hashAfter,
15664
15826
  verifyValid: async () => {
15665
- const onDisk = await _internals3.loadPlanJsonOnly(directory);
15827
+ const onDisk = await _internals4.loadPlanJsonOnly(directory);
15666
15828
  if (!onDisk)
15667
15829
  return true;
15668
15830
  for (const p of onDisk.phases) {
@@ -15687,12 +15849,9 @@ async function savePlan(directory, plan, options) {
15687
15849
  const SNAPSHOT_INTERVAL = 50;
15688
15850
  const latestSeq = await getLatestLedgerSeq(directory);
15689
15851
  if (latestSeq > 0 && latestSeq % SNAPSHOT_INTERVAL === 0) {
15690
- await takeSnapshotEvent(directory, validated, {
15691
- planHashAfter: hashAfter
15692
- }).catch((err) => {
15693
- if (process.env.DEBUG_SWARM) {
15694
- warn(`[savePlan] Periodic snapshot write failed (non-fatal): ${err instanceof Error ? err.message : String(err)}`);
15695
- }
15852
+ await takeSnapshotWithRetry(directory, validated, {
15853
+ planHashAfter: hashAfter,
15854
+ source: "savePlan_manager"
15696
15855
  });
15697
15856
  }
15698
15857
  const swarmDir = path4.resolve(directory, ".swarm");
@@ -15706,6 +15865,17 @@ async function savePlan(directory, plan, options) {
15706
15865
  unlinkSync(tempPath);
15707
15866
  } catch {}
15708
15867
  }
15868
+ try {
15869
+ const markerPath = path4.join(swarmDir, ".plan-write-marker");
15870
+ const inProgressMarker = JSON.stringify({
15871
+ source: "plan_manager",
15872
+ timestamp: new Date().toISOString(),
15873
+ phases_count: validated.phases.length,
15874
+ tasks_count: validated.phases.reduce((sum, p) => sum + p.tasks.length, 0),
15875
+ in_progress: true
15876
+ });
15877
+ await bunWrite(markerPath, inProgressMarker);
15878
+ } catch {}
15709
15879
  try {
15710
15880
  const contentHash = computePlanContentHash(validated);
15711
15881
  const markdown = derivePlanMarkdown(validated);
@@ -15739,41 +15909,146 @@ ${markdown}`;
15739
15909
  source: "plan_manager",
15740
15910
  timestamp: new Date().toISOString(),
15741
15911
  phases_count: validated.phases.length,
15742
- tasks_count: tasksCount
15912
+ tasks_count: tasksCount,
15913
+ in_progress: false
15743
15914
  });
15744
15915
  await bunWrite(markerPath, marker);
15745
15916
  } catch {}
15746
15917
  }
15747
- async function rebuildPlan(directory, plan) {
15918
+ async function rebuildPlan(directory, plan, options) {
15748
15919
  const targetPlan = plan ?? await replayFromLedger(directory);
15749
15920
  if (!targetPlan)
15750
15921
  return null;
15751
15922
  const swarmDir = path4.join(directory, ".swarm");
15752
15923
  const planPath = path4.join(swarmDir, "plan.json");
15753
15924
  const mdPath = path4.join(swarmDir, "plan.md");
15754
- const tempPlanPath = path4.join(swarmDir, `plan.json.rebuild.${Date.now()}`);
15925
+ const tempPlanPath = path4.join(swarmDir, `plan.json.rebuild.${Date.now()}.${Math.floor(Math.random() * 1e9)}`);
15755
15926
  await bunWrite(tempPlanPath, JSON.stringify(targetPlan, null, 2));
15756
15927
  renameSync2(tempPlanPath, planPath);
15757
- const contentHash = computePlanContentHash(targetPlan);
15758
- const markdown = derivePlanMarkdown(targetPlan);
15759
- const markdownWithHash = `<!-- PLAN_HASH: ${contentHash} -->
15760
- ${markdown}`;
15761
- const tempMdPath = path4.join(swarmDir, `plan.md.rebuild.${Date.now()}`);
15762
- await bunWrite(tempMdPath, markdownWithHash);
15763
- renameSync2(tempMdPath, mdPath);
15764
15928
  try {
15765
15929
  const markerPath = path4.join(swarmDir, ".plan-write-marker");
15766
- const tasksCount = targetPlan.phases.reduce((sum, phase) => sum + phase.tasks.length, 0);
15767
- const marker = JSON.stringify({
15930
+ const inProgressMarker = JSON.stringify({
15768
15931
  source: "plan_manager",
15769
15932
  timestamp: new Date().toISOString(),
15770
15933
  phases_count: targetPlan.phases.length,
15771
- tasks_count: tasksCount
15934
+ tasks_count: targetPlan.phases.reduce((sum, phase) => sum + phase.tasks.length, 0),
15935
+ in_progress: true
15772
15936
  });
15773
- await bunWrite(markerPath, marker);
15937
+ await bunWrite(markerPath, inProgressMarker);
15938
+ } catch {}
15939
+ try {
15940
+ const contentHash = computePlanContentHash(targetPlan);
15941
+ const markdown = derivePlanMarkdown(targetPlan);
15942
+ const markdownWithHash = `<!-- PLAN_HASH: ${contentHash} -->
15943
+ ${markdown}`;
15944
+ const tempMdPath = path4.join(swarmDir, `plan.md.rebuild.${Date.now()}.${Math.floor(Math.random() * 1e9)}`);
15945
+ await bunWrite(tempMdPath, markdownWithHash);
15946
+ renameSync2(tempMdPath, mdPath);
15947
+ } finally {
15948
+ try {
15949
+ const markerPath = path4.join(swarmDir, ".plan-write-marker");
15950
+ const tasksCount = targetPlan.phases.reduce((sum, phase) => sum + phase.tasks.length, 0);
15951
+ const marker = JSON.stringify({
15952
+ source: "plan_manager",
15953
+ timestamp: new Date().toISOString(),
15954
+ phases_count: targetPlan.phases.length,
15955
+ tasks_count: tasksCount,
15956
+ in_progress: false
15957
+ });
15958
+ await bunWrite(markerPath, marker);
15959
+ } catch {}
15960
+ }
15961
+ try {
15962
+ const planId = derivePlanId(targetPlan);
15963
+ const planHashAfter = computePlanHash(targetPlan);
15964
+ await appendLedgerEvent(directory, {
15965
+ event_type: "plan_rebuilt",
15966
+ source: "rebuildPlan",
15967
+ plan_id: planId,
15968
+ payload: {
15969
+ reason: options?.reason ?? "ledger_replay_recovery",
15970
+ phases_count: targetPlan.phases.length,
15971
+ tasks_count: targetPlan.phases.reduce((sum, p) => sum + p.tasks.length, 0)
15972
+ }
15973
+ }, { planHashAfter });
15774
15974
  } catch {}
15775
15975
  return targetPlan;
15776
15976
  }
15977
+ async function closePlanTerminalState(directory, plan, options) {
15978
+ const planId = derivePlanId(plan);
15979
+ const validated = PlanSchema.parse(plan);
15980
+ const hashAfter = computePlanHash(validated);
15981
+ for (const taskId of options.closedTaskIds) {
15982
+ let taskPhaseId;
15983
+ for (const phase of validated.phases) {
15984
+ if (phase.tasks.some((t) => t.id === taskId)) {
15985
+ taskPhaseId = phase.id;
15986
+ break;
15987
+ }
15988
+ }
15989
+ const fromStatus = options.originalStatuses?.get(taskId) ?? "in_progress";
15990
+ await appendLedgerEvent(directory, {
15991
+ plan_id: planId,
15992
+ event_type: "task_status_changed",
15993
+ task_id: taskId,
15994
+ phase_id: taskPhaseId,
15995
+ from_status: fromStatus,
15996
+ to_status: "closed",
15997
+ source: "close_terminal"
15998
+ }, { planHashAfter: hashAfter });
15999
+ }
16000
+ for (const phaseId of options.closedPhaseIds) {
16001
+ await appendLedgerEvent(directory, {
16002
+ plan_id: planId,
16003
+ event_type: "phase_completed",
16004
+ phase_id: phaseId,
16005
+ source: "close_terminal"
16006
+ }, { planHashAfter: hashAfter });
16007
+ }
16008
+ await takeSnapshotEvent(directory, validated, {
16009
+ planHashAfter: hashAfter,
16010
+ source: "close_terminal"
16011
+ });
16012
+ const swarmDir = path4.join(directory, ".swarm");
16013
+ const planPath = path4.join(swarmDir, "plan.json");
16014
+ const tempPlanPath = path4.join(swarmDir, `plan.json.close.${Date.now()}.${Math.floor(Math.random() * 1e9)}`);
16015
+ await bunWrite(tempPlanPath, JSON.stringify(validated, null, 2));
16016
+ renameSync2(tempPlanPath, planPath);
16017
+ try {
16018
+ const markerPath = path4.join(swarmDir, ".plan-write-marker");
16019
+ const inProgressMarker = JSON.stringify({
16020
+ source: "plan_manager_close",
16021
+ timestamp: new Date().toISOString(),
16022
+ phases_count: validated.phases.length,
16023
+ tasks_count: validated.phases.reduce((sum, phase) => sum + phase.tasks.length, 0),
16024
+ in_progress: true
16025
+ });
16026
+ await bunWrite(markerPath, inProgressMarker);
16027
+ } catch {}
16028
+ try {
16029
+ const mdPath = path4.join(swarmDir, "plan.md");
16030
+ const contentHash = computePlanContentHash(validated);
16031
+ const markdown = derivePlanMarkdown(validated);
16032
+ const markdownWithHash = `<!-- PLAN_HASH: ${contentHash} -->
16033
+ ${markdown}`;
16034
+ const mdTempPath = path4.join(swarmDir, `plan.md.close.${Date.now()}.${Math.floor(Math.random() * 1e9)}`);
16035
+ await bunWrite(mdTempPath, markdownWithHash);
16036
+ renameSync2(mdTempPath, mdPath);
16037
+ } finally {
16038
+ try {
16039
+ const markerPath = path4.join(swarmDir, ".plan-write-marker");
16040
+ const tasksCount = validated.phases.reduce((sum, phase) => sum + phase.tasks.length, 0);
16041
+ const marker = JSON.stringify({
16042
+ source: "plan_manager_close",
16043
+ timestamp: new Date().toISOString(),
16044
+ phases_count: validated.phases.length,
16045
+ tasks_count: tasksCount,
16046
+ in_progress: false
16047
+ });
16048
+ await bunWrite(markerPath, marker);
16049
+ } catch {}
16050
+ }
16051
+ }
15777
16052
  function derivePlanMarkdown(plan) {
15778
16053
  const statusMap = {
15779
16054
  pending: "PENDING",
@@ -16042,7 +16317,7 @@ function migrateLegacyPlan(planContent, swarmId) {
16042
16317
  };
16043
16318
  return plan;
16044
16319
  }
16045
- var PlanConcurrentModificationError, PlanTaskRemovalNotAcknowledgedError, startupLedgerCheckedWorkspaces, recoveryMutexes, _internals3, CAS_BACKOFF_START_MS = 5, CAS_BACKOFF_CAP_MS = 250, CAS_BACKOFF_JITTER = 0.25, CAS_MAX_RETRIES = 3;
16320
+ var PlanConcurrentModificationError, PlanTaskRemovalNotAcknowledgedError, startupLedgerCheckedWorkspaces, recoveryMutexes, _internals4, CAS_BACKOFF_START_MS = 5, CAS_BACKOFF_CAP_MS = 250, CAS_BACKOFF_JITTER = 0.25, CAS_MAX_RETRIES = 3;
16046
16321
  var init_manager = __esm(() => {
16047
16322
  init_plan_schema();
16048
16323
  init_utils2();
@@ -16068,7 +16343,7 @@ var init_manager = __esm(() => {
16068
16343
  };
16069
16344
  startupLedgerCheckedWorkspaces = new Set;
16070
16345
  recoveryMutexes = new Map;
16071
- _internals3 = {
16346
+ _internals4 = {
16072
16347
  loadPlan,
16073
16348
  loadPlanJsonOnly,
16074
16349
  regeneratePlanMarkdown
@@ -19763,11 +20038,11 @@ async function tryAcquireLock(directory, filePath, agent, taskId) {
19763
20038
  };
19764
20039
  return { acquired: true, lock };
19765
20040
  }
19766
- var import_proper_lockfile, LOCKS_DIR = ".swarm/locks", LOCK_TIMEOUT_MS, _internals4;
20041
+ var import_proper_lockfile, LOCKS_DIR = ".swarm/locks", LOCK_TIMEOUT_MS, _internals5;
19767
20042
  var init_file_locks = __esm(() => {
19768
20043
  import_proper_lockfile = __toESM(require_proper_lockfile(), 1);
19769
20044
  LOCK_TIMEOUT_MS = 5 * 60 * 1000;
19770
- _internals4 = {
20045
+ _internals5 = {
19771
20046
  tryAcquireLock,
19772
20047
  writeFile: fs3.promises.writeFile
19773
20048
  };
@@ -19867,6 +20142,19 @@ function checkUnsafeChars(taskId) {
19867
20142
  }
19868
20143
  return;
19869
20144
  }
20145
+ function isStrictTaskId(taskId) {
20146
+ if (!taskId)
20147
+ return false;
20148
+ const unsafeMsg = checkUnsafeChars(taskId);
20149
+ if (unsafeMsg)
20150
+ return false;
20151
+ return STRICT_TASK_ID_PATTERN.test(taskId);
20152
+ }
20153
+ function assertStrictTaskId(taskId) {
20154
+ if (!isStrictTaskId(taskId)) {
20155
+ throw new Error(`Invalid taskId: "${taskId}". Must match N.M or N.M.P (e.g. "1.1", "1.2.3").`);
20156
+ }
20157
+ }
19870
20158
  function sanitizeTaskId(taskId) {
19871
20159
  const unsafeMsg = checkUnsafeChars(taskId);
19872
20160
  if (unsafeMsg) {
@@ -19947,7 +20235,7 @@ function validateProjectRoot(directory) {
19947
20235
  }
19948
20236
  }
19949
20237
  async function saveEvidence(directory, taskId, evidence) {
19950
- _internals5.validateProjectRoot(directory);
20238
+ _internals6.validateProjectRoot(directory);
19951
20239
  const sanitizedTaskId = sanitizeTaskId2(taskId);
19952
20240
  const relativePath = path7.join("evidence", sanitizedTaskId, "evidence.json");
19953
20241
  validateSwarmPath(directory, relativePath);
@@ -20048,7 +20336,7 @@ async function loadEvidence(directory, taskId) {
20048
20336
  return { status: "invalid_schema", errors: ["Invalid JSON"] };
20049
20337
  }
20050
20338
  if (isFlatRetrospective(parsed)) {
20051
- const wrappedBundle = _internals5.wrapFlatRetrospective(parsed, sanitizedTaskId);
20339
+ const wrappedBundle = _internals6.wrapFlatRetrospective(parsed, sanitizedTaskId);
20052
20340
  try {
20053
20341
  const validated = EvidenceBundleSchema.parse(wrappedBundle);
20054
20342
  try {
@@ -20144,14 +20432,14 @@ async function checkRequirementCoverage(phase, directory) {
20144
20432
  }
20145
20433
  }
20146
20434
  async function archiveEvidence(directory, maxAgeDays, maxBundles) {
20147
- const taskIds = await _internals5.listEvidenceTaskIds(directory);
20435
+ const taskIds = await _internals6.listEvidenceTaskIds(directory);
20148
20436
  const cutoffDate = new Date;
20149
20437
  cutoffDate.setDate(cutoffDate.getDate() - maxAgeDays);
20150
20438
  const cutoffIso = cutoffDate.toISOString();
20151
20439
  const archived = [];
20152
20440
  const remainingBundles = [];
20153
20441
  for (const taskId of taskIds) {
20154
- const result = await _internals5.loadEvidence(directory, taskId);
20442
+ const result = await _internals6.loadEvidence(directory, taskId);
20155
20443
  if (result.status !== "found") {
20156
20444
  continue;
20157
20445
  }
@@ -20179,7 +20467,7 @@ async function archiveEvidence(directory, maxAgeDays, maxBundles) {
20179
20467
  }
20180
20468
  return archived;
20181
20469
  }
20182
- var VALID_EVIDENCE_TYPES, sanitizeTaskId2, MAX_DEPTH = 20, PROJECT_INDICATORS, LEGACY_TASK_COMPLEXITY_MAP, _internals5;
20470
+ var VALID_EVIDENCE_TYPES, sanitizeTaskId2, MAX_DEPTH = 20, PROJECT_INDICATORS, LEGACY_TASK_COMPLEXITY_MAP, _internals6;
20183
20471
  var init_manager2 = __esm(() => {
20184
20472
  init_zod();
20185
20473
  init_evidence_schema();
@@ -20222,7 +20510,7 @@ var init_manager2 = __esm(() => {
20222
20510
  medium: "moderate",
20223
20511
  high: "complex"
20224
20512
  };
20225
- _internals5 = {
20513
+ _internals6 = {
20226
20514
  wrapFlatRetrospective,
20227
20515
  loadEvidence,
20228
20516
  listEvidenceTaskIds,
@@ -20434,7 +20722,7 @@ function getProfile(directory, planId) {
20434
20722
  return row ? rowToProfile(row) : null;
20435
20723
  }
20436
20724
  function getOrCreateProfile(directory, planId, projectType) {
20437
- const existing = _internals6.getProfile(directory, planId);
20725
+ const existing = _internals7.getProfile(directory, planId);
20438
20726
  if (existing)
20439
20727
  return existing;
20440
20728
  const db = getProjectDb(directory);
@@ -20450,14 +20738,14 @@ function getOrCreateProfile(directory, planId, projectType) {
20450
20738
  throw err;
20451
20739
  }
20452
20740
  }
20453
- const after = _internals6.getProfile(directory, planId);
20741
+ const after = _internals7.getProfile(directory, planId);
20454
20742
  if (!after) {
20455
20743
  throw new Error(`Failed to create or load QA gate profile for plan_id=${planId}`);
20456
20744
  }
20457
20745
  return after;
20458
20746
  }
20459
20747
  function setGates(directory, planId, gates) {
20460
- const current = _internals6.getProfile(directory, planId);
20748
+ const current = _internals7.getProfile(directory, planId);
20461
20749
  if (!current) {
20462
20750
  throw new Error(`No QA gate profile found for plan_id=${planId} \u2014 call getOrCreateProfile first`);
20463
20751
  }
@@ -20481,7 +20769,7 @@ function setGates(directory, planId, gates) {
20481
20769
  JSON.stringify(merged),
20482
20770
  planId
20483
20771
  ]);
20484
- const updated = _internals6.getProfile(directory, planId);
20772
+ const updated = _internals7.getProfile(directory, planId);
20485
20773
  if (!updated) {
20486
20774
  throw new Error(`Failed to re-read QA gate profile after update for plan_id=${planId}`);
20487
20775
  }
@@ -20503,10 +20791,10 @@ function getEffectiveGates(profile, sessionOverrides) {
20503
20791
  }
20504
20792
  return merged;
20505
20793
  }
20506
- var _internals6, DEFAULT_QA_GATES;
20794
+ var _internals7, DEFAULT_QA_GATES;
20507
20795
  var init_qa_gate_profile = __esm(() => {
20508
20796
  init_project_db();
20509
- _internals6 = {
20797
+ _internals7 = {
20510
20798
  getProfile,
20511
20799
  getOrCreateProfile,
20512
20800
  setGates,
@@ -34954,7 +35242,7 @@ function resetToRemoteBranch(cwd, options) {
34954
35242
  const prunedBranches = [];
34955
35243
  try {
34956
35244
  const currentBranch = getCurrentBranch(cwd);
34957
- const defaultRemoteBranch = _internals7.detectDefaultRemoteBranch(cwd);
35245
+ const defaultRemoteBranch = _internals8.detectDefaultRemoteBranch(cwd);
34958
35246
  if (!defaultRemoteBranch) {
34959
35247
  return {
34960
35248
  success: false,
@@ -35136,7 +35424,7 @@ function resetToRemoteBranch(cwd, options) {
35136
35424
  function resetToMainAfterMerge(cwd, options) {
35137
35425
  const warnings = [];
35138
35426
  try {
35139
- const defaultBranch = _internals7.detectDefaultRemoteBranch(cwd);
35427
+ const defaultBranch = _internals8.detectDefaultRemoteBranch(cwd);
35140
35428
  if (!defaultBranch) {
35141
35429
  return {
35142
35430
  success: false,
@@ -35163,7 +35451,7 @@ function resetToMainAfterMerge(cwd, options) {
35163
35451
  }
35164
35452
  if (currentBranch === defaultBranch) {
35165
35453
  try {
35166
- const logOutput = _internals7.gitExec(["log", `${targetBranch}..HEAD`, "--oneline"], cwd);
35454
+ const logOutput = _internals8.gitExec(["log", `${targetBranch}..HEAD`, "--oneline"], cwd);
35167
35455
  if (logOutput.trim().length > 0) {
35168
35456
  return {
35169
35457
  success: false,
@@ -35178,11 +35466,11 @@ function resetToMainAfterMerge(cwd, options) {
35178
35466
  } catch {}
35179
35467
  } else {
35180
35468
  try {
35181
- _internals7.gitExec(["rev-parse", "--abbrev-ref", `${currentBranch}@{upstream}`], cwd);
35469
+ _internals8.gitExec(["rev-parse", "--abbrev-ref", `${currentBranch}@{upstream}`], cwd);
35182
35470
  } catch {
35183
35471
  try {
35184
- const localSha = _internals7.gitExec(["rev-parse", "HEAD"], cwd).trim();
35185
- const remoteSha = _internals7.gitExec(["rev-parse", targetBranch], cwd).trim();
35472
+ const localSha = _internals8.gitExec(["rev-parse", "HEAD"], cwd).trim();
35473
+ const remoteSha = _internals8.gitExec(["rev-parse", targetBranch], cwd).trim();
35186
35474
  if (localSha !== remoteSha) {
35187
35475
  return {
35188
35476
  success: false,
@@ -35208,7 +35496,7 @@ function resetToMainAfterMerge(cwd, options) {
35208
35496
  }
35209
35497
  }
35210
35498
  try {
35211
- _internals7.gitExec(["fetch", "--prune", "origin"], cwd);
35499
+ _internals8.gitExec(["fetch", "--prune", "origin"], cwd);
35212
35500
  } catch (err) {
35213
35501
  return {
35214
35502
  success: false,
@@ -35224,7 +35512,7 @@ function resetToMainAfterMerge(cwd, options) {
35224
35512
  let switchedBranch = false;
35225
35513
  if (currentBranch !== defaultBranch) {
35226
35514
  try {
35227
- _internals7.gitExec(["checkout", defaultBranch], cwd);
35515
+ _internals8.gitExec(["checkout", defaultBranch], cwd);
35228
35516
  switchedBranch = true;
35229
35517
  } catch (err) {
35230
35518
  return {
@@ -35239,7 +35527,7 @@ function resetToMainAfterMerge(cwd, options) {
35239
35527
  }
35240
35528
  }
35241
35529
  try {
35242
- _internals7.gitExec(["reset", "--hard", targetBranch], cwd);
35530
+ _internals8.gitExec(["reset", "--hard", targetBranch], cwd);
35243
35531
  } catch (err) {
35244
35532
  return {
35245
35533
  success: false,
@@ -35260,7 +35548,7 @@ function resetToMainAfterMerge(cwd, options) {
35260
35548
  while (Date.now() < endTime) {}
35261
35549
  }
35262
35550
  try {
35263
- _internals7.gitExec(["checkout", "--", "."], cwd);
35551
+ _internals8.gitExec(["checkout", "--", "."], cwd);
35264
35552
  discardSucceeded = true;
35265
35553
  break;
35266
35554
  } catch {}
@@ -35271,18 +35559,18 @@ function resetToMainAfterMerge(cwd, options) {
35271
35559
  changesDiscarded = discardSucceeded;
35272
35560
  }
35273
35561
  try {
35274
- _internals7.gitExec(["clean", "-fd"], cwd);
35562
+ _internals8.gitExec(["clean", "-fd"], cwd);
35275
35563
  } catch {
35276
35564
  warnings.push("Could not clean untracked files");
35277
35565
  }
35278
35566
  let branchDeleted = false;
35279
35567
  if (switchedBranch && previousBranch !== defaultBranch) {
35280
35568
  try {
35281
- const mergedOutput = _internals7.gitExec(["branch", "--merged", defaultBranch], cwd);
35569
+ const mergedOutput = _internals8.gitExec(["branch", "--merged", defaultBranch], cwd);
35282
35570
  const isMerged = mergedOutput.split(`
35283
35571
  `).some((line) => line.trim() === previousBranch || line.trim() === `* ${previousBranch}`);
35284
35572
  if (isMerged) {
35285
- _internals7.gitExec(["branch", "-d", previousBranch], cwd);
35573
+ _internals8.gitExec(["branch", "-d", previousBranch], cwd);
35286
35574
  branchDeleted = true;
35287
35575
  } else {
35288
35576
  warnings.push(`Branch ${previousBranch} is not merged into ${defaultBranch} \u2014 keeping it`);
@@ -35293,7 +35581,7 @@ function resetToMainAfterMerge(cwd, options) {
35293
35581
  }
35294
35582
  if (options?.pruneBranches) {
35295
35583
  try {
35296
- const mergedOutput = _internals7.gitExec(["branch", "--merged", defaultBranch], cwd);
35584
+ const mergedOutput = _internals8.gitExec(["branch", "--merged", defaultBranch], cwd);
35297
35585
  const mergedLines = mergedOutput.split(`
35298
35586
  `);
35299
35587
  for (const line of mergedLines) {
@@ -35302,7 +35590,7 @@ function resetToMainAfterMerge(cwd, options) {
35302
35590
  continue;
35303
35591
  }
35304
35592
  try {
35305
- _internals7.gitExec(["branch", "-d", trimmedLine], cwd);
35593
+ _internals8.gitExec(["branch", "-d", trimmedLine], cwd);
35306
35594
  } catch {
35307
35595
  warnings.push(`Could not prune branch: ${trimmedLine}`);
35308
35596
  }
@@ -35332,10 +35620,10 @@ function resetToMainAfterMerge(cwd, options) {
35332
35620
  };
35333
35621
  }
35334
35622
  }
35335
- var GIT_TIMEOUT_MS2 = 30000, _internals7;
35623
+ var GIT_TIMEOUT_MS2 = 30000, _internals8;
35336
35624
  var init_branch = __esm(() => {
35337
35625
  init_logger();
35338
- _internals7 = {
35626
+ _internals8 = {
35339
35627
  gitExec: gitExec2,
35340
35628
  detectDefaultRemoteBranch,
35341
35629
  getDefaultBaseBranch,
@@ -36529,7 +36817,7 @@ async function curateAndStoreSwarm(lessons, projectName, phaseInfo, directory, c
36529
36817
  existingEntries.push(entry);
36530
36818
  }
36531
36819
  await enforceKnowledgeCap(knowledgePath, config3.swarm_max_entries);
36532
- await _internals8.runAutoPromotion(directory, config3);
36820
+ await _internals9.runAutoPromotion(directory, config3);
36533
36821
  return { stored, skipped, rejected };
36534
36822
  }
36535
36823
  async function runAutoPromotion(directory, config3) {
@@ -36610,7 +36898,7 @@ function createKnowledgeCuratorHook(directory, config3) {
36610
36898
  });
36611
36899
  const projectName2 = evidenceData.project_name ?? "unknown";
36612
36900
  const phaseNumber2 = typeof evidenceData.phase_number === "number" ? evidenceData.phase_number : 1;
36613
- await _internals8.curateAndStoreSwarm(lessons, projectName2, { phase_number: phaseNumber2 }, directory, config3);
36901
+ await _internals9.curateAndStoreSwarm(lessons, projectName2, { phase_number: phaseNumber2 }, directory, config3);
36614
36902
  return;
36615
36903
  }
36616
36904
  const planContent = await readSwarmFileAsync(directory, "plan.md");
@@ -36632,17 +36920,17 @@ function createKnowledgeCuratorHook(directory, config3) {
36632
36920
  const projectName = projectNameMatch ? projectNameMatch[1].trim() : "unknown";
36633
36921
  const phaseMatch = /^Phase:\s*(\d+)/m.exec(planContent);
36634
36922
  const phaseNumber = phaseMatch ? parseInt(phaseMatch[1], 10) : 1;
36635
- await _internals8.curateAndStoreSwarm(normalLessons, projectName, { phase_number: phaseNumber }, directory, config3);
36923
+ await _internals9.curateAndStoreSwarm(normalLessons, projectName, { phase_number: phaseNumber }, directory, config3);
36636
36924
  };
36637
36925
  return safeHook(handler);
36638
36926
  }
36639
- var seenRetroSections, _internals8;
36927
+ var seenRetroSections, _internals9;
36640
36928
  var init_knowledge_curator = __esm(() => {
36641
36929
  init_knowledge_store();
36642
36930
  init_knowledge_validator();
36643
36931
  init_utils2();
36644
36932
  seenRetroSections = new Map;
36645
- _internals8 = {
36933
+ _internals9 = {
36646
36934
  isWriteToEvidenceFile,
36647
36935
  curateAndStoreSwarm,
36648
36936
  runAutoPromotion,
@@ -37849,7 +38137,7 @@ async function executeWriteRetro(args, directory) {
37849
38137
  }, null, 2);
37850
38138
  }
37851
38139
  }
37852
- var write_retro, _internals9;
38140
+ var write_retro, _internals10;
37853
38141
  var init_write_retro = __esm(() => {
37854
38142
  init_zod();
37855
38143
  init_evidence_schema();
@@ -37896,13 +38184,13 @@ var init_write_retro = __esm(() => {
37896
38184
  task_id: args.task_id !== undefined ? String(args.task_id) : undefined,
37897
38185
  metadata: args.metadata
37898
38186
  };
37899
- return await _internals9.executeWriteRetro(writeRetroArgs, directory);
38187
+ return await _internals10.executeWriteRetro(writeRetroArgs, directory);
37900
38188
  } catch {
37901
38189
  return JSON.stringify({ success: false, phase: rawPhase, message: "Invalid arguments" }, null, 2);
37902
38190
  }
37903
38191
  }
37904
38192
  });
37905
- _internals9 = {
38193
+ _internals10 = {
37906
38194
  executeWriteRetro,
37907
38195
  write_retro
37908
38196
  };
@@ -38193,6 +38481,12 @@ async function handleCloseCommand(directory, args, options = {}) {
38193
38481
  }
38194
38482
  }
38195
38483
  if (planExists) {
38484
+ const originalStatuses = new Map;
38485
+ for (const phase of planData.phases ?? []) {
38486
+ for (const task of phase.tasks ?? []) {
38487
+ originalStatuses.set(task.id, task.status);
38488
+ }
38489
+ }
38196
38490
  const guaranteeResult = guaranteeAllPlansComplete(planData);
38197
38491
  for (const phaseId of guaranteeResult.closedPhaseIds) {
38198
38492
  if (!closedPhases.includes(phaseId)) {
@@ -38206,11 +38500,15 @@ async function handleCloseCommand(directory, args, options = {}) {
38206
38500
  }
38207
38501
  if (!planAlreadyDone || guaranteeResult.closedPhaseIds.length > 0 || guaranteeResult.closedTaskIds.length > 0) {
38208
38502
  try {
38209
- await fs7.writeFile(planPath, JSON.stringify(planData, null, 2), "utf-8");
38503
+ await closePlanTerminalState(directory, planData, {
38504
+ closedPhaseIds: guaranteeResult.closedPhaseIds,
38505
+ closedTaskIds: guaranteeResult.closedTaskIds,
38506
+ originalStatuses
38507
+ });
38210
38508
  } catch (error93) {
38211
38509
  const msg = error93 instanceof Error ? error93.message : String(error93);
38212
- warnings.push(`Failed to persist terminal plan.json state: ${msg}`);
38213
- console.warn("[close-command] Failed to write plan.json:", error93);
38510
+ warnings.push(`Failed to persist terminal plan state: ${msg}`);
38511
+ console.warn("[close-command] Failed to write terminal plan state:", error93);
38214
38512
  }
38215
38513
  }
38216
38514
  }
@@ -38498,6 +38796,7 @@ var init_close = __esm(() => {
38498
38796
  init_knowledge_curator();
38499
38797
  init_knowledge_store();
38500
38798
  init_utils2();
38799
+ init_manager();
38501
38800
  init_scope_persistence();
38502
38801
  init_skill_improver();
38503
38802
  init_state();
@@ -38906,9 +39205,9 @@ async function detectDarkMatter(directory, options) {
38906
39205
  } catch {
38907
39206
  return [];
38908
39207
  }
38909
- const commitMap = await _internals10.parseGitLog(directory, maxCommitsToAnalyze);
38910
- const matrix = _internals10.buildCoChangeMatrix(commitMap);
38911
- const staticEdges = await _internals10.getStaticEdges(directory);
39208
+ const commitMap = await _internals11.parseGitLog(directory, maxCommitsToAnalyze);
39209
+ const matrix = _internals11.buildCoChangeMatrix(commitMap);
39210
+ const staticEdges = await _internals11.getStaticEdges(directory);
38912
39211
  const results = [];
38913
39212
  for (const entry of matrix.values()) {
38914
39213
  const key = `${entry.fileA}::${entry.fileB}`;
@@ -38988,7 +39287,7 @@ ${rows}
38988
39287
  These pairs likely share an architectural concern invisible to static analysis.
38989
39288
  Consider adding explicit documentation or extracting the shared concern.`;
38990
39289
  }
38991
- var co_change_analyzer, _internals10;
39290
+ var co_change_analyzer, _internals11;
38992
39291
  var init_co_change_analyzer = __esm(() => {
38993
39292
  init_zod();
38994
39293
  init_create_tool();
@@ -39020,11 +39319,11 @@ var init_co_change_analyzer = __esm(() => {
39020
39319
  npmiThreshold,
39021
39320
  maxCommitsToAnalyze
39022
39321
  };
39023
- const pairs = await _internals10.detectDarkMatter(directory, options);
39024
- return _internals10.formatDarkMatterOutput(pairs);
39322
+ const pairs = await _internals11.detectDarkMatter(directory, options);
39323
+ return _internals11.formatDarkMatterOutput(pairs);
39025
39324
  }
39026
39325
  });
39027
- _internals10 = {
39326
+ _internals11 = {
39028
39327
  parseGitLog,
39029
39328
  buildCoChangeMatrix,
39030
39329
  getStaticEdges,
@@ -39055,7 +39354,7 @@ async function handleDarkMatterCommand(directory, args) {
39055
39354
  }
39056
39355
  let pairs;
39057
39356
  try {
39058
- pairs = await _internals10.detectDarkMatter(directory, options);
39357
+ pairs = await _internals11.detectDarkMatter(directory, options);
39059
39358
  } catch (err) {
39060
39359
  const errMsg = err instanceof Error ? err.message : String(err);
39061
39360
  return `## Dark Matter Analysis Failed
@@ -39247,24 +39546,213 @@ function getPluginLockFilePaths() {
39247
39546
  }
39248
39547
  var init_cache_paths = () => {};
39249
39548
 
39549
+ // src/evidence/task-file.ts
39550
+ import * as path21 from "path";
39551
+ function taskEvidenceRelPath(taskId) {
39552
+ return path21.join("evidence", `${taskId}.json`);
39553
+ }
39554
+ function taskEvidencePath(directory, taskId) {
39555
+ return path21.join(directory, ".swarm", taskEvidenceRelPath(taskId));
39556
+ }
39557
+ var init_task_file = __esm(() => {
39558
+ init_bun_compat();
39559
+ init_lock();
39560
+ });
39561
+
39562
+ // src/gate-evidence.ts
39563
+ import { mkdirSync as mkdirSync7, readFileSync as readFileSync6 } from "fs";
39564
+ function isValidTaskId(taskId) {
39565
+ return isStrictTaskId(taskId);
39566
+ }
39567
+ function assertValidTaskId(taskId) {
39568
+ assertStrictTaskId(taskId);
39569
+ }
39570
+ function getEvidencePath(directory, taskId) {
39571
+ assertValidTaskId(taskId);
39572
+ return taskEvidencePath(directory, taskId);
39573
+ }
39574
+ function readExisting(evidencePath, taskId) {
39575
+ try {
39576
+ const raw = readFileSync6(evidencePath, "utf-8");
39577
+ return TaskEvidenceSchema.parse(JSON.parse(raw));
39578
+ } catch (error93) {
39579
+ if (error93.code === "ENOENT")
39580
+ return null;
39581
+ telemetry.gateParseError(taskId, error93);
39582
+ throw error93;
39583
+ }
39584
+ }
39585
+ async function readTaskEvidence(directory, taskId) {
39586
+ try {
39587
+ assertValidTaskId(taskId);
39588
+ return readExisting(getEvidencePath(directory, taskId), taskId);
39589
+ } catch {
39590
+ return null;
39591
+ }
39592
+ }
39593
+ function readTaskEvidenceRaw(directory, taskId) {
39594
+ assertValidTaskId(taskId);
39595
+ const evidencePath = getEvidencePath(directory, taskId);
39596
+ try {
39597
+ const raw = readFileSync6(evidencePath, "utf-8");
39598
+ return TaskEvidenceSchema.parse(JSON.parse(raw));
39599
+ } catch (error93) {
39600
+ if (error93.code === "ENOENT")
39601
+ return null;
39602
+ throw error93;
39603
+ }
39604
+ }
39605
+ var GateEvidenceSchema, TaskEvidenceSchema;
39606
+ var init_gate_evidence = __esm(() => {
39607
+ init_zod();
39608
+ init_task_file();
39609
+ init_telemetry();
39610
+ init_task_id();
39611
+ GateEvidenceSchema = exports_external.object({
39612
+ sessionId: exports_external.string(),
39613
+ timestamp: exports_external.string(),
39614
+ agent: exports_external.string()
39615
+ }).passthrough();
39616
+ TaskEvidenceSchema = exports_external.object({
39617
+ taskId: exports_external.string(),
39618
+ required_gates: exports_external.array(exports_external.string()).default([]),
39619
+ gates: exports_external.record(exports_external.string(), GateEvidenceSchema),
39620
+ turbo: exports_external.boolean().optional()
39621
+ });
39622
+ });
39623
+
39624
+ // src/evidence/gate-bridge.ts
39625
+ async function readDurableGateEvidence(directory, taskId) {
39626
+ try {
39627
+ return await readTaskEvidence(directory, taskId);
39628
+ } catch {
39629
+ return null;
39630
+ }
39631
+ }
39632
+ function getDurableGateEvidenceStatus(evidence) {
39633
+ if (!evidence?.gates || typeof evidence.gates !== "object") {
39634
+ return {
39635
+ isComplete: false,
39636
+ missingGates: [],
39637
+ evidenceExists: evidence != null,
39638
+ invalid: false
39639
+ };
39640
+ }
39641
+ if (!Array.isArray(evidence.required_gates) || evidence.required_gates.length === 0) {
39642
+ return {
39643
+ isComplete: false,
39644
+ missingGates: ["required_gates"],
39645
+ evidenceExists: true,
39646
+ invalid: false
39647
+ };
39648
+ }
39649
+ const missingGates = evidence.required_gates.filter((gate) => evidence.gates[gate] == null);
39650
+ return {
39651
+ isComplete: missingGates.length === 0,
39652
+ missingGates,
39653
+ evidenceExists: true,
39654
+ invalid: false
39655
+ };
39656
+ }
39657
+ async function getDurableGateEvidenceStatusForTask(directory, taskId) {
39658
+ if (!isValidTaskId(taskId)) {
39659
+ return {
39660
+ isComplete: false,
39661
+ missingGates: [],
39662
+ evidenceExists: false,
39663
+ invalid: false
39664
+ };
39665
+ }
39666
+ try {
39667
+ return getDurableGateEvidenceStatus(readTaskEvidenceRaw(directory, taskId));
39668
+ } catch {
39669
+ return {
39670
+ isComplete: false,
39671
+ missingGates: ["invalid_gate_evidence"],
39672
+ evidenceExists: true,
39673
+ invalid: true
39674
+ };
39675
+ }
39676
+ }
39677
+ function gateEvidenceToEntry(taskId, gate, type, evidence) {
39678
+ const gateRecord = evidence.gates[gate];
39679
+ if (!gateRecord) {
39680
+ return null;
39681
+ }
39682
+ const base = {
39683
+ task_id: taskId,
39684
+ timestamp: gateRecord.timestamp,
39685
+ agent: gateRecord.agent || gate,
39686
+ verdict: "pass",
39687
+ summary: `Gate evidence recorded by ${gate}`,
39688
+ metadata: { source: "durable_gate_evidence", gate }
39689
+ };
39690
+ if (type === "review") {
39691
+ return {
39692
+ ...base,
39693
+ type,
39694
+ risk: "low",
39695
+ issues: []
39696
+ };
39697
+ }
39698
+ if (type === "approval") {
39699
+ return {
39700
+ ...base,
39701
+ type
39702
+ };
39703
+ }
39704
+ return {
39705
+ ...base,
39706
+ type,
39707
+ tests_passed: 0,
39708
+ tests_failed: 0,
39709
+ failures: []
39710
+ };
39711
+ }
39712
+ function mergeDurableGateEntriesFromEvidence(taskId, entries, evidence) {
39713
+ if (!evidence?.gates) {
39714
+ return entries;
39715
+ }
39716
+ const merged = [...entries];
39717
+ for (const gate of Object.keys(evidence.gates).sort()) {
39718
+ const type = GATE_EVIDENCE_TYPE_BY_GATE[gate] ?? "approval";
39719
+ if ((type === "review" || type === "test") && merged.some((entry2) => entry2.type === type)) {
39720
+ continue;
39721
+ }
39722
+ const entry = gateEvidenceToEntry(taskId, gate, type, evidence);
39723
+ if (entry) {
39724
+ merged.push(entry);
39725
+ }
39726
+ }
39727
+ return merged;
39728
+ }
39729
+ var GATE_EVIDENCE_TYPE_BY_GATE;
39730
+ var init_gate_bridge = __esm(() => {
39731
+ init_gate_evidence();
39732
+ GATE_EVIDENCE_TYPE_BY_GATE = {
39733
+ reviewer: "review",
39734
+ test_engineer: "test"
39735
+ };
39736
+ });
39737
+
39250
39738
  // src/services/version-check.ts
39251
- import { existsSync as existsSync11, mkdirSync as mkdirSync7, readFileSync as readFileSync6, writeFileSync as writeFileSync4 } from "fs";
39739
+ import { existsSync as existsSync11, mkdirSync as mkdirSync8, readFileSync as readFileSync7, writeFileSync as writeFileSync4 } from "fs";
39252
39740
  import { homedir as homedir5 } from "os";
39253
- import { join as join19 } from "path";
39741
+ import { join as join20 } from "path";
39254
39742
  function cacheDir() {
39255
39743
  const xdg = process.env.XDG_CACHE_HOME;
39256
- const base = xdg && xdg.length > 0 ? xdg : join19(homedir5(), ".cache");
39257
- return join19(base, "opencode-swarm");
39744
+ const base = xdg && xdg.length > 0 ? xdg : join20(homedir5(), ".cache");
39745
+ return join20(base, "opencode-swarm");
39258
39746
  }
39259
39747
  function cacheFile() {
39260
- return join19(cacheDir(), "version-check.json");
39748
+ return join20(cacheDir(), "version-check.json");
39261
39749
  }
39262
39750
  function readVersionCache() {
39263
39751
  try {
39264
- const path21 = cacheFile();
39265
- if (!existsSync11(path21))
39752
+ const path22 = cacheFile();
39753
+ if (!existsSync11(path22))
39266
39754
  return null;
39267
- const raw = readFileSync6(path21, "utf-8");
39755
+ const raw = readFileSync7(path22, "utf-8");
39268
39756
  const parsed = JSON.parse(raw);
39269
39757
  if (typeof parsed?.checkedAt !== "number")
39270
39758
  return null;
@@ -39303,8 +39791,8 @@ var init_version_check = __esm(() => {
39303
39791
 
39304
39792
  // src/services/diagnose-service.ts
39305
39793
  import * as child_process4 from "child_process";
39306
- import { existsSync as existsSync12, readdirSync as readdirSync4, readFileSync as readFileSync7, statSync as statSync6 } from "fs";
39307
- import path21 from "path";
39794
+ import { existsSync as existsSync12, readdirSync as readdirSync4, readFileSync as readFileSync8, statSync as statSync6 } from "fs";
39795
+ import path22 from "path";
39308
39796
  import { fileURLToPath } from "url";
39309
39797
  function validateTaskDag(plan) {
39310
39798
  const allTaskIds = new Set;
@@ -39336,7 +39824,21 @@ async function checkEvidenceCompleteness(directory, plan) {
39336
39824
  }
39337
39825
  if (completedTaskIds.length > 0) {
39338
39826
  const evidenceTaskIds = new Set(await listEvidenceTaskIds(directory));
39339
- const missingEvidence = completedTaskIds.filter((id) => !evidenceTaskIds.has(id));
39827
+ const missingEvidence = [];
39828
+ for (const id of completedTaskIds) {
39829
+ const gateStatus = await getDurableGateEvidenceStatusForTask(directory, id);
39830
+ if (gateStatus.isComplete) {
39831
+ continue;
39832
+ }
39833
+ if (gateStatus.evidenceExists && gateStatus.missingGates.length > 0) {
39834
+ missingEvidence.push(id);
39835
+ continue;
39836
+ }
39837
+ if (evidenceTaskIds.has(id)) {
39838
+ continue;
39839
+ }
39840
+ missingEvidence.push(id);
39841
+ }
39340
39842
  if (missingEvidence.length === 0) {
39341
39843
  return {
39342
39844
  name: "Evidence",
@@ -39601,7 +40103,7 @@ async function checkSpecStaleness(directory, plan) {
39601
40103
  };
39602
40104
  }
39603
40105
  async function checkConfigParseability(directory) {
39604
- const configPath = path21.join(directory, ".opencode/opencode-swarm.json");
40106
+ const configPath = path22.join(directory, ".opencode/opencode-swarm.json");
39605
40107
  if (!existsSync12(configPath)) {
39606
40108
  return {
39607
40109
  name: "Config Parseability",
@@ -39610,7 +40112,7 @@ async function checkConfigParseability(directory) {
39610
40112
  };
39611
40113
  }
39612
40114
  try {
39613
- const content = readFileSync7(configPath, "utf-8");
40115
+ const content = readFileSync8(configPath, "utf-8");
39614
40116
  JSON.parse(content);
39615
40117
  return {
39616
40118
  name: "Config Parseability",
@@ -39630,7 +40132,7 @@ function resolveGrammarDir(thisDir) {
39630
40132
  const normalized = thisDir.replace(/\\/g, "/");
39631
40133
  const isSource = normalized.endsWith("/src/services");
39632
40134
  const isCliBundle = normalized.endsWith("/cli");
39633
- return isSource || isCliBundle ? path21.join(thisDir, "..", "lang", "grammars") : path21.join(thisDir, "lang", "grammars");
40135
+ return isSource || isCliBundle ? path22.join(thisDir, "..", "lang", "grammars") : path22.join(thisDir, "lang", "grammars");
39634
40136
  }
39635
40137
  async function checkGrammarWasmFiles() {
39636
40138
  const grammarFiles = [
@@ -39654,14 +40156,14 @@ async function checkGrammarWasmFiles() {
39654
40156
  "tree-sitter-ini.wasm",
39655
40157
  "tree-sitter-regex.wasm"
39656
40158
  ];
39657
- const thisDir = path21.dirname(fileURLToPath(import.meta.url));
40159
+ const thisDir = path22.dirname(fileURLToPath(import.meta.url));
39658
40160
  const grammarDir = resolveGrammarDir(thisDir);
39659
40161
  const missing = [];
39660
- if (!existsSync12(path21.join(grammarDir, "tree-sitter.wasm"))) {
40162
+ if (!existsSync12(path22.join(grammarDir, "tree-sitter.wasm"))) {
39661
40163
  missing.push("tree-sitter.wasm (core runtime)");
39662
40164
  }
39663
40165
  for (const file3 of grammarFiles) {
39664
- if (!existsSync12(path21.join(grammarDir, file3))) {
40166
+ if (!existsSync12(path22.join(grammarDir, file3))) {
39665
40167
  missing.push(file3);
39666
40168
  }
39667
40169
  }
@@ -39679,7 +40181,7 @@ async function checkGrammarWasmFiles() {
39679
40181
  };
39680
40182
  }
39681
40183
  async function checkCheckpointManifest(directory) {
39682
- const manifestPath = path21.join(directory, ".swarm/checkpoints.json");
40184
+ const manifestPath = path22.join(directory, ".swarm/checkpoints.json");
39683
40185
  if (!existsSync12(manifestPath)) {
39684
40186
  return {
39685
40187
  name: "Checkpoint Manifest",
@@ -39688,7 +40190,7 @@ async function checkCheckpointManifest(directory) {
39688
40190
  };
39689
40191
  }
39690
40192
  try {
39691
- const content = readFileSync7(manifestPath, "utf-8");
40193
+ const content = readFileSync8(manifestPath, "utf-8");
39692
40194
  const parsed = JSON.parse(content);
39693
40195
  if (!parsed.checkpoints || !Array.isArray(parsed.checkpoints)) {
39694
40196
  return {
@@ -39731,7 +40233,7 @@ async function checkCheckpointManifest(directory) {
39731
40233
  }
39732
40234
  }
39733
40235
  async function checkEventStreamIntegrity(directory) {
39734
- const eventsPath = path21.join(directory, ".swarm/events.jsonl");
40236
+ const eventsPath = path22.join(directory, ".swarm/events.jsonl");
39735
40237
  if (!existsSync12(eventsPath)) {
39736
40238
  return {
39737
40239
  name: "Event Stream",
@@ -39740,7 +40242,7 @@ async function checkEventStreamIntegrity(directory) {
39740
40242
  };
39741
40243
  }
39742
40244
  try {
39743
- const content = readFileSync7(eventsPath, "utf-8");
40245
+ const content = readFileSync8(eventsPath, "utf-8");
39744
40246
  const lines = content.split(`
39745
40247
  `).filter((line) => line.trim() !== "");
39746
40248
  let malformedCount = 0;
@@ -39772,7 +40274,7 @@ async function checkEventStreamIntegrity(directory) {
39772
40274
  }
39773
40275
  }
39774
40276
  async function checkSteeringDirectives(directory) {
39775
- const eventsPath = path21.join(directory, ".swarm/events.jsonl");
40277
+ const eventsPath = path22.join(directory, ".swarm/events.jsonl");
39776
40278
  if (!existsSync12(eventsPath)) {
39777
40279
  return {
39778
40280
  name: "Steering Directives",
@@ -39781,7 +40283,7 @@ async function checkSteeringDirectives(directory) {
39781
40283
  };
39782
40284
  }
39783
40285
  try {
39784
- const content = readFileSync7(eventsPath, "utf-8");
40286
+ const content = readFileSync8(eventsPath, "utf-8");
39785
40287
  const lines = content.split(`
39786
40288
  `).filter((line) => line.trim() !== "");
39787
40289
  const directivesIssued = [];
@@ -39828,7 +40330,7 @@ async function checkCurator(directory) {
39828
40330
  detail: "Disabled (enable via curator.enabled)"
39829
40331
  };
39830
40332
  }
39831
- const summaryPath = path21.join(directory, ".swarm/curator-summary.json");
40333
+ const summaryPath = path22.join(directory, ".swarm/curator-summary.json");
39832
40334
  if (!existsSync12(summaryPath)) {
39833
40335
  return {
39834
40336
  name: "Curator",
@@ -39837,7 +40339,7 @@ async function checkCurator(directory) {
39837
40339
  };
39838
40340
  }
39839
40341
  try {
39840
- const content = readFileSync7(summaryPath, "utf-8");
40342
+ const content = readFileSync8(summaryPath, "utf-8");
39841
40343
  const parsed = JSON.parse(content);
39842
40344
  if (typeof parsed.schema_version !== "number" || parsed.schema_version !== 1) {
39843
40345
  return {
@@ -39994,7 +40496,7 @@ async function getDiagnoseData(directory) {
39994
40496
  checks5.push(await checkSteeringDirectives(directory));
39995
40497
  checks5.push(await checkCurator(directory));
39996
40498
  try {
39997
- const evidenceDir = path21.join(directory, ".swarm", "evidence");
40499
+ const evidenceDir = path22.join(directory, ".swarm", "evidence");
39998
40500
  const snapshotFiles = existsSync12(evidenceDir) ? readdirSync4(evidenceDir).filter((f) => f.startsWith("agent-tools-") && f.endsWith(".json")) : [];
39999
40501
  if (snapshotFiles.length > 0) {
40000
40502
  const latest = snapshotFiles.sort().pop();
@@ -40032,9 +40534,9 @@ async function getDiagnoseData(directory) {
40032
40534
  cacheRows.push(`\u2B1C ${cachePath} \u2014 absent`);
40033
40535
  continue;
40034
40536
  }
40035
- const pkgJsonPath = path21.join(cachePath, "package.json");
40537
+ const pkgJsonPath = path22.join(cachePath, "package.json");
40036
40538
  try {
40037
- const raw = readFileSync7(pkgJsonPath, "utf-8");
40539
+ const raw = readFileSync8(pkgJsonPath, "utf-8");
40038
40540
  const parsed = JSON.parse(raw);
40039
40541
  const installedVersion = typeof parsed.version === "string" ? parsed.version : "?";
40040
40542
  cacheRows.push(`\u2705 ${cachePath} \u2014 v${installedVersion}`);
@@ -40091,6 +40593,7 @@ var init_diagnose_service = __esm(() => {
40091
40593
  init_package();
40092
40594
  init_cache_paths();
40093
40595
  init_loader();
40596
+ init_gate_bridge();
40094
40597
  init_manager2();
40095
40598
  init_utils2();
40096
40599
  init_manager();
@@ -40122,13 +40625,13 @@ __export(exports_config_doctor, {
40122
40625
  import * as crypto3 from "crypto";
40123
40626
  import * as fs8 from "fs";
40124
40627
  import * as os6 from "os";
40125
- import * as path22 from "path";
40628
+ import * as path23 from "path";
40126
40629
  function getUserConfigDir3() {
40127
- return process.env.XDG_CONFIG_HOME || path22.join(os6.homedir(), ".config");
40630
+ return process.env.XDG_CONFIG_HOME || path23.join(os6.homedir(), ".config");
40128
40631
  }
40129
40632
  function getConfigPaths(directory) {
40130
- const userConfigPath = path22.join(getUserConfigDir3(), "opencode", "opencode-swarm.json");
40131
- const projectConfigPath = path22.join(directory, ".opencode", "opencode-swarm.json");
40633
+ const userConfigPath = path23.join(getUserConfigDir3(), "opencode", "opencode-swarm.json");
40634
+ const projectConfigPath = path23.join(directory, ".opencode", "opencode-swarm.json");
40132
40635
  return { userConfigPath, projectConfigPath };
40133
40636
  }
40134
40637
  function computeHash(content) {
@@ -40153,9 +40656,9 @@ function isValidConfigPath(configPath, directory) {
40153
40656
  const normalizedUser = userConfigPath.replace(/\\/g, "/");
40154
40657
  const normalizedProject = projectConfigPath.replace(/\\/g, "/");
40155
40658
  try {
40156
- const resolvedConfig = path22.resolve(configPath);
40157
- const resolvedUser = path22.resolve(normalizedUser);
40158
- const resolvedProject = path22.resolve(normalizedProject);
40659
+ const resolvedConfig = path23.resolve(configPath);
40660
+ const resolvedUser = path23.resolve(normalizedUser);
40661
+ const resolvedProject = path23.resolve(normalizedProject);
40159
40662
  return resolvedConfig === resolvedUser || resolvedConfig === resolvedProject;
40160
40663
  } catch {
40161
40664
  return false;
@@ -40195,12 +40698,12 @@ function createConfigBackup(directory) {
40195
40698
  };
40196
40699
  }
40197
40700
  function writeBackupArtifact(directory, backup) {
40198
- const swarmDir = path22.join(directory, ".swarm");
40701
+ const swarmDir = path23.join(directory, ".swarm");
40199
40702
  if (!fs8.existsSync(swarmDir)) {
40200
40703
  fs8.mkdirSync(swarmDir, { recursive: true });
40201
40704
  }
40202
40705
  const backupFilename = `config-backup-${backup.createdAt}.json`;
40203
- const backupPath = path22.join(swarmDir, backupFilename);
40706
+ const backupPath = path23.join(swarmDir, backupFilename);
40204
40707
  const artifact = {
40205
40708
  createdAt: backup.createdAt,
40206
40709
  configPath: backup.configPath,
@@ -40230,7 +40733,7 @@ function restoreFromBackup(backupPath, directory) {
40230
40733
  return null;
40231
40734
  }
40232
40735
  const targetPath = artifact.configPath;
40233
- const targetDir = path22.dirname(targetPath);
40736
+ const targetDir = path23.dirname(targetPath);
40234
40737
  if (!fs8.existsSync(targetDir)) {
40235
40738
  fs8.mkdirSync(targetDir, { recursive: true });
40236
40739
  }
@@ -40261,9 +40764,9 @@ function readConfigFromFile(directory) {
40261
40764
  return null;
40262
40765
  }
40263
40766
  }
40264
- function validateConfigKey(path23, value, _config) {
40767
+ function validateConfigKey(path24, value, _config) {
40265
40768
  const findings = [];
40266
- switch (path23) {
40769
+ switch (path24) {
40267
40770
  case "agents": {
40268
40771
  if (value !== undefined) {
40269
40772
  findings.push({
@@ -40500,27 +41003,27 @@ function validateConfigKey(path23, value, _config) {
40500
41003
  }
40501
41004
  return findings;
40502
41005
  }
40503
- function walkConfigAndValidate(obj, path23, config3, findings) {
41006
+ function walkConfigAndValidate(obj, path24, config3, findings) {
40504
41007
  if (obj === null || obj === undefined) {
40505
41008
  return;
40506
41009
  }
40507
- if (path23 && typeof obj === "object" && !Array.isArray(obj)) {
40508
- const keyFindings = validateConfigKey(path23, obj, config3);
41010
+ if (path24 && typeof obj === "object" && !Array.isArray(obj)) {
41011
+ const keyFindings = validateConfigKey(path24, obj, config3);
40509
41012
  findings.push(...keyFindings);
40510
41013
  }
40511
41014
  if (typeof obj !== "object") {
40512
- const keyFindings = validateConfigKey(path23, obj, config3);
41015
+ const keyFindings = validateConfigKey(path24, obj, config3);
40513
41016
  findings.push(...keyFindings);
40514
41017
  return;
40515
41018
  }
40516
41019
  if (Array.isArray(obj)) {
40517
41020
  obj.forEach((item, index) => {
40518
- walkConfigAndValidate(item, `${path23}[${index}]`, config3, findings);
41021
+ walkConfigAndValidate(item, `${path24}[${index}]`, config3, findings);
40519
41022
  });
40520
41023
  return;
40521
41024
  }
40522
41025
  for (const [key, value] of Object.entries(obj)) {
40523
- const newPath = path23 ? `${path23}.${key}` : key;
41026
+ const newPath = path24 ? `${path24}.${key}` : key;
40524
41027
  walkConfigAndValidate(value, newPath, config3, findings);
40525
41028
  }
40526
41029
  }
@@ -40640,7 +41143,7 @@ function applySafeAutoFixes(directory, result) {
40640
41143
  }
40641
41144
  }
40642
41145
  if (appliedFixes.length > 0) {
40643
- const configDir = path22.dirname(configPath);
41146
+ const configDir = path23.dirname(configPath);
40644
41147
  if (!fs8.existsSync(configDir)) {
40645
41148
  fs8.mkdirSync(configDir, { recursive: true });
40646
41149
  }
@@ -40650,12 +41153,12 @@ function applySafeAutoFixes(directory, result) {
40650
41153
  return { appliedFixes, updatedConfigPath };
40651
41154
  }
40652
41155
  function writeDoctorArtifact(directory, result) {
40653
- const swarmDir = path22.join(directory, ".swarm");
41156
+ const swarmDir = path23.join(directory, ".swarm");
40654
41157
  if (!fs8.existsSync(swarmDir)) {
40655
41158
  fs8.mkdirSync(swarmDir, { recursive: true });
40656
41159
  }
40657
41160
  const artifactFilename = "config-doctor.json";
40658
- const artifactPath = path22.join(swarmDir, artifactFilename);
41161
+ const artifactPath = path23.join(swarmDir, artifactFilename);
40659
41162
  const guiOutput = {
40660
41163
  timestamp: result.timestamp,
40661
41164
  summary: result.summary,
@@ -40751,17 +41254,17 @@ function detectStraySwarmDirs(projectRoot) {
40751
41254
  if (!entry.isDirectory())
40752
41255
  continue;
40753
41256
  const name = entry.name;
40754
- const fullPath = path22.join(dir, name);
41257
+ const fullPath = path23.join(dir, name);
40755
41258
  if (SKIP_DIRS.has(name))
40756
41259
  continue;
40757
- const gitPath = path22.join(fullPath, ".git");
41260
+ const gitPath = path23.join(fullPath, ".git");
40758
41261
  try {
40759
41262
  const gitStat = fs8.statSync(gitPath);
40760
41263
  if (gitStat.isFile() || gitStat.isDirectory())
40761
41264
  continue;
40762
41265
  } catch {}
40763
41266
  if (name === ".swarm") {
40764
- const parentDir = path22.dirname(fullPath);
41267
+ const parentDir = path23.dirname(fullPath);
40765
41268
  if (parentDir === projectRoot)
40766
41269
  continue;
40767
41270
  let contents = [];
@@ -40771,7 +41274,7 @@ function detectStraySwarmDirs(projectRoot) {
40771
41274
  contents = ["<unreadable>"];
40772
41275
  }
40773
41276
  findings.push({
40774
- path: path22.relative(projectRoot, fullPath).replace(/\\/g, "/"),
41277
+ path: path23.relative(projectRoot, fullPath).replace(/\\/g, "/"),
40775
41278
  absolutePath: fullPath,
40776
41279
  contents: contents.slice(0, MAX_CONTENTS_ENTRIES),
40777
41280
  totalEntries: contents.length
@@ -40789,21 +41292,21 @@ function removeStraySwarmDir(projectRoot, strayPath) {
40789
41292
  let canonicalStray;
40790
41293
  try {
40791
41294
  canonicalRoot = fs8.realpathSync(projectRoot);
40792
- canonicalStray = fs8.realpathSync(path22.isAbsolute(strayPath) ? strayPath : path22.resolve(projectRoot, strayPath));
41295
+ canonicalStray = fs8.realpathSync(path23.isAbsolute(strayPath) ? strayPath : path23.resolve(projectRoot, strayPath));
40793
41296
  } catch (err) {
40794
41297
  return {
40795
41298
  success: false,
40796
41299
  message: `Failed to resolve paths: ${err instanceof Error ? err.message : String(err)}`
40797
41300
  };
40798
41301
  }
40799
- const rootSwarm = path22.join(canonicalRoot, ".swarm");
41302
+ const rootSwarm = path23.join(canonicalRoot, ".swarm");
40800
41303
  if (canonicalStray === rootSwarm || canonicalStray === canonicalRoot) {
40801
41304
  return {
40802
41305
  success: false,
40803
41306
  message: "Refusing to remove root .swarm/ directory"
40804
41307
  };
40805
41308
  }
40806
- if (!canonicalStray.startsWith(canonicalRoot + path22.sep)) {
41309
+ if (!canonicalStray.startsWith(canonicalRoot + path23.sep)) {
40807
41310
  return {
40808
41311
  success: false,
40809
41312
  message: "Path is outside project root \u2014 refusing to remove"
@@ -41892,7 +42395,7 @@ var init_profiles = __esm(() => {
41892
42395
 
41893
42396
  // src/lang/detector.ts
41894
42397
  import { access as access3, readdir as readdir2 } from "fs/promises";
41895
- import { extname as extname2, join as join21 } from "path";
42398
+ import { extname as extname2, join as join22 } from "path";
41896
42399
  async function detectProjectLanguages(projectDir) {
41897
42400
  const detected = new Set;
41898
42401
  async function scanDir(dir) {
@@ -41908,7 +42411,7 @@ async function detectProjectLanguages(projectDir) {
41908
42411
  if (detectFile.includes("*") || detectFile.includes("?"))
41909
42412
  continue;
41910
42413
  try {
41911
- await access3(join21(dir, detectFile));
42414
+ await access3(join22(dir, detectFile));
41912
42415
  detected.add(profile.id);
41913
42416
  break;
41914
42417
  } catch {}
@@ -41929,7 +42432,7 @@ async function detectProjectLanguages(projectDir) {
41929
42432
  const topEntries = await readdir2(projectDir, { withFileTypes: true });
41930
42433
  for (const entry of topEntries) {
41931
42434
  if (entry.isDirectory() && !entry.name.startsWith(".") && entry.name !== "node_modules") {
41932
- await scanDir(join21(projectDir, entry.name));
42435
+ await scanDir(join22(projectDir, entry.name));
41933
42436
  }
41934
42437
  }
41935
42438
  } catch {}
@@ -41948,7 +42451,7 @@ var init_detector = __esm(() => {
41948
42451
 
41949
42452
  // src/build/discovery.ts
41950
42453
  import * as fs9 from "fs";
41951
- import * as path23 from "path";
42454
+ import * as path24 from "path";
41952
42455
  function isCommandAvailable(command) {
41953
42456
  if (toolchainCache.has(command)) {
41954
42457
  return toolchainCache.get(command);
@@ -41956,7 +42459,7 @@ function isCommandAvailable(command) {
41956
42459
  const isWindows = process.platform === "win32";
41957
42460
  const cmd = isWindows ? `${command}.exe` : command;
41958
42461
  try {
41959
- const result = _internals11.spawnSyncImpl(isWindows ? ["where", cmd] : ["which", cmd], {
42462
+ const result = _internals12.spawnSyncImpl(isWindows ? ["where", cmd] : ["which", cmd], {
41960
42463
  cwd: process.cwd(),
41961
42464
  stdin: "ignore",
41962
42465
  stdout: "ignore",
@@ -41983,11 +42486,11 @@ function findBuildFiles(workingDir, patterns) {
41983
42486
  const regex = simpleGlobToRegex(pattern);
41984
42487
  const matches = files.filter((f) => regex.test(f));
41985
42488
  if (matches.length > 0) {
41986
- return path23.join(dir, matches[0]);
42489
+ return path24.join(dir, matches[0]);
41987
42490
  }
41988
42491
  } catch {}
41989
42492
  } else {
41990
- const filePath = path23.join(workingDir, pattern);
42493
+ const filePath = path24.join(workingDir, pattern);
41991
42494
  if (fs9.existsSync(filePath)) {
41992
42495
  return filePath;
41993
42496
  }
@@ -41996,7 +42499,7 @@ function findBuildFiles(workingDir, patterns) {
41996
42499
  return null;
41997
42500
  }
41998
42501
  function getRepoDefinedScripts(workingDir, scripts) {
41999
- const packageJsonPath = path23.join(workingDir, "package.json");
42502
+ const packageJsonPath = path24.join(workingDir, "package.json");
42000
42503
  if (!fs9.existsSync(packageJsonPath)) {
42001
42504
  return [];
42002
42505
  }
@@ -42037,7 +42540,7 @@ function findAllBuildFiles(workingDir) {
42037
42540
  const regex = simpleGlobToRegex(pattern);
42038
42541
  findFilesRecursive(workingDir, regex, allBuildFiles);
42039
42542
  } else {
42040
- const filePath = path23.join(workingDir, pattern);
42543
+ const filePath = path24.join(workingDir, pattern);
42041
42544
  if (fs9.existsSync(filePath)) {
42042
42545
  allBuildFiles.add(filePath);
42043
42546
  }
@@ -42050,7 +42553,7 @@ function findFilesRecursive(dir, regex, results) {
42050
42553
  try {
42051
42554
  const entries = fs9.readdirSync(dir, { withFileTypes: true });
42052
42555
  for (const entry of entries) {
42053
- const fullPath = path23.join(dir, entry.name);
42556
+ const fullPath = path24.join(dir, entry.name);
42054
42557
  if (entry.isDirectory() && !["node_modules", ".git", "dist", "build", "target"].includes(entry.name)) {
42055
42558
  findFilesRecursive(fullPath, regex, results);
42056
42559
  } else if (entry.isFile() && regex.test(entry.name)) {
@@ -42073,7 +42576,7 @@ async function discoverBuildCommandsFromProfiles(workingDir) {
42073
42576
  let foundCommand = false;
42074
42577
  for (const cmd of sortedCommands) {
42075
42578
  if (cmd.detectFile) {
42076
- const detectFilePath = path23.join(workingDir, cmd.detectFile);
42579
+ const detectFilePath = path24.join(workingDir, cmd.detectFile);
42077
42580
  if (!fs9.existsSync(detectFilePath)) {
42078
42581
  continue;
42079
42582
  }
@@ -42106,7 +42609,7 @@ async function discoverBuildCommands(workingDir, options) {
42106
42609
  const scope = options?.scope ?? "all";
42107
42610
  const changedFiles = options?.changedFiles ?? [];
42108
42611
  const _filesToCheck = filterByScope(workingDir, scope, changedFiles);
42109
- const profileResult = await _internals11.discoverBuildCommandsFromProfiles(workingDir);
42612
+ const profileResult = await _internals12.discoverBuildCommandsFromProfiles(workingDir);
42110
42613
  const profileCommands = profileResult.commands;
42111
42614
  const profileSkipped = profileResult.skipped;
42112
42615
  const coveredEcosystems = new Set;
@@ -42169,7 +42672,7 @@ function clearToolchainCache() {
42169
42672
  function getEcosystems() {
42170
42673
  return ECOSYSTEMS.map((e) => e.ecosystem);
42171
42674
  }
42172
- var ECOSYSTEMS, PROFILE_TO_ECOSYSTEM_NAMES, toolchainCache, IS_COMMAND_AVAILABLE_TIMEOUT_MS = 3000, _internals11, build_discovery;
42675
+ var ECOSYSTEMS, PROFILE_TO_ECOSYSTEM_NAMES, toolchainCache, IS_COMMAND_AVAILABLE_TIMEOUT_MS = 3000, _internals12, build_discovery;
42173
42676
  var init_discovery = __esm(() => {
42174
42677
  init_dist();
42175
42678
  init_detector();
@@ -42287,7 +42790,7 @@ var init_discovery = __esm(() => {
42287
42790
  php: ["php-composer"]
42288
42791
  };
42289
42792
  toolchainCache = new Map;
42290
- _internals11 = {
42793
+ _internals12 = {
42291
42794
  isCommandAvailable,
42292
42795
  discoverBuildCommandsFromProfiles,
42293
42796
  discoverBuildCommands,
@@ -42314,7 +42817,7 @@ var init_discovery = __esm(() => {
42314
42817
 
42315
42818
  // src/services/tool-doctor.ts
42316
42819
  import * as fs10 from "fs";
42317
- import * as path24 from "path";
42820
+ import * as path25 from "path";
42318
42821
  function extractRegisteredToolKeys(indexPath) {
42319
42822
  const registeredKeys = new Set;
42320
42823
  try {
@@ -42369,8 +42872,8 @@ function checkBinaryReadiness() {
42369
42872
  }
42370
42873
  function runToolDoctor(_directory, pluginRoot) {
42371
42874
  const findings = [];
42372
- const resolvedPluginRoot = pluginRoot ?? path24.resolve(import.meta.dir, "..", "..");
42373
- const indexPath = path24.join(resolvedPluginRoot, "src", "index.ts");
42875
+ const resolvedPluginRoot = pluginRoot ?? path25.resolve(import.meta.dir, "..", "..");
42876
+ const indexPath = path25.join(resolvedPluginRoot, "src", "index.ts");
42374
42877
  if (!fs10.existsSync(indexPath)) {
42375
42878
  return {
42376
42879
  findings: [
@@ -42590,7 +43093,7 @@ var exports_evidence_summary_service = {};
42590
43093
  __export(exports_evidence_summary_service, {
42591
43094
  isAutoSummaryEnabled: () => isAutoSummaryEnabled,
42592
43095
  buildEvidenceSummary: () => buildEvidenceSummary,
42593
- _internals: () => _internals12,
43096
+ _internals: () => _internals13,
42594
43097
  REQUIRED_EVIDENCE_TYPES: () => REQUIRED_EVIDENCE_TYPES,
42595
43098
  EVIDENCE_SUMMARY_VERSION: () => EVIDENCE_SUMMARY_VERSION
42596
43099
  });
@@ -42628,14 +43131,13 @@ function getTaskStatus(task, bundle) {
42628
43131
  if (task?.status) {
42629
43132
  return task.status;
42630
43133
  }
42631
- const entries = _internals12.normalizeBundleEntries(bundle);
43134
+ const entries = _internals13.normalizeBundleEntries(bundle);
42632
43135
  if (entries.length > 0) {
42633
43136
  return "completed";
42634
43137
  }
42635
43138
  return "pending";
42636
43139
  }
42637
- function isEvidenceComplete(bundle) {
42638
- const entries = _internals12.normalizeBundleEntries(bundle);
43140
+ function evidenceCompleteFromEntries(entries) {
42639
43141
  if (entries.length === 0) {
42640
43142
  return {
42641
43143
  isComplete: false,
@@ -42654,6 +43156,9 @@ function isEvidenceComplete(bundle) {
42654
43156
  missingEvidence: missing
42655
43157
  };
42656
43158
  }
43159
+ function isEvidenceComplete(bundle) {
43160
+ return evidenceCompleteFromEntries(_internals13.normalizeBundleEntries(bundle));
43161
+ }
42657
43162
  function getTaskBlockers(task, summary, status) {
42658
43163
  const blockers = [];
42659
43164
  if (task?.blocked_reason) {
@@ -42670,11 +43175,19 @@ function getTaskBlockers(task, summary, status) {
42670
43175
  async function buildTaskSummary(directory, task, taskId) {
42671
43176
  const result = await loadEvidence(directory, taskId);
42672
43177
  const bundle = result.status === "found" ? result.bundle : null;
43178
+ const gateEvidence = await readDurableGateEvidence(directory, taskId);
42673
43179
  const phase = task?.phase ?? 0;
42674
- const status = _internals12.getTaskStatus(task, bundle);
42675
- const evidenceCheck = _internals12.isEvidenceComplete(bundle);
42676
- const blockers = _internals12.getTaskBlockers(task, evidenceCheck, status);
42677
- const entries = _internals12.normalizeBundleEntries(bundle);
43180
+ const status = _internals13.getTaskStatus(task, bundle);
43181
+ const entries = mergeDurableGateEntriesFromEvidence(taskId, _internals13.normalizeBundleEntries(bundle), gateEvidence);
43182
+ let evidenceCheck = _internals13.evidenceCompleteFromEntries(entries);
43183
+ if (gateEvidence) {
43184
+ const gateStatus = getDurableGateEvidenceStatus(gateEvidence);
43185
+ evidenceCheck = gateStatus.isComplete ? { isComplete: true, missingEvidence: [] } : {
43186
+ isComplete: false,
43187
+ missingEvidence: gateStatus.missingGates.map((gate) => `gate:${gate}`)
43188
+ };
43189
+ }
43190
+ const blockers = _internals13.getTaskBlockers(task, evidenceCheck, status);
42678
43191
  const hasReview = entries.some((e) => e.type === "review");
42679
43192
  const hasTest = entries.some((e) => e.type === "test");
42680
43193
  const hasApproval = entries.some((e) => e.type === "approval");
@@ -42703,12 +43216,12 @@ async function buildPhaseSummary(directory, phase) {
42703
43216
  const taskSummaries = [];
42704
43217
  const _taskMap = new Map(phase.tasks.map((t) => [t.id, t]));
42705
43218
  for (const task of phase.tasks) {
42706
- const summary = await _internals12.buildTaskSummary(directory, task, task.id);
43219
+ const summary = await _internals13.buildTaskSummary(directory, task, task.id);
42707
43220
  taskSummaries.push(summary);
42708
43221
  }
42709
43222
  const extraTaskIds = taskIds.filter((id) => !phaseTaskIds.has(id));
42710
43223
  for (const taskId of extraTaskIds) {
42711
- const summary = await _internals12.buildTaskSummary(directory, undefined, taskId);
43224
+ const summary = await _internals13.buildTaskSummary(directory, undefined, taskId);
42712
43225
  if (summary.phase === phase.id) {
42713
43226
  taskSummaries.push(summary);
42714
43227
  }
@@ -42809,7 +43322,7 @@ async function buildEvidenceSummary(directory, currentPhase) {
42809
43322
  let totalTasks = 0;
42810
43323
  let completedTasks = 0;
42811
43324
  for (const phase of phasesToProcess) {
42812
- const summary = await _internals12.buildPhaseSummary(directory, phase);
43325
+ const summary = await _internals13.buildPhaseSummary(directory, phase);
42813
43326
  phaseSummaries.push(summary);
42814
43327
  totalTasks += summary.totalTasks;
42815
43328
  completedTasks += summary.completedTasks;
@@ -42831,7 +43344,7 @@ async function buildEvidenceSummary(directory, currentPhase) {
42831
43344
  overallBlockers,
42832
43345
  summaryText: ""
42833
43346
  };
42834
- artifact.summaryText = _internals12.generateSummaryText(artifact);
43347
+ artifact.summaryText = _internals13.generateSummaryText(artifact);
42835
43348
  log("[EvidenceSummary] Summary built", {
42836
43349
  phases: phaseSummaries.length,
42837
43350
  totalTasks,
@@ -42850,8 +43363,9 @@ function isAutoSummaryEnabled(automationConfig) {
42850
43363
  }
42851
43364
  return automationConfig.capabilities?.evidence_auto_summaries === true;
42852
43365
  }
42853
- var VALID_EVIDENCE_TYPES2, REQUIRED_EVIDENCE_TYPES, EVIDENCE_SUMMARY_VERSION = "1.0.0", _internals12;
43366
+ var VALID_EVIDENCE_TYPES2, REQUIRED_EVIDENCE_TYPES, EVIDENCE_SUMMARY_VERSION = "1.0.0", _internals13;
42854
43367
  var init_evidence_summary_service = __esm(() => {
43368
+ init_gate_bridge();
42855
43369
  init_manager2();
42856
43370
  init_manager();
42857
43371
  init_utils();
@@ -42864,11 +43378,12 @@ var init_evidence_summary_service = __esm(() => {
42864
43378
  "retrospective"
42865
43379
  ]);
42866
43380
  REQUIRED_EVIDENCE_TYPES = ["review", "test"];
42867
- _internals12 = {
43381
+ _internals13 = {
42868
43382
  buildEvidenceSummary,
42869
43383
  isAutoSummaryEnabled,
42870
43384
  normalizeBundleEntries,
42871
43385
  getTaskStatus,
43386
+ evidenceCompleteFromEntries,
42872
43387
  isEvidenceComplete,
42873
43388
  getTaskBlockers,
42874
43389
  buildTaskSummary,
@@ -42919,7 +43434,7 @@ function getVerdictEmoji(verdict) {
42919
43434
  return getVerdictIcon(verdict);
42920
43435
  }
42921
43436
  async function getTaskEvidenceData(directory, taskId) {
42922
- const result = await _internals13.loadEvidence(directory, taskId);
43437
+ const result = await _internals14.loadEvidence(directory, taskId);
42923
43438
  if (result.status !== "found") {
42924
43439
  return {
42925
43440
  hasEvidence: false,
@@ -42942,13 +43457,13 @@ async function getTaskEvidenceData(directory, taskId) {
42942
43457
  };
42943
43458
  }
42944
43459
  async function getEvidenceListData(directory) {
42945
- const taskIds = await _internals13.listEvidenceTaskIds(directory);
43460
+ const taskIds = await _internals14.listEvidenceTaskIds(directory);
42946
43461
  if (taskIds.length === 0) {
42947
43462
  return { hasEvidence: false, tasks: [] };
42948
43463
  }
42949
43464
  const tasks = [];
42950
43465
  for (const taskId of taskIds) {
42951
- const result = await _internals13.loadEvidence(directory, taskId);
43466
+ const result = await _internals14.loadEvidence(directory, taskId);
42952
43467
  if (result.status === "found") {
42953
43468
  tasks.push({
42954
43469
  taskId,
@@ -43062,10 +43577,10 @@ async function handleEvidenceSummaryCommand(directory) {
43062
43577
  return lines.join(`
43063
43578
  `);
43064
43579
  }
43065
- var _internals13;
43580
+ var _internals14;
43066
43581
  var init_evidence_service = __esm(() => {
43067
43582
  init_manager2();
43068
- _internals13 = {
43583
+ _internals14 = {
43069
43584
  loadEvidence,
43070
43585
  listEvidenceTaskIds
43071
43586
  };
@@ -43116,12 +43631,12 @@ var init_export = __esm(() => {
43116
43631
 
43117
43632
  // src/full-auto/state.ts
43118
43633
  import * as fs11 from "fs";
43119
- import * as path25 from "path";
43634
+ import * as path26 from "path";
43120
43635
  function nowISO() {
43121
43636
  return new Date().toISOString();
43122
43637
  }
43123
43638
  function ensureSwarmDir(directory) {
43124
- const swarmDir = path25.resolve(directory, ".swarm");
43639
+ const swarmDir = path26.resolve(directory, ".swarm");
43125
43640
  if (!fs11.existsSync(swarmDir)) {
43126
43641
  fs11.mkdirSync(swarmDir, { recursive: true });
43127
43642
  }
@@ -43472,7 +43987,7 @@ function extractCurrentPhaseFromPlan2(plan) {
43472
43987
  if (!plan) {
43473
43988
  return { currentPhase: null, currentTask: null, incompleteTasks: [] };
43474
43989
  }
43475
- if (!_internals14.validatePlanPhases(plan)) {
43990
+ if (!_internals15.validatePlanPhases(plan)) {
43476
43991
  return { currentPhase: null, currentTask: null, incompleteTasks: [] };
43477
43992
  }
43478
43993
  let currentPhase = null;
@@ -43614,9 +44129,9 @@ function extractPhaseMetrics(content) {
43614
44129
  async function getHandoffData(directory) {
43615
44130
  const now = new Date().toISOString();
43616
44131
  const sessionContent = await readSwarmFileAsync(directory, "session/state.json");
43617
- const sessionState = _internals14.parseSessionState(sessionContent);
44132
+ const sessionState = _internals15.parseSessionState(sessionContent);
43618
44133
  const plan = await loadPlanJsonOnly(directory);
43619
- const planInfo = _internals14.extractCurrentPhaseFromPlan(plan);
44134
+ const planInfo = _internals15.extractCurrentPhaseFromPlan(plan);
43620
44135
  if (!plan) {
43621
44136
  const planMdContent = await readSwarmFileAsync(directory, "plan.md");
43622
44137
  if (planMdContent) {
@@ -43635,8 +44150,8 @@ async function getHandoffData(directory) {
43635
44150
  }
43636
44151
  }
43637
44152
  const contextContent = await readSwarmFileAsync(directory, "context.md");
43638
- const recentDecisions = _internals14.extractDecisions(contextContent);
43639
- const rawPhaseMetrics = _internals14.extractPhaseMetrics(contextContent);
44153
+ const recentDecisions = _internals15.extractDecisions(contextContent);
44154
+ const rawPhaseMetrics = _internals15.extractPhaseMetrics(contextContent);
43640
44155
  const phaseMetrics = sanitizeString(rawPhaseMetrics, 1000);
43641
44156
  let delegationState = null;
43642
44157
  if (sessionState?.delegationState) {
@@ -43800,13 +44315,13 @@ ${lines.join(`
43800
44315
  `)}
43801
44316
  \`\`\``;
43802
44317
  }
43803
- var RTL_OVERRIDE_PATTERN, MAX_TASK_ID_LENGTH = 100, MAX_DECISION_LENGTH = 500, MAX_INCOMPLETE_TASKS = 20, _internals14;
44318
+ var RTL_OVERRIDE_PATTERN, MAX_TASK_ID_LENGTH = 100, MAX_DECISION_LENGTH = 500, MAX_INCOMPLETE_TASKS = 20, _internals15;
43804
44319
  var init_handoff_service = __esm(() => {
43805
44320
  init_utils2();
43806
44321
  init_manager();
43807
44322
  init_utils();
43808
44323
  RTL_OVERRIDE_PATTERN = /[\u202e\u202d\u202c\u200f]/g;
43809
- _internals14 = {
44324
+ _internals15 = {
43810
44325
  getHandoffData,
43811
44326
  formatHandoffMarkdown,
43812
44327
  formatContinuationPrompt,
@@ -43821,8 +44336,8 @@ var init_handoff_service = __esm(() => {
43821
44336
  });
43822
44337
 
43823
44338
  // src/session/snapshot-writer.ts
43824
- import { closeSync as closeSync3, fsyncSync as fsyncSync2, mkdirSync as mkdirSync10, openSync as openSync3, renameSync as renameSync6 } from "fs";
43825
- import * as path26 from "path";
44339
+ import { closeSync as closeSync3, fsyncSync as fsyncSync2, mkdirSync as mkdirSync11, openSync as openSync3, renameSync as renameSync6 } from "fs";
44340
+ import * as path27 from "path";
43826
44341
  function serializeAgentSession(s) {
43827
44342
  const gateLog = {};
43828
44343
  const rawGateLog = s.gateLog ?? new Map;
@@ -43919,8 +44434,8 @@ async function writeSnapshot(directory, state) {
43919
44434
  }
43920
44435
  const content = JSON.stringify(snapshot, null, 2);
43921
44436
  const resolvedPath = validateSwarmPath(directory, "session/state.json");
43922
- const dir = path26.dirname(resolvedPath);
43923
- mkdirSync10(dir, { recursive: true });
44437
+ const dir = path27.dirname(resolvedPath);
44438
+ mkdirSync11(dir, { recursive: true });
43924
44439
  const tempPath = `${resolvedPath}.tmp.${Date.now()}.${Math.random().toString(36).slice(2)}`;
43925
44440
  await bunWrite(tempPath, content);
43926
44441
  try {
@@ -43940,22 +44455,22 @@ async function writeSnapshot(directory, state) {
43940
44455
  }
43941
44456
  function createSnapshotWriterHook(directory) {
43942
44457
  return (_input, _output) => {
43943
- _writeInFlight = _writeInFlight.then(() => _internals15.writeSnapshot(directory, swarmState), () => _internals15.writeSnapshot(directory, swarmState));
44458
+ _writeInFlight = _writeInFlight.then(() => _internals16.writeSnapshot(directory, swarmState), () => _internals16.writeSnapshot(directory, swarmState));
43944
44459
  return _writeInFlight;
43945
44460
  };
43946
44461
  }
43947
44462
  async function flushPendingSnapshot(directory) {
43948
- _writeInFlight = _writeInFlight.then(() => _internals15.writeSnapshot(directory, swarmState), () => _internals15.writeSnapshot(directory, swarmState));
44463
+ _writeInFlight = _writeInFlight.then(() => _internals16.writeSnapshot(directory, swarmState), () => _internals16.writeSnapshot(directory, swarmState));
43949
44464
  await _writeInFlight;
43950
44465
  }
43951
- var _writeInFlight, _internals15;
44466
+ var _writeInFlight, _internals16;
43952
44467
  var init_snapshot_writer = __esm(() => {
43953
44468
  init_utils2();
43954
44469
  init_state();
43955
44470
  init_utils();
43956
44471
  init_bun_compat();
43957
44472
  _writeInFlight = Promise.resolve();
43958
- _internals15 = {
44473
+ _internals16 = {
43959
44474
  writeSnapshot,
43960
44475
  createSnapshotWriterHook,
43961
44476
  flushPendingSnapshot
@@ -44376,9 +44891,9 @@ var init_issue = __esm(() => {
44376
44891
 
44377
44892
  // src/hooks/knowledge-migrator.ts
44378
44893
  import { randomUUID as randomUUID2 } from "crypto";
44379
- import { existsSync as existsSync17, readFileSync as readFileSync12 } from "fs";
44894
+ import { existsSync as existsSync17, readFileSync as readFileSync13 } from "fs";
44380
44895
  import { mkdir as mkdir7, readFile as readFile7, writeFile as writeFile8 } from "fs/promises";
44381
- import * as path27 from "path";
44896
+ import * as path28 from "path";
44382
44897
  async function migrateKnowledgeToExternal(_directory, _config) {
44383
44898
  return {
44384
44899
  migrated: false,
@@ -44389,8 +44904,8 @@ async function migrateKnowledgeToExternal(_directory, _config) {
44389
44904
  };
44390
44905
  }
44391
44906
  async function migrateContextToKnowledge(directory, config3) {
44392
- const sentinelPath = path27.join(directory, ".swarm", ".knowledge-migrated");
44393
- const contextPath = path27.join(directory, ".swarm", "context.md");
44907
+ const sentinelPath = path28.join(directory, ".swarm", ".knowledge-migrated");
44908
+ const contextPath = path28.join(directory, ".swarm", "context.md");
44394
44909
  const knowledgePath = resolveSwarmKnowledgePath(directory);
44395
44910
  if (existsSync17(sentinelPath)) {
44396
44911
  return {
@@ -44420,9 +44935,9 @@ async function migrateContextToKnowledge(directory, config3) {
44420
44935
  skippedReason: "empty-context"
44421
44936
  };
44422
44937
  }
44423
- const rawEntries = _internals16.parseContextMd(contextContent);
44938
+ const rawEntries = _internals17.parseContextMd(contextContent);
44424
44939
  if (rawEntries.length === 0) {
44425
- await _internals16.writeSentinel(sentinelPath, 0, 0);
44940
+ await _internals17.writeSentinel(sentinelPath, 0, 0);
44426
44941
  return {
44427
44942
  migrated: true,
44428
44943
  entriesMigrated: 0,
@@ -44433,10 +44948,10 @@ async function migrateContextToKnowledge(directory, config3) {
44433
44948
  const existing = await readKnowledge(knowledgePath);
44434
44949
  let migrated = 0;
44435
44950
  let dropped = 0;
44436
- const projectName = _internals16.inferProjectName(directory);
44951
+ const projectName = _internals17.inferProjectName(directory);
44437
44952
  for (const raw of rawEntries) {
44438
44953
  if (config3.validation_enabled !== false) {
44439
- const category = raw.categoryHint ?? _internals16.inferCategoryFromText(raw.text);
44954
+ const category = raw.categoryHint ?? _internals17.inferCategoryFromText(raw.text);
44440
44955
  const result = validateLesson(raw.text, existing.map((e) => e.lesson), {
44441
44956
  category,
44442
44957
  scope: "global",
@@ -44456,8 +44971,8 @@ async function migrateContextToKnowledge(directory, config3) {
44456
44971
  const entry = {
44457
44972
  id: randomUUID2(),
44458
44973
  tier: "swarm",
44459
- lesson: _internals16.truncateLesson(raw.text),
44460
- category: raw.categoryHint ?? _internals16.inferCategoryFromText(raw.text),
44974
+ lesson: _internals17.truncateLesson(raw.text),
44975
+ category: raw.categoryHint ?? _internals17.inferCategoryFromText(raw.text),
44461
44976
  tags: [...inferredTags, `migration:${raw.sourceSection}`],
44462
44977
  scope: "global",
44463
44978
  confidence: 0.3,
@@ -44480,7 +44995,7 @@ async function migrateContextToKnowledge(directory, config3) {
44480
44995
  if (migrated > 0) {
44481
44996
  await rewriteKnowledge(knowledgePath, existing);
44482
44997
  }
44483
- await _internals16.writeSentinel(sentinelPath, migrated, dropped);
44998
+ await _internals17.writeSentinel(sentinelPath, migrated, dropped);
44484
44999
  log(`[knowledge-migrator] Migrated ${migrated} entries, dropped ${dropped}`);
44485
45000
  return {
44486
45001
  migrated: true,
@@ -44490,7 +45005,7 @@ async function migrateContextToKnowledge(directory, config3) {
44490
45005
  };
44491
45006
  }
44492
45007
  function parseContextMd(content) {
44493
- const sections = _internals16.splitIntoSections(content);
45008
+ const sections = _internals17.splitIntoSections(content);
44494
45009
  const entries = [];
44495
45010
  const seen = new Set;
44496
45011
  const sectionPatterns = [
@@ -44506,7 +45021,7 @@ function parseContextMd(content) {
44506
45021
  const match = sectionPatterns.find((sp) => sp.pattern.test(section.heading));
44507
45022
  if (!match)
44508
45023
  continue;
44509
- const bullets = _internals16.extractBullets(section.body);
45024
+ const bullets = _internals17.extractBullets(section.body);
44510
45025
  for (const bullet of bullets) {
44511
45026
  if (bullet.length < 15)
44512
45027
  continue;
@@ -44515,9 +45030,9 @@ function parseContextMd(content) {
44515
45030
  continue;
44516
45031
  seen.add(normalized);
44517
45032
  entries.push({
44518
- text: _internals16.truncateLesson(bullet),
45033
+ text: _internals17.truncateLesson(bullet),
44519
45034
  sourceSection: match.sourceSection,
44520
- categoryHint: _internals16.inferCategoryFromText(bullet)
45035
+ categoryHint: _internals17.inferCategoryFromText(bullet)
44521
45036
  });
44522
45037
  }
44523
45038
  }
@@ -44586,16 +45101,16 @@ function truncateLesson(text) {
44586
45101
  return `${text.slice(0, 277)}...`;
44587
45102
  }
44588
45103
  function inferProjectName(directory) {
44589
- const packageJsonPath = path27.join(directory, "package.json");
45104
+ const packageJsonPath = path28.join(directory, "package.json");
44590
45105
  if (existsSync17(packageJsonPath)) {
44591
45106
  try {
44592
- const pkg = JSON.parse(readFileSync12(packageJsonPath, "utf-8"));
45107
+ const pkg = JSON.parse(readFileSync13(packageJsonPath, "utf-8"));
44593
45108
  if (pkg.name && typeof pkg.name === "string") {
44594
45109
  return pkg.name;
44595
45110
  }
44596
45111
  } catch {}
44597
45112
  }
44598
- return path27.basename(directory);
45113
+ return path28.basename(directory);
44599
45114
  }
44600
45115
  async function writeSentinel(sentinelPath, migrated, dropped) {
44601
45116
  const sentinel = {
@@ -44607,15 +45122,15 @@ async function writeSentinel(sentinelPath, migrated, dropped) {
44607
45122
  schema_version: 1,
44608
45123
  migration_tool: "knowledge-migrator.ts"
44609
45124
  };
44610
- await mkdir7(path27.dirname(sentinelPath), { recursive: true });
45125
+ await mkdir7(path28.dirname(sentinelPath), { recursive: true });
44611
45126
  await writeFile8(sentinelPath, JSON.stringify(sentinel, null, 2), "utf-8");
44612
45127
  }
44613
- var _internals16;
45128
+ var _internals17;
44614
45129
  var init_knowledge_migrator = __esm(() => {
44615
45130
  init_logger();
44616
45131
  init_knowledge_store();
44617
45132
  init_knowledge_validator();
44618
- _internals16 = {
45133
+ _internals17 = {
44619
45134
  migrateContextToKnowledge,
44620
45135
  migrateKnowledgeToExternal,
44621
45136
  parseContextMd,
@@ -44629,7 +45144,7 @@ var init_knowledge_migrator = __esm(() => {
44629
45144
  });
44630
45145
 
44631
45146
  // src/commands/knowledge.ts
44632
- import { join as join25 } from "path";
45147
+ import { join as join26 } from "path";
44633
45148
  function resolveEntryByPrefix(entries, inputId) {
44634
45149
  const exact = entries.find((e) => e.id === inputId);
44635
45150
  if (exact)
@@ -44680,7 +45195,7 @@ async function handleKnowledgeRestoreCommand(directory, args) {
44680
45195
  return "Invalid entry ID. IDs must be 1-64 characters: letters, digits, hyphens, underscores only.";
44681
45196
  }
44682
45197
  try {
44683
- const quarantinePath = join25(directory, ".swarm", "knowledge-quarantined.jsonl");
45198
+ const quarantinePath = join26(directory, ".swarm", "knowledge-quarantined.jsonl");
44684
45199
  const entries = await readKnowledge(quarantinePath);
44685
45200
  const resolved = resolveEntryByPrefix(entries, inputId);
44686
45201
  if ("error" in resolved) {
@@ -44752,9 +45267,9 @@ var init_knowledge = __esm(() => {
44752
45267
 
44753
45268
  // src/services/plan-service.ts
44754
45269
  async function getPlanData(directory, phaseArg) {
44755
- const plan = await _internals17.loadPlanJsonOnly(directory);
45270
+ const plan = await _internals18.loadPlanJsonOnly(directory);
44756
45271
  if (plan) {
44757
- const fullMarkdown = _internals17.derivePlanMarkdown(plan);
45272
+ const fullMarkdown = _internals18.derivePlanMarkdown(plan);
44758
45273
  if (phaseArg === undefined || phaseArg === null || phaseArg === "") {
44759
45274
  return {
44760
45275
  hasPlan: true,
@@ -44797,7 +45312,7 @@ async function getPlanData(directory, phaseArg) {
44797
45312
  isLegacy: false
44798
45313
  };
44799
45314
  }
44800
- const planContent = await _internals17.readSwarmFileAsync(directory, "plan.md");
45315
+ const planContent = await _internals18.readSwarmFileAsync(directory, "plan.md");
44801
45316
  if (!planContent) {
44802
45317
  return {
44803
45318
  hasPlan: false,
@@ -44893,11 +45408,11 @@ async function handlePlanCommand(directory, args) {
44893
45408
  const planData = await getPlanData(directory, phaseArg);
44894
45409
  return formatPlanMarkdown(planData);
44895
45410
  }
44896
- var _internals17;
45411
+ var _internals18;
44897
45412
  var init_plan_service = __esm(() => {
44898
45413
  init_utils2();
44899
45414
  init_manager();
44900
- _internals17 = {
45415
+ _internals18 = {
44901
45416
  loadPlanJsonOnly,
44902
45417
  derivePlanMarkdown,
44903
45418
  readSwarmFileAsync
@@ -45135,7 +45650,7 @@ var init_path_security = () => {};
45135
45650
 
45136
45651
  // src/tools/lint.ts
45137
45652
  import * as fs12 from "fs";
45138
- import * as path28 from "path";
45653
+ import * as path29 from "path";
45139
45654
  function validateArgs(args) {
45140
45655
  if (typeof args !== "object" || args === null)
45141
45656
  return false;
@@ -45146,9 +45661,9 @@ function validateArgs(args) {
45146
45661
  }
45147
45662
  function getLinterCommand(linter, mode, projectDir) {
45148
45663
  const isWindows = process.platform === "win32";
45149
- const binDir = path28.join(projectDir, "node_modules", ".bin");
45150
- const biomeBin = isWindows ? path28.join(binDir, "biome.EXE") : path28.join(binDir, "biome");
45151
- const eslintBin = isWindows ? path28.join(binDir, "eslint.cmd") : path28.join(binDir, "eslint");
45664
+ const binDir = path29.join(projectDir, "node_modules", ".bin");
45665
+ const biomeBin = isWindows ? path29.join(binDir, "biome.EXE") : path29.join(binDir, "biome");
45666
+ const eslintBin = isWindows ? path29.join(binDir, "eslint.cmd") : path29.join(binDir, "eslint");
45152
45667
  switch (linter) {
45153
45668
  case "biome":
45154
45669
  if (mode === "fix") {
@@ -45164,7 +45679,7 @@ function getLinterCommand(linter, mode, projectDir) {
45164
45679
  }
45165
45680
  function getAdditionalLinterCommand(linter, mode, cwd) {
45166
45681
  const gradlewName = process.platform === "win32" ? "gradlew.bat" : "gradlew";
45167
- const gradlew = fs12.existsSync(path28.join(cwd, gradlewName)) ? path28.join(cwd, gradlewName) : null;
45682
+ const gradlew = fs12.existsSync(path29.join(cwd, gradlewName)) ? path29.join(cwd, gradlewName) : null;
45168
45683
  switch (linter) {
45169
45684
  case "ruff":
45170
45685
  return mode === "fix" ? ["ruff", "check", "--fix", "."] : ["ruff", "check", "."];
@@ -45198,10 +45713,10 @@ function getAdditionalLinterCommand(linter, mode, cwd) {
45198
45713
  }
45199
45714
  }
45200
45715
  function detectRuff(cwd) {
45201
- if (fs12.existsSync(path28.join(cwd, "ruff.toml")))
45716
+ if (fs12.existsSync(path29.join(cwd, "ruff.toml")))
45202
45717
  return isCommandAvailable("ruff");
45203
45718
  try {
45204
- const pyproject = path28.join(cwd, "pyproject.toml");
45719
+ const pyproject = path29.join(cwd, "pyproject.toml");
45205
45720
  if (fs12.existsSync(pyproject)) {
45206
45721
  const content = fs12.readFileSync(pyproject, "utf-8");
45207
45722
  if (content.includes("[tool.ruff]"))
@@ -45211,19 +45726,19 @@ function detectRuff(cwd) {
45211
45726
  return false;
45212
45727
  }
45213
45728
  function detectClippy(cwd) {
45214
- return fs12.existsSync(path28.join(cwd, "Cargo.toml")) && isCommandAvailable("cargo");
45729
+ return fs12.existsSync(path29.join(cwd, "Cargo.toml")) && isCommandAvailable("cargo");
45215
45730
  }
45216
45731
  function detectGolangciLint(cwd) {
45217
- return fs12.existsSync(path28.join(cwd, "go.mod")) && isCommandAvailable("golangci-lint");
45732
+ return fs12.existsSync(path29.join(cwd, "go.mod")) && isCommandAvailable("golangci-lint");
45218
45733
  }
45219
45734
  function detectCheckstyle(cwd) {
45220
- const hasMaven = fs12.existsSync(path28.join(cwd, "pom.xml"));
45221
- const hasGradle = fs12.existsSync(path28.join(cwd, "build.gradle")) || fs12.existsSync(path28.join(cwd, "build.gradle.kts"));
45222
- const hasBinary = hasMaven && isCommandAvailable("mvn") || hasGradle && (fs12.existsSync(path28.join(cwd, "gradlew")) || isCommandAvailable("gradle"));
45735
+ const hasMaven = fs12.existsSync(path29.join(cwd, "pom.xml"));
45736
+ const hasGradle = fs12.existsSync(path29.join(cwd, "build.gradle")) || fs12.existsSync(path29.join(cwd, "build.gradle.kts"));
45737
+ const hasBinary = hasMaven && isCommandAvailable("mvn") || hasGradle && (fs12.existsSync(path29.join(cwd, "gradlew")) || isCommandAvailable("gradle"));
45223
45738
  return (hasMaven || hasGradle) && hasBinary;
45224
45739
  }
45225
45740
  function detectKtlint(cwd) {
45226
- const hasKotlin = fs12.existsSync(path28.join(cwd, "build.gradle.kts")) || fs12.existsSync(path28.join(cwd, "build.gradle")) || (() => {
45741
+ const hasKotlin = fs12.existsSync(path29.join(cwd, "build.gradle.kts")) || fs12.existsSync(path29.join(cwd, "build.gradle")) || (() => {
45227
45742
  try {
45228
45743
  return fs12.readdirSync(cwd).some((f) => f.endsWith(".kt") || f.endsWith(".kts"));
45229
45744
  } catch {
@@ -45242,11 +45757,11 @@ function detectDotnetFormat(cwd) {
45242
45757
  }
45243
45758
  }
45244
45759
  function detectCppcheck(cwd) {
45245
- if (fs12.existsSync(path28.join(cwd, "CMakeLists.txt"))) {
45760
+ if (fs12.existsSync(path29.join(cwd, "CMakeLists.txt"))) {
45246
45761
  return isCommandAvailable("cppcheck");
45247
45762
  }
45248
45763
  try {
45249
- const dirsToCheck = [cwd, path28.join(cwd, "src")];
45764
+ const dirsToCheck = [cwd, path29.join(cwd, "src")];
45250
45765
  const hasCpp = dirsToCheck.some((dir) => {
45251
45766
  try {
45252
45767
  return fs12.readdirSync(dir).some((f) => /\.(c|cpp|cc|cxx|h|hpp)$/.test(f));
@@ -45260,13 +45775,13 @@ function detectCppcheck(cwd) {
45260
45775
  }
45261
45776
  }
45262
45777
  function detectSwiftlint(cwd) {
45263
- return fs12.existsSync(path28.join(cwd, "Package.swift")) && isCommandAvailable("swiftlint");
45778
+ return fs12.existsSync(path29.join(cwd, "Package.swift")) && isCommandAvailable("swiftlint");
45264
45779
  }
45265
45780
  function detectDartAnalyze(cwd) {
45266
- return fs12.existsSync(path28.join(cwd, "pubspec.yaml")) && (isCommandAvailable("dart") || isCommandAvailable("flutter"));
45781
+ return fs12.existsSync(path29.join(cwd, "pubspec.yaml")) && (isCommandAvailable("dart") || isCommandAvailable("flutter"));
45267
45782
  }
45268
45783
  function detectRubocop(cwd) {
45269
- return (fs12.existsSync(path28.join(cwd, "Gemfile")) || fs12.existsSync(path28.join(cwd, "gems.rb")) || fs12.existsSync(path28.join(cwd, ".rubocop.yml"))) && (isCommandAvailable("rubocop") || isCommandAvailable("bundle"));
45784
+ return (fs12.existsSync(path29.join(cwd, "Gemfile")) || fs12.existsSync(path29.join(cwd, "gems.rb")) || fs12.existsSync(path29.join(cwd, ".rubocop.yml"))) && (isCommandAvailable("rubocop") || isCommandAvailable("bundle"));
45270
45785
  }
45271
45786
  function detectAdditionalLinter(cwd) {
45272
45787
  if (detectRuff(cwd))
@@ -45294,10 +45809,10 @@ function detectAdditionalLinter(cwd) {
45294
45809
  function findBinInAncestors(startDir, binName) {
45295
45810
  let dir = startDir;
45296
45811
  while (true) {
45297
- const candidate = path28.join(dir, "node_modules", ".bin", binName);
45812
+ const candidate = path29.join(dir, "node_modules", ".bin", binName);
45298
45813
  if (fs12.existsSync(candidate))
45299
45814
  return candidate;
45300
- const parent = path28.dirname(dir);
45815
+ const parent = path29.dirname(dir);
45301
45816
  if (parent === dir)
45302
45817
  break;
45303
45818
  dir = parent;
@@ -45306,10 +45821,10 @@ function findBinInAncestors(startDir, binName) {
45306
45821
  }
45307
45822
  function findBinInEnvPath(binName) {
45308
45823
  const searchPath = process.env.PATH ?? "";
45309
- for (const dir of searchPath.split(path28.delimiter)) {
45824
+ for (const dir of searchPath.split(path29.delimiter)) {
45310
45825
  if (!dir)
45311
45826
  continue;
45312
- const candidate = path28.join(dir, binName);
45827
+ const candidate = path29.join(dir, binName);
45313
45828
  if (fs12.existsSync(candidate))
45314
45829
  return candidate;
45315
45830
  }
@@ -45322,13 +45837,13 @@ async function detectAvailableLinter(directory) {
45322
45837
  return null;
45323
45838
  const projectDir = directory;
45324
45839
  const isWindows = process.platform === "win32";
45325
- const biomeBin = isWindows ? path28.join(projectDir, "node_modules", ".bin", "biome.EXE") : path28.join(projectDir, "node_modules", ".bin", "biome");
45326
- const eslintBin = isWindows ? path28.join(projectDir, "node_modules", ".bin", "eslint.cmd") : path28.join(projectDir, "node_modules", ".bin", "eslint");
45840
+ const biomeBin = isWindows ? path29.join(projectDir, "node_modules", ".bin", "biome.EXE") : path29.join(projectDir, "node_modules", ".bin", "biome");
45841
+ const eslintBin = isWindows ? path29.join(projectDir, "node_modules", ".bin", "eslint.cmd") : path29.join(projectDir, "node_modules", ".bin", "eslint");
45327
45842
  const localResult = await _detectAvailableLinter(projectDir, biomeBin, eslintBin);
45328
45843
  if (localResult)
45329
45844
  return localResult;
45330
- const biomeAncestor = findBinInAncestors(path28.dirname(projectDir), isWindows ? "biome.EXE" : "biome");
45331
- const eslintAncestor = findBinInAncestors(path28.dirname(projectDir), isWindows ? "eslint.cmd" : "eslint");
45845
+ const biomeAncestor = findBinInAncestors(path29.dirname(projectDir), isWindows ? "biome.EXE" : "biome");
45846
+ const eslintAncestor = findBinInAncestors(path29.dirname(projectDir), isWindows ? "eslint.cmd" : "eslint");
45332
45847
  if (biomeAncestor || eslintAncestor) {
45333
45848
  return _detectAvailableLinter(projectDir, biomeAncestor ?? biomeBin, eslintAncestor ?? eslintBin);
45334
45849
  }
@@ -45487,7 +46002,7 @@ async function runAdditionalLint(linter, mode, cwd) {
45487
46002
  };
45488
46003
  }
45489
46004
  }
45490
- var MAX_OUTPUT_BYTES = 512000, MAX_COMMAND_LENGTH = 500, lint, _internals18;
46005
+ var MAX_OUTPUT_BYTES = 512000, MAX_COMMAND_LENGTH = 500, lint, _internals19;
45491
46006
  var init_lint = __esm(() => {
45492
46007
  init_zod();
45493
46008
  init_discovery();
@@ -45519,15 +46034,15 @@ var init_lint = __esm(() => {
45519
46034
  }
45520
46035
  const { mode } = args;
45521
46036
  const cwd = directory;
45522
- const linter = await _internals18.detectAvailableLinter(directory);
46037
+ const linter = await _internals19.detectAvailableLinter(directory);
45523
46038
  if (linter) {
45524
- const result = await _internals18.runLint(linter, mode, directory);
46039
+ const result = await _internals19.runLint(linter, mode, directory);
45525
46040
  return JSON.stringify(result, null, 2);
45526
46041
  }
45527
- const additionalLinter = _internals18.detectAdditionalLinter(cwd);
46042
+ const additionalLinter = _internals19.detectAdditionalLinter(cwd);
45528
46043
  if (additionalLinter) {
45529
46044
  warn(`[lint] Using ${additionalLinter} linter for this project`);
45530
- const result = await _internals18.runAdditionalLint(additionalLinter, mode, cwd);
46045
+ const result = await _internals19.runAdditionalLint(additionalLinter, mode, cwd);
45531
46046
  return JSON.stringify(result, null, 2);
45532
46047
  }
45533
46048
  const errorResult = {
@@ -45541,7 +46056,7 @@ For Rust: rustup component add clippy`
45541
46056
  return JSON.stringify(errorResult, null, 2);
45542
46057
  }
45543
46058
  });
45544
- _internals18 = {
46059
+ _internals19 = {
45545
46060
  detectAvailableLinter,
45546
46061
  runLint,
45547
46062
  detectAdditionalLinter,
@@ -45551,7 +46066,7 @@ For Rust: rustup component add clippy`
45551
46066
 
45552
46067
  // src/tools/secretscan.ts
45553
46068
  import * as fs13 from "fs";
45554
- import * as path29 from "path";
46069
+ import * as path30 from "path";
45555
46070
  function calculateShannonEntropy(str) {
45556
46071
  if (str.length === 0)
45557
46072
  return 0;
@@ -45599,7 +46114,7 @@ function isGlobOrPathPattern(pattern) {
45599
46114
  return pattern.includes("/") || pattern.includes("\\") || /[*?[\]{}]/.test(pattern);
45600
46115
  }
45601
46116
  function loadSecretScanIgnore(scanDir) {
45602
- const ignorePath = path29.join(scanDir, ".secretscanignore");
46117
+ const ignorePath = path30.join(scanDir, ".secretscanignore");
45603
46118
  try {
45604
46119
  if (!fs13.existsSync(ignorePath))
45605
46120
  return [];
@@ -45622,7 +46137,7 @@ function isExcluded(entry, relPath, exactNames, globPatterns) {
45622
46137
  if (exactNames.has(entry))
45623
46138
  return true;
45624
46139
  for (const pattern of globPatterns) {
45625
- if (path29.matchesGlob(relPath, pattern))
46140
+ if (path30.matchesGlob(relPath, pattern))
45626
46141
  return true;
45627
46142
  }
45628
46143
  return false;
@@ -45643,7 +46158,7 @@ function validateDirectoryInput(dir) {
45643
46158
  return null;
45644
46159
  }
45645
46160
  function isBinaryFile(filePath, buffer) {
45646
- const ext = path29.extname(filePath).toLowerCase();
46161
+ const ext = path30.extname(filePath).toLowerCase();
45647
46162
  if (DEFAULT_EXCLUDE_EXTENSIONS.has(ext)) {
45648
46163
  return true;
45649
46164
  }
@@ -45779,9 +46294,9 @@ function isSymlinkLoop(realPath, visited) {
45779
46294
  return false;
45780
46295
  }
45781
46296
  function isPathWithinScope(realPath, scanDir) {
45782
- const resolvedScanDir = path29.resolve(scanDir);
45783
- const resolvedRealPath = path29.resolve(realPath);
45784
- return resolvedRealPath === resolvedScanDir || resolvedRealPath.startsWith(resolvedScanDir + path29.sep) || resolvedRealPath.startsWith(`${resolvedScanDir}/`) || resolvedRealPath.startsWith(`${resolvedScanDir}\\`);
46297
+ const resolvedScanDir = path30.resolve(scanDir);
46298
+ const resolvedRealPath = path30.resolve(realPath);
46299
+ return resolvedRealPath === resolvedScanDir || resolvedRealPath.startsWith(resolvedScanDir + path30.sep) || resolvedRealPath.startsWith(`${resolvedScanDir}/`) || resolvedRealPath.startsWith(`${resolvedScanDir}\\`);
45785
46300
  }
45786
46301
  function findScannableFiles(dir, excludeExact, excludeGlobs, scanDir, visited, stats = {
45787
46302
  skippedDirs: 0,
@@ -45807,8 +46322,8 @@ function findScannableFiles(dir, excludeExact, excludeGlobs, scanDir, visited, s
45807
46322
  return a.localeCompare(b);
45808
46323
  });
45809
46324
  for (const entry of entries) {
45810
- const fullPath = path29.join(dir, entry);
45811
- const relPath = path29.relative(scanDir, fullPath).replace(/\\/g, "/");
46325
+ const fullPath = path30.join(dir, entry);
46326
+ const relPath = path30.relative(scanDir, fullPath).replace(/\\/g, "/");
45812
46327
  if (isExcluded(entry, relPath, excludeExact, excludeGlobs)) {
45813
46328
  stats.skippedDirs++;
45814
46329
  continue;
@@ -45843,7 +46358,7 @@ function findScannableFiles(dir, excludeExact, excludeGlobs, scanDir, visited, s
45843
46358
  const subFiles = findScannableFiles(fullPath, excludeExact, excludeGlobs, scanDir, visited, stats);
45844
46359
  files.push(...subFiles);
45845
46360
  } else if (lstat.isFile()) {
45846
- const ext = path29.extname(fullPath).toLowerCase();
46361
+ const ext = path30.extname(fullPath).toLowerCase();
45847
46362
  if (!DEFAULT_EXCLUDE_EXTENSIONS.has(ext)) {
45848
46363
  files.push(fullPath);
45849
46364
  } else {
@@ -45855,7 +46370,7 @@ function findScannableFiles(dir, excludeExact, excludeGlobs, scanDir, visited, s
45855
46370
  }
45856
46371
  async function runSecretscan(directory) {
45857
46372
  try {
45858
- const result = await _internals19.secretscan.execute({ directory }, {});
46373
+ const result = await _internals20.secretscan.execute({ directory }, {});
45859
46374
  const jsonStr = typeof result === "string" ? result : result.output;
45860
46375
  return JSON.parse(jsonStr);
45861
46376
  } catch (e) {
@@ -45870,7 +46385,7 @@ async function runSecretscan(directory) {
45870
46385
  return errorResult;
45871
46386
  }
45872
46387
  }
45873
- var MAX_FILE_PATH_LENGTH = 500, MAX_FILE_SIZE_BYTES, MAX_FILES_SCANNED = 1000, MAX_FINDINGS = 100, MAX_OUTPUT_BYTES2 = 512000, MAX_LINE_LENGTH = 1e4, MAX_CONTENT_BYTES, BINARY_SIGNATURES, BINARY_PREFIX_BYTES = 4, BINARY_NULL_CHECK_BYTES = 8192, BINARY_NULL_THRESHOLD = 0.1, DEFAULT_EXCLUDE_DIRS, DEFAULT_EXCLUDE_EXTENSIONS, SECRET_PATTERNS, O_NOFOLLOW, secretscan, _internals19;
46388
+ var MAX_FILE_PATH_LENGTH = 500, MAX_FILE_SIZE_BYTES, MAX_FILES_SCANNED = 1000, MAX_FINDINGS = 100, MAX_OUTPUT_BYTES2 = 512000, MAX_LINE_LENGTH = 1e4, MAX_CONTENT_BYTES, BINARY_SIGNATURES, BINARY_PREFIX_BYTES = 4, BINARY_NULL_CHECK_BYTES = 8192, BINARY_NULL_THRESHOLD = 0.1, DEFAULT_EXCLUDE_DIRS, DEFAULT_EXCLUDE_EXTENSIONS, SECRET_PATTERNS, O_NOFOLLOW, secretscan, _internals20;
45874
46389
  var init_secretscan = __esm(() => {
45875
46390
  init_zod();
45876
46391
  init_path_security();
@@ -46103,7 +46618,7 @@ var init_secretscan = __esm(() => {
46103
46618
  }
46104
46619
  }
46105
46620
  try {
46106
- const _scanDirRaw = path29.resolve(directory);
46621
+ const _scanDirRaw = path30.resolve(directory);
46107
46622
  const scanDir = (() => {
46108
46623
  try {
46109
46624
  return fs13.realpathSync(_scanDirRaw);
@@ -46242,7 +46757,7 @@ var init_secretscan = __esm(() => {
46242
46757
  }
46243
46758
  }
46244
46759
  });
46245
- _internals19 = {
46760
+ _internals20 = {
46246
46761
  secretscan,
46247
46762
  runSecretscan
46248
46763
  };
@@ -46250,7 +46765,7 @@ var init_secretscan = __esm(() => {
46250
46765
 
46251
46766
  // src/lang/default-backend.ts
46252
46767
  import * as fs14 from "fs";
46253
- import * as path30 from "path";
46768
+ import * as path31 from "path";
46254
46769
  function detectFileExists(dir, pattern) {
46255
46770
  if (pattern.includes("*") || pattern.includes("?")) {
46256
46771
  try {
@@ -46262,7 +46777,7 @@ function detectFileExists(dir, pattern) {
46262
46777
  }
46263
46778
  }
46264
46779
  try {
46265
- fs14.accessSync(path30.join(dir, pattern));
46780
+ fs14.accessSync(path31.join(dir, pattern));
46266
46781
  return true;
46267
46782
  } catch {
46268
46783
  return false;
@@ -46390,8 +46905,8 @@ function defaultBuildTestCommand(profile, framework, files, dir = ".", opts = {}
46390
46905
  return ["mvn", "test"];
46391
46906
  case "gradle": {
46392
46907
  const isWindows = process.platform === "win32";
46393
- const hasGradlewBat = fs14.existsSync(path30.join(dir, "gradlew.bat"));
46394
- const hasGradlew = fs14.existsSync(path30.join(dir, "gradlew"));
46908
+ const hasGradlewBat = fs14.existsSync(path31.join(dir, "gradlew.bat"));
46909
+ const hasGradlew = fs14.existsSync(path31.join(dir, "gradlew"));
46395
46910
  if (hasGradlewBat && isWindows)
46396
46911
  return ["gradlew.bat", "test"];
46397
46912
  if (hasGradlew)
@@ -46408,7 +46923,7 @@ function defaultBuildTestCommand(profile, framework, files, dir = ".", opts = {}
46408
46923
  "cmake-build-release",
46409
46924
  "out"
46410
46925
  ];
46411
- const actualBuildDir = buildDirCandidates.find((d) => fs14.existsSync(path30.join(dir, d, "CMakeCache.txt"))) ?? "build";
46926
+ const actualBuildDir = buildDirCandidates.find((d) => fs14.existsSync(path31.join(dir, d, "CMakeCache.txt"))) ?? "build";
46412
46927
  return ["ctest", "--test-dir", actualBuildDir];
46413
46928
  }
46414
46929
  case "swift-test":
@@ -46695,17 +47210,17 @@ async function defaultSelectBuildCommand(profile, dir) {
46695
47210
  return null;
46696
47211
  }
46697
47212
  async function defaultTestFilesFor(profile, sourceFile, dir) {
46698
- const ext = path30.extname(sourceFile);
47213
+ const ext = path31.extname(sourceFile);
46699
47214
  if (!profile.extensions.includes(ext))
46700
47215
  return [];
46701
- const base = path30.basename(sourceFile, ext);
46702
- const rel = path30.relative(dir, sourceFile);
46703
- const relDir = path30.dirname(rel);
47216
+ const base = path31.basename(sourceFile, ext);
47217
+ const rel = path31.relative(dir, sourceFile);
47218
+ const relDir = path31.dirname(rel);
46704
47219
  const stripSrc = relDir.replace(/^src(\/|\\)/, "");
46705
47220
  const candidates = new Set;
46706
47221
  for (const tDir of ["tests", "test", "__tests__", "spec"]) {
46707
47222
  for (const suffix of ["", "_test", ".test", "_spec", ".spec"]) {
46708
- candidates.add(path30.join(dir, tDir, stripSrc, `${base}${suffix}${ext}`));
47223
+ candidates.add(path31.join(dir, tDir, stripSrc, `${base}${suffix}${ext}`));
46709
47224
  }
46710
47225
  }
46711
47226
  const existing = [];
@@ -46746,7 +47261,7 @@ var init_default_backend = __esm(() => {
46746
47261
 
46747
47262
  // src/lang/backends/go.ts
46748
47263
  import * as fs15 from "fs";
46749
- import * as path31 from "path";
47264
+ import * as path32 from "path";
46750
47265
  function extractImports(_sourceFile, source) {
46751
47266
  const out = new Set;
46752
47267
  IMPORT_REGEX_SINGLE.lastIndex = 0;
@@ -46772,7 +47287,7 @@ function extractImports(_sourceFile, source) {
46772
47287
  async function selectFramework(dir) {
46773
47288
  let content;
46774
47289
  try {
46775
- content = fs15.readFileSync(path31.join(dir, "go.mod"), "utf-8");
47290
+ content = fs15.readFileSync(path32.join(dir, "go.mod"), "utf-8");
46776
47291
  } catch {
46777
47292
  return null;
46778
47293
  }
@@ -46793,16 +47308,16 @@ async function selectFramework(dir) {
46793
47308
  async function selectEntryPoints(dir) {
46794
47309
  const points = [];
46795
47310
  try {
46796
- fs15.accessSync(path31.join(dir, "main.go"));
47311
+ fs15.accessSync(path32.join(dir, "main.go"));
46797
47312
  points.push("main.go");
46798
47313
  } catch {}
46799
47314
  try {
46800
- const cmdDir = path31.join(dir, "cmd");
47315
+ const cmdDir = path32.join(dir, "cmd");
46801
47316
  const subdirs = fs15.readdirSync(cmdDir, { withFileTypes: true }).filter((d) => d.isDirectory());
46802
47317
  for (const sub of subdirs) {
46803
- const main = path31.join("cmd", sub.name, "main.go");
47318
+ const main = path32.join("cmd", sub.name, "main.go");
46804
47319
  try {
46805
- fs15.accessSync(path31.join(dir, main));
47320
+ fs15.accessSync(path32.join(dir, main));
46806
47321
  points.push(main);
46807
47322
  } catch {}
46808
47323
  }
@@ -46821,19 +47336,19 @@ function buildGoBackend() {
46821
47336
  selectEntryPoints
46822
47337
  };
46823
47338
  }
46824
- var PROFILE_ID = "go", IMPORT_REGEX_SINGLE, IMPORT_REGEX_GROUP, IMPORT_REGEX_GROUP_LINE, _internals20;
47339
+ var PROFILE_ID = "go", IMPORT_REGEX_SINGLE, IMPORT_REGEX_GROUP, IMPORT_REGEX_GROUP_LINE, _internals21;
46825
47340
  var init_go = __esm(() => {
46826
47341
  init_default_backend();
46827
47342
  init_profiles();
46828
47343
  IMPORT_REGEX_SINGLE = /^\s*import\s+(?:[a-zA-Z_.][a-zA-Z0-9_]*\s+)?"([^"]+)"/gm;
46829
47344
  IMPORT_REGEX_GROUP = /^\s*import\s*\(([\s\S]*?)\)/gm;
46830
47345
  IMPORT_REGEX_GROUP_LINE = /(?:[a-zA-Z_.][a-zA-Z0-9_]*\s+)?"([^"]+)"/g;
46831
- _internals20 = { extractImports };
47346
+ _internals21 = { extractImports };
46832
47347
  });
46833
47348
 
46834
47349
  // src/lang/backends/python.ts
46835
47350
  import * as fs16 from "fs";
46836
- import * as path32 from "path";
47351
+ import * as path33 from "path";
46837
47352
  function parseImportTargets(rawTargets) {
46838
47353
  const cleaned = rawTargets.replace(/[()]/g, "").split(`
46839
47354
  `).map((line) => line.replace(/#.*$/, "").replace(/\\\s*$/, "")).join(" ");
@@ -46893,7 +47408,7 @@ async function selectFramework2(dir) {
46893
47408
  ];
46894
47409
  for (const candidate of ["pyproject.toml", "requirements.txt", "setup.py"]) {
46895
47410
  try {
46896
- const content = fs16.readFileSync(path32.join(dir, candidate), "utf-8");
47411
+ const content = fs16.readFileSync(path33.join(dir, candidate), "utf-8");
46897
47412
  const lower = content.toLowerCase();
46898
47413
  for (const [pkg, name] of candidates) {
46899
47414
  if (lower.includes(pkg)) {
@@ -46907,7 +47422,7 @@ async function selectFramework2(dir) {
46907
47422
  async function selectEntryPoints2(dir) {
46908
47423
  const points = new Set;
46909
47424
  try {
46910
- const content = fs16.readFileSync(path32.join(dir, "pyproject.toml"), "utf-8");
47425
+ const content = fs16.readFileSync(path33.join(dir, "pyproject.toml"), "utf-8");
46911
47426
  const scriptsBlock = content.match(/\[project\.scripts\][\s\S]*?(?=\n\[|$)/);
46912
47427
  if (scriptsBlock) {
46913
47428
  for (const line of scriptsBlock[0].split(`
@@ -46922,7 +47437,7 @@ async function selectEntryPoints2(dir) {
46922
47437
  } catch {}
46923
47438
  for (const name of ["manage.py", "main.py", "app.py", "__main__.py"]) {
46924
47439
  try {
46925
- fs16.accessSync(path32.join(dir, name));
47440
+ fs16.accessSync(path33.join(dir, name));
46926
47441
  points.add(name);
46927
47442
  } catch {}
46928
47443
  }
@@ -46940,18 +47455,18 @@ function buildPythonBackend() {
46940
47455
  selectEntryPoints: selectEntryPoints2
46941
47456
  };
46942
47457
  }
46943
- var PROFILE_ID2 = "python", IMPORT_REGEX_FROM_WITH_TARGETS, IMPORT_REGEX_IMPORT, _internals21;
47458
+ var PROFILE_ID2 = "python", IMPORT_REGEX_FROM_WITH_TARGETS, IMPORT_REGEX_IMPORT, _internals22;
46944
47459
  var init_python = __esm(() => {
46945
47460
  init_default_backend();
46946
47461
  init_profiles();
46947
47462
  IMPORT_REGEX_FROM_WITH_TARGETS = /^\s*from\s+(\.*[\w.]*)\s+import\s+(\([^)]*\)|[^\n#]+)/gm;
46948
47463
  IMPORT_REGEX_IMPORT = /^\s*import\s+([^\n#]+)/gm;
46949
- _internals21 = { extractImports: extractImports2 };
47464
+ _internals22 = { extractImports: extractImports2 };
46950
47465
  });
46951
47466
 
46952
47467
  // src/test-impact/analyzer.ts
46953
47468
  import fs17 from "fs";
46954
- import path33 from "path";
47469
+ import path34 from "path";
46955
47470
  function normalizePath(p) {
46956
47471
  return p.replace(/\\/g, "/");
46957
47472
  }
@@ -46972,8 +47487,8 @@ function resolveRelativeImport(fromDir, importPath) {
46972
47487
  if (!importPath.startsWith(".")) {
46973
47488
  return null;
46974
47489
  }
46975
- const resolved = path33.resolve(fromDir, importPath);
46976
- if (path33.extname(resolved)) {
47490
+ const resolved = path34.resolve(fromDir, importPath);
47491
+ if (path34.extname(resolved)) {
46977
47492
  if (fs17.existsSync(resolved) && fs17.statSync(resolved).isFile()) {
46978
47493
  return normalizePath(resolved);
46979
47494
  }
@@ -46993,20 +47508,20 @@ function resolvePythonImport(fromDir, module) {
46993
47508
  const leadingDots = module.match(/^\.+/)?.[0].length ?? 0;
46994
47509
  let baseDir = fromDir;
46995
47510
  for (let i = 1;i < leadingDots; i++) {
46996
- baseDir = path33.dirname(baseDir);
47511
+ baseDir = path34.dirname(baseDir);
46997
47512
  }
46998
47513
  const rest = module.slice(leadingDots);
46999
47514
  if (rest.length === 0) {
47000
- const initPath = path33.join(baseDir, "__init__.py");
47515
+ const initPath = path34.join(baseDir, "__init__.py");
47001
47516
  if (fs17.existsSync(initPath) && fs17.statSync(initPath).isFile()) {
47002
47517
  return normalizePath(initPath);
47003
47518
  }
47004
47519
  return null;
47005
47520
  }
47006
- const subpath = rest.replace(/\./g, path33.sep);
47521
+ const subpath = rest.replace(/\./g, path34.sep);
47007
47522
  const candidates = [
47008
- `${path33.join(baseDir, subpath)}.py`,
47009
- path33.join(baseDir, subpath, "__init__.py")
47523
+ `${path34.join(baseDir, subpath)}.py`,
47524
+ path34.join(baseDir, subpath, "__init__.py")
47010
47525
  ];
47011
47526
  for (const c of candidates) {
47012
47527
  if (fs17.existsSync(c) && fs17.statSync(c).isFile())
@@ -47015,7 +47530,7 @@ function resolvePythonImport(fromDir, module) {
47015
47530
  return null;
47016
47531
  }
47017
47532
  function findGoModule(fromDir) {
47018
- const resolved = path33.resolve(fromDir);
47533
+ const resolved = path34.resolve(fromDir);
47019
47534
  let cur = resolved;
47020
47535
  const walked = [];
47021
47536
  for (let i = 0;i < 16; i++) {
@@ -47027,7 +47542,7 @@ function findGoModule(fromDir) {
47027
47542
  }
47028
47543
  walked.push(cur);
47029
47544
  try {
47030
- const goMod = path33.join(cur, "go.mod");
47545
+ const goMod = path34.join(cur, "go.mod");
47031
47546
  const content = fs17.readFileSync(goMod, "utf-8");
47032
47547
  const moduleMatch = content.match(/^\s*module\s+"?([^"\s/]+(?:\/[^"\s]+)*)"?/m);
47033
47548
  if (moduleMatch) {
@@ -47038,10 +47553,10 @@ function findGoModule(fromDir) {
47038
47553
  }
47039
47554
  } catch {}
47040
47555
  try {
47041
- fs17.accessSync(path33.join(cur, ".git"));
47556
+ fs17.accessSync(path34.join(cur, ".git"));
47042
47557
  break;
47043
47558
  } catch {}
47044
- const parent = path33.dirname(cur);
47559
+ const parent = path34.dirname(cur);
47045
47560
  if (parent === cur)
47046
47561
  break;
47047
47562
  cur = parent;
@@ -47053,12 +47568,12 @@ function findGoModule(fromDir) {
47053
47568
  function resolveGoImport(fromDir, importPath) {
47054
47569
  let dir = null;
47055
47570
  if (importPath.startsWith(".")) {
47056
- dir = path33.resolve(fromDir, importPath);
47571
+ dir = path34.resolve(fromDir, importPath);
47057
47572
  } else {
47058
47573
  const mod = findGoModule(fromDir);
47059
47574
  if (mod && (importPath === mod.modulePath || importPath.startsWith(`${mod.modulePath}/`))) {
47060
47575
  const subpath = importPath.slice(mod.modulePath.length);
47061
- dir = path33.join(mod.moduleRoot, subpath);
47576
+ dir = path34.join(mod.moduleRoot, subpath);
47062
47577
  }
47063
47578
  }
47064
47579
  if (dir === null)
@@ -47066,7 +47581,7 @@ function resolveGoImport(fromDir, importPath) {
47066
47581
  if (!fs17.existsSync(dir) || !fs17.statSync(dir).isDirectory())
47067
47582
  return [];
47068
47583
  try {
47069
- return fs17.readdirSync(dir).filter((f) => f.endsWith(".go") && !f.endsWith("_test.go")).map((f) => normalizePath(path33.join(dir, f)));
47584
+ return fs17.readdirSync(dir).filter((f) => f.endsWith(".go") && !f.endsWith("_test.go")).map((f) => normalizePath(path34.join(dir, f)));
47070
47585
  } catch {
47071
47586
  return [];
47072
47587
  }
@@ -47105,15 +47620,15 @@ function findTestFilesSync(cwd) {
47105
47620
  for (const entry of entries) {
47106
47621
  if (entry.isDirectory()) {
47107
47622
  if (!skipDirs.has(entry.name)) {
47108
- walk(path33.join(dir, entry.name), visitedInodes);
47623
+ walk(path34.join(dir, entry.name), visitedInodes);
47109
47624
  }
47110
47625
  } else if (entry.isFile()) {
47111
47626
  const name = entry.name;
47112
47627
  const isTsTest = /\.(test|spec)\.(ts|tsx|js|jsx)$/.test(name) || dir.includes("__tests__") && /\.(ts|tsx|js|jsx)$/.test(name);
47113
- const isPyTest = /^test_.+\.py$/.test(name) || /.+_test\.py$/.test(name) || dir.includes(`${path33.sep}tests${path33.sep}`) && name.endsWith(".py");
47628
+ const isPyTest = /^test_.+\.py$/.test(name) || /.+_test\.py$/.test(name) || dir.includes(`${path34.sep}tests${path34.sep}`) && name.endsWith(".py");
47114
47629
  const isGoTest = /.+_test\.go$/.test(name);
47115
47630
  if (isTsTest || isPyTest || isGoTest) {
47116
- testFiles.push(normalizePath(path33.join(dir, entry.name)));
47631
+ testFiles.push(normalizePath(path34.join(dir, entry.name)));
47117
47632
  }
47118
47633
  }
47119
47634
  }
@@ -47138,8 +47653,8 @@ function extractImports3(content) {
47138
47653
  ];
47139
47654
  }
47140
47655
  function addImpactEdgesForTestFile(testFile, content, impactMap) {
47141
- const ext = path33.extname(testFile).toLowerCase();
47142
- const testDir = path33.dirname(testFile);
47656
+ const ext = path34.extname(testFile).toLowerCase();
47657
+ const testDir = path34.dirname(testFile);
47143
47658
  function addEdge(source) {
47144
47659
  if (!impactMap[source])
47145
47660
  impactMap[source] = [];
@@ -47157,7 +47672,7 @@ function addImpactEdgesForTestFile(testFile, content, impactMap) {
47157
47672
  return;
47158
47673
  }
47159
47674
  if (PYTHON_EXTENSIONS.has(ext)) {
47160
- const modules = _internals21.extractImports(testFile, content);
47675
+ const modules = _internals22.extractImports(testFile, content);
47161
47676
  for (const mod of modules) {
47162
47677
  const resolved = resolvePythonImport(testDir, mod);
47163
47678
  if (resolved !== null)
@@ -47166,7 +47681,7 @@ function addImpactEdgesForTestFile(testFile, content, impactMap) {
47166
47681
  return;
47167
47682
  }
47168
47683
  if (GO_EXTENSIONS.has(ext)) {
47169
- const imports = _internals20.extractImports(testFile, content);
47684
+ const imports = _internals21.extractImports(testFile, content);
47170
47685
  for (const importPath of imports) {
47171
47686
  const sourceFiles = resolveGoImport(testDir, importPath);
47172
47687
  for (const source of sourceFiles)
@@ -47193,12 +47708,12 @@ async function buildImpactMapInternal(cwd) {
47193
47708
  return impactMap;
47194
47709
  }
47195
47710
  async function buildImpactMap(cwd) {
47196
- const impactMap = await _internals22.buildImpactMapInternal(cwd);
47197
- await _internals22.saveImpactMap(cwd, impactMap);
47711
+ const impactMap = await _internals23.buildImpactMapInternal(cwd);
47712
+ await _internals23.saveImpactMap(cwd, impactMap);
47198
47713
  return impactMap;
47199
47714
  }
47200
47715
  async function loadImpactMap(cwd, options) {
47201
- const cachePath = path33.join(cwd, ".swarm", "cache", "impact-map.json");
47716
+ const cachePath = path34.join(cwd, ".swarm", "cache", "impact-map.json");
47202
47717
  if (fs17.existsSync(cachePath)) {
47203
47718
  try {
47204
47719
  const content = fs17.readFileSync(cachePath, "utf-8");
@@ -47208,7 +47723,7 @@ async function loadImpactMap(cwd, options) {
47208
47723
  const hasValidValues = Object.values(map3).every((v) => Array.isArray(v) && v.every((item) => typeof item === "string"));
47209
47724
  if (hasValidValues) {
47210
47725
  const generatedAt = new Date(data.generatedAt).getTime();
47211
- if (!_internals22.isCacheStale(map3, generatedAt)) {
47726
+ if (!_internals23.isCacheStale(map3, generatedAt)) {
47212
47727
  return map3;
47213
47728
  }
47214
47729
  if (options?.skipRebuild) {
@@ -47228,15 +47743,15 @@ async function loadImpactMap(cwd, options) {
47228
47743
  if (options?.skipRebuild) {
47229
47744
  return {};
47230
47745
  }
47231
- return _internals22.buildImpactMap(cwd);
47746
+ return _internals23.buildImpactMap(cwd);
47232
47747
  }
47233
47748
  async function saveImpactMap(cwd, impactMap) {
47234
- if (!path33.isAbsolute(cwd)) {
47749
+ if (!path34.isAbsolute(cwd)) {
47235
47750
  throw new Error(`saveImpactMap requires an absolute project root path, got: "${cwd}"`);
47236
47751
  }
47237
- _internals22.validateProjectRoot(cwd);
47238
- const cacheDir2 = path33.join(cwd, ".swarm", "cache");
47239
- const cachePath = path33.join(cacheDir2, "impact-map.json");
47752
+ _internals23.validateProjectRoot(cwd);
47753
+ const cacheDir2 = path34.join(cwd, ".swarm", "cache");
47754
+ const cachePath = path34.join(cacheDir2, "impact-map.json");
47240
47755
  if (!fs17.existsSync(cacheDir2)) {
47241
47756
  fs17.mkdirSync(cacheDir2, { recursive: true });
47242
47757
  }
@@ -47258,7 +47773,7 @@ async function analyzeImpact(changedFiles, cwd, budget) {
47258
47773
  };
47259
47774
  }
47260
47775
  const validFiles = changedFiles.filter((f) => typeof f === "string" && f.length > 0 && !f.includes("\x00"));
47261
- const impactMap = await _internals22.loadImpactMap(cwd);
47776
+ const impactMap = await _internals23.loadImpactMap(cwd);
47262
47777
  const impactedTestsSet = new Set;
47263
47778
  const untestedFiles = [];
47264
47779
  let visitedCount = 0;
@@ -47268,7 +47783,7 @@ async function analyzeImpact(changedFiles, cwd, budget) {
47268
47783
  budgetExceeded = true;
47269
47784
  break;
47270
47785
  }
47271
- const normalizedChanged = normalizePath(path33.resolve(changedFile));
47786
+ const normalizedChanged = normalizePath(path34.resolve(changedFile));
47272
47787
  const tests = impactMap[normalizedChanged];
47273
47788
  if (tests && tests.length > 0) {
47274
47789
  for (const test of tests) {
@@ -47325,7 +47840,7 @@ async function analyzeImpact(changedFiles, cwd, budget) {
47325
47840
  budgetExceeded
47326
47841
  };
47327
47842
  }
47328
- var IMPORT_REGEX_ES, IMPORT_REGEX_REQUIRE, IMPORT_REGEX_REEXPORT, TS_EXTENSIONS, PYTHON_EXTENSIONS, GO_EXTENSIONS, EXTENSIONS_TO_TRY, goModuleCache, _internals22;
47843
+ var IMPORT_REGEX_ES, IMPORT_REGEX_REQUIRE, IMPORT_REGEX_REEXPORT, TS_EXTENSIONS, PYTHON_EXTENSIONS, GO_EXTENSIONS, EXTENSIONS_TO_TRY, goModuleCache, _internals23;
47329
47844
  var init_analyzer = __esm(() => {
47330
47845
  init_manager2();
47331
47846
  init_go();
@@ -47338,7 +47853,7 @@ var init_analyzer = __esm(() => {
47338
47853
  GO_EXTENSIONS = new Set([".go"]);
47339
47854
  EXTENSIONS_TO_TRY = [".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs"];
47340
47855
  goModuleCache = new Map;
47341
- _internals22 = {
47856
+ _internals23 = {
47342
47857
  validateProjectRoot,
47343
47858
  normalizePath,
47344
47859
  isCacheStale,
@@ -47561,15 +48076,15 @@ var FLAKY_THRESHOLD = 0.3, MIN_RUNS_FOR_QUARANTINE = 5, MAX_HISTORY_RUNS = 20;
47561
48076
 
47562
48077
  // src/test-impact/history-store.ts
47563
48078
  import fs18 from "fs";
47564
- import path34 from "path";
48079
+ import path35 from "path";
47565
48080
  function getHistoryPath(workingDir) {
47566
48081
  if (!workingDir) {
47567
48082
  throw new Error("getHistoryPath requires a working directory \u2014 project root must be provided by the caller");
47568
48083
  }
47569
- if (!path34.isAbsolute(workingDir)) {
48084
+ if (!path35.isAbsolute(workingDir)) {
47570
48085
  throw new Error(`getHistoryPath requires an absolute project root path, got: "${workingDir}"`);
47571
48086
  }
47572
- return path34.join(workingDir, ".swarm", "cache", "test-history.jsonl");
48087
+ return path35.join(workingDir, ".swarm", "cache", "test-history.jsonl");
47573
48088
  }
47574
48089
  function sanitizeErrorMessage(errorMessage) {
47575
48090
  if (errorMessage === undefined) {
@@ -47656,8 +48171,8 @@ function batchAppendTestRuns(records, workingDir) {
47656
48171
  }
47657
48172
  }
47658
48173
  const historyPath = getHistoryPath(workingDir);
47659
- const historyDir = path34.dirname(historyPath);
47660
- _internals23.validateProjectRoot(workingDir);
48174
+ const historyDir = path35.dirname(historyPath);
48175
+ _internals24.validateProjectRoot(workingDir);
47661
48176
  if (!fs18.existsSync(historyDir)) {
47662
48177
  fs18.mkdirSync(historyDir, { recursive: true });
47663
48178
  }
@@ -47737,7 +48252,7 @@ function getAllHistory(workingDir) {
47737
48252
  records.sort((a, b) => new Date(a.timestamp).getTime() - new Date(b.timestamp).getTime());
47738
48253
  return records;
47739
48254
  }
47740
- var MAX_HISTORY_PER_TEST = 20, MAX_ERROR_LENGTH = 500, MAX_STACK_LENGTH = 200, MAX_CHANGED_FILES = 50, DANGEROUS_PROPERTY_NAMES, _internals23;
48255
+ var MAX_HISTORY_PER_TEST = 20, MAX_ERROR_LENGTH = 500, MAX_STACK_LENGTH = 200, MAX_CHANGED_FILES = 50, DANGEROUS_PROPERTY_NAMES, _internals24;
47741
48256
  var init_history_store = __esm(() => {
47742
48257
  init_manager2();
47743
48258
  DANGEROUS_PROPERTY_NAMES = new Set([
@@ -47745,14 +48260,14 @@ var init_history_store = __esm(() => {
47745
48260
  "constructor",
47746
48261
  "prototype"
47747
48262
  ]);
47748
- _internals23 = {
48263
+ _internals24 = {
47749
48264
  validateProjectRoot
47750
48265
  };
47751
48266
  });
47752
48267
 
47753
48268
  // src/tools/resolve-working-directory.ts
47754
48269
  import * as fs19 from "fs";
47755
- import * as path35 from "path";
48270
+ import * as path36 from "path";
47756
48271
  function resolveWorkingDirectory(workingDirectory, fallbackDirectory) {
47757
48272
  if (workingDirectory == null || workingDirectory === "") {
47758
48273
  return { success: true, directory: fallbackDirectory };
@@ -47772,15 +48287,15 @@ function resolveWorkingDirectory(workingDirectory, fallbackDirectory) {
47772
48287
  };
47773
48288
  }
47774
48289
  }
47775
- const normalizedDir = path35.normalize(workingDirectory);
47776
- const pathParts = normalizedDir.split(path35.sep);
48290
+ const normalizedDir = path36.normalize(workingDirectory);
48291
+ const pathParts = normalizedDir.split(path36.sep);
47777
48292
  if (pathParts.includes("..")) {
47778
48293
  return {
47779
48294
  success: false,
47780
48295
  message: "Invalid working_directory: path traversal sequences (..) are not allowed"
47781
48296
  };
47782
48297
  }
47783
- const resolvedDir = path35.resolve(normalizedDir);
48298
+ const resolvedDir = path36.resolve(normalizedDir);
47784
48299
  let statResult;
47785
48300
  try {
47786
48301
  statResult = fs19.statSync(resolvedDir);
@@ -47796,7 +48311,7 @@ function resolveWorkingDirectory(workingDirectory, fallbackDirectory) {
47796
48311
  message: `Invalid working_directory: path "${resolvedDir}" is not a directory`
47797
48312
  };
47798
48313
  }
47799
- const resolvedFallback = path35.resolve(fallbackDirectory);
48314
+ const resolvedFallback = path36.resolve(fallbackDirectory);
47800
48315
  let fallbackExists = false;
47801
48316
  try {
47802
48317
  fs19.statSync(resolvedFallback);
@@ -47806,7 +48321,7 @@ function resolveWorkingDirectory(workingDirectory, fallbackDirectory) {
47806
48321
  }
47807
48322
  if (workingDirectory != null && workingDirectory !== "") {
47808
48323
  if (fallbackExists) {
47809
- const isSubdirectory = resolvedDir.startsWith(resolvedFallback + path35.sep);
48324
+ const isSubdirectory = resolvedDir.startsWith(resolvedFallback + path36.sep);
47810
48325
  if (isSubdirectory) {
47811
48326
  return {
47812
48327
  success: false,
@@ -47861,17 +48376,17 @@ var init_registry_backend = __esm(() => {
47861
48376
 
47862
48377
  // src/lang/backends/typescript.ts
47863
48378
  import * as fs20 from "fs";
47864
- import * as path36 from "path";
48379
+ import * as path37 from "path";
47865
48380
  function readPackageJsonRaw(dir) {
47866
48381
  try {
47867
- const content = fs20.readFileSync(path36.join(dir, "package.json"), "utf-8");
48382
+ const content = fs20.readFileSync(path37.join(dir, "package.json"), "utf-8");
47868
48383
  return JSON.parse(content);
47869
48384
  } catch {
47870
48385
  return null;
47871
48386
  }
47872
48387
  }
47873
48388
  function readPackageJson(dir) {
47874
- return _internals24.readPackageJsonRaw(dir);
48389
+ return _internals25.readPackageJsonRaw(dir);
47875
48390
  }
47876
48391
  function readPackageJsonTestScript(dir) {
47877
48392
  return readPackageJson(dir)?.scripts?.test ?? null;
@@ -48041,7 +48556,7 @@ function buildTypescriptBackend() {
48041
48556
  selectEntryPoints: selectEntryPoints3
48042
48557
  };
48043
48558
  }
48044
- var PROFILE_ID3 = "typescript", IMPORT_REGEX_ES2, IMPORT_REGEX_BARE, IMPORT_REGEX_REQUIRE2, IMPORT_REGEX_DYNAMIC, IMPORT_REGEX_REEXPORT2, _internals24;
48559
+ var PROFILE_ID3 = "typescript", IMPORT_REGEX_ES2, IMPORT_REGEX_BARE, IMPORT_REGEX_REQUIRE2, IMPORT_REGEX_DYNAMIC, IMPORT_REGEX_REEXPORT2, _internals25;
48045
48560
  var init_typescript = __esm(() => {
48046
48561
  init_default_backend();
48047
48562
  init_profiles();
@@ -48050,7 +48565,7 @@ var init_typescript = __esm(() => {
48050
48565
  IMPORT_REGEX_REQUIRE2 = /require\s*\(\s*['"]([^'"]+)['"]\s*\)/g;
48051
48566
  IMPORT_REGEX_DYNAMIC = /import\s*\(\s*['"]([^'"]+)['"]\s*\)/g;
48052
48567
  IMPORT_REGEX_REEXPORT2 = /export\s+(?:\{[^}]*\}|\*)\s+from\s+['"]([^'"]+)['"]/g;
48053
- _internals24 = {
48568
+ _internals25 = {
48054
48569
  readPackageJsonRaw,
48055
48570
  readPackageJsonTestScript,
48056
48571
  frameworkFromScriptsTest
@@ -48081,10 +48596,10 @@ __export(exports_dispatch, {
48081
48596
  pickedProfiles: () => pickedProfiles,
48082
48597
  pickBackend: () => pickBackend,
48083
48598
  clearDispatchCache: () => clearDispatchCache,
48084
- _internals: () => _internals25
48599
+ _internals: () => _internals26
48085
48600
  });
48086
48601
  import * as fs21 from "fs";
48087
- import * as path37 from "path";
48602
+ import * as path38 from "path";
48088
48603
  function safeReaddirSet(dir) {
48089
48604
  try {
48090
48605
  return new Set(fs21.readdirSync(dir));
@@ -48101,14 +48616,14 @@ function manifestHash(dir) {
48101
48616
  if (!entries.has(name))
48102
48617
  continue;
48103
48618
  try {
48104
- const stat3 = fs21.statSync(path37.join(dir, name));
48619
+ const stat3 = fs21.statSync(path38.join(dir, name));
48105
48620
  parts.push(`${name}:${stat3.size}:${stat3.mtimeMs}:${stat3.ino}`);
48106
48621
  } catch {}
48107
48622
  }
48108
48623
  return parts.join("|");
48109
48624
  }
48110
48625
  function findManifestRoot(start) {
48111
- const resolved = path37.resolve(start);
48626
+ const resolved = path38.resolve(start);
48112
48627
  const cached3 = manifestRootCache.get(resolved);
48113
48628
  if (cached3 !== undefined)
48114
48629
  return cached3;
@@ -48127,7 +48642,7 @@ function findManifestRoot(start) {
48127
48642
  return cur;
48128
48643
  }
48129
48644
  }
48130
- const parent = path37.dirname(cur);
48645
+ const parent = path38.dirname(cur);
48131
48646
  if (parent === cur)
48132
48647
  break;
48133
48648
  cur = parent;
@@ -48136,7 +48651,7 @@ function findManifestRoot(start) {
48136
48651
  return start;
48137
48652
  }
48138
48653
  function evictIfNeeded() {
48139
- if (cache.size <= _internals25.cacheCapacity)
48654
+ if (cache.size <= _internals26.cacheCapacity)
48140
48655
  return;
48141
48656
  let oldestKey;
48142
48657
  let oldestOrder = Infinity;
@@ -48167,7 +48682,7 @@ async function pickBackend(dir) {
48167
48682
  evictIfNeeded();
48168
48683
  return null;
48169
48684
  }
48170
- const profiles = await _internals25.detectProjectLanguages(root);
48685
+ const profiles = await _internals26.detectProjectLanguages(root);
48171
48686
  if (profiles.length === 0) {
48172
48687
  cache.set(cacheKey, {
48173
48688
  hash: hash3,
@@ -48199,12 +48714,12 @@ function clearDispatchCache() {
48199
48714
  manifestRootCache.clear();
48200
48715
  insertCounter = 0;
48201
48716
  }
48202
- var _internals25, cache, insertCounter = 0, MANIFEST_FILES, _MANIFEST_SET, manifestRootCache;
48717
+ var _internals26, cache, insertCounter = 0, MANIFEST_FILES, _MANIFEST_SET, manifestRootCache;
48203
48718
  var init_dispatch = __esm(() => {
48204
48719
  init_backends();
48205
48720
  init_detector();
48206
48721
  init_registry_backend();
48207
- _internals25 = {
48722
+ _internals26 = {
48208
48723
  detectProjectLanguages,
48209
48724
  cacheCapacity: 64
48210
48725
  };
@@ -48237,13 +48752,13 @@ var init_dispatch = __esm(() => {
48237
48752
 
48238
48753
  // src/tools/test-runner.ts
48239
48754
  import * as fs22 from "fs";
48240
- import * as path38 from "path";
48755
+ import * as path39 from "path";
48241
48756
  async function estimateFanOut(sourceFiles, cwd) {
48242
48757
  try {
48243
48758
  const impactMap = await loadImpactMap(cwd, { skipRebuild: true });
48244
48759
  const uniqueTestFiles = new Set;
48245
48760
  for (const sourceFile of sourceFiles) {
48246
- const resolvedPath = path38.resolve(cwd, sourceFile);
48761
+ const resolvedPath = path39.resolve(cwd, sourceFile);
48247
48762
  const normalizedPath = resolvedPath.replace(/\\/g, "/");
48248
48763
  const testFiles = impactMap[normalizedPath];
48249
48764
  if (testFiles) {
@@ -48321,14 +48836,14 @@ function hasDevDependency(devDeps, ...patterns) {
48321
48836
  return hasPackageJsonDependency(devDeps, ...patterns);
48322
48837
  }
48323
48838
  function detectGoTest(cwd) {
48324
- return fs22.existsSync(path38.join(cwd, "go.mod")) && isCommandAvailable("go");
48839
+ return fs22.existsSync(path39.join(cwd, "go.mod")) && isCommandAvailable("go");
48325
48840
  }
48326
48841
  function detectJavaMaven(cwd) {
48327
- return fs22.existsSync(path38.join(cwd, "pom.xml")) && isCommandAvailable("mvn");
48842
+ return fs22.existsSync(path39.join(cwd, "pom.xml")) && isCommandAvailable("mvn");
48328
48843
  }
48329
48844
  function detectGradle(cwd) {
48330
- const hasBuildFile = fs22.existsSync(path38.join(cwd, "build.gradle")) || fs22.existsSync(path38.join(cwd, "build.gradle.kts"));
48331
- const hasGradlew = fs22.existsSync(path38.join(cwd, "gradlew")) || fs22.existsSync(path38.join(cwd, "gradlew.bat"));
48845
+ const hasBuildFile = fs22.existsSync(path39.join(cwd, "build.gradle")) || fs22.existsSync(path39.join(cwd, "build.gradle.kts"));
48846
+ const hasGradlew = fs22.existsSync(path39.join(cwd, "gradlew")) || fs22.existsSync(path39.join(cwd, "gradlew.bat"));
48332
48847
  return hasBuildFile && (hasGradlew || isCommandAvailable("gradle"));
48333
48848
  }
48334
48849
  function detectDotnetTest(cwd) {
@@ -48341,25 +48856,25 @@ function detectDotnetTest(cwd) {
48341
48856
  }
48342
48857
  }
48343
48858
  function detectCTest(cwd) {
48344
- const hasSource = fs22.existsSync(path38.join(cwd, "CMakeLists.txt"));
48345
- const hasBuildCache = fs22.existsSync(path38.join(cwd, "CMakeCache.txt")) || fs22.existsSync(path38.join(cwd, "build", "CMakeCache.txt"));
48859
+ const hasSource = fs22.existsSync(path39.join(cwd, "CMakeLists.txt"));
48860
+ const hasBuildCache = fs22.existsSync(path39.join(cwd, "CMakeCache.txt")) || fs22.existsSync(path39.join(cwd, "build", "CMakeCache.txt"));
48346
48861
  return (hasSource || hasBuildCache) && isCommandAvailable("ctest");
48347
48862
  }
48348
48863
  function detectSwiftTest(cwd) {
48349
- return fs22.existsSync(path38.join(cwd, "Package.swift")) && isCommandAvailable("swift");
48864
+ return fs22.existsSync(path39.join(cwd, "Package.swift")) && isCommandAvailable("swift");
48350
48865
  }
48351
48866
  function detectDartTest(cwd) {
48352
- return fs22.existsSync(path38.join(cwd, "pubspec.yaml")) && (isCommandAvailable("dart") || isCommandAvailable("flutter"));
48867
+ return fs22.existsSync(path39.join(cwd, "pubspec.yaml")) && (isCommandAvailable("dart") || isCommandAvailable("flutter"));
48353
48868
  }
48354
48869
  function detectRSpec(cwd) {
48355
- const hasRSpecFile = fs22.existsSync(path38.join(cwd, ".rspec"));
48356
- const hasGemfile = fs22.existsSync(path38.join(cwd, "Gemfile"));
48357
- const hasSpecDir = fs22.existsSync(path38.join(cwd, "spec"));
48870
+ const hasRSpecFile = fs22.existsSync(path39.join(cwd, ".rspec"));
48871
+ const hasGemfile = fs22.existsSync(path39.join(cwd, "Gemfile"));
48872
+ const hasSpecDir = fs22.existsSync(path39.join(cwd, "spec"));
48358
48873
  const hasRSpec = hasRSpecFile || hasGemfile && hasSpecDir;
48359
48874
  return hasRSpec && (isCommandAvailable("bundle") || isCommandAvailable("rspec"));
48360
48875
  }
48361
48876
  function detectMinitest(cwd) {
48362
- return fs22.existsSync(path38.join(cwd, "test")) && (fs22.existsSync(path38.join(cwd, "Gemfile")) || fs22.existsSync(path38.join(cwd, "Rakefile"))) && isCommandAvailable("ruby");
48877
+ return fs22.existsSync(path39.join(cwd, "test")) && (fs22.existsSync(path39.join(cwd, "Gemfile")) || fs22.existsSync(path39.join(cwd, "Rakefile"))) && isCommandAvailable("ruby");
48363
48878
  }
48364
48879
  async function detectTestFrameworkViaDispatch(cwd) {
48365
48880
  try {
@@ -48421,7 +48936,7 @@ async function parseTestOutputViaDispatch(framework, output, baseDir) {
48421
48936
  async function detectTestFramework(cwd) {
48422
48937
  const baseDir = cwd;
48423
48938
  try {
48424
- const packageJsonPath = path38.join(baseDir, "package.json");
48939
+ const packageJsonPath = path39.join(baseDir, "package.json");
48425
48940
  if (fs22.existsSync(packageJsonPath)) {
48426
48941
  const content = fs22.readFileSync(packageJsonPath, "utf-8");
48427
48942
  const pkg = JSON.parse(content);
@@ -48442,16 +48957,16 @@ async function detectTestFramework(cwd) {
48442
48957
  return "jest";
48443
48958
  if (hasDevDependency(devDeps, "mocha", "@types/mocha"))
48444
48959
  return "mocha";
48445
- if (fs22.existsSync(path38.join(baseDir, "bun.lockb")) || fs22.existsSync(path38.join(baseDir, "bun.lock"))) {
48960
+ if (fs22.existsSync(path39.join(baseDir, "bun.lockb")) || fs22.existsSync(path39.join(baseDir, "bun.lock"))) {
48446
48961
  if (scripts.test?.includes("bun"))
48447
48962
  return "bun";
48448
48963
  }
48449
48964
  }
48450
48965
  } catch {}
48451
48966
  try {
48452
- const pyprojectTomlPath = path38.join(baseDir, "pyproject.toml");
48453
- const setupCfgPath = path38.join(baseDir, "setup.cfg");
48454
- const requirementsTxtPath = path38.join(baseDir, "requirements.txt");
48967
+ const pyprojectTomlPath = path39.join(baseDir, "pyproject.toml");
48968
+ const setupCfgPath = path39.join(baseDir, "setup.cfg");
48969
+ const requirementsTxtPath = path39.join(baseDir, "requirements.txt");
48455
48970
  if (fs22.existsSync(pyprojectTomlPath)) {
48456
48971
  const content = fs22.readFileSync(pyprojectTomlPath, "utf-8");
48457
48972
  if (content.includes("[tool.pytest"))
@@ -48471,7 +48986,7 @@ async function detectTestFramework(cwd) {
48471
48986
  }
48472
48987
  } catch {}
48473
48988
  try {
48474
- const cargoTomlPath = path38.join(baseDir, "Cargo.toml");
48989
+ const cargoTomlPath = path39.join(baseDir, "Cargo.toml");
48475
48990
  if (fs22.existsSync(cargoTomlPath)) {
48476
48991
  const content = fs22.readFileSync(cargoTomlPath, "utf-8");
48477
48992
  if (content.includes("[dev-dependencies]")) {
@@ -48482,9 +48997,9 @@ async function detectTestFramework(cwd) {
48482
48997
  }
48483
48998
  } catch {}
48484
48999
  try {
48485
- const pesterConfigPath = path38.join(baseDir, "pester.config.ps1");
48486
- const pesterConfigJsonPath = path38.join(baseDir, "pester.config.ps1.json");
48487
- const pesterPs1Path = path38.join(baseDir, "tests.ps1");
49000
+ const pesterConfigPath = path39.join(baseDir, "pester.config.ps1");
49001
+ const pesterConfigJsonPath = path39.join(baseDir, "pester.config.ps1.json");
49002
+ const pesterPs1Path = path39.join(baseDir, "tests.ps1");
48488
49003
  if (fs22.existsSync(pesterConfigPath) || fs22.existsSync(pesterConfigJsonPath) || fs22.existsSync(pesterPs1Path)) {
48489
49004
  return "pester";
48490
49005
  }
@@ -48513,12 +49028,12 @@ function isTestDirectoryPath(normalizedPath) {
48513
49028
  return normalizedPath.split("/").some((segment) => TEST_DIRECTORY_NAMES.includes(segment));
48514
49029
  }
48515
49030
  function resolveWorkspacePath(file3, workingDir) {
48516
- return path38.isAbsolute(file3) ? path38.resolve(file3) : path38.resolve(workingDir, file3);
49031
+ return path39.isAbsolute(file3) ? path39.resolve(file3) : path39.resolve(workingDir, file3);
48517
49032
  }
48518
49033
  function toWorkspaceOutputPath(absolutePath, workingDir, preferRelative) {
48519
49034
  if (!preferRelative)
48520
49035
  return absolutePath;
48521
- return path38.relative(workingDir, absolutePath);
49036
+ return path39.relative(workingDir, absolutePath);
48522
49037
  }
48523
49038
  function dedupePush(target, value) {
48524
49039
  if (!target.includes(value)) {
@@ -48555,18 +49070,18 @@ function buildLanguageSpecificTestNames(nameWithoutExt, ext) {
48555
49070
  }
48556
49071
  }
48557
49072
  function getRepoLevelCandidateDirectories(workingDir, relativePath, ext) {
48558
- const relativeDir = path38.dirname(relativePath);
49073
+ const relativeDir = path39.dirname(relativePath);
48559
49074
  const nestedRelativeDir = relativeDir === "." ? "" : relativeDir;
48560
49075
  const directories = TEST_DIRECTORY_NAMES.flatMap((dirName) => {
48561
- const rootDir = path38.join(workingDir, dirName);
48562
- return nestedRelativeDir ? [rootDir, path38.join(rootDir, nestedRelativeDir)] : [rootDir];
49076
+ const rootDir = path39.join(workingDir, dirName);
49077
+ return nestedRelativeDir ? [rootDir, path39.join(rootDir, nestedRelativeDir)] : [rootDir];
48563
49078
  });
48564
49079
  const normalizedRelativePath = relativePath.replace(/\\/g, "/");
48565
49080
  if (ext === ".java" && normalizedRelativePath.startsWith("src/main/java/")) {
48566
- directories.push(path38.join(workingDir, "src/test/java", path38.dirname(normalizedRelativePath.slice("src/main/java/".length))));
49081
+ directories.push(path39.join(workingDir, "src/test/java", path39.dirname(normalizedRelativePath.slice("src/main/java/".length))));
48567
49082
  }
48568
49083
  if ((ext === ".kt" || ext === ".java") && normalizedRelativePath.startsWith("src/main/kotlin/")) {
48569
- directories.push(path38.join(workingDir, "src/test/kotlin", path38.dirname(normalizedRelativePath.slice("src/main/kotlin/".length))));
49084
+ directories.push(path39.join(workingDir, "src/test/kotlin", path39.dirname(normalizedRelativePath.slice("src/main/kotlin/".length))));
48570
49085
  }
48571
49086
  return [...new Set(directories)];
48572
49087
  }
@@ -48594,23 +49109,23 @@ function isLanguageSpecificTestFile(basename6) {
48594
49109
  }
48595
49110
  function isConventionTestFilePath(filePath) {
48596
49111
  const normalizedPath = filePath.replace(/\\/g, "/");
48597
- const basename6 = path38.basename(filePath);
49112
+ const basename6 = path39.basename(filePath);
48598
49113
  return hasCompoundTestExtension(basename6) || basename6.includes(".spec.") || basename6.includes(".test.") || isLanguageSpecificTestFile(basename6) || isTestDirectoryPath(normalizedPath);
48599
49114
  }
48600
49115
  function getTestFilesFromConvention(sourceFiles, workingDir = process.cwd()) {
48601
49116
  const testFiles = [];
48602
49117
  for (const file3 of sourceFiles) {
48603
49118
  const absoluteFile = resolveWorkspacePath(file3, workingDir);
48604
- const relativeFile = path38.relative(workingDir, absoluteFile);
48605
- const basename6 = path38.basename(absoluteFile);
48606
- const dirname17 = path38.dirname(absoluteFile);
48607
- const preferRelativeOutput = !path38.isAbsolute(file3);
49119
+ const relativeFile = path39.relative(workingDir, absoluteFile);
49120
+ const basename6 = path39.basename(absoluteFile);
49121
+ const dirname17 = path39.dirname(absoluteFile);
49122
+ const preferRelativeOutput = !path39.isAbsolute(file3);
48608
49123
  if (isConventionTestFilePath(relativeFile) || isConventionTestFilePath(file3)) {
48609
49124
  dedupePush(testFiles, toWorkspaceOutputPath(absoluteFile, workingDir, preferRelativeOutput));
48610
49125
  continue;
48611
49126
  }
48612
49127
  const nameWithoutExt = basename6.replace(/\.[^.]+$/, "");
48613
- const ext = path38.extname(basename6);
49128
+ const ext = path39.extname(basename6);
48614
49129
  const genericTestNames = [
48615
49130
  `${nameWithoutExt}.spec${ext}`,
48616
49131
  `${nameWithoutExt}.test${ext}`
@@ -48619,7 +49134,7 @@ function getTestFilesFromConvention(sourceFiles, workingDir = process.cwd()) {
48619
49134
  const colocatedCandidates = [
48620
49135
  ...genericTestNames,
48621
49136
  ...languageSpecificTestNames
48622
- ].map((candidateName) => path38.join(dirname17, candidateName));
49137
+ ].map((candidateName) => path39.join(dirname17, candidateName));
48623
49138
  const testDirectoryNames = [
48624
49139
  basename6,
48625
49140
  ...genericTestNames,
@@ -48628,8 +49143,8 @@ function getTestFilesFromConvention(sourceFiles, workingDir = process.cwd()) {
48628
49143
  const repoLevelDirectories = getRepoLevelCandidateDirectories(workingDir, relativeFile, ext);
48629
49144
  const possibleTestFiles = [
48630
49145
  ...colocatedCandidates,
48631
- ...TEST_DIRECTORY_NAMES.flatMap((dirName) => testDirectoryNames.map((candidateName) => path38.join(dirname17, dirName, candidateName))),
48632
- ...repoLevelDirectories.flatMap((candidateDir) => testDirectoryNames.map((candidateName) => path38.join(candidateDir, candidateName)))
49146
+ ...TEST_DIRECTORY_NAMES.flatMap((dirName) => testDirectoryNames.map((candidateName) => path39.join(dirname17, dirName, candidateName))),
49147
+ ...repoLevelDirectories.flatMap((candidateDir) => testDirectoryNames.map((candidateName) => path39.join(candidateDir, candidateName)))
48633
49148
  ];
48634
49149
  for (const testFile of possibleTestFiles) {
48635
49150
  if (fs22.existsSync(testFile)) {
@@ -48650,7 +49165,7 @@ async function getTestFilesFromGraph(sourceFiles, workingDir) {
48650
49165
  try {
48651
49166
  const absoluteTestFile = resolveWorkspacePath(testFile, workingDir);
48652
49167
  const content = fs22.readFileSync(absoluteTestFile, "utf-8");
48653
- const testDir = path38.dirname(absoluteTestFile);
49168
+ const testDir = path39.dirname(absoluteTestFile);
48654
49169
  const importRegex = /import\s+.*?\s+from\s+['"]([^'"]+)['"]/g;
48655
49170
  let match;
48656
49171
  match = importRegex.exec(content);
@@ -48658,8 +49173,8 @@ async function getTestFilesFromGraph(sourceFiles, workingDir) {
48658
49173
  const importPath = match[1];
48659
49174
  let resolvedImport;
48660
49175
  if (importPath.startsWith(".")) {
48661
- resolvedImport = path38.resolve(testDir, importPath);
48662
- const existingExt = path38.extname(resolvedImport);
49176
+ resolvedImport = path39.resolve(testDir, importPath);
49177
+ const existingExt = path39.extname(resolvedImport);
48663
49178
  if (!existingExt) {
48664
49179
  for (const extToTry of [
48665
49180
  ".ts",
@@ -48679,12 +49194,12 @@ async function getTestFilesFromGraph(sourceFiles, workingDir) {
48679
49194
  } else {
48680
49195
  continue;
48681
49196
  }
48682
- const importBasename = path38.basename(resolvedImport, path38.extname(resolvedImport));
48683
- const importDir = path38.dirname(resolvedImport);
49197
+ const importBasename = path39.basename(resolvedImport, path39.extname(resolvedImport));
49198
+ const importDir = path39.dirname(resolvedImport);
48684
49199
  for (const sourceFile of absoluteSourceFiles) {
48685
- const sourceDir = path38.dirname(sourceFile);
48686
- const sourceBasename = path38.basename(sourceFile, path38.extname(sourceFile));
48687
- const isRelatedDir = importDir === sourceDir || importDir === path38.join(sourceDir, "__tests__") || importDir === path38.join(sourceDir, "tests") || importDir === path38.join(sourceDir, "test") || importDir === path38.join(sourceDir, "spec");
49200
+ const sourceDir = path39.dirname(sourceFile);
49201
+ const sourceBasename = path39.basename(sourceFile, path39.extname(sourceFile));
49202
+ const isRelatedDir = importDir === sourceDir || importDir === path39.join(sourceDir, "__tests__") || importDir === path39.join(sourceDir, "tests") || importDir === path39.join(sourceDir, "test") || importDir === path39.join(sourceDir, "spec");
48688
49203
  if (resolvedImport === sourceFile || importBasename === sourceBasename && isRelatedDir) {
48689
49204
  dedupePush(testFiles, testFile);
48690
49205
  break;
@@ -48697,8 +49212,8 @@ async function getTestFilesFromGraph(sourceFiles, workingDir) {
48697
49212
  while (match !== null) {
48698
49213
  const importPath = match[1];
48699
49214
  if (importPath.startsWith(".")) {
48700
- let resolvedImport = path38.resolve(testDir, importPath);
48701
- const existingExt = path38.extname(resolvedImport);
49215
+ let resolvedImport = path39.resolve(testDir, importPath);
49216
+ const existingExt = path39.extname(resolvedImport);
48702
49217
  if (!existingExt) {
48703
49218
  for (const extToTry of [
48704
49219
  ".ts",
@@ -48715,12 +49230,12 @@ async function getTestFilesFromGraph(sourceFiles, workingDir) {
48715
49230
  }
48716
49231
  }
48717
49232
  }
48718
- const importDir = path38.dirname(resolvedImport);
48719
- const importBasename = path38.basename(resolvedImport, path38.extname(resolvedImport));
49233
+ const importDir = path39.dirname(resolvedImport);
49234
+ const importBasename = path39.basename(resolvedImport, path39.extname(resolvedImport));
48720
49235
  for (const sourceFile of absoluteSourceFiles) {
48721
- const sourceDir = path38.dirname(sourceFile);
48722
- const sourceBasename = path38.basename(sourceFile, path38.extname(sourceFile));
48723
- const isRelatedDir = importDir === sourceDir || importDir === path38.join(sourceDir, "__tests__") || importDir === path38.join(sourceDir, "tests") || importDir === path38.join(sourceDir, "test") || importDir === path38.join(sourceDir, "spec");
49236
+ const sourceDir = path39.dirname(sourceFile);
49237
+ const sourceBasename = path39.basename(sourceFile, path39.extname(sourceFile));
49238
+ const isRelatedDir = importDir === sourceDir || importDir === path39.join(sourceDir, "__tests__") || importDir === path39.join(sourceDir, "tests") || importDir === path39.join(sourceDir, "test") || importDir === path39.join(sourceDir, "spec");
48724
49239
  if (resolvedImport === sourceFile || importBasename === sourceBasename && isRelatedDir) {
48725
49240
  dedupePush(testFiles, testFile);
48726
49241
  break;
@@ -48830,8 +49345,8 @@ function buildTestCommand2(framework, scope, files, coverage, baseDir) {
48830
49345
  return ["mvn", "test"];
48831
49346
  case "gradle": {
48832
49347
  const isWindows = process.platform === "win32";
48833
- const hasGradlewBat = fs22.existsSync(path38.join(baseDir, "gradlew.bat"));
48834
- const hasGradlew = fs22.existsSync(path38.join(baseDir, "gradlew"));
49348
+ const hasGradlewBat = fs22.existsSync(path39.join(baseDir, "gradlew.bat"));
49349
+ const hasGradlew = fs22.existsSync(path39.join(baseDir, "gradlew"));
48835
49350
  if (hasGradlewBat && isWindows)
48836
49351
  return ["gradlew.bat", "test"];
48837
49352
  if (hasGradlew)
@@ -48848,7 +49363,7 @@ function buildTestCommand2(framework, scope, files, coverage, baseDir) {
48848
49363
  "cmake-build-release",
48849
49364
  "out"
48850
49365
  ];
48851
- const actualBuildDir = buildDirCandidates.find((d) => fs22.existsSync(path38.join(baseDir, d, "CMakeCache.txt"))) ?? "build";
49366
+ const actualBuildDir = buildDirCandidates.find((d) => fs22.existsSync(path39.join(baseDir, d, "CMakeCache.txt"))) ?? "build";
48852
49367
  return ["ctest", "--test-dir", actualBuildDir];
48853
49368
  }
48854
49369
  case "swift-test":
@@ -49280,11 +49795,11 @@ async function runTests(framework, scope, files, coverage, timeout_ms, cwd) {
49280
49795
  };
49281
49796
  }
49282
49797
  const startTime = Date.now();
49283
- const vitestJsonOutputPath = framework === "vitest" ? path38.join(cwd, ".swarm", "cache", "test-runner-vitest.json") : undefined;
49798
+ const vitestJsonOutputPath = framework === "vitest" ? path39.join(cwd, ".swarm", "cache", "test-runner-vitest.json") : undefined;
49284
49799
  try {
49285
49800
  if (vitestJsonOutputPath) {
49286
49801
  try {
49287
- fs22.mkdirSync(path38.dirname(vitestJsonOutputPath), { recursive: true });
49802
+ fs22.mkdirSync(path39.dirname(vitestJsonOutputPath), { recursive: true });
49288
49803
  if (fs22.existsSync(vitestJsonOutputPath)) {
49289
49804
  fs22.unlinkSync(vitestJsonOutputPath);
49290
49805
  }
@@ -49400,10 +49915,10 @@ async function runTests(framework, scope, files, coverage, timeout_ms, cwd) {
49400
49915
  }
49401
49916
  function normalizeHistoryTestFile(testFile, workingDir) {
49402
49917
  const normalized = testFile.replace(/\\/g, "/");
49403
- if (!path38.isAbsolute(testFile))
49918
+ if (!path39.isAbsolute(testFile))
49404
49919
  return normalized;
49405
- const relative9 = path38.relative(workingDir, testFile);
49406
- if (relative9.startsWith("..") || path38.isAbsolute(relative9)) {
49920
+ const relative9 = path39.relative(workingDir, testFile);
49921
+ if (relative9.startsWith("..") || path39.isAbsolute(relative9)) {
49407
49922
  return normalized;
49408
49923
  }
49409
49924
  return relative9.replace(/\\/g, "/");
@@ -49741,7 +50256,7 @@ var init_test_runner = __esm(() => {
49741
50256
  const sourceFiles = args.files.filter((file3) => {
49742
50257
  if (directTestFiles.includes(file3))
49743
50258
  return false;
49744
- const ext = path38.extname(file3).toLowerCase();
50259
+ const ext = path39.extname(file3).toLowerCase();
49745
50260
  return SOURCE_EXTENSIONS.has(ext);
49746
50261
  });
49747
50262
  const invalidFiles = args.files.filter((file3) => !directTestFiles.includes(file3) && !sourceFiles.includes(file3));
@@ -49787,7 +50302,7 @@ var init_test_runner = __esm(() => {
49787
50302
  if (isConventionTestFilePath(f)) {
49788
50303
  return false;
49789
50304
  }
49790
- const ext = path38.extname(f).toLowerCase();
50305
+ const ext = path39.extname(f).toLowerCase();
49791
50306
  return SOURCE_EXTENSIONS.has(ext);
49792
50307
  });
49793
50308
  if (sourceFiles.length === 0) {
@@ -49837,7 +50352,7 @@ var init_test_runner = __esm(() => {
49837
50352
  if (isConventionTestFilePath(f)) {
49838
50353
  return false;
49839
50354
  }
49840
- const ext = path38.extname(f).toLowerCase();
50355
+ const ext = path39.extname(f).toLowerCase();
49841
50356
  return SOURCE_EXTENSIONS.has(ext);
49842
50357
  });
49843
50358
  if (sourceFiles.length === 0) {
@@ -49889,8 +50404,8 @@ var init_test_runner = __esm(() => {
49889
50404
  }
49890
50405
  if (impactResult.impactedTests.length > 0) {
49891
50406
  testFiles = impactResult.impactedTests.map((absPath) => {
49892
- const relativePath = path38.relative(workingDir, absPath);
49893
- return path38.isAbsolute(relativePath) ? absPath : relativePath;
50407
+ const relativePath = path39.relative(workingDir, absPath);
50408
+ return path39.isAbsolute(relativePath) ? absPath : relativePath;
49894
50409
  });
49895
50410
  } else {
49896
50411
  graphFallbackReason = "no impacted tests found via impact analysis, falling back to graph";
@@ -49966,7 +50481,7 @@ var init_test_runner = __esm(() => {
49966
50481
 
49967
50482
  // src/services/preflight-service.ts
49968
50483
  import * as fs23 from "fs";
49969
- import * as path39 from "path";
50484
+ import * as path40 from "path";
49970
50485
  function validateDirectoryPath(dir) {
49971
50486
  if (!dir || typeof dir !== "string") {
49972
50487
  throw new Error("Directory path is required");
@@ -49974,8 +50489,8 @@ function validateDirectoryPath(dir) {
49974
50489
  if (dir.includes("..")) {
49975
50490
  throw new Error("Directory path must not contain path traversal sequences");
49976
50491
  }
49977
- const normalized = path39.normalize(dir);
49978
- const absolutePath = path39.isAbsolute(normalized) ? normalized : path39.resolve(normalized);
50492
+ const normalized = path40.normalize(dir);
50493
+ const absolutePath = path40.isAbsolute(normalized) ? normalized : path40.resolve(normalized);
49979
50494
  return absolutePath;
49980
50495
  }
49981
50496
  function validateTimeout(timeoutMs, defaultValue) {
@@ -49998,7 +50513,7 @@ function validateTimeout(timeoutMs, defaultValue) {
49998
50513
  }
49999
50514
  function getPackageVersion(dir) {
50000
50515
  try {
50001
- const packagePath = path39.join(dir, "package.json");
50516
+ const packagePath = path40.join(dir, "package.json");
50002
50517
  if (fs23.existsSync(packagePath)) {
50003
50518
  const content = fs23.readFileSync(packagePath, "utf-8");
50004
50519
  const pkg = JSON.parse(content);
@@ -50009,7 +50524,7 @@ function getPackageVersion(dir) {
50009
50524
  }
50010
50525
  function getChangelogVersion(dir) {
50011
50526
  try {
50012
- const changelogPath = path39.join(dir, "CHANGELOG.md");
50527
+ const changelogPath = path40.join(dir, "CHANGELOG.md");
50013
50528
  if (fs23.existsSync(changelogPath)) {
50014
50529
  const content = fs23.readFileSync(changelogPath, "utf-8");
50015
50530
  const match = content.match(/^##\s*\[?(\d+\.\d+\.\d+)\]?/m);
@@ -50023,7 +50538,7 @@ function getChangelogVersion(dir) {
50023
50538
  function getVersionFileVersion(dir) {
50024
50539
  const possibleFiles = ["VERSION.txt", "version.txt", "VERSION", "version"];
50025
50540
  for (const file3 of possibleFiles) {
50026
- const filePath = path39.join(dir, file3);
50541
+ const filePath = path40.join(dir, file3);
50027
50542
  if (fs23.existsSync(filePath)) {
50028
50543
  try {
50029
50544
  const content = fs23.readFileSync(filePath, "utf-8").trim();
@@ -50039,9 +50554,9 @@ function getVersionFileVersion(dir) {
50039
50554
  async function runVersionCheck(dir, _timeoutMs) {
50040
50555
  const startTime = Date.now();
50041
50556
  try {
50042
- const packageVersion = _internals26.getPackageVersion(dir);
50043
- const changelogVersion = _internals26.getChangelogVersion(dir);
50044
- const versionFileVersion = _internals26.getVersionFileVersion(dir);
50557
+ const packageVersion = _internals27.getPackageVersion(dir);
50558
+ const changelogVersion = _internals27.getChangelogVersion(dir);
50559
+ const versionFileVersion = _internals27.getVersionFileVersion(dir);
50045
50560
  const versions3 = [];
50046
50561
  if (packageVersion)
50047
50562
  versions3.push(`package.json: ${packageVersion}`);
@@ -50313,7 +50828,22 @@ async function runEvidenceCheck(dir) {
50313
50828
  };
50314
50829
  }
50315
50830
  const evidenceTaskIds = new Set(await listEvidenceTaskIds(dir));
50316
- const missingEvidence = completedTaskIds.filter((id) => !evidenceTaskIds.has(id));
50831
+ const missingEvidence = [];
50832
+ for (const id of completedTaskIds) {
50833
+ const gateStatus = await getDurableGateEvidenceStatusForTask(dir, id);
50834
+ if (gateStatus.isComplete) {
50835
+ continue;
50836
+ }
50837
+ if (gateStatus.evidenceExists && gateStatus.missingGates.length > 0) {
50838
+ missingEvidence.push(id);
50839
+ continue;
50840
+ }
50841
+ if (evidenceTaskIds.has(id)) {
50842
+ continue;
50843
+ }
50844
+ missingEvidence.push(id);
50845
+ }
50846
+ const completedWithEvidence = completedTaskIds.length - missingEvidence.length;
50317
50847
  if (missingEvidence.length > 0) {
50318
50848
  return {
50319
50849
  type: "evidence",
@@ -50321,7 +50851,7 @@ async function runEvidenceCheck(dir) {
50321
50851
  message: `${missingEvidence.length} completed task(s) missing evidence`,
50322
50852
  details: {
50323
50853
  totalCompleted: completedTaskIds.length,
50324
- totalWithEvidence: evidenceTaskIds.size,
50854
+ totalWithEvidence: completedWithEvidence,
50325
50855
  missingTasks: missingEvidence.slice(0, 10),
50326
50856
  missingCount: missingEvidence.length
50327
50857
  },
@@ -50334,7 +50864,7 @@ async function runEvidenceCheck(dir) {
50334
50864
  message: `All ${completedTaskIds.length} completed tasks have evidence`,
50335
50865
  details: {
50336
50866
  totalCompleted: completedTaskIds.length,
50337
- totalWithEvidence: evidenceTaskIds.size
50867
+ totalWithEvidence: completedWithEvidence
50338
50868
  },
50339
50869
  durationMs: Date.now() - startTime
50340
50870
  };
@@ -50350,7 +50880,7 @@ async function runEvidenceCheck(dir) {
50350
50880
  async function runRequirementCoverageCheck(dir, currentPhase) {
50351
50881
  const startTime = Date.now();
50352
50882
  try {
50353
- const specPath = path39.join(dir, ".swarm", "spec.md");
50883
+ const specPath = path40.join(dir, ".swarm", "spec.md");
50354
50884
  if (!fs23.existsSync(specPath)) {
50355
50885
  return {
50356
50886
  type: "req_coverage",
@@ -50391,7 +50921,7 @@ async function runPreflight(dir, phase, config3) {
50391
50921
  const reportId = `preflight-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
50392
50922
  let validatedDir;
50393
50923
  try {
50394
- validatedDir = _internals26.validateDirectoryPath(dir);
50924
+ validatedDir = _internals27.validateDirectoryPath(dir);
50395
50925
  } catch (error93) {
50396
50926
  return {
50397
50927
  id: reportId,
@@ -50411,7 +50941,7 @@ async function runPreflight(dir, phase, config3) {
50411
50941
  }
50412
50942
  let validatedTimeout;
50413
50943
  try {
50414
- validatedTimeout = _internals26.validateTimeout(config3?.checkTimeoutMs, DEFAULT_CONFIG.checkTimeoutMs);
50944
+ validatedTimeout = _internals27.validateTimeout(config3?.checkTimeoutMs, DEFAULT_CONFIG.checkTimeoutMs);
50415
50945
  } catch (error93) {
50416
50946
  return {
50417
50947
  id: reportId,
@@ -50452,12 +50982,12 @@ async function runPreflight(dir, phase, config3) {
50452
50982
  });
50453
50983
  const checks5 = [];
50454
50984
  log("[Preflight] Running lint check...");
50455
- const lintResult = await _internals26.runLintCheck(validatedDir, cfg.linter, cfg.checkTimeoutMs);
50985
+ const lintResult = await _internals27.runLintCheck(validatedDir, cfg.linter, cfg.checkTimeoutMs);
50456
50986
  checks5.push(lintResult);
50457
50987
  log(`[Preflight] Lint check: ${lintResult.status} ${lintResult.message}`);
50458
50988
  if (!cfg.skipTests) {
50459
50989
  log("[Preflight] Running tests check...");
50460
- const testsResult = await _internals26.runTestsCheck(validatedDir, cfg.testScope, cfg.checkTimeoutMs);
50990
+ const testsResult = await _internals27.runTestsCheck(validatedDir, cfg.testScope, cfg.checkTimeoutMs);
50461
50991
  checks5.push(testsResult);
50462
50992
  log(`[Preflight] Tests check: ${testsResult.status} ${testsResult.message}`);
50463
50993
  } else {
@@ -50469,7 +50999,7 @@ async function runPreflight(dir, phase, config3) {
50469
50999
  }
50470
51000
  if (!cfg.skipSecrets) {
50471
51001
  log("[Preflight] Running secrets check...");
50472
- const secretsResult = await _internals26.runSecretsCheck(validatedDir, cfg.checkTimeoutMs);
51002
+ const secretsResult = await _internals27.runSecretsCheck(validatedDir, cfg.checkTimeoutMs);
50473
51003
  checks5.push(secretsResult);
50474
51004
  log(`[Preflight] Secrets check: ${secretsResult.status} ${secretsResult.message}`);
50475
51005
  } else {
@@ -50481,7 +51011,7 @@ async function runPreflight(dir, phase, config3) {
50481
51011
  }
50482
51012
  if (!cfg.skipEvidence) {
50483
51013
  log("[Preflight] Running evidence check...");
50484
- const evidenceResult = await _internals26.runEvidenceCheck(validatedDir);
51014
+ const evidenceResult = await _internals27.runEvidenceCheck(validatedDir);
50485
51015
  checks5.push(evidenceResult);
50486
51016
  log(`[Preflight] Evidence check: ${evidenceResult.status} ${evidenceResult.message}`);
50487
51017
  } else {
@@ -50492,12 +51022,12 @@ async function runPreflight(dir, phase, config3) {
50492
51022
  });
50493
51023
  }
50494
51024
  log("[Preflight] Running requirement coverage check...");
50495
- const reqCoverageResult = await _internals26.runRequirementCoverageCheck(validatedDir, phase);
51025
+ const reqCoverageResult = await _internals27.runRequirementCoverageCheck(validatedDir, phase);
50496
51026
  checks5.push(reqCoverageResult);
50497
51027
  log(`[Preflight] Requirement coverage check: ${reqCoverageResult.status} ${reqCoverageResult.message}`);
50498
51028
  if (!cfg.skipVersion) {
50499
51029
  log("[Preflight] Running version check...");
50500
- const versionResult = await _internals26.runVersionCheck(validatedDir, cfg.checkTimeoutMs);
51030
+ const versionResult = await _internals27.runVersionCheck(validatedDir, cfg.checkTimeoutMs);
50501
51031
  checks5.push(versionResult);
50502
51032
  log(`[Preflight] Version check: ${versionResult.status} ${versionResult.message}`);
50503
51033
  } else {
@@ -50560,11 +51090,12 @@ function formatPreflightMarkdown(report) {
50560
51090
  async function handlePreflightCommand(directory, _args) {
50561
51091
  const plan = await loadPlan(directory);
50562
51092
  const phase = plan?.current_phase ?? 1;
50563
- const report = await _internals26.runPreflight(directory, phase);
50564
- return _internals26.formatPreflightMarkdown(report);
51093
+ const report = await _internals27.runPreflight(directory, phase);
51094
+ return _internals27.formatPreflightMarkdown(report);
50565
51095
  }
50566
- var MIN_CHECK_TIMEOUT_MS = 5000, MAX_CHECK_TIMEOUT_MS = 300000, DEFAULT_CONFIG, _internals26;
51096
+ var MIN_CHECK_TIMEOUT_MS = 5000, MAX_CHECK_TIMEOUT_MS = 300000, DEFAULT_CONFIG, _internals27;
50567
51097
  var init_preflight_service = __esm(() => {
51098
+ init_gate_bridge();
50568
51099
  init_manager2();
50569
51100
  init_manager();
50570
51101
  init_lint();
@@ -50580,7 +51111,7 @@ var init_preflight_service = __esm(() => {
50580
51111
  testScope: "convention",
50581
51112
  linter: "biome"
50582
51113
  };
50583
- _internals26 = {
51114
+ _internals27 = {
50584
51115
  runPreflight,
50585
51116
  formatPreflightMarkdown,
50586
51117
  handlePreflightCommand,
@@ -51467,7 +51998,7 @@ var init_manager3 = __esm(() => {
51467
51998
 
51468
51999
  // src/commands/reset.ts
51469
52000
  import * as fs24 from "fs";
51470
- import * as path40 from "path";
52001
+ import * as path41 from "path";
51471
52002
  async function handleResetCommand(directory, args) {
51472
52003
  const hasConfirm = args.includes("--confirm");
51473
52004
  if (!hasConfirm) {
@@ -51507,7 +52038,7 @@ async function handleResetCommand(directory, args) {
51507
52038
  }
51508
52039
  for (const filename of ["SWARM_PLAN.md", "SWARM_PLAN.json"]) {
51509
52040
  try {
51510
- const rootPath = path40.join(directory, filename);
52041
+ const rootPath = path41.join(directory, filename);
51511
52042
  if (fs24.existsSync(rootPath)) {
51512
52043
  fs24.unlinkSync(rootPath);
51513
52044
  results.push(`- \u2705 Deleted ${filename} (root)`);
@@ -51547,7 +52078,7 @@ var init_reset = __esm(() => {
51547
52078
 
51548
52079
  // src/commands/reset-session.ts
51549
52080
  import * as fs25 from "fs";
51550
- import * as path41 from "path";
52081
+ import * as path42 from "path";
51551
52082
  async function handleResetSessionCommand(directory, _args) {
51552
52083
  const results = [];
51553
52084
  try {
@@ -51562,13 +52093,13 @@ async function handleResetSessionCommand(directory, _args) {
51562
52093
  results.push("\u274C Failed to delete state.json");
51563
52094
  }
51564
52095
  try {
51565
- const sessionDir = path41.dirname(validateSwarmPath(directory, "session/state.json"));
52096
+ const sessionDir = path42.dirname(validateSwarmPath(directory, "session/state.json"));
51566
52097
  if (fs25.existsSync(sessionDir)) {
51567
52098
  const files = fs25.readdirSync(sessionDir);
51568
52099
  const otherFiles = files.filter((f) => f !== "state.json");
51569
52100
  let deletedCount = 0;
51570
52101
  for (const file3 of otherFiles) {
51571
- const filePath = path41.join(sessionDir, file3);
52102
+ const filePath = path42.join(sessionDir, file3);
51572
52103
  if (fs25.lstatSync(filePath).isFile()) {
51573
52104
  fs25.unlinkSync(filePath);
51574
52105
  deletedCount++;
@@ -51600,7 +52131,7 @@ var init_reset_session = __esm(() => {
51600
52131
  });
51601
52132
 
51602
52133
  // src/summaries/manager.ts
51603
- import * as path42 from "path";
52134
+ import * as path43 from "path";
51604
52135
  function sanitizeSummaryId(id) {
51605
52136
  if (!id || id.length === 0) {
51606
52137
  throw new Error("Invalid summary ID: empty string");
@@ -51623,7 +52154,7 @@ function sanitizeSummaryId(id) {
51623
52154
  }
51624
52155
  async function loadFullOutput(directory, id) {
51625
52156
  const sanitizedId = sanitizeSummaryId(id);
51626
- const relativePath = path42.join("summaries", `${sanitizedId}.json`);
52157
+ const relativePath = path43.join("summaries", `${sanitizedId}.json`);
51627
52158
  validateSwarmPath(directory, relativePath);
51628
52159
  const content = await readSwarmFileAsync(directory, relativePath);
51629
52160
  if (content === null) {
@@ -51686,7 +52217,7 @@ var init_retrieve = __esm(() => {
51686
52217
 
51687
52218
  // src/commands/rollback.ts
51688
52219
  import * as fs26 from "fs";
51689
- import * as path43 from "path";
52220
+ import * as path44 from "path";
51690
52221
  async function handleRollbackCommand(directory, args) {
51691
52222
  const phaseArg = args[0];
51692
52223
  if (!phaseArg) {
@@ -51751,8 +52282,8 @@ async function handleRollbackCommand(directory, args) {
51751
52282
  if (EXCLUDE_FILES.has(file3) || file3.startsWith("plan-ledger.archived-")) {
51752
52283
  continue;
51753
52284
  }
51754
- const src = path43.join(checkpointDir, file3);
51755
- const dest = path43.join(swarmDir, file3);
52285
+ const src = path44.join(checkpointDir, file3);
52286
+ const dest = path44.join(swarmDir, file3);
51756
52287
  try {
51757
52288
  fs26.cpSync(src, dest, { recursive: true, force: true });
51758
52289
  successes.push(file3);
@@ -51771,12 +52302,12 @@ async function handleRollbackCommand(directory, args) {
51771
52302
  ].join(`
51772
52303
  `);
51773
52304
  }
51774
- const existingLedgerPath = path43.join(swarmDir, "plan-ledger.jsonl");
52305
+ const existingLedgerPath = path44.join(swarmDir, "plan-ledger.jsonl");
51775
52306
  if (fs26.existsSync(existingLedgerPath)) {
51776
52307
  fs26.unlinkSync(existingLedgerPath);
51777
52308
  }
51778
52309
  try {
51779
- const planJsonPath = path43.join(swarmDir, "plan.json");
52310
+ const planJsonPath = path44.join(swarmDir, "plan.json");
51780
52311
  if (fs26.existsSync(planJsonPath)) {
51781
52312
  const planRaw = fs26.readFileSync(planJsonPath, "utf-8");
51782
52313
  const plan = PlanSchema.parse(JSON.parse(planRaw));
@@ -51837,7 +52368,7 @@ async function handleSimulateCommand(directory, args) {
51837
52368
  }
51838
52369
  let darkMatterPairs;
51839
52370
  try {
51840
- darkMatterPairs = await _internals10.detectDarkMatter(directory, options);
52371
+ darkMatterPairs = await _internals11.detectDarkMatter(directory, options);
51841
52372
  } catch (err) {
51842
52373
  const errMsg = err instanceof Error ? err.message : String(err);
51843
52374
  return `## Simulate Report
@@ -51867,9 +52398,9 @@ Ensure this is a git repository with commit history.`;
51867
52398
  `);
51868
52399
  try {
51869
52400
  const fs27 = await import("fs/promises");
51870
- const path44 = await import("path");
51871
- const reportPath = path44.join(directory, ".swarm", "simulate-report.md");
51872
- await fs27.mkdir(path44.dirname(reportPath), { recursive: true });
52401
+ const path45 = await import("path");
52402
+ const reportPath = path45.join(directory, ".swarm", "simulate-report.md");
52403
+ await fs27.mkdir(path45.dirname(reportPath), { recursive: true });
51873
52404
  await fs27.writeFile(reportPath, report, "utf-8");
51874
52405
  } catch (err) {
51875
52406
  const writeErr = err instanceof Error ? err.message : String(err);
@@ -51893,12 +52424,12 @@ async function handleSpecifyCommand(_directory, args) {
51893
52424
 
51894
52425
  // src/turbo/lean/state.ts
51895
52426
  import * as fs27 from "fs";
51896
- import * as path44 from "path";
52427
+ import * as path45 from "path";
51897
52428
  function nowISO2() {
51898
52429
  return new Date().toISOString();
51899
52430
  }
51900
52431
  function ensureSwarmDir2(directory) {
51901
- const swarmDir = path44.resolve(directory, ".swarm");
52432
+ const swarmDir = path45.resolve(directory, ".swarm");
51902
52433
  if (!fs27.existsSync(swarmDir)) {
51903
52434
  fs27.mkdirSync(swarmDir, { recursive: true });
51904
52435
  }
@@ -51942,7 +52473,7 @@ function markStateUnreadable2(directory, reason) {
51942
52473
  }
51943
52474
  function readPersisted2(directory) {
51944
52475
  try {
51945
- const filePath = path44.join(directory, ".swarm", STATE_FILE2);
52476
+ const filePath = path45.join(directory, ".swarm", STATE_FILE2);
51946
52477
  if (!fs27.existsSync(filePath)) {
51947
52478
  const seed = emptyPersisted2();
51948
52479
  try {
@@ -51978,7 +52509,7 @@ function writePersisted2(directory, persisted) {
51978
52509
  let payload;
51979
52510
  try {
51980
52511
  ensureSwarmDir2(directory);
51981
- filePath = path44.join(directory, ".swarm", STATE_FILE2);
52512
+ filePath = path45.join(directory, ".swarm", STATE_FILE2);
51982
52513
  tmpPath = `${filePath}.tmp.${Date.now()}`;
51983
52514
  persisted.updatedAt = nowISO2();
51984
52515
  payload = `${JSON.stringify(persisted, null, 2)}
@@ -52105,10 +52636,10 @@ var init_context_budget_service = __esm(() => {
52105
52636
 
52106
52637
  // src/services/status-service.ts
52107
52638
  import * as fsSync2 from "fs";
52108
- import * as path45 from "path";
52639
+ import * as path46 from "path";
52109
52640
  function readSpecStalenessSnapshot(directory) {
52110
52641
  try {
52111
- const p = path45.join(directory, ".swarm", "spec-staleness.json");
52642
+ const p = path46.join(directory, ".swarm", "spec-staleness.json");
52112
52643
  if (!fsSync2.existsSync(p))
52113
52644
  return { stale: false };
52114
52645
  const raw = fsSync2.readFileSync(p, "utf-8");
@@ -52202,7 +52733,7 @@ async function getStatusData(directory, agents) {
52202
52733
  }
52203
52734
  function enrichWithLeanTurbo(status, directory) {
52204
52735
  const turboMode = hasActiveTurboMode();
52205
- const leanActive = _internals27.hasActiveLeanTurbo();
52736
+ const leanActive = _internals28.hasActiveLeanTurbo();
52206
52737
  let turboStrategy = "off";
52207
52738
  if (leanActive) {
52208
52739
  turboStrategy = "lean";
@@ -52221,7 +52752,7 @@ function enrichWithLeanTurbo(status, directory) {
52221
52752
  }
52222
52753
  }
52223
52754
  if (leanSessionID) {
52224
- const runState = _internals27.loadLeanTurboRunState(directory, leanSessionID);
52755
+ const runState = _internals28.loadLeanTurboRunState(directory, leanSessionID);
52225
52756
  if (runState) {
52226
52757
  status.leanTurboPhase = runState.phase;
52227
52758
  status.leanMaxParallelCoders = runState.maxParallelCoders;
@@ -52253,7 +52784,7 @@ function enrichWithLeanTurbo(status, directory) {
52253
52784
  }
52254
52785
  }
52255
52786
  }
52256
- status.fullAutoActive = _internals27.hasActiveFullAuto();
52787
+ status.fullAutoActive = _internals28.hasActiveFullAuto();
52257
52788
  return status;
52258
52789
  }
52259
52790
  function formatStatusMarkdown(status) {
@@ -52335,7 +52866,7 @@ async function handleStatusCommand(directory, agents) {
52335
52866
  }
52336
52867
  return formatStatusMarkdown(statusData);
52337
52868
  }
52338
- var _internals27;
52869
+ var _internals28;
52339
52870
  var init_status_service = __esm(() => {
52340
52871
  init_extractors();
52341
52872
  init_utils2();
@@ -52344,7 +52875,7 @@ var init_status_service = __esm(() => {
52344
52875
  init_state3();
52345
52876
  init_compaction_service();
52346
52877
  init_context_budget_service();
52347
- _internals27 = {
52878
+ _internals28 = {
52348
52879
  loadLeanTurboRunState,
52349
52880
  hasActiveLeanTurbo,
52350
52881
  hasActiveFullAuto
@@ -52435,7 +52966,7 @@ async function handleTurboCommand(directory, args, sessionID) {
52435
52966
  if (arg0 === "on") {
52436
52967
  let strategy = "standard";
52437
52968
  try {
52438
- const { config: config3 } = _internals28.loadPluginConfigWithMeta(directory);
52969
+ const { config: config3 } = _internals29.loadPluginConfigWithMeta(directory);
52439
52970
  if (config3.turbo?.strategy === "lean") {
52440
52971
  strategy = "lean";
52441
52972
  }
@@ -52490,7 +53021,7 @@ function enableLeanTurbo(session, directory, sessionID) {
52490
53021
  let maxParallelCoders = 4;
52491
53022
  let conflictPolicy = "serialize";
52492
53023
  try {
52493
- const { config: config3 } = _internals28.loadPluginConfigWithMeta(directory);
53024
+ const { config: config3 } = _internals29.loadPluginConfigWithMeta(directory);
52494
53025
  const leanConfig = config3.turbo?.lean;
52495
53026
  if (leanConfig) {
52496
53027
  maxParallelCoders = leanConfig.max_parallel_coders ?? 4;
@@ -52560,13 +53091,13 @@ function buildStatusMessage(session, directory, sessionID) {
52560
53091
  ].join(`
52561
53092
  `);
52562
53093
  }
52563
- var _internals28;
53094
+ var _internals29;
52564
53095
  var init_turbo = __esm(() => {
52565
53096
  init_config();
52566
53097
  init_state();
52567
53098
  init_state3();
52568
53099
  init_logger();
52569
- _internals28 = {
53100
+ _internals29 = {
52570
53101
  loadPluginConfigWithMeta
52571
53102
  };
52572
53103
  });
@@ -52634,7 +53165,7 @@ var init_write_retro2 = __esm(() => {
52634
53165
 
52635
53166
  // src/commands/command-dispatch.ts
52636
53167
  import fs28 from "fs";
52637
- import path46 from "path";
53168
+ import path47 from "path";
52638
53169
  function normalizeSwarmCommandInput(command, argumentText) {
52639
53170
  if (command !== "swarm" && !command.startsWith("swarm-")) {
52640
53171
  return { isSwarmCommand: false, tokens: [] };
@@ -52659,7 +53190,7 @@ function formatCommandNotFound(tokens) {
52659
53190
  const attemptedCommand = tokens[0] || "";
52660
53191
  const MAX_DISPLAY = 100;
52661
53192
  const displayCommand = attemptedCommand.length > MAX_DISPLAY ? `${attemptedCommand.slice(0, MAX_DISPLAY)}...` : attemptedCommand;
52662
- const similar = _internals29.findSimilarCommands(attemptedCommand);
53193
+ const similar = _internals30.findSimilarCommands(attemptedCommand);
52663
53194
  const header = `Command \`/swarm ${displayCommand}\` not found.`;
52664
53195
  const suggestions = similar.length > 0 ? `Did you mean:
52665
53196
  ${similar.map((cmd) => ` - /swarm ${cmd}`).join(`
@@ -52670,9 +53201,9 @@ ${similar.map((cmd) => ` - /swarm ${cmd}`).join(`
52670
53201
  `);
52671
53202
  }
52672
53203
  function maybeMarkFirstRun(directory) {
52673
- const sentinelPath = path46.join(directory, ".swarm", ".first-run-complete");
53204
+ const sentinelPath = path47.join(directory, ".swarm", ".first-run-complete");
52674
53205
  try {
52675
- const swarmDir = path46.join(directory, ".swarm");
53206
+ const swarmDir = path47.join(directory, ".swarm");
52676
53207
  fs28.mkdirSync(swarmDir, { recursive: true });
52677
53208
  fs28.writeFileSync(sentinelPath, `first-run-complete: ${new Date().toISOString()}
52678
53209
  `, { flag: "wx" });
@@ -53108,7 +53639,7 @@ async function buildSwarmCommandPrompt(args) {
53108
53639
  activeAgentName,
53109
53640
  registeredAgents
53110
53641
  } = args;
53111
- const resolved = _internals29.resolveCommand(tokens);
53642
+ const resolved = _internals30.resolveCommand(tokens);
53112
53643
  if (!resolved) {
53113
53644
  if (tokens.length === 0) {
53114
53645
  return buildHelpText();
@@ -53259,7 +53790,7 @@ function findSimilarCommands(query) {
53259
53790
  }
53260
53791
  const scored = VALID_COMMANDS.map((cmd) => {
53261
53792
  const cmdLower = cmd.toLowerCase();
53262
- const fullScore = _internals29.levenshteinDistance(q, cmdLower);
53793
+ const fullScore = _internals30.levenshteinDistance(q, cmdLower);
53263
53794
  let tokenScore = Infinity;
53264
53795
  if (cmd.includes(" ") || cmd.includes("-")) {
53265
53796
  const qTokens = q.split(/[\s-]+/);
@@ -53272,7 +53803,7 @@ function findSimilarCommands(query) {
53272
53803
  for (const ct of cmdTokens) {
53273
53804
  if (ct.length === 0)
53274
53805
  continue;
53275
- const dist = _internals29.levenshteinDistance(qt, ct);
53806
+ const dist = _internals30.levenshteinDistance(qt, ct);
53276
53807
  if (dist < minDist)
53277
53808
  minDist = dist;
53278
53809
  }
@@ -53282,7 +53813,7 @@ function findSimilarCommands(query) {
53282
53813
  }
53283
53814
  const dashStrippedQ = q.replace(/-/g, "");
53284
53815
  const dashStrippedCmd = cmdLower.replace(/-/g, "");
53285
- const dashScore = _internals29.levenshteinDistance(dashStrippedQ, dashStrippedCmd);
53816
+ const dashScore = _internals30.levenshteinDistance(dashStrippedQ, dashStrippedCmd);
53286
53817
  const score = Math.min(fullScore, tokenScore, dashScore);
53287
53818
  return { cmd, score };
53288
53819
  });
@@ -53314,11 +53845,11 @@ async function handleHelpCommand(ctx) {
53314
53845
  return buildHelpText2();
53315
53846
  }
53316
53847
  const tokens = targetCommand.split(/\s+/);
53317
- const resolved = _internals29.resolveCommand(tokens);
53848
+ const resolved = _internals30.resolveCommand(tokens);
53318
53849
  if (resolved) {
53319
- return _internals29.buildDetailedHelp(resolved.key, resolved.entry);
53850
+ return _internals30.buildDetailedHelp(resolved.key, resolved.entry);
53320
53851
  }
53321
- const similar = _internals29.findSimilarCommands(targetCommand);
53852
+ const similar = _internals30.findSimilarCommands(targetCommand);
53322
53853
  const { buildHelpText: fullHelp } = await Promise.resolve().then(() => (init_commands(), exports_commands));
53323
53854
  if (similar.length > 0) {
53324
53855
  return `Command '/swarm ${targetCommand}' not found.
@@ -53354,24 +53885,24 @@ function validateAliases() {
53354
53885
  }
53355
53886
  aliasTargets.get(target).push(name);
53356
53887
  const visited = new Set;
53357
- const path47 = [];
53888
+ const path48 = [];
53358
53889
  let current = target;
53359
53890
  while (current) {
53360
53891
  const currentEntry = COMMAND_REGISTRY[current];
53361
53892
  if (!currentEntry)
53362
53893
  break;
53363
53894
  if (visited.has(current)) {
53364
- const cycleStart = path47.indexOf(current);
53895
+ const cycleStart = path48.indexOf(current);
53365
53896
  const fullChain = [
53366
53897
  name,
53367
- ...path47.slice(0, cycleStart > 0 ? cycleStart : path47.length),
53898
+ ...path48.slice(0, cycleStart > 0 ? cycleStart : path48.length),
53368
53899
  current
53369
53900
  ].join(" \u2192 ");
53370
53901
  errors5.push(`Circular alias detected: ${fullChain}`);
53371
53902
  break;
53372
53903
  }
53373
53904
  visited.add(current);
53374
- path47.push(current);
53905
+ path48.push(current);
53375
53906
  current = currentEntry.aliasOf || "";
53376
53907
  }
53377
53908
  }
@@ -53412,7 +53943,7 @@ function resolveCommand(tokens) {
53412
53943
  }
53413
53944
  return null;
53414
53945
  }
53415
- var COMMAND_REGISTRY, VALID_COMMANDS, _internals29, validation;
53946
+ var COMMAND_REGISTRY, VALID_COMMANDS, _internals30, validation;
53416
53947
  var init_registry = __esm(() => {
53417
53948
  init_acknowledge_spec_drift();
53418
53949
  init_agents();
@@ -53482,7 +54013,7 @@ var init_registry = __esm(() => {
53482
54013
  clashesWithNativeCcCommand: "/agents"
53483
54014
  },
53484
54015
  help: {
53485
- handler: (ctx) => _internals29.handleHelpCommand(ctx),
54016
+ handler: (ctx) => _internals30.handleHelpCommand(ctx),
53486
54017
  description: "Show help for swarm commands",
53487
54018
  category: "core",
53488
54019
  args: "[command]",
@@ -53854,7 +54385,7 @@ Subcommands:
53854
54385
  }
53855
54386
  };
53856
54387
  VALID_COMMANDS = Object.keys(COMMAND_REGISTRY);
53857
- _internals29 = {
54388
+ _internals30 = {
53858
54389
  handleHelpCommand,
53859
54390
  validateAliases,
53860
54391
  resolveCommand,
@@ -53862,7 +54393,7 @@ Subcommands:
53862
54393
  findSimilarCommands,
53863
54394
  buildDetailedHelp
53864
54395
  };
53865
- validation = _internals29.validateAliases();
54396
+ validation = _internals30.validateAliases();
53866
54397
  if (!validation.valid) {
53867
54398
  throw new Error(`COMMAND_REGISTRY alias validation failed:
53868
54399
  ${validation.errors.join(`
@@ -53882,53 +54413,53 @@ init_cache_paths();
53882
54413
  init_constants();
53883
54414
  import * as fs29 from "fs";
53884
54415
  import * as os7 from "os";
53885
- import * as path47 from "path";
54416
+ import * as path48 from "path";
53886
54417
  var { version: version4 } = package_default;
53887
54418
  var CONFIG_DIR = getPluginConfigDir();
53888
- var OPENCODE_CONFIG_PATH = path47.join(CONFIG_DIR, "opencode.json");
53889
- var PLUGIN_CONFIG_PATH = path47.join(CONFIG_DIR, "opencode-swarm.json");
53890
- var PROMPTS_DIR = path47.join(CONFIG_DIR, "opencode-swarm");
54419
+ var OPENCODE_CONFIG_PATH = path48.join(CONFIG_DIR, "opencode.json");
54420
+ var PLUGIN_CONFIG_PATH = path48.join(CONFIG_DIR, "opencode-swarm.json");
54421
+ var PROMPTS_DIR = path48.join(CONFIG_DIR, "opencode-swarm");
53891
54422
  var OPENCODE_PLUGIN_CACHE_PATHS = getPluginCachePaths();
53892
54423
  var OPENCODE_PLUGIN_LOCK_FILE_PATHS = getPluginLockFilePaths();
53893
54424
  function isSafeCachePath(p) {
53894
- const resolved = path47.resolve(p);
53895
- const home = path47.resolve(os7.homedir());
54425
+ const resolved = path48.resolve(p);
54426
+ const home = path48.resolve(os7.homedir());
53896
54427
  if (resolved === "/" || resolved === home || resolved.length <= home.length) {
53897
54428
  return false;
53898
54429
  }
53899
- const segments = resolved.split(path47.sep).filter((s) => s.length > 0);
54430
+ const segments = resolved.split(path48.sep).filter((s) => s.length > 0);
53900
54431
  if (segments.length < 4) {
53901
54432
  return false;
53902
54433
  }
53903
- const leaf = path47.basename(resolved);
54434
+ const leaf = path48.basename(resolved);
53904
54435
  if (leaf !== "opencode-swarm@latest" && leaf !== "opencode-swarm") {
53905
54436
  return false;
53906
54437
  }
53907
- const parent = path47.basename(path47.dirname(resolved));
54438
+ const parent = path48.basename(path48.dirname(resolved));
53908
54439
  if (parent !== "packages" && parent !== "node_modules") {
53909
54440
  return false;
53910
54441
  }
53911
- const grandparent = path47.basename(path47.dirname(path47.dirname(resolved)));
54442
+ const grandparent = path48.basename(path48.dirname(path48.dirname(resolved)));
53912
54443
  if (grandparent !== "opencode") {
53913
54444
  return false;
53914
54445
  }
53915
54446
  return true;
53916
54447
  }
53917
54448
  function isSafeLockFilePath(p) {
53918
- const resolved = path47.resolve(p);
53919
- const home = path47.resolve(os7.homedir());
54449
+ const resolved = path48.resolve(p);
54450
+ const home = path48.resolve(os7.homedir());
53920
54451
  if (resolved === "/" || resolved === home || resolved.length <= home.length) {
53921
54452
  return false;
53922
54453
  }
53923
- const segments = resolved.split(path47.sep).filter((s) => s.length > 0);
54454
+ const segments = resolved.split(path48.sep).filter((s) => s.length > 0);
53924
54455
  if (segments.length < 4) {
53925
54456
  return false;
53926
54457
  }
53927
- const leaf = path47.basename(resolved);
54458
+ const leaf = path48.basename(resolved);
53928
54459
  if (leaf !== "bun.lock" && leaf !== "bun.lockb" && leaf !== "package-lock.json") {
53929
54460
  return false;
53930
54461
  }
53931
- const parent = path47.basename(path47.dirname(resolved));
54462
+ const parent = path48.basename(path48.dirname(resolved));
53932
54463
  if (parent !== "opencode") {
53933
54464
  return false;
53934
54465
  }
@@ -53954,8 +54485,8 @@ function saveJson(filepath, data) {
53954
54485
  }
53955
54486
  function writeProjectConfigIfMissing(cwd) {
53956
54487
  try {
53957
- const opencodeDir = path47.join(cwd, ".opencode");
53958
- const projectConfigPath = path47.join(opencodeDir, "opencode-swarm.json");
54488
+ const opencodeDir = path48.join(cwd, ".opencode");
54489
+ const projectConfigPath = path48.join(opencodeDir, "opencode-swarm.json");
53959
54490
  if (fs29.existsSync(projectConfigPath)) {
53960
54491
  return;
53961
54492
  }
@@ -53972,7 +54503,7 @@ async function install() {
53972
54503
  `);
53973
54504
  ensureDir(CONFIG_DIR);
53974
54505
  ensureDir(PROMPTS_DIR);
53975
- const LEGACY_CONFIG_PATH = path47.join(CONFIG_DIR, "config.json");
54506
+ const LEGACY_CONFIG_PATH = path48.join(CONFIG_DIR, "config.json");
53976
54507
  let opencodeConfig = loadJson(OPENCODE_CONFIG_PATH);
53977
54508
  if (!opencodeConfig) {
53978
54509
  const legacyConfig = loadJson(LEGACY_CONFIG_PATH);