opencode-swarm 7.83.0 → 7.85.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/.opencode/skills/codebase-review-swarm/references/review-protocol-v8.2.md +4 -0
- package/.opencode/skills/council/SKILL.md +6 -1
- package/.opencode/skills/deep-dive/SKILL.md +2 -0
- package/.opencode/skills/deep-research/SKILL.md +6 -0
- package/.opencode/skills/swarm-pr-feedback/SKILL.md +6 -0
- package/.opencode/skills/swarm-pr-review/SKILL.md +4 -0
- package/README.md +3 -1
- package/dist/background/lane-output-store.d.ts +72 -0
- package/dist/background/pending-delegations.d.ts +6 -0
- package/dist/cli/capability-probe-jevmgwmf.js +18 -0
- package/dist/cli/config-doctor-zejarrr6.js +35 -0
- package/dist/cli/dispatch-k86d928w.js +477 -0
- package/dist/cli/evidence-summary-service-g2znnd33.js +320 -0
- package/dist/cli/explorer-gz70sm9b.js +16 -0
- package/dist/cli/gate-evidence-y8zn7fe2.js +29 -0
- package/dist/cli/guardrail-explain-w4txg349.js +30 -0
- package/dist/cli/guardrail-log-80116wmz.js +15 -0
- package/dist/cli/index-0sxvwjt0.js +1241 -0
- package/dist/cli/index-293f68mj.js +13538 -0
- package/dist/cli/index-5cb86007.js +110 -0
- package/dist/cli/index-a76rekgs.js +67 -0
- package/dist/cli/index-b9v501fr.js +371 -0
- package/dist/cli/index-bcp79s17.js +1673 -0
- package/dist/cli/index-ckntc5gf.js +91 -0
- package/dist/cli/index-d9fbxaqd.js +2314 -0
- package/dist/cli/index-e7h9bb6v.js +233 -0
- package/dist/cli/index-e8pk68cc.js +540 -0
- package/dist/cli/index-eb85wtx9.js +242 -0
- package/dist/cli/index-f8r50m3h.js +14505 -0
- package/dist/cli/index-fjwwrwr5.js +37 -0
- package/dist/cli/index-hw9b2xng.js +2046 -0
- package/dist/cli/index-hz59hg4h.js +452 -0
- package/dist/cli/index-jtqkh8jf.js +119 -0
- package/dist/cli/index-p0arc26j.js +28 -0
- package/dist/cli/index-p0ye10nd.js +222 -0
- package/dist/cli/index-qqabjns2.js +412 -0
- package/dist/cli/index-red8fm8p.js +2914 -0
- package/dist/cli/index-vq2321gg.js +2391 -0
- package/dist/cli/index-x7qck34v.js +583 -0
- package/dist/cli/index-yhqt45de.js +29027 -0
- package/dist/cli/index-yhsmmv2z.js +339 -0
- package/dist/cli/index-yx44zd0p.js +40 -0
- package/dist/cli/index-zfsbaaqh.js +29 -0
- package/dist/cli/index.js +73 -69708
- package/dist/cli/knowledge-store-n4x6zyk7.js +73 -0
- package/dist/cli/pending-delegations-rd40tv9s.js +261 -0
- package/dist/cli/pr-subscriptions-y1nn36e5.js +33 -0
- package/dist/cli/schema-8d32b2v6.js +168 -0
- package/dist/cli/skill-generator-a5ehggyg.js +55 -0
- package/dist/cli/task-envelope-qn0qtnh0.js +90 -0
- package/dist/cli/telemetry-9bbyxrvn.js +20 -0
- package/dist/cli/workspace-snapshot-w58jr2ga.js +90 -0
- package/dist/commands/guardrail-explain.d.ts +1 -0
- package/dist/commands/guardrail-log.d.ts +1 -0
- package/dist/commands/index.d.ts +2 -0
- package/dist/commands/registry.d.ts +14 -0
- package/dist/hooks/guardrails/audit-log.d.ts +114 -0
- package/dist/index.js +4005 -2432
- package/dist/services/diagnose-service.d.ts +5 -0
- package/dist/services/guardrail-explain-service.d.ts +42 -0
- package/dist/services/guardrail-log-service.d.ts +10 -0
- package/dist/tools/dispatch-lanes.d.ts +14 -3
- package/dist/tools/index.d.ts +1 -0
- package/dist/tools/manifest.d.ts +1 -0
- package/dist/tools/retrieve-lane-output.d.ts +2 -0
- package/dist/tools/tool-metadata.d.ts +4 -0
- package/package.json +2 -2
|
@@ -0,0 +1,242 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
import {
|
|
3
|
+
validateSwarmPath
|
|
4
|
+
} from "./index-ckntc5gf.js";
|
|
5
|
+
import {
|
|
6
|
+
log
|
|
7
|
+
} from "./index-yx44zd0p.js";
|
|
8
|
+
import {
|
|
9
|
+
withEvidenceLock
|
|
10
|
+
} from "./index-bcp79s17.js";
|
|
11
|
+
import {
|
|
12
|
+
exports_external
|
|
13
|
+
} from "./index-293f68mj.js";
|
|
14
|
+
|
|
15
|
+
// src/background/pr-subscriptions.ts
|
|
16
|
+
import * as fs from "fs";
|
|
17
|
+
import * as path from "path";
|
|
18
|
+
var PR_SUBSCRIPTIONS_FILE = "pr-monitor/subscriptions.jsonl";
|
|
19
|
+
var STORE_LOCK_AGENT = "pr-monitor";
|
|
20
|
+
var STORE_LOCK_TASK = "pr-subscriptions";
|
|
21
|
+
var onSubscriptionCreated = null;
|
|
22
|
+
function setOnSubscriptionCreated(callback) {
|
|
23
|
+
onSubscriptionCreated = callback;
|
|
24
|
+
}
|
|
25
|
+
var RecordSchema = exports_external.object({
|
|
26
|
+
correlationId: exports_external.string().min(1),
|
|
27
|
+
sessionID: exports_external.string().min(1),
|
|
28
|
+
prNumber: exports_external.number().int().positive(),
|
|
29
|
+
repoFullName: exports_external.string().regex(/^[^/]+\/[^/]+$/, "Must be owner/repo format"),
|
|
30
|
+
prUrl: exports_external.string().min(1).regex(/^https:\/\/github\.com\/[^/]+\/[^/]+\/pull\/\d+$/, "Must be a valid GitHub PR URL"),
|
|
31
|
+
headRefOid: exports_external.string().optional(),
|
|
32
|
+
lastCheckedAt: exports_external.number(),
|
|
33
|
+
lastCommentId: exports_external.string().optional(),
|
|
34
|
+
lastCheckRunSet: exports_external.string().optional(),
|
|
35
|
+
mergeableState: exports_external.string().optional(),
|
|
36
|
+
isWatching: exports_external.boolean(),
|
|
37
|
+
hasUnaddressedEvents: exports_external.boolean(),
|
|
38
|
+
status: exports_external.enum(["active", "removed", "expired"]),
|
|
39
|
+
createdAt: exports_external.number(),
|
|
40
|
+
updatedAt: exports_external.number(),
|
|
41
|
+
errorCount: exports_external.number().int().min(0),
|
|
42
|
+
customPollIntervalSeconds: exports_external.number().int().positive().optional(),
|
|
43
|
+
customFailureThreshold: exports_external.number().int().min(0).optional(),
|
|
44
|
+
customCooldownSeconds: exports_external.number().int().min(0).optional()
|
|
45
|
+
}).strict();
|
|
46
|
+
function storePath(directory) {
|
|
47
|
+
return validateSwarmPath(directory, PR_SUBSCRIPTIONS_FILE);
|
|
48
|
+
}
|
|
49
|
+
function ensureSwarmDir(directory) {
|
|
50
|
+
fs.mkdirSync(path.resolve(directory, ".swarm", "pr-monitor"), {
|
|
51
|
+
recursive: true
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
function buildCorrelationId(sessionID, repoFullName, prNumber) {
|
|
55
|
+
return `${sessionID}::${repoFullName}::${prNumber}`;
|
|
56
|
+
}
|
|
57
|
+
function readAllRecords(directory) {
|
|
58
|
+
let raw;
|
|
59
|
+
try {
|
|
60
|
+
raw = fs.readFileSync(storePath(directory), "utf-8");
|
|
61
|
+
} catch (err) {
|
|
62
|
+
if (err.code === "ENOENT")
|
|
63
|
+
return [];
|
|
64
|
+
log(`[pr-monitor] readAllRecords failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
65
|
+
return [];
|
|
66
|
+
}
|
|
67
|
+
const folded = new Map;
|
|
68
|
+
for (const line of raw.split(`
|
|
69
|
+
`)) {
|
|
70
|
+
const trimmed = line.trim();
|
|
71
|
+
if (trimmed.length === 0)
|
|
72
|
+
continue;
|
|
73
|
+
let parsedJson;
|
|
74
|
+
try {
|
|
75
|
+
parsedJson = JSON.parse(trimmed);
|
|
76
|
+
} catch {
|
|
77
|
+
continue;
|
|
78
|
+
}
|
|
79
|
+
const result = RecordSchema.safeParse(parsedJson);
|
|
80
|
+
if (!result.success)
|
|
81
|
+
continue;
|
|
82
|
+
folded.set(result.data.correlationId, result.data);
|
|
83
|
+
}
|
|
84
|
+
return [...folded.values()];
|
|
85
|
+
}
|
|
86
|
+
function appendRecord(directory, record) {
|
|
87
|
+
const result = RecordSchema.safeParse(record);
|
|
88
|
+
if (!result.success) {
|
|
89
|
+
throw new Error(`Invalid subscription record: ${result.error.message}`);
|
|
90
|
+
}
|
|
91
|
+
ensureSwarmDir(directory);
|
|
92
|
+
fs.appendFileSync(storePath(directory), `${JSON.stringify(record)}
|
|
93
|
+
`, "utf-8");
|
|
94
|
+
}
|
|
95
|
+
async function subscribe(directory, input) {
|
|
96
|
+
if (!directory || directory.trim() === "") {
|
|
97
|
+
throw new Error("directory is required");
|
|
98
|
+
}
|
|
99
|
+
if (!input.sessionID || input.sessionID.trim() === "") {
|
|
100
|
+
throw new Error("sessionID is required and must be non-empty");
|
|
101
|
+
}
|
|
102
|
+
if (!input.repoFullName || input.repoFullName.trim() === "") {
|
|
103
|
+
throw new Error("repoFullName is required and must be non-empty");
|
|
104
|
+
}
|
|
105
|
+
if (!input.prUrl || input.prUrl.trim() === "") {
|
|
106
|
+
throw new Error("prUrl is required and must be non-empty");
|
|
107
|
+
}
|
|
108
|
+
if (!input.prNumber || !Number.isInteger(input.prNumber) || input.prNumber <= 0) {
|
|
109
|
+
throw new Error("prNumber is required and must be a positive integer");
|
|
110
|
+
}
|
|
111
|
+
const correlationId = buildCorrelationId(input.sessionID, input.repoFullName, input.prNumber);
|
|
112
|
+
const now = Date.now();
|
|
113
|
+
return withEvidenceLock(directory, PR_SUBSCRIPTIONS_FILE, STORE_LOCK_AGENT, STORE_LOCK_TASK, async () => {
|
|
114
|
+
const existing = readAllRecords(directory);
|
|
115
|
+
const match = existing.find((r) => r.correlationId === correlationId && r.status === "active");
|
|
116
|
+
if (match) {
|
|
117
|
+
onSubscriptionCreated?.(directory, match);
|
|
118
|
+
return match;
|
|
119
|
+
}
|
|
120
|
+
if (input.maxSubscriptions !== undefined && input.maxSubscriptions > 0) {
|
|
121
|
+
const activeCount = existing.filter((r) => r.status === "active").length;
|
|
122
|
+
if (activeCount >= input.maxSubscriptions) {
|
|
123
|
+
throw new Error(`PR subscription limit reached: ${activeCount}/${input.maxSubscriptions}`);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
const record = {
|
|
127
|
+
correlationId,
|
|
128
|
+
sessionID: input.sessionID,
|
|
129
|
+
prNumber: input.prNumber,
|
|
130
|
+
repoFullName: input.repoFullName,
|
|
131
|
+
prUrl: input.prUrl,
|
|
132
|
+
lastCheckedAt: now,
|
|
133
|
+
isWatching: true,
|
|
134
|
+
hasUnaddressedEvents: false,
|
|
135
|
+
status: "active",
|
|
136
|
+
createdAt: now,
|
|
137
|
+
updatedAt: now,
|
|
138
|
+
errorCount: 0
|
|
139
|
+
};
|
|
140
|
+
appendRecord(directory, record);
|
|
141
|
+
onSubscriptionCreated?.(directory, record);
|
|
142
|
+
return record;
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
async function unsubscribe(directory, correlationId) {
|
|
146
|
+
if (!correlationId)
|
|
147
|
+
return null;
|
|
148
|
+
return withEvidenceLock(directory, PR_SUBSCRIPTIONS_FILE, STORE_LOCK_AGENT, STORE_LOCK_TASK, async () => {
|
|
149
|
+
const existing = readAllRecords(directory);
|
|
150
|
+
const match = existing.find((r) => r.correlationId === correlationId && r.status === "active");
|
|
151
|
+
if (!match)
|
|
152
|
+
return null;
|
|
153
|
+
const now = Date.now();
|
|
154
|
+
const removed = {
|
|
155
|
+
...match,
|
|
156
|
+
status: "removed",
|
|
157
|
+
isWatching: false,
|
|
158
|
+
updatedAt: now
|
|
159
|
+
};
|
|
160
|
+
appendRecord(directory, removed);
|
|
161
|
+
return removed;
|
|
162
|
+
});
|
|
163
|
+
}
|
|
164
|
+
async function listActive(directory) {
|
|
165
|
+
return readAllRecords(directory).filter((r) => r.status === "active");
|
|
166
|
+
}
|
|
167
|
+
async function lookupByPr(directory, repoFullName, prNumber) {
|
|
168
|
+
for (const record of readAllRecords(directory)) {
|
|
169
|
+
if (record.status === "active" && record.repoFullName === repoFullName && record.prNumber === prNumber) {
|
|
170
|
+
return record;
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
return null;
|
|
174
|
+
}
|
|
175
|
+
async function updateSnapshot(directory, correlationId, updates) {
|
|
176
|
+
if (!correlationId)
|
|
177
|
+
return null;
|
|
178
|
+
return withEvidenceLock(directory, PR_SUBSCRIPTIONS_FILE, STORE_LOCK_AGENT, STORE_LOCK_TASK, async () => {
|
|
179
|
+
const existing = readAllRecords(directory);
|
|
180
|
+
const match = existing.find((r) => r.correlationId === correlationId && r.status === "active");
|
|
181
|
+
if (!match)
|
|
182
|
+
return null;
|
|
183
|
+
const updated = {
|
|
184
|
+
...match,
|
|
185
|
+
...updates,
|
|
186
|
+
correlationId,
|
|
187
|
+
sessionID: match.sessionID,
|
|
188
|
+
repoFullName: match.repoFullName,
|
|
189
|
+
prNumber: match.prNumber,
|
|
190
|
+
prUrl: match.prUrl,
|
|
191
|
+
createdAt: match.createdAt,
|
|
192
|
+
updatedAt: Date.now()
|
|
193
|
+
};
|
|
194
|
+
appendRecord(directory, updated);
|
|
195
|
+
return updated;
|
|
196
|
+
});
|
|
197
|
+
}
|
|
198
|
+
async function sweepStale(directory, ttlDays, mergedPrs) {
|
|
199
|
+
if (!ttlDays || ttlDays <= 0)
|
|
200
|
+
return 0;
|
|
201
|
+
const ttlMs = ttlDays * 86400000;
|
|
202
|
+
const now = Date.now();
|
|
203
|
+
try {
|
|
204
|
+
return await withEvidenceLock(directory, PR_SUBSCRIPTIONS_FILE, STORE_LOCK_AGENT, STORE_LOCK_TASK, async () => {
|
|
205
|
+
let swept = 0;
|
|
206
|
+
for (const record of readAllRecords(directory)) {
|
|
207
|
+
if (record.status !== "active")
|
|
208
|
+
continue;
|
|
209
|
+
const prKey = `${record.repoFullName}::${record.prNumber}`;
|
|
210
|
+
const isMerged = mergedPrs?.has(prKey) ?? false;
|
|
211
|
+
const isStale = now - record.updatedAt > ttlMs;
|
|
212
|
+
if (isMerged) {
|
|
213
|
+
appendRecord(directory, {
|
|
214
|
+
...record,
|
|
215
|
+
status: "expired",
|
|
216
|
+
isWatching: false,
|
|
217
|
+
updatedAt: now
|
|
218
|
+
});
|
|
219
|
+
swept += 1;
|
|
220
|
+
log(`[pr-monitor] Swept subscription: merged/closed: ${prKey}`);
|
|
221
|
+
continue;
|
|
222
|
+
}
|
|
223
|
+
if (isStale && !record.hasUnaddressedEvents) {
|
|
224
|
+
appendRecord(directory, {
|
|
225
|
+
...record,
|
|
226
|
+
status: "expired",
|
|
227
|
+
isWatching: false,
|
|
228
|
+
updatedAt: now
|
|
229
|
+
});
|
|
230
|
+
swept += 1;
|
|
231
|
+
log(`[pr-monitor] Swept subscription: stale (TTL ${ttlDays}d): ${prKey}`);
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
return swept;
|
|
235
|
+
});
|
|
236
|
+
} catch (err) {
|
|
237
|
+
log(`[pr-monitor] sweepStale failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
238
|
+
return 0;
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
export { PR_SUBSCRIPTIONS_FILE, setOnSubscriptionCreated, buildCorrelationId, subscribe, unsubscribe, listActive, lookupByPr, updateSnapshot, sweepStale };
|