opencode-swarm 7.153.2 → 7.154.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 (71) hide show
  1. package/dist/background/pending-delegations.d.ts +29 -0
  2. package/dist/background/pr-subscriptions.d.ts +258 -27
  3. package/dist/cli/{config-doctor-tv0ar88m.js → config-doctor-8p9y543t.js} +2 -2
  4. package/dist/cli/{core-kmsm50zn.js → core-1h6x6k59.js} +1 -1
  5. package/dist/cli/{curation-policy-twa6agf8.js → curation-policy-9r902jw4.js} +6 -6
  6. package/dist/cli/{curator-llm-factory-dxkhdhwg.js → curator-llm-factory-ypwf3a90.js} +29 -29
  7. package/dist/cli/{curator-wxe863k9.js → curator-yj00z1qz.js} +29 -29
  8. package/dist/cli/{evidence-summary-service-9akrdg9t.js → evidence-summary-service-npq04240.js} +12 -12
  9. package/dist/cli/{gate-evidence-bdzqbg2y.js → gate-evidence-4b6t0ycn.js} +6 -6
  10. package/dist/cli/{guardrail-explain-kx9rem51.js → guardrail-explain-dyxbhrdj.js} +30 -30
  11. package/dist/cli/{guardrail-log-zxzyx1de.js → guardrail-log-eyecsekk.js} +5 -5
  12. package/dist/cli/{guardrail-reset-1mc3st34.js → guardrail-reset-269jdwhd.js} +29 -29
  13. package/dist/cli/{hive-promoter-gncwtq0z.js → hive-promoter-5936am48.js} +29 -29
  14. package/dist/cli/{index-hhv2pvab.js → index-10zvxqra.js} +1 -1
  15. package/dist/cli/{index-j4f8sz67.js → index-1tdsddab.js} +192 -102
  16. package/dist/cli/{index-kenz5bja.js → index-2kzxkx50.js} +31 -31
  17. package/dist/cli/{index-3bh4h6ve.js → index-2mbs5q26.js} +7 -7
  18. package/dist/cli/{index-x3y6zhgj.js → index-3db7xza0.js} +1 -1
  19. package/dist/cli/{index-h3zhb18p.js → index-3hdnfmhp.js} +2 -2
  20. package/dist/cli/{index-84m4per1.js → index-3mhgv8d6.js} +2 -2
  21. package/dist/cli/{index-21pt4jwf.js → index-48m4841x.js} +1 -1
  22. package/dist/cli/{index-ebshrg4x.js → index-4g00jhbs.js} +3 -3
  23. package/dist/cli/{index-5zp4c36c.js → index-4y7g04py.js} +1 -1
  24. package/dist/cli/{index-vhbds89e.js → index-68w5jxv5.js} +4 -4
  25. package/dist/cli/{index-4pjkdcgc.js → index-6yc06dx9.js} +1 -1
  26. package/dist/cli/{index-2mqmvxac.js → index-7jnh1sgb.js} +7 -1
  27. package/dist/cli/{index-pk1gbqmq.js → index-c6dfyzdh.js} +1 -1
  28. package/dist/cli/{index-td0jz8xe.js → index-c809a69b.js} +2 -2
  29. package/dist/cli/{index-0azn976d.js → index-dwh02jmv.js} +7 -7
  30. package/dist/cli/{index-3cegckkq.js → index-garsang6.js} +1 -1
  31. package/dist/cli/{index-bw55r5bz.js → index-hk4wa0v1.js} +6 -6
  32. package/dist/cli/{index-5ad8xcv3.js → index-mddgkqg9.js} +2 -2
  33. package/dist/cli/{index-s6b8jgtn.js → index-nkr634n6.js} +1 -1
  34. package/dist/cli/{index-3fpqpyp6.js → index-p4y7jefb.js} +2 -2
  35. package/dist/cli/{index-kvk65qzz.js → index-pcj7jk4t.js} +3 -3
  36. package/dist/cli/{index-56ejcj07.js → index-qcz4xprd.js} +4 -4
  37. package/dist/cli/{index-zppxpc3y.js → index-s0a4ewkb.js} +2 -2
  38. package/dist/cli/{index-h06112sh.js → index-s70tmqn3.js} +5 -5
  39. package/dist/cli/{index-yvepnbyd.js → index-snnps1vm.js} +5 -5
  40. package/dist/cli/{index-a58nmnmz.js → index-tnm9bb8b.js} +5 -3
  41. package/dist/cli/{index-x8vw6ap1.js → index-ttqnhxxq.js} +59 -42
  42. package/dist/cli/{index-891g7hbf.js → index-vtdwkfbv.js} +1 -1
  43. package/dist/cli/index-wfxg3s7n.js +1158 -0
  44. package/dist/cli/{index-02rbfrab.js → index-wpstzk85.js} +4 -4
  45. package/dist/cli/{index-1gzdnjg9.js → index-y64jrbch.js} +2 -2
  46. package/dist/cli/{index-3ttktt56.js → index-yve4e8fx.js} +1 -1
  47. package/dist/cli/index.js +29 -29
  48. package/dist/cli/{knowledge-escalator-gp3mpbqe.js → knowledge-escalator-bxpzeth0.js} +11 -11
  49. package/dist/cli/{knowledge-events-nvkhtqvn.js → knowledge-events-jxdpg2hj.js} +9 -9
  50. package/dist/cli/{knowledge-link-ge0rddxw.js → knowledge-link-nwxykjya.js} +5 -5
  51. package/dist/cli/{knowledge-store-2ngh8xvv.js → knowledge-store-336hyzs8.js} +6 -6
  52. package/dist/cli/{knowledge-validator-4bphyrec.js → knowledge-validator-9wkvnsv0.js} +8 -8
  53. package/dist/cli/{pending-delegations-nk78wx7h.js → pending-delegations-0fmj1qy6.js} +3 -3
  54. package/dist/cli/{pr-subscriptions-dq1f61ye.js → pr-subscriptions-1ndwgtbw.js} +15 -4
  55. package/dist/cli/{runner-n50w1y4w.js → runner-06dvm53x.js} +6 -6
  56. package/dist/cli/{scan-cursor-c16xtygz.js → scan-cursor-3xxqtxwx.js} +7 -7
  57. package/dist/cli/{schema-83tbte2g.js → schema-jdx83m4m.js} +1 -1
  58. package/dist/cli/{scope-persistence-gdbw8xh8.js → scope-persistence-wgxn2kba.js} +8 -8
  59. package/dist/cli/{skill-generator-gr13xeha.js → skill-generator-vmxsc2fm.js} +13 -13
  60. package/dist/cli/{telemetry-hh1j99za.js → telemetry-q2km2zrz.js} +1 -1
  61. package/dist/cli/{worktree-collision-ownership-4drcjymy.js → worktree-collision-ownership-gsay5210.js} +5 -5
  62. package/dist/cli/{worktree-isolation-jjkfg2pg.js → worktree-isolation-peb4bkg3.js} +29 -29
  63. package/dist/commands/pr-monitor-status.d.ts +8 -1
  64. package/dist/config/schema.d.ts +8 -0
  65. package/dist/hooks/pr-review-resilience-circuit.d.ts +232 -0
  66. package/dist/hooks/pr-workflow-gate.d.ts +10 -11
  67. package/dist/index.js +298 -289
  68. package/dist/observability/catalog.d.ts +6 -3
  69. package/dist/telemetry.d.ts +21 -1
  70. package/package.json +1 -1
  71. package/dist/cli/index-meg33yyv.js +0 -247
