opencode-swarm 7.9.0 → 7.11.0

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.9.0",
37
+ version: "7.11.0",
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",
@@ -16054,7 +16054,14 @@ var init_tool_names = __esm(() => {
16054
16054
  "set_qa_gates",
16055
16055
  "web_search",
16056
16056
  "convene_general_council",
16057
- "write_final_council_evidence"
16057
+ "write_final_council_evidence",
16058
+ "skill_generate",
16059
+ "skill_list",
16060
+ "skill_apply",
16061
+ "skill_inspect",
16062
+ "skill_improve",
16063
+ "spec_write",
16064
+ "knowledge_ack"
16058
16065
  ];
16059
16066
  TOOL_NAME_SET = new Set(TOOL_NAMES);
16060
16067
  });
@@ -16110,6 +16117,8 @@ var init_constants = __esm(() => {
16110
16117
  "council_generalist",
16111
16118
  "council_skeptic",
16112
16119
  "council_domain_expert",
16120
+ "skill_improver",
16121
+ "spec_writer",
16113
16122
  ...QA_AGENTS,
16114
16123
  ...PIPELINE_AGENTS
16115
16124
  ];
@@ -16292,7 +16301,13 @@ var init_constants = __esm(() => {
16292
16301
  "set_qa_gates",
16293
16302
  "convene_general_council",
16294
16303
  "web_search",
16295
- "write_final_council_evidence"
16304
+ "write_final_council_evidence",
16305
+ "skill_generate",
16306
+ "skill_list",
16307
+ "skill_apply",
16308
+ "skill_inspect",
16309
+ "skill_improve",
16310
+ "knowledge_ack"
16296
16311
  ],
16297
16312
  explorer: [
16298
16313
  "complexity_hotspots",
@@ -16462,7 +16477,32 @@ var init_constants = __esm(() => {
16462
16477
  curator_phase: ["knowledge_recall"],
16463
16478
  council_generalist: [],
16464
16479
  council_skeptic: [],
16465
- council_domain_expert: []
16480
+ council_domain_expert: [],
16481
+ skill_improver: [
16482
+ "knowledge_recall",
16483
+ "knowledge_query",
16484
+ "skill_list",
16485
+ "skill_inspect",
16486
+ "skill_generate",
16487
+ "skill_improve",
16488
+ "search",
16489
+ "doc_scan",
16490
+ "doc_extract",
16491
+ "web_search"
16492
+ ],
16493
+ spec_writer: [
16494
+ "search",
16495
+ "knowledge_recall",
16496
+ "knowledge_query",
16497
+ "doc_scan",
16498
+ "doc_extract",
16499
+ "req_coverage",
16500
+ "lint_spec",
16501
+ "retrieve_summary",
16502
+ "symbols",
16503
+ "extract_code_blocks",
16504
+ "spec_write"
16505
+ ]
16466
16506
  };
16467
16507
  for (const [agentName, tools] of Object.entries(AGENT_TOOL_MAP)) {
16468
16508
  const invalidTools = tools.filter((tool) => !TOOL_NAME_SET.has(tool));
@@ -16526,6 +16566,14 @@ var init_constants = __esm(() => {
16526
16566
  curator_phase: {
16527
16567
  model: "opencode/gpt-5-nano",
16528
16568
  fallback_models: ["opencode/big-pickle"]
16569
+ },
16570
+ skill_improver: {
16571
+ model: "opencode/big-pickle",
16572
+ fallback_models: ["opencode/gpt-5-nano"]
16573
+ },
16574
+ spec_writer: {
16575
+ model: "opencode/big-pickle",
16576
+ fallback_models: ["opencode/gpt-5-nano"]
16529
16577
  }
16530
16578
  };
16531
16579
  });
@@ -16559,7 +16607,7 @@ function getCanonicalAgentRole(agentName, generatedAgentNames) {
16559
16607
  function stripKnownSwarmPrefix(agentName) {
16560
16608
  return getCanonicalAgentRole(agentName);
16561
16609
  }
16562
- var SEPARATORS, CANONICAL_ROLES_LONGEST_FIRST, CANONICAL_ROLES_SET, AgentOverrideConfigSchema, SwarmConfigSchema, HooksConfigSchema, ScoringWeightsSchema, DecisionDecaySchema, TokenRatiosSchema, ScoringConfigSchema, ContextBudgetConfigSchema, EvidenceConfigSchema, GateFeatureSchema, PlaceholderScanConfigSchema, QualityBudgetConfigSchema, GateConfigSchema, PipelineConfigSchema, PhaseCompleteConfigSchema, SummaryConfigSchema, ReviewPassesConfigSchema, AdversarialDetectionConfigSchema, AdversarialTestingConfigSchemaBase, AdversarialTestingConfigSchema, IntegrationAnalysisConfigSchema, DocsConfigSchema, UIReviewConfigSchema, CompactionAdvisoryConfigSchema, LintConfigSchema, SecretscanConfigSchema, GuardrailsProfileSchema, DEFAULT_AGENT_PROFILES, DEFAULT_ARCHITECT_PROFILE, GuardrailsConfigSchema, WatchdogConfigSchema, SelfReviewConfigSchema, ToolFilterConfigSchema, PlanCursorConfigSchema, CheckpointConfigSchema, AutomationModeSchema, AutomationCapabilitiesSchema, AutomationConfigSchemaBase, AutomationConfigSchema, KnowledgeConfigSchema, CuratorConfigSchema, SlopDetectorConfigSchema, IncrementalVerifyConfigSchema, CompactionConfigSchema, PrmConfigSchema, AgentAuthorityRuleSchema, AuthorityConfigSchema, GeneralCouncilMemberConfigSchema, GeneralCouncilConfigSchema, CouncilConfigSchema, ParallelizationConfigSchema, PluginConfigSchema;
16610
+ var SEPARATORS, CANONICAL_ROLES_LONGEST_FIRST, CANONICAL_ROLES_SET, AgentOverrideConfigSchema, SwarmConfigSchema, HooksConfigSchema, ScoringWeightsSchema, DecisionDecaySchema, TokenRatiosSchema, ScoringConfigSchema, ContextBudgetConfigSchema, EvidenceConfigSchema, GateFeatureSchema, PlaceholderScanConfigSchema, QualityBudgetConfigSchema, GateConfigSchema, PipelineConfigSchema, PhaseCompleteConfigSchema, SummaryConfigSchema, ReviewPassesConfigSchema, AdversarialDetectionConfigSchema, AdversarialTestingConfigSchemaBase, AdversarialTestingConfigSchema, IntegrationAnalysisConfigSchema, DocsConfigSchema, UIReviewConfigSchema, CompactionAdvisoryConfigSchema, LintConfigSchema, SecretscanConfigSchema, GuardrailsProfileSchema, DEFAULT_AGENT_PROFILES, DEFAULT_ARCHITECT_PROFILE, GuardrailsConfigSchema, WatchdogConfigSchema, SelfReviewConfigSchema, ToolFilterConfigSchema, PlanCursorConfigSchema, CheckpointConfigSchema, AutomationModeSchema, AutomationCapabilitiesSchema, AutomationConfigSchemaBase, AutomationConfigSchema, KnowledgeConfigSchema, CuratorConfigSchema, KnowledgeApplicationConfigSchema, SkillImproverConfigSchema, SpecWriterConfigSchema, SlopDetectorConfigSchema, IncrementalVerifyConfigSchema, CompactionConfigSchema, PrmConfigSchema, AgentAuthorityRuleSchema, AuthorityConfigSchema, GeneralCouncilMemberConfigSchema, GeneralCouncilConfigSchema, CouncilConfigSchema, ParallelizationConfigSchema, PluginConfigSchema;
16563
16611
  var init_schema = __esm(() => {
16564
16612
  init_zod();
16565
16613
  init_constants();
@@ -17000,6 +17048,7 @@ var init_schema = __esm(() => {
17000
17048
  low_utility_threshold: exports_external.number().min(0).max(1).default(0.3),
17001
17049
  min_retrievals_for_utility: exports_external.number().min(1).max(100).default(3),
17002
17050
  schema_version: exports_external.number().int().min(1).default(1),
17051
+ directive_min_confidence: exports_external.number().min(0).max(1).default(0.75),
17003
17052
  same_project_weight: exports_external.number().min(0).max(5).default(1),
17004
17053
  cross_project_weight: exports_external.number().min(0).max(5).default(0.5),
17005
17054
  min_encounter_score: exports_external.number().min(0).max(1).default(0.1),
@@ -17019,7 +17068,36 @@ var init_schema = __esm(() => {
17019
17068
  compliance_report: exports_external.boolean().default(true),
17020
17069
  suppress_warnings: exports_external.boolean().default(true),
17021
17070
  drift_inject_max_chars: exports_external.number().min(100).max(2000).default(500),
17022
- llm_timeout_ms: exports_external.number().int().min(5000).max(600000).default(300000)
17071
+ llm_timeout_ms: exports_external.number().int().min(5000).max(600000).default(300000),
17072
+ skill_generation_enabled: exports_external.boolean().default(true),
17073
+ skill_generation_mode: exports_external.enum(["draft", "active"]).default("draft"),
17074
+ min_skill_confidence: exports_external.number().min(0).max(1).default(0.85),
17075
+ min_skill_confirmations: exports_external.number().int().min(1).max(50).default(2)
17076
+ });
17077
+ KnowledgeApplicationConfigSchema = exports_external.object({
17078
+ enabled: exports_external.boolean().default(true),
17079
+ mode: exports_external.enum(["warn", "enforce"]).default("warn"),
17080
+ min_confidence: exports_external.number().min(0).max(1).default(0.85),
17081
+ critical_requires_ack: exports_external.boolean().default(true),
17082
+ require_skill_refs: exports_external.boolean().default(true)
17083
+ });
17084
+ SkillImproverConfigSchema = exports_external.object({
17085
+ enabled: exports_external.boolean().default(false),
17086
+ model: exports_external.string().nullable().default(null),
17087
+ fallback_models: exports_external.array(exports_external.string()).default([]),
17088
+ max_calls_per_day: exports_external.number().int().min(1).max(1000).default(10),
17089
+ trigger: exports_external.enum(["manual", "scheduled"]).default("manual"),
17090
+ targets: exports_external.array(exports_external.enum(["skills", "spec", "architect_prompt", "knowledge"])).default(["skills", "spec", "architect_prompt", "knowledge"]),
17091
+ write_mode: exports_external.enum(["proposal", "draft_skills"]).default("proposal"),
17092
+ require_user_approval: exports_external.boolean().default(true),
17093
+ quota_window: exports_external.enum(["utc", "local"]).default("utc"),
17094
+ allow_deterministic_fallback: exports_external.boolean().default(true)
17095
+ });
17096
+ SpecWriterConfigSchema = exports_external.object({
17097
+ enabled: exports_external.boolean().default(true),
17098
+ model: exports_external.string().nullable().default(null),
17099
+ fallback_models: exports_external.array(exports_external.string()).default([]),
17100
+ allow_spec_write: exports_external.boolean().default(true)
17023
17101
  });
17024
17102
  SlopDetectorConfigSchema = exports_external.object({
17025
17103
  enabled: exports_external.boolean().default(true),
@@ -17155,6 +17233,9 @@ var init_schema = __esm(() => {
17155
17233
  automation: AutomationConfigSchema.optional(),
17156
17234
  knowledge: KnowledgeConfigSchema.optional(),
17157
17235
  curator: CuratorConfigSchema.optional(),
17236
+ knowledge_application: KnowledgeApplicationConfigSchema.optional(),
17237
+ skill_improver: SkillImproverConfigSchema.optional(),
17238
+ spec_writer: SpecWriterConfigSchema.optional(),
17158
17239
  tool_output: exports_external.object({
17159
17240
  truncation_enabled: exports_external.boolean().default(true),
17160
17241
  max_lines: exports_external.number().min(10).max(500).default(150),
@@ -20705,6 +20786,10 @@ function resetSwarmState() {
20705
20786
  swarmState.opencodeClient = null;
20706
20787
  swarmState.curatorInitAgentNames = [];
20707
20788
  swarmState.curatorPhaseAgentNames = [];
20789
+ swarmState.skillImproverAgentNames = [];
20790
+ swarmState.specWriterAgentNames = [];
20791
+ swarmState.currentCriticalShownIds.clear();
20792
+ swarmState.knowledgeAckDedup.clear();
20708
20793
  swarmState.generatedAgentNames = [];
20709
20794
  _rehydrationCache = null;
20710
20795
  swarmState.fullAutoEnabledInConfig = false;
@@ -20750,6 +20835,10 @@ var init_state = __esm(() => {
20750
20835
  opencodeClient: null,
20751
20836
  curatorInitAgentNames: [],
20752
20837
  curatorPhaseAgentNames: [],
20838
+ skillImproverAgentNames: [],
20839
+ specWriterAgentNames: [],
20840
+ currentCriticalShownIds: new Map,
20841
+ knowledgeAckDedup: new Set,
20753
20842
  generatedAgentNames: [],
20754
20843
  lastBudgetPct: 0,
20755
20844
  agentSessions: defaultRunContext.agentSessions,
@@ -34490,6 +34579,205 @@ function resetToRemoteBranch(cwd, options) {
34490
34579
  };
34491
34580
  }
34492
34581
  }
34582
+ function resetToMainAfterMerge(cwd, options) {
34583
+ const warnings = [];
34584
+ try {
34585
+ const defaultBranch = _internals6.detectDefaultRemoteBranch(cwd);
34586
+ if (!defaultBranch) {
34587
+ return {
34588
+ success: false,
34589
+ targetBranch: "",
34590
+ previousBranch: "",
34591
+ message: "Could not detect default remote branch",
34592
+ branchDeleted: false,
34593
+ changesDiscarded: false,
34594
+ warnings
34595
+ };
34596
+ }
34597
+ const currentBranch = getCurrentBranch(cwd);
34598
+ const targetBranch = `origin/${defaultBranch}`;
34599
+ if (currentBranch === "HEAD") {
34600
+ return {
34601
+ success: false,
34602
+ targetBranch,
34603
+ previousBranch: "HEAD",
34604
+ message: "Cannot reset: detached HEAD state",
34605
+ branchDeleted: false,
34606
+ changesDiscarded: false,
34607
+ warnings
34608
+ };
34609
+ }
34610
+ if (currentBranch === defaultBranch) {
34611
+ try {
34612
+ const logOutput = _internals6.gitExec(["log", `${targetBranch}..HEAD`, "--oneline"], cwd);
34613
+ if (logOutput.trim().length > 0) {
34614
+ return {
34615
+ success: false,
34616
+ targetBranch,
34617
+ previousBranch: currentBranch,
34618
+ message: `Cannot reset: ${defaultBranch} has unpushed commits. Push them first.`,
34619
+ branchDeleted: false,
34620
+ changesDiscarded: false,
34621
+ warnings
34622
+ };
34623
+ }
34624
+ } catch {}
34625
+ } else {
34626
+ try {
34627
+ _internals6.gitExec(["rev-parse", "--abbrev-ref", `${currentBranch}@{upstream}`], cwd);
34628
+ } catch {
34629
+ try {
34630
+ const localSha = _internals6.gitExec(["rev-parse", "HEAD"], cwd).trim();
34631
+ const remoteSha = _internals6.gitExec(["rev-parse", targetBranch], cwd).trim();
34632
+ if (localSha !== remoteSha) {
34633
+ return {
34634
+ success: false,
34635
+ targetBranch,
34636
+ previousBranch: currentBranch,
34637
+ message: `Cannot reset: branch ${currentBranch} is local-only and diverges from ${defaultBranch}. Push or check manually.`,
34638
+ branchDeleted: false,
34639
+ changesDiscarded: false,
34640
+ warnings
34641
+ };
34642
+ }
34643
+ } catch {
34644
+ return {
34645
+ success: false,
34646
+ targetBranch,
34647
+ previousBranch: currentBranch,
34648
+ message: `Cannot reset: unable to compare ${currentBranch} with ${defaultBranch}`,
34649
+ branchDeleted: false,
34650
+ changesDiscarded: false,
34651
+ warnings
34652
+ };
34653
+ }
34654
+ }
34655
+ }
34656
+ try {
34657
+ _internals6.gitExec(["fetch", "--prune", "origin"], cwd);
34658
+ } catch (err) {
34659
+ return {
34660
+ success: false,
34661
+ targetBranch,
34662
+ previousBranch: currentBranch,
34663
+ message: `Cannot reset: fetch failed \u2014 ${err instanceof Error ? err.message : String(err)}`,
34664
+ branchDeleted: false,
34665
+ changesDiscarded: false,
34666
+ warnings
34667
+ };
34668
+ }
34669
+ const previousBranch = currentBranch;
34670
+ let switchedBranch = false;
34671
+ if (currentBranch !== defaultBranch) {
34672
+ try {
34673
+ _internals6.gitExec(["checkout", defaultBranch], cwd);
34674
+ switchedBranch = true;
34675
+ } catch (err) {
34676
+ return {
34677
+ success: false,
34678
+ targetBranch,
34679
+ previousBranch,
34680
+ message: `Checkout to ${defaultBranch} failed: ${err instanceof Error ? err.message : String(err)}`,
34681
+ branchDeleted: false,
34682
+ changesDiscarded: false,
34683
+ warnings
34684
+ };
34685
+ }
34686
+ }
34687
+ try {
34688
+ _internals6.gitExec(["reset", "--hard", targetBranch], cwd);
34689
+ } catch (err) {
34690
+ return {
34691
+ success: false,
34692
+ targetBranch,
34693
+ previousBranch,
34694
+ message: `Reset to ${targetBranch} failed: ${err instanceof Error ? err.message : String(err)}`,
34695
+ branchDeleted: false,
34696
+ changesDiscarded: false,
34697
+ warnings
34698
+ };
34699
+ }
34700
+ let changesDiscarded = false;
34701
+ if (hasUncommittedChanges(cwd)) {
34702
+ let discardSucceeded = false;
34703
+ for (let retry = 0;retry < 4; retry++) {
34704
+ if (retry > 0 && process.platform === "win32") {
34705
+ const endTime = Date.now() + 500;
34706
+ while (Date.now() < endTime) {}
34707
+ }
34708
+ try {
34709
+ _internals6.gitExec(["checkout", "--", "."], cwd);
34710
+ discardSucceeded = true;
34711
+ break;
34712
+ } catch {}
34713
+ }
34714
+ if (!discardSucceeded) {
34715
+ warnings.push("Could not discard all uncommitted changes after reset");
34716
+ }
34717
+ changesDiscarded = discardSucceeded;
34718
+ }
34719
+ try {
34720
+ _internals6.gitExec(["clean", "-fd"], cwd);
34721
+ } catch {
34722
+ warnings.push("Could not clean untracked files");
34723
+ }
34724
+ let branchDeleted = false;
34725
+ if (switchedBranch && previousBranch !== defaultBranch) {
34726
+ try {
34727
+ const mergedOutput = _internals6.gitExec(["branch", "--merged", defaultBranch], cwd);
34728
+ const isMerged = mergedOutput.split(`
34729
+ `).some((line) => line.trim() === previousBranch || line.trim() === `* ${previousBranch}`);
34730
+ if (isMerged) {
34731
+ _internals6.gitExec(["branch", "-d", previousBranch], cwd);
34732
+ branchDeleted = true;
34733
+ } else {
34734
+ warnings.push(`Branch ${previousBranch} is not merged into ${defaultBranch} \u2014 keeping it`);
34735
+ }
34736
+ } catch {
34737
+ warnings.push(`Could not delete branch ${previousBranch}`);
34738
+ }
34739
+ }
34740
+ if (options?.pruneBranches) {
34741
+ try {
34742
+ const mergedOutput = _internals6.gitExec(["branch", "--merged", defaultBranch], cwd);
34743
+ const mergedLines = mergedOutput.split(`
34744
+ `);
34745
+ for (const line of mergedLines) {
34746
+ const trimmedLine = line.trim();
34747
+ if (!trimmedLine || trimmedLine.startsWith("*") || trimmedLine === defaultBranch) {
34748
+ continue;
34749
+ }
34750
+ try {
34751
+ _internals6.gitExec(["branch", "-d", trimmedLine], cwd);
34752
+ } catch {
34753
+ warnings.push(`Could not prune branch: ${trimmedLine}`);
34754
+ }
34755
+ }
34756
+ } catch (err) {
34757
+ warnings.push(`Prune failed: ${err instanceof Error ? err.message : String(err)}`);
34758
+ }
34759
+ }
34760
+ return {
34761
+ success: true,
34762
+ targetBranch,
34763
+ previousBranch,
34764
+ message: branchDeleted ? `Reset to ${defaultBranch} and deleted branch ${previousBranch}` : `Reset to ${defaultBranch}`,
34765
+ branchDeleted,
34766
+ changesDiscarded,
34767
+ warnings
34768
+ };
34769
+ } catch (err) {
34770
+ return {
34771
+ success: false,
34772
+ targetBranch: "",
34773
+ previousBranch: "",
34774
+ message: `Unexpected error: ${err instanceof Error ? err.message : String(err)}`,
34775
+ branchDeleted: false,
34776
+ changesDiscarded: false,
34777
+ warnings
34778
+ };
34779
+ }
34780
+ }
34493
34781
  var GIT_TIMEOUT_MS2 = 30000, _internals6;
34494
34782
  var init_branch = __esm(() => {
34495
34783
  init_logger();
@@ -34497,10 +34785,81 @@ var init_branch = __esm(() => {
34497
34785
  gitExec: gitExec2,
34498
34786
  detectDefaultRemoteBranch,
34499
34787
  getDefaultBaseBranch,
34500
- resetToRemoteBranch
34788
+ resetToRemoteBranch,
34789
+ resetToMainAfterMerge
34501
34790
  };
34502
34791
  });
34503
34792
 
34793
+ // src/background/event-bus.ts
34794
+ class AutomationEventBus {
34795
+ listeners = new Map;
34796
+ eventHistory = [];
34797
+ maxHistorySize;
34798
+ constructor(options) {
34799
+ this.maxHistorySize = options?.maxHistorySize ?? 100;
34800
+ }
34801
+ subscribe(type, listener) {
34802
+ if (!this.listeners.has(type)) {
34803
+ this.listeners.set(type, new Set);
34804
+ }
34805
+ this.listeners.get(type).add(listener);
34806
+ return () => {
34807
+ this.listeners.get(type)?.delete(listener);
34808
+ };
34809
+ }
34810
+ async publish(type, payload, source) {
34811
+ const event = {
34812
+ type,
34813
+ timestamp: Date.now(),
34814
+ payload,
34815
+ source
34816
+ };
34817
+ this.eventHistory.push(event);
34818
+ if (this.eventHistory.length > this.maxHistorySize) {
34819
+ this.eventHistory.shift();
34820
+ }
34821
+ log(`[EventBus] ${type}`, {
34822
+ source,
34823
+ payload: typeof payload === "object" ? "..." : payload
34824
+ });
34825
+ const listeners = this.listeners.get(type);
34826
+ if (listeners) {
34827
+ await Promise.all(Array.from(listeners).map(async (listener) => {
34828
+ try {
34829
+ await listener(event);
34830
+ } catch (error93) {
34831
+ log(`[EventBus] Listener error for ${type}`, { error: error93 });
34832
+ }
34833
+ }));
34834
+ }
34835
+ }
34836
+ getHistory(types) {
34837
+ if (!types || types.length === 0) {
34838
+ return [...this.eventHistory];
34839
+ }
34840
+ return this.eventHistory.filter((e) => types.includes(e.type));
34841
+ }
34842
+ clearHistory() {
34843
+ this.eventHistory = [];
34844
+ }
34845
+ getListenerCount(type) {
34846
+ return this.listeners.get(type)?.size ?? 0;
34847
+ }
34848
+ hasListeners(type) {
34849
+ return this.getListenerCount(type) > 0;
34850
+ }
34851
+ }
34852
+ function getGlobalEventBus() {
34853
+ if (!globalEventBus) {
34854
+ globalEventBus = new AutomationEventBus;
34855
+ }
34856
+ return globalEventBus;
34857
+ }
34858
+ var globalEventBus = null;
34859
+ var init_event_bus = __esm(() => {
34860
+ init_utils();
34861
+ });
34862
+
34504
34863
  // src/hooks/knowledge-store.ts
34505
34864
  import { existsSync as existsSync7 } from "fs";
34506
34865
  import { appendFile as appendFile2, mkdir as mkdir2, readFile as readFile3, writeFile as writeFile3 } from "fs/promises";
@@ -34540,13 +34899,59 @@ async function readKnowledge(filePath) {
34540
34899
  if (!trimmed)
34541
34900
  continue;
34542
34901
  try {
34543
- results.push(JSON.parse(trimmed));
34902
+ const raw = JSON.parse(trimmed);
34903
+ results.push(normalizeEntry(raw));
34544
34904
  } catch {
34545
34905
  console.warn(`[knowledge-store] Skipping corrupted JSONL line in ${filePath}: ${trimmed.slice(0, 80)}`);
34546
34906
  }
34547
34907
  }
34548
34908
  return results;
34549
34909
  }
34910
+ function normalizeEntry(raw) {
34911
+ if (!raw || typeof raw !== "object")
34912
+ return raw;
34913
+ const obj = raw;
34914
+ if (!("retrieval_outcomes" in obj))
34915
+ return raw;
34916
+ const ro = obj.retrieval_outcomes;
34917
+ if (ro && typeof ro === "object") {
34918
+ if (typeof ro.shown_count !== "number") {
34919
+ ro.shown_count = typeof ro.applied_count === "number" ? ro.applied_count : 0;
34920
+ }
34921
+ if (typeof ro.acknowledged_count !== "number")
34922
+ ro.acknowledged_count = 0;
34923
+ if (typeof ro.applied_explicit_count !== "number") {
34924
+ ro.applied_explicit_count = 0;
34925
+ }
34926
+ if (typeof ro.ignored_count !== "number")
34927
+ ro.ignored_count = 0;
34928
+ if (typeof ro.violated_count !== "number")
34929
+ ro.violated_count = 0;
34930
+ if (typeof ro.succeeded_after_shown_count !== "number") {
34931
+ ro.succeeded_after_shown_count = typeof ro.succeeded_after_count === "number" ? ro.succeeded_after_count : 0;
34932
+ }
34933
+ if (typeof ro.failed_after_shown_count !== "number") {
34934
+ ro.failed_after_shown_count = typeof ro.failed_after_count === "number" ? ro.failed_after_count : 0;
34935
+ }
34936
+ }
34937
+ const arrayFields = [
34938
+ "triggers",
34939
+ "required_actions",
34940
+ "forbidden_actions",
34941
+ "applies_to_agents",
34942
+ "applies_to_tools",
34943
+ "verification_checks",
34944
+ "source_refs",
34945
+ "source_knowledge_ids"
34946
+ ];
34947
+ for (const f of arrayFields) {
34948
+ const v = obj[f];
34949
+ if (v !== undefined && !Array.isArray(v)) {
34950
+ delete obj[f];
34951
+ }
34952
+ }
34953
+ return raw;
34954
+ }
34550
34955
  async function readRejectedLessons(directory) {
34551
34956
  return readKnowledge(resolveSwarmRejectedPath(directory));
34552
34957
  }
@@ -34668,78 +35073,9 @@ var init_knowledge_store = __esm(() => {
34668
35073
  import_proper_lockfile3 = __toESM(require_proper_lockfile(), 1);
34669
35074
  });
34670
35075
 
34671
- // src/hooks/knowledge-reader.ts
34672
- import { existsSync as existsSync8 } from "fs";
34673
- import { mkdir as mkdir3, readFile as readFile4, writeFile as writeFile4 } from "fs/promises";
34674
- import * as path11 from "path";
34675
- async function updateRetrievalOutcome(directory, phaseInfo, phaseSucceeded) {
34676
- const shownFile = path11.join(directory, ".swarm", ".knowledge-shown.json");
34677
- try {
34678
- if (!existsSync8(shownFile)) {
34679
- return;
34680
- }
34681
- const content = await readFile4(shownFile, "utf-8");
34682
- const shownData = JSON.parse(content);
34683
- const shownIds = shownData[phaseInfo];
34684
- if (!shownIds || shownIds.length === 0) {
34685
- return;
34686
- }
34687
- const swarmPath = resolveSwarmKnowledgePath(directory);
34688
- const entries = await readKnowledge(swarmPath);
34689
- let updated = false;
34690
- const foundInSwarm = new Set;
34691
- for (const entry of entries) {
34692
- if (shownIds.includes(entry.id)) {
34693
- entry.retrieval_outcomes.applied_count++;
34694
- if (phaseSucceeded) {
34695
- entry.retrieval_outcomes.succeeded_after_count++;
34696
- } else {
34697
- entry.retrieval_outcomes.failed_after_count++;
34698
- }
34699
- updated = true;
34700
- foundInSwarm.add(entry.id);
34701
- }
34702
- }
34703
- if (updated) {
34704
- await rewriteKnowledge(swarmPath, entries);
34705
- }
34706
- const remainingIds = shownIds.filter((id) => !foundInSwarm.has(id));
34707
- if (remainingIds.length === 0) {
34708
- delete shownData[phaseInfo];
34709
- await writeFile4(shownFile, JSON.stringify(shownData, null, 2), "utf-8");
34710
- return;
34711
- }
34712
- const hivePath = resolveHiveKnowledgePath();
34713
- const hiveEntries = await readKnowledge(hivePath);
34714
- let hiveUpdated = false;
34715
- for (const entry of hiveEntries) {
34716
- if (remainingIds.includes(entry.id)) {
34717
- entry.retrieval_outcomes.applied_count++;
34718
- if (phaseSucceeded) {
34719
- entry.retrieval_outcomes.succeeded_after_count++;
34720
- } else {
34721
- entry.retrieval_outcomes.failed_after_count++;
34722
- }
34723
- hiveUpdated = true;
34724
- }
34725
- }
34726
- if (hiveUpdated) {
34727
- await rewriteKnowledge(hivePath, hiveEntries);
34728
- }
34729
- delete shownData[phaseInfo];
34730
- await writeFile4(shownFile, JSON.stringify(shownData, null, 2), "utf-8");
34731
- } catch {
34732
- warn("[swarm] Knowledge: failed to update retrieval outcomes");
34733
- }
34734
- }
34735
- var init_knowledge_reader = __esm(() => {
34736
- init_logger();
34737
- init_knowledge_store();
34738
- });
34739
-
34740
35076
  // src/hooks/knowledge-validator.ts
34741
- import { appendFile as appendFile3, mkdir as mkdir4, writeFile as writeFile5 } from "fs/promises";
34742
- import * as path12 from "path";
35077
+ import { appendFile as appendFile3, mkdir as mkdir3, writeFile as writeFile4 } from "fs/promises";
35078
+ import * as path11 from "path";
34743
35079
  function normalizeText(text) {
34744
35080
  return text.normalize("NFKC").toLowerCase().replace(/[^\w\s]/g, " ").replace(/\s+/g, " ").trim();
34745
35081
  }
@@ -34893,11 +35229,11 @@ async function quarantineEntry(directory, entryId, reason, reportedBy) {
34893
35229
  return;
34894
35230
  }
34895
35231
  const sanitizedReason = reason.slice(0, 500).replace(/[\x00-\x08\x0b-\x0c\x0e-\x1f\x7f\x0d]/g, "");
34896
- const knowledgePath = path12.join(directory, ".swarm", "knowledge.jsonl");
34897
- const quarantinePath = path12.join(directory, ".swarm", "knowledge-quarantined.jsonl");
34898
- const rejectedPath = path12.join(directory, ".swarm", "knowledge-rejected.jsonl");
34899
- const swarmDir = path12.join(directory, ".swarm");
34900
- await mkdir4(swarmDir, { recursive: true });
35232
+ const knowledgePath = path11.join(directory, ".swarm", "knowledge.jsonl");
35233
+ const quarantinePath = path11.join(directory, ".swarm", "knowledge-quarantined.jsonl");
35234
+ const rejectedPath = path11.join(directory, ".swarm", "knowledge-rejected.jsonl");
35235
+ const swarmDir = path11.join(directory, ".swarm");
35236
+ await mkdir3(swarmDir, { recursive: true });
34901
35237
  let release;
34902
35238
  try {
34903
35239
  release = await import_proper_lockfile4.default.lock(swarmDir, {
@@ -34918,7 +35254,7 @@ async function quarantineEntry(directory, entryId, reason, reportedBy) {
34918
35254
  const jsonlContent = remaining.length > 0 ? `${remaining.map((e) => JSON.stringify(e)).join(`
34919
35255
  `)}
34920
35256
  ` : "";
34921
- await writeFile5(knowledgePath, jsonlContent, "utf-8");
35257
+ await writeFile4(knowledgePath, jsonlContent, "utf-8");
34922
35258
  await appendFile3(quarantinePath, `${JSON.stringify(quarantined)}
34923
35259
  `, "utf-8");
34924
35260
  const quarantinedEntries = await readKnowledge(quarantinePath);
@@ -34927,7 +35263,7 @@ async function quarantineEntry(directory, entryId, reason, reportedBy) {
34927
35263
  const capContent = trimmed.length > 0 ? `${trimmed.map((e) => JSON.stringify(e)).join(`
34928
35264
  `)}
34929
35265
  ` : "";
34930
- await writeFile5(quarantinePath, capContent, "utf-8");
35266
+ await writeFile4(quarantinePath, capContent, "utf-8");
34931
35267
  }
34932
35268
  const rejectedRecord = {
34933
35269
  id: entryId,
@@ -34953,11 +35289,11 @@ async function restoreEntry(directory, entryId) {
34953
35289
  warn("[knowledge-validator] restoreEntry: invalid entryId rejected");
34954
35290
  return;
34955
35291
  }
34956
- const knowledgePath = path12.join(directory, ".swarm", "knowledge.jsonl");
34957
- const quarantinePath = path12.join(directory, ".swarm", "knowledge-quarantined.jsonl");
34958
- const rejectedPath = path12.join(directory, ".swarm", "knowledge-rejected.jsonl");
34959
- const swarmDir = path12.join(directory, ".swarm");
34960
- await mkdir4(swarmDir, { recursive: true });
35292
+ const knowledgePath = path11.join(directory, ".swarm", "knowledge.jsonl");
35293
+ const quarantinePath = path11.join(directory, ".swarm", "knowledge-quarantined.jsonl");
35294
+ const rejectedPath = path11.join(directory, ".swarm", "knowledge-rejected.jsonl");
35295
+ const swarmDir = path11.join(directory, ".swarm");
35296
+ await mkdir3(swarmDir, { recursive: true });
34961
35297
  let release;
34962
35298
  try {
34963
35299
  release = await import_proper_lockfile4.default.lock(swarmDir, {
@@ -34973,7 +35309,7 @@ async function restoreEntry(directory, entryId) {
34973
35309
  const jsonlContent = remaining.length > 0 ? `${remaining.map((e) => JSON.stringify(e)).join(`
34974
35310
  `)}
34975
35311
  ` : "";
34976
- await writeFile5(quarantinePath, jsonlContent, "utf-8");
35312
+ await writeFile4(quarantinePath, jsonlContent, "utf-8");
34977
35313
  await appendFile3(knowledgePath, `${JSON.stringify(original)}
34978
35314
  `, "utf-8");
34979
35315
  const rejectedEntries = await readKnowledge(rejectedPath);
@@ -34981,14 +35317,14 @@ async function restoreEntry(directory, entryId) {
34981
35317
  const rejectedContent = filtered.length > 0 ? `${filtered.map((e) => JSON.stringify(e)).join(`
34982
35318
  `)}
34983
35319
  ` : "";
34984
- await writeFile5(rejectedPath, rejectedContent, "utf-8");
35320
+ await writeFile4(rejectedPath, rejectedContent, "utf-8");
34985
35321
  } finally {
34986
35322
  if (release) {
34987
35323
  await release();
34988
35324
  }
34989
35325
  }
34990
35326
  }
34991
- var import_proper_lockfile4, DANGEROUS_COMMAND_PATTERNS, SECURITY_DEGRADING_PATTERNS, INVISIBLE_FORMAT_CHARS, INJECTION_PATTERNS, VALID_CATEGORIES, TECH_REFERENCE_WORDS, ACTION_VERB_WORDS, NEGATION_PAIRS;
35327
+ var import_proper_lockfile4, DANGEROUS_COMMAND_PATTERNS, SECURITY_DEGRADING_PATTERNS, INVISIBLE_FORMAT_CHARS, INJECTION_PATTERNS, VALID_CATEGORIES, TECH_REFERENCE_WORDS, ACTION_VERB_WORDS, NEGATION_PAIRS, VALID_DIRECTIVE_PRIORITIES;
34992
35328
  var init_knowledge_validator = __esm(() => {
34993
35329
  init_logger();
34994
35330
  init_knowledge_store();
@@ -35094,6 +35430,329 @@ var init_knowledge_validator = __esm(() => {
35094
35430
  ["use", "don't use"],
35095
35431
  ["recommended", "not recommended"]
35096
35432
  ];
35433
+ VALID_DIRECTIVE_PRIORITIES = new Set([
35434
+ "low",
35435
+ "medium",
35436
+ "high",
35437
+ "critical"
35438
+ ]);
35439
+ });
35440
+
35441
+ // src/hooks/curator.ts
35442
+ var init_curator = __esm(() => {
35443
+ init_event_bus();
35444
+ init_schema();
35445
+ init_manager();
35446
+ init_state();
35447
+ init_bun_compat();
35448
+ init_logger();
35449
+ init_knowledge_store();
35450
+ init_knowledge_validator();
35451
+ init_utils2();
35452
+ });
35453
+
35454
+ // src/hooks/hive-promoter.ts
35455
+ import path12 from "path";
35456
+ function isAlreadyInHive(entry, hiveEntries, threshold) {
35457
+ return findNearDuplicate(entry.lesson, hiveEntries, threshold) !== undefined;
35458
+ }
35459
+ function countDistinctPhases(confirmedBy) {
35460
+ const phaseNumbers = new Set;
35461
+ for (const record3 of confirmedBy) {
35462
+ phaseNumbers.add(record3.phase_number);
35463
+ }
35464
+ return phaseNumbers.size;
35465
+ }
35466
+ function countDistinctProjects(confirmedBy) {
35467
+ const projectNames = new Set;
35468
+ for (const record3 of confirmedBy) {
35469
+ projectNames.add(record3.project_name);
35470
+ }
35471
+ return projectNames.size;
35472
+ }
35473
+ function hasProjectConfirmation(hiveEntry, projectName) {
35474
+ return hiveEntry.confirmed_by.some((record3) => record3.project_name === projectName);
35475
+ }
35476
+ function calculateEncounterScore(currentScore, isSameProject, config3) {
35477
+ const weight = isSameProject ? config3.same_project_weight : config3.cross_project_weight;
35478
+ const increment = config3.encounter_increment * weight;
35479
+ const newScore = currentScore + increment;
35480
+ return Math.min(Math.max(newScore, config3.min_encounter_score), config3.max_encounter_score);
35481
+ }
35482
+ function getEntryAgeMs(createdAt) {
35483
+ const createdTime = new Date(createdAt).getTime();
35484
+ if (Number.isNaN(createdTime))
35485
+ return 0;
35486
+ return Date.now() - createdTime;
35487
+ }
35488
+ async function checkHivePromotions(swarmEntries, config3) {
35489
+ let newPromotions = 0;
35490
+ let encountersIncremented = 0;
35491
+ let advancements = 0;
35492
+ if (config3.hive_enabled === false) {
35493
+ return {
35494
+ timestamp: new Date().toISOString(),
35495
+ new_promotions: 0,
35496
+ encounters_incremented: 0,
35497
+ advancements: 0,
35498
+ total_hive_entries: 0
35499
+ };
35500
+ }
35501
+ const hiveEntries = await readKnowledge(resolveHiveKnowledgePath());
35502
+ for (const swarmEntry of swarmEntries) {
35503
+ if (isAlreadyInHive(swarmEntry, hiveEntries, config3.dedup_threshold)) {
35504
+ continue;
35505
+ }
35506
+ let shouldPromote = false;
35507
+ if (swarmEntry.hive_eligible === true && countDistinctPhases(swarmEntry.confirmed_by) >= 3) {
35508
+ shouldPromote = true;
35509
+ }
35510
+ if (swarmEntry.tags.includes("hive-fast-track")) {
35511
+ shouldPromote = true;
35512
+ }
35513
+ const ageMs = getEntryAgeMs(swarmEntry.created_at);
35514
+ const ageThresholdMs = config3.auto_promote_days * 86400000;
35515
+ if (ageMs >= ageThresholdMs) {
35516
+ shouldPromote = true;
35517
+ }
35518
+ if (!shouldPromote) {
35519
+ continue;
35520
+ }
35521
+ const validationResult = validateLesson(swarmEntry.lesson, hiveEntries.map((e) => e.lesson), {
35522
+ category: swarmEntry.category,
35523
+ scope: swarmEntry.scope,
35524
+ confidence: swarmEntry.confidence
35525
+ });
35526
+ if (validationResult.severity === "error") {
35527
+ const rejectedLesson = {
35528
+ id: crypto.randomUUID(),
35529
+ lesson: swarmEntry.lesson,
35530
+ rejection_reason: validationResult.reason || "validation failed for hive promotion",
35531
+ rejected_at: new Date().toISOString(),
35532
+ rejection_layer: validationResult.layer || 2
35533
+ };
35534
+ const hiveRejectedPath = resolveHiveRejectedPath();
35535
+ await appendKnowledge(hiveRejectedPath, rejectedLesson);
35536
+ continue;
35537
+ }
35538
+ const newHiveEntry = {
35539
+ id: crypto.randomUUID(),
35540
+ tier: "hive",
35541
+ lesson: swarmEntry.lesson,
35542
+ category: swarmEntry.category,
35543
+ tags: swarmEntry.tags,
35544
+ scope: swarmEntry.scope,
35545
+ confidence: 0.5,
35546
+ status: "candidate",
35547
+ confirmed_by: [],
35548
+ retrieval_outcomes: {
35549
+ applied_count: 0,
35550
+ succeeded_after_count: 0,
35551
+ failed_after_count: 0
35552
+ },
35553
+ schema_version: config3.schema_version,
35554
+ created_at: new Date().toISOString(),
35555
+ updated_at: new Date().toISOString(),
35556
+ source_project: swarmEntry.project_name,
35557
+ encounter_score: config3.initial_encounter_score
35558
+ };
35559
+ await appendKnowledge(resolveHiveKnowledgePath(), newHiveEntry);
35560
+ newPromotions++;
35561
+ hiveEntries.push(newHiveEntry);
35562
+ }
35563
+ let hiveModified = false;
35564
+ for (const hiveEntry of hiveEntries) {
35565
+ const nearDuplicate = findNearDuplicate(hiveEntry.lesson, swarmEntries, config3.dedup_threshold);
35566
+ if (!nearDuplicate) {
35567
+ continue;
35568
+ }
35569
+ const isSameProject = nearDuplicate.project_name === hiveEntry.source_project;
35570
+ if (hasProjectConfirmation(hiveEntry, nearDuplicate.project_name)) {
35571
+ continue;
35572
+ }
35573
+ const newConfirmation = {
35574
+ project_name: nearDuplicate.project_name,
35575
+ confirmed_at: new Date().toISOString()
35576
+ };
35577
+ hiveEntry.confirmed_by.push(newConfirmation);
35578
+ const currentScore = hiveEntry.encounter_score ?? 1;
35579
+ hiveEntry.encounter_score = calculateEncounterScore(currentScore, isSameProject, config3);
35580
+ encountersIncremented++;
35581
+ hiveEntry.updated_at = new Date().toISOString();
35582
+ if (hiveEntry.status === "candidate" && countDistinctProjects(hiveEntry.confirmed_by) >= 3) {
35583
+ hiveEntry.status = "established";
35584
+ advancements++;
35585
+ }
35586
+ hiveModified = true;
35587
+ }
35588
+ if (hiveModified) {
35589
+ await rewriteKnowledge(resolveHiveKnowledgePath(), hiveEntries);
35590
+ }
35591
+ if (newPromotions > 0 || hiveModified) {
35592
+ await enforceKnowledgeCap(resolveHiveKnowledgePath(), config3.hive_max_entries);
35593
+ }
35594
+ return {
35595
+ timestamp: new Date().toISOString(),
35596
+ new_promotions: newPromotions,
35597
+ encounters_incremented: encountersIncremented,
35598
+ advancements,
35599
+ total_hive_entries: hiveEntries.length
35600
+ };
35601
+ }
35602
+ async function promoteToHive(directory, lesson, category) {
35603
+ const trimmedLesson = lesson.trim();
35604
+ const hiveEntries = await readKnowledge(resolveHiveKnowledgePath());
35605
+ const validationResult = validateLesson(trimmedLesson, hiveEntries.map((e) => e.lesson), {
35606
+ category: category || "process",
35607
+ scope: "global",
35608
+ confidence: 1
35609
+ });
35610
+ if (validationResult.severity === "error") {
35611
+ throw new Error(`Lesson rejected by validator: ${validationResult.reason}`);
35612
+ }
35613
+ if (findNearDuplicate(trimmedLesson, hiveEntries, 0.6)) {
35614
+ return `Lesson already exists in hive (near-duplicate).`;
35615
+ }
35616
+ const newHiveEntry = {
35617
+ id: crypto.randomUUID(),
35618
+ tier: "hive",
35619
+ lesson: trimmedLesson,
35620
+ category: category || "process",
35621
+ tags: [],
35622
+ scope: "global",
35623
+ confidence: 1,
35624
+ status: "promoted",
35625
+ confirmed_by: [],
35626
+ retrieval_outcomes: {
35627
+ applied_count: 0,
35628
+ succeeded_after_count: 0,
35629
+ failed_after_count: 0
35630
+ },
35631
+ schema_version: 1,
35632
+ created_at: new Date().toISOString(),
35633
+ updated_at: new Date().toISOString(),
35634
+ source_project: path12.basename(directory) || "unknown",
35635
+ encounter_score: 1
35636
+ };
35637
+ await appendKnowledge(resolveHiveKnowledgePath(), newHiveEntry);
35638
+ return `Promoted to hive: "${trimmedLesson.slice(0, 50)}${trimmedLesson.length > 50 ? "..." : ""}" (confidence: 1.0, source: manual)`;
35639
+ }
35640
+ async function promoteFromSwarm(directory, lessonId) {
35641
+ const swarmEntries = await readKnowledge(resolveSwarmKnowledgePath(directory));
35642
+ const swarmEntry = swarmEntries.find((e) => e.id === lessonId);
35643
+ if (!swarmEntry) {
35644
+ throw new Error(`Lesson ${lessonId} not found in .swarm/knowledge.jsonl`);
35645
+ }
35646
+ const hiveEntries = await readKnowledge(resolveHiveKnowledgePath());
35647
+ const validationResult = validateLesson(swarmEntry.lesson, hiveEntries.map((e) => e.lesson), {
35648
+ category: swarmEntry.category,
35649
+ scope: swarmEntry.scope,
35650
+ confidence: swarmEntry.confidence
35651
+ });
35652
+ if (validationResult.severity === "error") {
35653
+ throw new Error(`Lesson rejected by validator: ${validationResult.reason}`);
35654
+ }
35655
+ if (findNearDuplicate(swarmEntry.lesson, hiveEntries, 0.6)) {
35656
+ return `Lesson already exists in hive (near-duplicate).`;
35657
+ }
35658
+ const newHiveEntry = {
35659
+ id: crypto.randomUUID(),
35660
+ tier: "hive",
35661
+ lesson: swarmEntry.lesson,
35662
+ category: swarmEntry.category,
35663
+ tags: swarmEntry.tags,
35664
+ scope: swarmEntry.scope,
35665
+ confidence: 1,
35666
+ status: "promoted",
35667
+ confirmed_by: [],
35668
+ retrieval_outcomes: {
35669
+ applied_count: 0,
35670
+ succeeded_after_count: 0,
35671
+ failed_after_count: 0
35672
+ },
35673
+ schema_version: 1,
35674
+ created_at: new Date().toISOString(),
35675
+ updated_at: new Date().toISOString(),
35676
+ source_project: swarmEntry.project_name,
35677
+ encounter_score: 1
35678
+ };
35679
+ await appendKnowledge(resolveHiveKnowledgePath(), newHiveEntry);
35680
+ return `Promoted lesson ${lessonId} from swarm to hive: "${swarmEntry.lesson.slice(0, 50)}${swarmEntry.lesson.length > 50 ? "..." : ""}"`;
35681
+ }
35682
+ var init_hive_promoter = __esm(() => {
35683
+ init_curator();
35684
+ init_knowledge_store();
35685
+ init_knowledge_validator();
35686
+ init_utils2();
35687
+ });
35688
+
35689
+ // src/hooks/knowledge-reader.ts
35690
+ import { existsSync as existsSync8 } from "fs";
35691
+ import { mkdir as mkdir4, readFile as readFile4, writeFile as writeFile5 } from "fs/promises";
35692
+ import * as path13 from "path";
35693
+ async function updateRetrievalOutcome(directory, phaseInfo, phaseSucceeded) {
35694
+ const shownFile = path13.join(directory, ".swarm", ".knowledge-shown.json");
35695
+ try {
35696
+ if (!existsSync8(shownFile)) {
35697
+ return;
35698
+ }
35699
+ const content = await readFile4(shownFile, "utf-8");
35700
+ const shownData = JSON.parse(content);
35701
+ const shownIds = shownData[phaseInfo];
35702
+ if (!shownIds || shownIds.length === 0) {
35703
+ return;
35704
+ }
35705
+ const swarmPath = resolveSwarmKnowledgePath(directory);
35706
+ const entries = await readKnowledge(swarmPath);
35707
+ let updated = false;
35708
+ const foundInSwarm = new Set;
35709
+ for (const entry of entries) {
35710
+ if (shownIds.includes(entry.id)) {
35711
+ const ro = entry.retrieval_outcomes;
35712
+ if (phaseSucceeded) {
35713
+ ro.succeeded_after_shown_count = (ro.succeeded_after_shown_count ?? 0) + 1;
35714
+ } else {
35715
+ ro.failed_after_shown_count = (ro.failed_after_shown_count ?? 0) + 1;
35716
+ }
35717
+ updated = true;
35718
+ foundInSwarm.add(entry.id);
35719
+ }
35720
+ }
35721
+ if (updated) {
35722
+ await rewriteKnowledge(swarmPath, entries);
35723
+ }
35724
+ const remainingIds = shownIds.filter((id) => !foundInSwarm.has(id));
35725
+ if (remainingIds.length === 0) {
35726
+ delete shownData[phaseInfo];
35727
+ await writeFile5(shownFile, JSON.stringify(shownData, null, 2), "utf-8");
35728
+ return;
35729
+ }
35730
+ const hivePath = resolveHiveKnowledgePath();
35731
+ const hiveEntries = await readKnowledge(hivePath);
35732
+ let hiveUpdated = false;
35733
+ for (const entry of hiveEntries) {
35734
+ if (remainingIds.includes(entry.id)) {
35735
+ const ro = entry.retrieval_outcomes;
35736
+ if (phaseSucceeded) {
35737
+ ro.succeeded_after_shown_count = (ro.succeeded_after_shown_count ?? 0) + 1;
35738
+ } else {
35739
+ ro.failed_after_shown_count = (ro.failed_after_shown_count ?? 0) + 1;
35740
+ }
35741
+ hiveUpdated = true;
35742
+ }
35743
+ }
35744
+ if (hiveUpdated) {
35745
+ await rewriteKnowledge(hivePath, hiveEntries);
35746
+ }
35747
+ delete shownData[phaseInfo];
35748
+ await writeFile5(shownFile, JSON.stringify(shownData, null, 2), "utf-8");
35749
+ } catch {
35750
+ warn("[swarm] Knowledge: failed to update retrieval outcomes");
35751
+ }
35752
+ }
35753
+ var init_knowledge_reader = __esm(() => {
35754
+ init_logger();
35755
+ init_knowledge_store();
35097
35756
  });
35098
35757
 
35099
35758
  // src/hooks/knowledge-curator.ts
@@ -35431,133 +36090,6 @@ var init_knowledge_curator = __esm(() => {
35431
36090
  };
35432
36091
  });
35433
36092
 
35434
- // src/session/snapshot-writer.ts
35435
- import { mkdirSync as mkdirSync7, renameSync as renameSync5 } from "fs";
35436
- import * as path13 from "path";
35437
- function serializeAgentSession(s) {
35438
- const gateLog = {};
35439
- const rawGateLog = s.gateLog ?? new Map;
35440
- for (const [taskId, gates] of rawGateLog) {
35441
- gateLog[taskId] = Array.from(gates ?? []);
35442
- }
35443
- const reviewerCallCount = {};
35444
- const rawReviewerCallCount = s.reviewerCallCount ?? new Map;
35445
- for (const [phase, count] of rawReviewerCallCount) {
35446
- reviewerCallCount[String(phase)] = count;
35447
- }
35448
- const partialGateWarningsIssuedForTask = Array.from(s.partialGateWarningsIssuedForTask ?? new Set);
35449
- const catastrophicPhaseWarnings = Array.from(s.catastrophicPhaseWarnings ?? new Set);
35450
- const phaseAgentsDispatched = Array.from(s.phaseAgentsDispatched ?? new Set);
35451
- const lastCompletedPhaseAgentsDispatched = Array.from(s.lastCompletedPhaseAgentsDispatched ?? new Set);
35452
- const windows = {};
35453
- const rawWindows = s.windows ?? {};
35454
- for (const [key, win] of Object.entries(rawWindows)) {
35455
- windows[key] = {
35456
- id: win.id,
35457
- agentName: win.agentName,
35458
- startedAtMs: win.startedAtMs,
35459
- toolCalls: win.toolCalls,
35460
- consecutiveErrors: win.consecutiveErrors,
35461
- hardLimitHit: win.hardLimitHit,
35462
- lastSuccessTimeMs: win.lastSuccessTimeMs,
35463
- recentToolCalls: win.recentToolCalls,
35464
- warningIssued: win.warningIssued,
35465
- warningReason: win.warningReason,
35466
- transientRetryCount: win.transientRetryCount ?? 0
35467
- };
35468
- }
35469
- return {
35470
- agentName: s.agentName,
35471
- lastToolCallTime: s.lastToolCallTime,
35472
- lastAgentEventTime: s.lastAgentEventTime,
35473
- delegationActive: s.delegationActive,
35474
- activeInvocationId: s.activeInvocationId,
35475
- lastInvocationIdByAgent: s.lastInvocationIdByAgent ?? {},
35476
- windows,
35477
- lastCompactionHint: s.lastCompactionHint ?? 0,
35478
- architectWriteCount: s.architectWriteCount ?? 0,
35479
- lastCoderDelegationTaskId: s.lastCoderDelegationTaskId ?? null,
35480
- currentTaskId: s.currentTaskId ?? null,
35481
- turboMode: s.turboMode ?? false,
35482
- gateLog,
35483
- reviewerCallCount,
35484
- lastGateFailure: s.lastGateFailure ?? null,
35485
- partialGateWarningsIssuedForTask,
35486
- selfFixAttempted: s.selfFixAttempted ?? false,
35487
- selfCodingWarnedAtCount: s.selfCodingWarnedAtCount ?? 0,
35488
- catastrophicPhaseWarnings,
35489
- lastPhaseCompleteTimestamp: s.lastPhaseCompleteTimestamp ?? 0,
35490
- lastPhaseCompletePhase: s.lastPhaseCompletePhase ?? 0,
35491
- phaseAgentsDispatched,
35492
- lastCompletedPhaseAgentsDispatched,
35493
- qaSkipCount: s.qaSkipCount ?? 0,
35494
- qaSkipTaskIds: s.qaSkipTaskIds ?? [],
35495
- pendingAdvisoryMessages: s.pendingAdvisoryMessages ?? [],
35496
- taskWorkflowStates: Object.fromEntries(s.taskWorkflowStates ?? new Map),
35497
- ...s.scopeViolationDetected !== undefined && {
35498
- scopeViolationDetected: s.scopeViolationDetected
35499
- },
35500
- model_fallback_index: s.model_fallback_index ?? 0,
35501
- modelFallbackExhausted: s.modelFallbackExhausted ?? false,
35502
- coderRevisions: s.coderRevisions ?? 0,
35503
- revisionLimitHit: s.revisionLimitHit ?? false,
35504
- fullAutoMode: s.fullAutoMode ?? false,
35505
- fullAutoInteractionCount: s.fullAutoInteractionCount ?? 0,
35506
- fullAutoDeadlockCount: s.fullAutoDeadlockCount ?? 0,
35507
- fullAutoLastQuestionHash: s.fullAutoLastQuestionHash ?? null,
35508
- sessionRehydratedAt: s.sessionRehydratedAt ?? 0
35509
- };
35510
- }
35511
- async function writeSnapshot(directory, state) {
35512
- try {
35513
- const snapshot = {
35514
- version: 2,
35515
- writtenAt: Date.now(),
35516
- toolAggregates: Object.fromEntries(state.toolAggregates),
35517
- activeAgent: Object.fromEntries(state.activeAgent),
35518
- delegationChains: Object.fromEntries(state.delegationChains),
35519
- agentSessions: {}
35520
- };
35521
- for (const [sessionId, sessionState] of state.agentSessions) {
35522
- snapshot.agentSessions[sessionId] = serializeAgentSession(sessionState);
35523
- }
35524
- const content = JSON.stringify(snapshot, null, 2);
35525
- const resolvedPath = validateSwarmPath(directory, "session/state.json");
35526
- const dir = path13.dirname(resolvedPath);
35527
- mkdirSync7(dir, { recursive: true });
35528
- const tempPath = `${resolvedPath}.tmp.${Date.now()}.${Math.random().toString(36).slice(2)}`;
35529
- await bunWrite(tempPath, content);
35530
- renameSync5(tempPath, resolvedPath);
35531
- } catch (error93) {
35532
- log("[snapshot-writer] write failed", {
35533
- error: error93 instanceof Error ? error93.message : String(error93)
35534
- });
35535
- }
35536
- }
35537
- function createSnapshotWriterHook(directory) {
35538
- return (_input, _output) => {
35539
- _writeInFlight = _writeInFlight.then(() => _internals8.writeSnapshot(directory, swarmState), () => _internals8.writeSnapshot(directory, swarmState));
35540
- return _writeInFlight;
35541
- };
35542
- }
35543
- async function flushPendingSnapshot(directory) {
35544
- _writeInFlight = _writeInFlight.then(() => _internals8.writeSnapshot(directory, swarmState), () => _internals8.writeSnapshot(directory, swarmState));
35545
- await _writeInFlight;
35546
- }
35547
- var _writeInFlight, _internals8;
35548
- var init_snapshot_writer = __esm(() => {
35549
- init_utils2();
35550
- init_state();
35551
- init_utils();
35552
- init_bun_compat();
35553
- _writeInFlight = Promise.resolve();
35554
- _internals8 = {
35555
- writeSnapshot,
35556
- createSnapshotWriterHook,
35557
- flushPendingSnapshot
35558
- };
35559
- });
35560
-
35561
36093
  // src/tools/write-retro.ts
35562
36094
  async function executeWriteRetro(args, directory) {
35563
36095
  if (/^(CON|PRN|AUX|NUL|COM[0-9]|LPT[0-9])(:|$)/i.test(directory)) {
@@ -35859,7 +36391,7 @@ async function executeWriteRetro(args, directory) {
35859
36391
  }, null, 2);
35860
36392
  }
35861
36393
  }
35862
- var write_retro, _internals9;
36394
+ var write_retro, _internals8;
35863
36395
  var init_write_retro = __esm(() => {
35864
36396
  init_zod();
35865
36397
  init_evidence_schema();
@@ -35906,13 +36438,13 @@ var init_write_retro = __esm(() => {
35906
36438
  task_id: args.task_id !== undefined ? String(args.task_id) : undefined,
35907
36439
  metadata: args.metadata
35908
36440
  };
35909
- return await _internals9.executeWriteRetro(writeRetroArgs, directory);
36441
+ return await _internals8.executeWriteRetro(writeRetroArgs, directory);
35910
36442
  } catch {
35911
36443
  return JSON.stringify({ success: false, phase: rawPhase, message: "Invalid arguments" }, null, 2);
35912
36444
  }
35913
36445
  }
35914
36446
  });
35915
- _internals9 = {
36447
+ _internals8 = {
35916
36448
  executeWriteRetro,
35917
36449
  write_retro
35918
36450
  };
@@ -35974,6 +36506,7 @@ async function handleCloseCommand(directory, args) {
35974
36506
  const closedPhases = [];
35975
36507
  const closedTasks = [];
35976
36508
  const warnings = [];
36509
+ let hivePromoted = 0;
35977
36510
  if (!planAlreadyDone) {
35978
36511
  for (const phase of inProgressPhases) {
35979
36512
  closedPhases.push(phase.id);
@@ -36094,6 +36627,26 @@ async function handleCloseCommand(directory, args) {
36094
36627
  if (curationSucceeded && allLessons.length > 0) {
36095
36628
  await fs7.unlink(lessonsFilePath).catch(() => {});
36096
36629
  }
36630
+ if (curationSucceeded) {
36631
+ try {
36632
+ const knowledgePath = resolveSwarmKnowledgePath(directory);
36633
+ const entries = await readKnowledge(knowledgePath);
36634
+ if (entries.length > 0) {
36635
+ for (const entry of entries) {
36636
+ try {
36637
+ await promoteToHive(directory, entry.lesson, entry.category);
36638
+ hivePromoted++;
36639
+ } catch (promotionErr) {
36640
+ const msg = promotionErr instanceof Error ? promotionErr.message : String(promotionErr);
36641
+ warnings.push(`Hive promotion skipped for lesson: ${msg}`);
36642
+ }
36643
+ }
36644
+ }
36645
+ } catch (hiveErr) {
36646
+ const msg = hiveErr instanceof Error ? hiveErr.message : String(hiveErr);
36647
+ warnings.push(`Hive promotion failed: ${msg}`);
36648
+ }
36649
+ }
36097
36650
  if (planExists) {
36098
36651
  const guaranteeResult = guaranteeAllPlansComplete(planData);
36099
36652
  for (const phaseId of guaranteeResult.closedPhaseIds) {
@@ -36122,6 +36675,7 @@ async function handleCloseCommand(directory, args) {
36122
36675
  let archiveResult = "";
36123
36676
  let archivedFileCount = 0;
36124
36677
  const archivedActiveStateFiles = new Set;
36678
+ const archivedActiveStateDirs = new Set;
36125
36679
  try {
36126
36680
  await fs7.mkdir(archiveDir, { recursive: true });
36127
36681
  for (const artifact of ARCHIVE_ARTIFACTS) {
@@ -36135,38 +36689,34 @@ async function handleCloseCommand(directory, args) {
36135
36689
  }
36136
36690
  } catch {}
36137
36691
  }
36138
- const evidenceDir = path14.join(swarmDir, "evidence");
36139
- const archiveEvidenceDir = path14.join(archiveDir, "evidence");
36140
- try {
36141
- const evidenceEntries = await fs7.readdir(evidenceDir);
36142
- if (evidenceEntries.length > 0) {
36143
- await fs7.mkdir(archiveEvidenceDir, { recursive: true });
36144
- for (const entry of evidenceEntries) {
36145
- const srcEntry = path14.join(evidenceDir, entry);
36146
- const destEntry = path14.join(archiveEvidenceDir, entry);
36147
- try {
36148
- const stat2 = await fs7.stat(srcEntry);
36149
- if (stat2.isDirectory()) {
36150
- await fs7.mkdir(destEntry, { recursive: true });
36151
- const subEntries = await fs7.readdir(srcEntry);
36152
- for (const sub of subEntries) {
36153
- await fs7.copyFile(path14.join(srcEntry, sub), path14.join(destEntry, sub)).catch(() => {});
36692
+ for (const dirName of ACTIVE_STATE_DIRS_TO_CLEAN) {
36693
+ const srcDir = path14.join(swarmDir, dirName);
36694
+ const destDir = path14.join(archiveDir, dirName);
36695
+ try {
36696
+ const entries = await fs7.readdir(srcDir);
36697
+ if (entries.length > 0) {
36698
+ await fs7.mkdir(destDir, { recursive: true });
36699
+ for (const entry of entries) {
36700
+ const srcEntry = path14.join(srcDir, entry);
36701
+ const destEntry = path14.join(destDir, entry);
36702
+ try {
36703
+ const stat2 = await fs7.stat(srcEntry);
36704
+ if (stat2.isDirectory()) {
36705
+ await fs7.mkdir(destEntry, { recursive: true });
36706
+ const subEntries = await fs7.readdir(srcEntry);
36707
+ for (const sub of subEntries) {
36708
+ await fs7.copyFile(path14.join(srcEntry, sub), path14.join(destEntry, sub)).catch(() => {});
36709
+ }
36710
+ } else {
36711
+ await fs7.copyFile(srcEntry, destEntry);
36154
36712
  }
36155
- } else {
36156
- await fs7.copyFile(srcEntry, destEntry);
36157
- }
36158
- archivedFileCount++;
36159
- } catch {}
36713
+ archivedFileCount++;
36714
+ } catch {}
36715
+ }
36160
36716
  }
36161
- }
36162
- } catch {}
36163
- const sessionStatePath = path14.join(swarmDir, "session", "state.json");
36164
- try {
36165
- const archiveSessionDir = path14.join(archiveDir, "session");
36166
- await fs7.mkdir(archiveSessionDir, { recursive: true });
36167
- await fs7.copyFile(sessionStatePath, path14.join(archiveSessionDir, "state.json"));
36168
- archivedFileCount++;
36169
- } catch {}
36717
+ archivedActiveStateDirs.add(dirName);
36718
+ } catch {}
36719
+ }
36170
36720
  archiveResult = `Archived ${archivedFileCount} artifact(s) to .swarm/archive/swarm-${timestamp}/`;
36171
36721
  } catch (archiveError) {
36172
36722
  warnings.push(`Archive creation failed: ${archiveError instanceof Error ? archiveError.message : String(archiveError)}`);
@@ -36196,6 +36746,16 @@ async function handleCloseCommand(directory, args) {
36196
36746
  } else {
36197
36747
  warnings.push("Skipped active-state cleanup because no active-state files were archived. Files preserved to prevent data loss.");
36198
36748
  }
36749
+ for (const dirName of ACTIVE_STATE_DIRS_TO_CLEAN) {
36750
+ if (!archivedActiveStateDirs.has(dirName)) {
36751
+ continue;
36752
+ }
36753
+ const dirPath = path14.join(swarmDir, dirName);
36754
+ try {
36755
+ await fs7.rm(dirPath, { recursive: true, force: true });
36756
+ cleanedFiles.push(`${dirName}/`);
36757
+ } catch {}
36758
+ }
36199
36759
  try {
36200
36760
  const swarmFiles = await fs7.readdir(swarmDir);
36201
36761
  const configBackups = swarmFiles.filter((f) => f.startsWith("config-backup-") && f.endsWith(".json"));
@@ -36254,17 +36814,30 @@ async function handleCloseCommand(directory, args) {
36254
36814
  const prunedBranches = [];
36255
36815
  const isGit = isGitRepo2(directory);
36256
36816
  if (isGit) {
36257
- const alignResult = resetToRemoteBranch(directory, { pruneBranches });
36258
- gitAlignResult = alignResult.message;
36259
- prunedBranches.push(...alignResult.prunedBranches);
36260
- if (!alignResult.success) {
36261
- warnings.push(`Git alignment: ${alignResult.message}`);
36262
- }
36263
- if (alignResult.alreadyAligned) {
36264
- gitAlignResult = `Already aligned with ${alignResult.targetBranch}`;
36265
- }
36266
- for (const w of alignResult.warnings) {
36267
- warnings.push(w);
36817
+ const aggressiveResult = resetToMainAfterMerge(directory, {
36818
+ pruneBranches
36819
+ });
36820
+ if (aggressiveResult.success) {
36821
+ gitAlignResult = aggressiveResult.message;
36822
+ for (const w of aggressiveResult.warnings) {
36823
+ warnings.push(w);
36824
+ }
36825
+ if (aggressiveResult.changesDiscarded) {
36826
+ warnings.push("Uncommitted changes were discarded during git alignment");
36827
+ }
36828
+ } else {
36829
+ const alignResult = resetToRemoteBranch(directory, { pruneBranches });
36830
+ gitAlignResult = alignResult.message;
36831
+ prunedBranches.push(...alignResult.prunedBranches);
36832
+ if (!alignResult.success) {
36833
+ warnings.push(`Git alignment: ${alignResult.message}`);
36834
+ }
36835
+ if (alignResult.alreadyAligned) {
36836
+ gitAlignResult = `Already aligned with ${alignResult.targetBranch}`;
36837
+ }
36838
+ for (const w of alignResult.warnings) {
36839
+ warnings.push(w);
36840
+ }
36268
36841
  }
36269
36842
  } else {
36270
36843
  gitAlignResult = "Not a git repository \u2014 skipped git alignment";
@@ -36304,6 +36877,7 @@ async function handleCloseCommand(directory, args) {
36304
36877
  ...swarmPlanFilesRemoved > 0 ? [`- Removed ${swarmPlanFilesRemoved} SWARM_PLAN checkpoint artifact(s)`] : [],
36305
36878
  ...planExists && !planAlreadyDone ? ["- Set non-completed phases/tasks to closed status"] : [],
36306
36879
  ...curationSucceeded && allLessons.length > 0 ? [`- Committed ${allLessons.length} lesson(s) to knowledge store`] : [],
36880
+ ...hivePromoted > 0 ? [`- Promoted ${hivePromoted} lesson(s) to hive knowledge`] : [],
36307
36881
  "",
36308
36882
  ...warnings.length > 0 ? ["## Warnings", ...warnings.map((w) => `- ${w}`), ""] : []
36309
36883
  ].join(`
@@ -36315,13 +36889,6 @@ async function handleCloseCommand(directory, args) {
36315
36889
  warnings.push(`Failed to write close-summary.md: ${msg}`);
36316
36890
  console.warn("[close-command] Failed to write close-summary.md:", error93);
36317
36891
  }
36318
- try {
36319
- await flushPendingSnapshot(directory);
36320
- } catch (error93) {
36321
- const msg = error93 instanceof Error ? error93.message : String(error93);
36322
- warnings.push(`flushPendingSnapshot failed: ${msg}`);
36323
- console.warn("[close-command] flushPendingSnapshot error:", error93);
36324
- }
36325
36892
  const preservedClient = swarmState.opencodeClient;
36326
36893
  const preservedFullAutoFlag = swarmState.fullAutoEnabledInConfig;
36327
36894
  const preservedCuratorInitNames = swarmState.curatorInitAgentNames;
@@ -36362,15 +36929,16 @@ ${otherWarnings.map((w) => `- ${w}`).join(`
36362
36929
  **Archive:** ${archiveResult}
36363
36930
  **Git:** ${gitAlignResult}${lessonSummary}${warningMsg}`;
36364
36931
  }
36365
- var ARCHIVE_ARTIFACTS, ACTIVE_STATE_TO_CLEAN;
36932
+ var ARCHIVE_ARTIFACTS, ACTIVE_STATE_TO_CLEAN, ACTIVE_STATE_DIRS_TO_CLEAN;
36366
36933
  var init_close = __esm(() => {
36367
36934
  init_schema();
36368
36935
  init_manager2();
36369
36936
  init_branch();
36937
+ init_hive_promoter();
36370
36938
  init_knowledge_curator();
36939
+ init_knowledge_store();
36371
36940
  init_utils2();
36372
36941
  init_scope_persistence();
36373
- init_snapshot_writer();
36374
36942
  init_state();
36375
36943
  init_write_retro();
36376
36944
  ARCHIVE_ARTIFACTS = [
@@ -36383,7 +36951,18 @@ var init_close = __esm(() => {
36383
36951
  "handoff-prompt.md",
36384
36952
  "handoff-consumed.md",
36385
36953
  "escalation-report.md",
36386
- "close-lessons.md"
36954
+ "close-lessons.md",
36955
+ "knowledge.jsonl",
36956
+ "knowledge-rejected.jsonl",
36957
+ "repo-graph.json",
36958
+ "doc-manifest.json",
36959
+ "dark-matter.md",
36960
+ "telemetry.jsonl",
36961
+ "swarm.db",
36962
+ "swarm.db-shm",
36963
+ "swarm.db-wal",
36964
+ "close-summary.md",
36965
+ "spec.md"
36387
36966
  ];
36388
36967
  ACTIVE_STATE_TO_CLEAN = [
36389
36968
  "plan.json",
@@ -36393,7 +36972,23 @@ var init_close = __esm(() => {
36393
36972
  "handoff.md",
36394
36973
  "handoff-prompt.md",
36395
36974
  "handoff-consumed.md",
36396
- "escalation-report.md"
36975
+ "escalation-report.md",
36976
+ "knowledge.jsonl",
36977
+ "knowledge-rejected.jsonl",
36978
+ "repo-graph.json",
36979
+ "doc-manifest.json",
36980
+ "dark-matter.md",
36981
+ "telemetry.jsonl",
36982
+ "swarm.db",
36983
+ "swarm.db-shm",
36984
+ "swarm.db-wal"
36985
+ ];
36986
+ ACTIVE_STATE_DIRS_TO_CLEAN = [
36987
+ "evidence",
36988
+ "session",
36989
+ "scopes",
36990
+ "locks",
36991
+ "spec-archive"
36397
36992
  ];
36398
36993
  });
36399
36994
 
@@ -36496,322 +37091,6 @@ var init_council = __esm(() => {
36496
37091
  `);
36497
37092
  });
36498
37093
 
36499
- // src/background/event-bus.ts
36500
- class AutomationEventBus {
36501
- listeners = new Map;
36502
- eventHistory = [];
36503
- maxHistorySize;
36504
- constructor(options) {
36505
- this.maxHistorySize = options?.maxHistorySize ?? 100;
36506
- }
36507
- subscribe(type, listener) {
36508
- if (!this.listeners.has(type)) {
36509
- this.listeners.set(type, new Set);
36510
- }
36511
- this.listeners.get(type).add(listener);
36512
- return () => {
36513
- this.listeners.get(type)?.delete(listener);
36514
- };
36515
- }
36516
- async publish(type, payload, source) {
36517
- const event = {
36518
- type,
36519
- timestamp: Date.now(),
36520
- payload,
36521
- source
36522
- };
36523
- this.eventHistory.push(event);
36524
- if (this.eventHistory.length > this.maxHistorySize) {
36525
- this.eventHistory.shift();
36526
- }
36527
- log(`[EventBus] ${type}`, {
36528
- source,
36529
- payload: typeof payload === "object" ? "..." : payload
36530
- });
36531
- const listeners = this.listeners.get(type);
36532
- if (listeners) {
36533
- await Promise.all(Array.from(listeners).map(async (listener) => {
36534
- try {
36535
- await listener(event);
36536
- } catch (error93) {
36537
- log(`[EventBus] Listener error for ${type}`, { error: error93 });
36538
- }
36539
- }));
36540
- }
36541
- }
36542
- getHistory(types) {
36543
- if (!types || types.length === 0) {
36544
- return [...this.eventHistory];
36545
- }
36546
- return this.eventHistory.filter((e) => types.includes(e.type));
36547
- }
36548
- clearHistory() {
36549
- this.eventHistory = [];
36550
- }
36551
- getListenerCount(type) {
36552
- return this.listeners.get(type)?.size ?? 0;
36553
- }
36554
- hasListeners(type) {
36555
- return this.getListenerCount(type) > 0;
36556
- }
36557
- }
36558
- function getGlobalEventBus() {
36559
- if (!globalEventBus) {
36560
- globalEventBus = new AutomationEventBus;
36561
- }
36562
- return globalEventBus;
36563
- }
36564
- var globalEventBus = null;
36565
- var init_event_bus = __esm(() => {
36566
- init_utils();
36567
- });
36568
-
36569
- // src/hooks/curator.ts
36570
- var init_curator = __esm(() => {
36571
- init_event_bus();
36572
- init_manager();
36573
- init_bun_compat();
36574
- init_logger();
36575
- init_knowledge_store();
36576
- init_knowledge_validator();
36577
- init_utils2();
36578
- });
36579
-
36580
- // src/hooks/hive-promoter.ts
36581
- import path16 from "path";
36582
- function isAlreadyInHive(entry, hiveEntries, threshold) {
36583
- return findNearDuplicate(entry.lesson, hiveEntries, threshold) !== undefined;
36584
- }
36585
- function countDistinctPhases(confirmedBy) {
36586
- const phaseNumbers = new Set;
36587
- for (const record3 of confirmedBy) {
36588
- phaseNumbers.add(record3.phase_number);
36589
- }
36590
- return phaseNumbers.size;
36591
- }
36592
- function countDistinctProjects(confirmedBy) {
36593
- const projectNames = new Set;
36594
- for (const record3 of confirmedBy) {
36595
- projectNames.add(record3.project_name);
36596
- }
36597
- return projectNames.size;
36598
- }
36599
- function hasProjectConfirmation(hiveEntry, projectName) {
36600
- return hiveEntry.confirmed_by.some((record3) => record3.project_name === projectName);
36601
- }
36602
- function calculateEncounterScore(currentScore, isSameProject, config3) {
36603
- const weight = isSameProject ? config3.same_project_weight : config3.cross_project_weight;
36604
- const increment = config3.encounter_increment * weight;
36605
- const newScore = currentScore + increment;
36606
- return Math.min(Math.max(newScore, config3.min_encounter_score), config3.max_encounter_score);
36607
- }
36608
- function getEntryAgeMs(createdAt) {
36609
- const createdTime = new Date(createdAt).getTime();
36610
- if (Number.isNaN(createdTime))
36611
- return 0;
36612
- return Date.now() - createdTime;
36613
- }
36614
- async function checkHivePromotions(swarmEntries, config3) {
36615
- let newPromotions = 0;
36616
- let encountersIncremented = 0;
36617
- let advancements = 0;
36618
- if (config3.hive_enabled === false) {
36619
- return {
36620
- timestamp: new Date().toISOString(),
36621
- new_promotions: 0,
36622
- encounters_incremented: 0,
36623
- advancements: 0,
36624
- total_hive_entries: 0
36625
- };
36626
- }
36627
- const hiveEntries = await readKnowledge(resolveHiveKnowledgePath());
36628
- for (const swarmEntry of swarmEntries) {
36629
- if (isAlreadyInHive(swarmEntry, hiveEntries, config3.dedup_threshold)) {
36630
- continue;
36631
- }
36632
- let shouldPromote = false;
36633
- if (swarmEntry.hive_eligible === true && countDistinctPhases(swarmEntry.confirmed_by) >= 3) {
36634
- shouldPromote = true;
36635
- }
36636
- if (swarmEntry.tags.includes("hive-fast-track")) {
36637
- shouldPromote = true;
36638
- }
36639
- const ageMs = getEntryAgeMs(swarmEntry.created_at);
36640
- const ageThresholdMs = config3.auto_promote_days * 86400000;
36641
- if (ageMs >= ageThresholdMs) {
36642
- shouldPromote = true;
36643
- }
36644
- if (!shouldPromote) {
36645
- continue;
36646
- }
36647
- const validationResult = validateLesson(swarmEntry.lesson, hiveEntries.map((e) => e.lesson), {
36648
- category: swarmEntry.category,
36649
- scope: swarmEntry.scope,
36650
- confidence: swarmEntry.confidence
36651
- });
36652
- if (validationResult.severity === "error") {
36653
- const rejectedLesson = {
36654
- id: crypto.randomUUID(),
36655
- lesson: swarmEntry.lesson,
36656
- rejection_reason: validationResult.reason || "validation failed for hive promotion",
36657
- rejected_at: new Date().toISOString(),
36658
- rejection_layer: validationResult.layer || 2
36659
- };
36660
- const hiveRejectedPath = resolveHiveRejectedPath();
36661
- await appendKnowledge(hiveRejectedPath, rejectedLesson);
36662
- continue;
36663
- }
36664
- const newHiveEntry = {
36665
- id: crypto.randomUUID(),
36666
- tier: "hive",
36667
- lesson: swarmEntry.lesson,
36668
- category: swarmEntry.category,
36669
- tags: swarmEntry.tags,
36670
- scope: swarmEntry.scope,
36671
- confidence: 0.5,
36672
- status: "candidate",
36673
- confirmed_by: [],
36674
- retrieval_outcomes: {
36675
- applied_count: 0,
36676
- succeeded_after_count: 0,
36677
- failed_after_count: 0
36678
- },
36679
- schema_version: config3.schema_version,
36680
- created_at: new Date().toISOString(),
36681
- updated_at: new Date().toISOString(),
36682
- source_project: swarmEntry.project_name,
36683
- encounter_score: config3.initial_encounter_score
36684
- };
36685
- await appendKnowledge(resolveHiveKnowledgePath(), newHiveEntry);
36686
- newPromotions++;
36687
- hiveEntries.push(newHiveEntry);
36688
- }
36689
- let hiveModified = false;
36690
- for (const hiveEntry of hiveEntries) {
36691
- const nearDuplicate = findNearDuplicate(hiveEntry.lesson, swarmEntries, config3.dedup_threshold);
36692
- if (!nearDuplicate) {
36693
- continue;
36694
- }
36695
- const isSameProject = nearDuplicate.project_name === hiveEntry.source_project;
36696
- if (hasProjectConfirmation(hiveEntry, nearDuplicate.project_name)) {
36697
- continue;
36698
- }
36699
- const newConfirmation = {
36700
- project_name: nearDuplicate.project_name,
36701
- confirmed_at: new Date().toISOString()
36702
- };
36703
- hiveEntry.confirmed_by.push(newConfirmation);
36704
- const currentScore = hiveEntry.encounter_score ?? 1;
36705
- hiveEntry.encounter_score = calculateEncounterScore(currentScore, isSameProject, config3);
36706
- encountersIncremented++;
36707
- hiveEntry.updated_at = new Date().toISOString();
36708
- if (hiveEntry.status === "candidate" && countDistinctProjects(hiveEntry.confirmed_by) >= 3) {
36709
- hiveEntry.status = "established";
36710
- advancements++;
36711
- }
36712
- hiveModified = true;
36713
- }
36714
- if (hiveModified) {
36715
- await rewriteKnowledge(resolveHiveKnowledgePath(), hiveEntries);
36716
- }
36717
- if (newPromotions > 0 || hiveModified) {
36718
- await enforceKnowledgeCap(resolveHiveKnowledgePath(), config3.hive_max_entries);
36719
- }
36720
- return {
36721
- timestamp: new Date().toISOString(),
36722
- new_promotions: newPromotions,
36723
- encounters_incremented: encountersIncremented,
36724
- advancements,
36725
- total_hive_entries: hiveEntries.length
36726
- };
36727
- }
36728
- async function promoteToHive(directory, lesson, category) {
36729
- const trimmedLesson = lesson.trim();
36730
- const hiveEntries = await readKnowledge(resolveHiveKnowledgePath());
36731
- const validationResult = validateLesson(trimmedLesson, hiveEntries.map((e) => e.lesson), {
36732
- category: category || "process",
36733
- scope: "global",
36734
- confidence: 1
36735
- });
36736
- if (validationResult.severity === "error") {
36737
- throw new Error(`Lesson rejected by validator: ${validationResult.reason}`);
36738
- }
36739
- if (findNearDuplicate(trimmedLesson, hiveEntries, 0.6)) {
36740
- return `Lesson already exists in hive (near-duplicate).`;
36741
- }
36742
- const newHiveEntry = {
36743
- id: crypto.randomUUID(),
36744
- tier: "hive",
36745
- lesson: trimmedLesson,
36746
- category: category || "process",
36747
- tags: [],
36748
- scope: "global",
36749
- confidence: 1,
36750
- status: "promoted",
36751
- confirmed_by: [],
36752
- retrieval_outcomes: {
36753
- applied_count: 0,
36754
- succeeded_after_count: 0,
36755
- failed_after_count: 0
36756
- },
36757
- schema_version: 1,
36758
- created_at: new Date().toISOString(),
36759
- updated_at: new Date().toISOString(),
36760
- source_project: path16.basename(directory) || "unknown",
36761
- encounter_score: 1
36762
- };
36763
- await appendKnowledge(resolveHiveKnowledgePath(), newHiveEntry);
36764
- return `Promoted to hive: "${trimmedLesson.slice(0, 50)}${trimmedLesson.length > 50 ? "..." : ""}" (confidence: 1.0, source: manual)`;
36765
- }
36766
- async function promoteFromSwarm(directory, lessonId) {
36767
- const swarmEntries = await readKnowledge(resolveSwarmKnowledgePath(directory));
36768
- const swarmEntry = swarmEntries.find((e) => e.id === lessonId);
36769
- if (!swarmEntry) {
36770
- throw new Error(`Lesson ${lessonId} not found in .swarm/knowledge.jsonl`);
36771
- }
36772
- const hiveEntries = await readKnowledge(resolveHiveKnowledgePath());
36773
- const validationResult = validateLesson(swarmEntry.lesson, hiveEntries.map((e) => e.lesson), {
36774
- category: swarmEntry.category,
36775
- scope: swarmEntry.scope,
36776
- confidence: swarmEntry.confidence
36777
- });
36778
- if (validationResult.severity === "error") {
36779
- throw new Error(`Lesson rejected by validator: ${validationResult.reason}`);
36780
- }
36781
- if (findNearDuplicate(swarmEntry.lesson, hiveEntries, 0.6)) {
36782
- return `Lesson already exists in hive (near-duplicate).`;
36783
- }
36784
- const newHiveEntry = {
36785
- id: crypto.randomUUID(),
36786
- tier: "hive",
36787
- lesson: swarmEntry.lesson,
36788
- category: swarmEntry.category,
36789
- tags: swarmEntry.tags,
36790
- scope: swarmEntry.scope,
36791
- confidence: 1,
36792
- status: "promoted",
36793
- confirmed_by: [],
36794
- retrieval_outcomes: {
36795
- applied_count: 0,
36796
- succeeded_after_count: 0,
36797
- failed_after_count: 0
36798
- },
36799
- schema_version: 1,
36800
- created_at: new Date().toISOString(),
36801
- updated_at: new Date().toISOString(),
36802
- source_project: swarmEntry.project_name,
36803
- encounter_score: 1
36804
- };
36805
- await appendKnowledge(resolveHiveKnowledgePath(), newHiveEntry);
36806
- return `Promoted lesson ${lessonId} from swarm to hive: "${swarmEntry.lesson.slice(0, 50)}${swarmEntry.lesson.length > 50 ? "..." : ""}"`;
36807
- }
36808
- var init_hive_promoter = __esm(() => {
36809
- init_curator();
36810
- init_knowledge_store();
36811
- init_knowledge_validator();
36812
- init_utils2();
36813
- });
36814
-
36815
37094
  // src/commands/curate.ts
36816
37095
  async function handleCurateCommand(directory, _args) {
36817
37096
  try {
@@ -36849,7 +37128,7 @@ var init_curate = __esm(() => {
36849
37128
  import * as child_process3 from "child_process";
36850
37129
  import { randomUUID } from "crypto";
36851
37130
  import { readdir, readFile as readFile5, stat as stat2 } from "fs/promises";
36852
- import * as path17 from "path";
37131
+ import * as path16 from "path";
36853
37132
  import { promisify } from "util";
36854
37133
  function getExecFileAsync() {
36855
37134
  return promisify(child_process3.execFile);
@@ -36951,7 +37230,7 @@ async function scanSourceFiles(dir) {
36951
37230
  try {
36952
37231
  const entries = await readdir(dir, { withFileTypes: true });
36953
37232
  for (const entry of entries) {
36954
- const fullPath = path17.join(dir, entry.name);
37233
+ const fullPath = path16.join(dir, entry.name);
36955
37234
  if (entry.isDirectory()) {
36956
37235
  if (skipDirs.has(entry.name)) {
36957
37236
  continue;
@@ -36959,7 +37238,7 @@ async function scanSourceFiles(dir) {
36959
37238
  const subFiles = await scanSourceFiles(fullPath);
36960
37239
  results.push(...subFiles);
36961
37240
  } else if (entry.isFile()) {
36962
- const ext = path17.extname(entry.name);
37241
+ const ext = path16.extname(entry.name);
36963
37242
  if ([".ts", ".tsx", ".js", ".jsx", ".mjs"].includes(ext)) {
36964
37243
  results.push(fullPath);
36965
37244
  }
@@ -36981,8 +37260,8 @@ async function getStaticEdges(directory) {
36981
37260
  continue;
36982
37261
  }
36983
37262
  try {
36984
- const sourceDir = path17.dirname(sourceFile);
36985
- const resolvedPath = path17.resolve(sourceDir, importPath);
37263
+ const sourceDir = path16.dirname(sourceFile);
37264
+ const resolvedPath = path16.resolve(sourceDir, importPath);
36986
37265
  const extensions = [
36987
37266
  "",
36988
37267
  ".ts",
@@ -37007,8 +37286,8 @@ async function getStaticEdges(directory) {
37007
37286
  if (!targetFile) {
37008
37287
  continue;
37009
37288
  }
37010
- const relSource = path17.relative(directory, sourceFile).replace(/\\/g, "/");
37011
- const relTarget = path17.relative(directory, targetFile).replace(/\\/g, "/");
37289
+ const relSource = path16.relative(directory, sourceFile).replace(/\\/g, "/");
37290
+ const relTarget = path16.relative(directory, targetFile).replace(/\\/g, "/");
37012
37291
  const [key] = relSource < relTarget ? [`${relSource}::${relTarget}`, relSource, relTarget] : [`${relTarget}::${relSource}`, relTarget, relSource];
37013
37292
  edges.add(key);
37014
37293
  } catch {}
@@ -37020,7 +37299,7 @@ async function getStaticEdges(directory) {
37020
37299
  function isTestImplementationPair(fileA, fileB) {
37021
37300
  const testPatterns = [".test.ts", ".test.js", ".spec.ts", ".spec.js"];
37022
37301
  const getBaseName = (filePath) => {
37023
- const base = path17.basename(filePath);
37302
+ const base = path16.basename(filePath);
37024
37303
  for (const pattern of testPatterns) {
37025
37304
  if (base.endsWith(pattern)) {
37026
37305
  return base.slice(0, -pattern.length);
@@ -37030,16 +37309,16 @@ function isTestImplementationPair(fileA, fileB) {
37030
37309
  };
37031
37310
  const baseA = getBaseName(fileA);
37032
37311
  const baseB = getBaseName(fileB);
37033
- return baseA === baseB && baseA !== path17.basename(fileA) && baseA !== path17.basename(fileB);
37312
+ return baseA === baseB && baseA !== path16.basename(fileA) && baseA !== path16.basename(fileB);
37034
37313
  }
37035
37314
  function hasSharedPrefix(fileA, fileB) {
37036
- const dirA = path17.dirname(fileA);
37037
- const dirB = path17.dirname(fileB);
37315
+ const dirA = path16.dirname(fileA);
37316
+ const dirB = path16.dirname(fileB);
37038
37317
  if (dirA !== dirB) {
37039
37318
  return false;
37040
37319
  }
37041
- const baseA = path17.basename(fileA).replace(/\.(ts|js|tsx|jsx|mjs)$/, "");
37042
- const baseB = path17.basename(fileB).replace(/\.(ts|js|tsx|jsx|mjs)$/, "");
37320
+ const baseA = path16.basename(fileA).replace(/\.(ts|js|tsx|jsx|mjs)$/, "");
37321
+ const baseB = path16.basename(fileB).replace(/\.(ts|js|tsx|jsx|mjs)$/, "");
37043
37322
  if (baseA.startsWith(baseB) || baseB.startsWith(baseA)) {
37044
37323
  return true;
37045
37324
  }
@@ -37067,9 +37346,9 @@ async function detectDarkMatter(directory, options) {
37067
37346
  } catch {
37068
37347
  return [];
37069
37348
  }
37070
- const commitMap = await _internals10.parseGitLog(directory, maxCommitsToAnalyze);
37071
- const matrix = _internals10.buildCoChangeMatrix(commitMap);
37072
- const staticEdges = await _internals10.getStaticEdges(directory);
37349
+ const commitMap = await _internals9.parseGitLog(directory, maxCommitsToAnalyze);
37350
+ const matrix = _internals9.buildCoChangeMatrix(commitMap);
37351
+ const staticEdges = await _internals9.getStaticEdges(directory);
37073
37352
  const results = [];
37074
37353
  for (const entry of matrix.values()) {
37075
37354
  const key = `${entry.fileA}::${entry.fileB}`;
@@ -37093,8 +37372,8 @@ function darkMatterToKnowledgeEntries(pairs, projectName) {
37093
37372
  const entries = [];
37094
37373
  const now = new Date().toISOString();
37095
37374
  for (const pair of pairs.slice(0, 10)) {
37096
- const baseA = path17.basename(pair.fileA);
37097
- const baseB = path17.basename(pair.fileB);
37375
+ const baseA = path16.basename(pair.fileA);
37376
+ const baseB = path16.basename(pair.fileB);
37098
37377
  let lesson = `Files ${pair.fileA} and ${pair.fileB} co-change with NPMI=${pair.npmi.toFixed(3)} but have no import relationship. This hidden coupling suggests a shared architectural concern \u2014 changes to one likely require changes to the other.`;
37099
37378
  if (lesson.length > 280) {
37100
37379
  lesson = `Files ${baseA} and ${baseB} co-change with NPMI=${pair.npmi.toFixed(3)} but have no import relationship. This hidden coupling suggests a shared architectural concern \u2014 changes to one likely require changes to the other.`;
@@ -37149,7 +37428,7 @@ ${rows}
37149
37428
  These pairs likely share an architectural concern invisible to static analysis.
37150
37429
  Consider adding explicit documentation or extracting the shared concern.`;
37151
37430
  }
37152
- var co_change_analyzer, _internals10;
37431
+ var co_change_analyzer, _internals9;
37153
37432
  var init_co_change_analyzer = __esm(() => {
37154
37433
  init_zod();
37155
37434
  init_create_tool();
@@ -37181,11 +37460,11 @@ var init_co_change_analyzer = __esm(() => {
37181
37460
  npmiThreshold,
37182
37461
  maxCommitsToAnalyze
37183
37462
  };
37184
- const pairs = await _internals10.detectDarkMatter(directory, options);
37185
- return _internals10.formatDarkMatterOutput(pairs);
37463
+ const pairs = await _internals9.detectDarkMatter(directory, options);
37464
+ return _internals9.formatDarkMatterOutput(pairs);
37186
37465
  }
37187
37466
  });
37188
- _internals10 = {
37467
+ _internals9 = {
37189
37468
  parseGitLog,
37190
37469
  buildCoChangeMatrix,
37191
37470
  getStaticEdges,
@@ -37196,7 +37475,7 @@ var init_co_change_analyzer = __esm(() => {
37196
37475
  });
37197
37476
 
37198
37477
  // src/commands/dark-matter.ts
37199
- import path18 from "path";
37478
+ import path17 from "path";
37200
37479
  async function handleDarkMatterCommand(directory, args) {
37201
37480
  const options = {};
37202
37481
  for (let i = 0;i < args.length; i++) {
@@ -37216,7 +37495,7 @@ async function handleDarkMatterCommand(directory, args) {
37216
37495
  }
37217
37496
  let pairs;
37218
37497
  try {
37219
- pairs = await _internals10.detectDarkMatter(directory, options);
37498
+ pairs = await _internals9.detectDarkMatter(directory, options);
37220
37499
  } catch (err) {
37221
37500
  const errMsg = err instanceof Error ? err.message : String(err);
37222
37501
  return `## Dark Matter Analysis Failed
@@ -37228,7 +37507,7 @@ Ensure this is a git repository with commit history.`;
37228
37507
  const output = formatDarkMatterOutput(pairs);
37229
37508
  if (pairs.length > 0) {
37230
37509
  try {
37231
- const projectName = path18.basename(path18.resolve(directory));
37510
+ const projectName = path17.basename(path17.resolve(directory));
37232
37511
  const entries = darkMatterToKnowledgeEntries(pairs, projectName);
37233
37512
  if (entries.length > 0) {
37234
37513
  const knowledgePath = resolveSwarmKnowledgePath(directory);
@@ -37253,51 +37532,51 @@ var init_dark_matter = __esm(() => {
37253
37532
 
37254
37533
  // src/config/cache-paths.ts
37255
37534
  import * as os5 from "os";
37256
- import * as path19 from "path";
37535
+ import * as path18 from "path";
37257
37536
  function getPluginConfigDir() {
37258
- return path19.join(process.env.XDG_CONFIG_HOME || path19.join(os5.homedir(), ".config"), "opencode");
37537
+ return path18.join(process.env.XDG_CONFIG_HOME || path18.join(os5.homedir(), ".config"), "opencode");
37259
37538
  }
37260
37539
  function getPluginCachePaths() {
37261
- const cacheBase = process.env.XDG_CACHE_HOME || path19.join(os5.homedir(), ".cache");
37540
+ const cacheBase = process.env.XDG_CACHE_HOME || path18.join(os5.homedir(), ".cache");
37262
37541
  const configDir = getPluginConfigDir();
37263
37542
  const paths = [
37264
- path19.join(cacheBase, "opencode", "node_modules", "opencode-swarm"),
37265
- path19.join(cacheBase, "opencode", "packages", "opencode-swarm@latest"),
37266
- path19.join(configDir, "node_modules", "opencode-swarm")
37543
+ path18.join(cacheBase, "opencode", "node_modules", "opencode-swarm"),
37544
+ path18.join(cacheBase, "opencode", "packages", "opencode-swarm@latest"),
37545
+ path18.join(configDir, "node_modules", "opencode-swarm")
37267
37546
  ];
37268
37547
  if (process.platform === "darwin") {
37269
- const libCaches = path19.join(os5.homedir(), "Library", "Caches");
37270
- paths.push(path19.join(libCaches, "opencode", "node_modules", "opencode-swarm"), path19.join(libCaches, "opencode", "packages", "opencode-swarm@latest"));
37548
+ const libCaches = path18.join(os5.homedir(), "Library", "Caches");
37549
+ paths.push(path18.join(libCaches, "opencode", "node_modules", "opencode-swarm"), path18.join(libCaches, "opencode", "packages", "opencode-swarm@latest"));
37271
37550
  }
37272
37551
  if (process.platform === "win32") {
37273
- const localAppData = process.env.LOCALAPPDATA || path19.join(os5.homedir(), "AppData", "Local");
37274
- const appData = process.env.APPDATA || path19.join(os5.homedir(), "AppData", "Roaming");
37275
- paths.push(path19.join(localAppData, "opencode", "node_modules", "opencode-swarm"), path19.join(localAppData, "opencode", "packages", "opencode-swarm@latest"), path19.join(appData, "opencode", "node_modules", "opencode-swarm"));
37552
+ const localAppData = process.env.LOCALAPPDATA || path18.join(os5.homedir(), "AppData", "Local");
37553
+ const appData = process.env.APPDATA || path18.join(os5.homedir(), "AppData", "Roaming");
37554
+ paths.push(path18.join(localAppData, "opencode", "node_modules", "opencode-swarm"), path18.join(localAppData, "opencode", "packages", "opencode-swarm@latest"), path18.join(appData, "opencode", "node_modules", "opencode-swarm"));
37276
37555
  }
37277
37556
  return paths;
37278
37557
  }
37279
37558
  function getPluginLockFilePaths() {
37280
- const cacheBase = process.env.XDG_CACHE_HOME || path19.join(os5.homedir(), ".cache");
37559
+ const cacheBase = process.env.XDG_CACHE_HOME || path18.join(os5.homedir(), ".cache");
37281
37560
  const configDir = getPluginConfigDir();
37282
37561
  const paths = [
37283
- path19.join(cacheBase, "opencode", "bun.lock"),
37284
- path19.join(cacheBase, "opencode", "bun.lockb"),
37285
- path19.join(configDir, "package-lock.json")
37562
+ path18.join(cacheBase, "opencode", "bun.lock"),
37563
+ path18.join(cacheBase, "opencode", "bun.lockb"),
37564
+ path18.join(configDir, "package-lock.json")
37286
37565
  ];
37287
37566
  if (process.platform === "darwin") {
37288
- const libCaches = path19.join(os5.homedir(), "Library", "Caches");
37289
- paths.push(path19.join(libCaches, "opencode", "bun.lock"), path19.join(libCaches, "opencode", "bun.lockb"));
37567
+ const libCaches = path18.join(os5.homedir(), "Library", "Caches");
37568
+ paths.push(path18.join(libCaches, "opencode", "bun.lock"), path18.join(libCaches, "opencode", "bun.lockb"));
37290
37569
  }
37291
37570
  if (process.platform === "win32") {
37292
- const localAppData = process.env.LOCALAPPDATA || path19.join(os5.homedir(), "AppData", "Local");
37293
- paths.push(path19.join(localAppData, "opencode", "bun.lock"), path19.join(localAppData, "opencode", "bun.lockb"));
37571
+ const localAppData = process.env.LOCALAPPDATA || path18.join(os5.homedir(), "AppData", "Local");
37572
+ paths.push(path18.join(localAppData, "opencode", "bun.lock"), path18.join(localAppData, "opencode", "bun.lockb"));
37294
37573
  }
37295
37574
  return paths;
37296
37575
  }
37297
37576
  var init_cache_paths = () => {};
37298
37577
 
37299
37578
  // src/services/version-check.ts
37300
- import { existsSync as existsSync9, mkdirSync as mkdirSync8, readFileSync as readFileSync5, writeFileSync as writeFileSync4 } from "fs";
37579
+ import { existsSync as existsSync9, mkdirSync as mkdirSync7, readFileSync as readFileSync5, writeFileSync as writeFileSync4 } from "fs";
37301
37580
  import { homedir as homedir5 } from "os";
37302
37581
  import { join as join17 } from "path";
37303
37582
  function cacheDir() {
@@ -37310,10 +37589,10 @@ function cacheFile() {
37310
37589
  }
37311
37590
  function readVersionCache() {
37312
37591
  try {
37313
- const path20 = cacheFile();
37314
- if (!existsSync9(path20))
37592
+ const path19 = cacheFile();
37593
+ if (!existsSync9(path19))
37315
37594
  return null;
37316
- const raw = readFileSync5(path20, "utf-8");
37595
+ const raw = readFileSync5(path19, "utf-8");
37317
37596
  const parsed = JSON.parse(raw);
37318
37597
  if (typeof parsed?.checkedAt !== "number")
37319
37598
  return null;
@@ -37353,7 +37632,7 @@ var init_version_check = __esm(() => {
37353
37632
  // src/services/diagnose-service.ts
37354
37633
  import * as child_process4 from "child_process";
37355
37634
  import { existsSync as existsSync10, readdirSync as readdirSync4, readFileSync as readFileSync6, statSync as statSync6 } from "fs";
37356
- import path20 from "path";
37635
+ import path19 from "path";
37357
37636
  import { fileURLToPath } from "url";
37358
37637
  function validateTaskDag(plan) {
37359
37638
  const allTaskIds = new Set;
@@ -37650,7 +37929,7 @@ async function checkSpecStaleness(directory, plan) {
37650
37929
  };
37651
37930
  }
37652
37931
  async function checkConfigParseability(directory) {
37653
- const configPath = path20.join(directory, ".opencode/opencode-swarm.json");
37932
+ const configPath = path19.join(directory, ".opencode/opencode-swarm.json");
37654
37933
  if (!existsSync10(configPath)) {
37655
37934
  return {
37656
37935
  name: "Config Parseability",
@@ -37679,7 +37958,7 @@ function resolveGrammarDir(thisDir) {
37679
37958
  const normalized = thisDir.replace(/\\/g, "/");
37680
37959
  const isSource = normalized.endsWith("/src/services");
37681
37960
  const isCliBundle = normalized.endsWith("/cli");
37682
- return isSource || isCliBundle ? path20.join(thisDir, "..", "lang", "grammars") : path20.join(thisDir, "lang", "grammars");
37961
+ return isSource || isCliBundle ? path19.join(thisDir, "..", "lang", "grammars") : path19.join(thisDir, "lang", "grammars");
37683
37962
  }
37684
37963
  async function checkGrammarWasmFiles() {
37685
37964
  const grammarFiles = [
@@ -37703,14 +37982,14 @@ async function checkGrammarWasmFiles() {
37703
37982
  "tree-sitter-ini.wasm",
37704
37983
  "tree-sitter-regex.wasm"
37705
37984
  ];
37706
- const thisDir = path20.dirname(fileURLToPath(import.meta.url));
37985
+ const thisDir = path19.dirname(fileURLToPath(import.meta.url));
37707
37986
  const grammarDir = resolveGrammarDir(thisDir);
37708
37987
  const missing = [];
37709
- if (!existsSync10(path20.join(grammarDir, "tree-sitter.wasm"))) {
37988
+ if (!existsSync10(path19.join(grammarDir, "tree-sitter.wasm"))) {
37710
37989
  missing.push("tree-sitter.wasm (core runtime)");
37711
37990
  }
37712
37991
  for (const file3 of grammarFiles) {
37713
- if (!existsSync10(path20.join(grammarDir, file3))) {
37992
+ if (!existsSync10(path19.join(grammarDir, file3))) {
37714
37993
  missing.push(file3);
37715
37994
  }
37716
37995
  }
@@ -37728,7 +38007,7 @@ async function checkGrammarWasmFiles() {
37728
38007
  };
37729
38008
  }
37730
38009
  async function checkCheckpointManifest(directory) {
37731
- const manifestPath = path20.join(directory, ".swarm/checkpoints.json");
38010
+ const manifestPath = path19.join(directory, ".swarm/checkpoints.json");
37732
38011
  if (!existsSync10(manifestPath)) {
37733
38012
  return {
37734
38013
  name: "Checkpoint Manifest",
@@ -37780,7 +38059,7 @@ async function checkCheckpointManifest(directory) {
37780
38059
  }
37781
38060
  }
37782
38061
  async function checkEventStreamIntegrity(directory) {
37783
- const eventsPath = path20.join(directory, ".swarm/events.jsonl");
38062
+ const eventsPath = path19.join(directory, ".swarm/events.jsonl");
37784
38063
  if (!existsSync10(eventsPath)) {
37785
38064
  return {
37786
38065
  name: "Event Stream",
@@ -37821,7 +38100,7 @@ async function checkEventStreamIntegrity(directory) {
37821
38100
  }
37822
38101
  }
37823
38102
  async function checkSteeringDirectives(directory) {
37824
- const eventsPath = path20.join(directory, ".swarm/events.jsonl");
38103
+ const eventsPath = path19.join(directory, ".swarm/events.jsonl");
37825
38104
  if (!existsSync10(eventsPath)) {
37826
38105
  return {
37827
38106
  name: "Steering Directives",
@@ -37877,7 +38156,7 @@ async function checkCurator(directory) {
37877
38156
  detail: "Disabled (enable via curator.enabled)"
37878
38157
  };
37879
38158
  }
37880
- const summaryPath = path20.join(directory, ".swarm/curator-summary.json");
38159
+ const summaryPath = path19.join(directory, ".swarm/curator-summary.json");
37881
38160
  if (!existsSync10(summaryPath)) {
37882
38161
  return {
37883
38162
  name: "Curator",
@@ -38043,7 +38322,7 @@ async function getDiagnoseData(directory) {
38043
38322
  checks5.push(await checkSteeringDirectives(directory));
38044
38323
  checks5.push(await checkCurator(directory));
38045
38324
  try {
38046
- const evidenceDir = path20.join(directory, ".swarm", "evidence");
38325
+ const evidenceDir = path19.join(directory, ".swarm", "evidence");
38047
38326
  const snapshotFiles = existsSync10(evidenceDir) ? readdirSync4(evidenceDir).filter((f) => f.startsWith("agent-tools-") && f.endsWith(".json")) : [];
38048
38327
  if (snapshotFiles.length > 0) {
38049
38328
  const latest = snapshotFiles.sort().pop();
@@ -38081,7 +38360,7 @@ async function getDiagnoseData(directory) {
38081
38360
  cacheRows.push(`\u2B1C ${cachePath} \u2014 absent`);
38082
38361
  continue;
38083
38362
  }
38084
- const pkgJsonPath = path20.join(cachePath, "package.json");
38363
+ const pkgJsonPath = path19.join(cachePath, "package.json");
38085
38364
  try {
38086
38365
  const raw = readFileSync6(pkgJsonPath, "utf-8");
38087
38366
  const parsed = JSON.parse(raw);
@@ -38169,13 +38448,13 @@ __export(exports_config_doctor, {
38169
38448
  import * as crypto3 from "crypto";
38170
38449
  import * as fs8 from "fs";
38171
38450
  import * as os6 from "os";
38172
- import * as path21 from "path";
38451
+ import * as path20 from "path";
38173
38452
  function getUserConfigDir3() {
38174
- return process.env.XDG_CONFIG_HOME || path21.join(os6.homedir(), ".config");
38453
+ return process.env.XDG_CONFIG_HOME || path20.join(os6.homedir(), ".config");
38175
38454
  }
38176
38455
  function getConfigPaths(directory) {
38177
- const userConfigPath = path21.join(getUserConfigDir3(), "opencode", "opencode-swarm.json");
38178
- const projectConfigPath = path21.join(directory, ".opencode", "opencode-swarm.json");
38456
+ const userConfigPath = path20.join(getUserConfigDir3(), "opencode", "opencode-swarm.json");
38457
+ const projectConfigPath = path20.join(directory, ".opencode", "opencode-swarm.json");
38179
38458
  return { userConfigPath, projectConfigPath };
38180
38459
  }
38181
38460
  function computeHash(content) {
@@ -38200,9 +38479,9 @@ function isValidConfigPath(configPath, directory) {
38200
38479
  const normalizedUser = userConfigPath.replace(/\\/g, "/");
38201
38480
  const normalizedProject = projectConfigPath.replace(/\\/g, "/");
38202
38481
  try {
38203
- const resolvedConfig = path21.resolve(configPath);
38204
- const resolvedUser = path21.resolve(normalizedUser);
38205
- const resolvedProject = path21.resolve(normalizedProject);
38482
+ const resolvedConfig = path20.resolve(configPath);
38483
+ const resolvedUser = path20.resolve(normalizedUser);
38484
+ const resolvedProject = path20.resolve(normalizedProject);
38206
38485
  return resolvedConfig === resolvedUser || resolvedConfig === resolvedProject;
38207
38486
  } catch {
38208
38487
  return false;
@@ -38242,12 +38521,12 @@ function createConfigBackup(directory) {
38242
38521
  };
38243
38522
  }
38244
38523
  function writeBackupArtifact(directory, backup) {
38245
- const swarmDir = path21.join(directory, ".swarm");
38524
+ const swarmDir = path20.join(directory, ".swarm");
38246
38525
  if (!fs8.existsSync(swarmDir)) {
38247
38526
  fs8.mkdirSync(swarmDir, { recursive: true });
38248
38527
  }
38249
38528
  const backupFilename = `config-backup-${backup.createdAt}.json`;
38250
- const backupPath = path21.join(swarmDir, backupFilename);
38529
+ const backupPath = path20.join(swarmDir, backupFilename);
38251
38530
  const artifact = {
38252
38531
  createdAt: backup.createdAt,
38253
38532
  configPath: backup.configPath,
@@ -38277,7 +38556,7 @@ function restoreFromBackup(backupPath, directory) {
38277
38556
  return null;
38278
38557
  }
38279
38558
  const targetPath = artifact.configPath;
38280
- const targetDir = path21.dirname(targetPath);
38559
+ const targetDir = path20.dirname(targetPath);
38281
38560
  if (!fs8.existsSync(targetDir)) {
38282
38561
  fs8.mkdirSync(targetDir, { recursive: true });
38283
38562
  }
@@ -38308,9 +38587,9 @@ function readConfigFromFile(directory) {
38308
38587
  return null;
38309
38588
  }
38310
38589
  }
38311
- function validateConfigKey(path22, value, _config) {
38590
+ function validateConfigKey(path21, value, _config) {
38312
38591
  const findings = [];
38313
- switch (path22) {
38592
+ switch (path21) {
38314
38593
  case "agents": {
38315
38594
  if (value !== undefined) {
38316
38595
  findings.push({
@@ -38557,27 +38836,27 @@ function validateConfigKey(path22, value, _config) {
38557
38836
  }
38558
38837
  return findings;
38559
38838
  }
38560
- function walkConfigAndValidate(obj, path22, config3, findings) {
38839
+ function walkConfigAndValidate(obj, path21, config3, findings) {
38561
38840
  if (obj === null || obj === undefined) {
38562
38841
  return;
38563
38842
  }
38564
- if (path22 && typeof obj === "object" && !Array.isArray(obj)) {
38565
- const keyFindings = validateConfigKey(path22, obj, config3);
38843
+ if (path21 && typeof obj === "object" && !Array.isArray(obj)) {
38844
+ const keyFindings = validateConfigKey(path21, obj, config3);
38566
38845
  findings.push(...keyFindings);
38567
38846
  }
38568
38847
  if (typeof obj !== "object") {
38569
- const keyFindings = validateConfigKey(path22, obj, config3);
38848
+ const keyFindings = validateConfigKey(path21, obj, config3);
38570
38849
  findings.push(...keyFindings);
38571
38850
  return;
38572
38851
  }
38573
38852
  if (Array.isArray(obj)) {
38574
38853
  obj.forEach((item, index) => {
38575
- walkConfigAndValidate(item, `${path22}[${index}]`, config3, findings);
38854
+ walkConfigAndValidate(item, `${path21}[${index}]`, config3, findings);
38576
38855
  });
38577
38856
  return;
38578
38857
  }
38579
38858
  for (const [key, value] of Object.entries(obj)) {
38580
- const newPath = path22 ? `${path22}.${key}` : key;
38859
+ const newPath = path21 ? `${path21}.${key}` : key;
38581
38860
  walkConfigAndValidate(value, newPath, config3, findings);
38582
38861
  }
38583
38862
  }
@@ -38697,7 +38976,7 @@ function applySafeAutoFixes(directory, result) {
38697
38976
  }
38698
38977
  }
38699
38978
  if (appliedFixes.length > 0) {
38700
- const configDir = path21.dirname(configPath);
38979
+ const configDir = path20.dirname(configPath);
38701
38980
  if (!fs8.existsSync(configDir)) {
38702
38981
  fs8.mkdirSync(configDir, { recursive: true });
38703
38982
  }
@@ -38707,12 +38986,12 @@ function applySafeAutoFixes(directory, result) {
38707
38986
  return { appliedFixes, updatedConfigPath };
38708
38987
  }
38709
38988
  function writeDoctorArtifact(directory, result) {
38710
- const swarmDir = path21.join(directory, ".swarm");
38989
+ const swarmDir = path20.join(directory, ".swarm");
38711
38990
  if (!fs8.existsSync(swarmDir)) {
38712
38991
  fs8.mkdirSync(swarmDir, { recursive: true });
38713
38992
  }
38714
38993
  const artifactFilename = "config-doctor.json";
38715
- const artifactPath = path21.join(swarmDir, artifactFilename);
38994
+ const artifactPath = path20.join(swarmDir, artifactFilename);
38716
38995
  const guiOutput = {
38717
38996
  timestamp: result.timestamp,
38718
38997
  summary: result.summary,
@@ -39815,7 +40094,7 @@ var init_detector = __esm(() => {
39815
40094
 
39816
40095
  // src/build/discovery.ts
39817
40096
  import * as fs9 from "fs";
39818
- import * as path22 from "path";
40097
+ import * as path21 from "path";
39819
40098
  function isCommandAvailable(command) {
39820
40099
  if (toolchainCache.has(command)) {
39821
40100
  return toolchainCache.get(command);
@@ -39847,11 +40126,11 @@ function findBuildFiles(workingDir, patterns) {
39847
40126
  const regex = simpleGlobToRegex(pattern);
39848
40127
  const matches = files.filter((f) => regex.test(f));
39849
40128
  if (matches.length > 0) {
39850
- return path22.join(dir, matches[0]);
40129
+ return path21.join(dir, matches[0]);
39851
40130
  }
39852
40131
  } catch {}
39853
40132
  } else {
39854
- const filePath = path22.join(workingDir, pattern);
40133
+ const filePath = path21.join(workingDir, pattern);
39855
40134
  if (fs9.existsSync(filePath)) {
39856
40135
  return filePath;
39857
40136
  }
@@ -39860,7 +40139,7 @@ function findBuildFiles(workingDir, patterns) {
39860
40139
  return null;
39861
40140
  }
39862
40141
  function getRepoDefinedScripts(workingDir, scripts) {
39863
- const packageJsonPath = path22.join(workingDir, "package.json");
40142
+ const packageJsonPath = path21.join(workingDir, "package.json");
39864
40143
  if (!fs9.existsSync(packageJsonPath)) {
39865
40144
  return [];
39866
40145
  }
@@ -39901,7 +40180,7 @@ function findAllBuildFiles(workingDir) {
39901
40180
  const regex = simpleGlobToRegex(pattern);
39902
40181
  findFilesRecursive(workingDir, regex, allBuildFiles);
39903
40182
  } else {
39904
- const filePath = path22.join(workingDir, pattern);
40183
+ const filePath = path21.join(workingDir, pattern);
39905
40184
  if (fs9.existsSync(filePath)) {
39906
40185
  allBuildFiles.add(filePath);
39907
40186
  }
@@ -39914,7 +40193,7 @@ function findFilesRecursive(dir, regex, results) {
39914
40193
  try {
39915
40194
  const entries = fs9.readdirSync(dir, { withFileTypes: true });
39916
40195
  for (const entry of entries) {
39917
- const fullPath = path22.join(dir, entry.name);
40196
+ const fullPath = path21.join(dir, entry.name);
39918
40197
  if (entry.isDirectory() && !["node_modules", ".git", "dist", "build", "target"].includes(entry.name)) {
39919
40198
  findFilesRecursive(fullPath, regex, results);
39920
40199
  } else if (entry.isFile() && regex.test(entry.name)) {
@@ -39937,7 +40216,7 @@ async function discoverBuildCommandsFromProfiles(workingDir) {
39937
40216
  let foundCommand = false;
39938
40217
  for (const cmd of sortedCommands) {
39939
40218
  if (cmd.detectFile) {
39940
- const detectFilePath = path22.join(workingDir, cmd.detectFile);
40219
+ const detectFilePath = path21.join(workingDir, cmd.detectFile);
39941
40220
  if (!fs9.existsSync(detectFilePath)) {
39942
40221
  continue;
39943
40222
  }
@@ -39970,7 +40249,7 @@ async function discoverBuildCommands(workingDir, options) {
39970
40249
  const scope = options?.scope ?? "all";
39971
40250
  const changedFiles = options?.changedFiles ?? [];
39972
40251
  const _filesToCheck = filterByScope(workingDir, scope, changedFiles);
39973
- const profileResult = await _internals11.discoverBuildCommandsFromProfiles(workingDir);
40252
+ const profileResult = await _internals10.discoverBuildCommandsFromProfiles(workingDir);
39974
40253
  const profileCommands = profileResult.commands;
39975
40254
  const profileSkipped = profileResult.skipped;
39976
40255
  const coveredEcosystems = new Set;
@@ -40033,7 +40312,7 @@ function clearToolchainCache() {
40033
40312
  function getEcosystems() {
40034
40313
  return ECOSYSTEMS.map((e) => e.ecosystem);
40035
40314
  }
40036
- var ECOSYSTEMS, PROFILE_TO_ECOSYSTEM_NAMES, toolchainCache, _internals11, build_discovery;
40315
+ var ECOSYSTEMS, PROFILE_TO_ECOSYSTEM_NAMES, toolchainCache, _internals10, build_discovery;
40037
40316
  var init_discovery = __esm(() => {
40038
40317
  init_dist();
40039
40318
  init_detector();
@@ -40151,7 +40430,7 @@ var init_discovery = __esm(() => {
40151
40430
  php: ["php-composer"]
40152
40431
  };
40153
40432
  toolchainCache = new Map;
40154
- _internals11 = {
40433
+ _internals10 = {
40155
40434
  isCommandAvailable,
40156
40435
  discoverBuildCommandsFromProfiles,
40157
40436
  discoverBuildCommands,
@@ -40177,7 +40456,7 @@ var init_discovery = __esm(() => {
40177
40456
 
40178
40457
  // src/services/tool-doctor.ts
40179
40458
  import * as fs10 from "fs";
40180
- import * as path23 from "path";
40459
+ import * as path22 from "path";
40181
40460
  function extractRegisteredToolKeys(indexPath) {
40182
40461
  const registeredKeys = new Set;
40183
40462
  try {
@@ -40232,8 +40511,8 @@ function checkBinaryReadiness() {
40232
40511
  }
40233
40512
  function runToolDoctor(_directory, pluginRoot) {
40234
40513
  const findings = [];
40235
- const resolvedPluginRoot = pluginRoot ?? path23.resolve(import.meta.dir, "..", "..");
40236
- const indexPath = path23.join(resolvedPluginRoot, "src", "index.ts");
40514
+ const resolvedPluginRoot = pluginRoot ?? path22.resolve(import.meta.dir, "..", "..");
40515
+ const indexPath = path22.join(resolvedPluginRoot, "src", "index.ts");
40237
40516
  if (!fs10.existsSync(indexPath)) {
40238
40517
  return {
40239
40518
  findings: [
@@ -40403,7 +40682,7 @@ var exports_evidence_summary_service = {};
40403
40682
  __export(exports_evidence_summary_service, {
40404
40683
  isAutoSummaryEnabled: () => isAutoSummaryEnabled,
40405
40684
  buildEvidenceSummary: () => buildEvidenceSummary,
40406
- _internals: () => _internals12,
40685
+ _internals: () => _internals11,
40407
40686
  REQUIRED_EVIDENCE_TYPES: () => REQUIRED_EVIDENCE_TYPES,
40408
40687
  EVIDENCE_SUMMARY_VERSION: () => EVIDENCE_SUMMARY_VERSION
40409
40688
  });
@@ -40441,14 +40720,14 @@ function getTaskStatus(task, bundle) {
40441
40720
  if (task?.status) {
40442
40721
  return task.status;
40443
40722
  }
40444
- const entries = _internals12.normalizeBundleEntries(bundle);
40723
+ const entries = _internals11.normalizeBundleEntries(bundle);
40445
40724
  if (entries.length > 0) {
40446
40725
  return "completed";
40447
40726
  }
40448
40727
  return "pending";
40449
40728
  }
40450
40729
  function isEvidenceComplete(bundle) {
40451
- const entries = _internals12.normalizeBundleEntries(bundle);
40730
+ const entries = _internals11.normalizeBundleEntries(bundle);
40452
40731
  if (entries.length === 0) {
40453
40732
  return {
40454
40733
  isComplete: false,
@@ -40484,10 +40763,10 @@ async function buildTaskSummary(directory, task, taskId) {
40484
40763
  const result = await loadEvidence(directory, taskId);
40485
40764
  const bundle = result.status === "found" ? result.bundle : null;
40486
40765
  const phase = task?.phase ?? 0;
40487
- const status = _internals12.getTaskStatus(task, bundle);
40488
- const evidenceCheck = _internals12.isEvidenceComplete(bundle);
40489
- const blockers = _internals12.getTaskBlockers(task, evidenceCheck, status);
40490
- const entries = _internals12.normalizeBundleEntries(bundle);
40766
+ const status = _internals11.getTaskStatus(task, bundle);
40767
+ const evidenceCheck = _internals11.isEvidenceComplete(bundle);
40768
+ const blockers = _internals11.getTaskBlockers(task, evidenceCheck, status);
40769
+ const entries = _internals11.normalizeBundleEntries(bundle);
40491
40770
  const hasReview = entries.some((e) => e.type === "review");
40492
40771
  const hasTest = entries.some((e) => e.type === "test");
40493
40772
  const hasApproval = entries.some((e) => e.type === "approval");
@@ -40516,12 +40795,12 @@ async function buildPhaseSummary(directory, phase) {
40516
40795
  const taskSummaries = [];
40517
40796
  const _taskMap = new Map(phase.tasks.map((t) => [t.id, t]));
40518
40797
  for (const task of phase.tasks) {
40519
- const summary = await _internals12.buildTaskSummary(directory, task, task.id);
40798
+ const summary = await _internals11.buildTaskSummary(directory, task, task.id);
40520
40799
  taskSummaries.push(summary);
40521
40800
  }
40522
40801
  const extraTaskIds = taskIds.filter((id) => !phaseTaskIds.has(id));
40523
40802
  for (const taskId of extraTaskIds) {
40524
- const summary = await _internals12.buildTaskSummary(directory, undefined, taskId);
40803
+ const summary = await _internals11.buildTaskSummary(directory, undefined, taskId);
40525
40804
  if (summary.phase === phase.id) {
40526
40805
  taskSummaries.push(summary);
40527
40806
  }
@@ -40622,7 +40901,7 @@ async function buildEvidenceSummary(directory, currentPhase) {
40622
40901
  let totalTasks = 0;
40623
40902
  let completedTasks = 0;
40624
40903
  for (const phase of phasesToProcess) {
40625
- const summary = await _internals12.buildPhaseSummary(directory, phase);
40904
+ const summary = await _internals11.buildPhaseSummary(directory, phase);
40626
40905
  phaseSummaries.push(summary);
40627
40906
  totalTasks += summary.totalTasks;
40628
40907
  completedTasks += summary.completedTasks;
@@ -40644,7 +40923,7 @@ async function buildEvidenceSummary(directory, currentPhase) {
40644
40923
  overallBlockers,
40645
40924
  summaryText: ""
40646
40925
  };
40647
- artifact.summaryText = _internals12.generateSummaryText(artifact);
40926
+ artifact.summaryText = _internals11.generateSummaryText(artifact);
40648
40927
  log("[EvidenceSummary] Summary built", {
40649
40928
  phases: phaseSummaries.length,
40650
40929
  totalTasks,
@@ -40663,7 +40942,7 @@ function isAutoSummaryEnabled(automationConfig) {
40663
40942
  }
40664
40943
  return automationConfig.capabilities?.evidence_auto_summaries === true;
40665
40944
  }
40666
- var VALID_EVIDENCE_TYPES2, REQUIRED_EVIDENCE_TYPES, EVIDENCE_SUMMARY_VERSION = "1.0.0", _internals12;
40945
+ var VALID_EVIDENCE_TYPES2, REQUIRED_EVIDENCE_TYPES, EVIDENCE_SUMMARY_VERSION = "1.0.0", _internals11;
40667
40946
  var init_evidence_summary_service = __esm(() => {
40668
40947
  init_manager2();
40669
40948
  init_manager();
@@ -40677,7 +40956,7 @@ var init_evidence_summary_service = __esm(() => {
40677
40956
  "retrospective"
40678
40957
  ]);
40679
40958
  REQUIRED_EVIDENCE_TYPES = ["review", "test"];
40680
- _internals12 = {
40959
+ _internals11 = {
40681
40960
  buildEvidenceSummary,
40682
40961
  isAutoSummaryEnabled,
40683
40962
  normalizeBundleEntries,
@@ -40924,12 +41203,12 @@ var init_export = __esm(() => {
40924
41203
 
40925
41204
  // src/full-auto/state.ts
40926
41205
  import * as fs11 from "fs";
40927
- import * as path24 from "path";
41206
+ import * as path23 from "path";
40928
41207
  function nowISO() {
40929
41208
  return new Date().toISOString();
40930
41209
  }
40931
41210
  function ensureSwarmDir(directory) {
40932
- const swarmDir = path24.resolve(directory, ".swarm");
41211
+ const swarmDir = path23.resolve(directory, ".swarm");
40933
41212
  if (!fs11.existsSync(swarmDir)) {
40934
41213
  fs11.mkdirSync(swarmDir, { recursive: true });
40935
41214
  }
@@ -41280,7 +41559,7 @@ function extractCurrentPhaseFromPlan2(plan) {
41280
41559
  if (!plan) {
41281
41560
  return { currentPhase: null, currentTask: null, incompleteTasks: [] };
41282
41561
  }
41283
- if (!_internals13.validatePlanPhases(plan)) {
41562
+ if (!_internals12.validatePlanPhases(plan)) {
41284
41563
  return { currentPhase: null, currentTask: null, incompleteTasks: [] };
41285
41564
  }
41286
41565
  let currentPhase = null;
@@ -41422,9 +41701,9 @@ function extractPhaseMetrics(content) {
41422
41701
  async function getHandoffData(directory) {
41423
41702
  const now = new Date().toISOString();
41424
41703
  const sessionContent = await readSwarmFileAsync(directory, "session/state.json");
41425
- const sessionState = _internals13.parseSessionState(sessionContent);
41704
+ const sessionState = _internals12.parseSessionState(sessionContent);
41426
41705
  const plan = await loadPlanJsonOnly(directory);
41427
- const planInfo = _internals13.extractCurrentPhaseFromPlan(plan);
41706
+ const planInfo = _internals12.extractCurrentPhaseFromPlan(plan);
41428
41707
  if (!plan) {
41429
41708
  const planMdContent = await readSwarmFileAsync(directory, "plan.md");
41430
41709
  if (planMdContent) {
@@ -41443,8 +41722,8 @@ async function getHandoffData(directory) {
41443
41722
  }
41444
41723
  }
41445
41724
  const contextContent = await readSwarmFileAsync(directory, "context.md");
41446
- const recentDecisions = _internals13.extractDecisions(contextContent);
41447
- const rawPhaseMetrics = _internals13.extractPhaseMetrics(contextContent);
41725
+ const recentDecisions = _internals12.extractDecisions(contextContent);
41726
+ const rawPhaseMetrics = _internals12.extractPhaseMetrics(contextContent);
41448
41727
  const phaseMetrics = sanitizeString(rawPhaseMetrics, 1000);
41449
41728
  let delegationState = null;
41450
41729
  if (sessionState?.delegationState) {
@@ -41608,13 +41887,13 @@ ${lines.join(`
41608
41887
  `)}
41609
41888
  \`\`\``;
41610
41889
  }
41611
- var RTL_OVERRIDE_PATTERN, MAX_TASK_ID_LENGTH = 100, MAX_DECISION_LENGTH = 500, MAX_INCOMPLETE_TASKS = 20, _internals13;
41890
+ var RTL_OVERRIDE_PATTERN, MAX_TASK_ID_LENGTH = 100, MAX_DECISION_LENGTH = 500, MAX_INCOMPLETE_TASKS = 20, _internals12;
41612
41891
  var init_handoff_service = __esm(() => {
41613
41892
  init_utils2();
41614
41893
  init_manager();
41615
41894
  init_utils();
41616
41895
  RTL_OVERRIDE_PATTERN = /[\u202e\u202d\u202c\u200f]/g;
41617
- _internals13 = {
41896
+ _internals12 = {
41618
41897
  getHandoffData,
41619
41898
  formatHandoffMarkdown,
41620
41899
  formatContinuationPrompt,
@@ -41628,6 +41907,133 @@ var init_handoff_service = __esm(() => {
41628
41907
  };
41629
41908
  });
41630
41909
 
41910
+ // src/session/snapshot-writer.ts
41911
+ import { mkdirSync as mkdirSync10, renameSync as renameSync6 } from "fs";
41912
+ import * as path24 from "path";
41913
+ function serializeAgentSession(s) {
41914
+ const gateLog = {};
41915
+ const rawGateLog = s.gateLog ?? new Map;
41916
+ for (const [taskId, gates] of rawGateLog) {
41917
+ gateLog[taskId] = Array.from(gates ?? []);
41918
+ }
41919
+ const reviewerCallCount = {};
41920
+ const rawReviewerCallCount = s.reviewerCallCount ?? new Map;
41921
+ for (const [phase, count] of rawReviewerCallCount) {
41922
+ reviewerCallCount[String(phase)] = count;
41923
+ }
41924
+ const partialGateWarningsIssuedForTask = Array.from(s.partialGateWarningsIssuedForTask ?? new Set);
41925
+ const catastrophicPhaseWarnings = Array.from(s.catastrophicPhaseWarnings ?? new Set);
41926
+ const phaseAgentsDispatched = Array.from(s.phaseAgentsDispatched ?? new Set);
41927
+ const lastCompletedPhaseAgentsDispatched = Array.from(s.lastCompletedPhaseAgentsDispatched ?? new Set);
41928
+ const windows = {};
41929
+ const rawWindows = s.windows ?? {};
41930
+ for (const [key, win] of Object.entries(rawWindows)) {
41931
+ windows[key] = {
41932
+ id: win.id,
41933
+ agentName: win.agentName,
41934
+ startedAtMs: win.startedAtMs,
41935
+ toolCalls: win.toolCalls,
41936
+ consecutiveErrors: win.consecutiveErrors,
41937
+ hardLimitHit: win.hardLimitHit,
41938
+ lastSuccessTimeMs: win.lastSuccessTimeMs,
41939
+ recentToolCalls: win.recentToolCalls,
41940
+ warningIssued: win.warningIssued,
41941
+ warningReason: win.warningReason,
41942
+ transientRetryCount: win.transientRetryCount ?? 0
41943
+ };
41944
+ }
41945
+ return {
41946
+ agentName: s.agentName,
41947
+ lastToolCallTime: s.lastToolCallTime,
41948
+ lastAgentEventTime: s.lastAgentEventTime,
41949
+ delegationActive: s.delegationActive,
41950
+ activeInvocationId: s.activeInvocationId,
41951
+ lastInvocationIdByAgent: s.lastInvocationIdByAgent ?? {},
41952
+ windows,
41953
+ lastCompactionHint: s.lastCompactionHint ?? 0,
41954
+ architectWriteCount: s.architectWriteCount ?? 0,
41955
+ lastCoderDelegationTaskId: s.lastCoderDelegationTaskId ?? null,
41956
+ currentTaskId: s.currentTaskId ?? null,
41957
+ turboMode: s.turboMode ?? false,
41958
+ gateLog,
41959
+ reviewerCallCount,
41960
+ lastGateFailure: s.lastGateFailure ?? null,
41961
+ partialGateWarningsIssuedForTask,
41962
+ selfFixAttempted: s.selfFixAttempted ?? false,
41963
+ selfCodingWarnedAtCount: s.selfCodingWarnedAtCount ?? 0,
41964
+ catastrophicPhaseWarnings,
41965
+ lastPhaseCompleteTimestamp: s.lastPhaseCompleteTimestamp ?? 0,
41966
+ lastPhaseCompletePhase: s.lastPhaseCompletePhase ?? 0,
41967
+ phaseAgentsDispatched,
41968
+ lastCompletedPhaseAgentsDispatched,
41969
+ qaSkipCount: s.qaSkipCount ?? 0,
41970
+ qaSkipTaskIds: s.qaSkipTaskIds ?? [],
41971
+ pendingAdvisoryMessages: s.pendingAdvisoryMessages ?? [],
41972
+ taskWorkflowStates: Object.fromEntries(s.taskWorkflowStates ?? new Map),
41973
+ ...s.scopeViolationDetected !== undefined && {
41974
+ scopeViolationDetected: s.scopeViolationDetected
41975
+ },
41976
+ model_fallback_index: s.model_fallback_index ?? 0,
41977
+ modelFallbackExhausted: s.modelFallbackExhausted ?? false,
41978
+ coderRevisions: s.coderRevisions ?? 0,
41979
+ revisionLimitHit: s.revisionLimitHit ?? false,
41980
+ fullAutoMode: s.fullAutoMode ?? false,
41981
+ fullAutoInteractionCount: s.fullAutoInteractionCount ?? 0,
41982
+ fullAutoDeadlockCount: s.fullAutoDeadlockCount ?? 0,
41983
+ fullAutoLastQuestionHash: s.fullAutoLastQuestionHash ?? null,
41984
+ sessionRehydratedAt: s.sessionRehydratedAt ?? 0
41985
+ };
41986
+ }
41987
+ async function writeSnapshot(directory, state) {
41988
+ try {
41989
+ const snapshot = {
41990
+ version: 2,
41991
+ writtenAt: Date.now(),
41992
+ toolAggregates: Object.fromEntries(state.toolAggregates),
41993
+ activeAgent: Object.fromEntries(state.activeAgent),
41994
+ delegationChains: Object.fromEntries(state.delegationChains),
41995
+ agentSessions: {}
41996
+ };
41997
+ for (const [sessionId, sessionState] of state.agentSessions) {
41998
+ snapshot.agentSessions[sessionId] = serializeAgentSession(sessionState);
41999
+ }
42000
+ const content = JSON.stringify(snapshot, null, 2);
42001
+ const resolvedPath = validateSwarmPath(directory, "session/state.json");
42002
+ const dir = path24.dirname(resolvedPath);
42003
+ mkdirSync10(dir, { recursive: true });
42004
+ const tempPath = `${resolvedPath}.tmp.${Date.now()}.${Math.random().toString(36).slice(2)}`;
42005
+ await bunWrite(tempPath, content);
42006
+ renameSync6(tempPath, resolvedPath);
42007
+ } catch (error93) {
42008
+ log("[snapshot-writer] write failed", {
42009
+ error: error93 instanceof Error ? error93.message : String(error93)
42010
+ });
42011
+ }
42012
+ }
42013
+ function createSnapshotWriterHook(directory) {
42014
+ return (_input, _output) => {
42015
+ _writeInFlight = _writeInFlight.then(() => _internals13.writeSnapshot(directory, swarmState), () => _internals13.writeSnapshot(directory, swarmState));
42016
+ return _writeInFlight;
42017
+ };
42018
+ }
42019
+ async function flushPendingSnapshot(directory) {
42020
+ _writeInFlight = _writeInFlight.then(() => _internals13.writeSnapshot(directory, swarmState), () => _internals13.writeSnapshot(directory, swarmState));
42021
+ await _writeInFlight;
42022
+ }
42023
+ var _writeInFlight, _internals13;
42024
+ var init_snapshot_writer = __esm(() => {
42025
+ init_utils2();
42026
+ init_state();
42027
+ init_utils();
42028
+ init_bun_compat();
42029
+ _writeInFlight = Promise.resolve();
42030
+ _internals13 = {
42031
+ writeSnapshot,
42032
+ createSnapshotWriterHook,
42033
+ flushPendingSnapshot
42034
+ };
42035
+ });
42036
+
41631
42037
  // src/commands/handoff.ts
41632
42038
  import crypto4 from "crypto";
41633
42039
  import { renameSync as renameSync7, unlinkSync as unlinkSync4 } from "fs";
@@ -47772,7 +48178,7 @@ async function handleSimulateCommand(directory, args) {
47772
48178
  }
47773
48179
  let darkMatterPairs;
47774
48180
  try {
47775
- darkMatterPairs = await _internals10.detectDarkMatter(directory, options);
48181
+ darkMatterPairs = await _internals9.detectDarkMatter(directory, options);
47776
48182
  } catch (err) {
47777
48183
  const errMsg = err instanceof Error ? err.message : String(err);
47778
48184
  return `## Simulate Report