opencode-swarm 7.32.3 → 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.32.3",
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
@@ -17326,8 +17601,12 @@ var init_schema = __esm(() => {
17326
17601
  });
17327
17602
  MemoryConfigSchema = exports_external.object({
17328
17603
  enabled: exports_external.boolean().default(false),
17329
- provider: exports_external.literal("local-jsonl").default("local-jsonl"),
17604
+ provider: exports_external.enum(["local-jsonl", "sqlite"]).default("local-jsonl"),
17330
17605
  storageDir: exports_external.string().default(".swarm/memory"),
17606
+ sqlite: exports_external.object({
17607
+ path: exports_external.string().default(".swarm/memory/memory.db"),
17608
+ busyTimeoutMs: exports_external.number().int().min(0).max(60000).default(5000)
17609
+ }).default({ path: ".swarm/memory/memory.db", busyTimeoutMs: 5000 }),
17331
17610
  recall: exports_external.object({
17332
17611
  defaultMaxItems: exports_external.number().int().min(1).max(20).default(8),
17333
17612
  defaultTokenBudget: exports_external.number().int().min(100).max(5000).default(1200),
@@ -19759,11 +20038,11 @@ async function tryAcquireLock(directory, filePath, agent, taskId) {
19759
20038
  };
19760
20039
  return { acquired: true, lock };
19761
20040
  }
19762
- 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;
19763
20042
  var init_file_locks = __esm(() => {
19764
20043
  import_proper_lockfile = __toESM(require_proper_lockfile(), 1);
19765
20044
  LOCK_TIMEOUT_MS = 5 * 60 * 1000;
19766
- _internals4 = {
20045
+ _internals5 = {
19767
20046
  tryAcquireLock,
19768
20047
  writeFile: fs3.promises.writeFile
19769
20048
  };
@@ -19863,6 +20142,19 @@ function checkUnsafeChars(taskId) {
19863
20142
  }
19864
20143
  return;
19865
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
+ }
19866
20158
  function sanitizeTaskId(taskId) {
19867
20159
  const unsafeMsg = checkUnsafeChars(taskId);
19868
20160
  if (unsafeMsg) {
@@ -19943,7 +20235,7 @@ function validateProjectRoot(directory) {
19943
20235
  }
19944
20236
  }
19945
20237
  async function saveEvidence(directory, taskId, evidence) {
19946
- _internals5.validateProjectRoot(directory);
20238
+ _internals6.validateProjectRoot(directory);
19947
20239
  const sanitizedTaskId = sanitizeTaskId2(taskId);
19948
20240
  const relativePath = path7.join("evidence", sanitizedTaskId, "evidence.json");
19949
20241
  validateSwarmPath(directory, relativePath);
@@ -20044,7 +20336,7 @@ async function loadEvidence(directory, taskId) {
20044
20336
  return { status: "invalid_schema", errors: ["Invalid JSON"] };
20045
20337
  }
20046
20338
  if (isFlatRetrospective(parsed)) {
20047
- const wrappedBundle = _internals5.wrapFlatRetrospective(parsed, sanitizedTaskId);
20339
+ const wrappedBundle = _internals6.wrapFlatRetrospective(parsed, sanitizedTaskId);
20048
20340
  try {
20049
20341
  const validated = EvidenceBundleSchema.parse(wrappedBundle);
20050
20342
  try {
@@ -20140,14 +20432,14 @@ async function checkRequirementCoverage(phase, directory) {
20140
20432
  }
20141
20433
  }
20142
20434
  async function archiveEvidence(directory, maxAgeDays, maxBundles) {
20143
- const taskIds = await _internals5.listEvidenceTaskIds(directory);
20435
+ const taskIds = await _internals6.listEvidenceTaskIds(directory);
20144
20436
  const cutoffDate = new Date;
20145
20437
  cutoffDate.setDate(cutoffDate.getDate() - maxAgeDays);
20146
20438
  const cutoffIso = cutoffDate.toISOString();
20147
20439
  const archived = [];
20148
20440
  const remainingBundles = [];
20149
20441
  for (const taskId of taskIds) {
20150
- const result = await _internals5.loadEvidence(directory, taskId);
20442
+ const result = await _internals6.loadEvidence(directory, taskId);
20151
20443
  if (result.status !== "found") {
20152
20444
  continue;
20153
20445
  }
@@ -20175,7 +20467,7 @@ async function archiveEvidence(directory, maxAgeDays, maxBundles) {
20175
20467
  }
20176
20468
  return archived;
20177
20469
  }
20178
- 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;
20179
20471
  var init_manager2 = __esm(() => {
20180
20472
  init_zod();
20181
20473
  init_evidence_schema();
@@ -20218,7 +20510,7 @@ var init_manager2 = __esm(() => {
20218
20510
  medium: "moderate",
20219
20511
  high: "complex"
20220
20512
  };
20221
- _internals5 = {
20513
+ _internals6 = {
20222
20514
  wrapFlatRetrospective,
20223
20515
  loadEvidence,
20224
20516
  listEvidenceTaskIds,
@@ -20430,7 +20722,7 @@ function getProfile(directory, planId) {
20430
20722
  return row ? rowToProfile(row) : null;
20431
20723
  }
20432
20724
  function getOrCreateProfile(directory, planId, projectType) {
20433
- const existing = _internals6.getProfile(directory, planId);
20725
+ const existing = _internals7.getProfile(directory, planId);
20434
20726
  if (existing)
20435
20727
  return existing;
20436
20728
  const db = getProjectDb(directory);
@@ -20446,14 +20738,14 @@ function getOrCreateProfile(directory, planId, projectType) {
20446
20738
  throw err;
20447
20739
  }
20448
20740
  }
20449
- const after = _internals6.getProfile(directory, planId);
20741
+ const after = _internals7.getProfile(directory, planId);
20450
20742
  if (!after) {
20451
20743
  throw new Error(`Failed to create or load QA gate profile for plan_id=${planId}`);
20452
20744
  }
20453
20745
  return after;
20454
20746
  }
20455
20747
  function setGates(directory, planId, gates) {
20456
- const current = _internals6.getProfile(directory, planId);
20748
+ const current = _internals7.getProfile(directory, planId);
20457
20749
  if (!current) {
20458
20750
  throw new Error(`No QA gate profile found for plan_id=${planId} \u2014 call getOrCreateProfile first`);
20459
20751
  }
@@ -20477,7 +20769,7 @@ function setGates(directory, planId, gates) {
20477
20769
  JSON.stringify(merged),
20478
20770
  planId
20479
20771
  ]);
20480
- const updated = _internals6.getProfile(directory, planId);
20772
+ const updated = _internals7.getProfile(directory, planId);
20481
20773
  if (!updated) {
20482
20774
  throw new Error(`Failed to re-read QA gate profile after update for plan_id=${planId}`);
20483
20775
  }
@@ -20499,10 +20791,10 @@ function getEffectiveGates(profile, sessionOverrides) {
20499
20791
  }
20500
20792
  return merged;
20501
20793
  }
20502
- var _internals6, DEFAULT_QA_GATES;
20794
+ var _internals7, DEFAULT_QA_GATES;
20503
20795
  var init_qa_gate_profile = __esm(() => {
20504
20796
  init_project_db();
20505
- _internals6 = {
20797
+ _internals7 = {
20506
20798
  getProfile,
20507
20799
  getOrCreateProfile,
20508
20800
  setGates,
@@ -34950,7 +35242,7 @@ function resetToRemoteBranch(cwd, options) {
34950
35242
  const prunedBranches = [];
34951
35243
  try {
34952
35244
  const currentBranch = getCurrentBranch(cwd);
34953
- const defaultRemoteBranch = _internals7.detectDefaultRemoteBranch(cwd);
35245
+ const defaultRemoteBranch = _internals8.detectDefaultRemoteBranch(cwd);
34954
35246
  if (!defaultRemoteBranch) {
34955
35247
  return {
34956
35248
  success: false,
@@ -35132,7 +35424,7 @@ function resetToRemoteBranch(cwd, options) {
35132
35424
  function resetToMainAfterMerge(cwd, options) {
35133
35425
  const warnings = [];
35134
35426
  try {
35135
- const defaultBranch = _internals7.detectDefaultRemoteBranch(cwd);
35427
+ const defaultBranch = _internals8.detectDefaultRemoteBranch(cwd);
35136
35428
  if (!defaultBranch) {
35137
35429
  return {
35138
35430
  success: false,
@@ -35159,7 +35451,7 @@ function resetToMainAfterMerge(cwd, options) {
35159
35451
  }
35160
35452
  if (currentBranch === defaultBranch) {
35161
35453
  try {
35162
- const logOutput = _internals7.gitExec(["log", `${targetBranch}..HEAD`, "--oneline"], cwd);
35454
+ const logOutput = _internals8.gitExec(["log", `${targetBranch}..HEAD`, "--oneline"], cwd);
35163
35455
  if (logOutput.trim().length > 0) {
35164
35456
  return {
35165
35457
  success: false,
@@ -35174,11 +35466,11 @@ function resetToMainAfterMerge(cwd, options) {
35174
35466
  } catch {}
35175
35467
  } else {
35176
35468
  try {
35177
- _internals7.gitExec(["rev-parse", "--abbrev-ref", `${currentBranch}@{upstream}`], cwd);
35469
+ _internals8.gitExec(["rev-parse", "--abbrev-ref", `${currentBranch}@{upstream}`], cwd);
35178
35470
  } catch {
35179
35471
  try {
35180
- const localSha = _internals7.gitExec(["rev-parse", "HEAD"], cwd).trim();
35181
- 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();
35182
35474
  if (localSha !== remoteSha) {
35183
35475
  return {
35184
35476
  success: false,
@@ -35204,7 +35496,7 @@ function resetToMainAfterMerge(cwd, options) {
35204
35496
  }
35205
35497
  }
35206
35498
  try {
35207
- _internals7.gitExec(["fetch", "--prune", "origin"], cwd);
35499
+ _internals8.gitExec(["fetch", "--prune", "origin"], cwd);
35208
35500
  } catch (err) {
35209
35501
  return {
35210
35502
  success: false,
@@ -35220,7 +35512,7 @@ function resetToMainAfterMerge(cwd, options) {
35220
35512
  let switchedBranch = false;
35221
35513
  if (currentBranch !== defaultBranch) {
35222
35514
  try {
35223
- _internals7.gitExec(["checkout", defaultBranch], cwd);
35515
+ _internals8.gitExec(["checkout", defaultBranch], cwd);
35224
35516
  switchedBranch = true;
35225
35517
  } catch (err) {
35226
35518
  return {
@@ -35235,7 +35527,7 @@ function resetToMainAfterMerge(cwd, options) {
35235
35527
  }
35236
35528
  }
35237
35529
  try {
35238
- _internals7.gitExec(["reset", "--hard", targetBranch], cwd);
35530
+ _internals8.gitExec(["reset", "--hard", targetBranch], cwd);
35239
35531
  } catch (err) {
35240
35532
  return {
35241
35533
  success: false,
@@ -35256,7 +35548,7 @@ function resetToMainAfterMerge(cwd, options) {
35256
35548
  while (Date.now() < endTime) {}
35257
35549
  }
35258
35550
  try {
35259
- _internals7.gitExec(["checkout", "--", "."], cwd);
35551
+ _internals8.gitExec(["checkout", "--", "."], cwd);
35260
35552
  discardSucceeded = true;
35261
35553
  break;
35262
35554
  } catch {}
@@ -35267,18 +35559,18 @@ function resetToMainAfterMerge(cwd, options) {
35267
35559
  changesDiscarded = discardSucceeded;
35268
35560
  }
35269
35561
  try {
35270
- _internals7.gitExec(["clean", "-fd"], cwd);
35562
+ _internals8.gitExec(["clean", "-fd"], cwd);
35271
35563
  } catch {
35272
35564
  warnings.push("Could not clean untracked files");
35273
35565
  }
35274
35566
  let branchDeleted = false;
35275
35567
  if (switchedBranch && previousBranch !== defaultBranch) {
35276
35568
  try {
35277
- const mergedOutput = _internals7.gitExec(["branch", "--merged", defaultBranch], cwd);
35569
+ const mergedOutput = _internals8.gitExec(["branch", "--merged", defaultBranch], cwd);
35278
35570
  const isMerged = mergedOutput.split(`
35279
35571
  `).some((line) => line.trim() === previousBranch || line.trim() === `* ${previousBranch}`);
35280
35572
  if (isMerged) {
35281
- _internals7.gitExec(["branch", "-d", previousBranch], cwd);
35573
+ _internals8.gitExec(["branch", "-d", previousBranch], cwd);
35282
35574
  branchDeleted = true;
35283
35575
  } else {
35284
35576
  warnings.push(`Branch ${previousBranch} is not merged into ${defaultBranch} \u2014 keeping it`);
@@ -35289,7 +35581,7 @@ function resetToMainAfterMerge(cwd, options) {
35289
35581
  }
35290
35582
  if (options?.pruneBranches) {
35291
35583
  try {
35292
- const mergedOutput = _internals7.gitExec(["branch", "--merged", defaultBranch], cwd);
35584
+ const mergedOutput = _internals8.gitExec(["branch", "--merged", defaultBranch], cwd);
35293
35585
  const mergedLines = mergedOutput.split(`
35294
35586
  `);
35295
35587
  for (const line of mergedLines) {
@@ -35298,7 +35590,7 @@ function resetToMainAfterMerge(cwd, options) {
35298
35590
  continue;
35299
35591
  }
35300
35592
  try {
35301
- _internals7.gitExec(["branch", "-d", trimmedLine], cwd);
35593
+ _internals8.gitExec(["branch", "-d", trimmedLine], cwd);
35302
35594
  } catch {
35303
35595
  warnings.push(`Could not prune branch: ${trimmedLine}`);
35304
35596
  }
@@ -35328,10 +35620,10 @@ function resetToMainAfterMerge(cwd, options) {
35328
35620
  };
35329
35621
  }
35330
35622
  }
35331
- var GIT_TIMEOUT_MS2 = 30000, _internals7;
35623
+ var GIT_TIMEOUT_MS2 = 30000, _internals8;
35332
35624
  var init_branch = __esm(() => {
35333
35625
  init_logger();
35334
- _internals7 = {
35626
+ _internals8 = {
35335
35627
  gitExec: gitExec2,
35336
35628
  detectDefaultRemoteBranch,
35337
35629
  getDefaultBaseBranch,
@@ -36525,7 +36817,7 @@ async function curateAndStoreSwarm(lessons, projectName, phaseInfo, directory, c
36525
36817
  existingEntries.push(entry);
36526
36818
  }
36527
36819
  await enforceKnowledgeCap(knowledgePath, config3.swarm_max_entries);
36528
- await _internals8.runAutoPromotion(directory, config3);
36820
+ await _internals9.runAutoPromotion(directory, config3);
36529
36821
  return { stored, skipped, rejected };
36530
36822
  }
36531
36823
  async function runAutoPromotion(directory, config3) {
@@ -36606,7 +36898,7 @@ function createKnowledgeCuratorHook(directory, config3) {
36606
36898
  });
36607
36899
  const projectName2 = evidenceData.project_name ?? "unknown";
36608
36900
  const phaseNumber2 = typeof evidenceData.phase_number === "number" ? evidenceData.phase_number : 1;
36609
- await _internals8.curateAndStoreSwarm(lessons, projectName2, { phase_number: phaseNumber2 }, directory, config3);
36901
+ await _internals9.curateAndStoreSwarm(lessons, projectName2, { phase_number: phaseNumber2 }, directory, config3);
36610
36902
  return;
36611
36903
  }
36612
36904
  const planContent = await readSwarmFileAsync(directory, "plan.md");
@@ -36628,17 +36920,17 @@ function createKnowledgeCuratorHook(directory, config3) {
36628
36920
  const projectName = projectNameMatch ? projectNameMatch[1].trim() : "unknown";
36629
36921
  const phaseMatch = /^Phase:\s*(\d+)/m.exec(planContent);
36630
36922
  const phaseNumber = phaseMatch ? parseInt(phaseMatch[1], 10) : 1;
36631
- await _internals8.curateAndStoreSwarm(normalLessons, projectName, { phase_number: phaseNumber }, directory, config3);
36923
+ await _internals9.curateAndStoreSwarm(normalLessons, projectName, { phase_number: phaseNumber }, directory, config3);
36632
36924
  };
36633
36925
  return safeHook(handler);
36634
36926
  }
36635
- var seenRetroSections, _internals8;
36927
+ var seenRetroSections, _internals9;
36636
36928
  var init_knowledge_curator = __esm(() => {
36637
36929
  init_knowledge_store();
36638
36930
  init_knowledge_validator();
36639
36931
  init_utils2();
36640
36932
  seenRetroSections = new Map;
36641
- _internals8 = {
36933
+ _internals9 = {
36642
36934
  isWriteToEvidenceFile,
36643
36935
  curateAndStoreSwarm,
36644
36936
  runAutoPromotion,
@@ -37845,7 +38137,7 @@ async function executeWriteRetro(args, directory) {
37845
38137
  }, null, 2);
37846
38138
  }
37847
38139
  }
37848
- var write_retro, _internals9;
38140
+ var write_retro, _internals10;
37849
38141
  var init_write_retro = __esm(() => {
37850
38142
  init_zod();
37851
38143
  init_evidence_schema();
@@ -37892,13 +38184,13 @@ var init_write_retro = __esm(() => {
37892
38184
  task_id: args.task_id !== undefined ? String(args.task_id) : undefined,
37893
38185
  metadata: args.metadata
37894
38186
  };
37895
- return await _internals9.executeWriteRetro(writeRetroArgs, directory);
38187
+ return await _internals10.executeWriteRetro(writeRetroArgs, directory);
37896
38188
  } catch {
37897
38189
  return JSON.stringify({ success: false, phase: rawPhase, message: "Invalid arguments" }, null, 2);
37898
38190
  }
37899
38191
  }
37900
38192
  });
37901
- _internals9 = {
38193
+ _internals10 = {
37902
38194
  executeWriteRetro,
37903
38195
  write_retro
37904
38196
  };
@@ -38189,6 +38481,12 @@ async function handleCloseCommand(directory, args, options = {}) {
38189
38481
  }
38190
38482
  }
38191
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
+ }
38192
38490
  const guaranteeResult = guaranteeAllPlansComplete(planData);
38193
38491
  for (const phaseId of guaranteeResult.closedPhaseIds) {
38194
38492
  if (!closedPhases.includes(phaseId)) {
@@ -38202,11 +38500,15 @@ async function handleCloseCommand(directory, args, options = {}) {
38202
38500
  }
38203
38501
  if (!planAlreadyDone || guaranteeResult.closedPhaseIds.length > 0 || guaranteeResult.closedTaskIds.length > 0) {
38204
38502
  try {
38205
- 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
+ });
38206
38508
  } catch (error93) {
38207
38509
  const msg = error93 instanceof Error ? error93.message : String(error93);
38208
- warnings.push(`Failed to persist terminal plan.json state: ${msg}`);
38209
- 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);
38210
38512
  }
38211
38513
  }
38212
38514
  }
@@ -38494,6 +38796,7 @@ var init_close = __esm(() => {
38494
38796
  init_knowledge_curator();
38495
38797
  init_knowledge_store();
38496
38798
  init_utils2();
38799
+ init_manager();
38497
38800
  init_scope_persistence();
38498
38801
  init_skill_improver();
38499
38802
  init_state();
@@ -38902,9 +39205,9 @@ async function detectDarkMatter(directory, options) {
38902
39205
  } catch {
38903
39206
  return [];
38904
39207
  }
38905
- const commitMap = await _internals10.parseGitLog(directory, maxCommitsToAnalyze);
38906
- const matrix = _internals10.buildCoChangeMatrix(commitMap);
38907
- 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);
38908
39211
  const results = [];
38909
39212
  for (const entry of matrix.values()) {
38910
39213
  const key = `${entry.fileA}::${entry.fileB}`;
@@ -38984,7 +39287,7 @@ ${rows}
38984
39287
  These pairs likely share an architectural concern invisible to static analysis.
38985
39288
  Consider adding explicit documentation or extracting the shared concern.`;
38986
39289
  }
38987
- var co_change_analyzer, _internals10;
39290
+ var co_change_analyzer, _internals11;
38988
39291
  var init_co_change_analyzer = __esm(() => {
38989
39292
  init_zod();
38990
39293
  init_create_tool();
@@ -39016,11 +39319,11 @@ var init_co_change_analyzer = __esm(() => {
39016
39319
  npmiThreshold,
39017
39320
  maxCommitsToAnalyze
39018
39321
  };
39019
- const pairs = await _internals10.detectDarkMatter(directory, options);
39020
- return _internals10.formatDarkMatterOutput(pairs);
39322
+ const pairs = await _internals11.detectDarkMatter(directory, options);
39323
+ return _internals11.formatDarkMatterOutput(pairs);
39021
39324
  }
39022
39325
  });
39023
- _internals10 = {
39326
+ _internals11 = {
39024
39327
  parseGitLog,
39025
39328
  buildCoChangeMatrix,
39026
39329
  getStaticEdges,
@@ -39051,7 +39354,7 @@ async function handleDarkMatterCommand(directory, args) {
39051
39354
  }
39052
39355
  let pairs;
39053
39356
  try {
39054
- pairs = await _internals10.detectDarkMatter(directory, options);
39357
+ pairs = await _internals11.detectDarkMatter(directory, options);
39055
39358
  } catch (err) {
39056
39359
  const errMsg = err instanceof Error ? err.message : String(err);
39057
39360
  return `## Dark Matter Analysis Failed
@@ -39243,24 +39546,213 @@ function getPluginLockFilePaths() {
39243
39546
  }
39244
39547
  var init_cache_paths = () => {};
39245
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
+
39246
39738
  // src/services/version-check.ts
39247
- 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";
39248
39740
  import { homedir as homedir5 } from "os";
39249
- import { join as join19 } from "path";
39741
+ import { join as join20 } from "path";
39250
39742
  function cacheDir() {
39251
39743
  const xdg = process.env.XDG_CACHE_HOME;
39252
- const base = xdg && xdg.length > 0 ? xdg : join19(homedir5(), ".cache");
39253
- return join19(base, "opencode-swarm");
39744
+ const base = xdg && xdg.length > 0 ? xdg : join20(homedir5(), ".cache");
39745
+ return join20(base, "opencode-swarm");
39254
39746
  }
39255
39747
  function cacheFile() {
39256
- return join19(cacheDir(), "version-check.json");
39748
+ return join20(cacheDir(), "version-check.json");
39257
39749
  }
39258
39750
  function readVersionCache() {
39259
39751
  try {
39260
- const path21 = cacheFile();
39261
- if (!existsSync11(path21))
39752
+ const path22 = cacheFile();
39753
+ if (!existsSync11(path22))
39262
39754
  return null;
39263
- const raw = readFileSync6(path21, "utf-8");
39755
+ const raw = readFileSync7(path22, "utf-8");
39264
39756
  const parsed = JSON.parse(raw);
39265
39757
  if (typeof parsed?.checkedAt !== "number")
39266
39758
  return null;
@@ -39299,8 +39791,8 @@ var init_version_check = __esm(() => {
39299
39791
 
39300
39792
  // src/services/diagnose-service.ts
39301
39793
  import * as child_process4 from "child_process";
39302
- import { existsSync as existsSync12, readdirSync as readdirSync4, readFileSync as readFileSync7, statSync as statSync6 } from "fs";
39303
- 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";
39304
39796
  import { fileURLToPath } from "url";
39305
39797
  function validateTaskDag(plan) {
39306
39798
  const allTaskIds = new Set;
@@ -39332,7 +39824,21 @@ async function checkEvidenceCompleteness(directory, plan) {
39332
39824
  }
39333
39825
  if (completedTaskIds.length > 0) {
39334
39826
  const evidenceTaskIds = new Set(await listEvidenceTaskIds(directory));
39335
- 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
+ }
39336
39842
  if (missingEvidence.length === 0) {
39337
39843
  return {
39338
39844
  name: "Evidence",
@@ -39597,7 +40103,7 @@ async function checkSpecStaleness(directory, plan) {
39597
40103
  };
39598
40104
  }
39599
40105
  async function checkConfigParseability(directory) {
39600
- const configPath = path21.join(directory, ".opencode/opencode-swarm.json");
40106
+ const configPath = path22.join(directory, ".opencode/opencode-swarm.json");
39601
40107
  if (!existsSync12(configPath)) {
39602
40108
  return {
39603
40109
  name: "Config Parseability",
@@ -39606,7 +40112,7 @@ async function checkConfigParseability(directory) {
39606
40112
  };
39607
40113
  }
39608
40114
  try {
39609
- const content = readFileSync7(configPath, "utf-8");
40115
+ const content = readFileSync8(configPath, "utf-8");
39610
40116
  JSON.parse(content);
39611
40117
  return {
39612
40118
  name: "Config Parseability",
@@ -39626,7 +40132,7 @@ function resolveGrammarDir(thisDir) {
39626
40132
  const normalized = thisDir.replace(/\\/g, "/");
39627
40133
  const isSource = normalized.endsWith("/src/services");
39628
40134
  const isCliBundle = normalized.endsWith("/cli");
39629
- 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");
39630
40136
  }
39631
40137
  async function checkGrammarWasmFiles() {
39632
40138
  const grammarFiles = [
@@ -39650,14 +40156,14 @@ async function checkGrammarWasmFiles() {
39650
40156
  "tree-sitter-ini.wasm",
39651
40157
  "tree-sitter-regex.wasm"
39652
40158
  ];
39653
- const thisDir = path21.dirname(fileURLToPath(import.meta.url));
40159
+ const thisDir = path22.dirname(fileURLToPath(import.meta.url));
39654
40160
  const grammarDir = resolveGrammarDir(thisDir);
39655
40161
  const missing = [];
39656
- if (!existsSync12(path21.join(grammarDir, "tree-sitter.wasm"))) {
40162
+ if (!existsSync12(path22.join(grammarDir, "tree-sitter.wasm"))) {
39657
40163
  missing.push("tree-sitter.wasm (core runtime)");
39658
40164
  }
39659
40165
  for (const file3 of grammarFiles) {
39660
- if (!existsSync12(path21.join(grammarDir, file3))) {
40166
+ if (!existsSync12(path22.join(grammarDir, file3))) {
39661
40167
  missing.push(file3);
39662
40168
  }
39663
40169
  }
@@ -39675,7 +40181,7 @@ async function checkGrammarWasmFiles() {
39675
40181
  };
39676
40182
  }
39677
40183
  async function checkCheckpointManifest(directory) {
39678
- const manifestPath = path21.join(directory, ".swarm/checkpoints.json");
40184
+ const manifestPath = path22.join(directory, ".swarm/checkpoints.json");
39679
40185
  if (!existsSync12(manifestPath)) {
39680
40186
  return {
39681
40187
  name: "Checkpoint Manifest",
@@ -39684,7 +40190,7 @@ async function checkCheckpointManifest(directory) {
39684
40190
  };
39685
40191
  }
39686
40192
  try {
39687
- const content = readFileSync7(manifestPath, "utf-8");
40193
+ const content = readFileSync8(manifestPath, "utf-8");
39688
40194
  const parsed = JSON.parse(content);
39689
40195
  if (!parsed.checkpoints || !Array.isArray(parsed.checkpoints)) {
39690
40196
  return {
@@ -39727,7 +40233,7 @@ async function checkCheckpointManifest(directory) {
39727
40233
  }
39728
40234
  }
39729
40235
  async function checkEventStreamIntegrity(directory) {
39730
- const eventsPath = path21.join(directory, ".swarm/events.jsonl");
40236
+ const eventsPath = path22.join(directory, ".swarm/events.jsonl");
39731
40237
  if (!existsSync12(eventsPath)) {
39732
40238
  return {
39733
40239
  name: "Event Stream",
@@ -39736,7 +40242,7 @@ async function checkEventStreamIntegrity(directory) {
39736
40242
  };
39737
40243
  }
39738
40244
  try {
39739
- const content = readFileSync7(eventsPath, "utf-8");
40245
+ const content = readFileSync8(eventsPath, "utf-8");
39740
40246
  const lines = content.split(`
39741
40247
  `).filter((line) => line.trim() !== "");
39742
40248
  let malformedCount = 0;
@@ -39768,7 +40274,7 @@ async function checkEventStreamIntegrity(directory) {
39768
40274
  }
39769
40275
  }
39770
40276
  async function checkSteeringDirectives(directory) {
39771
- const eventsPath = path21.join(directory, ".swarm/events.jsonl");
40277
+ const eventsPath = path22.join(directory, ".swarm/events.jsonl");
39772
40278
  if (!existsSync12(eventsPath)) {
39773
40279
  return {
39774
40280
  name: "Steering Directives",
@@ -39777,7 +40283,7 @@ async function checkSteeringDirectives(directory) {
39777
40283
  };
39778
40284
  }
39779
40285
  try {
39780
- const content = readFileSync7(eventsPath, "utf-8");
40286
+ const content = readFileSync8(eventsPath, "utf-8");
39781
40287
  const lines = content.split(`
39782
40288
  `).filter((line) => line.trim() !== "");
39783
40289
  const directivesIssued = [];
@@ -39824,7 +40330,7 @@ async function checkCurator(directory) {
39824
40330
  detail: "Disabled (enable via curator.enabled)"
39825
40331
  };
39826
40332
  }
39827
- const summaryPath = path21.join(directory, ".swarm/curator-summary.json");
40333
+ const summaryPath = path22.join(directory, ".swarm/curator-summary.json");
39828
40334
  if (!existsSync12(summaryPath)) {
39829
40335
  return {
39830
40336
  name: "Curator",
@@ -39833,7 +40339,7 @@ async function checkCurator(directory) {
39833
40339
  };
39834
40340
  }
39835
40341
  try {
39836
- const content = readFileSync7(summaryPath, "utf-8");
40342
+ const content = readFileSync8(summaryPath, "utf-8");
39837
40343
  const parsed = JSON.parse(content);
39838
40344
  if (typeof parsed.schema_version !== "number" || parsed.schema_version !== 1) {
39839
40345
  return {
@@ -39990,7 +40496,7 @@ async function getDiagnoseData(directory) {
39990
40496
  checks5.push(await checkSteeringDirectives(directory));
39991
40497
  checks5.push(await checkCurator(directory));
39992
40498
  try {
39993
- const evidenceDir = path21.join(directory, ".swarm", "evidence");
40499
+ const evidenceDir = path22.join(directory, ".swarm", "evidence");
39994
40500
  const snapshotFiles = existsSync12(evidenceDir) ? readdirSync4(evidenceDir).filter((f) => f.startsWith("agent-tools-") && f.endsWith(".json")) : [];
39995
40501
  if (snapshotFiles.length > 0) {
39996
40502
  const latest = snapshotFiles.sort().pop();
@@ -40028,9 +40534,9 @@ async function getDiagnoseData(directory) {
40028
40534
  cacheRows.push(`\u2B1C ${cachePath} \u2014 absent`);
40029
40535
  continue;
40030
40536
  }
40031
- const pkgJsonPath = path21.join(cachePath, "package.json");
40537
+ const pkgJsonPath = path22.join(cachePath, "package.json");
40032
40538
  try {
40033
- const raw = readFileSync7(pkgJsonPath, "utf-8");
40539
+ const raw = readFileSync8(pkgJsonPath, "utf-8");
40034
40540
  const parsed = JSON.parse(raw);
40035
40541
  const installedVersion = typeof parsed.version === "string" ? parsed.version : "?";
40036
40542
  cacheRows.push(`\u2705 ${cachePath} \u2014 v${installedVersion}`);
@@ -40087,6 +40593,7 @@ var init_diagnose_service = __esm(() => {
40087
40593
  init_package();
40088
40594
  init_cache_paths();
40089
40595
  init_loader();
40596
+ init_gate_bridge();
40090
40597
  init_manager2();
40091
40598
  init_utils2();
40092
40599
  init_manager();
@@ -40118,13 +40625,13 @@ __export(exports_config_doctor, {
40118
40625
  import * as crypto3 from "crypto";
40119
40626
  import * as fs8 from "fs";
40120
40627
  import * as os6 from "os";
40121
- import * as path22 from "path";
40628
+ import * as path23 from "path";
40122
40629
  function getUserConfigDir3() {
40123
- return process.env.XDG_CONFIG_HOME || path22.join(os6.homedir(), ".config");
40630
+ return process.env.XDG_CONFIG_HOME || path23.join(os6.homedir(), ".config");
40124
40631
  }
40125
40632
  function getConfigPaths(directory) {
40126
- const userConfigPath = path22.join(getUserConfigDir3(), "opencode", "opencode-swarm.json");
40127
- 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");
40128
40635
  return { userConfigPath, projectConfigPath };
40129
40636
  }
40130
40637
  function computeHash(content) {
@@ -40149,9 +40656,9 @@ function isValidConfigPath(configPath, directory) {
40149
40656
  const normalizedUser = userConfigPath.replace(/\\/g, "/");
40150
40657
  const normalizedProject = projectConfigPath.replace(/\\/g, "/");
40151
40658
  try {
40152
- const resolvedConfig = path22.resolve(configPath);
40153
- const resolvedUser = path22.resolve(normalizedUser);
40154
- const resolvedProject = path22.resolve(normalizedProject);
40659
+ const resolvedConfig = path23.resolve(configPath);
40660
+ const resolvedUser = path23.resolve(normalizedUser);
40661
+ const resolvedProject = path23.resolve(normalizedProject);
40155
40662
  return resolvedConfig === resolvedUser || resolvedConfig === resolvedProject;
40156
40663
  } catch {
40157
40664
  return false;
@@ -40191,12 +40698,12 @@ function createConfigBackup(directory) {
40191
40698
  };
40192
40699
  }
40193
40700
  function writeBackupArtifact(directory, backup) {
40194
- const swarmDir = path22.join(directory, ".swarm");
40701
+ const swarmDir = path23.join(directory, ".swarm");
40195
40702
  if (!fs8.existsSync(swarmDir)) {
40196
40703
  fs8.mkdirSync(swarmDir, { recursive: true });
40197
40704
  }
40198
40705
  const backupFilename = `config-backup-${backup.createdAt}.json`;
40199
- const backupPath = path22.join(swarmDir, backupFilename);
40706
+ const backupPath = path23.join(swarmDir, backupFilename);
40200
40707
  const artifact = {
40201
40708
  createdAt: backup.createdAt,
40202
40709
  configPath: backup.configPath,
@@ -40226,7 +40733,7 @@ function restoreFromBackup(backupPath, directory) {
40226
40733
  return null;
40227
40734
  }
40228
40735
  const targetPath = artifact.configPath;
40229
- const targetDir = path22.dirname(targetPath);
40736
+ const targetDir = path23.dirname(targetPath);
40230
40737
  if (!fs8.existsSync(targetDir)) {
40231
40738
  fs8.mkdirSync(targetDir, { recursive: true });
40232
40739
  }
@@ -40257,9 +40764,9 @@ function readConfigFromFile(directory) {
40257
40764
  return null;
40258
40765
  }
40259
40766
  }
40260
- function validateConfigKey(path23, value, _config) {
40767
+ function validateConfigKey(path24, value, _config) {
40261
40768
  const findings = [];
40262
- switch (path23) {
40769
+ switch (path24) {
40263
40770
  case "agents": {
40264
40771
  if (value !== undefined) {
40265
40772
  findings.push({
@@ -40496,27 +41003,27 @@ function validateConfigKey(path23, value, _config) {
40496
41003
  }
40497
41004
  return findings;
40498
41005
  }
40499
- function walkConfigAndValidate(obj, path23, config3, findings) {
41006
+ function walkConfigAndValidate(obj, path24, config3, findings) {
40500
41007
  if (obj === null || obj === undefined) {
40501
41008
  return;
40502
41009
  }
40503
- if (path23 && typeof obj === "object" && !Array.isArray(obj)) {
40504
- const keyFindings = validateConfigKey(path23, obj, config3);
41010
+ if (path24 && typeof obj === "object" && !Array.isArray(obj)) {
41011
+ const keyFindings = validateConfigKey(path24, obj, config3);
40505
41012
  findings.push(...keyFindings);
40506
41013
  }
40507
41014
  if (typeof obj !== "object") {
40508
- const keyFindings = validateConfigKey(path23, obj, config3);
41015
+ const keyFindings = validateConfigKey(path24, obj, config3);
40509
41016
  findings.push(...keyFindings);
40510
41017
  return;
40511
41018
  }
40512
41019
  if (Array.isArray(obj)) {
40513
41020
  obj.forEach((item, index) => {
40514
- walkConfigAndValidate(item, `${path23}[${index}]`, config3, findings);
41021
+ walkConfigAndValidate(item, `${path24}[${index}]`, config3, findings);
40515
41022
  });
40516
41023
  return;
40517
41024
  }
40518
41025
  for (const [key, value] of Object.entries(obj)) {
40519
- const newPath = path23 ? `${path23}.${key}` : key;
41026
+ const newPath = path24 ? `${path24}.${key}` : key;
40520
41027
  walkConfigAndValidate(value, newPath, config3, findings);
40521
41028
  }
40522
41029
  }
@@ -40636,7 +41143,7 @@ function applySafeAutoFixes(directory, result) {
40636
41143
  }
40637
41144
  }
40638
41145
  if (appliedFixes.length > 0) {
40639
- const configDir = path22.dirname(configPath);
41146
+ const configDir = path23.dirname(configPath);
40640
41147
  if (!fs8.existsSync(configDir)) {
40641
41148
  fs8.mkdirSync(configDir, { recursive: true });
40642
41149
  }
@@ -40646,12 +41153,12 @@ function applySafeAutoFixes(directory, result) {
40646
41153
  return { appliedFixes, updatedConfigPath };
40647
41154
  }
40648
41155
  function writeDoctorArtifact(directory, result) {
40649
- const swarmDir = path22.join(directory, ".swarm");
41156
+ const swarmDir = path23.join(directory, ".swarm");
40650
41157
  if (!fs8.existsSync(swarmDir)) {
40651
41158
  fs8.mkdirSync(swarmDir, { recursive: true });
40652
41159
  }
40653
41160
  const artifactFilename = "config-doctor.json";
40654
- const artifactPath = path22.join(swarmDir, artifactFilename);
41161
+ const artifactPath = path23.join(swarmDir, artifactFilename);
40655
41162
  const guiOutput = {
40656
41163
  timestamp: result.timestamp,
40657
41164
  summary: result.summary,
@@ -40747,17 +41254,17 @@ function detectStraySwarmDirs(projectRoot) {
40747
41254
  if (!entry.isDirectory())
40748
41255
  continue;
40749
41256
  const name = entry.name;
40750
- const fullPath = path22.join(dir, name);
41257
+ const fullPath = path23.join(dir, name);
40751
41258
  if (SKIP_DIRS.has(name))
40752
41259
  continue;
40753
- const gitPath = path22.join(fullPath, ".git");
41260
+ const gitPath = path23.join(fullPath, ".git");
40754
41261
  try {
40755
41262
  const gitStat = fs8.statSync(gitPath);
40756
41263
  if (gitStat.isFile() || gitStat.isDirectory())
40757
41264
  continue;
40758
41265
  } catch {}
40759
41266
  if (name === ".swarm") {
40760
- const parentDir = path22.dirname(fullPath);
41267
+ const parentDir = path23.dirname(fullPath);
40761
41268
  if (parentDir === projectRoot)
40762
41269
  continue;
40763
41270
  let contents = [];
@@ -40767,7 +41274,7 @@ function detectStraySwarmDirs(projectRoot) {
40767
41274
  contents = ["<unreadable>"];
40768
41275
  }
40769
41276
  findings.push({
40770
- path: path22.relative(projectRoot, fullPath).replace(/\\/g, "/"),
41277
+ path: path23.relative(projectRoot, fullPath).replace(/\\/g, "/"),
40771
41278
  absolutePath: fullPath,
40772
41279
  contents: contents.slice(0, MAX_CONTENTS_ENTRIES),
40773
41280
  totalEntries: contents.length
@@ -40785,21 +41292,21 @@ function removeStraySwarmDir(projectRoot, strayPath) {
40785
41292
  let canonicalStray;
40786
41293
  try {
40787
41294
  canonicalRoot = fs8.realpathSync(projectRoot);
40788
- canonicalStray = fs8.realpathSync(path22.isAbsolute(strayPath) ? strayPath : path22.resolve(projectRoot, strayPath));
41295
+ canonicalStray = fs8.realpathSync(path23.isAbsolute(strayPath) ? strayPath : path23.resolve(projectRoot, strayPath));
40789
41296
  } catch (err) {
40790
41297
  return {
40791
41298
  success: false,
40792
41299
  message: `Failed to resolve paths: ${err instanceof Error ? err.message : String(err)}`
40793
41300
  };
40794
41301
  }
40795
- const rootSwarm = path22.join(canonicalRoot, ".swarm");
41302
+ const rootSwarm = path23.join(canonicalRoot, ".swarm");
40796
41303
  if (canonicalStray === rootSwarm || canonicalStray === canonicalRoot) {
40797
41304
  return {
40798
41305
  success: false,
40799
41306
  message: "Refusing to remove root .swarm/ directory"
40800
41307
  };
40801
41308
  }
40802
- if (!canonicalStray.startsWith(canonicalRoot + path22.sep)) {
41309
+ if (!canonicalStray.startsWith(canonicalRoot + path23.sep)) {
40803
41310
  return {
40804
41311
  success: false,
40805
41312
  message: "Path is outside project root \u2014 refusing to remove"
@@ -41888,7 +42395,7 @@ var init_profiles = __esm(() => {
41888
42395
 
41889
42396
  // src/lang/detector.ts
41890
42397
  import { access as access3, readdir as readdir2 } from "fs/promises";
41891
- import { extname as extname2, join as join21 } from "path";
42398
+ import { extname as extname2, join as join22 } from "path";
41892
42399
  async function detectProjectLanguages(projectDir) {
41893
42400
  const detected = new Set;
41894
42401
  async function scanDir(dir) {
@@ -41904,7 +42411,7 @@ async function detectProjectLanguages(projectDir) {
41904
42411
  if (detectFile.includes("*") || detectFile.includes("?"))
41905
42412
  continue;
41906
42413
  try {
41907
- await access3(join21(dir, detectFile));
42414
+ await access3(join22(dir, detectFile));
41908
42415
  detected.add(profile.id);
41909
42416
  break;
41910
42417
  } catch {}
@@ -41925,7 +42432,7 @@ async function detectProjectLanguages(projectDir) {
41925
42432
  const topEntries = await readdir2(projectDir, { withFileTypes: true });
41926
42433
  for (const entry of topEntries) {
41927
42434
  if (entry.isDirectory() && !entry.name.startsWith(".") && entry.name !== "node_modules") {
41928
- await scanDir(join21(projectDir, entry.name));
42435
+ await scanDir(join22(projectDir, entry.name));
41929
42436
  }
41930
42437
  }
41931
42438
  } catch {}
@@ -41944,7 +42451,7 @@ var init_detector = __esm(() => {
41944
42451
 
41945
42452
  // src/build/discovery.ts
41946
42453
  import * as fs9 from "fs";
41947
- import * as path23 from "path";
42454
+ import * as path24 from "path";
41948
42455
  function isCommandAvailable(command) {
41949
42456
  if (toolchainCache.has(command)) {
41950
42457
  return toolchainCache.get(command);
@@ -41952,7 +42459,7 @@ function isCommandAvailable(command) {
41952
42459
  const isWindows = process.platform === "win32";
41953
42460
  const cmd = isWindows ? `${command}.exe` : command;
41954
42461
  try {
41955
- const result = _internals11.spawnSyncImpl(isWindows ? ["where", cmd] : ["which", cmd], {
42462
+ const result = _internals12.spawnSyncImpl(isWindows ? ["where", cmd] : ["which", cmd], {
41956
42463
  cwd: process.cwd(),
41957
42464
  stdin: "ignore",
41958
42465
  stdout: "ignore",
@@ -41979,11 +42486,11 @@ function findBuildFiles(workingDir, patterns) {
41979
42486
  const regex = simpleGlobToRegex(pattern);
41980
42487
  const matches = files.filter((f) => regex.test(f));
41981
42488
  if (matches.length > 0) {
41982
- return path23.join(dir, matches[0]);
42489
+ return path24.join(dir, matches[0]);
41983
42490
  }
41984
42491
  } catch {}
41985
42492
  } else {
41986
- const filePath = path23.join(workingDir, pattern);
42493
+ const filePath = path24.join(workingDir, pattern);
41987
42494
  if (fs9.existsSync(filePath)) {
41988
42495
  return filePath;
41989
42496
  }
@@ -41992,7 +42499,7 @@ function findBuildFiles(workingDir, patterns) {
41992
42499
  return null;
41993
42500
  }
41994
42501
  function getRepoDefinedScripts(workingDir, scripts) {
41995
- const packageJsonPath = path23.join(workingDir, "package.json");
42502
+ const packageJsonPath = path24.join(workingDir, "package.json");
41996
42503
  if (!fs9.existsSync(packageJsonPath)) {
41997
42504
  return [];
41998
42505
  }
@@ -42033,7 +42540,7 @@ function findAllBuildFiles(workingDir) {
42033
42540
  const regex = simpleGlobToRegex(pattern);
42034
42541
  findFilesRecursive(workingDir, regex, allBuildFiles);
42035
42542
  } else {
42036
- const filePath = path23.join(workingDir, pattern);
42543
+ const filePath = path24.join(workingDir, pattern);
42037
42544
  if (fs9.existsSync(filePath)) {
42038
42545
  allBuildFiles.add(filePath);
42039
42546
  }
@@ -42046,7 +42553,7 @@ function findFilesRecursive(dir, regex, results) {
42046
42553
  try {
42047
42554
  const entries = fs9.readdirSync(dir, { withFileTypes: true });
42048
42555
  for (const entry of entries) {
42049
- const fullPath = path23.join(dir, entry.name);
42556
+ const fullPath = path24.join(dir, entry.name);
42050
42557
  if (entry.isDirectory() && !["node_modules", ".git", "dist", "build", "target"].includes(entry.name)) {
42051
42558
  findFilesRecursive(fullPath, regex, results);
42052
42559
  } else if (entry.isFile() && regex.test(entry.name)) {
@@ -42069,7 +42576,7 @@ async function discoverBuildCommandsFromProfiles(workingDir) {
42069
42576
  let foundCommand = false;
42070
42577
  for (const cmd of sortedCommands) {
42071
42578
  if (cmd.detectFile) {
42072
- const detectFilePath = path23.join(workingDir, cmd.detectFile);
42579
+ const detectFilePath = path24.join(workingDir, cmd.detectFile);
42073
42580
  if (!fs9.existsSync(detectFilePath)) {
42074
42581
  continue;
42075
42582
  }
@@ -42102,7 +42609,7 @@ async function discoverBuildCommands(workingDir, options) {
42102
42609
  const scope = options?.scope ?? "all";
42103
42610
  const changedFiles = options?.changedFiles ?? [];
42104
42611
  const _filesToCheck = filterByScope(workingDir, scope, changedFiles);
42105
- const profileResult = await _internals11.discoverBuildCommandsFromProfiles(workingDir);
42612
+ const profileResult = await _internals12.discoverBuildCommandsFromProfiles(workingDir);
42106
42613
  const profileCommands = profileResult.commands;
42107
42614
  const profileSkipped = profileResult.skipped;
42108
42615
  const coveredEcosystems = new Set;
@@ -42165,7 +42672,7 @@ function clearToolchainCache() {
42165
42672
  function getEcosystems() {
42166
42673
  return ECOSYSTEMS.map((e) => e.ecosystem);
42167
42674
  }
42168
- 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;
42169
42676
  var init_discovery = __esm(() => {
42170
42677
  init_dist();
42171
42678
  init_detector();
@@ -42283,7 +42790,7 @@ var init_discovery = __esm(() => {
42283
42790
  php: ["php-composer"]
42284
42791
  };
42285
42792
  toolchainCache = new Map;
42286
- _internals11 = {
42793
+ _internals12 = {
42287
42794
  isCommandAvailable,
42288
42795
  discoverBuildCommandsFromProfiles,
42289
42796
  discoverBuildCommands,
@@ -42310,7 +42817,7 @@ var init_discovery = __esm(() => {
42310
42817
 
42311
42818
  // src/services/tool-doctor.ts
42312
42819
  import * as fs10 from "fs";
42313
- import * as path24 from "path";
42820
+ import * as path25 from "path";
42314
42821
  function extractRegisteredToolKeys(indexPath) {
42315
42822
  const registeredKeys = new Set;
42316
42823
  try {
@@ -42365,8 +42872,8 @@ function checkBinaryReadiness() {
42365
42872
  }
42366
42873
  function runToolDoctor(_directory, pluginRoot) {
42367
42874
  const findings = [];
42368
- const resolvedPluginRoot = pluginRoot ?? path24.resolve(import.meta.dir, "..", "..");
42369
- 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");
42370
42877
  if (!fs10.existsSync(indexPath)) {
42371
42878
  return {
42372
42879
  findings: [
@@ -42586,7 +43093,7 @@ var exports_evidence_summary_service = {};
42586
43093
  __export(exports_evidence_summary_service, {
42587
43094
  isAutoSummaryEnabled: () => isAutoSummaryEnabled,
42588
43095
  buildEvidenceSummary: () => buildEvidenceSummary,
42589
- _internals: () => _internals12,
43096
+ _internals: () => _internals13,
42590
43097
  REQUIRED_EVIDENCE_TYPES: () => REQUIRED_EVIDENCE_TYPES,
42591
43098
  EVIDENCE_SUMMARY_VERSION: () => EVIDENCE_SUMMARY_VERSION
42592
43099
  });
@@ -42624,14 +43131,13 @@ function getTaskStatus(task, bundle) {
42624
43131
  if (task?.status) {
42625
43132
  return task.status;
42626
43133
  }
42627
- const entries = _internals12.normalizeBundleEntries(bundle);
43134
+ const entries = _internals13.normalizeBundleEntries(bundle);
42628
43135
  if (entries.length > 0) {
42629
43136
  return "completed";
42630
43137
  }
42631
43138
  return "pending";
42632
43139
  }
42633
- function isEvidenceComplete(bundle) {
42634
- const entries = _internals12.normalizeBundleEntries(bundle);
43140
+ function evidenceCompleteFromEntries(entries) {
42635
43141
  if (entries.length === 0) {
42636
43142
  return {
42637
43143
  isComplete: false,
@@ -42650,6 +43156,9 @@ function isEvidenceComplete(bundle) {
42650
43156
  missingEvidence: missing
42651
43157
  };
42652
43158
  }
43159
+ function isEvidenceComplete(bundle) {
43160
+ return evidenceCompleteFromEntries(_internals13.normalizeBundleEntries(bundle));
43161
+ }
42653
43162
  function getTaskBlockers(task, summary, status) {
42654
43163
  const blockers = [];
42655
43164
  if (task?.blocked_reason) {
@@ -42666,11 +43175,19 @@ function getTaskBlockers(task, summary, status) {
42666
43175
  async function buildTaskSummary(directory, task, taskId) {
42667
43176
  const result = await loadEvidence(directory, taskId);
42668
43177
  const bundle = result.status === "found" ? result.bundle : null;
43178
+ const gateEvidence = await readDurableGateEvidence(directory, taskId);
42669
43179
  const phase = task?.phase ?? 0;
42670
- const status = _internals12.getTaskStatus(task, bundle);
42671
- const evidenceCheck = _internals12.isEvidenceComplete(bundle);
42672
- const blockers = _internals12.getTaskBlockers(task, evidenceCheck, status);
42673
- 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);
42674
43191
  const hasReview = entries.some((e) => e.type === "review");
42675
43192
  const hasTest = entries.some((e) => e.type === "test");
42676
43193
  const hasApproval = entries.some((e) => e.type === "approval");
@@ -42699,12 +43216,12 @@ async function buildPhaseSummary(directory, phase) {
42699
43216
  const taskSummaries = [];
42700
43217
  const _taskMap = new Map(phase.tasks.map((t) => [t.id, t]));
42701
43218
  for (const task of phase.tasks) {
42702
- const summary = await _internals12.buildTaskSummary(directory, task, task.id);
43219
+ const summary = await _internals13.buildTaskSummary(directory, task, task.id);
42703
43220
  taskSummaries.push(summary);
42704
43221
  }
42705
43222
  const extraTaskIds = taskIds.filter((id) => !phaseTaskIds.has(id));
42706
43223
  for (const taskId of extraTaskIds) {
42707
- const summary = await _internals12.buildTaskSummary(directory, undefined, taskId);
43224
+ const summary = await _internals13.buildTaskSummary(directory, undefined, taskId);
42708
43225
  if (summary.phase === phase.id) {
42709
43226
  taskSummaries.push(summary);
42710
43227
  }
@@ -42805,7 +43322,7 @@ async function buildEvidenceSummary(directory, currentPhase) {
42805
43322
  let totalTasks = 0;
42806
43323
  let completedTasks = 0;
42807
43324
  for (const phase of phasesToProcess) {
42808
- const summary = await _internals12.buildPhaseSummary(directory, phase);
43325
+ const summary = await _internals13.buildPhaseSummary(directory, phase);
42809
43326
  phaseSummaries.push(summary);
42810
43327
  totalTasks += summary.totalTasks;
42811
43328
  completedTasks += summary.completedTasks;
@@ -42827,7 +43344,7 @@ async function buildEvidenceSummary(directory, currentPhase) {
42827
43344
  overallBlockers,
42828
43345
  summaryText: ""
42829
43346
  };
42830
- artifact.summaryText = _internals12.generateSummaryText(artifact);
43347
+ artifact.summaryText = _internals13.generateSummaryText(artifact);
42831
43348
  log("[EvidenceSummary] Summary built", {
42832
43349
  phases: phaseSummaries.length,
42833
43350
  totalTasks,
@@ -42846,8 +43363,9 @@ function isAutoSummaryEnabled(automationConfig) {
42846
43363
  }
42847
43364
  return automationConfig.capabilities?.evidence_auto_summaries === true;
42848
43365
  }
42849
- 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;
42850
43367
  var init_evidence_summary_service = __esm(() => {
43368
+ init_gate_bridge();
42851
43369
  init_manager2();
42852
43370
  init_manager();
42853
43371
  init_utils();
@@ -42860,11 +43378,12 @@ var init_evidence_summary_service = __esm(() => {
42860
43378
  "retrospective"
42861
43379
  ]);
42862
43380
  REQUIRED_EVIDENCE_TYPES = ["review", "test"];
42863
- _internals12 = {
43381
+ _internals13 = {
42864
43382
  buildEvidenceSummary,
42865
43383
  isAutoSummaryEnabled,
42866
43384
  normalizeBundleEntries,
42867
43385
  getTaskStatus,
43386
+ evidenceCompleteFromEntries,
42868
43387
  isEvidenceComplete,
42869
43388
  getTaskBlockers,
42870
43389
  buildTaskSummary,
@@ -42915,7 +43434,7 @@ function getVerdictEmoji(verdict) {
42915
43434
  return getVerdictIcon(verdict);
42916
43435
  }
42917
43436
  async function getTaskEvidenceData(directory, taskId) {
42918
- const result = await _internals13.loadEvidence(directory, taskId);
43437
+ const result = await _internals14.loadEvidence(directory, taskId);
42919
43438
  if (result.status !== "found") {
42920
43439
  return {
42921
43440
  hasEvidence: false,
@@ -42938,13 +43457,13 @@ async function getTaskEvidenceData(directory, taskId) {
42938
43457
  };
42939
43458
  }
42940
43459
  async function getEvidenceListData(directory) {
42941
- const taskIds = await _internals13.listEvidenceTaskIds(directory);
43460
+ const taskIds = await _internals14.listEvidenceTaskIds(directory);
42942
43461
  if (taskIds.length === 0) {
42943
43462
  return { hasEvidence: false, tasks: [] };
42944
43463
  }
42945
43464
  const tasks = [];
42946
43465
  for (const taskId of taskIds) {
42947
- const result = await _internals13.loadEvidence(directory, taskId);
43466
+ const result = await _internals14.loadEvidence(directory, taskId);
42948
43467
  if (result.status === "found") {
42949
43468
  tasks.push({
42950
43469
  taskId,
@@ -43058,10 +43577,10 @@ async function handleEvidenceSummaryCommand(directory) {
43058
43577
  return lines.join(`
43059
43578
  `);
43060
43579
  }
43061
- var _internals13;
43580
+ var _internals14;
43062
43581
  var init_evidence_service = __esm(() => {
43063
43582
  init_manager2();
43064
- _internals13 = {
43583
+ _internals14 = {
43065
43584
  loadEvidence,
43066
43585
  listEvidenceTaskIds
43067
43586
  };
@@ -43112,12 +43631,12 @@ var init_export = __esm(() => {
43112
43631
 
43113
43632
  // src/full-auto/state.ts
43114
43633
  import * as fs11 from "fs";
43115
- import * as path25 from "path";
43634
+ import * as path26 from "path";
43116
43635
  function nowISO() {
43117
43636
  return new Date().toISOString();
43118
43637
  }
43119
43638
  function ensureSwarmDir(directory) {
43120
- const swarmDir = path25.resolve(directory, ".swarm");
43639
+ const swarmDir = path26.resolve(directory, ".swarm");
43121
43640
  if (!fs11.existsSync(swarmDir)) {
43122
43641
  fs11.mkdirSync(swarmDir, { recursive: true });
43123
43642
  }
@@ -43468,7 +43987,7 @@ function extractCurrentPhaseFromPlan2(plan) {
43468
43987
  if (!plan) {
43469
43988
  return { currentPhase: null, currentTask: null, incompleteTasks: [] };
43470
43989
  }
43471
- if (!_internals14.validatePlanPhases(plan)) {
43990
+ if (!_internals15.validatePlanPhases(plan)) {
43472
43991
  return { currentPhase: null, currentTask: null, incompleteTasks: [] };
43473
43992
  }
43474
43993
  let currentPhase = null;
@@ -43610,9 +44129,9 @@ function extractPhaseMetrics(content) {
43610
44129
  async function getHandoffData(directory) {
43611
44130
  const now = new Date().toISOString();
43612
44131
  const sessionContent = await readSwarmFileAsync(directory, "session/state.json");
43613
- const sessionState = _internals14.parseSessionState(sessionContent);
44132
+ const sessionState = _internals15.parseSessionState(sessionContent);
43614
44133
  const plan = await loadPlanJsonOnly(directory);
43615
- const planInfo = _internals14.extractCurrentPhaseFromPlan(plan);
44134
+ const planInfo = _internals15.extractCurrentPhaseFromPlan(plan);
43616
44135
  if (!plan) {
43617
44136
  const planMdContent = await readSwarmFileAsync(directory, "plan.md");
43618
44137
  if (planMdContent) {
@@ -43631,8 +44150,8 @@ async function getHandoffData(directory) {
43631
44150
  }
43632
44151
  }
43633
44152
  const contextContent = await readSwarmFileAsync(directory, "context.md");
43634
- const recentDecisions = _internals14.extractDecisions(contextContent);
43635
- const rawPhaseMetrics = _internals14.extractPhaseMetrics(contextContent);
44153
+ const recentDecisions = _internals15.extractDecisions(contextContent);
44154
+ const rawPhaseMetrics = _internals15.extractPhaseMetrics(contextContent);
43636
44155
  const phaseMetrics = sanitizeString(rawPhaseMetrics, 1000);
43637
44156
  let delegationState = null;
43638
44157
  if (sessionState?.delegationState) {
@@ -43796,13 +44315,13 @@ ${lines.join(`
43796
44315
  `)}
43797
44316
  \`\`\``;
43798
44317
  }
43799
- 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;
43800
44319
  var init_handoff_service = __esm(() => {
43801
44320
  init_utils2();
43802
44321
  init_manager();
43803
44322
  init_utils();
43804
44323
  RTL_OVERRIDE_PATTERN = /[\u202e\u202d\u202c\u200f]/g;
43805
- _internals14 = {
44324
+ _internals15 = {
43806
44325
  getHandoffData,
43807
44326
  formatHandoffMarkdown,
43808
44327
  formatContinuationPrompt,
@@ -43817,8 +44336,8 @@ var init_handoff_service = __esm(() => {
43817
44336
  });
43818
44337
 
43819
44338
  // src/session/snapshot-writer.ts
43820
- import { closeSync as closeSync3, fsyncSync as fsyncSync2, mkdirSync as mkdirSync10, openSync as openSync3, renameSync as renameSync6 } from "fs";
43821
- 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";
43822
44341
  function serializeAgentSession(s) {
43823
44342
  const gateLog = {};
43824
44343
  const rawGateLog = s.gateLog ?? new Map;
@@ -43915,8 +44434,8 @@ async function writeSnapshot(directory, state) {
43915
44434
  }
43916
44435
  const content = JSON.stringify(snapshot, null, 2);
43917
44436
  const resolvedPath = validateSwarmPath(directory, "session/state.json");
43918
- const dir = path26.dirname(resolvedPath);
43919
- mkdirSync10(dir, { recursive: true });
44437
+ const dir = path27.dirname(resolvedPath);
44438
+ mkdirSync11(dir, { recursive: true });
43920
44439
  const tempPath = `${resolvedPath}.tmp.${Date.now()}.${Math.random().toString(36).slice(2)}`;
43921
44440
  await bunWrite(tempPath, content);
43922
44441
  try {
@@ -43936,22 +44455,22 @@ async function writeSnapshot(directory, state) {
43936
44455
  }
43937
44456
  function createSnapshotWriterHook(directory) {
43938
44457
  return (_input, _output) => {
43939
- _writeInFlight = _writeInFlight.then(() => _internals15.writeSnapshot(directory, swarmState), () => _internals15.writeSnapshot(directory, swarmState));
44458
+ _writeInFlight = _writeInFlight.then(() => _internals16.writeSnapshot(directory, swarmState), () => _internals16.writeSnapshot(directory, swarmState));
43940
44459
  return _writeInFlight;
43941
44460
  };
43942
44461
  }
43943
44462
  async function flushPendingSnapshot(directory) {
43944
- _writeInFlight = _writeInFlight.then(() => _internals15.writeSnapshot(directory, swarmState), () => _internals15.writeSnapshot(directory, swarmState));
44463
+ _writeInFlight = _writeInFlight.then(() => _internals16.writeSnapshot(directory, swarmState), () => _internals16.writeSnapshot(directory, swarmState));
43945
44464
  await _writeInFlight;
43946
44465
  }
43947
- var _writeInFlight, _internals15;
44466
+ var _writeInFlight, _internals16;
43948
44467
  var init_snapshot_writer = __esm(() => {
43949
44468
  init_utils2();
43950
44469
  init_state();
43951
44470
  init_utils();
43952
44471
  init_bun_compat();
43953
44472
  _writeInFlight = Promise.resolve();
43954
- _internals15 = {
44473
+ _internals16 = {
43955
44474
  writeSnapshot,
43956
44475
  createSnapshotWriterHook,
43957
44476
  flushPendingSnapshot
@@ -44372,9 +44891,9 @@ var init_issue = __esm(() => {
44372
44891
 
44373
44892
  // src/hooks/knowledge-migrator.ts
44374
44893
  import { randomUUID as randomUUID2 } from "crypto";
44375
- import { existsSync as existsSync17, readFileSync as readFileSync12 } from "fs";
44894
+ import { existsSync as existsSync17, readFileSync as readFileSync13 } from "fs";
44376
44895
  import { mkdir as mkdir7, readFile as readFile7, writeFile as writeFile8 } from "fs/promises";
44377
- import * as path27 from "path";
44896
+ import * as path28 from "path";
44378
44897
  async function migrateKnowledgeToExternal(_directory, _config) {
44379
44898
  return {
44380
44899
  migrated: false,
@@ -44385,8 +44904,8 @@ async function migrateKnowledgeToExternal(_directory, _config) {
44385
44904
  };
44386
44905
  }
44387
44906
  async function migrateContextToKnowledge(directory, config3) {
44388
- const sentinelPath = path27.join(directory, ".swarm", ".knowledge-migrated");
44389
- 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");
44390
44909
  const knowledgePath = resolveSwarmKnowledgePath(directory);
44391
44910
  if (existsSync17(sentinelPath)) {
44392
44911
  return {
@@ -44416,9 +44935,9 @@ async function migrateContextToKnowledge(directory, config3) {
44416
44935
  skippedReason: "empty-context"
44417
44936
  };
44418
44937
  }
44419
- const rawEntries = _internals16.parseContextMd(contextContent);
44938
+ const rawEntries = _internals17.parseContextMd(contextContent);
44420
44939
  if (rawEntries.length === 0) {
44421
- await _internals16.writeSentinel(sentinelPath, 0, 0);
44940
+ await _internals17.writeSentinel(sentinelPath, 0, 0);
44422
44941
  return {
44423
44942
  migrated: true,
44424
44943
  entriesMigrated: 0,
@@ -44429,10 +44948,10 @@ async function migrateContextToKnowledge(directory, config3) {
44429
44948
  const existing = await readKnowledge(knowledgePath);
44430
44949
  let migrated = 0;
44431
44950
  let dropped = 0;
44432
- const projectName = _internals16.inferProjectName(directory);
44951
+ const projectName = _internals17.inferProjectName(directory);
44433
44952
  for (const raw of rawEntries) {
44434
44953
  if (config3.validation_enabled !== false) {
44435
- const category = raw.categoryHint ?? _internals16.inferCategoryFromText(raw.text);
44954
+ const category = raw.categoryHint ?? _internals17.inferCategoryFromText(raw.text);
44436
44955
  const result = validateLesson(raw.text, existing.map((e) => e.lesson), {
44437
44956
  category,
44438
44957
  scope: "global",
@@ -44452,8 +44971,8 @@ async function migrateContextToKnowledge(directory, config3) {
44452
44971
  const entry = {
44453
44972
  id: randomUUID2(),
44454
44973
  tier: "swarm",
44455
- lesson: _internals16.truncateLesson(raw.text),
44456
- category: raw.categoryHint ?? _internals16.inferCategoryFromText(raw.text),
44974
+ lesson: _internals17.truncateLesson(raw.text),
44975
+ category: raw.categoryHint ?? _internals17.inferCategoryFromText(raw.text),
44457
44976
  tags: [...inferredTags, `migration:${raw.sourceSection}`],
44458
44977
  scope: "global",
44459
44978
  confidence: 0.3,
@@ -44476,7 +44995,7 @@ async function migrateContextToKnowledge(directory, config3) {
44476
44995
  if (migrated > 0) {
44477
44996
  await rewriteKnowledge(knowledgePath, existing);
44478
44997
  }
44479
- await _internals16.writeSentinel(sentinelPath, migrated, dropped);
44998
+ await _internals17.writeSentinel(sentinelPath, migrated, dropped);
44480
44999
  log(`[knowledge-migrator] Migrated ${migrated} entries, dropped ${dropped}`);
44481
45000
  return {
44482
45001
  migrated: true,
@@ -44486,7 +45005,7 @@ async function migrateContextToKnowledge(directory, config3) {
44486
45005
  };
44487
45006
  }
44488
45007
  function parseContextMd(content) {
44489
- const sections = _internals16.splitIntoSections(content);
45008
+ const sections = _internals17.splitIntoSections(content);
44490
45009
  const entries = [];
44491
45010
  const seen = new Set;
44492
45011
  const sectionPatterns = [
@@ -44502,7 +45021,7 @@ function parseContextMd(content) {
44502
45021
  const match = sectionPatterns.find((sp) => sp.pattern.test(section.heading));
44503
45022
  if (!match)
44504
45023
  continue;
44505
- const bullets = _internals16.extractBullets(section.body);
45024
+ const bullets = _internals17.extractBullets(section.body);
44506
45025
  for (const bullet of bullets) {
44507
45026
  if (bullet.length < 15)
44508
45027
  continue;
@@ -44511,9 +45030,9 @@ function parseContextMd(content) {
44511
45030
  continue;
44512
45031
  seen.add(normalized);
44513
45032
  entries.push({
44514
- text: _internals16.truncateLesson(bullet),
45033
+ text: _internals17.truncateLesson(bullet),
44515
45034
  sourceSection: match.sourceSection,
44516
- categoryHint: _internals16.inferCategoryFromText(bullet)
45035
+ categoryHint: _internals17.inferCategoryFromText(bullet)
44517
45036
  });
44518
45037
  }
44519
45038
  }
@@ -44582,16 +45101,16 @@ function truncateLesson(text) {
44582
45101
  return `${text.slice(0, 277)}...`;
44583
45102
  }
44584
45103
  function inferProjectName(directory) {
44585
- const packageJsonPath = path27.join(directory, "package.json");
45104
+ const packageJsonPath = path28.join(directory, "package.json");
44586
45105
  if (existsSync17(packageJsonPath)) {
44587
45106
  try {
44588
- const pkg = JSON.parse(readFileSync12(packageJsonPath, "utf-8"));
45107
+ const pkg = JSON.parse(readFileSync13(packageJsonPath, "utf-8"));
44589
45108
  if (pkg.name && typeof pkg.name === "string") {
44590
45109
  return pkg.name;
44591
45110
  }
44592
45111
  } catch {}
44593
45112
  }
44594
- return path27.basename(directory);
45113
+ return path28.basename(directory);
44595
45114
  }
44596
45115
  async function writeSentinel(sentinelPath, migrated, dropped) {
44597
45116
  const sentinel = {
@@ -44603,15 +45122,15 @@ async function writeSentinel(sentinelPath, migrated, dropped) {
44603
45122
  schema_version: 1,
44604
45123
  migration_tool: "knowledge-migrator.ts"
44605
45124
  };
44606
- await mkdir7(path27.dirname(sentinelPath), { recursive: true });
45125
+ await mkdir7(path28.dirname(sentinelPath), { recursive: true });
44607
45126
  await writeFile8(sentinelPath, JSON.stringify(sentinel, null, 2), "utf-8");
44608
45127
  }
44609
- var _internals16;
45128
+ var _internals17;
44610
45129
  var init_knowledge_migrator = __esm(() => {
44611
45130
  init_logger();
44612
45131
  init_knowledge_store();
44613
45132
  init_knowledge_validator();
44614
- _internals16 = {
45133
+ _internals17 = {
44615
45134
  migrateContextToKnowledge,
44616
45135
  migrateKnowledgeToExternal,
44617
45136
  parseContextMd,
@@ -44625,7 +45144,7 @@ var init_knowledge_migrator = __esm(() => {
44625
45144
  });
44626
45145
 
44627
45146
  // src/commands/knowledge.ts
44628
- import { join as join25 } from "path";
45147
+ import { join as join26 } from "path";
44629
45148
  function resolveEntryByPrefix(entries, inputId) {
44630
45149
  const exact = entries.find((e) => e.id === inputId);
44631
45150
  if (exact)
@@ -44676,7 +45195,7 @@ async function handleKnowledgeRestoreCommand(directory, args) {
44676
45195
  return "Invalid entry ID. IDs must be 1-64 characters: letters, digits, hyphens, underscores only.";
44677
45196
  }
44678
45197
  try {
44679
- const quarantinePath = join25(directory, ".swarm", "knowledge-quarantined.jsonl");
45198
+ const quarantinePath = join26(directory, ".swarm", "knowledge-quarantined.jsonl");
44680
45199
  const entries = await readKnowledge(quarantinePath);
44681
45200
  const resolved = resolveEntryByPrefix(entries, inputId);
44682
45201
  if ("error" in resolved) {
@@ -44748,9 +45267,9 @@ var init_knowledge = __esm(() => {
44748
45267
 
44749
45268
  // src/services/plan-service.ts
44750
45269
  async function getPlanData(directory, phaseArg) {
44751
- const plan = await _internals17.loadPlanJsonOnly(directory);
45270
+ const plan = await _internals18.loadPlanJsonOnly(directory);
44752
45271
  if (plan) {
44753
- const fullMarkdown = _internals17.derivePlanMarkdown(plan);
45272
+ const fullMarkdown = _internals18.derivePlanMarkdown(plan);
44754
45273
  if (phaseArg === undefined || phaseArg === null || phaseArg === "") {
44755
45274
  return {
44756
45275
  hasPlan: true,
@@ -44793,7 +45312,7 @@ async function getPlanData(directory, phaseArg) {
44793
45312
  isLegacy: false
44794
45313
  };
44795
45314
  }
44796
- const planContent = await _internals17.readSwarmFileAsync(directory, "plan.md");
45315
+ const planContent = await _internals18.readSwarmFileAsync(directory, "plan.md");
44797
45316
  if (!planContent) {
44798
45317
  return {
44799
45318
  hasPlan: false,
@@ -44889,11 +45408,11 @@ async function handlePlanCommand(directory, args) {
44889
45408
  const planData = await getPlanData(directory, phaseArg);
44890
45409
  return formatPlanMarkdown(planData);
44891
45410
  }
44892
- var _internals17;
45411
+ var _internals18;
44893
45412
  var init_plan_service = __esm(() => {
44894
45413
  init_utils2();
44895
45414
  init_manager();
44896
- _internals17 = {
45415
+ _internals18 = {
44897
45416
  loadPlanJsonOnly,
44898
45417
  derivePlanMarkdown,
44899
45418
  readSwarmFileAsync
@@ -45131,7 +45650,7 @@ var init_path_security = () => {};
45131
45650
 
45132
45651
  // src/tools/lint.ts
45133
45652
  import * as fs12 from "fs";
45134
- import * as path28 from "path";
45653
+ import * as path29 from "path";
45135
45654
  function validateArgs(args) {
45136
45655
  if (typeof args !== "object" || args === null)
45137
45656
  return false;
@@ -45142,9 +45661,9 @@ function validateArgs(args) {
45142
45661
  }
45143
45662
  function getLinterCommand(linter, mode, projectDir) {
45144
45663
  const isWindows = process.platform === "win32";
45145
- const binDir = path28.join(projectDir, "node_modules", ".bin");
45146
- const biomeBin = isWindows ? path28.join(binDir, "biome.EXE") : path28.join(binDir, "biome");
45147
- 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");
45148
45667
  switch (linter) {
45149
45668
  case "biome":
45150
45669
  if (mode === "fix") {
@@ -45160,7 +45679,7 @@ function getLinterCommand(linter, mode, projectDir) {
45160
45679
  }
45161
45680
  function getAdditionalLinterCommand(linter, mode, cwd) {
45162
45681
  const gradlewName = process.platform === "win32" ? "gradlew.bat" : "gradlew";
45163
- 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;
45164
45683
  switch (linter) {
45165
45684
  case "ruff":
45166
45685
  return mode === "fix" ? ["ruff", "check", "--fix", "."] : ["ruff", "check", "."];
@@ -45194,10 +45713,10 @@ function getAdditionalLinterCommand(linter, mode, cwd) {
45194
45713
  }
45195
45714
  }
45196
45715
  function detectRuff(cwd) {
45197
- if (fs12.existsSync(path28.join(cwd, "ruff.toml")))
45716
+ if (fs12.existsSync(path29.join(cwd, "ruff.toml")))
45198
45717
  return isCommandAvailable("ruff");
45199
45718
  try {
45200
- const pyproject = path28.join(cwd, "pyproject.toml");
45719
+ const pyproject = path29.join(cwd, "pyproject.toml");
45201
45720
  if (fs12.existsSync(pyproject)) {
45202
45721
  const content = fs12.readFileSync(pyproject, "utf-8");
45203
45722
  if (content.includes("[tool.ruff]"))
@@ -45207,19 +45726,19 @@ function detectRuff(cwd) {
45207
45726
  return false;
45208
45727
  }
45209
45728
  function detectClippy(cwd) {
45210
- return fs12.existsSync(path28.join(cwd, "Cargo.toml")) && isCommandAvailable("cargo");
45729
+ return fs12.existsSync(path29.join(cwd, "Cargo.toml")) && isCommandAvailable("cargo");
45211
45730
  }
45212
45731
  function detectGolangciLint(cwd) {
45213
- return fs12.existsSync(path28.join(cwd, "go.mod")) && isCommandAvailable("golangci-lint");
45732
+ return fs12.existsSync(path29.join(cwd, "go.mod")) && isCommandAvailable("golangci-lint");
45214
45733
  }
45215
45734
  function detectCheckstyle(cwd) {
45216
- const hasMaven = fs12.existsSync(path28.join(cwd, "pom.xml"));
45217
- const hasGradle = fs12.existsSync(path28.join(cwd, "build.gradle")) || fs12.existsSync(path28.join(cwd, "build.gradle.kts"));
45218
- 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"));
45219
45738
  return (hasMaven || hasGradle) && hasBinary;
45220
45739
  }
45221
45740
  function detectKtlint(cwd) {
45222
- 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")) || (() => {
45223
45742
  try {
45224
45743
  return fs12.readdirSync(cwd).some((f) => f.endsWith(".kt") || f.endsWith(".kts"));
45225
45744
  } catch {
@@ -45238,11 +45757,11 @@ function detectDotnetFormat(cwd) {
45238
45757
  }
45239
45758
  }
45240
45759
  function detectCppcheck(cwd) {
45241
- if (fs12.existsSync(path28.join(cwd, "CMakeLists.txt"))) {
45760
+ if (fs12.existsSync(path29.join(cwd, "CMakeLists.txt"))) {
45242
45761
  return isCommandAvailable("cppcheck");
45243
45762
  }
45244
45763
  try {
45245
- const dirsToCheck = [cwd, path28.join(cwd, "src")];
45764
+ const dirsToCheck = [cwd, path29.join(cwd, "src")];
45246
45765
  const hasCpp = dirsToCheck.some((dir) => {
45247
45766
  try {
45248
45767
  return fs12.readdirSync(dir).some((f) => /\.(c|cpp|cc|cxx|h|hpp)$/.test(f));
@@ -45256,13 +45775,13 @@ function detectCppcheck(cwd) {
45256
45775
  }
45257
45776
  }
45258
45777
  function detectSwiftlint(cwd) {
45259
- return fs12.existsSync(path28.join(cwd, "Package.swift")) && isCommandAvailable("swiftlint");
45778
+ return fs12.existsSync(path29.join(cwd, "Package.swift")) && isCommandAvailable("swiftlint");
45260
45779
  }
45261
45780
  function detectDartAnalyze(cwd) {
45262
- 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"));
45263
45782
  }
45264
45783
  function detectRubocop(cwd) {
45265
- 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"));
45266
45785
  }
45267
45786
  function detectAdditionalLinter(cwd) {
45268
45787
  if (detectRuff(cwd))
@@ -45290,10 +45809,10 @@ function detectAdditionalLinter(cwd) {
45290
45809
  function findBinInAncestors(startDir, binName) {
45291
45810
  let dir = startDir;
45292
45811
  while (true) {
45293
- const candidate = path28.join(dir, "node_modules", ".bin", binName);
45812
+ const candidate = path29.join(dir, "node_modules", ".bin", binName);
45294
45813
  if (fs12.existsSync(candidate))
45295
45814
  return candidate;
45296
- const parent = path28.dirname(dir);
45815
+ const parent = path29.dirname(dir);
45297
45816
  if (parent === dir)
45298
45817
  break;
45299
45818
  dir = parent;
@@ -45302,10 +45821,10 @@ function findBinInAncestors(startDir, binName) {
45302
45821
  }
45303
45822
  function findBinInEnvPath(binName) {
45304
45823
  const searchPath = process.env.PATH ?? "";
45305
- for (const dir of searchPath.split(path28.delimiter)) {
45824
+ for (const dir of searchPath.split(path29.delimiter)) {
45306
45825
  if (!dir)
45307
45826
  continue;
45308
- const candidate = path28.join(dir, binName);
45827
+ const candidate = path29.join(dir, binName);
45309
45828
  if (fs12.existsSync(candidate))
45310
45829
  return candidate;
45311
45830
  }
@@ -45318,13 +45837,13 @@ async function detectAvailableLinter(directory) {
45318
45837
  return null;
45319
45838
  const projectDir = directory;
45320
45839
  const isWindows = process.platform === "win32";
45321
- const biomeBin = isWindows ? path28.join(projectDir, "node_modules", ".bin", "biome.EXE") : path28.join(projectDir, "node_modules", ".bin", "biome");
45322
- 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");
45323
45842
  const localResult = await _detectAvailableLinter(projectDir, biomeBin, eslintBin);
45324
45843
  if (localResult)
45325
45844
  return localResult;
45326
- const biomeAncestor = findBinInAncestors(path28.dirname(projectDir), isWindows ? "biome.EXE" : "biome");
45327
- 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");
45328
45847
  if (biomeAncestor || eslintAncestor) {
45329
45848
  return _detectAvailableLinter(projectDir, biomeAncestor ?? biomeBin, eslintAncestor ?? eslintBin);
45330
45849
  }
@@ -45483,7 +46002,7 @@ async function runAdditionalLint(linter, mode, cwd) {
45483
46002
  };
45484
46003
  }
45485
46004
  }
45486
- var MAX_OUTPUT_BYTES = 512000, MAX_COMMAND_LENGTH = 500, lint, _internals18;
46005
+ var MAX_OUTPUT_BYTES = 512000, MAX_COMMAND_LENGTH = 500, lint, _internals19;
45487
46006
  var init_lint = __esm(() => {
45488
46007
  init_zod();
45489
46008
  init_discovery();
@@ -45515,15 +46034,15 @@ var init_lint = __esm(() => {
45515
46034
  }
45516
46035
  const { mode } = args;
45517
46036
  const cwd = directory;
45518
- const linter = await _internals18.detectAvailableLinter(directory);
46037
+ const linter = await _internals19.detectAvailableLinter(directory);
45519
46038
  if (linter) {
45520
- const result = await _internals18.runLint(linter, mode, directory);
46039
+ const result = await _internals19.runLint(linter, mode, directory);
45521
46040
  return JSON.stringify(result, null, 2);
45522
46041
  }
45523
- const additionalLinter = _internals18.detectAdditionalLinter(cwd);
46042
+ const additionalLinter = _internals19.detectAdditionalLinter(cwd);
45524
46043
  if (additionalLinter) {
45525
46044
  warn(`[lint] Using ${additionalLinter} linter for this project`);
45526
- const result = await _internals18.runAdditionalLint(additionalLinter, mode, cwd);
46045
+ const result = await _internals19.runAdditionalLint(additionalLinter, mode, cwd);
45527
46046
  return JSON.stringify(result, null, 2);
45528
46047
  }
45529
46048
  const errorResult = {
@@ -45537,7 +46056,7 @@ For Rust: rustup component add clippy`
45537
46056
  return JSON.stringify(errorResult, null, 2);
45538
46057
  }
45539
46058
  });
45540
- _internals18 = {
46059
+ _internals19 = {
45541
46060
  detectAvailableLinter,
45542
46061
  runLint,
45543
46062
  detectAdditionalLinter,
@@ -45547,7 +46066,7 @@ For Rust: rustup component add clippy`
45547
46066
 
45548
46067
  // src/tools/secretscan.ts
45549
46068
  import * as fs13 from "fs";
45550
- import * as path29 from "path";
46069
+ import * as path30 from "path";
45551
46070
  function calculateShannonEntropy(str) {
45552
46071
  if (str.length === 0)
45553
46072
  return 0;
@@ -45595,7 +46114,7 @@ function isGlobOrPathPattern(pattern) {
45595
46114
  return pattern.includes("/") || pattern.includes("\\") || /[*?[\]{}]/.test(pattern);
45596
46115
  }
45597
46116
  function loadSecretScanIgnore(scanDir) {
45598
- const ignorePath = path29.join(scanDir, ".secretscanignore");
46117
+ const ignorePath = path30.join(scanDir, ".secretscanignore");
45599
46118
  try {
45600
46119
  if (!fs13.existsSync(ignorePath))
45601
46120
  return [];
@@ -45618,7 +46137,7 @@ function isExcluded(entry, relPath, exactNames, globPatterns) {
45618
46137
  if (exactNames.has(entry))
45619
46138
  return true;
45620
46139
  for (const pattern of globPatterns) {
45621
- if (path29.matchesGlob(relPath, pattern))
46140
+ if (path30.matchesGlob(relPath, pattern))
45622
46141
  return true;
45623
46142
  }
45624
46143
  return false;
@@ -45639,7 +46158,7 @@ function validateDirectoryInput(dir) {
45639
46158
  return null;
45640
46159
  }
45641
46160
  function isBinaryFile(filePath, buffer) {
45642
- const ext = path29.extname(filePath).toLowerCase();
46161
+ const ext = path30.extname(filePath).toLowerCase();
45643
46162
  if (DEFAULT_EXCLUDE_EXTENSIONS.has(ext)) {
45644
46163
  return true;
45645
46164
  }
@@ -45775,9 +46294,9 @@ function isSymlinkLoop(realPath, visited) {
45775
46294
  return false;
45776
46295
  }
45777
46296
  function isPathWithinScope(realPath, scanDir) {
45778
- const resolvedScanDir = path29.resolve(scanDir);
45779
- const resolvedRealPath = path29.resolve(realPath);
45780
- 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}\\`);
45781
46300
  }
45782
46301
  function findScannableFiles(dir, excludeExact, excludeGlobs, scanDir, visited, stats = {
45783
46302
  skippedDirs: 0,
@@ -45803,8 +46322,8 @@ function findScannableFiles(dir, excludeExact, excludeGlobs, scanDir, visited, s
45803
46322
  return a.localeCompare(b);
45804
46323
  });
45805
46324
  for (const entry of entries) {
45806
- const fullPath = path29.join(dir, entry);
45807
- const relPath = path29.relative(scanDir, fullPath).replace(/\\/g, "/");
46325
+ const fullPath = path30.join(dir, entry);
46326
+ const relPath = path30.relative(scanDir, fullPath).replace(/\\/g, "/");
45808
46327
  if (isExcluded(entry, relPath, excludeExact, excludeGlobs)) {
45809
46328
  stats.skippedDirs++;
45810
46329
  continue;
@@ -45839,7 +46358,7 @@ function findScannableFiles(dir, excludeExact, excludeGlobs, scanDir, visited, s
45839
46358
  const subFiles = findScannableFiles(fullPath, excludeExact, excludeGlobs, scanDir, visited, stats);
45840
46359
  files.push(...subFiles);
45841
46360
  } else if (lstat.isFile()) {
45842
- const ext = path29.extname(fullPath).toLowerCase();
46361
+ const ext = path30.extname(fullPath).toLowerCase();
45843
46362
  if (!DEFAULT_EXCLUDE_EXTENSIONS.has(ext)) {
45844
46363
  files.push(fullPath);
45845
46364
  } else {
@@ -45851,7 +46370,7 @@ function findScannableFiles(dir, excludeExact, excludeGlobs, scanDir, visited, s
45851
46370
  }
45852
46371
  async function runSecretscan(directory) {
45853
46372
  try {
45854
- const result = await _internals19.secretscan.execute({ directory }, {});
46373
+ const result = await _internals20.secretscan.execute({ directory }, {});
45855
46374
  const jsonStr = typeof result === "string" ? result : result.output;
45856
46375
  return JSON.parse(jsonStr);
45857
46376
  } catch (e) {
@@ -45866,7 +46385,7 @@ async function runSecretscan(directory) {
45866
46385
  return errorResult;
45867
46386
  }
45868
46387
  }
45869
- 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;
45870
46389
  var init_secretscan = __esm(() => {
45871
46390
  init_zod();
45872
46391
  init_path_security();
@@ -46099,7 +46618,7 @@ var init_secretscan = __esm(() => {
46099
46618
  }
46100
46619
  }
46101
46620
  try {
46102
- const _scanDirRaw = path29.resolve(directory);
46621
+ const _scanDirRaw = path30.resolve(directory);
46103
46622
  const scanDir = (() => {
46104
46623
  try {
46105
46624
  return fs13.realpathSync(_scanDirRaw);
@@ -46238,7 +46757,7 @@ var init_secretscan = __esm(() => {
46238
46757
  }
46239
46758
  }
46240
46759
  });
46241
- _internals19 = {
46760
+ _internals20 = {
46242
46761
  secretscan,
46243
46762
  runSecretscan
46244
46763
  };
@@ -46246,7 +46765,7 @@ var init_secretscan = __esm(() => {
46246
46765
 
46247
46766
  // src/lang/default-backend.ts
46248
46767
  import * as fs14 from "fs";
46249
- import * as path30 from "path";
46768
+ import * as path31 from "path";
46250
46769
  function detectFileExists(dir, pattern) {
46251
46770
  if (pattern.includes("*") || pattern.includes("?")) {
46252
46771
  try {
@@ -46258,7 +46777,7 @@ function detectFileExists(dir, pattern) {
46258
46777
  }
46259
46778
  }
46260
46779
  try {
46261
- fs14.accessSync(path30.join(dir, pattern));
46780
+ fs14.accessSync(path31.join(dir, pattern));
46262
46781
  return true;
46263
46782
  } catch {
46264
46783
  return false;
@@ -46386,8 +46905,8 @@ function defaultBuildTestCommand(profile, framework, files, dir = ".", opts = {}
46386
46905
  return ["mvn", "test"];
46387
46906
  case "gradle": {
46388
46907
  const isWindows = process.platform === "win32";
46389
- const hasGradlewBat = fs14.existsSync(path30.join(dir, "gradlew.bat"));
46390
- 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"));
46391
46910
  if (hasGradlewBat && isWindows)
46392
46911
  return ["gradlew.bat", "test"];
46393
46912
  if (hasGradlew)
@@ -46404,7 +46923,7 @@ function defaultBuildTestCommand(profile, framework, files, dir = ".", opts = {}
46404
46923
  "cmake-build-release",
46405
46924
  "out"
46406
46925
  ];
46407
- 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";
46408
46927
  return ["ctest", "--test-dir", actualBuildDir];
46409
46928
  }
46410
46929
  case "swift-test":
@@ -46691,17 +47210,17 @@ async function defaultSelectBuildCommand(profile, dir) {
46691
47210
  return null;
46692
47211
  }
46693
47212
  async function defaultTestFilesFor(profile, sourceFile, dir) {
46694
- const ext = path30.extname(sourceFile);
47213
+ const ext = path31.extname(sourceFile);
46695
47214
  if (!profile.extensions.includes(ext))
46696
47215
  return [];
46697
- const base = path30.basename(sourceFile, ext);
46698
- const rel = path30.relative(dir, sourceFile);
46699
- 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);
46700
47219
  const stripSrc = relDir.replace(/^src(\/|\\)/, "");
46701
47220
  const candidates = new Set;
46702
47221
  for (const tDir of ["tests", "test", "__tests__", "spec"]) {
46703
47222
  for (const suffix of ["", "_test", ".test", "_spec", ".spec"]) {
46704
- candidates.add(path30.join(dir, tDir, stripSrc, `${base}${suffix}${ext}`));
47223
+ candidates.add(path31.join(dir, tDir, stripSrc, `${base}${suffix}${ext}`));
46705
47224
  }
46706
47225
  }
46707
47226
  const existing = [];
@@ -46742,7 +47261,7 @@ var init_default_backend = __esm(() => {
46742
47261
 
46743
47262
  // src/lang/backends/go.ts
46744
47263
  import * as fs15 from "fs";
46745
- import * as path31 from "path";
47264
+ import * as path32 from "path";
46746
47265
  function extractImports(_sourceFile, source) {
46747
47266
  const out = new Set;
46748
47267
  IMPORT_REGEX_SINGLE.lastIndex = 0;
@@ -46768,7 +47287,7 @@ function extractImports(_sourceFile, source) {
46768
47287
  async function selectFramework(dir) {
46769
47288
  let content;
46770
47289
  try {
46771
- content = fs15.readFileSync(path31.join(dir, "go.mod"), "utf-8");
47290
+ content = fs15.readFileSync(path32.join(dir, "go.mod"), "utf-8");
46772
47291
  } catch {
46773
47292
  return null;
46774
47293
  }
@@ -46789,16 +47308,16 @@ async function selectFramework(dir) {
46789
47308
  async function selectEntryPoints(dir) {
46790
47309
  const points = [];
46791
47310
  try {
46792
- fs15.accessSync(path31.join(dir, "main.go"));
47311
+ fs15.accessSync(path32.join(dir, "main.go"));
46793
47312
  points.push("main.go");
46794
47313
  } catch {}
46795
47314
  try {
46796
- const cmdDir = path31.join(dir, "cmd");
47315
+ const cmdDir = path32.join(dir, "cmd");
46797
47316
  const subdirs = fs15.readdirSync(cmdDir, { withFileTypes: true }).filter((d) => d.isDirectory());
46798
47317
  for (const sub of subdirs) {
46799
- const main = path31.join("cmd", sub.name, "main.go");
47318
+ const main = path32.join("cmd", sub.name, "main.go");
46800
47319
  try {
46801
- fs15.accessSync(path31.join(dir, main));
47320
+ fs15.accessSync(path32.join(dir, main));
46802
47321
  points.push(main);
46803
47322
  } catch {}
46804
47323
  }
@@ -46817,19 +47336,19 @@ function buildGoBackend() {
46817
47336
  selectEntryPoints
46818
47337
  };
46819
47338
  }
46820
- 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;
46821
47340
  var init_go = __esm(() => {
46822
47341
  init_default_backend();
46823
47342
  init_profiles();
46824
47343
  IMPORT_REGEX_SINGLE = /^\s*import\s+(?:[a-zA-Z_.][a-zA-Z0-9_]*\s+)?"([^"]+)"/gm;
46825
47344
  IMPORT_REGEX_GROUP = /^\s*import\s*\(([\s\S]*?)\)/gm;
46826
47345
  IMPORT_REGEX_GROUP_LINE = /(?:[a-zA-Z_.][a-zA-Z0-9_]*\s+)?"([^"]+)"/g;
46827
- _internals20 = { extractImports };
47346
+ _internals21 = { extractImports };
46828
47347
  });
46829
47348
 
46830
47349
  // src/lang/backends/python.ts
46831
47350
  import * as fs16 from "fs";
46832
- import * as path32 from "path";
47351
+ import * as path33 from "path";
46833
47352
  function parseImportTargets(rawTargets) {
46834
47353
  const cleaned = rawTargets.replace(/[()]/g, "").split(`
46835
47354
  `).map((line) => line.replace(/#.*$/, "").replace(/\\\s*$/, "")).join(" ");
@@ -46889,7 +47408,7 @@ async function selectFramework2(dir) {
46889
47408
  ];
46890
47409
  for (const candidate of ["pyproject.toml", "requirements.txt", "setup.py"]) {
46891
47410
  try {
46892
- const content = fs16.readFileSync(path32.join(dir, candidate), "utf-8");
47411
+ const content = fs16.readFileSync(path33.join(dir, candidate), "utf-8");
46893
47412
  const lower = content.toLowerCase();
46894
47413
  for (const [pkg, name] of candidates) {
46895
47414
  if (lower.includes(pkg)) {
@@ -46903,7 +47422,7 @@ async function selectFramework2(dir) {
46903
47422
  async function selectEntryPoints2(dir) {
46904
47423
  const points = new Set;
46905
47424
  try {
46906
- const content = fs16.readFileSync(path32.join(dir, "pyproject.toml"), "utf-8");
47425
+ const content = fs16.readFileSync(path33.join(dir, "pyproject.toml"), "utf-8");
46907
47426
  const scriptsBlock = content.match(/\[project\.scripts\][\s\S]*?(?=\n\[|$)/);
46908
47427
  if (scriptsBlock) {
46909
47428
  for (const line of scriptsBlock[0].split(`
@@ -46918,7 +47437,7 @@ async function selectEntryPoints2(dir) {
46918
47437
  } catch {}
46919
47438
  for (const name of ["manage.py", "main.py", "app.py", "__main__.py"]) {
46920
47439
  try {
46921
- fs16.accessSync(path32.join(dir, name));
47440
+ fs16.accessSync(path33.join(dir, name));
46922
47441
  points.add(name);
46923
47442
  } catch {}
46924
47443
  }
@@ -46936,18 +47455,18 @@ function buildPythonBackend() {
46936
47455
  selectEntryPoints: selectEntryPoints2
46937
47456
  };
46938
47457
  }
46939
- 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;
46940
47459
  var init_python = __esm(() => {
46941
47460
  init_default_backend();
46942
47461
  init_profiles();
46943
47462
  IMPORT_REGEX_FROM_WITH_TARGETS = /^\s*from\s+(\.*[\w.]*)\s+import\s+(\([^)]*\)|[^\n#]+)/gm;
46944
47463
  IMPORT_REGEX_IMPORT = /^\s*import\s+([^\n#]+)/gm;
46945
- _internals21 = { extractImports: extractImports2 };
47464
+ _internals22 = { extractImports: extractImports2 };
46946
47465
  });
46947
47466
 
46948
47467
  // src/test-impact/analyzer.ts
46949
47468
  import fs17 from "fs";
46950
- import path33 from "path";
47469
+ import path34 from "path";
46951
47470
  function normalizePath(p) {
46952
47471
  return p.replace(/\\/g, "/");
46953
47472
  }
@@ -46968,8 +47487,8 @@ function resolveRelativeImport(fromDir, importPath) {
46968
47487
  if (!importPath.startsWith(".")) {
46969
47488
  return null;
46970
47489
  }
46971
- const resolved = path33.resolve(fromDir, importPath);
46972
- if (path33.extname(resolved)) {
47490
+ const resolved = path34.resolve(fromDir, importPath);
47491
+ if (path34.extname(resolved)) {
46973
47492
  if (fs17.existsSync(resolved) && fs17.statSync(resolved).isFile()) {
46974
47493
  return normalizePath(resolved);
46975
47494
  }
@@ -46989,20 +47508,20 @@ function resolvePythonImport(fromDir, module) {
46989
47508
  const leadingDots = module.match(/^\.+/)?.[0].length ?? 0;
46990
47509
  let baseDir = fromDir;
46991
47510
  for (let i = 1;i < leadingDots; i++) {
46992
- baseDir = path33.dirname(baseDir);
47511
+ baseDir = path34.dirname(baseDir);
46993
47512
  }
46994
47513
  const rest = module.slice(leadingDots);
46995
47514
  if (rest.length === 0) {
46996
- const initPath = path33.join(baseDir, "__init__.py");
47515
+ const initPath = path34.join(baseDir, "__init__.py");
46997
47516
  if (fs17.existsSync(initPath) && fs17.statSync(initPath).isFile()) {
46998
47517
  return normalizePath(initPath);
46999
47518
  }
47000
47519
  return null;
47001
47520
  }
47002
- const subpath = rest.replace(/\./g, path33.sep);
47521
+ const subpath = rest.replace(/\./g, path34.sep);
47003
47522
  const candidates = [
47004
- `${path33.join(baseDir, subpath)}.py`,
47005
- path33.join(baseDir, subpath, "__init__.py")
47523
+ `${path34.join(baseDir, subpath)}.py`,
47524
+ path34.join(baseDir, subpath, "__init__.py")
47006
47525
  ];
47007
47526
  for (const c of candidates) {
47008
47527
  if (fs17.existsSync(c) && fs17.statSync(c).isFile())
@@ -47011,7 +47530,7 @@ function resolvePythonImport(fromDir, module) {
47011
47530
  return null;
47012
47531
  }
47013
47532
  function findGoModule(fromDir) {
47014
- const resolved = path33.resolve(fromDir);
47533
+ const resolved = path34.resolve(fromDir);
47015
47534
  let cur = resolved;
47016
47535
  const walked = [];
47017
47536
  for (let i = 0;i < 16; i++) {
@@ -47023,7 +47542,7 @@ function findGoModule(fromDir) {
47023
47542
  }
47024
47543
  walked.push(cur);
47025
47544
  try {
47026
- const goMod = path33.join(cur, "go.mod");
47545
+ const goMod = path34.join(cur, "go.mod");
47027
47546
  const content = fs17.readFileSync(goMod, "utf-8");
47028
47547
  const moduleMatch = content.match(/^\s*module\s+"?([^"\s/]+(?:\/[^"\s]+)*)"?/m);
47029
47548
  if (moduleMatch) {
@@ -47034,10 +47553,10 @@ function findGoModule(fromDir) {
47034
47553
  }
47035
47554
  } catch {}
47036
47555
  try {
47037
- fs17.accessSync(path33.join(cur, ".git"));
47556
+ fs17.accessSync(path34.join(cur, ".git"));
47038
47557
  break;
47039
47558
  } catch {}
47040
- const parent = path33.dirname(cur);
47559
+ const parent = path34.dirname(cur);
47041
47560
  if (parent === cur)
47042
47561
  break;
47043
47562
  cur = parent;
@@ -47049,12 +47568,12 @@ function findGoModule(fromDir) {
47049
47568
  function resolveGoImport(fromDir, importPath) {
47050
47569
  let dir = null;
47051
47570
  if (importPath.startsWith(".")) {
47052
- dir = path33.resolve(fromDir, importPath);
47571
+ dir = path34.resolve(fromDir, importPath);
47053
47572
  } else {
47054
47573
  const mod = findGoModule(fromDir);
47055
47574
  if (mod && (importPath === mod.modulePath || importPath.startsWith(`${mod.modulePath}/`))) {
47056
47575
  const subpath = importPath.slice(mod.modulePath.length);
47057
- dir = path33.join(mod.moduleRoot, subpath);
47576
+ dir = path34.join(mod.moduleRoot, subpath);
47058
47577
  }
47059
47578
  }
47060
47579
  if (dir === null)
@@ -47062,7 +47581,7 @@ function resolveGoImport(fromDir, importPath) {
47062
47581
  if (!fs17.existsSync(dir) || !fs17.statSync(dir).isDirectory())
47063
47582
  return [];
47064
47583
  try {
47065
- 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)));
47066
47585
  } catch {
47067
47586
  return [];
47068
47587
  }
@@ -47101,15 +47620,15 @@ function findTestFilesSync(cwd) {
47101
47620
  for (const entry of entries) {
47102
47621
  if (entry.isDirectory()) {
47103
47622
  if (!skipDirs.has(entry.name)) {
47104
- walk(path33.join(dir, entry.name), visitedInodes);
47623
+ walk(path34.join(dir, entry.name), visitedInodes);
47105
47624
  }
47106
47625
  } else if (entry.isFile()) {
47107
47626
  const name = entry.name;
47108
47627
  const isTsTest = /\.(test|spec)\.(ts|tsx|js|jsx)$/.test(name) || dir.includes("__tests__") && /\.(ts|tsx|js|jsx)$/.test(name);
47109
- 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");
47110
47629
  const isGoTest = /.+_test\.go$/.test(name);
47111
47630
  if (isTsTest || isPyTest || isGoTest) {
47112
- testFiles.push(normalizePath(path33.join(dir, entry.name)));
47631
+ testFiles.push(normalizePath(path34.join(dir, entry.name)));
47113
47632
  }
47114
47633
  }
47115
47634
  }
@@ -47134,8 +47653,8 @@ function extractImports3(content) {
47134
47653
  ];
47135
47654
  }
47136
47655
  function addImpactEdgesForTestFile(testFile, content, impactMap) {
47137
- const ext = path33.extname(testFile).toLowerCase();
47138
- const testDir = path33.dirname(testFile);
47656
+ const ext = path34.extname(testFile).toLowerCase();
47657
+ const testDir = path34.dirname(testFile);
47139
47658
  function addEdge(source) {
47140
47659
  if (!impactMap[source])
47141
47660
  impactMap[source] = [];
@@ -47153,7 +47672,7 @@ function addImpactEdgesForTestFile(testFile, content, impactMap) {
47153
47672
  return;
47154
47673
  }
47155
47674
  if (PYTHON_EXTENSIONS.has(ext)) {
47156
- const modules = _internals21.extractImports(testFile, content);
47675
+ const modules = _internals22.extractImports(testFile, content);
47157
47676
  for (const mod of modules) {
47158
47677
  const resolved = resolvePythonImport(testDir, mod);
47159
47678
  if (resolved !== null)
@@ -47162,7 +47681,7 @@ function addImpactEdgesForTestFile(testFile, content, impactMap) {
47162
47681
  return;
47163
47682
  }
47164
47683
  if (GO_EXTENSIONS.has(ext)) {
47165
- const imports = _internals20.extractImports(testFile, content);
47684
+ const imports = _internals21.extractImports(testFile, content);
47166
47685
  for (const importPath of imports) {
47167
47686
  const sourceFiles = resolveGoImport(testDir, importPath);
47168
47687
  for (const source of sourceFiles)
@@ -47189,12 +47708,12 @@ async function buildImpactMapInternal(cwd) {
47189
47708
  return impactMap;
47190
47709
  }
47191
47710
  async function buildImpactMap(cwd) {
47192
- const impactMap = await _internals22.buildImpactMapInternal(cwd);
47193
- await _internals22.saveImpactMap(cwd, impactMap);
47711
+ const impactMap = await _internals23.buildImpactMapInternal(cwd);
47712
+ await _internals23.saveImpactMap(cwd, impactMap);
47194
47713
  return impactMap;
47195
47714
  }
47196
47715
  async function loadImpactMap(cwd, options) {
47197
- const cachePath = path33.join(cwd, ".swarm", "cache", "impact-map.json");
47716
+ const cachePath = path34.join(cwd, ".swarm", "cache", "impact-map.json");
47198
47717
  if (fs17.existsSync(cachePath)) {
47199
47718
  try {
47200
47719
  const content = fs17.readFileSync(cachePath, "utf-8");
@@ -47204,7 +47723,7 @@ async function loadImpactMap(cwd, options) {
47204
47723
  const hasValidValues = Object.values(map3).every((v) => Array.isArray(v) && v.every((item) => typeof item === "string"));
47205
47724
  if (hasValidValues) {
47206
47725
  const generatedAt = new Date(data.generatedAt).getTime();
47207
- if (!_internals22.isCacheStale(map3, generatedAt)) {
47726
+ if (!_internals23.isCacheStale(map3, generatedAt)) {
47208
47727
  return map3;
47209
47728
  }
47210
47729
  if (options?.skipRebuild) {
@@ -47224,15 +47743,15 @@ async function loadImpactMap(cwd, options) {
47224
47743
  if (options?.skipRebuild) {
47225
47744
  return {};
47226
47745
  }
47227
- return _internals22.buildImpactMap(cwd);
47746
+ return _internals23.buildImpactMap(cwd);
47228
47747
  }
47229
47748
  async function saveImpactMap(cwd, impactMap) {
47230
- if (!path33.isAbsolute(cwd)) {
47749
+ if (!path34.isAbsolute(cwd)) {
47231
47750
  throw new Error(`saveImpactMap requires an absolute project root path, got: "${cwd}"`);
47232
47751
  }
47233
- _internals22.validateProjectRoot(cwd);
47234
- const cacheDir2 = path33.join(cwd, ".swarm", "cache");
47235
- 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");
47236
47755
  if (!fs17.existsSync(cacheDir2)) {
47237
47756
  fs17.mkdirSync(cacheDir2, { recursive: true });
47238
47757
  }
@@ -47254,7 +47773,7 @@ async function analyzeImpact(changedFiles, cwd, budget) {
47254
47773
  };
47255
47774
  }
47256
47775
  const validFiles = changedFiles.filter((f) => typeof f === "string" && f.length > 0 && !f.includes("\x00"));
47257
- const impactMap = await _internals22.loadImpactMap(cwd);
47776
+ const impactMap = await _internals23.loadImpactMap(cwd);
47258
47777
  const impactedTestsSet = new Set;
47259
47778
  const untestedFiles = [];
47260
47779
  let visitedCount = 0;
@@ -47264,7 +47783,7 @@ async function analyzeImpact(changedFiles, cwd, budget) {
47264
47783
  budgetExceeded = true;
47265
47784
  break;
47266
47785
  }
47267
- const normalizedChanged = normalizePath(path33.resolve(changedFile));
47786
+ const normalizedChanged = normalizePath(path34.resolve(changedFile));
47268
47787
  const tests = impactMap[normalizedChanged];
47269
47788
  if (tests && tests.length > 0) {
47270
47789
  for (const test of tests) {
@@ -47321,7 +47840,7 @@ async function analyzeImpact(changedFiles, cwd, budget) {
47321
47840
  budgetExceeded
47322
47841
  };
47323
47842
  }
47324
- 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;
47325
47844
  var init_analyzer = __esm(() => {
47326
47845
  init_manager2();
47327
47846
  init_go();
@@ -47334,7 +47853,7 @@ var init_analyzer = __esm(() => {
47334
47853
  GO_EXTENSIONS = new Set([".go"]);
47335
47854
  EXTENSIONS_TO_TRY = [".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs"];
47336
47855
  goModuleCache = new Map;
47337
- _internals22 = {
47856
+ _internals23 = {
47338
47857
  validateProjectRoot,
47339
47858
  normalizePath,
47340
47859
  isCacheStale,
@@ -47557,15 +48076,15 @@ var FLAKY_THRESHOLD = 0.3, MIN_RUNS_FOR_QUARANTINE = 5, MAX_HISTORY_RUNS = 20;
47557
48076
 
47558
48077
  // src/test-impact/history-store.ts
47559
48078
  import fs18 from "fs";
47560
- import path34 from "path";
48079
+ import path35 from "path";
47561
48080
  function getHistoryPath(workingDir) {
47562
48081
  if (!workingDir) {
47563
48082
  throw new Error("getHistoryPath requires a working directory \u2014 project root must be provided by the caller");
47564
48083
  }
47565
- if (!path34.isAbsolute(workingDir)) {
48084
+ if (!path35.isAbsolute(workingDir)) {
47566
48085
  throw new Error(`getHistoryPath requires an absolute project root path, got: "${workingDir}"`);
47567
48086
  }
47568
- return path34.join(workingDir, ".swarm", "cache", "test-history.jsonl");
48087
+ return path35.join(workingDir, ".swarm", "cache", "test-history.jsonl");
47569
48088
  }
47570
48089
  function sanitizeErrorMessage(errorMessage) {
47571
48090
  if (errorMessage === undefined) {
@@ -47652,8 +48171,8 @@ function batchAppendTestRuns(records, workingDir) {
47652
48171
  }
47653
48172
  }
47654
48173
  const historyPath = getHistoryPath(workingDir);
47655
- const historyDir = path34.dirname(historyPath);
47656
- _internals23.validateProjectRoot(workingDir);
48174
+ const historyDir = path35.dirname(historyPath);
48175
+ _internals24.validateProjectRoot(workingDir);
47657
48176
  if (!fs18.existsSync(historyDir)) {
47658
48177
  fs18.mkdirSync(historyDir, { recursive: true });
47659
48178
  }
@@ -47733,7 +48252,7 @@ function getAllHistory(workingDir) {
47733
48252
  records.sort((a, b) => new Date(a.timestamp).getTime() - new Date(b.timestamp).getTime());
47734
48253
  return records;
47735
48254
  }
47736
- 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;
47737
48256
  var init_history_store = __esm(() => {
47738
48257
  init_manager2();
47739
48258
  DANGEROUS_PROPERTY_NAMES = new Set([
@@ -47741,14 +48260,14 @@ var init_history_store = __esm(() => {
47741
48260
  "constructor",
47742
48261
  "prototype"
47743
48262
  ]);
47744
- _internals23 = {
48263
+ _internals24 = {
47745
48264
  validateProjectRoot
47746
48265
  };
47747
48266
  });
47748
48267
 
47749
48268
  // src/tools/resolve-working-directory.ts
47750
48269
  import * as fs19 from "fs";
47751
- import * as path35 from "path";
48270
+ import * as path36 from "path";
47752
48271
  function resolveWorkingDirectory(workingDirectory, fallbackDirectory) {
47753
48272
  if (workingDirectory == null || workingDirectory === "") {
47754
48273
  return { success: true, directory: fallbackDirectory };
@@ -47768,15 +48287,15 @@ function resolveWorkingDirectory(workingDirectory, fallbackDirectory) {
47768
48287
  };
47769
48288
  }
47770
48289
  }
47771
- const normalizedDir = path35.normalize(workingDirectory);
47772
- const pathParts = normalizedDir.split(path35.sep);
48290
+ const normalizedDir = path36.normalize(workingDirectory);
48291
+ const pathParts = normalizedDir.split(path36.sep);
47773
48292
  if (pathParts.includes("..")) {
47774
48293
  return {
47775
48294
  success: false,
47776
48295
  message: "Invalid working_directory: path traversal sequences (..) are not allowed"
47777
48296
  };
47778
48297
  }
47779
- const resolvedDir = path35.resolve(normalizedDir);
48298
+ const resolvedDir = path36.resolve(normalizedDir);
47780
48299
  let statResult;
47781
48300
  try {
47782
48301
  statResult = fs19.statSync(resolvedDir);
@@ -47792,7 +48311,7 @@ function resolveWorkingDirectory(workingDirectory, fallbackDirectory) {
47792
48311
  message: `Invalid working_directory: path "${resolvedDir}" is not a directory`
47793
48312
  };
47794
48313
  }
47795
- const resolvedFallback = path35.resolve(fallbackDirectory);
48314
+ const resolvedFallback = path36.resolve(fallbackDirectory);
47796
48315
  let fallbackExists = false;
47797
48316
  try {
47798
48317
  fs19.statSync(resolvedFallback);
@@ -47802,7 +48321,7 @@ function resolveWorkingDirectory(workingDirectory, fallbackDirectory) {
47802
48321
  }
47803
48322
  if (workingDirectory != null && workingDirectory !== "") {
47804
48323
  if (fallbackExists) {
47805
- const isSubdirectory = resolvedDir.startsWith(resolvedFallback + path35.sep);
48324
+ const isSubdirectory = resolvedDir.startsWith(resolvedFallback + path36.sep);
47806
48325
  if (isSubdirectory) {
47807
48326
  return {
47808
48327
  success: false,
@@ -47857,17 +48376,17 @@ var init_registry_backend = __esm(() => {
47857
48376
 
47858
48377
  // src/lang/backends/typescript.ts
47859
48378
  import * as fs20 from "fs";
47860
- import * as path36 from "path";
48379
+ import * as path37 from "path";
47861
48380
  function readPackageJsonRaw(dir) {
47862
48381
  try {
47863
- const content = fs20.readFileSync(path36.join(dir, "package.json"), "utf-8");
48382
+ const content = fs20.readFileSync(path37.join(dir, "package.json"), "utf-8");
47864
48383
  return JSON.parse(content);
47865
48384
  } catch {
47866
48385
  return null;
47867
48386
  }
47868
48387
  }
47869
48388
  function readPackageJson(dir) {
47870
- return _internals24.readPackageJsonRaw(dir);
48389
+ return _internals25.readPackageJsonRaw(dir);
47871
48390
  }
47872
48391
  function readPackageJsonTestScript(dir) {
47873
48392
  return readPackageJson(dir)?.scripts?.test ?? null;
@@ -48037,7 +48556,7 @@ function buildTypescriptBackend() {
48037
48556
  selectEntryPoints: selectEntryPoints3
48038
48557
  };
48039
48558
  }
48040
- 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;
48041
48560
  var init_typescript = __esm(() => {
48042
48561
  init_default_backend();
48043
48562
  init_profiles();
@@ -48046,7 +48565,7 @@ var init_typescript = __esm(() => {
48046
48565
  IMPORT_REGEX_REQUIRE2 = /require\s*\(\s*['"]([^'"]+)['"]\s*\)/g;
48047
48566
  IMPORT_REGEX_DYNAMIC = /import\s*\(\s*['"]([^'"]+)['"]\s*\)/g;
48048
48567
  IMPORT_REGEX_REEXPORT2 = /export\s+(?:\{[^}]*\}|\*)\s+from\s+['"]([^'"]+)['"]/g;
48049
- _internals24 = {
48568
+ _internals25 = {
48050
48569
  readPackageJsonRaw,
48051
48570
  readPackageJsonTestScript,
48052
48571
  frameworkFromScriptsTest
@@ -48077,10 +48596,10 @@ __export(exports_dispatch, {
48077
48596
  pickedProfiles: () => pickedProfiles,
48078
48597
  pickBackend: () => pickBackend,
48079
48598
  clearDispatchCache: () => clearDispatchCache,
48080
- _internals: () => _internals25
48599
+ _internals: () => _internals26
48081
48600
  });
48082
48601
  import * as fs21 from "fs";
48083
- import * as path37 from "path";
48602
+ import * as path38 from "path";
48084
48603
  function safeReaddirSet(dir) {
48085
48604
  try {
48086
48605
  return new Set(fs21.readdirSync(dir));
@@ -48097,14 +48616,14 @@ function manifestHash(dir) {
48097
48616
  if (!entries.has(name))
48098
48617
  continue;
48099
48618
  try {
48100
- const stat3 = fs21.statSync(path37.join(dir, name));
48619
+ const stat3 = fs21.statSync(path38.join(dir, name));
48101
48620
  parts.push(`${name}:${stat3.size}:${stat3.mtimeMs}:${stat3.ino}`);
48102
48621
  } catch {}
48103
48622
  }
48104
48623
  return parts.join("|");
48105
48624
  }
48106
48625
  function findManifestRoot(start) {
48107
- const resolved = path37.resolve(start);
48626
+ const resolved = path38.resolve(start);
48108
48627
  const cached3 = manifestRootCache.get(resolved);
48109
48628
  if (cached3 !== undefined)
48110
48629
  return cached3;
@@ -48123,7 +48642,7 @@ function findManifestRoot(start) {
48123
48642
  return cur;
48124
48643
  }
48125
48644
  }
48126
- const parent = path37.dirname(cur);
48645
+ const parent = path38.dirname(cur);
48127
48646
  if (parent === cur)
48128
48647
  break;
48129
48648
  cur = parent;
@@ -48132,7 +48651,7 @@ function findManifestRoot(start) {
48132
48651
  return start;
48133
48652
  }
48134
48653
  function evictIfNeeded() {
48135
- if (cache.size <= _internals25.cacheCapacity)
48654
+ if (cache.size <= _internals26.cacheCapacity)
48136
48655
  return;
48137
48656
  let oldestKey;
48138
48657
  let oldestOrder = Infinity;
@@ -48163,7 +48682,7 @@ async function pickBackend(dir) {
48163
48682
  evictIfNeeded();
48164
48683
  return null;
48165
48684
  }
48166
- const profiles = await _internals25.detectProjectLanguages(root);
48685
+ const profiles = await _internals26.detectProjectLanguages(root);
48167
48686
  if (profiles.length === 0) {
48168
48687
  cache.set(cacheKey, {
48169
48688
  hash: hash3,
@@ -48195,12 +48714,12 @@ function clearDispatchCache() {
48195
48714
  manifestRootCache.clear();
48196
48715
  insertCounter = 0;
48197
48716
  }
48198
- var _internals25, cache, insertCounter = 0, MANIFEST_FILES, _MANIFEST_SET, manifestRootCache;
48717
+ var _internals26, cache, insertCounter = 0, MANIFEST_FILES, _MANIFEST_SET, manifestRootCache;
48199
48718
  var init_dispatch = __esm(() => {
48200
48719
  init_backends();
48201
48720
  init_detector();
48202
48721
  init_registry_backend();
48203
- _internals25 = {
48722
+ _internals26 = {
48204
48723
  detectProjectLanguages,
48205
48724
  cacheCapacity: 64
48206
48725
  };
@@ -48233,13 +48752,13 @@ var init_dispatch = __esm(() => {
48233
48752
 
48234
48753
  // src/tools/test-runner.ts
48235
48754
  import * as fs22 from "fs";
48236
- import * as path38 from "path";
48755
+ import * as path39 from "path";
48237
48756
  async function estimateFanOut(sourceFiles, cwd) {
48238
48757
  try {
48239
48758
  const impactMap = await loadImpactMap(cwd, { skipRebuild: true });
48240
48759
  const uniqueTestFiles = new Set;
48241
48760
  for (const sourceFile of sourceFiles) {
48242
- const resolvedPath = path38.resolve(cwd, sourceFile);
48761
+ const resolvedPath = path39.resolve(cwd, sourceFile);
48243
48762
  const normalizedPath = resolvedPath.replace(/\\/g, "/");
48244
48763
  const testFiles = impactMap[normalizedPath];
48245
48764
  if (testFiles) {
@@ -48317,14 +48836,14 @@ function hasDevDependency(devDeps, ...patterns) {
48317
48836
  return hasPackageJsonDependency(devDeps, ...patterns);
48318
48837
  }
48319
48838
  function detectGoTest(cwd) {
48320
- return fs22.existsSync(path38.join(cwd, "go.mod")) && isCommandAvailable("go");
48839
+ return fs22.existsSync(path39.join(cwd, "go.mod")) && isCommandAvailable("go");
48321
48840
  }
48322
48841
  function detectJavaMaven(cwd) {
48323
- return fs22.existsSync(path38.join(cwd, "pom.xml")) && isCommandAvailable("mvn");
48842
+ return fs22.existsSync(path39.join(cwd, "pom.xml")) && isCommandAvailable("mvn");
48324
48843
  }
48325
48844
  function detectGradle(cwd) {
48326
- const hasBuildFile = fs22.existsSync(path38.join(cwd, "build.gradle")) || fs22.existsSync(path38.join(cwd, "build.gradle.kts"));
48327
- 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"));
48328
48847
  return hasBuildFile && (hasGradlew || isCommandAvailable("gradle"));
48329
48848
  }
48330
48849
  function detectDotnetTest(cwd) {
@@ -48337,25 +48856,25 @@ function detectDotnetTest(cwd) {
48337
48856
  }
48338
48857
  }
48339
48858
  function detectCTest(cwd) {
48340
- const hasSource = fs22.existsSync(path38.join(cwd, "CMakeLists.txt"));
48341
- 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"));
48342
48861
  return (hasSource || hasBuildCache) && isCommandAvailable("ctest");
48343
48862
  }
48344
48863
  function detectSwiftTest(cwd) {
48345
- return fs22.existsSync(path38.join(cwd, "Package.swift")) && isCommandAvailable("swift");
48864
+ return fs22.existsSync(path39.join(cwd, "Package.swift")) && isCommandAvailable("swift");
48346
48865
  }
48347
48866
  function detectDartTest(cwd) {
48348
- 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"));
48349
48868
  }
48350
48869
  function detectRSpec(cwd) {
48351
- const hasRSpecFile = fs22.existsSync(path38.join(cwd, ".rspec"));
48352
- const hasGemfile = fs22.existsSync(path38.join(cwd, "Gemfile"));
48353
- 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"));
48354
48873
  const hasRSpec = hasRSpecFile || hasGemfile && hasSpecDir;
48355
48874
  return hasRSpec && (isCommandAvailable("bundle") || isCommandAvailable("rspec"));
48356
48875
  }
48357
48876
  function detectMinitest(cwd) {
48358
- 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");
48359
48878
  }
48360
48879
  async function detectTestFrameworkViaDispatch(cwd) {
48361
48880
  try {
@@ -48417,7 +48936,7 @@ async function parseTestOutputViaDispatch(framework, output, baseDir) {
48417
48936
  async function detectTestFramework(cwd) {
48418
48937
  const baseDir = cwd;
48419
48938
  try {
48420
- const packageJsonPath = path38.join(baseDir, "package.json");
48939
+ const packageJsonPath = path39.join(baseDir, "package.json");
48421
48940
  if (fs22.existsSync(packageJsonPath)) {
48422
48941
  const content = fs22.readFileSync(packageJsonPath, "utf-8");
48423
48942
  const pkg = JSON.parse(content);
@@ -48438,16 +48957,16 @@ async function detectTestFramework(cwd) {
48438
48957
  return "jest";
48439
48958
  if (hasDevDependency(devDeps, "mocha", "@types/mocha"))
48440
48959
  return "mocha";
48441
- 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"))) {
48442
48961
  if (scripts.test?.includes("bun"))
48443
48962
  return "bun";
48444
48963
  }
48445
48964
  }
48446
48965
  } catch {}
48447
48966
  try {
48448
- const pyprojectTomlPath = path38.join(baseDir, "pyproject.toml");
48449
- const setupCfgPath = path38.join(baseDir, "setup.cfg");
48450
- 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");
48451
48970
  if (fs22.existsSync(pyprojectTomlPath)) {
48452
48971
  const content = fs22.readFileSync(pyprojectTomlPath, "utf-8");
48453
48972
  if (content.includes("[tool.pytest"))
@@ -48467,7 +48986,7 @@ async function detectTestFramework(cwd) {
48467
48986
  }
48468
48987
  } catch {}
48469
48988
  try {
48470
- const cargoTomlPath = path38.join(baseDir, "Cargo.toml");
48989
+ const cargoTomlPath = path39.join(baseDir, "Cargo.toml");
48471
48990
  if (fs22.existsSync(cargoTomlPath)) {
48472
48991
  const content = fs22.readFileSync(cargoTomlPath, "utf-8");
48473
48992
  if (content.includes("[dev-dependencies]")) {
@@ -48478,9 +48997,9 @@ async function detectTestFramework(cwd) {
48478
48997
  }
48479
48998
  } catch {}
48480
48999
  try {
48481
- const pesterConfigPath = path38.join(baseDir, "pester.config.ps1");
48482
- const pesterConfigJsonPath = path38.join(baseDir, "pester.config.ps1.json");
48483
- 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");
48484
49003
  if (fs22.existsSync(pesterConfigPath) || fs22.existsSync(pesterConfigJsonPath) || fs22.existsSync(pesterPs1Path)) {
48485
49004
  return "pester";
48486
49005
  }
@@ -48509,12 +49028,12 @@ function isTestDirectoryPath(normalizedPath) {
48509
49028
  return normalizedPath.split("/").some((segment) => TEST_DIRECTORY_NAMES.includes(segment));
48510
49029
  }
48511
49030
  function resolveWorkspacePath(file3, workingDir) {
48512
- return path38.isAbsolute(file3) ? path38.resolve(file3) : path38.resolve(workingDir, file3);
49031
+ return path39.isAbsolute(file3) ? path39.resolve(file3) : path39.resolve(workingDir, file3);
48513
49032
  }
48514
49033
  function toWorkspaceOutputPath(absolutePath, workingDir, preferRelative) {
48515
49034
  if (!preferRelative)
48516
49035
  return absolutePath;
48517
- return path38.relative(workingDir, absolutePath);
49036
+ return path39.relative(workingDir, absolutePath);
48518
49037
  }
48519
49038
  function dedupePush(target, value) {
48520
49039
  if (!target.includes(value)) {
@@ -48551,18 +49070,18 @@ function buildLanguageSpecificTestNames(nameWithoutExt, ext) {
48551
49070
  }
48552
49071
  }
48553
49072
  function getRepoLevelCandidateDirectories(workingDir, relativePath, ext) {
48554
- const relativeDir = path38.dirname(relativePath);
49073
+ const relativeDir = path39.dirname(relativePath);
48555
49074
  const nestedRelativeDir = relativeDir === "." ? "" : relativeDir;
48556
49075
  const directories = TEST_DIRECTORY_NAMES.flatMap((dirName) => {
48557
- const rootDir = path38.join(workingDir, dirName);
48558
- return nestedRelativeDir ? [rootDir, path38.join(rootDir, nestedRelativeDir)] : [rootDir];
49076
+ const rootDir = path39.join(workingDir, dirName);
49077
+ return nestedRelativeDir ? [rootDir, path39.join(rootDir, nestedRelativeDir)] : [rootDir];
48559
49078
  });
48560
49079
  const normalizedRelativePath = relativePath.replace(/\\/g, "/");
48561
49080
  if (ext === ".java" && normalizedRelativePath.startsWith("src/main/java/")) {
48562
- 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))));
48563
49082
  }
48564
49083
  if ((ext === ".kt" || ext === ".java") && normalizedRelativePath.startsWith("src/main/kotlin/")) {
48565
- 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))));
48566
49085
  }
48567
49086
  return [...new Set(directories)];
48568
49087
  }
@@ -48590,23 +49109,23 @@ function isLanguageSpecificTestFile(basename6) {
48590
49109
  }
48591
49110
  function isConventionTestFilePath(filePath) {
48592
49111
  const normalizedPath = filePath.replace(/\\/g, "/");
48593
- const basename6 = path38.basename(filePath);
49112
+ const basename6 = path39.basename(filePath);
48594
49113
  return hasCompoundTestExtension(basename6) || basename6.includes(".spec.") || basename6.includes(".test.") || isLanguageSpecificTestFile(basename6) || isTestDirectoryPath(normalizedPath);
48595
49114
  }
48596
49115
  function getTestFilesFromConvention(sourceFiles, workingDir = process.cwd()) {
48597
49116
  const testFiles = [];
48598
49117
  for (const file3 of sourceFiles) {
48599
49118
  const absoluteFile = resolveWorkspacePath(file3, workingDir);
48600
- const relativeFile = path38.relative(workingDir, absoluteFile);
48601
- const basename6 = path38.basename(absoluteFile);
48602
- const dirname17 = path38.dirname(absoluteFile);
48603
- 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);
48604
49123
  if (isConventionTestFilePath(relativeFile) || isConventionTestFilePath(file3)) {
48605
49124
  dedupePush(testFiles, toWorkspaceOutputPath(absoluteFile, workingDir, preferRelativeOutput));
48606
49125
  continue;
48607
49126
  }
48608
49127
  const nameWithoutExt = basename6.replace(/\.[^.]+$/, "");
48609
- const ext = path38.extname(basename6);
49128
+ const ext = path39.extname(basename6);
48610
49129
  const genericTestNames = [
48611
49130
  `${nameWithoutExt}.spec${ext}`,
48612
49131
  `${nameWithoutExt}.test${ext}`
@@ -48615,7 +49134,7 @@ function getTestFilesFromConvention(sourceFiles, workingDir = process.cwd()) {
48615
49134
  const colocatedCandidates = [
48616
49135
  ...genericTestNames,
48617
49136
  ...languageSpecificTestNames
48618
- ].map((candidateName) => path38.join(dirname17, candidateName));
49137
+ ].map((candidateName) => path39.join(dirname17, candidateName));
48619
49138
  const testDirectoryNames = [
48620
49139
  basename6,
48621
49140
  ...genericTestNames,
@@ -48624,8 +49143,8 @@ function getTestFilesFromConvention(sourceFiles, workingDir = process.cwd()) {
48624
49143
  const repoLevelDirectories = getRepoLevelCandidateDirectories(workingDir, relativeFile, ext);
48625
49144
  const possibleTestFiles = [
48626
49145
  ...colocatedCandidates,
48627
- ...TEST_DIRECTORY_NAMES.flatMap((dirName) => testDirectoryNames.map((candidateName) => path38.join(dirname17, dirName, candidateName))),
48628
- ...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)))
48629
49148
  ];
48630
49149
  for (const testFile of possibleTestFiles) {
48631
49150
  if (fs22.existsSync(testFile)) {
@@ -48646,7 +49165,7 @@ async function getTestFilesFromGraph(sourceFiles, workingDir) {
48646
49165
  try {
48647
49166
  const absoluteTestFile = resolveWorkspacePath(testFile, workingDir);
48648
49167
  const content = fs22.readFileSync(absoluteTestFile, "utf-8");
48649
- const testDir = path38.dirname(absoluteTestFile);
49168
+ const testDir = path39.dirname(absoluteTestFile);
48650
49169
  const importRegex = /import\s+.*?\s+from\s+['"]([^'"]+)['"]/g;
48651
49170
  let match;
48652
49171
  match = importRegex.exec(content);
@@ -48654,8 +49173,8 @@ async function getTestFilesFromGraph(sourceFiles, workingDir) {
48654
49173
  const importPath = match[1];
48655
49174
  let resolvedImport;
48656
49175
  if (importPath.startsWith(".")) {
48657
- resolvedImport = path38.resolve(testDir, importPath);
48658
- const existingExt = path38.extname(resolvedImport);
49176
+ resolvedImport = path39.resolve(testDir, importPath);
49177
+ const existingExt = path39.extname(resolvedImport);
48659
49178
  if (!existingExt) {
48660
49179
  for (const extToTry of [
48661
49180
  ".ts",
@@ -48675,12 +49194,12 @@ async function getTestFilesFromGraph(sourceFiles, workingDir) {
48675
49194
  } else {
48676
49195
  continue;
48677
49196
  }
48678
- const importBasename = path38.basename(resolvedImport, path38.extname(resolvedImport));
48679
- const importDir = path38.dirname(resolvedImport);
49197
+ const importBasename = path39.basename(resolvedImport, path39.extname(resolvedImport));
49198
+ const importDir = path39.dirname(resolvedImport);
48680
49199
  for (const sourceFile of absoluteSourceFiles) {
48681
- const sourceDir = path38.dirname(sourceFile);
48682
- const sourceBasename = path38.basename(sourceFile, path38.extname(sourceFile));
48683
- 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");
48684
49203
  if (resolvedImport === sourceFile || importBasename === sourceBasename && isRelatedDir) {
48685
49204
  dedupePush(testFiles, testFile);
48686
49205
  break;
@@ -48693,8 +49212,8 @@ async function getTestFilesFromGraph(sourceFiles, workingDir) {
48693
49212
  while (match !== null) {
48694
49213
  const importPath = match[1];
48695
49214
  if (importPath.startsWith(".")) {
48696
- let resolvedImport = path38.resolve(testDir, importPath);
48697
- const existingExt = path38.extname(resolvedImport);
49215
+ let resolvedImport = path39.resolve(testDir, importPath);
49216
+ const existingExt = path39.extname(resolvedImport);
48698
49217
  if (!existingExt) {
48699
49218
  for (const extToTry of [
48700
49219
  ".ts",
@@ -48711,12 +49230,12 @@ async function getTestFilesFromGraph(sourceFiles, workingDir) {
48711
49230
  }
48712
49231
  }
48713
49232
  }
48714
- const importDir = path38.dirname(resolvedImport);
48715
- const importBasename = path38.basename(resolvedImport, path38.extname(resolvedImport));
49233
+ const importDir = path39.dirname(resolvedImport);
49234
+ const importBasename = path39.basename(resolvedImport, path39.extname(resolvedImport));
48716
49235
  for (const sourceFile of absoluteSourceFiles) {
48717
- const sourceDir = path38.dirname(sourceFile);
48718
- const sourceBasename = path38.basename(sourceFile, path38.extname(sourceFile));
48719
- 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");
48720
49239
  if (resolvedImport === sourceFile || importBasename === sourceBasename && isRelatedDir) {
48721
49240
  dedupePush(testFiles, testFile);
48722
49241
  break;
@@ -48826,8 +49345,8 @@ function buildTestCommand2(framework, scope, files, coverage, baseDir) {
48826
49345
  return ["mvn", "test"];
48827
49346
  case "gradle": {
48828
49347
  const isWindows = process.platform === "win32";
48829
- const hasGradlewBat = fs22.existsSync(path38.join(baseDir, "gradlew.bat"));
48830
- 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"));
48831
49350
  if (hasGradlewBat && isWindows)
48832
49351
  return ["gradlew.bat", "test"];
48833
49352
  if (hasGradlew)
@@ -48844,7 +49363,7 @@ function buildTestCommand2(framework, scope, files, coverage, baseDir) {
48844
49363
  "cmake-build-release",
48845
49364
  "out"
48846
49365
  ];
48847
- 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";
48848
49367
  return ["ctest", "--test-dir", actualBuildDir];
48849
49368
  }
48850
49369
  case "swift-test":
@@ -49276,11 +49795,11 @@ async function runTests(framework, scope, files, coverage, timeout_ms, cwd) {
49276
49795
  };
49277
49796
  }
49278
49797
  const startTime = Date.now();
49279
- 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;
49280
49799
  try {
49281
49800
  if (vitestJsonOutputPath) {
49282
49801
  try {
49283
- fs22.mkdirSync(path38.dirname(vitestJsonOutputPath), { recursive: true });
49802
+ fs22.mkdirSync(path39.dirname(vitestJsonOutputPath), { recursive: true });
49284
49803
  if (fs22.existsSync(vitestJsonOutputPath)) {
49285
49804
  fs22.unlinkSync(vitestJsonOutputPath);
49286
49805
  }
@@ -49396,10 +49915,10 @@ async function runTests(framework, scope, files, coverage, timeout_ms, cwd) {
49396
49915
  }
49397
49916
  function normalizeHistoryTestFile(testFile, workingDir) {
49398
49917
  const normalized = testFile.replace(/\\/g, "/");
49399
- if (!path38.isAbsolute(testFile))
49918
+ if (!path39.isAbsolute(testFile))
49400
49919
  return normalized;
49401
- const relative9 = path38.relative(workingDir, testFile);
49402
- if (relative9.startsWith("..") || path38.isAbsolute(relative9)) {
49920
+ const relative9 = path39.relative(workingDir, testFile);
49921
+ if (relative9.startsWith("..") || path39.isAbsolute(relative9)) {
49403
49922
  return normalized;
49404
49923
  }
49405
49924
  return relative9.replace(/\\/g, "/");
@@ -49737,7 +50256,7 @@ var init_test_runner = __esm(() => {
49737
50256
  const sourceFiles = args.files.filter((file3) => {
49738
50257
  if (directTestFiles.includes(file3))
49739
50258
  return false;
49740
- const ext = path38.extname(file3).toLowerCase();
50259
+ const ext = path39.extname(file3).toLowerCase();
49741
50260
  return SOURCE_EXTENSIONS.has(ext);
49742
50261
  });
49743
50262
  const invalidFiles = args.files.filter((file3) => !directTestFiles.includes(file3) && !sourceFiles.includes(file3));
@@ -49783,7 +50302,7 @@ var init_test_runner = __esm(() => {
49783
50302
  if (isConventionTestFilePath(f)) {
49784
50303
  return false;
49785
50304
  }
49786
- const ext = path38.extname(f).toLowerCase();
50305
+ const ext = path39.extname(f).toLowerCase();
49787
50306
  return SOURCE_EXTENSIONS.has(ext);
49788
50307
  });
49789
50308
  if (sourceFiles.length === 0) {
@@ -49833,7 +50352,7 @@ var init_test_runner = __esm(() => {
49833
50352
  if (isConventionTestFilePath(f)) {
49834
50353
  return false;
49835
50354
  }
49836
- const ext = path38.extname(f).toLowerCase();
50355
+ const ext = path39.extname(f).toLowerCase();
49837
50356
  return SOURCE_EXTENSIONS.has(ext);
49838
50357
  });
49839
50358
  if (sourceFiles.length === 0) {
@@ -49885,8 +50404,8 @@ var init_test_runner = __esm(() => {
49885
50404
  }
49886
50405
  if (impactResult.impactedTests.length > 0) {
49887
50406
  testFiles = impactResult.impactedTests.map((absPath) => {
49888
- const relativePath = path38.relative(workingDir, absPath);
49889
- return path38.isAbsolute(relativePath) ? absPath : relativePath;
50407
+ const relativePath = path39.relative(workingDir, absPath);
50408
+ return path39.isAbsolute(relativePath) ? absPath : relativePath;
49890
50409
  });
49891
50410
  } else {
49892
50411
  graphFallbackReason = "no impacted tests found via impact analysis, falling back to graph";
@@ -49962,7 +50481,7 @@ var init_test_runner = __esm(() => {
49962
50481
 
49963
50482
  // src/services/preflight-service.ts
49964
50483
  import * as fs23 from "fs";
49965
- import * as path39 from "path";
50484
+ import * as path40 from "path";
49966
50485
  function validateDirectoryPath(dir) {
49967
50486
  if (!dir || typeof dir !== "string") {
49968
50487
  throw new Error("Directory path is required");
@@ -49970,8 +50489,8 @@ function validateDirectoryPath(dir) {
49970
50489
  if (dir.includes("..")) {
49971
50490
  throw new Error("Directory path must not contain path traversal sequences");
49972
50491
  }
49973
- const normalized = path39.normalize(dir);
49974
- 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);
49975
50494
  return absolutePath;
49976
50495
  }
49977
50496
  function validateTimeout(timeoutMs, defaultValue) {
@@ -49994,7 +50513,7 @@ function validateTimeout(timeoutMs, defaultValue) {
49994
50513
  }
49995
50514
  function getPackageVersion(dir) {
49996
50515
  try {
49997
- const packagePath = path39.join(dir, "package.json");
50516
+ const packagePath = path40.join(dir, "package.json");
49998
50517
  if (fs23.existsSync(packagePath)) {
49999
50518
  const content = fs23.readFileSync(packagePath, "utf-8");
50000
50519
  const pkg = JSON.parse(content);
@@ -50005,7 +50524,7 @@ function getPackageVersion(dir) {
50005
50524
  }
50006
50525
  function getChangelogVersion(dir) {
50007
50526
  try {
50008
- const changelogPath = path39.join(dir, "CHANGELOG.md");
50527
+ const changelogPath = path40.join(dir, "CHANGELOG.md");
50009
50528
  if (fs23.existsSync(changelogPath)) {
50010
50529
  const content = fs23.readFileSync(changelogPath, "utf-8");
50011
50530
  const match = content.match(/^##\s*\[?(\d+\.\d+\.\d+)\]?/m);
@@ -50019,7 +50538,7 @@ function getChangelogVersion(dir) {
50019
50538
  function getVersionFileVersion(dir) {
50020
50539
  const possibleFiles = ["VERSION.txt", "version.txt", "VERSION", "version"];
50021
50540
  for (const file3 of possibleFiles) {
50022
- const filePath = path39.join(dir, file3);
50541
+ const filePath = path40.join(dir, file3);
50023
50542
  if (fs23.existsSync(filePath)) {
50024
50543
  try {
50025
50544
  const content = fs23.readFileSync(filePath, "utf-8").trim();
@@ -50035,9 +50554,9 @@ function getVersionFileVersion(dir) {
50035
50554
  async function runVersionCheck(dir, _timeoutMs) {
50036
50555
  const startTime = Date.now();
50037
50556
  try {
50038
- const packageVersion = _internals26.getPackageVersion(dir);
50039
- const changelogVersion = _internals26.getChangelogVersion(dir);
50040
- const versionFileVersion = _internals26.getVersionFileVersion(dir);
50557
+ const packageVersion = _internals27.getPackageVersion(dir);
50558
+ const changelogVersion = _internals27.getChangelogVersion(dir);
50559
+ const versionFileVersion = _internals27.getVersionFileVersion(dir);
50041
50560
  const versions3 = [];
50042
50561
  if (packageVersion)
50043
50562
  versions3.push(`package.json: ${packageVersion}`);
@@ -50309,7 +50828,22 @@ async function runEvidenceCheck(dir) {
50309
50828
  };
50310
50829
  }
50311
50830
  const evidenceTaskIds = new Set(await listEvidenceTaskIds(dir));
50312
- 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;
50313
50847
  if (missingEvidence.length > 0) {
50314
50848
  return {
50315
50849
  type: "evidence",
@@ -50317,7 +50851,7 @@ async function runEvidenceCheck(dir) {
50317
50851
  message: `${missingEvidence.length} completed task(s) missing evidence`,
50318
50852
  details: {
50319
50853
  totalCompleted: completedTaskIds.length,
50320
- totalWithEvidence: evidenceTaskIds.size,
50854
+ totalWithEvidence: completedWithEvidence,
50321
50855
  missingTasks: missingEvidence.slice(0, 10),
50322
50856
  missingCount: missingEvidence.length
50323
50857
  },
@@ -50330,7 +50864,7 @@ async function runEvidenceCheck(dir) {
50330
50864
  message: `All ${completedTaskIds.length} completed tasks have evidence`,
50331
50865
  details: {
50332
50866
  totalCompleted: completedTaskIds.length,
50333
- totalWithEvidence: evidenceTaskIds.size
50867
+ totalWithEvidence: completedWithEvidence
50334
50868
  },
50335
50869
  durationMs: Date.now() - startTime
50336
50870
  };
@@ -50346,7 +50880,7 @@ async function runEvidenceCheck(dir) {
50346
50880
  async function runRequirementCoverageCheck(dir, currentPhase) {
50347
50881
  const startTime = Date.now();
50348
50882
  try {
50349
- const specPath = path39.join(dir, ".swarm", "spec.md");
50883
+ const specPath = path40.join(dir, ".swarm", "spec.md");
50350
50884
  if (!fs23.existsSync(specPath)) {
50351
50885
  return {
50352
50886
  type: "req_coverage",
@@ -50387,7 +50921,7 @@ async function runPreflight(dir, phase, config3) {
50387
50921
  const reportId = `preflight-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
50388
50922
  let validatedDir;
50389
50923
  try {
50390
- validatedDir = _internals26.validateDirectoryPath(dir);
50924
+ validatedDir = _internals27.validateDirectoryPath(dir);
50391
50925
  } catch (error93) {
50392
50926
  return {
50393
50927
  id: reportId,
@@ -50407,7 +50941,7 @@ async function runPreflight(dir, phase, config3) {
50407
50941
  }
50408
50942
  let validatedTimeout;
50409
50943
  try {
50410
- validatedTimeout = _internals26.validateTimeout(config3?.checkTimeoutMs, DEFAULT_CONFIG.checkTimeoutMs);
50944
+ validatedTimeout = _internals27.validateTimeout(config3?.checkTimeoutMs, DEFAULT_CONFIG.checkTimeoutMs);
50411
50945
  } catch (error93) {
50412
50946
  return {
50413
50947
  id: reportId,
@@ -50448,12 +50982,12 @@ async function runPreflight(dir, phase, config3) {
50448
50982
  });
50449
50983
  const checks5 = [];
50450
50984
  log("[Preflight] Running lint check...");
50451
- const lintResult = await _internals26.runLintCheck(validatedDir, cfg.linter, cfg.checkTimeoutMs);
50985
+ const lintResult = await _internals27.runLintCheck(validatedDir, cfg.linter, cfg.checkTimeoutMs);
50452
50986
  checks5.push(lintResult);
50453
50987
  log(`[Preflight] Lint check: ${lintResult.status} ${lintResult.message}`);
50454
50988
  if (!cfg.skipTests) {
50455
50989
  log("[Preflight] Running tests check...");
50456
- const testsResult = await _internals26.runTestsCheck(validatedDir, cfg.testScope, cfg.checkTimeoutMs);
50990
+ const testsResult = await _internals27.runTestsCheck(validatedDir, cfg.testScope, cfg.checkTimeoutMs);
50457
50991
  checks5.push(testsResult);
50458
50992
  log(`[Preflight] Tests check: ${testsResult.status} ${testsResult.message}`);
50459
50993
  } else {
@@ -50465,7 +50999,7 @@ async function runPreflight(dir, phase, config3) {
50465
50999
  }
50466
51000
  if (!cfg.skipSecrets) {
50467
51001
  log("[Preflight] Running secrets check...");
50468
- const secretsResult = await _internals26.runSecretsCheck(validatedDir, cfg.checkTimeoutMs);
51002
+ const secretsResult = await _internals27.runSecretsCheck(validatedDir, cfg.checkTimeoutMs);
50469
51003
  checks5.push(secretsResult);
50470
51004
  log(`[Preflight] Secrets check: ${secretsResult.status} ${secretsResult.message}`);
50471
51005
  } else {
@@ -50477,7 +51011,7 @@ async function runPreflight(dir, phase, config3) {
50477
51011
  }
50478
51012
  if (!cfg.skipEvidence) {
50479
51013
  log("[Preflight] Running evidence check...");
50480
- const evidenceResult = await _internals26.runEvidenceCheck(validatedDir);
51014
+ const evidenceResult = await _internals27.runEvidenceCheck(validatedDir);
50481
51015
  checks5.push(evidenceResult);
50482
51016
  log(`[Preflight] Evidence check: ${evidenceResult.status} ${evidenceResult.message}`);
50483
51017
  } else {
@@ -50488,12 +51022,12 @@ async function runPreflight(dir, phase, config3) {
50488
51022
  });
50489
51023
  }
50490
51024
  log("[Preflight] Running requirement coverage check...");
50491
- const reqCoverageResult = await _internals26.runRequirementCoverageCheck(validatedDir, phase);
51025
+ const reqCoverageResult = await _internals27.runRequirementCoverageCheck(validatedDir, phase);
50492
51026
  checks5.push(reqCoverageResult);
50493
51027
  log(`[Preflight] Requirement coverage check: ${reqCoverageResult.status} ${reqCoverageResult.message}`);
50494
51028
  if (!cfg.skipVersion) {
50495
51029
  log("[Preflight] Running version check...");
50496
- const versionResult = await _internals26.runVersionCheck(validatedDir, cfg.checkTimeoutMs);
51030
+ const versionResult = await _internals27.runVersionCheck(validatedDir, cfg.checkTimeoutMs);
50497
51031
  checks5.push(versionResult);
50498
51032
  log(`[Preflight] Version check: ${versionResult.status} ${versionResult.message}`);
50499
51033
  } else {
@@ -50556,11 +51090,12 @@ function formatPreflightMarkdown(report) {
50556
51090
  async function handlePreflightCommand(directory, _args) {
50557
51091
  const plan = await loadPlan(directory);
50558
51092
  const phase = plan?.current_phase ?? 1;
50559
- const report = await _internals26.runPreflight(directory, phase);
50560
- return _internals26.formatPreflightMarkdown(report);
51093
+ const report = await _internals27.runPreflight(directory, phase);
51094
+ return _internals27.formatPreflightMarkdown(report);
50561
51095
  }
50562
- 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;
50563
51097
  var init_preflight_service = __esm(() => {
51098
+ init_gate_bridge();
50564
51099
  init_manager2();
50565
51100
  init_manager();
50566
51101
  init_lint();
@@ -50576,7 +51111,7 @@ var init_preflight_service = __esm(() => {
50576
51111
  testScope: "convention",
50577
51112
  linter: "biome"
50578
51113
  };
50579
- _internals26 = {
51114
+ _internals27 = {
50580
51115
  runPreflight,
50581
51116
  formatPreflightMarkdown,
50582
51117
  handlePreflightCommand,
@@ -51463,7 +51998,7 @@ var init_manager3 = __esm(() => {
51463
51998
 
51464
51999
  // src/commands/reset.ts
51465
52000
  import * as fs24 from "fs";
51466
- import * as path40 from "path";
52001
+ import * as path41 from "path";
51467
52002
  async function handleResetCommand(directory, args) {
51468
52003
  const hasConfirm = args.includes("--confirm");
51469
52004
  if (!hasConfirm) {
@@ -51503,7 +52038,7 @@ async function handleResetCommand(directory, args) {
51503
52038
  }
51504
52039
  for (const filename of ["SWARM_PLAN.md", "SWARM_PLAN.json"]) {
51505
52040
  try {
51506
- const rootPath = path40.join(directory, filename);
52041
+ const rootPath = path41.join(directory, filename);
51507
52042
  if (fs24.existsSync(rootPath)) {
51508
52043
  fs24.unlinkSync(rootPath);
51509
52044
  results.push(`- \u2705 Deleted ${filename} (root)`);
@@ -51543,7 +52078,7 @@ var init_reset = __esm(() => {
51543
52078
 
51544
52079
  // src/commands/reset-session.ts
51545
52080
  import * as fs25 from "fs";
51546
- import * as path41 from "path";
52081
+ import * as path42 from "path";
51547
52082
  async function handleResetSessionCommand(directory, _args) {
51548
52083
  const results = [];
51549
52084
  try {
@@ -51558,13 +52093,13 @@ async function handleResetSessionCommand(directory, _args) {
51558
52093
  results.push("\u274C Failed to delete state.json");
51559
52094
  }
51560
52095
  try {
51561
- const sessionDir = path41.dirname(validateSwarmPath(directory, "session/state.json"));
52096
+ const sessionDir = path42.dirname(validateSwarmPath(directory, "session/state.json"));
51562
52097
  if (fs25.existsSync(sessionDir)) {
51563
52098
  const files = fs25.readdirSync(sessionDir);
51564
52099
  const otherFiles = files.filter((f) => f !== "state.json");
51565
52100
  let deletedCount = 0;
51566
52101
  for (const file3 of otherFiles) {
51567
- const filePath = path41.join(sessionDir, file3);
52102
+ const filePath = path42.join(sessionDir, file3);
51568
52103
  if (fs25.lstatSync(filePath).isFile()) {
51569
52104
  fs25.unlinkSync(filePath);
51570
52105
  deletedCount++;
@@ -51596,7 +52131,7 @@ var init_reset_session = __esm(() => {
51596
52131
  });
51597
52132
 
51598
52133
  // src/summaries/manager.ts
51599
- import * as path42 from "path";
52134
+ import * as path43 from "path";
51600
52135
  function sanitizeSummaryId(id) {
51601
52136
  if (!id || id.length === 0) {
51602
52137
  throw new Error("Invalid summary ID: empty string");
@@ -51619,7 +52154,7 @@ function sanitizeSummaryId(id) {
51619
52154
  }
51620
52155
  async function loadFullOutput(directory, id) {
51621
52156
  const sanitizedId = sanitizeSummaryId(id);
51622
- const relativePath = path42.join("summaries", `${sanitizedId}.json`);
52157
+ const relativePath = path43.join("summaries", `${sanitizedId}.json`);
51623
52158
  validateSwarmPath(directory, relativePath);
51624
52159
  const content = await readSwarmFileAsync(directory, relativePath);
51625
52160
  if (content === null) {
@@ -51682,7 +52217,7 @@ var init_retrieve = __esm(() => {
51682
52217
 
51683
52218
  // src/commands/rollback.ts
51684
52219
  import * as fs26 from "fs";
51685
- import * as path43 from "path";
52220
+ import * as path44 from "path";
51686
52221
  async function handleRollbackCommand(directory, args) {
51687
52222
  const phaseArg = args[0];
51688
52223
  if (!phaseArg) {
@@ -51747,8 +52282,8 @@ async function handleRollbackCommand(directory, args) {
51747
52282
  if (EXCLUDE_FILES.has(file3) || file3.startsWith("plan-ledger.archived-")) {
51748
52283
  continue;
51749
52284
  }
51750
- const src = path43.join(checkpointDir, file3);
51751
- const dest = path43.join(swarmDir, file3);
52285
+ const src = path44.join(checkpointDir, file3);
52286
+ const dest = path44.join(swarmDir, file3);
51752
52287
  try {
51753
52288
  fs26.cpSync(src, dest, { recursive: true, force: true });
51754
52289
  successes.push(file3);
@@ -51767,12 +52302,12 @@ async function handleRollbackCommand(directory, args) {
51767
52302
  ].join(`
51768
52303
  `);
51769
52304
  }
51770
- const existingLedgerPath = path43.join(swarmDir, "plan-ledger.jsonl");
52305
+ const existingLedgerPath = path44.join(swarmDir, "plan-ledger.jsonl");
51771
52306
  if (fs26.existsSync(existingLedgerPath)) {
51772
52307
  fs26.unlinkSync(existingLedgerPath);
51773
52308
  }
51774
52309
  try {
51775
- const planJsonPath = path43.join(swarmDir, "plan.json");
52310
+ const planJsonPath = path44.join(swarmDir, "plan.json");
51776
52311
  if (fs26.existsSync(planJsonPath)) {
51777
52312
  const planRaw = fs26.readFileSync(planJsonPath, "utf-8");
51778
52313
  const plan = PlanSchema.parse(JSON.parse(planRaw));
@@ -51833,7 +52368,7 @@ async function handleSimulateCommand(directory, args) {
51833
52368
  }
51834
52369
  let darkMatterPairs;
51835
52370
  try {
51836
- darkMatterPairs = await _internals10.detectDarkMatter(directory, options);
52371
+ darkMatterPairs = await _internals11.detectDarkMatter(directory, options);
51837
52372
  } catch (err) {
51838
52373
  const errMsg = err instanceof Error ? err.message : String(err);
51839
52374
  return `## Simulate Report
@@ -51863,9 +52398,9 @@ Ensure this is a git repository with commit history.`;
51863
52398
  `);
51864
52399
  try {
51865
52400
  const fs27 = await import("fs/promises");
51866
- const path44 = await import("path");
51867
- const reportPath = path44.join(directory, ".swarm", "simulate-report.md");
51868
- 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 });
51869
52404
  await fs27.writeFile(reportPath, report, "utf-8");
51870
52405
  } catch (err) {
51871
52406
  const writeErr = err instanceof Error ? err.message : String(err);
@@ -51889,12 +52424,12 @@ async function handleSpecifyCommand(_directory, args) {
51889
52424
 
51890
52425
  // src/turbo/lean/state.ts
51891
52426
  import * as fs27 from "fs";
51892
- import * as path44 from "path";
52427
+ import * as path45 from "path";
51893
52428
  function nowISO2() {
51894
52429
  return new Date().toISOString();
51895
52430
  }
51896
52431
  function ensureSwarmDir2(directory) {
51897
- const swarmDir = path44.resolve(directory, ".swarm");
52432
+ const swarmDir = path45.resolve(directory, ".swarm");
51898
52433
  if (!fs27.existsSync(swarmDir)) {
51899
52434
  fs27.mkdirSync(swarmDir, { recursive: true });
51900
52435
  }
@@ -51938,7 +52473,7 @@ function markStateUnreadable2(directory, reason) {
51938
52473
  }
51939
52474
  function readPersisted2(directory) {
51940
52475
  try {
51941
- const filePath = path44.join(directory, ".swarm", STATE_FILE2);
52476
+ const filePath = path45.join(directory, ".swarm", STATE_FILE2);
51942
52477
  if (!fs27.existsSync(filePath)) {
51943
52478
  const seed = emptyPersisted2();
51944
52479
  try {
@@ -51974,7 +52509,7 @@ function writePersisted2(directory, persisted) {
51974
52509
  let payload;
51975
52510
  try {
51976
52511
  ensureSwarmDir2(directory);
51977
- filePath = path44.join(directory, ".swarm", STATE_FILE2);
52512
+ filePath = path45.join(directory, ".swarm", STATE_FILE2);
51978
52513
  tmpPath = `${filePath}.tmp.${Date.now()}`;
51979
52514
  persisted.updatedAt = nowISO2();
51980
52515
  payload = `${JSON.stringify(persisted, null, 2)}
@@ -52101,10 +52636,10 @@ var init_context_budget_service = __esm(() => {
52101
52636
 
52102
52637
  // src/services/status-service.ts
52103
52638
  import * as fsSync2 from "fs";
52104
- import * as path45 from "path";
52639
+ import * as path46 from "path";
52105
52640
  function readSpecStalenessSnapshot(directory) {
52106
52641
  try {
52107
- const p = path45.join(directory, ".swarm", "spec-staleness.json");
52642
+ const p = path46.join(directory, ".swarm", "spec-staleness.json");
52108
52643
  if (!fsSync2.existsSync(p))
52109
52644
  return { stale: false };
52110
52645
  const raw = fsSync2.readFileSync(p, "utf-8");
@@ -52198,7 +52733,7 @@ async function getStatusData(directory, agents) {
52198
52733
  }
52199
52734
  function enrichWithLeanTurbo(status, directory) {
52200
52735
  const turboMode = hasActiveTurboMode();
52201
- const leanActive = _internals27.hasActiveLeanTurbo();
52736
+ const leanActive = _internals28.hasActiveLeanTurbo();
52202
52737
  let turboStrategy = "off";
52203
52738
  if (leanActive) {
52204
52739
  turboStrategy = "lean";
@@ -52217,7 +52752,7 @@ function enrichWithLeanTurbo(status, directory) {
52217
52752
  }
52218
52753
  }
52219
52754
  if (leanSessionID) {
52220
- const runState = _internals27.loadLeanTurboRunState(directory, leanSessionID);
52755
+ const runState = _internals28.loadLeanTurboRunState(directory, leanSessionID);
52221
52756
  if (runState) {
52222
52757
  status.leanTurboPhase = runState.phase;
52223
52758
  status.leanMaxParallelCoders = runState.maxParallelCoders;
@@ -52249,7 +52784,7 @@ function enrichWithLeanTurbo(status, directory) {
52249
52784
  }
52250
52785
  }
52251
52786
  }
52252
- status.fullAutoActive = _internals27.hasActiveFullAuto();
52787
+ status.fullAutoActive = _internals28.hasActiveFullAuto();
52253
52788
  return status;
52254
52789
  }
52255
52790
  function formatStatusMarkdown(status) {
@@ -52331,7 +52866,7 @@ async function handleStatusCommand(directory, agents) {
52331
52866
  }
52332
52867
  return formatStatusMarkdown(statusData);
52333
52868
  }
52334
- var _internals27;
52869
+ var _internals28;
52335
52870
  var init_status_service = __esm(() => {
52336
52871
  init_extractors();
52337
52872
  init_utils2();
@@ -52340,7 +52875,7 @@ var init_status_service = __esm(() => {
52340
52875
  init_state3();
52341
52876
  init_compaction_service();
52342
52877
  init_context_budget_service();
52343
- _internals27 = {
52878
+ _internals28 = {
52344
52879
  loadLeanTurboRunState,
52345
52880
  hasActiveLeanTurbo,
52346
52881
  hasActiveFullAuto
@@ -52431,7 +52966,7 @@ async function handleTurboCommand(directory, args, sessionID) {
52431
52966
  if (arg0 === "on") {
52432
52967
  let strategy = "standard";
52433
52968
  try {
52434
- const { config: config3 } = _internals28.loadPluginConfigWithMeta(directory);
52969
+ const { config: config3 } = _internals29.loadPluginConfigWithMeta(directory);
52435
52970
  if (config3.turbo?.strategy === "lean") {
52436
52971
  strategy = "lean";
52437
52972
  }
@@ -52486,7 +53021,7 @@ function enableLeanTurbo(session, directory, sessionID) {
52486
53021
  let maxParallelCoders = 4;
52487
53022
  let conflictPolicy = "serialize";
52488
53023
  try {
52489
- const { config: config3 } = _internals28.loadPluginConfigWithMeta(directory);
53024
+ const { config: config3 } = _internals29.loadPluginConfigWithMeta(directory);
52490
53025
  const leanConfig = config3.turbo?.lean;
52491
53026
  if (leanConfig) {
52492
53027
  maxParallelCoders = leanConfig.max_parallel_coders ?? 4;
@@ -52556,13 +53091,13 @@ function buildStatusMessage(session, directory, sessionID) {
52556
53091
  ].join(`
52557
53092
  `);
52558
53093
  }
52559
- var _internals28;
53094
+ var _internals29;
52560
53095
  var init_turbo = __esm(() => {
52561
53096
  init_config();
52562
53097
  init_state();
52563
53098
  init_state3();
52564
53099
  init_logger();
52565
- _internals28 = {
53100
+ _internals29 = {
52566
53101
  loadPluginConfigWithMeta
52567
53102
  };
52568
53103
  });
@@ -52630,7 +53165,7 @@ var init_write_retro2 = __esm(() => {
52630
53165
 
52631
53166
  // src/commands/command-dispatch.ts
52632
53167
  import fs28 from "fs";
52633
- import path46 from "path";
53168
+ import path47 from "path";
52634
53169
  function normalizeSwarmCommandInput(command, argumentText) {
52635
53170
  if (command !== "swarm" && !command.startsWith("swarm-")) {
52636
53171
  return { isSwarmCommand: false, tokens: [] };
@@ -52655,7 +53190,7 @@ function formatCommandNotFound(tokens) {
52655
53190
  const attemptedCommand = tokens[0] || "";
52656
53191
  const MAX_DISPLAY = 100;
52657
53192
  const displayCommand = attemptedCommand.length > MAX_DISPLAY ? `${attemptedCommand.slice(0, MAX_DISPLAY)}...` : attemptedCommand;
52658
- const similar = _internals29.findSimilarCommands(attemptedCommand);
53193
+ const similar = _internals30.findSimilarCommands(attemptedCommand);
52659
53194
  const header = `Command \`/swarm ${displayCommand}\` not found.`;
52660
53195
  const suggestions = similar.length > 0 ? `Did you mean:
52661
53196
  ${similar.map((cmd) => ` - /swarm ${cmd}`).join(`
@@ -52666,9 +53201,9 @@ ${similar.map((cmd) => ` - /swarm ${cmd}`).join(`
52666
53201
  `);
52667
53202
  }
52668
53203
  function maybeMarkFirstRun(directory) {
52669
- const sentinelPath = path46.join(directory, ".swarm", ".first-run-complete");
53204
+ const sentinelPath = path47.join(directory, ".swarm", ".first-run-complete");
52670
53205
  try {
52671
- const swarmDir = path46.join(directory, ".swarm");
53206
+ const swarmDir = path47.join(directory, ".swarm");
52672
53207
  fs28.mkdirSync(swarmDir, { recursive: true });
52673
53208
  fs28.writeFileSync(sentinelPath, `first-run-complete: ${new Date().toISOString()}
52674
53209
  `, { flag: "wx" });
@@ -53104,7 +53639,7 @@ async function buildSwarmCommandPrompt(args) {
53104
53639
  activeAgentName,
53105
53640
  registeredAgents
53106
53641
  } = args;
53107
- const resolved = _internals29.resolveCommand(tokens);
53642
+ const resolved = _internals30.resolveCommand(tokens);
53108
53643
  if (!resolved) {
53109
53644
  if (tokens.length === 0) {
53110
53645
  return buildHelpText();
@@ -53255,7 +53790,7 @@ function findSimilarCommands(query) {
53255
53790
  }
53256
53791
  const scored = VALID_COMMANDS.map((cmd) => {
53257
53792
  const cmdLower = cmd.toLowerCase();
53258
- const fullScore = _internals29.levenshteinDistance(q, cmdLower);
53793
+ const fullScore = _internals30.levenshteinDistance(q, cmdLower);
53259
53794
  let tokenScore = Infinity;
53260
53795
  if (cmd.includes(" ") || cmd.includes("-")) {
53261
53796
  const qTokens = q.split(/[\s-]+/);
@@ -53268,7 +53803,7 @@ function findSimilarCommands(query) {
53268
53803
  for (const ct of cmdTokens) {
53269
53804
  if (ct.length === 0)
53270
53805
  continue;
53271
- const dist = _internals29.levenshteinDistance(qt, ct);
53806
+ const dist = _internals30.levenshteinDistance(qt, ct);
53272
53807
  if (dist < minDist)
53273
53808
  minDist = dist;
53274
53809
  }
@@ -53278,7 +53813,7 @@ function findSimilarCommands(query) {
53278
53813
  }
53279
53814
  const dashStrippedQ = q.replace(/-/g, "");
53280
53815
  const dashStrippedCmd = cmdLower.replace(/-/g, "");
53281
- const dashScore = _internals29.levenshteinDistance(dashStrippedQ, dashStrippedCmd);
53816
+ const dashScore = _internals30.levenshteinDistance(dashStrippedQ, dashStrippedCmd);
53282
53817
  const score = Math.min(fullScore, tokenScore, dashScore);
53283
53818
  return { cmd, score };
53284
53819
  });
@@ -53310,11 +53845,11 @@ async function handleHelpCommand(ctx) {
53310
53845
  return buildHelpText2();
53311
53846
  }
53312
53847
  const tokens = targetCommand.split(/\s+/);
53313
- const resolved = _internals29.resolveCommand(tokens);
53848
+ const resolved = _internals30.resolveCommand(tokens);
53314
53849
  if (resolved) {
53315
- return _internals29.buildDetailedHelp(resolved.key, resolved.entry);
53850
+ return _internals30.buildDetailedHelp(resolved.key, resolved.entry);
53316
53851
  }
53317
- const similar = _internals29.findSimilarCommands(targetCommand);
53852
+ const similar = _internals30.findSimilarCommands(targetCommand);
53318
53853
  const { buildHelpText: fullHelp } = await Promise.resolve().then(() => (init_commands(), exports_commands));
53319
53854
  if (similar.length > 0) {
53320
53855
  return `Command '/swarm ${targetCommand}' not found.
@@ -53350,24 +53885,24 @@ function validateAliases() {
53350
53885
  }
53351
53886
  aliasTargets.get(target).push(name);
53352
53887
  const visited = new Set;
53353
- const path47 = [];
53888
+ const path48 = [];
53354
53889
  let current = target;
53355
53890
  while (current) {
53356
53891
  const currentEntry = COMMAND_REGISTRY[current];
53357
53892
  if (!currentEntry)
53358
53893
  break;
53359
53894
  if (visited.has(current)) {
53360
- const cycleStart = path47.indexOf(current);
53895
+ const cycleStart = path48.indexOf(current);
53361
53896
  const fullChain = [
53362
53897
  name,
53363
- ...path47.slice(0, cycleStart > 0 ? cycleStart : path47.length),
53898
+ ...path48.slice(0, cycleStart > 0 ? cycleStart : path48.length),
53364
53899
  current
53365
53900
  ].join(" \u2192 ");
53366
53901
  errors5.push(`Circular alias detected: ${fullChain}`);
53367
53902
  break;
53368
53903
  }
53369
53904
  visited.add(current);
53370
- path47.push(current);
53905
+ path48.push(current);
53371
53906
  current = currentEntry.aliasOf || "";
53372
53907
  }
53373
53908
  }
@@ -53408,7 +53943,7 @@ function resolveCommand(tokens) {
53408
53943
  }
53409
53944
  return null;
53410
53945
  }
53411
- var COMMAND_REGISTRY, VALID_COMMANDS, _internals29, validation;
53946
+ var COMMAND_REGISTRY, VALID_COMMANDS, _internals30, validation;
53412
53947
  var init_registry = __esm(() => {
53413
53948
  init_acknowledge_spec_drift();
53414
53949
  init_agents();
@@ -53478,7 +54013,7 @@ var init_registry = __esm(() => {
53478
54013
  clashesWithNativeCcCommand: "/agents"
53479
54014
  },
53480
54015
  help: {
53481
- handler: (ctx) => _internals29.handleHelpCommand(ctx),
54016
+ handler: (ctx) => _internals30.handleHelpCommand(ctx),
53482
54017
  description: "Show help for swarm commands",
53483
54018
  category: "core",
53484
54019
  args: "[command]",
@@ -53850,7 +54385,7 @@ Subcommands:
53850
54385
  }
53851
54386
  };
53852
54387
  VALID_COMMANDS = Object.keys(COMMAND_REGISTRY);
53853
- _internals29 = {
54388
+ _internals30 = {
53854
54389
  handleHelpCommand,
53855
54390
  validateAliases,
53856
54391
  resolveCommand,
@@ -53858,7 +54393,7 @@ Subcommands:
53858
54393
  findSimilarCommands,
53859
54394
  buildDetailedHelp
53860
54395
  };
53861
- validation = _internals29.validateAliases();
54396
+ validation = _internals30.validateAliases();
53862
54397
  if (!validation.valid) {
53863
54398
  throw new Error(`COMMAND_REGISTRY alias validation failed:
53864
54399
  ${validation.errors.join(`
@@ -53878,53 +54413,53 @@ init_cache_paths();
53878
54413
  init_constants();
53879
54414
  import * as fs29 from "fs";
53880
54415
  import * as os7 from "os";
53881
- import * as path47 from "path";
54416
+ import * as path48 from "path";
53882
54417
  var { version: version4 } = package_default;
53883
54418
  var CONFIG_DIR = getPluginConfigDir();
53884
- var OPENCODE_CONFIG_PATH = path47.join(CONFIG_DIR, "opencode.json");
53885
- var PLUGIN_CONFIG_PATH = path47.join(CONFIG_DIR, "opencode-swarm.json");
53886
- 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");
53887
54422
  var OPENCODE_PLUGIN_CACHE_PATHS = getPluginCachePaths();
53888
54423
  var OPENCODE_PLUGIN_LOCK_FILE_PATHS = getPluginLockFilePaths();
53889
54424
  function isSafeCachePath(p) {
53890
- const resolved = path47.resolve(p);
53891
- const home = path47.resolve(os7.homedir());
54425
+ const resolved = path48.resolve(p);
54426
+ const home = path48.resolve(os7.homedir());
53892
54427
  if (resolved === "/" || resolved === home || resolved.length <= home.length) {
53893
54428
  return false;
53894
54429
  }
53895
- const segments = resolved.split(path47.sep).filter((s) => s.length > 0);
54430
+ const segments = resolved.split(path48.sep).filter((s) => s.length > 0);
53896
54431
  if (segments.length < 4) {
53897
54432
  return false;
53898
54433
  }
53899
- const leaf = path47.basename(resolved);
54434
+ const leaf = path48.basename(resolved);
53900
54435
  if (leaf !== "opencode-swarm@latest" && leaf !== "opencode-swarm") {
53901
54436
  return false;
53902
54437
  }
53903
- const parent = path47.basename(path47.dirname(resolved));
54438
+ const parent = path48.basename(path48.dirname(resolved));
53904
54439
  if (parent !== "packages" && parent !== "node_modules") {
53905
54440
  return false;
53906
54441
  }
53907
- const grandparent = path47.basename(path47.dirname(path47.dirname(resolved)));
54442
+ const grandparent = path48.basename(path48.dirname(path48.dirname(resolved)));
53908
54443
  if (grandparent !== "opencode") {
53909
54444
  return false;
53910
54445
  }
53911
54446
  return true;
53912
54447
  }
53913
54448
  function isSafeLockFilePath(p) {
53914
- const resolved = path47.resolve(p);
53915
- const home = path47.resolve(os7.homedir());
54449
+ const resolved = path48.resolve(p);
54450
+ const home = path48.resolve(os7.homedir());
53916
54451
  if (resolved === "/" || resolved === home || resolved.length <= home.length) {
53917
54452
  return false;
53918
54453
  }
53919
- const segments = resolved.split(path47.sep).filter((s) => s.length > 0);
54454
+ const segments = resolved.split(path48.sep).filter((s) => s.length > 0);
53920
54455
  if (segments.length < 4) {
53921
54456
  return false;
53922
54457
  }
53923
- const leaf = path47.basename(resolved);
54458
+ const leaf = path48.basename(resolved);
53924
54459
  if (leaf !== "bun.lock" && leaf !== "bun.lockb" && leaf !== "package-lock.json") {
53925
54460
  return false;
53926
54461
  }
53927
- const parent = path47.basename(path47.dirname(resolved));
54462
+ const parent = path48.basename(path48.dirname(resolved));
53928
54463
  if (parent !== "opencode") {
53929
54464
  return false;
53930
54465
  }
@@ -53950,8 +54485,8 @@ function saveJson(filepath, data) {
53950
54485
  }
53951
54486
  function writeProjectConfigIfMissing(cwd) {
53952
54487
  try {
53953
- const opencodeDir = path47.join(cwd, ".opencode");
53954
- const projectConfigPath = path47.join(opencodeDir, "opencode-swarm.json");
54488
+ const opencodeDir = path48.join(cwd, ".opencode");
54489
+ const projectConfigPath = path48.join(opencodeDir, "opencode-swarm.json");
53955
54490
  if (fs29.existsSync(projectConfigPath)) {
53956
54491
  return;
53957
54492
  }
@@ -53968,7 +54503,7 @@ async function install() {
53968
54503
  `);
53969
54504
  ensureDir(CONFIG_DIR);
53970
54505
  ensureDir(PROMPTS_DIR);
53971
- const LEGACY_CONFIG_PATH = path47.join(CONFIG_DIR, "config.json");
54506
+ const LEGACY_CONFIG_PATH = path48.join(CONFIG_DIR, "config.json");
53972
54507
  let opencodeConfig = loadJson(OPENCODE_CONFIG_PATH);
53973
54508
  if (!opencodeConfig) {
53974
54509
  const legacyConfig = loadJson(LEGACY_CONFIG_PATH);