@@ -242,6 +242,26 @@ export interface BackgroundDelegationWorkflowLaneRecovery {
242
242
  reason: string;
243
243
  }
244
244
  export type BackgroundDelegationWorkflowLaneFailureClass = 'contract' | 'resource' | 'deadline';
245
+ /**
246
+ * Issue #2382: structured, bounded classification of the terminal error that
247
+ * settled a lane, captured from `classifyLaneTerminalError` at settle time so
248
+ * downstream consumers (the PR-review resilience circuit) can derive a typed
249
+ * provider-terminal signal from durable evidence instead of parsing the
250
+ * bounded display string in `error`.
251
+ *
252
+ * Deliberately carries NO message text: `error` remains the display surface.
253
+ * `kind` mirrors the SDK discriminator semantics (authoritative for the
254
+ * settled status); `category`/`statusCode`/`hostRetryable` are advisory
255
+ * provenance from `classifyProviderFailure` / `ApiError.data`.
256
+ */
257
+ export interface BackgroundDelegationTerminalErrorClass {
258
+ kind: 'provider' | 'aborted' | 'output_length' | 'unknown';
259
+ /** Canonical `classifyProviderFailure` category (e.g. `provider.rate_limit`). */
260
+ category: string;
261
+ statusCode?: number;
262
+ /** `ApiError.data.isRetryable` — host-stated, not inferred. */
263
+ hostRetryable?: boolean;
264
+ }
245
265
  export interface BackgroundDelegationResult {
246
266
  text?: string;
247
267
  error?: string;
@@ -259,6 +279,15 @@ export interface BackgroundDelegationResult {
259
279
  * Optional because successful lanes and legacy terminal results have none.
260
280
  */
261
281
  workflowLaneFailureClass?: BackgroundDelegationWorkflowLaneFailureClass;
282
+ /**
283
+ * Issue #2382: typed terminal-error classification captured at settle time
284
+ * (see {@link BackgroundDelegationTerminalErrorClass}). Optional because only
285
+ * lanes settled from a real child run with a classified terminal error carry
286
+ * it; successful, cancelled, stale, and legacy records have none. Present in
287
+ * the `.strict()` ResultSchema below in the same edit — an undeclared field
288
+ * here would make whole records invisible to `readDelegations`.
289
+ */
290
+ terminalErrorClass?: BackgroundDelegationTerminalErrorClass;
262
291
  /**
263
292
  * Workflow lanes whose discovery artifact was accepted only after repair — a
264
293
  * synthesized canonical header, or valid rows retained beside malformed ones.
@@ -1,30 +1,126 @@
1
1
  /**
2
- * Durable PR monitoring subscription store.
2
+ * Durable PR monitoring subscription store (bounded checkpoint model, issue #2042).
3
3
  *
4
- * Append-only JSONL event log under project-root
5
- * `.swarm/pr-monitor/subscriptions.jsonl`. Each line is a full record snapshot;
6
- * readers fold to the latest snapshot per `correlationId`. This tracks which PRs
7
- * are actively being monitored by which sessions so the background poller knows
8
- * what to watch.
4
+ * State lives under project-root `.swarm/pr-monitor/`:
9
5
  *
10
- * Concurrency: all writes (subscribe, unsubscribe, update, sweep) run under a
11
- * single project-scoped lock via `withEvidenceLock`, so concurrent callers cannot
12
- * interleave appends. Reads are lock-free (line-oriented; partial trailing lines
13
- * are skipped defensively).
6
+ * - `subscriptions.checkpoint.json` authoritative, versioned, atomically
7
+ * written (tmp+rename) snapshot of the latest validated record per
8
+ * `correlationId`, plus a bounded terminal-record set, migration cursor, and
9
+ * maintenance counters. Every read is bounded by the live set (~tens of
10
+ * records), never by history.
11
+ * - `subscriptions.audit.jsonl` — bounded transition audit tail (subscribe /
12
+ * unsubscribe / expire / compaction / migration / archive / recovery events
13
+ * only — NOT per-poll snapshots). High/low-water rewrite keeps the newest
14
+ * lines under hard line+byte bounds.
15
+ * - `subscriptions.jsonl` — LEGACY v1 append-only log. Before a checkpoint
16
+ * exists it is the read source (v1 semantics preserved); afterwards it is a
17
+ * migration source only. Migration folds it incrementally under bounded
18
+ * memory, persists a crash-resumable byte cursor, then renames the absorbed
19
+ * file to `subscriptions.legacy.jsonl` (deleted once older than
20
+ * `legacyArchiveTtlMs`). If the legacy file later changes (downgrade /
21
+ * external v1 writer), the tail is re-folded and absorbed — v1 append
22
+ * semantics keep working.
14
23
  *
15
- * Containment: the path is validated with `validateSwarmPath`, so it can never
24
+ * Merge semantics (last-write-wins, v1-compatible):
25
+ * - within the legacy log, the later line wins per `correlationId` (v1 fold);
26
+ * - overlay merge against the checkpoint picks the greater `updatedAt`; on a
27
+ * tie the legacy-fold result wins (v1 positional semantics for same-ms
28
+ * external appends — pinned by tests/unit/state/pr-subscription-state.test.ts).
29
+ *
30
+ * Identity: the checkpoint is bound to its project root (`rootPath`). A copied
31
+ * `.swarm` reads as empty (never starts the wrong monitor) and rebinds on the
32
+ * next write; the displaced file is quarantined to a single
33
+ * `subscriptions.checkpoint.foreign.json` slot. Corrupt checkpoints are
34
+ * quarantined to `subscriptions.checkpoint.corrupt.json` and the store recovers
35
+ * from the legacy log when present.
36
+ *
37
+ * Concurrency: all mutations (subscribe, unsubscribe, update, sweep, audit,
38
+ * archive, migration, read-bootstrap) run under a single project-scoped
39
+ * `withEvidenceLock` on the unchanged v1 lock key, so v1 and v2 writers
40
+ * serialize across processes. Plain reads are lock-free; the one-time legacy
41
+ * read-bootstrap may acquire the lock (short timeout) to persist the first
42
+ * checkpoint so read-only installs also converge to bounded reads.
43
+ *
44
+ * Containment: every path is validated with `validateSwarmPath`, so nothing can
16
45
  * escape `.swarm/` (Invariant 4).
17
46
  */
18
47
  export declare const PR_SUBSCRIPTIONS_FILE = "pr-monitor/subscriptions.jsonl";
48
+ export declare const PR_SUBSCRIPTIONS_CHECKPOINT_FILE = "pr-monitor/subscriptions.checkpoint.json";
49
+ export declare const PR_SUBSCRIPTIONS_AUDIT_FILE = "pr-monitor/subscriptions.audit.jsonl";
50
+ /**
51
+ * Hard bounds for the bounded subscription store (issue #2042 Required 2).
52
+ * Mirrors the TRAJECTORY_LIMITS export pattern from src/prm/trajectory-store.ts.
53
+ */
54
+ export declare const PR_SUBSCRIPTION_LIMITS: {
55
+ /** Streaming read granularity — the legacy fold never materializes the file. */
56
+ readonly readChunkBytes: number;
57
+ /** Per-line byte bound in the legacy fold; oversize lines are skipped+counted. */
58
+ readonly maxRecordBytes: number;
59
+ /** Legacy-migration progress persistence granularity (crash-resume). */
60
+ readonly migrationChunkBytes: number;
61
+ /**
62
+ * Hard ceiling on legacy-log folding per store operation — the explicit
63
+ * finite migration work budget (issue #2042 Required 6). A legacy source
64
+ * larger than this is NEVER scanned (fail-safe refusal, loudly reported
65
+ * via health + the /swarm pr status footer with a repair hint, never
66
+ * silently dropped — the pending-delegations MAX_RECOVERY_LEDGER_BYTES
67
+ * precedent). Steady-state real files are ≤ a few MiB; anything near this
68
+ * ceiling already made every pre-fix operation multi-second.
69
+ */
70
+ readonly legacySourceMaxBytes: number;
71
+ /**
72
+ * Store-side live-subscription safety net when the caller omits
73
+ * `maxSubscriptions`. Production callers pass `config.max_subscriptions`
74
+ * (schema default 20, max 100 — src/config/schema.ts), so this only binds
75
+ * hypothetical callers that omit the field. Explicit values always win;
76
+ * `0` still disables the limit.
77
+ */
78
+ readonly defaultMaxActiveSubscriptions: 20;
79
+ /** Hard guard on the checkpoint records map (100 max actives + 60 terminals + slack). */
80
+ readonly maxCheckpointRecords: 512;
81
+ /** Pressure-reporting ceiling — active records are NEVER dropped for bytes. */
82
+ readonly maxCheckpointBytes: number;
83
+ /**
84
+ * Hard READ-side ceiling (availability guard): a checkpoint file larger than
85
+ * this is rejected as invalid (quarantine + legacy recovery) instead of
86
+ * being synchronously loaded. Only external tampering or a caller bypassing
87
+ * the config-bounded subscribe cap (schema range 1–100) could produce one;
88
+ * steady state is ~tens of records, far under the 256 KiB pressure line.
89
+ */
90
+ readonly checkpointHardReadBytes: number;
91
+ /** Terminal (removed/expired) record retention watermarks + age ceiling. */
92
+ readonly terminalRecordsHigh: 60;
93
+ readonly terminalRecordsLow: 30;
94
+ readonly terminalMaxAgeMs: number;
95
+ /**
96
+ * Audit-tail watermarks. The BYTE pair is the absolute storage bound: the
97
+ * rewrite fires once the file passes `auditMaxBytesLow` and exceeds
98
+ * `auditMaxBytesHigh`. The LINE pair is the retention shape applied during
99
+ * that rewrite (keep the newest lines within both Low watermarks).
100
+ */
101
+ readonly auditMaxLinesHigh: 500;
102
+ readonly auditMaxLinesLow: 250;
103
+ readonly auditMaxBytesHigh: number;
104
+ readonly auditMaxBytesLow: number;
105
+ /** Absorbed legacy archive is deleted once older than this. */
106
+ readonly legacyArchiveTtlMs: number;
107
+ /** Read-bootstrap lock timeout — short so contention cannot stall reads. */
108
+ readonly bootstrapLockTimeoutMs: 5000;
109
+ };
19
110
  /**
20
111
  * Register the lazy-start callback invoked after a successful subscription.
21
112
  * Called once during plugin init to wire the PR monitor worker lifecycle.
113
+ *
114
+ * Contract: the callback MUST NOT call store operations synchronously — it
115
+ * runs while the caller still holds the store's evidence lock, and
116
+ * proper-lockfile has no in-process reentrancy, so a re-entering callback
117
+ * would block until the lock times out.
22
118
  */
23
119
  export declare function setOnSubscriptionCreated(callback: (directory: string, record: PrSubscriptionRecord) => void): void;
24
120
  export type PrSubscriptionStatus = 'active' | 'removed' | 'expired';
25
121
  /**
26
- * A durable PR monitoring subscription record. Each append to the JSONL log
27
- * is a full snapshot; readers fold by correlationId (last-write-wins).
122
+ * A durable PR monitoring subscription record. The checkpoint stores the
123
+ * latest validated snapshot per `correlationId`.
28
124
  */
29
125
  export interface PrSubscriptionRecord {
30
126
  /** Composite key: `${sessionID}::${repoFullName}::${prNumber}`. */
@@ -69,39 +165,157 @@ export interface SubscribeInput {
69
165
  /** Max active subscriptions allowed (for limit enforcement). */
70
166
  maxSubscriptions?: number;
71
167
  }
168
+ export interface PrSubscriptionTerminalSummary {
169
+ removed: number;
170
+ expired: number;
171
+ lastTerminalAt: number | null;
172
+ }
173
+ export interface PrSubscriptionMigrationState {
174
+ /** Byte cursor of the incremental legacy fold (always a line boundary). */
175
+ scannedBytes: number;
176
+ /** Legacy size at the last scan (change detection). */
177
+ sourceBytes: number;
178
+ /**
179
+ * Legacy mtime at the last scan. Same-size recreation (a downgraded v1
180
+ * writer rewriting the log) is invisible to the size check alone, so the
181
+ * mtime is the second change-detection signal.
182
+ */
183
+ sourceMtimeMs: number;
184
+ /** Corrupt/oversize lines skipped during migration scanning. */
185
+ corruptLines: number;
186
+ done: boolean;
187
+ archived: boolean;
188
+ startedAt: number;
189
+ }
190
+ export interface PrSubscriptionMaintenance {
191
+ compactions: number;
192
+ droppedAuditTransitions: number;
193
+ /** All-time corrupt/oversize legacy lines (migration + re-folds). */
194
+ corruptLegacyRecords: number;
195
+ lastCompactedAt: number | null;
196
+ /** foreign-rebind + corrupt-quarantine recovery events. */
197
+ resets: number;
198
+ }
199
+ export interface PrSubscriptionCheckpoint {
200
+ schemaVersion: 1;
201
+ sequence: number;
202
+ rootPath: string;
203
+ updatedAt: number;
204
+ records: Record<string, PrSubscriptionRecord>;
205
+ terminalSummary: PrSubscriptionTerminalSummary;
206
+ migration: PrSubscriptionMigrationState | null;
207
+ maintenance: PrSubscriptionMaintenance;
208
+ }
209
+ /**
210
+ * Recovery source of a store view — mirrors the delegation-ledger
211
+ * recovery-source disclosure (issue #2042 Required 8).
212
+ */
213
+ export type PrSubscriptionRecoverySource = 'checkpoint' | 'checkpoint+legacy' | 'legacy-log' | 'empty' | 'foreign' | 'corrupt-recovered';
214
+ /** Bounded store health (issue #2042 Required 8). Counts and bytes only. */
215
+ export interface PrSubscriptionHealth {
216
+ schemaVersion: number;
217
+ sequence: number;
218
+ checkpointAgeMs: number | null;
219
+ checkpointBytes: number;
220
+ checkpointLimitBytes: number;
221
+ pressurePct: number;
222
+ activeCount: number;
223
+ removedCount: number;
224
+ expiredCount: number;
225
+ terminalSummary: PrSubscriptionTerminalSummary;
226
+ auditLines: number;
227
+ auditBytes: number;
228
+ auditLimitBytes: number;
229
+ compactions: number;
230
+ corruptLegacyRecords: number;
231
+ droppedAuditTransitions: number;
232
+ resets: number;
233
+ recoverySource: PrSubscriptionRecoverySource;
234
+ migration: {
235
+ done: boolean;
236
+ scannedBytes: number;
237
+ sourceBytes: number;
238
+ } | null;
239
+ legacyArchiveBytes: number;
240
+ /**
241
+ * True when a legacy source exceeds `legacySourceMaxBytes` and is being
242
+ * refused (never folded, never archived) — surfaced in the /swarm pr
243
+ * status footer with a repair hint.
244
+ */
245
+ legacyOverLimit: boolean;
246
+ }
72
247
  /**
73
248
  * Build the composite correlation key from session, repo, and PR number.
74
249
  */
75
250
  export declare function buildCorrelationId(sessionID: string, repoFullName: string, prNumber: number): string;
76
251
  /**
77
- * Subscribe to PR monitoring. Appends a new `active` subscription record. If an
252
+ * Project-root identity comparison for checkpoint replay (issue #2042
253
+ * Required 5). Both sides are `path.resolve`d; POSIX compares exactly, win32
254
+ * compares case-insensitively (drive-letter/segment case). No
255
+ * realpath/UNC/8.3 normalization — an unresolved mismatch fails SAFE
256
+ * (foreign → no monitor start, rebind on write, health-visible).
257
+ *
258
+ * This intentionally treats a MOVED project directory the same as a copied
259
+ * `.swarm`: the stored rootPath no longer resolves to the current root, so
260
+ * reads see nothing and the next write rebinds (the displaced checkpoint is
261
+ * preserved in `subscriptions.checkpoint.foreign.json`). Re-create
262
+ * subscriptions with `/swarm pr subscribe` after a move.
263
+ */
264
+ declare function sameProjectRoot(recorded: string, current: string): boolean;
265
+ interface LegacyFoldResult {
266
+ /** Latest record per correlationId in the folded region (later line wins). */
267
+ folded: Map<string, PrSubscriptionRecord>;
268
+ /** Byte offset after the last fully consumed line (always a line boundary). */
269
+ nextByte: number;
270
+ eof: boolean;
271
+ corruptLines: number;
272
+ }
273
+ /**
274
+ * Fold a byte region of the legacy JSONL log with bounded memory. Line
275
+ * scanning is byte-level (a 0x0A newline can never occur inside a UTF-8
276
+ * multibyte sequence), so complete lines decode exactly and `nextByte` is a
277
+ * byte-exact resume boundary. Records are parsed, schema-validated, and
278
+ * identity-checked (`correlationId` must compose from its parts); malformed,
279
+ * oversize, and identity-mismatched lines are skipped and COUNTED — never
280
+ * silently treated as removed or active (issue #2042 Required 5/6). A final
281
+ * unterminated line is processed leniently (v1 `split('\n')` semantics).
282
+ * `maxBytes` is a soft budget — the region extends to the end of the current
283
+ * line so the cursor always lands on a boundary.
284
+ */
285
+ declare function foldLegacyRegion(filePath: string, startByte: number, maxBytes: number): LegacyFoldResult;
286
+ /**
287
+ * Overlay-merge legacy fold results into a records view: greater `updatedAt`
288
+ * wins; tie → legacy-fold result wins (v1 positional semantics — pinned by
289
+ * tests/unit/state/pr-subscription-state.test.ts). Returns the number of
290
+ * records actually replaced/added (dirty detection).
291
+ */
292
+ declare function mergeFoldedRecords(view: Record<string, PrSubscriptionRecord>, overlay: Map<string, PrSubscriptionRecord>): number;
293
+ /**
294
+ * Subscribe to PR monitoring. Creates a new `active` subscription record. If an
78
295
  * active subscription with the same correlationId already exists, returns the
79
296
  * existing record (idempotent). Throws if the number of active subscriptions
80
- * exceeds `input.maxSubscriptions` (when provided).
81
- *
82
- * Runs a lazy stale sweep before the append (same pattern as
83
- * pending-delegations.ts).
297
+ * would exceed the limit — the explicit `maxSubscriptions` when provided, else
298
+ * the store-side safety net (`PR_SUBSCRIPTION_LIMITS.defaultMaxActiveSubscriptions`).
84
299
  */
85
300
  export declare function subscribe(directory: string, input: SubscribeInput): Promise<PrSubscriptionRecord>;
86
301
  /**
87
- * Unsubscribe from PR monitoring. Appends a new record with `status='removed'`
88
- * for the given correlationId. Correlation-key folding means the latest record
89
- * wins. Returns the folded record after the write, or null if no active
90
- * subscription was found.
302
+ * Unsubscribe from PR monitoring. Transitions the active record for the given
303
+ * correlationId to `status='removed'`. Returns the removed record, or null if
304
+ * no active subscription was found.
91
305
  */
92
306
  export declare function unsubscribe(directory: string, correlationId: string): Promise<PrSubscriptionRecord | null>;
93
307
  /**
94
- * List all active subscriptions. Lock-free read that folds the JSONL and
95
- * returns only records with `status='active'`.
308
+ * List all active subscriptions. Lock-free bounded read: checkpoint plus, while
309
+ * a legacy source is pending, its folded tail.
96
310
  */
97
311
  export declare function listActive(directory: string): Promise<PrSubscriptionRecord[]>;
98
312
  /**
99
- * Look up an active subscription for a specific PR. Lock-free read.
313
+ * Look up an active subscription for a specific PR. Lock-free bounded read.
100
314
  */
101
315
  export declare function lookupByPr(directory: string, repoFullName: string, prNumber: number): Promise<PrSubscriptionRecord | null>;
102
316
  /**
103
317
  * Update the snapshot for a given correlationId. Merges `updates` into the
104
- * existing active record and appends the new snapshot. Returns the merged
318
+ * existing active record and persists the new snapshot. Returns the merged
105
319
  * record, or null if no active subscription was found.
106
320
  */
107
321
  export declare function updateSnapshot(directory: string, correlationId: string, updates: Partial<PrSubscriptionRecord>): Promise<PrSubscriptionRecord | null>;
@@ -111,7 +325,9 @@ export declare function updateSnapshot(directory: string, correlationId: string,
111
325
  * (b) They have had no state change for `ttlDays` AND `hasUnaddressedEvents` is false.
112
326
  *
113
327
  * Subscriptions with `hasUnaddressedEvents === true` are NEVER swept unless the
114
- * PR is in the merged/closed set.
328
+ * PR is in the merged/closed set. Swept history is compacted by the bounded
329
+ * checkpoint/audit model (terminal records and audit lines are bounded; active
330
+ * records — including unaddressed-event actives — are never dropped).
115
331
  *
116
332
  * @param directory - Project root directory
117
333
  * @param ttlDays - Days of inactivity before considering a subscription stale
@@ -119,3 +335,18 @@ export declare function updateSnapshot(directory: string, correlationId: string,
119
335
  * @returns Number of subscriptions swept
120
336
  */
121
337
  export declare function sweepStale(directory: string, ttlDays: number, mergedPrs?: ReadonlySet<string>): Promise<number>;
338
+ /**
339
+ * Bounded store health (issue #2042 Required 8). Pure read — no bootstrap, no
340
+ * quarantine, never throws.
341
+ */
342
+ export declare function getPrSubscriptionHealth(directory: string): Promise<PrSubscriptionHealth>;
343
+ /**
344
+ * Dependency-injection seam for unit tests (repo convention — never
345
+ * mock.module). Restore in afterEach.
346
+ */
347
+ export declare const _internals: {
348
+ foldLegacyRegion: typeof foldLegacyRegion;
349
+ mergeFoldedRecords: typeof mergeFoldedRecords;
350
+ sameProjectRoot: typeof sameProjectRoot;
351
+ };
352
+ export {};
@@ -12,9 +12,9 @@ import {
12
12
  shouldRunOnStartup,
13
13
  writeBackupArtifact,
14
14
  writeDoctorArtifact
15
- } from "./index-hhv2pvab.js";
15
+ } from "./index-10zvxqra.js";
16
16
  import"./index-z6xqpmqg.js";
17
- import"./index-a58nmnmz.js";
17
+ import"./index-tnm9bb8b.js";
18
18
  import"./index-myt57pht.js";
19
19
  import"./index-zjygnfay.js";
20
20
  import"./index-bk5tah7q.js";
@@ -14,7 +14,7 @@ import {
14
14
  resolveWorktreeBaseDir,
15
15
  shortenWorktreePath,
16
16
  writeLaneProfileToDiskReal
17
- } from "./index-s6b8jgtn.js";
17
+ } from "./index-nkr634n6.js";
18
18
  import"./index-z6xqpmqg.js";
19
19
  import"./index-r3mvsbtq.js";
20
20
  import"./index-myt57pht.js";
@@ -4,14 +4,14 @@ import {
4
4
  authorizeCuration,
5
5
  buildConfigFingerprintInput,
6
6
  readCohortConfigFingerprint
7
- } from "./index-3ttktt56.js";
7
+ } from "./index-yve4e8fx.js";
8
8
  import"./index-rtry5xyf.js";
9
- import"./index-x3y6zhgj.js";
10
- import"./index-zppxpc3y.js";
11
- import"./index-td0jz8xe.js";
12
- import"./index-891g7hbf.js";
9
+ import"./index-3db7xza0.js";
10
+ import"./index-s0a4ewkb.js";
11
+ import"./index-c809a69b.js";
12
+ import"./index-vtdwkfbv.js";
13
13
  import"./index-ed5ykebp.js";
14
- import"./index-x8vw6ap1.js";
14
+ import"./index-ttqnhxxq.js";
15
15
  import"./index-7g4c7s5r.js";
16
16
  import"./index-bpmtbmy9.js";
17
17
  import"./index-zgwm4ryv.js";
@@ -1,60 +1,60 @@
1
1
  // @bun
2
2
  import {
3
3
  createCuratorLLMDelegate
4
- } from "./index-j4f8sz67.js";
5
- import"./index-h3zhb18p.js";
6
- import"./index-hhv2pvab.js";
7
- import"./index-0azn976d.js";
4
+ } from "./index-1tdsddab.js";
5
+ import"./index-3hdnfmhp.js";
6
+ import"./index-10zvxqra.js";
7
+ import"./index-dwh02jmv.js";
8
8
  import"./index-134d35c1.js";
9
9
  import"./index-nj6rmyeh.js";
10
- import"./index-4pjkdcgc.js";
11
- import"./index-1gzdnjg9.js";
10
+ import"./index-6yc06dx9.js";
11
+ import"./index-y64jrbch.js";
12
12
  import"./index-y8552snf.js";
13
- import"./index-5ad8xcv3.js";
13
+ import"./index-mddgkqg9.js";
14
14
  import"./index-70ha9e09.js";
15
15
  import"./index-c8s9a3zh.js";
16
16
  import"./index-9ss2m4rs.js";
17
17
  import"./index-vnn7qq8c.js";
18
- import"./index-meg33yyv.js";
19
- import"./index-vhbds89e.js";
20
- import"./index-yvepnbyd.js";
21
- import"./index-56ejcj07.js";
22
- import"./index-3ttktt56.js";
18
+ import"./index-wfxg3s7n.js";
19
+ import"./index-68w5jxv5.js";
20
+ import"./index-snnps1vm.js";
21
+ import"./index-qcz4xprd.js";
22
+ import"./index-yve4e8fx.js";
23
23
  import"./index-rtry5xyf.js";
24
- import"./index-3cegckkq.js";
24
+ import"./index-garsang6.js";
25
25
  import"./index-zsrtt42s.js";
26
- import"./index-02rbfrab.js";
27
- import"./index-s6b8jgtn.js";
28
- import"./index-2mqmvxac.js";
29
- import"./index-h06112sh.js";
30
- import"./index-ebshrg4x.js";
31
- import"./index-pk1gbqmq.js";
26
+ import"./index-wpstzk85.js";
27
+ import"./index-nkr634n6.js";
28
+ import"./index-7jnh1sgb.js";
29
+ import"./index-s70tmqn3.js";
30
+ import"./index-4g00jhbs.js";
31
+ import"./index-c6dfyzdh.js";
32
32
  import"./index-556ja8an.js";
33
33
  import"./index-b43rt5ph.js";
34
34
  import"./index-q7sjgr1y.js";
35
35
  import"./index-4fwbbad3.js";
36
- import"./index-bw55r5bz.js";
37
- import"./index-3bh4h6ve.js";
38
- import"./index-3fpqpyp6.js";
36
+ import"./index-hk4wa0v1.js";
37
+ import"./index-2mbs5q26.js";
38
+ import"./index-p4y7jefb.js";
39
39
  import"./index-gprxjmm7.js";
40
40
  import"./index-n832052r.js";
41
41
  import"./index-4cgee5vh.js";
42
42
  import"./index-z6xqpmqg.js";
43
43
  import"./index-r3mvsbtq.js";
44
- import"./index-5zp4c36c.js";
45
- import"./index-a58nmnmz.js";
44
+ import"./index-4y7g04py.js";
45
+ import"./index-tnm9bb8b.js";
46
46
  import"./index-myt57pht.js";
47
47
  import"./index-9e6fdz2h.js";
48
48
  import"./index-4rhhvd1a.js";
49
49
  import"./index-zjygnfay.js";
50
50
  import"./index-ae75rja9.js";
51
- import"./index-x3y6zhgj.js";
52
- import"./index-zppxpc3y.js";
51
+ import"./index-3db7xza0.js";
52
+ import"./index-s0a4ewkb.js";
53
53
  import"./index-bk5tah7q.js";
54
- import"./index-td0jz8xe.js";
55
- import"./index-891g7hbf.js";
54
+ import"./index-c809a69b.js";
55
+ import"./index-vtdwkfbv.js";
56
56
  import"./index-ed5ykebp.js";
57
- import"./index-x8vw6ap1.js";
57
+ import"./index-ttqnhxxq.js";
58
58
  import"./index-7g4c7s5r.js";
59
59
  import"./index-bpmtbmy9.js";
60
60
  import"./index-zgwm4ryv.js";
@@ -14,60 +14,60 @@ import {
14
14
  runCuratorInit,
15
15
  runCuratorPhase,
16
16
  writeCuratorSummary
17
- } from "./index-j4f8sz67.js";
18
- import"./index-h3zhb18p.js";
19
- import"./index-hhv2pvab.js";
20
- import"./index-0azn976d.js";
17
+ } from "./index-1tdsddab.js";
18
+ import"./index-3hdnfmhp.js";
19
+ import"./index-10zvxqra.js";
20
+ import"./index-dwh02jmv.js";
21
21
  import"./index-134d35c1.js";
