opencode-swarm 7.168.1 → 7.169.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.
Files changed (133) hide show
  1. package/.opencode/skills/swarm-pr-feedback/SKILL.md +11 -11
  2. package/binaries/win32-arm64/swarm-sandbox-runner.exe +0 -0
  3. package/binaries/win32-x64/swarm-sandbox-runner.exe +0 -0
  4. package/dist/cli/{coder-settlement-54a3d97g.js → coder-settlement-fd6ba876.js} +12 -12
  5. package/dist/cli/{config-doctor-vzp6b3ng.js → config-doctor-zeppqwwx.js} +2 -2
  6. package/dist/cli/{core-yynse50x.js → core-fj1afc31.js} +5 -2
  7. package/dist/cli/{curation-policy-mgwv8h2k.js → curation-policy-k74qz9ms.js} +5 -5
  8. package/dist/cli/{curator-drift-k0zrnm09.js → curator-drift-3ssjr0nx.js} +5 -5
  9. package/dist/cli/{curator-agdhhzqt.js → curator-emftndv0.js} +39 -38
  10. package/dist/cli/curator-llm-factory-4t773tmz.js +72 -0
  11. package/dist/cli/{dispatch-8ks9dyk5.js → dispatch-hwwj3qrb.js} +2 -2
  12. package/dist/cli/{evidence-summary-service-6mmcekr7.js → evidence-summary-service-51b69jc3.js} +16 -16
  13. package/dist/cli/{gate-evidence-xqvkqhrk.js → gate-evidence-53s161wb.js} +7 -7
  14. package/dist/cli/guardrail-explain-mhx8gt8q.js +73 -0
  15. package/dist/cli/{guardrail-log-5wa5c77w.js → guardrail-log-xg6hrdsq.js} +8 -8
  16. package/dist/cli/{guardrail-reset-dh78tbcf.js → guardrail-reset-fgv5kt5x.js} +39 -38
  17. package/dist/cli/{hive-promoter-3czsx7c6.js → hive-promoter-41zygtgx.js} +39 -38
  18. package/dist/cli/index-0hgmsyfp.js +92 -0
  19. package/dist/cli/{index-6df6wbvj.js → index-0vgs5r39.js} +8 -8
  20. package/dist/cli/{index-3jmb4ppa.js → index-1cbjemgh.js} +2 -2
  21. package/dist/cli/{index-p612v1mv.js → index-2s7dvzff.js} +200 -51
  22. package/dist/cli/{index-qthc56c4.js → index-2znfa537.js} +4 -4
  23. package/dist/cli/{index-91ww9hyr.js → index-3bfzpzsb.js} +1 -1
  24. package/dist/cli/{index-kkmezerc.js → index-3zcds757.js} +3101 -1918
  25. package/dist/cli/{index-d5qf7hvh.js → index-5400m33a.js} +1 -1
  26. package/dist/cli/{index-bw9x8d8n.js → index-55fkkjec.js} +5 -5
  27. package/dist/cli/{index-qwsh0h2g.js → index-5qt9yf5w.js} +4 -4
  28. package/dist/cli/{index-chebm5h5.js → index-5reh1bjz.js} +3 -3
  29. package/dist/cli/{index-2xbww1x0.js → index-76ng6vmq.js} +7 -7
  30. package/dist/cli/{index-qhey6vc3.js → index-7h01bkm6.js} +2 -2
  31. package/dist/cli/{index-gh9ybrrs.js → index-83m0y4cj.js} +6 -6
  32. package/dist/cli/{index-yt9n9zt3.js → index-8x9keek6.js} +41 -40
  33. package/dist/cli/{index-8ybjqg51.js → index-9ttqbhvw.js} +1 -1
  34. package/dist/cli/{index-kear8gb7.js → index-b3pmzbh1.js} +2 -2
  35. package/dist/cli/{index-h439y187.js → index-bernkwgf.js} +1 -1
  36. package/dist/cli/{index-m35hybf0.js → index-bm5xrfnx.js} +1 -1
  37. package/dist/cli/{index-pyf517sz.js → index-br3mvbsa.js} +2 -2
  38. package/dist/cli/{index-4r5pmtvk.js → index-bx1wgn3a.js} +4 -4
  39. package/dist/cli/{index-xhb4gryr.js → index-c7kr7tnk.js} +4 -4
  40. package/dist/cli/{index-nwwk3dej.js → index-cgpwjctj.js} +1 -1
  41. package/dist/cli/{index-q8091q8b.js → index-dd48vt27.js} +3 -3
  42. package/dist/cli/{index-wst6n478.js → index-dvbf6fpn.js} +1 -1
  43. package/dist/cli/{index-w3x1dmrf.js → index-e4dxf5cr.js} +39 -38
  44. package/dist/cli/{index-5g6rhkn7.js → index-egkc2bpv.js} +36 -1
  45. package/dist/cli/{index-4kv1ew3q.js → index-exf0j569.js} +1 -1
  46. package/dist/cli/{index-a8xbvsse.js → index-fgp96k3r.js} +2 -2
  47. package/dist/cli/{index-5zqakgp4.js → index-fhh02gwx.js} +3 -3
  48. package/dist/cli/{index-dfyv3xkd.js → index-gfbggp8k.js} +9 -9
  49. package/dist/cli/{index-f1fps3w9.js → index-ksybszed.js} +7 -7
  50. package/dist/cli/{index-v3xc4sde.js → index-nbdmdyke.js} +2 -1
  51. package/dist/cli/{index-z6qreakh.js → index-nprdr0sm.js} +6 -4
  52. package/dist/cli/{index-9b2105n0.js → index-nwv3e3kc.js} +2 -2
  53. package/dist/cli/{index-bvqqwx84.js → index-nyn01yrz.js} +2 -2
  54. package/dist/cli/{index-y85aptep.js → index-p6xsgk4r.js} +7 -7
  55. package/dist/cli/{index-xkf3672y.js → index-s96dpjsk.js} +2 -2
  56. package/dist/cli/{index-j0bxxz9d.js → index-sb1s03y9.js} +8 -8
  57. package/dist/cli/{index-gmpmgtzn.js → index-sxcfszbe.js} +5 -5
  58. package/dist/cli/{index-qkwtth00.js → index-wwr67xc0.js} +197 -35
  59. package/dist/cli/{index-gp9yzr1v.js → index-xnpjwc4h.js} +1 -1
  60. package/dist/cli/{index-apy1qfj0.js → index-yj24ny5k.js} +26 -4
  61. package/dist/cli/{index-w1dfkp1q.js → index-zapc8vj4.js} +14 -14
  62. package/dist/cli/index.js +39 -38
  63. package/dist/cli/{knowledge-escalator-135dz4eh.js → knowledge-escalator-07s44av0.js} +13 -13
  64. package/dist/cli/{knowledge-events-27gwv47q.js → knowledge-events-j2n1569p.js} +11 -11
  65. package/dist/cli/{knowledge-link-dr3xnwyd.js → knowledge-link-rkxfrmhm.js} +4 -4
  66. package/dist/cli/{knowledge-store-80m44bfw.js → knowledge-store-85metj89.js} +5 -5
  67. package/dist/cli/{knowledge-validator-crsfb2cc.js → knowledge-validator-63k1xzcc.js} +7 -7
  68. package/dist/cli/{pending-delegations-gwgjzzkz.js → pending-delegations-dckmjymn.js} +12 -12
  69. package/dist/cli/{pr-subscriptions-g633nhz4.js → pr-subscriptions-pyh73me6.js} +12 -12
  70. package/dist/cli/{pr-workflow-gate-4dc5nt2e.js → pr-workflow-gate-k1r4rjw4.js} +39 -38
  71. package/dist/cli/{runner-k0ycgv8x.js → runner-1dwrgyyr.js} +6 -6
  72. package/dist/cli/{scan-cursor-avxjsm4w.js → scan-cursor-k6egg4n0.js} +6 -6
  73. package/dist/cli/{schema-3ja77k4y.js → schema-vdrtpggt.js} +5 -1
  74. package/dist/cli/{scope-persistence-f540tc50.js → scope-persistence-h1mmww19.js} +14 -14
  75. package/dist/cli/{skill-generator-kcqqpg1g.js → skill-generator-pmn6gmvk.js} +15 -15
  76. package/dist/cli/{snapshot-coordination-init-e4s8bn4p.js → snapshot-coordination-init-rspykgd0.js} +39 -38
  77. package/dist/cli/{telemetry-2wzapf11.js → telemetry-fdtaemnv.js} +1 -1
  78. package/dist/cli/{workspace-snapshot-rkgxhj9b.js → workspace-snapshot-hkz2wt1c.js} +4 -4
  79. package/dist/cli/{worktree-collision-ownership-rk9gz638.js → worktree-collision-ownership-x84dzzzc.js} +18 -104
  80. package/dist/cli/{worktree-isolation-1bdzfgky.js → worktree-isolation-nw9pakkx.js} +39 -38
  81. package/dist/commands/destructive-purge.d.ts +85 -0
  82. package/dist/commands/registry.d.ts +2 -2
  83. package/dist/commands/reset-session.d.ts +5 -1
  84. package/dist/config/constants.d.ts +4 -1
  85. package/dist/config/lane-context.d.ts +19 -0
  86. package/dist/config/schema.d.ts +77 -0
  87. package/dist/evaluation/index.d.ts +1 -0
  88. package/dist/evaluation/retrieval-quality.d.ts +116 -0
  89. package/dist/failures/invocation-failure.d.ts +23 -4
  90. package/dist/hooks/init-orphan-recovery.d.ts +7 -0
  91. package/dist/hooks/pr-workflow-gate.d.ts +8 -2
  92. package/dist/index.js +596 -590
  93. package/dist/memory/embeddings/reranker.d.ts +13 -2
  94. package/dist/memory/evaluation.d.ts +99 -0
  95. package/dist/memory/heldout-evaluation-corpus.d.ts +51 -0
  96. package/dist/memory/index.d.ts +5 -2
  97. package/dist/memory/sqlite-provider.d.ts +35 -1
  98. package/dist/memory/types.d.ts +14 -0
  99. package/dist/observability/otel-mapping.d.ts +5 -5
  100. package/dist/observability/otlp-exporter.d.ts +80 -0
  101. package/dist/parallel/lane-owners.d.ts +76 -0
  102. package/dist/tools/repo-graph/query.d.ts +6 -1
  103. package/dist/tools/repo-graph/types.d.ts +13 -4
  104. package/dist/utils/bun-compat.d.ts +20 -0
  105. package/dist/utils/gitignore-warning.d.ts +5 -2
  106. package/dist/worktree/base-migration.d.ts +55 -0
  107. package/dist/worktree/core.d.ts +15 -6
  108. package/dist/worktree/ownership.d.ts +66 -0
  109. package/opencode-swarm.schema.json +97 -0
  110. package/package.json +4 -2
  111. package/tests/fixtures/memory-recall-heldout/manifest.json +311 -0
  112. package/tests/fixtures/memory-recall-heldout/sources/bash.sh +1 -0
  113. package/tests/fixtures/memory-recall-heldout/sources/c.c +1 -0
  114. package/tests/fixtures/memory-recall-heldout/sources/cpp.cpp +1 -0
  115. package/tests/fixtures/memory-recall-heldout/sources/csharp.cs +1 -0
  116. package/tests/fixtures/memory-recall-heldout/sources/css.css +3 -0
  117. package/tests/fixtures/memory-recall-heldout/sources/dart.dart +1 -0
  118. package/tests/fixtures/memory-recall-heldout/sources/go.go +3 -0
  119. package/tests/fixtures/memory-recall-heldout/sources/ini.ini +2 -0
  120. package/tests/fixtures/memory-recall-heldout/sources/java.java +1 -0
  121. package/tests/fixtures/memory-recall-heldout/sources/javascript.js +3 -0
  122. package/tests/fixtures/memory-recall-heldout/sources/kotlin.kt +1 -0
  123. package/tests/fixtures/memory-recall-heldout/sources/php.php +1 -0
  124. package/tests/fixtures/memory-recall-heldout/sources/powershell.ps1 +1 -0
  125. package/tests/fixtures/memory-recall-heldout/sources/python.py +2 -0
  126. package/tests/fixtures/memory-recall-heldout/sources/regex.regex +1 -0
  127. package/tests/fixtures/memory-recall-heldout/sources/ruby.rb +3 -0
  128. package/tests/fixtures/memory-recall-heldout/sources/rust.rs +1 -0
  129. package/tests/fixtures/memory-recall-heldout/sources/swift.swift +1 -0
  130. package/tests/fixtures/memory-recall-heldout/sources/tsx.tsx +3 -0
  131. package/tests/fixtures/memory-recall-heldout/sources/typescript.ts +3 -0
  132. package/dist/cli/curator-llm-factory-ygxd6hfx.js +0 -71
  133. package/dist/cli/guardrail-explain-vjtjhgzs.js +0 -72
