opencode-swarm 7.66.3 → 7.68.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/README.md +4 -0
- package/dist/background/event-bus.d.ts +1 -1
- package/dist/background/index.d.ts +2 -0
- package/dist/background/pr-event-subscribers.d.ts +46 -0
- package/dist/background/pr-monitor-worker.d.ts +154 -0
- package/dist/background/pr-subscriptions.d.ts +115 -0
- package/dist/cli/index.js +1886 -951
- package/dist/commands/index.d.ts +1 -0
- package/dist/commands/learning.d.ts +1 -0
- package/dist/commands/pr-monitor-status.d.ts +36 -0
- package/dist/commands/pr-subscribe.d.ts +33 -0
- package/dist/commands/pr-unsubscribe.d.ts +32 -0
- package/dist/commands/registry.d.ts +28 -0
- package/dist/config/evidence-schema.d.ts +214 -0
- package/dist/config/schema.d.ts +37 -0
- package/dist/git/pr.d.ts +80 -0
- package/dist/hooks/curator.d.ts +4 -1
- package/dist/hooks/skill-usage-log.d.ts +10 -0
- package/dist/index.js +5517 -3173
- package/dist/mutation/engine.d.ts +12 -1
- package/dist/services/learning-metrics.d.ts +63 -0
- package/dist/services/skill-changelog.d.ts +21 -0
- package/dist/services/skill-generator.d.ts +7 -1
- package/dist/services/skill-reviser.d.ts +59 -0
- package/dist/state.d.ts +25 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -38,6 +38,7 @@ Most AI coding tools let one model write code and ask that same model whether th
|
|
|
38
38
|
- 🔬 **External Skill Curation Pipeline** — Opt-in discovery, quarantine, evaluation, and promotion of external skill candidates from configured sources (disabled by default; enable via `external_skills.curation_enabled: true` in config). Includes 7 tools: `external_skill_discover`, `external_skill_list`, `external_skill_inspect`, `external_skill_promote`, `external_skill_reject`, `external_skill_delete`, `external_skill_revoke`. Candidates pass through a 3-gate validation pipeline before evaluation: **prompt injection scan** (12 regex patterns), **unsafe instruction scan** (25 patterns), and **provenance integrity check** (SHA-256, timestamp, URL, publisher, and hash verification).
|
|
39
39
|
- 🔄 **Phase completion gates** — completion-verify and drift verifier gates enforced before phase completion
|
|
40
40
|
- 🔁 **Resumable sessions** — all state saved to `.swarm/`; pick up any project any day
|
|
41
|
+
- 🖥️ **PR Monitor** — GitHub PR subscription and background polling via `gh` CLI; delivers real-time CI, review, and merge status updates via the AutomationEventBus (FR-001, opt-in via `pr_monitor.enabled: true`). Subscribe with `/swarm pr subscribe <pr-url|owner/repo#N|N>`; unsubscribe with `/swarm pr unsubscribe <pr-url|owner/repo#N|N>`; check status with `/swarm pr status`. Enable `auto_pr_feedback: true` in `pr_monitor` config to inject `[MODE: PR_FEEDBACK pr="URL"]` on CI failures and merge conflicts automatically.
|
|
41
42
|
- 🌐 **20 languages** — TypeScript, Python, Go, Rust, Java, Kotlin, C/C++, C#, Ruby, Swift, Dart, PHP, JavaScript, CSS, Bash, PowerShell, INI, Regex (extending: see [docs/adding-a-language.md](docs/adding-a-language.md))
|
|
42
43
|
- 🛡️ **Built-in security** — SAST, secrets scanning, dependency audit per task
|
|
43
44
|
- 🔒 **Scope enforcement** — Validates write targets against declared scope with cross-process persistence, TTL expiry, and scope-aware destructive command blocking. **Handles both single-string and array-based path arguments** (`files[]`, `paths[]`, `targetFiles[]`) to prevent scope bypass via multi-file tool calls.
|
|
@@ -1100,6 +1101,9 @@ Control how tool outputs are summarized for LLM context.
|
|
|
1100
1101
|
| `/swarm issue <issue-url\|owner/repo#N\|N> [--plan] [--trace]` | Ingest a GitHub issue for localization and resolution |
|
|
1101
1102
|
| `/swarm pr-review <pr-url\|owner/repo#N\|N> [--council] [instructions...]` | Structured deep PR review with parallel lanes, reviewer confirmation, and critic challenge |
|
|
1102
1103
|
| `/swarm pr-feedback [<pr-url\|owner/repo#N\|N>] [instructions...]` | Ingest and close known PR feedback (review comments, CI failures, conflicts) without a fresh review |
|
|
1104
|
+
| `/swarm pr subscribe <pr-url\|owner/repo#N\|N>` | Subscribe current session to PR monitoring (session-scoped); requires `pr_monitor.enabled: true` |
|
|
1105
|
+
| `/swarm pr unsubscribe <pr-url\|owner/repo#N\|N>` | Remove session's subscription to a PR |
|
|
1106
|
+
| `/swarm pr status` | List active PR subscriptions for current session with relative timestamps |
|
|
1103
1107
|
| `/swarm deep-dive <scope> [--profile <name>] [--max-explorers <n>]` | Read-only codebase audit with parallel explorers, dual reviewers, and critic challenge |
|
|
1104
1108
|
| `/swarm design-docs <description> [--out <dir>] [--lang <name>] [--update]` | Generate or sync language-agnostic design docs (requires `design_docs.enabled`) |
|
|
1105
1109
|
| `/swarm dark-matter` | Detect hidden file couplings from co-change history |
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* Events flow through the system without external dependencies.
|
|
6
6
|
*/
|
|
7
7
|
/** Automation event types */
|
|
8
|
-
export type AutomationEventType = 'queue.item.enqueued' | 'queue.item.dequeued' | 'queue.item.completed' | 'queue.item.failed' | 'queue.item.retry scheduled' | 'worker.started' | 'worker.stopped' | 'worker.error' | 'circuit.breaker.opened' | 'circuit.breaker.half-open' | 'circuit.breaker.closed' | 'loop.protection.triggered' | 'automation.started' | 'automation.stopped' | 'preflight.requested' | 'preflight.triggered' | 'preflight.skipped' | 'preflight.completed' | 'phase.boundary.detected' | 'phase.status.checked' | 'task.completed' | 'evidence.summary.generated' | 'evidence.summary.error' | 'curator.init.completed' | 'curator.init.llm_completed' | 'curator.init.llm_fallback' | 'curator.phase.completed' | 'curator.phase.llm_completed' | 'curator.phase.llm_fallback' | 'curator.drift.completed' | 'curator.docdrift.completed' | 'curator.error';
|
|
8
|
+
export type AutomationEventType = 'queue.item.enqueued' | 'queue.item.dequeued' | 'queue.item.completed' | 'queue.item.failed' | 'queue.item.retry scheduled' | 'worker.started' | 'worker.stopped' | 'worker.error' | 'circuit.breaker.opened' | 'circuit.breaker.half-open' | 'circuit.breaker.closed' | 'loop.protection.triggered' | 'automation.started' | 'automation.stopped' | 'preflight.requested' | 'preflight.triggered' | 'preflight.skipped' | 'preflight.completed' | 'phase.boundary.detected' | 'phase.status.checked' | 'task.completed' | 'evidence.summary.generated' | 'evidence.summary.error' | 'curator.init.completed' | 'curator.init.llm_completed' | 'curator.init.llm_fallback' | 'curator.phase.completed' | 'curator.phase.llm_completed' | 'curator.phase.llm_fallback' | 'curator.drift.completed' | 'curator.docdrift.completed' | 'curator.error' | 'pr.subscribed' | 'pr.unsubscribed' | 'pr.status.updated' | 'pr.ci.failed' | 'pr.ci.passed' | 'pr.new.comment' | 'pr.merge.conflict' | 'pr.merge.conflict_resolved' | 'pr.merged' | 'pr.closed' | 'pr.review.approved' | 'pr.review.changes_requested' | 'pr.subscription.expired' | 'pr.error';
|
|
9
9
|
/** Base automation event */
|
|
10
10
|
export interface AutomationEvent<T = unknown> {
|
|
11
11
|
type: AutomationEventType;
|
|
@@ -16,6 +16,8 @@ export { type AutomationEvent, AutomationEventBus, type AutomationEventType, } f
|
|
|
16
16
|
export { createEvidenceSummaryIntegration, type EvidenceSummaryIntegrationConfig, type EvidenceSummaryTriggerEvent, type EvidenceSummaryTriggerPayload, } from './evidence-summary-integration';
|
|
17
17
|
export { type AutomationFrameworkConfig, BackgroundAutomationManager, createAutomationManager, } from './manager';
|
|
18
18
|
export { PlanSyncWorker, type PlanSyncWorkerOptions, type PlanSyncWorkerStatus, } from './plan-sync-worker';
|
|
19
|
+
export { type PrEventSubscriberOptions, registerPrEventSubscribers, } from './pr-event-subscribers';
|
|
20
|
+
export { PrMonitorWorker, type PrMonitorWorkerOptions, type PrMonitorWorkerStatus, } from './pr-monitor-worker';
|
|
19
21
|
export { AutomationQueue, type QueueItem, type QueuePriority, type RetryMetadata, } from './queue';
|
|
20
22
|
export { AutomationStatusArtifact, type AutomationStatusSnapshot, } from './status-artifact';
|
|
21
23
|
export { type PhaseBoundaryResult, PhaseBoundaryTrigger, type PreflightHandler, type PreflightRequest, type PreflightRequestPayload, type PreflightTriggerConfig, type PreflightTriggerEventType, PreflightTriggerManager, } from './trigger';
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PR Event Bus Subscribers — Advisory notification delivery.
|
|
3
|
+
*
|
|
4
|
+
* Subscribes to PR events on the global event bus and delivers structured
|
|
5
|
+
* advisory messages to ALL active sessions that are subscribed to the
|
|
6
|
+
* relevant PR. Each event type is gated by a config flag from PrMonitorConfig.
|
|
7
|
+
*
|
|
8
|
+
* Fail-open: errors in delivery never crash the event bus.
|
|
9
|
+
* Dedup: advisories are deduped per session per PR+event type.
|
|
10
|
+
*/
|
|
11
|
+
import type { PrMonitorConfig } from '../config/schema';
|
|
12
|
+
import { getAgentSession } from '../state';
|
|
13
|
+
import { log } from '../utils';
|
|
14
|
+
import { getGlobalEventBus } from './event-bus';
|
|
15
|
+
import { listActive } from './pr-subscriptions';
|
|
16
|
+
export interface PrEventSubscriberOptions {
|
|
17
|
+
directory: string;
|
|
18
|
+
config: PrMonitorConfig;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* DI seam for testability. Exposes internal functions that are replaced
|
|
22
|
+
* in tests via the _internals object.
|
|
23
|
+
*/
|
|
24
|
+
export declare const _internals: {
|
|
25
|
+
handlePrEvent: typeof handlePrEvent;
|
|
26
|
+
getGlobalEventBus: typeof getGlobalEventBus;
|
|
27
|
+
listActive: typeof listActive;
|
|
28
|
+
getAgentSession: typeof getAgentSession;
|
|
29
|
+
log: typeof log;
|
|
30
|
+
};
|
|
31
|
+
/**
|
|
32
|
+
* Register subscribers on the global event bus for the three gated PR event
|
|
33
|
+
* types. Returns a cleanup function that unsubscribes all listeners.
|
|
34
|
+
*
|
|
35
|
+
* Skips event types whose config flag is disabled (false).
|
|
36
|
+
*/
|
|
37
|
+
export declare function registerPrEventSubscribers(options: PrEventSubscriberOptions): () => void;
|
|
38
|
+
/**
|
|
39
|
+
* Handle a single PR event: look up active subscriptions matching the event's
|
|
40
|
+
* repo+PR, format an advisory, and push it to every matching session.
|
|
41
|
+
*/
|
|
42
|
+
declare function handlePrEvent(event: {
|
|
43
|
+
type: string;
|
|
44
|
+
payload: unknown;
|
|
45
|
+
}, directory: string, config: PrMonitorConfig): Promise<void>;
|
|
46
|
+
export {};
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PR Monitor Worker
|
|
3
|
+
*
|
|
4
|
+
* Background polling worker that periodically checks subscribed PRs for status
|
|
5
|
+
* changes (CI, comments, merge conflicts, merge/close events) and publishes
|
|
6
|
+
* automation events. Follows the PlanSyncWorker standalone class pattern with
|
|
7
|
+
* start/stop/dispose lifecycle and bounded, fail-open operation.
|
|
8
|
+
*/
|
|
9
|
+
import type { PrMonitorConfig } from '../config/schema';
|
|
10
|
+
import { getMergeState, getPRComments, getPRReviewState, getPRStatus } from '../git/pr';
|
|
11
|
+
import { type AutomationEventType, getGlobalEventBus } from './event-bus';
|
|
12
|
+
import { listActive, sweepStale, unsubscribe, updateSnapshot } from './pr-subscriptions';
|
|
13
|
+
/** Configuration options for PrMonitorWorker construction. */
|
|
14
|
+
export interface PrMonitorWorkerOptions {
|
|
15
|
+
/** Project root directory (parent of .swarm/). */
|
|
16
|
+
directory: string;
|
|
17
|
+
/** Parsed pr_monitor config from schema. */
|
|
18
|
+
config: PrMonitorConfig;
|
|
19
|
+
/** Optional callback for emitted events (in addition to event bus). */
|
|
20
|
+
onEvent?: (event: AutomationEvent<unknown>) => void;
|
|
21
|
+
}
|
|
22
|
+
/** Worker status machine states. */
|
|
23
|
+
export type PrMonitorWorkerStatus = 'stopped' | 'starting' | 'running' | 'stopping';
|
|
24
|
+
/** Typed wrapper around AutomationEvent for PR monitor payloads. */
|
|
25
|
+
export interface AutomationEvent<T = unknown> {
|
|
26
|
+
type: AutomationEventType;
|
|
27
|
+
timestamp: number;
|
|
28
|
+
payload: T;
|
|
29
|
+
source: string;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* PR Monitor Worker.
|
|
33
|
+
*
|
|
34
|
+
* Standalone class that polls GitHub PRs for status changes using the gh CLI
|
|
35
|
+
* wrappers. Publishes typed automation events for CI failures, new comments,
|
|
36
|
+
* merge conflicts, merge/close transitions, and head-branch updates.
|
|
37
|
+
*
|
|
38
|
+
* Lifecycle: start() → running → stop() → stopped → dispose().
|
|
39
|
+
* Fail-open: construction and poll-cycle errors are logged, never thrown.
|
|
40
|
+
*/
|
|
41
|
+
export declare class PrMonitorWorker {
|
|
42
|
+
private readonly directory;
|
|
43
|
+
private readonly config;
|
|
44
|
+
private readonly onEvent?;
|
|
45
|
+
private status;
|
|
46
|
+
private pollTimer;
|
|
47
|
+
private disposed;
|
|
48
|
+
/** In-memory circuit-breaker state per PR correlationId. */
|
|
49
|
+
private readonly circuitBreakerMap;
|
|
50
|
+
/** In-memory review decision per PR correlationId (not persisted). */
|
|
51
|
+
private readonly reviewStateMap;
|
|
52
|
+
/** Accumulates merged/closed PR keys during the current poll cycle for sweep cleanup. */
|
|
53
|
+
private mergedOrClosedKeys;
|
|
54
|
+
constructor(options: PrMonitorWorkerOptions);
|
|
55
|
+
/**
|
|
56
|
+
* Start the polling worker. Fail-open: logs and returns on bad state
|
|
57
|
+
* instead of throwing.
|
|
58
|
+
*/
|
|
59
|
+
start(): void;
|
|
60
|
+
/**
|
|
61
|
+
* Stop the polling worker. Clears the interval timer but does not
|
|
62
|
+
* interrupt an in-flight poll cycle — it will complete and the result
|
|
63
|
+
* is discarded.
|
|
64
|
+
*/
|
|
65
|
+
stop(): void;
|
|
66
|
+
/**
|
|
67
|
+
* Stop and permanently prevent restart.
|
|
68
|
+
*/
|
|
69
|
+
dispose(): void;
|
|
70
|
+
/**
|
|
71
|
+
* Get current worker status.
|
|
72
|
+
*/
|
|
73
|
+
getStatus(): PrMonitorWorkerStatus;
|
|
74
|
+
/**
|
|
75
|
+
* Check if worker is currently running.
|
|
76
|
+
*/
|
|
77
|
+
isRunning(): boolean;
|
|
78
|
+
/**
|
|
79
|
+
* Public entry point for a single poll cycle. Checks only disposed
|
|
80
|
+
* state (not running status) so it can be invoked directly in tests
|
|
81
|
+
* or manual polling scenarios.
|
|
82
|
+
*/
|
|
83
|
+
pollCycle(): Promise<void>;
|
|
84
|
+
/**
|
|
85
|
+
* Internal poll cycle implementation: fetch subscriptions, detect
|
|
86
|
+
* changes, publish events, update snapshots, run sweep.
|
|
87
|
+
*/
|
|
88
|
+
private executePollCycle;
|
|
89
|
+
/**
|
|
90
|
+
* Process subscriptions with a concurrency limit using a sliding window.
|
|
91
|
+
*/
|
|
92
|
+
private processWithConcurrency;
|
|
93
|
+
/**
|
|
94
|
+
* Wrap a single PR poll with a configurable timeout.
|
|
95
|
+
* If the poll exceeds poll_timeout_ms, the timeout error is
|
|
96
|
+
* delegated to handlePollError (circuit-breaker accounting) and
|
|
97
|
+
* the method resolves — it never rethrows.
|
|
98
|
+
*/
|
|
99
|
+
private pollWithTimeout;
|
|
100
|
+
/**
|
|
101
|
+
* Poll a single PR subscription: fetch current state, detect changes,
|
|
102
|
+
* publish events, and update the snapshot. Handles circuit-breaking.
|
|
103
|
+
*/
|
|
104
|
+
private pollSinglePr;
|
|
105
|
+
/**
|
|
106
|
+
* Pure computation: compare current fetch results against the subscription
|
|
107
|
+
* snapshot and return all events/mutations to apply. No side effects.
|
|
108
|
+
*/
|
|
109
|
+
private computeChanges;
|
|
110
|
+
/**
|
|
111
|
+
* Pure computation: detect CI transitions and push events into the array.
|
|
112
|
+
*/
|
|
113
|
+
private computeCIEvents;
|
|
114
|
+
/**
|
|
115
|
+
* Apply computed changes: emit events, update merged/closed tracking,
|
|
116
|
+
* unsubscribe, and update snapshot. Checks isTimedOut before each
|
|
117
|
+
* state mutation to prevent stale writes after timeout.
|
|
118
|
+
*/
|
|
119
|
+
private applyChanges;
|
|
120
|
+
/**
|
|
121
|
+
* Handle a poll error for a single PR: increment error count, apply
|
|
122
|
+
* circuit-breaker suspension with exponential backoff.
|
|
123
|
+
*/
|
|
124
|
+
private handlePollError;
|
|
125
|
+
/**
|
|
126
|
+
* Publish an event to the global event bus and optional callback.
|
|
127
|
+
*/
|
|
128
|
+
private emitEvent;
|
|
129
|
+
/**
|
|
130
|
+
* Run stale subscription sweep if cleanup_ttl_days > 0.
|
|
131
|
+
* Passes any merged/closed PR keys observed during the poll cycle
|
|
132
|
+
* so that sweepStale can remove subscriptions for those PRs.
|
|
133
|
+
*/
|
|
134
|
+
private runSweep;
|
|
135
|
+
/**
|
|
136
|
+
* Serialize statusCheckRollup to a stable string for snapshot comparison.
|
|
137
|
+
*/
|
|
138
|
+
private serializeChecks;
|
|
139
|
+
/**
|
|
140
|
+
* Parse a serialized check set back into an array.
|
|
141
|
+
*/
|
|
142
|
+
private parseCheckSet;
|
|
143
|
+
}
|
|
144
|
+
export declare const _internals: {
|
|
145
|
+
getPRStatus: typeof getPRStatus;
|
|
146
|
+
getPRComments: typeof getPRComments;
|
|
147
|
+
getMergeState: typeof getMergeState;
|
|
148
|
+
getPRReviewState: typeof getPRReviewState;
|
|
149
|
+
listActive: typeof listActive;
|
|
150
|
+
updateSnapshot: typeof updateSnapshot;
|
|
151
|
+
unsubscribe: typeof unsubscribe;
|
|
152
|
+
sweepStale: typeof sweepStale;
|
|
153
|
+
getGlobalEventBus: typeof getGlobalEventBus;
|
|
154
|
+
};
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Durable PR monitoring subscription store.
|
|
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.
|
|
9
|
+
*
|
|
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).
|
|
14
|
+
*
|
|
15
|
+
* Containment: the path is validated with `validateSwarmPath`, so it can never
|
|
16
|
+
* escape `.swarm/` (Invariant 4).
|
|
17
|
+
*/
|
|
18
|
+
export declare const PR_SUBSCRIPTIONS_FILE = "pr-monitor/subscriptions.jsonl";
|
|
19
|
+
/**
|
|
20
|
+
* Register the lazy-start callback invoked after a successful subscription.
|
|
21
|
+
* Called once during plugin init to wire the PR monitor worker lifecycle.
|
|
22
|
+
*/
|
|
23
|
+
export declare function setOnSubscriptionCreated(callback: (directory: string, record: PrSubscriptionRecord) => void): void;
|
|
24
|
+
export type PrSubscriptionStatus = 'active' | 'removed' | 'expired';
|
|
25
|
+
/**
|
|
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).
|
|
28
|
+
*/
|
|
29
|
+
export interface PrSubscriptionRecord {
|
|
30
|
+
/** Composite key: `${sessionID}::${repoFullName}::${prNumber}`. */
|
|
31
|
+
correlationId: string;
|
|
32
|
+
sessionID: string;
|
|
33
|
+
prNumber: number;
|
|
34
|
+
/** e.g. "owner/repo". */
|
|
35
|
+
repoFullName: string;
|
|
36
|
+
prUrl: string;
|
|
37
|
+
headRefOid?: string;
|
|
38
|
+
/** Epoch ms — last time the poller checked this PR. */
|
|
39
|
+
lastCheckedAt: number;
|
|
40
|
+
lastCommentId?: string;
|
|
41
|
+
/** JSON stringified array of check names + conclusions. */
|
|
42
|
+
lastCheckRunSet?: string;
|
|
43
|
+
mergeableState?: string;
|
|
44
|
+
isWatching: boolean;
|
|
45
|
+
/** Guard for cleanup sweep — subscriptions with unaddressed events are retained. */
|
|
46
|
+
hasUnaddressedEvents: boolean;
|
|
47
|
+
status: PrSubscriptionStatus;
|
|
48
|
+
/** Epoch ms — when the subscription was first created. */
|
|
49
|
+
createdAt: number;
|
|
50
|
+
/** Epoch ms — when this snapshot was written. */
|
|
51
|
+
updatedAt: number;
|
|
52
|
+
errorCount: number;
|
|
53
|
+
/** Per-PR poll-interval override (FR-017). */
|
|
54
|
+
customPollIntervalSeconds?: number;
|
|
55
|
+
customFailureThreshold?: number;
|
|
56
|
+
customCooldownSeconds?: number;
|
|
57
|
+
}
|
|
58
|
+
export interface SubscribeInput {
|
|
59
|
+
sessionID: string;
|
|
60
|
+
prNumber: number;
|
|
61
|
+
repoFullName: string;
|
|
62
|
+
prUrl: string;
|
|
63
|
+
/** Max active subscriptions allowed (for limit enforcement). */
|
|
64
|
+
maxSubscriptions?: number;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Build the composite correlation key from session, repo, and PR number.
|
|
68
|
+
*/
|
|
69
|
+
export declare function buildCorrelationId(sessionID: string, repoFullName: string, prNumber: number): string;
|
|
70
|
+
/**
|
|
71
|
+
* Subscribe to PR monitoring. Appends a new `active` subscription record. If an
|
|
72
|
+
* active subscription with the same correlationId already exists, returns the
|
|
73
|
+
* existing record (idempotent). Throws if the number of active subscriptions
|
|
74
|
+
* exceeds `input.maxSubscriptions` (when provided).
|
|
75
|
+
*
|
|
76
|
+
* Runs a lazy stale sweep before the append (same pattern as
|
|
77
|
+
* pending-delegations.ts).
|
|
78
|
+
*/
|
|
79
|
+
export declare function subscribe(directory: string, input: SubscribeInput): Promise<PrSubscriptionRecord>;
|
|
80
|
+
/**
|
|
81
|
+
* Unsubscribe from PR monitoring. Appends a new record with `status='removed'`
|
|
82
|
+
* for the given correlationId. Correlation-key folding means the latest record
|
|
83
|
+
* wins. Returns the folded record after the write, or null if no active
|
|
84
|
+
* subscription was found.
|
|
85
|
+
*/
|
|
86
|
+
export declare function unsubscribe(directory: string, correlationId: string): Promise<PrSubscriptionRecord | null>;
|
|
87
|
+
/**
|
|
88
|
+
* List all active subscriptions. Lock-free read that folds the JSONL and
|
|
89
|
+
* returns only records with `status='active'`.
|
|
90
|
+
*/
|
|
91
|
+
export declare function listActive(directory: string): Promise<PrSubscriptionRecord[]>;
|
|
92
|
+
/**
|
|
93
|
+
* Look up an active subscription for a specific PR. Lock-free read.
|
|
94
|
+
*/
|
|
95
|
+
export declare function lookupByPr(directory: string, repoFullName: string, prNumber: number): Promise<PrSubscriptionRecord | null>;
|
|
96
|
+
/**
|
|
97
|
+
* Update the snapshot for a given correlationId. Merges `updates` into the
|
|
98
|
+
* existing active record and appends the new snapshot. Returns the merged
|
|
99
|
+
* record, or null if no active subscription was found.
|
|
100
|
+
*/
|
|
101
|
+
export declare function updateSnapshot(directory: string, correlationId: string, updates: Partial<PrSubscriptionRecord>): Promise<PrSubscriptionRecord | null>;
|
|
102
|
+
/**
|
|
103
|
+
* Sweep stale subscriptions. Marks subscriptions as `expired` when:
|
|
104
|
+
* (a) They are `active` AND appear in the `mergedPrs` set (PR was merged/closed), OR
|
|
105
|
+
* (b) They have had no state change for `ttlDays` AND `hasUnaddressedEvents` is false.
|
|
106
|
+
*
|
|
107
|
+
* Subscriptions with `hasUnaddressedEvents === true` are NEVER swept unless the
|
|
108
|
+
* PR is in the merged/closed set.
|
|
109
|
+
*
|
|
110
|
+
* @param directory - Project root directory
|
|
111
|
+
* @param ttlDays - Days of inactivity before considering a subscription stale
|
|
112
|
+
* @param mergedPrs - Set of "repoFullName::prNumber" strings for merged/closed PRs
|
|
113
|
+
* @returns Number of subscriptions swept
|
|
114
|
+
*/
|
|
115
|
+
export declare function sweepStale(directory: string, ttlDays: number, mergedPrs?: ReadonlySet<string>): Promise<number>;
|