22
22
  import"./index-nj6rmyeh.js";
23
- import"./index-4pjkdcgc.js";
24
- import"./index-1gzdnjg9.js";
23
+ import"./index-6yc06dx9.js";
24
+ import"./index-y64jrbch.js";
25
25
  import"./index-y8552snf.js";
26
- import"./index-5ad8xcv3.js";
26
+ import"./index-mddgkqg9.js";
27
27
  import"./index-70ha9e09.js";
28
28
  import"./index-c8s9a3zh.js";
29
29
  import"./index-9ss2m4rs.js";
30
30
  import"./index-vnn7qq8c.js";
31
- import"./index-meg33yyv.js";
32
- import"./index-vhbds89e.js";
33
- import"./index-yvepnbyd.js";
34
- import"./index-56ejcj07.js";
35
- import"./index-3ttktt56.js";
31
+ import"./index-wfxg3s7n.js";
32
+ import"./index-68w5jxv5.js";
33
+ import"./index-snnps1vm.js";
34
+ import"./index-qcz4xprd.js";
35
+ import"./index-yve4e8fx.js";
36
36
  import"./index-rtry5xyf.js";
37
- import"./index-3cegckkq.js";
37
+ import"./index-garsang6.js";
38
38
  import"./index-zsrtt42s.js";