@@ -3,6 +3,16 @@ export interface RerankCandidate {
3
3
  text: string;
4
4
  score?: number;
5
5
  }
6
+ /**
7
+ * The narrow reranking contract used by the SQLite retrieval pipeline.
8
+ * Keeping this structural makes deterministic, offline evaluation possible
9
+ * without making the optional transformers dependency part of the evaluator.
10
+ */
11
+ export interface MemoryReranker {
12
+ readonly available: boolean;
13
+ readonly modelVersion?: string;
14
+ rerank<T extends RerankCandidate>(candidates: T[], query?: string, topN?: number): Promise<T[]>;
15
+ }
6
16
  /**
7
17
  * Latency gate: skip reranking when the previous recall step already
8
18
  * exceeded the caller's latency budget.
@@ -18,8 +28,9 @@ export declare function shouldRerank(previousRecallElapsedMs: number, latencyBud
18
28
  * Graceful degradation: if the package is missing or the model fails to
19
29
  * load, `available` is false and rerank() returns candidates unchanged.
20
30
  */
21
- export declare class CrossEncoderReranker {
31
+ export declare class CrossEncoderReranker implements MemoryReranker {
22
32
  private readonly options;
33
+ readonly modelVersion: string;
23
34
  private loadFailed;
24
35
  private _available;
25
36
  private pipeline;
@@ -38,5 +49,5 @@ export declare class CrossEncoderReranker {
38
49
  * Returns the top `topN` candidates sorted descending by cross-encoder
39
50
  * score. If the model is unavailable, returns candidates unchanged.
40
51
  */
41
- rerank(candidates: RerankCandidate[], query: string, topN?: number): Promise<RerankCandidate[]>;
52
+ rerank<T extends RerankCandidate>(candidates: T[], query?: string, topN?: number): Promise<T[]>;
42
53
  }
@@ -1,10 +1,88 @@
1
+ import { type SQLiteRetrievalDependencies } from './sqlite-provider';
1
2
  import type { MemoryKind, MemoryRecord, MemoryScopeRef, MemorySource, RecallMode } from './types';
2
3
  export type RecallEvaluationProviderName = 'local-jsonl' | 'sqlite';
3
4
  export type RecallEvaluationMode = Extract<RecallMode, 'manual' | 'injection' | 'curator'>;
5
+ export type RecallEvaluationProfile = 'lexical' | 'hybrid' | 'hybrid+rerank';
6
+ export interface RecallEvaluationResourceCaps {
7
+ candidate_count: number;
8
+ token_budget: number;
9
+ }
10
+ export interface RecallEvaluationResourceUsage {
11
+ lexical_candidate_count: number;
12
+ dense_candidate_count: number;
13
+ rerank_candidate_count: number;
14
+ returned_count: number;
15
+ query_embedding_invocation_count: number;
16
+ /** Text-only estimate over actual returned records; prompt consumption is not measured here. */
17
+ returned_token_estimate: number;
18
+ }
19
+ export interface RecallEvaluationManifest {
20
+ version: '1.0.0';
21
+ source_id: string;
22
+ model_id: string;
23
+ provider_id: string;
24
+ config_hash: string;
25
+ corpus_hash: string;
26
+ profile_thresholds: Record<string, number>;
27
+ sample_counts: Record<string, number>;
28
+ metric_definitions: Record<string, string>;
29
+ uncertainty: {
30
+ method: string;
31
+ confidence: number;
32
+ sample_count: number;
33
+ };
34
+ variants?: Record<string, RecallEvaluationIdentity>;
35
+ }
36
+ export interface RecallEvaluationIdentity {
37
+ source_id: string;
38
+ model_id: string;
39
+ provider_id: string;
40
+ config_hash: string;
41
+ }
42
+ export interface RecallEvaluationScenario {
43
+ id: string;
44
+ language: string;
45
+ analyzer_id?: string;
46
+ source_provenance: 'direct-source';
47
+ /** Graph extraction/index querying is deliberately not claimed by memory recall. */
48
+ index_state: 'not-measured';
49
+ graph_measurement: {
50
+ status: 'unmeasured';
51
+ reason: string;
52
+ };
53
+ expected_symbols: string[];
54
+ expected_edges: Array<string | {
55
+ from: string;
56
+ to: string;
57
+ }>;
58
+ known_misses: string[];
59
+ spurious_edges: Array<string | {
60
+ from: string;
61
+ to: string;
62
+ }>;
63
+ }
64
+ export interface RecallEvaluationComparison {
65
+ fixture: string;
66
+ provider: RecallEvaluationProviderName;
67
+ mode: RecallEvaluationMode;
68
+ baseline_profile: RecallEvaluationProfile;
69
+ variant_profile: RecallEvaluationProfile;
70
+ precision_at_k_delta: number;
71
+ recall_at_k_delta: number;
72
+ latency_ms_delta: number;
73
+ cost_delta: null;
74
+ cost_comparison: 'unavailable';
75
+ }
4
76
  export interface RecallEvaluationOptions {
5
77
  fixtureDirectory: string;
6
78
  providers?: RecallEvaluationProviderName[];
7
79
  modes?: RecallEvaluationMode[];
80
+ /** Omitted preserves the legacy provider × mode report. */
81
+ profiles?: RecallEvaluationProfile[];
82
+ /** Instance-owned offline dependencies; never used by normal agent recall. */
83
+ dependencies?: SQLiteRetrievalDependencies;
84
+ resourceCaps?: Partial<RecallEvaluationResourceCaps>;
85
+ heldoutCorpusDirectory?: string;
8
86
  keepTempRoots?: boolean;
9
87
  }
10
88
  export interface RecallEvaluationMetrics {
@@ -28,6 +106,20 @@ export interface RecallEvaluationRun {
28
106
  retrieved_ids: string[];
29
107
  metrics: RecallEvaluationMetrics;
30
108
  passed: boolean;
109
+ profile?: RecallEvaluationProfile;
110
+ status?: 'complete' | 'degraded' | 'skipped';
111
+ degradation_reason?: string;
112
+ provenance?: string;
113
+ resource_cap?: RecallEvaluationResourceCaps;
114
+ resource_usage?: RecallEvaluationResourceUsage;
115
+ latency_ms?: number;
116
+ cost_provenance?: string;
117
+ cost?: {
118
+ provenance: string;
119
+ amount: null;
120
+ };
121
+ identity?: RecallEvaluationIdentity;
122
+ scenario?: RecallEvaluationScenario;
31
123
  }
32
124
  export interface RecallEvaluationReport {
33
125
  schema_version: 1;
@@ -41,6 +133,9 @@ export interface RecallEvaluationReport {
41
133
  passed_run_count: number;
42
134
  };
43
135
  runs: RecallEvaluationRun[];
136
+ comparisons: RecallEvaluationComparison[];
137
+ /** Additive contract metadata; schema_version stays v1 for legacy callers. */
138
+ manifest: RecallEvaluationManifest;
44
139
  }
45
140
  type FixtureRecordState = {
46
141
  deleted?: boolean;
@@ -71,7 +166,11 @@ interface RecallEvaluationFixture {
71
166
  k?: number;
72
167
  expectedLabels: string[];
73
168
  records: FixtureRecord[];
169
+ scenario?: RecallEvaluationScenario;
170
+ sourceHash?: string;
74
171
  }
75
172
  export declare function evaluateMemoryRecallFixtures(options: RecallEvaluationOptions): Promise<RecallEvaluationReport>;
76
173
  export declare function loadRecallEvaluationFixtures(fixtureDirectory: string): Promise<RecallEvaluationFixture[]>;
174
+ /** Strict, filesystem-independent report metadata validation. */
175
+ export declare function validateRecallEvaluationManifest(value: unknown): asserts value is RecallEvaluationManifest;
77
176
  export {};
@@ -0,0 +1,51 @@
1
+ export declare const MAX_HELDOUT_MANIFEST_BYTES: number;
2
+ export interface HeldoutRecallCorpusCase {
3
+ id?: string;
4
+ language: string;
5
+ expected_symbols: string[];
6
+ expected_edges: Array<string | {
7
+ from: string;
8
+ to: string;
9
+ }>;
10
+ known_misses: string[];
11
+ spurious_edges: Array<string | {
12
+ from: string;
13
+ to: string;
14
+ }>;
15
+ paraphrase: string;
16
+ source_path?: string;
17
+ content_hash?: string;
18
+ analyzer_id?: string;
19
+ }
20
+ export interface HeldoutRecallCorpusManifest {
21
+ corpus_id: string;
22
+ split: 'heldout';
23
+ version?: string;
24
+ thresholds?: Record<string, number>;
25
+ cases: HeldoutRecallCorpusCase[];
26
+ }
27
+ export interface LoadedHeldoutRecallScenario extends HeldoutRecallCorpusCase {
28
+ id: string;
29
+ source_text: string;
30
+ source_hash: string;
31
+ source_provenance: 'direct-source';
32
+ }
33
+ /**
34
+ * Validate the data contract only. Filesystem membership, safe paths, byte
35
+ * caps, and source hashes are intentionally enforced by the loader below.
36
+ */
37
+ export declare function validateHeldoutRecallCorpusManifest(value: unknown): asserts value is HeldoutRecallCorpusManifest;
38
+ /**
39
+ * Bounded filesystem boundary for held-out corpora. It does not recurse, and
40
+ * every optional source file must remain inside the supplied corpus root.
41
+ */
42
+ export declare function loadHeldoutRecallEvaluationCorpus(corpusDirectory: string): Promise<HeldoutRecallCorpusManifest>;
43
+ /**
44
+ * Bounded direct-source scenarios for production retrieval evaluation. This
45
+ * loader validates corpus membership and content hashes; it never scores or
46
+ * manufactures analyzer results.
47
+ */
48
+ export declare function loadHeldoutRecallEvaluationScenarios(corpusDirectory: string): Promise<{
49
+ manifest: HeldoutRecallCorpusManifest;
50
+ scenarios: LoadedHeldoutRecallScenario[];
51
+ }>;
@@ -1,9 +1,11 @@
1
1
  export type { MemoryConfig } from './config';
2
2
  export { DEFAULT_MEMORY_CONFIG, resolveMemoryConfig } from './config';
3
+ export type { MemoryReranker, RerankCandidate } from './embeddings/reranker';
3
4
  export { MemoryDisabledError, MemoryPiiDetectorError, MemoryValidationError, } from './errors';
4
- export { evaluateMemoryRecallFixtures, loadRecallEvaluationFixtures, type RecallEvaluationMetrics, type RecallEvaluationMode, type RecallEvaluationOptions, type RecallEvaluationProviderName, type RecallEvaluationReport, type RecallEvaluationRun, } from './evaluation';
5
+ export { evaluateMemoryRecallFixtures, loadRecallEvaluationFixtures, type RecallEvaluationComparison, type RecallEvaluationIdentity, type RecallEvaluationManifest, type RecallEvaluationMetrics, type RecallEvaluationMode, type RecallEvaluationOptions, type RecallEvaluationProfile, type RecallEvaluationProviderName, type RecallEvaluationReport, type RecallEvaluationResourceCaps, type RecallEvaluationResourceUsage, type RecallEvaluationRun, type RecallEvaluationScenario, validateRecallEvaluationManifest, } from './evaluation';
5
6
  export type { MemoryGatewayOptions, ProposeMemoryInput, RecallMemoryInput, RecordMemoryOutcomeInput, } from './gateway';
6
7
  export { createConfiguredMemoryProvider, createConfiguredMemoryProviderForRoot, createMemoryGateway, MemoryGateway, } from './gateway';
8
+ export { type HeldoutRecallCorpusCase, type HeldoutRecallCorpusManifest, type LoadedHeldoutRecallScenario, loadHeldoutRecallEvaluationCorpus, loadHeldoutRecallEvaluationScenarios, validateHeldoutRecallCorpusManifest, } from './heldout-evaluation-corpus';
7
9
  export { createMemoryLifecycleHooks, type MemoryLifecycleHookOptions, type MemoryLifecycleHooks, } from './injector';
8
10
  export { backupLegacyJsonl, getLegacyJsonlFileStatus, getLegacyOutcomeJsonlSignature, type JsonlBackupResult, type JsonlImportPayload, type JsonlInvalidRow, type JsonlMigrationReport, LEGACY_JSONL_MIGRATION_NAME, LEGACY_JSONL_MIGRATION_VERSION, LEGACY_JSONL_OUTCOME_META_KEY, readLegacyJsonl, readMigrationReport, resolveMemoryStorageDir, resolveSqliteDatabasePath, writeJsonlExport, writeMigrationReport, } from './jsonl-migration';
9
11
  export { LocalJsonlMemoryProvider } from './local-jsonl-provider';
@@ -19,6 +21,7 @@ export { readDeadAnchorMemoryIds, readReflectionDigest, recordOutcomeWithReflect
19
21
  export { MEMORY_RECALL_PROFILES, type MemoryRecallProfile, normalizeMemoryAgentRole, resolveMemoryRecallProfile, } from './role-profiles';
20
22
  export { appendMemoryRunLog, sanitizeRunId } from './run-log';
21
23
  export { computeMemoryContentHash, createBundleId, createMemoryId, createProposalId, isExpired, MemoryAnchorSchema, normalizeMemoryAnchorFile, normalizeMemoryText, validateCuratorMemoryDecision, validateMemoryProposal, validateMemoryRecordRules, } from './schema';
24
+ export type { MemoryRecallQualityTrace, SQLiteRetrievalDependencies, } from './sqlite-provider';
22
25
  export { EVENT_CHAIN_GENESIS, MEMORY_EVENTS_CHAIN_HEAD_KEY, type MemoryAuditVerificationReport, type MemoryEventRow, memoryEventRowHash, SQLiteMemoryProvider, verifyMemoryEventChainRows, } from './sqlite-provider';
23
26
  export { isCohortRoot, isLocalRoot, resolveVettedMemoryRoot, rootStoragePath, type VettedMemoryRoot, wrapLocalRoot, } from './storage-root';
24
- export type { AppliedMemoryChange, CuratorMemoryDecision, MemoryAnchor, MemoryContext, MemoryKind, MemoryListFilter, MemoryOutcome, MemoryPatch, MemoryProposal, MemoryRecord, MemoryRelation, MemoryScopeRef, MemoryScopeType, NewMemoryRecord, RecallBundle, RecallInjectionSkipReason, RecallMode, RecallRequest, RecallResultItem, ResolvedCuratorMemoryDecision, } from './types';
27
+ export type { AppliedMemoryChange, CuratorMemoryDecision, MemoryAnchor, MemoryContext, MemoryKind, MemoryListFilter, MemoryOutcome, MemoryPatch, MemoryProposal, MemoryRecord, MemoryRelation, MemoryScopeRef, MemoryScopeType, NewMemoryRecord, RecallBundle, RecallInjectionSkipReason, RecallMode, RecallQualityProfile, RecallRequest, RecallResultItem, ResolvedCuratorMemoryDecision, } from './types';
@@ -1,4 +1,6 @@
1
1
  import { type MemoryConfig } from './config';
2
+ import { type MemoryReranker } from './embeddings/reranker';
3
+ import type { EmbeddingProvider } from './embeddings/types';
2
4
  import { type JsonlMigrationReport } from './jsonl-migration';
3
5
  import { type MemoryOutcomeEvent } from './outcome-events';
4
6
  import type { MemoryCompactOptions, MemoryCompactResult, MemoryProposalStore, MemoryProvider, MemoryRecallUsageEvent, MemoryRecallUsageFilter, MemoryRewardEvent, MemoryRewardEventFilter, MemoryTransaction } from './provider';
@@ -55,6 +57,7 @@ interface Migration {
55
57
  name: string;
56
58
  sql: string;
57
59
  }
60
+ declare function capQualityRecallItemsByTokenBudget(items: readonly RecallResultItem[], tokenBudget: number): RecallResultItem[];
58
61
  export declare const MIGRATIONS: Migration[];
59
62
  export interface SQLiteJsonlImportResult {
60
63
  importedMemories: number;
@@ -63,6 +66,33 @@ export interface SQLiteJsonlImportResult {
63
66
  invalidRows: JsonlMigrationReport['invalidRows'];
64
67
  totalRows: number;
65
68
  }
69
+ export interface SQLiteRetrievalDependencies {
70
+ /** Optional deterministic override used by quality evaluation and focused tests. */
71
+ embeddingProvider?: EmbeddingProvider;
72
+ /** Selects dense candidates without claiming sqlite-vec availability. */
73
+ denseSelector?: (request: RecallRequest, queryEmbedding: Float32Array, records: readonly MemoryRecord[]) => Promise<MemoryRecord[]>;
74
+ reranker?: MemoryReranker;
75
+ /** Monotonic clock seam; default is Date.now. */
76
+ now?: () => number;
77
+ }
78
+ export interface MemoryRecallQualityTrace {
79
+ profile: 'lexical' | 'hybrid' | 'hybrid+rerank';
80
+ status: 'complete' | 'degraded' | 'skipped';
81
+ degradationReason?: string;
82
+ provenance: 'lexical' | 'sqlite-vec' | 'injected-dense';
83
+ usedEmbedding: boolean;
84
+ usedReranker: boolean;
85
+ latencyMs: number;
86
+ resourceUsage: {
87
+ lexical_candidate_count: number;
88
+ dense_candidate_count: number;
89
+ rerank_candidate_count: number;
90
+ returned_count: number;
91
+ query_embedding_invocation_count: number;
92
+ /** Deterministic estimate over the text actually returned, not a budget echo. */
93
+ returned_token_estimate: number;
94
+ };
95
+ }
66
96
  export declare class SQLiteMemoryProvider implements MemoryProvider, MemoryProposalStore {
67
97
  readonly name = "sqlite";
68
98
  private readonly rootDirectory;
@@ -83,6 +113,7 @@ export declare class SQLiteMemoryProvider implements MemoryProvider, MemoryPropo
83
113
  private embeddingProvider;
84
114
  private embeddingCache;
85
115
  private reranker;
116
+ private readonly retrievalDependencies;
86
117
  private memories;
87
118
  private proposals;
88
119
  private lastAutomaticJsonlMigration;
@@ -97,7 +128,7 @@ export declare class SQLiteMemoryProvider implements MemoryProvider, MemoryPropo
97
128
  * `.swarm` path with full `validateSwarmPath` enforcement (today's
98
129
  * behavior).
99
130
  */
100
- vettedCohortRoot?: string | null);
131
+ vettedCohortRoot?: string | null, retrievalDependencies?: SQLiteRetrievalDependencies);
101
132
  /**
102
133
  * #1850 (critic GAP-5): explicit cohort-root path branch.
103
134
  * - cohort root → `<cohortRoot>/memory.db` (NO validateSwarmPath — the
@@ -122,6 +153,7 @@ export declare class SQLiteMemoryProvider implements MemoryProvider, MemoryPropo
122
153
  recallWithDiagnostics(request: RecallRequest): Promise<{
123
154
  items: RecallResultItem[];
124
155
  diagnostics: RecallScoringDiagnostics;
156
+ qualityTrace?: MemoryRecallQualityTrace;
125
157
  }>;
126
158
  private expandRelated;
127
159
  recordRecallUsage(event: MemoryRecallUsageEvent): Promise<void>;
@@ -179,6 +211,7 @@ export declare class SQLiteMemoryProvider implements MemoryProvider, MemoryPropo
179
211
  private selectRecallCandidates;
180
212
  private getStoredModelVersion;
181
213
  private selectDenseCandidates;
214
+ private now;
182
215
  private runMigrations;
183
216
  private backfillScopeKeys;
184
217
  private backfillRecallRunIds;
@@ -292,5 +325,6 @@ export declare const _test_exports: {
292
325
  extractFtsTerms: typeof extractFtsTerms;
293
326
  FTS_SCHEMA_MIGRATION_NAME: string;
294
327
  FTS_SCHEMA_MIGRATION_VERSION: number;
328
+ capQualityRecallItemsByTokenBudget: typeof capQualityRecallItemsByTokenBudget;
295
329
  };
296
330
  export {};
@@ -195,6 +195,8 @@ export interface AppliedMemoryChange {
195
195
  }
196
196
  export type RecallMode = 'manual' | 'injection' | 'curator' | 'evaluation';
197
197
  export type RecallInjectionSkipReason = 'disabled' | 'no_signal' | 'below_threshold' | 'no_results';
198
+ /** Explicit, evaluator-only opt-in. Normal agent recall never requests it. */
199
+ export type RecallQualityProfile = 'lexical' | 'hybrid' | 'hybrid+rerank';
198
200
  export interface RecallRequest {
199
201
  query: string;
200
202
  task?: string;
@@ -214,6 +216,18 @@ export interface RecallRequest {
214
216
  * suppression never deletes or tombstones the underlying record.
215
217
  */
216
218
  includeLowQ?: boolean;
219
+ /**
220
+ * Produces bounded retrieval-quality telemetry on `recallWithDiagnostics`.
221
+ * This is intentionally opt-in so agent-facing recall output stays unchanged.
222
+ */
223
+ quality?: {
224
+ profile: RecallQualityProfile;
225
+ /**
226
+ * Bounded evaluator-only retrieval work cap. Omitted for normal agent
227
+ * recall, which preserves the established provider candidate behavior.
228
+ */
229
+ candidateCap?: number;
230
+ };
217
231
  }
218
232
  export interface RecallResultItem {
219
233
  record: MemoryRecord;
@@ -1,11 +1,11 @@
1
1
  /**
2
2
  * External-convention attribute mappings (issue #2029 item 6).
3
3
  *
4
- * These are INERT LOOKUP TABLES. There is no OpenTelemetry SDK dependency, no
5
- * exporter, and no runtime consumer in this change: the tables are consumed as
6
- * data by the static contract check (which asserts every catalog entry records a
7
- * mapping decision) and by `docs/observability-event-contract.md`. The runtime
8
- * consumer lands in #2049.
4
+ * These tables are DATA consumed by the static contract check (which asserts
5
+ * every catalog entry records a mapping decision), by
6
+ * `docs/observability-event-contract.md`, and since issue #2485 by the
7
+ * opt-in runtime exporter (`src/observability/otlp-exporter.ts`), the runtime
8
+ * consumer originally deferred here to #2049.
9
9
  *
10
10
  * Import rules: no filesystem, network, subprocess, or OTel SDK.
11
11
  */
@@ -0,0 +1,80 @@
1
+ import type { ObservabilityEvent } from './envelope.js';
2
+ /** Spool home, relative to the project root (retention-registry row `otlp-export-spool`). */
3
+ export declare const OTLP_EXPORT_SPOOL_DIR = ".swarm/otlp-export";
4
+ /** Bounded iteration ceiling for one flush cycle (drain-all semantics). */
5
+ export declare const MAX_FLUSH_ITERATIONS = 100;
6
+ export interface OtlpExportConfig {
7
+ enabled: boolean;
8
+ endpoint: string;
9
+ convention: 'genai' | 'openinference';
10
+ headers?: Record<string, string>;
11
+ batchSize: number;
12
+ flushIntervalMs: number;
13
+ requestTimeoutMs: number;
14
+ spoolMaxBytes: number;
15
+ spoolMaxAgeMs: number;
16
+ maxRetries: number;
17
+ backoffBaseMs: number;
18
+ backoffMaxMs: number;
19
+ circuitThreshold: number;
20
+ circuitCooldownMs: number;
21
+ }
22
+ export type OtlpExporterState = 'disabled' | 'active' | 'cooldown';
23
+ export interface OtlpExporterHealth {
24
+ state: OtlpExporterState;
25
+ convention: 'genai' | 'openinference' | null;
26
+ mappingVersion: string | null;
27
+ spoolRecords: number;
28
+ spoolBytes: number;
29
+ accepted: number;
30
+ exported: number;
31
+ retried: number;
32
+ dropped: Record<string, number>;
33
+ lastErrorCategory: string | null;
34
+ lastErrorAt: string | null;
35
+ lastSuccessAt: string | null;
36
+ circuitOpen: boolean;
37
+ }
38
+ /**
39
+ * Project a canonical event onto the pinned attribute table for `convention`
40
+ * plus the closed `swarm.*` extension set. PURE: no I/O, no clock, no throw.
41
+ * `legacy.raw` is read ONLY at the exact mapped keys with typeof guards —
42
+ * never traversed or serialized (it may be circular; envelope.ts documents
43
+ * the alias contract).
44
+ */
45
+ export declare function projectOtlpAttributes(event: ObservabilityEvent, convention: 'genai' | 'openinference'): Record<string, string | number | boolean>;
46
+ /**
47
+ * Build one OTLP/HTTP-JSON span for the event, or `null` when the event must
48
+ * not be exported at all (`content` privacy class).
49
+ */
50
+ export declare function buildOtlpSpan(event: ObservabilityEvent, convention: 'genai' | 'openinference'): Record<string, unknown> | null;
51
+ /** Minimal fetch shape used by the transport (Bun's fetch adds `preconnect`). */
52
+ export type OtlpFetch = (input: string | URL | Request, init?: RequestInit) => Promise<Response>;
53
+ /** DI seam (repo convention): tests inject a stub collector fetch. */
54
+ export declare const _internals: {
55
+ fetch: OtlpFetch;
56
+ sleep: (ms: number) => Promise<void>;
57
+ now: () => number;
58
+ };
59
+ /** Drain ALL pending batches now (bounded by MAX_FLUSH_ITERATIONS). */
60
+ export declare function flushOtlpExporterForTesting(directory: string): Promise<void>;
61
+ /**
62
+ * Register the OTLP exporter for this project root. O(1), idempotent, never
63
+ * throws — safe on the plugin init path (invariant 1). All flush/listener
64
+ * I/O is post-resolution; the ONE init-path exception is a small
65
+ * (state.json-sized) synchronous read performed only when the exporter is
66
+ * enabled — fail-open and far inside the invariant's latency budget. When
67
+ * disabled (default), the kill switch is set, or the endpoint violates
68
+ * policy, NOTHING is registered and no `.swarm/otlp-export/` directory is
69
+ * created.
70
+ */
71
+ export declare function registerOtlpExporter(directory: string, config: OtlpExportConfig): void;
72
+ export declare function isOtlpExporterActive(): boolean;
73
+ /**
74
+ * Drop the listener and forget in-memory state. Records already appended to
75
+ * the spool are ON DISK (appends are synchronous), so nothing in-flight is
76
+ * lost; counters are persisted before clearing so health survives rebind.
77
+ */
78
+ export declare function resetOtlpExporterForTesting(): void;
79
+ /** Merged health for `/swarm report`. Null when the exporter never ran here. */
80
+ export declare function readOtlpExporterHealth(directory: string): OtlpExporterHealth | null;
@@ -0,0 +1,76 @@
1
+ /**
2
+ * Issue #2527 (PARALLEL-3): durable live-lane owner records.
3
+ *
4
+ * Every cross-process liveness signal that existed before this module
5
+ * expired after five minutes regardless of the lane's actual state: lane
6
+ * lock metas are stamped once (`file-locks.ts` LOCK_TIMEOUT_MS) with no
7
+ * renewal path, and provisioning owners are leased for five minutes and
8
+ * then dropped by init orphan recovery. A lane that legitimately ran longer
9
+ * became invisible to a second process and was reclaimed as an "orphan".
10
+ *
11
+ * This store gives a lane a durable owner signal whose lifetime is the
12
+ * LANE's, not a lock TTL:
13
+ *
14
+ * - recorded at lane provisioning (lean runner AND standard worktree
15
+ * isolation — one primitive for both lane types, F3/A3);
16
+ * - cleared when the worktree is removed (`removeWorktree` in
17
+ * `src/worktree/core.ts`, both success returns) and by GC-on-read for
18
+ * any record whose lane path no longer exists (crashes, manual removal,
19
+ * every non-git deletion path);
20
+ * - liveness = owning PID exists AND the record's `startedAt` is within a
21
+ * 24-hour claim window. The window bounds PID-reuse blindness: a record
22
+ * older than 24h is stale regardless of what now lives at that PID
23
+ * (dispatch deadlines are minutes, so a genuinely-running lane never
24
+ * approaches it; a >24h CLEAN lane being reclaimed is the low-harm case
25
+ * — a >24h DIRTY lane still survives via git's own refusal, F2).
26
+ * `process.kill(pid, 0)` EPERM ⇒ alive (fail-closed on Windows ACLs).
27
+ *
28
+ * Store pattern mirrors `dead-lane-reclaim.ts`: a bounded JSON file under
29
+ * `.swarm/`, written via `atomicWriteSwarmFileSync`, never grown past the
30
+ * entry/byte caps.
31
+ */
32
+ import * as fs from 'node:fs';
33
+ import { atomicWriteSwarmFileSync } from '../utils/atomic-write';
34
+ /** Plan-critic round-1 item 5: PID-recency witness bound (24h). */
35
+ export declare const LIVE_LANE_OWNER_CLAIM_WINDOW_MS: number;
36
+ export interface LiveLaneOwnerEntry {
37
+ lanePath: string;
38
+ branchName: string;
39
+ sessionId: string;
40
+ taskId: string;
41
+ ownerPid: number;
42
+ startedAt: number;
43
+ }
44
+ export interface LiveLaneOwnersView {
45
+ /** Records whose owner process is alive within the claim window. */
46
+ live: LiveLaneOwnerEntry[];
47
+ /** Records dropped this read: path gone, or past the claim window. */
48
+ reaped: LiveLaneOwnerEntry[];
49
+ }
50
+ export declare const _internals: {
51
+ readFileSync: (p: string, enc: BufferEncoding) => string;
52
+ rmSync: typeof fs.rmSync;
53
+ statSync: (p: string) => unknown;
54
+ atomicWriteSwarmFileSync: typeof atomicWriteSwarmFileSync;
55
+ now: () => number;
56
+ kill: (pid: number, signal: 0) => true;
57
+ process: {
58
+ pid: number;
59
+ };
60
+ };
61
+ /** Record (or refresh) the durable owner of a live lane. Never throws. */
62
+ export declare function recordLiveLaneOwner(directory: string, entry: {
63
+ lanePath: string;
64
+ branchName: string;
65
+ sessionId: string;
66
+ taskId: string;
67
+ }): void;
68
+ /** Clear the durable owner record for one lane path. Never throws. */
69
+ export declare function clearLiveLaneOwner(directory: string, lanePath: string): void;
70
+ /**
71
+ * Read the live-lane-owner view, GC-ing records whose lane path no longer
72
+ * exists (universal clear fallback: every removal path that bypassed
73
+ * `removeWorktree` — manual rm, /swarm close sweeps, future tooling — is
74
+ * healed on the next read) and records past the 24h claim window.
75
+ */
76
+ export declare function listLiveLaneOwners(directory: string): LiveLaneOwnersView;
@@ -1,6 +1,11 @@
1
1
  import type { FreshnessProbe } from './freshness';
2
- import type { BlastRadiusResult, CallerReference, ContextPackResult, ContextPackSourceMode, DeadExportsResult, FileOntology, FileReference, GraphHealthResult, GraphNode, LocalizationBlock, PackageBoundarySummary, RepoGraph, SymbolReference } from './types';
2
+ import type { BlastRadiusResult, CallerReference, ContextPackResult, ContextPackSourceMode, DeadExportsResult, FileOntology, FileReference, GraphHealthResult, GraphNode, LocalizationBlock, PackageBoundarySummary, RepoGraph, SymbolEdge, SymbolReference } from './types';
3
+ export interface SymbolEdgeIndexes {
4
+ forward: Map<string, SymbolEdge[]>;
5
+ reverse: Map<string, SymbolEdge[]>;
6
+ }
3
7
  export declare function getGraphNode(graph: RepoGraph, input: string): GraphNode | undefined;
8
+ export declare function getSymbolEdgeIndexes(graph: RepoGraph): SymbolEdgeIndexes;
4
9
  /**
5
10
  * Drop every cached query index. Required after any in-place mutation of a
6
11
  * graph's `nodes` or `edges` (see the {@link queryIndexCache} contract note),
@@ -14,8 +14,7 @@ export declare const REPO_GRAPH_FILENAME = "repo-graph.json";
14
14
  * the importing file) and per-node `exportLines`, enabling the `callers` and
15
15
  * `dead_exports` queries. Both fields are optional, so graphs written by older
16
16
  * versions (1.0.0) still load — but `dead_exports` requires >= 1.1.0 data and
17
- * self-gates via {@link isSchemaVersionAtLeast} rather than relying on the
18
- * loader (which only checks that a version string is present, not its value).
17
+ * self-gates via {@link isSchemaVersionAtLeast}.
19
18
  *
20
19
  * 1.2.0 adds per-node `exportRanges` (1-based inclusive line spans keyed by
21
20
  * symbol name — exported symbols for every grammar, plus non-exported member
@@ -29,8 +28,8 @@ export declare const REPO_GRAPH_FILENAME = "repo-graph.json";
29
28
  * that distinguishes edges whose resolved target is a scannable source file
30
29
  * (a graph node) from edges whose target is an asset (JSON/CSS/etc. — a real
31
30
  * file that never becomes a node). The field is optional, so 1.0.0–1.2.0
32
- * graphs still load; `storage.ts` only checks that a version string is
33
- * present, and feature gating is per-query via {@link isSchemaVersionAtLeast}.
31
+ * graphs still load; feature gating is per-query via
32
+ * {@link isSchemaVersionAtLeast}.
34
33
  * For pre-1.3.0 graphs the loader/queries fall back to an extension check
35
34
  * (`isScannableSourcePath`) to classify an untagged edge's target kind.
36
35
  *
@@ -65,6 +64,8 @@ export declare const REPO_GRAPH_FILENAME = "repo-graph.json";
65
64
  * notes instead of failing (issue #1536).
66
65
  */
67
66
  export declare const GRAPH_SCHEMA_VERSION = "1.7.0";
67
+ /** The oldest graph schema whose persisted shape this build can interpret. */
68
+ export declare const MIN_SUPPORTED_GRAPH_SCHEMA_VERSION = "1.0.0";
68
69
  /**
69
70
  * Default per-file source-size ceiling shared by graph construction and
70
71
  * query-time source reads. The builder treats this as the default value of
@@ -80,6 +81,14 @@ export declare const DEFAULT_MAX_SOURCE_BYTES: number;
80
81
  * is greater than or equal to `minimum`.
81
82
  */
82
83
  export declare function isSchemaVersionAtLeast(version: string | undefined, minimum: string): boolean;
84
+ /**
85
+ * Return whether a persisted graph schema is a canonical numeric semver in
86
+ * the supported compatibility window. This is deliberately stricter than
87
+ * {@link isSchemaVersionAtLeast}: feature gates may tolerate malformed input
88
+ * by treating missing components as zero, but a persistence boundary must
89
+ * never trust an unknown or future graph shape.
90
+ */
91
+ export declare function isGraphSchemaVersionCompatible(version: unknown): version is string;
83
92
  export declare const FILE_ROLE_VALUES: readonly ["api_route", "middleware", "service_module", "data_module", "swarm_tool", "agent", "hook", "config", "schema", "test_file", "cli_command", "documentation", "source_module"];
84
93
  export type FileRole = (typeof FILE_ROLE_VALUES)[number];
85
94
  export declare const ROUTE_METHOD_VALUES: readonly ["GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS", "HEAD", "ALL"];
@@ -98,6 +98,14 @@ export interface BunCompatSpawnOptions {
98
98
  stdout?: 'inherit' | 'ignore' | 'pipe';
99
99
  stderr?: 'inherit' | 'ignore' | 'pipe';
100
100
  timeout?: number;
101
+ /**
102
+ * Maximum bytes retained for each buffered stdout/stderr stream. Invalid
103
+ * values fall back to `DEFAULT_BUN_SPAWN_MAX_BUFFER_BYTES` so asynchronous
104
+ * `bunSpawn` keeps its no-throw compatibility contract. Synchronous
105
+ * `bunSpawnSync` delegates to the host synchronous API and does not apply
106
+ * this asynchronous stream-capture option.
107
+ */
108
+ maxBuffer?: number;
101
109
  /** Preserve the caller's exact Windows argv quoting (required for cmd.exe /c). */
102
110
  windowsVerbatimArguments?: boolean;
103
111
  /**
@@ -111,6 +119,18 @@ export interface BunCompatSpawnOptions {
111
119
  */
112
120
  killProcessTree?: boolean;
113
121
  }
122
+ /**
123
+ * Default bounded capture for unclaimed subprocess pipes. Five MiB matches
124
+ * the established Git subprocess limit while remaining finite by default.
125
+ */
126
+ export declare const DEFAULT_BUN_SPAWN_MAX_BUFFER_BYTES: number;
127
+ /** Raised when either buffered pipe exceeds its configured output limit. */
128
+ export declare class BunCompatOutputLimitError extends Error {
129
+ readonly limit: number;
130
+ readonly captured: number;
131
+ readonly total: number;
132
+ constructor(limit: number, captured: number, total: number);
133
+ }
114
134
  export interface BunCompatStream {
115
135
  text(): Promise<string>;
116
136
  bytes(): Promise<Uint8Array>;
@@ -87,8 +87,11 @@ export declare const ENSURE_SWARM_GIT_EXCLUDED_PER_CALL_TIMEOUT_MS = 1500;
87
87
  * Steps:
88
88
  * 1. Resolve git root via `git rev-parse --show-toplevel`
89
89
  * 2. Resolve local exclude path via `git rev-parse --git-path info/exclude`
90
- * 3. Check if `.swarm/` is already ignored via `git check-ignore -q`
91
- * 4. If not ignored: append `.swarm/` to the local exclude file (idempotent)
90
+ * 3. Check if `.swarm/` AND `.swarm-worktrees/` are already ignored via two
91
+ * independent `git check-ignore -q` probes (they are distinct patterns
92
+ * `.swarm/` does not cover `.swarm-worktrees/`, #2527)
93
+ * 4. For whichever pattern is not ignored: append it to the local exclude
94
+ * file (idempotent, per-pattern)
92
95
  * 5. Detect tracked `.swarm/` files via `git ls-files -- .swarm`
93
96
  * 6. If tracked: emit an unsuppressed remediation warning
94
97
  *