39
- import"./index-02rbfrab.js";
40
- import"./index-s6b8jgtn.js";
41
- import"./index-2mqmvxac.js";
42
- import"./index-h06112sh.js";
43
- import"./index-ebshrg4x.js";
44
- import"./index-pk1gbqmq.js";
39
+ import"./index-wpstzk85.js";
40
+ import"./index-nkr634n6.js";
41
+ import"./index-7jnh1sgb.js";
42
+ import"./index-s70tmqn3.js";
43
+ import"./index-4g00jhbs.js";
44
+ import"./index-c6dfyzdh.js";
45
45
  import"./index-556ja8an.js";
46
46
  import"./index-b43rt5ph.js";
47
47
  import"./index-q7sjgr1y.js";
48
48
  import"./index-4fwbbad3.js";
49
- import"./index-bw55r5bz.js";
50
- import"./index-3bh4h6ve.js";
51
- import"./index-3fpqpyp6.js";
49
+ import"./index-hk4wa0v1.js";
50
+ import"./index-2mbs5q26.js";
51
+ import"./index-p4y7jefb.js";
52
52
  import"./index-gprxjmm7.js";
53
53
  import"./index-n832052r.js";
54
54
  import"./index-4cgee5vh.js";
55
55
  import"./index-z6xqpmqg.js";
56
56
  import"./index-r3mvsbtq.js";
57
- import"./index-5zp4c36c.js";
58
- import"./index-a58nmnmz.js";
57
+ import"./index-4y7g04py.js";
58
+ import"./index-tnm9bb8b.js";
59
59
  import"./index-myt57pht.js";
60
60
  import"./index-9e6fdz2h.js";
61
61
  import"./index-4rhhvd1a.js";
62
62
  import"./index-zjygnfay.js";
63
63
  import"./index-ae75rja9.js";
64
- import"./index-x3y6zhgj.js";
65
- import"./index-zppxpc3y.js";
64
+ import"./index-3db7xza0.js";
65
+ import"./index-s0a4ewkb.js";
66
66
  import"./index-bk5tah7q.js";
67
- import"./index-td0jz8xe.js";
68
- import"./index-891g7hbf.js";
67
+ import"./index-c809a69b.js";
68
+ import"./index-vtdwkfbv.js";
69
69
  import"./index-ed5ykebp.js";
70
- import"./index-x8vw6ap1.js";
70
+ import"./index-ttqnhxxq.js";
71
71
  import"./index-7g4c7s5r.js";
72
72
  import"./index-bpmtbmy9.js";
73
73
  import"./index-zgwm4ryv.js";
@@ -6,16 +6,16 @@ import {
6
6
  loadPlanJsonOnly,
7
7
  mergeDurableGateEntriesFromEvidence,
8
8
  readDurableGateEvidence
9
- } from "./index-0azn976d.js";
9
+ } from "./index-dwh02jmv.js";
10
10
  import"./index-134d35c1.js";
11
- import"./index-1gzdnjg9.js";
11
+ import"./index-y64jrbch.js";
12
12
  import"./index-y8552snf.js";
13
13
  import"./index-9ss2m4rs.js";
14
14
  import"./index-zsrtt42s.js";
15
- import"./index-02rbfrab.js";
16
- import"./index-s6b8jgtn.js";
17
- import"./index-ebshrg4x.js";
18
- import"./index-pk1gbqmq.js";
15
+ import"./index-wpstzk85.js";
16
+ import"./index-nkr634n6.js";
17
+ import"./index-4g00jhbs.js";
18
+ import"./index-c6dfyzdh.js";
19
19
  import"./index-556ja8an.js";
20
20
  import"./index-4fwbbad3.js";
21
21
  import"./index-gprxjmm7.js";
@@ -23,18 +23,18 @@ import"./index-n832052r.js";
23
23
  import"./index-4cgee5vh.js";
24
24
  import"./index-z6xqpmqg.js";
25
25
  import"./index-r3mvsbtq.js";
26
- import"./index-5zp4c36c.js";
27
- import"./index-a58nmnmz.js";
26
+ import"./index-4y7g04py.js";
27
+ import"./index-tnm9bb8b.js";
28
28
  import"./index-myt57pht.js";
29
29
  import"./index-9e6fdz2h.js";
30
30
  import"./index-4rhhvd1a.js";
31
31
  import"./index-zjygnfay.js";
32
- import"./index-zppxpc3y.js";
32
+ import"./index-s0a4ewkb.js";
33
33
  import"./index-bk5tah7q.js";
34
- import"./index-td0jz8xe.js";
35
- import"./index-891g7hbf.js";
34
+ import"./index-c809a69b.js";
35
+ import"./index-vtdwkfbv.js";
36
36
  import"./index-ed5ykebp.js";
37
- import"./index-x8vw6ap1.js";
37
+ import"./index-ttqnhxxq.js";
38
38
  import"./index-7g4c7s5r.js";
39
39
  import"./index-bpmtbmy9.js";
40
40
  import {