opencode-swarm 7.157.0 → 7.158.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/swarm-pr-review/SKILL.md +24 -26
- package/.opencode/skills/swarm-pr-review/references/findings-persistence-contract.md +11 -3
- package/.opencode/skills/swarm-pr-review/references/parser-dry-run.md +1 -1
- package/.opencode/skills/swarm-pr-review/references/prompt-templates.md +3 -3
- package/dist/background/candidate-contract.d.ts +20 -3
- package/dist/background/candidate-parser.d.ts +8 -1
- package/dist/background/pr-review-contract.d.ts +93 -5
- package/dist/cli/{coder-settlement-dz2x352d.js → coder-settlement-5sexsmqz.js} +9 -9
- package/dist/cli/{config-doctor-4jxf9w9e.js → config-doctor-ewn2kw6d.js} +3 -3
- package/dist/cli/{core-xf2f087t.js → core-72wdmzps.js} +3 -3
- package/dist/cli/{curation-policy-72qx868r.js → curation-policy-vn3m5nq2.js} +4 -4
- package/dist/cli/curator-drift-g6w4ga1q.js +1 -1
- package/dist/cli/{curator-pjjw3ja4.js → curator-g06sa98p.js} +31 -31
- package/dist/cli/{curator-llm-factory-7mfvey3x.js → curator-llm-factory-r8q84m4g.js} +31 -31
- package/dist/cli/{evidence-summary-service-5ffkbs50.js → evidence-summary-service-ttd0ntm0.js} +12 -12
- package/dist/cli/{gate-evidence-ne9rbdtb.js → gate-evidence-agnxf7md.js} +6 -6
- package/dist/cli/{guardrail-explain-b9vr4ta3.js → guardrail-explain-qf4k176t.js} +32 -32
- package/dist/cli/{guardrail-log-hrt36jz5.js → guardrail-log-g4qc595v.js} +4 -4
- package/dist/cli/{guardrail-reset-pggm9hx4.js → guardrail-reset-zpxk0p1j.js} +31 -31
- package/dist/cli/{hive-promoter-7vxm11sm.js → hive-promoter-zxy07gjg.js} +31 -31
- package/dist/cli/{index-ebratyzr.js → index-1vxmqvpt.js} +1 -1
- package/dist/cli/{index-1dzy1j4v.js → index-5tchehv7.js} +2 -2
- package/dist/cli/{index-b5xm177r.js → index-5zgf140g.js} +1 -1
- package/dist/cli/{index-2e60kmzg.js → index-663wnh64.js} +6 -6
- package/dist/cli/{index-79k7p589.js → index-6xxpwk5x.js} +1 -1
- package/dist/cli/{index-3qpr16k2.js → index-745dh1z1.js} +34 -34
- package/dist/cli/{index-ngn6jmad.js → index-7s1hmrfh.js} +1 -1
- package/dist/cli/{index-dwkrdpz2.js → index-8fqb0ynp.js} +1 -1
- package/dist/cli/{index-p0by16z8.js → index-a1884hh4.js} +5 -5
- package/dist/cli/{index-93ymj3j5.js → index-bv24pbaj.js} +4 -4
- package/dist/cli/{index-vbqssmbs.js → index-c57cyrwn.js} +8 -8
- package/dist/cli/{index-tvtvhjh0.js → index-dmfbmnp7.js} +4 -4
- package/dist/cli/{index-3vqdt1sx.js → index-f036tggv.js} +5 -5
- package/dist/cli/{index-4w20thrc.js → index-f776m4r5.js} +2 -2
- package/dist/cli/{index-61nkp124.js → index-fwe1wh6r.js} +2 -2
- package/dist/cli/{index-q94gt4n9.js → index-gm10kvne.js} +3 -3
- package/dist/cli/{index-xe6zbfps.js → index-h52hs4e9.js} +1 -1
- package/dist/cli/{index-n7gv8m7v.js → index-nvta6kcv.js} +3 -3
- package/dist/cli/{index-gpf3cjre.js → index-pfnj5pvs.js} +1 -1
- package/dist/cli/{index-zq7pw6qg.js → index-pvs2zw1y.js} +2 -2
- package/dist/cli/{index-gk6wpq41.js → index-rac2gkvr.js} +862 -461
- package/dist/cli/{index-4kd1nqd2.js → index-rc93mm6e.js} +3 -5
- package/dist/cli/{index-nd22bsnt.js → index-rd324153.js} +2 -2
- package/dist/cli/{index-g0j2hnse.js → index-vwx0by4y.js} +5 -5
- package/dist/cli/{index-91ybfvy2.js → index-x4ftmdha.js} +1 -1
- package/dist/cli/{index-j3egsxa1.js → index-x71shq8j.js} +6 -6
- package/dist/cli/{index-n6ayyadp.js → index-y3hdwh66.js} +4 -4
- package/dist/cli/{index-12e2hztp.js → index-yfbp4q09.js} +1 -1
- package/dist/cli/{index-9r7gp6cp.js → index-yt75r1er.js} +4 -0
- package/dist/cli/{index-t0kxka8n.js → index-z54qw70y.js} +1 -1
- package/dist/cli/{index-8n602qc2.js → index-zawd71cg.js} +6 -6
- package/dist/cli/{index-6sbx96v6.js → index-zcmwwp1x.js} +5 -4
- package/dist/cli/index.js +32 -32
- package/dist/cli/{knowledge-escalator-d65mctqy.js → knowledge-escalator-22zaj224.js} +11 -11
- package/dist/cli/{knowledge-events-6aet71sp.js → knowledge-events-xbx1k408.js} +9 -9
- package/dist/cli/{knowledge-link-z9cchqdj.js → knowledge-link-cj2abbae.js} +3 -3
- package/dist/cli/{knowledge-store-vvgxbakx.js → knowledge-store-fnm8xh9c.js} +4 -4
- package/dist/cli/{knowledge-validator-4fb6pbpn.js → knowledge-validator-t2jztjy1.js} +6 -6
- package/dist/cli/{model-preflight-cv9kvw8h.js → model-preflight-w85ecyxh.js} +1 -1
- package/dist/cli/{pending-delegations-f52jtanf.js → pending-delegations-29rtv1gb.js} +1 -1
- package/dist/cli/pr-review-reentry-authorization-25dep81m.js +299 -0
- package/dist/cli/{pr-subscriptions-76vg2xya.js → pr-subscriptions-cgac3ydd.js} +2 -2
- package/dist/cli/{runner-eagt6gf8.js → runner-sj5sf36c.js} +4 -4
- package/dist/cli/{scan-cursor-q3530gc8.js → scan-cursor-8acs9kwe.js} +5 -5
- package/dist/cli/{schema-5zc62306.js → schema-rjhassd0.js} +2 -2
- package/dist/cli/{scope-persistence-fzqf115q.js → scope-persistence-jb1a5dzh.js} +7 -7
- package/dist/cli/{skill-generator-kh1z90tm.js → skill-generator-frgppk1w.js} +13 -13
- package/dist/cli/{worktree-collision-ownership-2qxjtxt6.js → worktree-collision-ownership-f5sj6ffa.js} +4 -4
- package/dist/cli/{worktree-isolation-40v34p0s.js → worktree-isolation-5b0w6bha.js} +31 -31
- package/dist/hooks/pr-review-reentry-authorization.d.ts +97 -0
- package/dist/hooks/pr-workflow-gate.d.ts +211 -8
- package/dist/index.js +468 -461
- package/dist/tools/authorize-pr-review-reentry.d.ts +16 -0
- package/dist/tools/complete-pr-workflow.d.ts +2 -1
- package/dist/tools/index.d.ts +1 -0
- package/dist/tools/manifest.d.ts +1 -0
- package/dist/tools/repo-graph/types.d.ts +9 -0
- package/dist/tools/repo-graph.d.ts +1 -1
- package/dist/tools/tool-metadata.d.ts +4 -0
- package/dist/tools/write-pr-review-artifact.d.ts +18 -0
- package/package.json +1 -1
|
@@ -0,0 +1,299 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
import {
|
|
3
|
+
PrReviewRunIdSchema,
|
|
4
|
+
prWorkflowSessionFileStem,
|
|
5
|
+
readPrReviewReentryBindingContext
|
|
6
|
+
} from "./index-rac2gkvr.js";
|
|
7
|
+
import"./index-z54qw70y.js";
|
|
8
|
+
import"./index-rc93mm6e.js";
|
|
9
|
+
import"./index-rd324153.js";
|
|
10
|
+
import"./index-bv24pbaj.js";
|
|
11
|
+
import"./index-7s1hmrfh.js";
|
|
12
|
+
import"./index-txdagbh7.js";
|
|
13
|
+
import"./index-134d35c1.js";
|
|
14
|
+
import"./index-nj6rmyeh.js";
|
|
15
|
+
import"./index-y3hdwh66.js";
|
|
16
|
+
import"./index-vwx0by4y.js";
|
|
17
|
+
import"./index-5tchehv7.js";
|
|
18
|
+
import"./index-70ha9e09.js";
|
|
19
|
+
import"./index-c8s9a3zh.js";
|
|
20
|
+
import"./index-9ss2m4rs.js";
|
|
21
|
+
import"./index-x4ftmdha.js";
|
|
22
|
+
import"./index-zsrtt42s.js";
|
|
23
|
+
import"./index-c57cyrwn.js";
|
|
24
|
+
import"./index-3f7hqtgg.js";
|
|
25
|
+
import"./index-8fqb0ynp.js";
|
|
26
|
+
import"./index-dmfbmnp7.js";
|
|
27
|
+
import"./index-pfnj5pvs.js";
|
|
28
|
+
import"./index-rtry5xyf.js";
|
|
29
|
+
import"./index-fwe1wh6r.js";
|
|
30
|
+
import"./index-a1884hh4.js";
|
|
31
|
+
import"./index-yfbp4q09.js";
|
|
32
|
+
import"./index-ddszzne4.js";
|
|
33
|
+
import"./index-nvta6kcv.js";
|
|
34
|
+
import"./index-6xxpwk5x.js";
|
|
35
|
+
import"./index-nwkr6tvv.js";
|
|
36
|
+
import"./index-556ja8an.js";
|
|
37
|
+
import"./index-4fwbbad3.js";
|
|
38
|
+
import"./index-b43rt5ph.js";
|
|
39
|
+
import"./index-q7sjgr1y.js";
|
|
40
|
+
import"./index-x71shq8j.js";
|
|
41
|
+
import"./index-f036tggv.js";
|
|
42
|
+
import"./index-gm10kvne.js";
|
|
43
|
+
import"./index-gprxjmm7.js";
|
|
44
|
+
import"./index-n832052r.js";
|
|
45
|
+
import {
|
|
46
|
+
validateSwarmPath
|
|
47
|
+
} from "./index-dtn0pne5.js";
|
|
48
|
+
import"./index-z6xqpmqg.js";
|
|
49
|
+
import"./index-r3mvsbtq.js";
|
|
50
|
+
import"./index-663wnh64.js";
|
|
51
|
+
import"./index-f776m4r5.js";
|
|
52
|
+
import"./index-9e6fdz2h.js";
|
|
53
|
+
import"./index-4rhhvd1a.js";
|
|
54
|
+
import"./index-yt75r1er.js";
|
|
55
|
+
import"./index-zjygnfay.js";
|
|
56
|
+
import"./index-ae75rja9.js";
|
|
57
|
+
import"./index-5zgf140g.js";
|
|
58
|
+
import"./index-h52hs4e9.js";
|
|
59
|
+
import"./index-bk5tah7q.js";
|
|
60
|
+
import"./index-zcmwwp1x.js";
|
|
61
|
+
import"./index-xagq35tf.js";
|
|
62
|
+
import"./index-ed5ykebp.js";
|
|
63
|
+
import"./index-h1g8w4v0.js";
|
|
64
|
+
import {
|
|
65
|
+
require_proper_lockfile
|
|
66
|
+
} from "./index-7g4c7s5r.js";
|
|
67
|
+
import {
|
|
68
|
+
exports_external,
|
|
69
|
+
init_zod
|
|
70
|
+
} from "./index-bpmtbmy9.js";
|
|
71
|
+
import"./index-zgwm4ryv.js";
|
|
72
|
+
import {
|
|
73
|
+
__toESM
|
|
74
|
+
} from "./index-a76rekgs.js";
|
|
75
|
+
|
|
76
|
+
// src/hooks/pr-review-reentry-authorization.ts
|
|
77
|
+
init_zod();
|
|
78
|
+
var import_proper_lockfile = __toESM(require_proper_lockfile(), 1);
|
|
79
|
+
import { randomUUID } from "crypto";
|
|
80
|
+
import * as fsp from "fs/promises";
|
|
81
|
+
import * as path from "path";
|
|
82
|
+
var AUTHORIZATION_TTL_MS = 10 * 60 * 1000;
|
|
83
|
+
var MAX_ACTIVE_AUTHORIZATIONS = 8;
|
|
84
|
+
var MAX_PERSISTED_AUTHORIZATIONS = 32;
|
|
85
|
+
var REENTRY_AUTHORIZATIONS_MAX_BYTES = 64 * 1024;
|
|
86
|
+
var PrReviewReentryAuthorizationRecordSchema = exports_external.object({
|
|
87
|
+
schemaVersion: exports_external.literal(1),
|
|
88
|
+
authorizationId: exports_external.string().min(1).max(64),
|
|
89
|
+
sessionId: exports_external.string().min(1).max(256),
|
|
90
|
+
workflowInstanceId: exports_external.string().min(1).max(128).optional(),
|
|
91
|
+
runId: PrReviewRunIdSchema.optional(),
|
|
92
|
+
prHeadSha: exports_external.string().regex(/^[0-9a-f]{6,64}$/i),
|
|
93
|
+
revisionDigest: exports_external.string().min(1).max(256),
|
|
94
|
+
role: exports_external.enum(["reviewer", "test_engineer"]),
|
|
95
|
+
generation: exports_external.number().int().nonnegative(),
|
|
96
|
+
createdAt: exports_external.string().datetime(),
|
|
97
|
+
expiresAt: exports_external.string().datetime(),
|
|
98
|
+
consumedAt: exports_external.string().datetime().optional(),
|
|
99
|
+
consumedCallId: exports_external.string().min(1).max(128).optional()
|
|
100
|
+
}).strict();
|
|
101
|
+
var AuthorizationFileSchema = exports_external.object({
|
|
102
|
+
schemaVersion: exports_external.literal(1),
|
|
103
|
+
sessionId: exports_external.string().min(1).max(256),
|
|
104
|
+
authorizations: exports_external.array(PrReviewReentryAuthorizationRecordSchema).max(MAX_PERSISTED_AUTHORIZATIONS)
|
|
105
|
+
}).strict();
|
|
106
|
+
function reentryAuthorizationFilePath(directory, sessionID) {
|
|
107
|
+
const relative = path.join("pr-review", "reentry-authorizations", `${prWorkflowSessionFileStem(sessionID)}.json`);
|
|
108
|
+
return validateSwarmPath(directory, relative);
|
|
109
|
+
}
|
|
110
|
+
async function readAuthorizationFile(filePath) {
|
|
111
|
+
let raw;
|
|
112
|
+
try {
|
|
113
|
+
const stat2 = await fsp.stat(filePath);
|
|
114
|
+
if (!stat2.isFile() || stat2.size > REENTRY_AUTHORIZATIONS_MAX_BYTES) {
|
|
115
|
+
throw new Error("reentry authorization store is not a bounded regular file");
|
|
116
|
+
}
|
|
117
|
+
raw = await fsp.readFile(filePath, "utf8");
|
|
118
|
+
} catch (error) {
|
|
119
|
+
if (error.code === "ENOENT")
|
|
120
|
+
return null;
|
|
121
|
+
throw error;
|
|
122
|
+
}
|
|
123
|
+
const decoded = JSON.parse(raw);
|
|
124
|
+
const parsed = AuthorizationFileSchema.safeParse(decoded);
|
|
125
|
+
if (!parsed.success) {
|
|
126
|
+
throw new Error(`reentry authorization store is invalid: ${parsed.error.issues.map((issue) => `${issue.path.join(".")}: ${issue.message}`).join("; ")}`);
|
|
127
|
+
}
|
|
128
|
+
return parsed.data;
|
|
129
|
+
}
|
|
130
|
+
var RENAME_RETRY_DELAYS_MS = [10, 25, 50, 100, 200];
|
|
131
|
+
var RETRYABLE_RENAME_CODES = new Set(["EPERM", "EBUSY", "EACCES", "EEXIST"]);
|
|
132
|
+
async function renameWithRetryAsync(tempPath, targetPath) {
|
|
133
|
+
let lastError;
|
|
134
|
+
for (let attempt = 0;attempt <= _internals.renameRetryDelaysMs.length; attempt++) {
|
|
135
|
+
try {
|
|
136
|
+
await _internals.renameImpl(tempPath, targetPath);
|
|
137
|
+
return;
|
|
138
|
+
} catch (err) {
|
|
139
|
+
lastError = err;
|
|
140
|
+
const code = err?.code;
|
|
141
|
+
if (!code || !RETRYABLE_RENAME_CODES.has(code))
|
|
142
|
+
throw err;
|
|
143
|
+
if (attempt < _internals.renameRetryDelaysMs.length) {
|
|
144
|
+
await new Promise((resolve) => setTimeout(resolve, _internals.renameRetryDelaysMs[attempt]));
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
throw lastError;
|
|
149
|
+
}
|
|
150
|
+
async function writeAuthorizationFile(filePath, file) {
|
|
151
|
+
const serialized = `${JSON.stringify(file, null, 2)}
|
|
152
|
+
`;
|
|
153
|
+
if (Buffer.byteLength(serialized, "utf8") > REENTRY_AUTHORIZATIONS_MAX_BYTES) {
|
|
154
|
+
throw new Error("reentry authorization store exceeds its write bound");
|
|
155
|
+
}
|
|
156
|
+
await fsp.mkdir(path.dirname(filePath), { recursive: true });
|
|
157
|
+
const tempPath = path.join(path.dirname(filePath), `.${path.basename(filePath)}.${randomUUID()}.tmp`);
|
|
158
|
+
try {
|
|
159
|
+
await fsp.writeFile(tempPath, serialized, { encoding: "utf8", flag: "wx" });
|
|
160
|
+
await renameWithRetryAsync(tempPath, filePath);
|
|
161
|
+
} finally {
|
|
162
|
+
await fsp.rm(tempPath, { force: true }).catch(() => {
|
|
163
|
+
return;
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
function pruneAuthorizations(records, nowMs) {
|
|
168
|
+
const kept = [];
|
|
169
|
+
for (const record of [...records].sort((left, right) => right.createdAt.localeCompare(left.createdAt)).slice(0, MAX_PERSISTED_AUTHORIZATIONS)) {
|
|
170
|
+
if (record.consumedAt)
|
|
171
|
+
continue;
|
|
172
|
+
if (Date.parse(record.expiresAt) <= nowMs)
|
|
173
|
+
continue;
|
|
174
|
+
kept.push(record);
|
|
175
|
+
}
|
|
176
|
+
return kept;
|
|
177
|
+
}
|
|
178
|
+
var lf = import_proper_lockfile.default;
|
|
179
|
+
async function withAuthorizationLock(filePath, write) {
|
|
180
|
+
await fsp.mkdir(path.dirname(filePath), { recursive: true });
|
|
181
|
+
const release = await lf.lock(path.dirname(filePath), {
|
|
182
|
+
lockfilePath: `${filePath}.lock`,
|
|
183
|
+
retries: { retries: 8, minTimeout: 10, maxTimeout: 100 },
|
|
184
|
+
stale: 1e4,
|
|
185
|
+
update: 1000,
|
|
186
|
+
realpath: false
|
|
187
|
+
});
|
|
188
|
+
try {
|
|
189
|
+
return await write();
|
|
190
|
+
} finally {
|
|
191
|
+
await release().catch(() => {
|
|
192
|
+
return;
|
|
193
|
+
});
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
async function issuePrReviewReentryAuthorization(directory, sessionID, request) {
|
|
197
|
+
const trimmedSession = sessionID.trim();
|
|
198
|
+
if (!trimmedSession) {
|
|
199
|
+
throw new Error("BLOCKED: re-entry authorization requires an active sessionID");
|
|
200
|
+
}
|
|
201
|
+
const binding = await readPrReviewReentryBindingContext(directory, trimmedSession);
|
|
202
|
+
if (!binding || binding.prHeadSha !== request.prHeadSha.toLowerCase()) {
|
|
203
|
+
throw new Error(`BLOCKED: re-entry authorization requires an active PR_REVIEW workflow bound to the declared head (active: ${binding?.prHeadSha ?? "(none)"})`);
|
|
204
|
+
}
|
|
205
|
+
if (request.runId && binding.runId && request.runId !== binding.runId) {
|
|
206
|
+
throw new Error("BLOCKED: re-entry authorization run does not match the active PR-review run");
|
|
207
|
+
}
|
|
208
|
+
const filePath = reentryAuthorizationFilePath(directory, trimmedSession);
|
|
209
|
+
return withAuthorizationLock(filePath, async () => {
|
|
210
|
+
const existing = await readAuthorizationFile(filePath);
|
|
211
|
+
const nowMs = Date.now();
|
|
212
|
+
const now = new Date(nowMs).toISOString();
|
|
213
|
+
const records = pruneAuthorizations(existing?.authorizations ?? [], nowMs);
|
|
214
|
+
const active = records.filter((record2) => !record2.consumedAt && record2.role === request.role && record2.generation === binding.generation);
|
|
215
|
+
if (active.length > 0) {
|
|
216
|
+
throw new Error(`BLOCKED: an unconsumed re-entry authorization for role "${request.role}" at generation ${binding.generation} already exists; use it (one immediate Task dispatch) before issuing another`);
|
|
217
|
+
}
|
|
218
|
+
if (records.length >= MAX_ACTIVE_AUTHORIZATIONS) {
|
|
219
|
+
throw new Error(`BLOCKED: re-entry authorization store is at its bound of ${MAX_ACTIVE_AUTHORIZATIONS} active authorizations`);
|
|
220
|
+
}
|
|
221
|
+
const record = {
|
|
222
|
+
schemaVersion: 1,
|
|
223
|
+
authorizationId: randomUUID(),
|
|
224
|
+
sessionId: trimmedSession,
|
|
225
|
+
...binding.workflowInstanceId ? { workflowInstanceId: binding.workflowInstanceId } : {},
|
|
226
|
+
...binding.runId ? { runId: binding.runId } : {},
|
|
227
|
+
prHeadSha: binding.prHeadSha,
|
|
228
|
+
revisionDigest: binding.revisionDigest,
|
|
229
|
+
role: request.role,
|
|
230
|
+
generation: binding.generation,
|
|
231
|
+
createdAt: now,
|
|
232
|
+
expiresAt: new Date(nowMs + AUTHORIZATION_TTL_MS).toISOString()
|
|
233
|
+
};
|
|
234
|
+
await writeAuthorizationFile(filePath, {
|
|
235
|
+
schemaVersion: 1,
|
|
236
|
+
sessionId: trimmedSession,
|
|
237
|
+
authorizations: [record, ...records]
|
|
238
|
+
});
|
|
239
|
+
return record;
|
|
240
|
+
});
|
|
241
|
+
}
|
|
242
|
+
async function consumePrReviewReentryAuthorization(directory, sessionID, request) {
|
|
243
|
+
const trimmedSession = sessionID.trim();
|
|
244
|
+
if (!trimmedSession)
|
|
245
|
+
return null;
|
|
246
|
+
const filePath = reentryAuthorizationFilePath(directory, trimmedSession);
|
|
247
|
+
try {
|
|
248
|
+
return await withAuthorizationLock(filePath, async () => {
|
|
249
|
+
const existing = await readAuthorizationFile(filePath);
|
|
250
|
+
if (!existing)
|
|
251
|
+
return null;
|
|
252
|
+
const nowMs = Date.now();
|
|
253
|
+
const records = pruneAuthorizations(existing.authorizations, nowMs);
|
|
254
|
+
const index = records.findIndex((record) => !record.consumedAt && record.role === request.role && record.sessionId === trimmedSession && Date.parse(record.expiresAt) > nowMs);
|
|
255
|
+
if (index < 0) {
|
|
256
|
+
if (records.length !== existing.authorizations.length) {
|
|
257
|
+
await writeAuthorizationFile(filePath, {
|
|
258
|
+
...existing,
|
|
259
|
+
authorizations: records
|
|
260
|
+
});
|
|
261
|
+
}
|
|
262
|
+
return null;
|
|
263
|
+
}
|
|
264
|
+
const binding = await readPrReviewReentryBindingContext(directory, trimmedSession);
|
|
265
|
+
const candidate = records[index];
|
|
266
|
+
if (!binding || binding.prHeadSha !== candidate.prHeadSha || binding.revisionDigest !== candidate.revisionDigest || binding.generation !== candidate.generation || candidate.workflowInstanceId !== undefined && binding.workflowInstanceId !== candidate.workflowInstanceId || candidate.workflowInstanceId === undefined && binding.workflowInstanceId !== undefined) {
|
|
267
|
+
return null;
|
|
268
|
+
}
|
|
269
|
+
const consumed = {
|
|
270
|
+
...candidate,
|
|
271
|
+
consumedAt: new Date(nowMs).toISOString(),
|
|
272
|
+
consumedCallId: request.callID
|
|
273
|
+
};
|
|
274
|
+
records[index] = consumed;
|
|
275
|
+
await writeAuthorizationFile(filePath, {
|
|
276
|
+
...existing,
|
|
277
|
+
authorizations: records
|
|
278
|
+
});
|
|
279
|
+
return consumed;
|
|
280
|
+
});
|
|
281
|
+
} catch {
|
|
282
|
+
return null;
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
var _internals = {
|
|
286
|
+
AUTHORIZATION_TTL_MS,
|
|
287
|
+
MAX_ACTIVE_AUTHORIZATIONS,
|
|
288
|
+
reentryAuthorizationFilePath,
|
|
289
|
+
pruneAuthorizations,
|
|
290
|
+
renameImpl: (from, to) => fsp.rename(from, to),
|
|
291
|
+
renameRetryDelaysMs: RENAME_RETRY_DELAYS_MS,
|
|
292
|
+
renameWithRetryAsync,
|
|
293
|
+
writeAuthorizationFile
|
|
294
|
+
};
|
|
295
|
+
export {
|
|
296
|
+
issuePrReviewReentryAuthorization,
|
|
297
|
+
consumePrReviewReentryAuthorization,
|
|
298
|
+
_internals
|
|
299
|
+
};
|
|
@@ -14,12 +14,12 @@ import {
|
|
|
14
14
|
sweepStale,
|
|
15
15
|
unsubscribe,
|
|
16
16
|
updateSnapshot
|
|
17
|
-
} from "./index-
|
|
17
|
+
} from "./index-x4ftmdha.js";
|
|
18
18
|
import"./index-dtn0pne5.js";
|
|
19
19
|
import"./index-z6xqpmqg.js";
|
|
20
20
|
import"./index-r3mvsbtq.js";
|
|
21
21
|
import"./index-zjygnfay.js";
|
|
22
|
-
import"./index-
|
|
22
|
+
import"./index-zcmwwp1x.js";
|
|
23
23
|
import"./index-xagq35tf.js";
|
|
24
24
|
import"./index-ed5ykebp.js";
|
|
25
25
|
import"./index-h1g8w4v0.js";
|
|
@@ -3,12 +3,12 @@ import {
|
|
|
3
3
|
_internals,
|
|
4
4
|
createModelEvaluationExecutor,
|
|
5
5
|
runEvaluation
|
|
6
|
-
} from "./index-
|
|
7
|
-
import"./index-
|
|
6
|
+
} from "./index-z54qw70y.js";
|
|
7
|
+
import"./index-7s1hmrfh.js";
|
|
8
8
|
import"./index-txdagbh7.js";
|
|
9
9
|
import"./index-r3mvsbtq.js";
|
|
10
|
-
import"./index-
|
|
11
|
-
import"./index-
|
|
10
|
+
import"./index-h52hs4e9.js";
|
|
11
|
+
import"./index-zcmwwp1x.js";
|
|
12
12
|
import"./index-xagq35tf.js";
|
|
13
13
|
import"./index-ed5ykebp.js";
|
|
14
14
|
import"./index-h1g8w4v0.js";
|
|
@@ -4,15 +4,15 @@ import {
|
|
|
4
4
|
alreadyCuratedThisGeneration,
|
|
5
5
|
claimNextScanBatch,
|
|
6
6
|
getScanStatus
|
|
7
|
-
} from "./index-
|
|
8
|
-
import"./index-
|
|
7
|
+
} from "./index-5tchehv7.js";
|
|
8
|
+
import"./index-x71shq8j.js";
|
|
9
9
|
import"./index-9e6fdz2h.js";
|
|
10
10
|
import"./index-4rhhvd1a.js";
|
|
11
11
|
import"./index-ae75rja9.js";
|
|
12
|
-
import"./index-
|
|
13
|
-
import"./index-
|
|
12
|
+
import"./index-5zgf140g.js";
|
|
13
|
+
import"./index-h52hs4e9.js";
|
|
14
14
|
import"./index-bk5tah7q.js";
|
|
15
|
-
import"./index-
|
|
15
|
+
import"./index-zcmwwp1x.js";
|
|
16
16
|
import"./index-xagq35tf.js";
|
|
17
17
|
import"./index-ed5ykebp.js";
|
|
18
18
|
import"./index-h1g8w4v0.js";
|
|
@@ -101,8 +101,8 @@ import {
|
|
|
101
101
|
resolveGeneratedAgentRole,
|
|
102
102
|
resolveGuardrailsConfig,
|
|
103
103
|
stripKnownSwarmPrefix
|
|
104
|
-
} from "./index-
|
|
105
|
-
import"./index-
|
|
104
|
+
} from "./index-f776m4r5.js";
|
|
105
|
+
import"./index-yt75r1er.js";
|
|
106
106
|
import"./index-zjygnfay.js";
|
|
107
107
|
import"./index-bk5tah7q.js";
|
|
108
108
|
import"./index-bpmtbmy9.js";
|
|
@@ -23,18 +23,18 @@ import {
|
|
|
23
23
|
tombstoneScopeBinding,
|
|
24
24
|
writeScopeBindingToDisk,
|
|
25
25
|
writeScopeToDisk
|
|
26
|
-
} from "./index-
|
|
27
|
-
import"./index-
|
|
26
|
+
} from "./index-nvta6kcv.js";
|
|
27
|
+
import"./index-6xxpwk5x.js";
|
|
28
28
|
import"./index-nwkr6tvv.js";
|
|
29
29
|
import"./index-556ja8an.js";
|
|
30
|
-
import"./index-
|
|
31
|
-
import"./index-
|
|
32
|
-
import"./index-9r7gp6cp.js";
|
|
33
|
-
import"./index-zjygnfay.js";
|
|
30
|
+
import"./index-663wnh64.js";
|
|
31
|
+
import"./index-f776m4r5.js";
|
|
34
32
|
import"./index-9e6fdz2h.js";
|
|
35
33
|
import"./index-4rhhvd1a.js";
|
|
34
|
+
import"./index-yt75r1er.js";
|
|
35
|
+
import"./index-zjygnfay.js";
|
|
36
36
|
import"./index-bk5tah7q.js";
|
|
37
|
-
import"./index-
|
|
37
|
+
import"./index-zcmwwp1x.js";
|
|
38
38
|
import"./index-xagq35tf.js";
|
|
39
39
|
import"./index-ed5ykebp.js";
|
|
40
40
|
import"./index-h1g8w4v0.js";
|
|
@@ -33,30 +33,30 @@ import {
|
|
|
33
33
|
sanitizeSlug,
|
|
34
34
|
selectCandidateEntries,
|
|
35
35
|
writeEvalStub
|
|
36
|
-
} from "./index-
|
|
37
|
-
import"./index-
|
|
38
|
-
import"./index-
|
|
36
|
+
} from "./index-y3hdwh66.js";
|
|
37
|
+
import"./index-dmfbmnp7.js";
|
|
38
|
+
import"./index-pfnj5pvs.js";
|
|
39
39
|
import"./index-rtry5xyf.js";
|
|
40
40
|
import"./index-q7sjgr1y.js";
|
|
41
|
-
import"./index-
|
|
42
|
-
import"./index-
|
|
43
|
-
import"./index-
|
|
41
|
+
import"./index-x71shq8j.js";
|
|
42
|
+
import"./index-f036tggv.js";
|
|
43
|
+
import"./index-gm10kvne.js";
|
|
44
44
|
import"./index-gprxjmm7.js";
|
|
45
45
|
import"./index-n832052r.js";
|
|
46
46
|
import"./index-dtn0pne5.js";
|
|
47
47
|
import"./index-z6xqpmqg.js";
|
|
48
48
|
import"./index-r3mvsbtq.js";
|
|
49
|
-
import"./index-
|
|
50
|
-
import"./index-
|
|
51
|
-
import"./index-9r7gp6cp.js";
|
|
52
|
-
import"./index-zjygnfay.js";
|
|
49
|
+
import"./index-663wnh64.js";
|
|
50
|
+
import"./index-f776m4r5.js";
|
|
53
51
|
import"./index-9e6fdz2h.js";
|
|
54
52
|
import"./index-4rhhvd1a.js";
|
|
53
|
+
import"./index-yt75r1er.js";
|
|
54
|
+
import"./index-zjygnfay.js";
|
|
55
55
|
import"./index-ae75rja9.js";
|
|
56
|
-
import"./index-
|
|
57
|
-
import"./index-
|
|
56
|
+
import"./index-5zgf140g.js";
|
|
57
|
+
import"./index-h52hs4e9.js";
|
|
58
58
|
import"./index-bk5tah7q.js";
|
|
59
|
-
import"./index-
|
|
59
|
+
import"./index-zcmwwp1x.js";
|
|
60
60
|
import"./index-xagq35tf.js";
|
|
61
61
|
import"./index-ed5ykebp.js";
|
|
62
62
|
import"./index-h1g8w4v0.js";
|
|
@@ -6,24 +6,24 @@ import {
|
|
|
6
6
|
WORKTREE_PROVISIONING_OWNER_LEASE_MS,
|
|
7
7
|
removeWorktreeProvisioningOwner,
|
|
8
8
|
scanWorktreeProvisioningOwnersForRecovery
|
|
9
|
-
} from "./index-
|
|
9
|
+
} from "./index-8fqb0ynp.js";
|
|
10
10
|
import {
|
|
11
11
|
scanDelegationFallbacksForRecovery,
|
|
12
12
|
scanDelegationsForRecovery
|
|
13
|
-
} from "./index-
|
|
13
|
+
} from "./index-yfbp4q09.js";
|
|
14
14
|
import"./index-ddszzne4.js";
|
|
15
15
|
import"./index-dtn0pne5.js";
|
|
16
16
|
import"./index-z6xqpmqg.js";
|
|
17
17
|
import {
|
|
18
18
|
bunSpawn
|
|
19
19
|
} from "./index-r3mvsbtq.js";
|
|
20
|
-
import"./index-zjygnfay.js";
|
|
21
20
|
import {
|
|
22
21
|
init_git_executable,
|
|
23
22
|
resolveGitExecutable
|
|
24
23
|
} from "./index-9e6fdz2h.js";
|
|
25
24
|
import"./index-4rhhvd1a.js";
|
|
26
|
-
import"./index-
|
|
25
|
+
import"./index-zjygnfay.js";
|
|
26
|
+
import"./index-zcmwwp1x.js";
|
|
27
27
|
import"./index-xagq35tf.js";
|
|
28
28
|
import"./index-ed5ykebp.js";
|
|
29
29
|
import"./index-h1g8w4v0.js";
|
|
@@ -21,61 +21,61 @@ import {
|
|
|
21
21
|
sanitizeWorktreeTaskId,
|
|
22
22
|
standardWorktreeByCallID,
|
|
23
23
|
standardWorktreeSerializationSessions
|
|
24
|
-
} from "./index-
|
|
25
|
-
import"./index-
|
|
26
|
-
import"./index-
|
|
27
|
-
import"./index-
|
|
28
|
-
import"./index-
|
|
29
|
-
import"./index-
|
|
24
|
+
} from "./index-rac2gkvr.js";
|
|
25
|
+
import"./index-z54qw70y.js";
|
|
26
|
+
import"./index-rc93mm6e.js";
|
|
27
|
+
import"./index-rd324153.js";
|
|
28
|
+
import"./index-bv24pbaj.js";
|
|
29
|
+
import"./index-7s1hmrfh.js";
|
|
30
|
+
import"./index-txdagbh7.js";
|
|
30
31
|
import"./index-134d35c1.js";
|
|
31
32
|
import"./index-nj6rmyeh.js";
|
|
32
|
-
import"./index-
|
|
33
|
-
import"./index-
|
|
34
|
-
import"./index-
|
|
33
|
+
import"./index-y3hdwh66.js";
|
|
34
|
+
import"./index-vwx0by4y.js";
|
|
35
|
+
import"./index-5tchehv7.js";
|
|
35
36
|
import"./index-70ha9e09.js";
|
|
36
37
|
import"./index-c8s9a3zh.js";
|
|
37
38
|
import"./index-9ss2m4rs.js";
|
|
38
|
-
import"./index-
|
|
39
|
+
import"./index-x4ftmdha.js";
|
|
39
40
|
import"./index-zsrtt42s.js";
|
|
40
|
-
import"./index-
|
|
41
|
-
import"./index-
|
|
42
|
-
import"./index-
|
|
43
|
-
import"./index-
|
|
44
|
-
import"./index-
|
|
41
|
+
import"./index-c57cyrwn.js";
|
|
42
|
+
import"./index-3f7hqtgg.js";
|
|
43
|
+
import"./index-8fqb0ynp.js";
|
|
44
|
+
import"./index-dmfbmnp7.js";
|
|
45
|
+
import"./index-pfnj5pvs.js";
|
|
45
46
|
import"./index-rtry5xyf.js";
|
|
46
|
-
import"./index-
|
|
47
|
-
import"./index-
|
|
48
|
-
import"./index-
|
|
47
|
+
import"./index-fwe1wh6r.js";
|
|
48
|
+
import"./index-a1884hh4.js";
|
|
49
|
+
import"./index-yfbp4q09.js";
|
|
49
50
|
import"./index-ddszzne4.js";
|
|
50
|
-
import"./index-
|
|
51
|
-
import"./index-
|
|
52
|
-
import"./index-79k7p589.js";
|
|
51
|
+
import"./index-nvta6kcv.js";
|
|
52
|
+
import"./index-6xxpwk5x.js";
|
|
53
53
|
import"./index-nwkr6tvv.js";
|
|
54
54
|
import"./index-556ja8an.js";
|
|
55
55
|
import"./index-4fwbbad3.js";
|
|
56
56
|
import"./index-b43rt5ph.js";
|
|
57
57
|
import"./index-q7sjgr1y.js";
|
|
58
|
-
import"./index-
|
|
59
|
-
import"./index-
|
|
58
|
+
import"./index-x71shq8j.js";
|
|
59
|
+
import"./index-f036tggv.js";
|
|
60
60
|
import {
|
|
61
61
|
resolveWorktreeIsolationConfig
|
|
62
|
-
} from "./index-
|
|
62
|
+
} from "./index-gm10kvne.js";
|
|
63
63
|
import"./index-gprxjmm7.js";
|
|
64
64
|
import"./index-n832052r.js";
|
|
65
65
|
import"./index-dtn0pne5.js";
|
|
66
66
|
import"./index-z6xqpmqg.js";
|
|
67
67
|
import"./index-r3mvsbtq.js";
|
|
68
|
-
import"./index-
|
|
69
|
-
import"./index-
|
|
70
|
-
import"./index-9r7gp6cp.js";
|
|
71
|
-
import"./index-zjygnfay.js";
|
|
68
|
+
import"./index-663wnh64.js";
|
|
69
|
+
import"./index-f776m4r5.js";
|
|
72
70
|
import"./index-9e6fdz2h.js";
|
|
73
71
|
import"./index-4rhhvd1a.js";
|
|
72
|
+
import"./index-yt75r1er.js";
|
|
73
|
+
import"./index-zjygnfay.js";
|
|
74
74
|
import"./index-ae75rja9.js";
|
|
75
|
-
import"./index-
|
|
76
|
-
import"./index-
|
|
75
|
+
import"./index-5zgf140g.js";
|
|
76
|
+
import"./index-h52hs4e9.js";
|
|
77
77
|
import"./index-bk5tah7q.js";
|
|
78
|
-
import"./index-
|
|
78
|
+
import"./index-zcmwwp1x.js";
|
|
79
79
|
import"./index-xagq35tf.js";
|
|
80
80
|
import"./index-ed5ykebp.js";
|
|
81
81
|
import"./index-h1g8w4v0.js";
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
/**
|
|
3
|
+
* Correlated one-use reviewer re-entry authorization (issue #2383).
|
|
4
|
+
*
|
|
5
|
+
* Replaces prompt-text inspection (`MODE: PR_REVIEW`) as the ONLY way a
|
|
6
|
+
* direct Task dispatch of `reviewer`/`test_engineer` may bypass the generic
|
|
7
|
+
* Stage-A task-workflow requirement. The PR workflow controller issues an
|
|
8
|
+
* authorization bound to the exact active session, workflow, run, base/head
|
|
9
|
+
* SHA, worktree revision digest, role, and gate generation; the Task
|
|
10
|
+
* delegation gate consumes it atomically, exactly once. Stale, cross-session,
|
|
11
|
+
* wrong-role, replayed, expired, or revision-drifted requests fail closed to
|
|
12
|
+
* the normal gating path.
|
|
13
|
+
*
|
|
14
|
+
* Persistence: `.swarm/pr-review/reentry-authorizations/<session-stem>.json`,
|
|
15
|
+
* guarded by a `proper-lockfile` lock (the same dependency the candidate
|
|
16
|
+
* sidecar store uses). Bounded: at most MAX_ACTIVE_AUTHORIZATIONS unconsumed
|
|
17
|
+
* authorizations per session; expired/unconsumed records are pruned on write.
|
|
18
|
+
*/
|
|
19
|
+
export type PrReviewReentryRole = 'reviewer' | 'test_engineer';
|
|
20
|
+
export interface PrReviewReentryAuthorizationRecord {
|
|
21
|
+
schemaVersion: 1;
|
|
22
|
+
authorizationId: string;
|
|
23
|
+
sessionId: string;
|
|
24
|
+
workflowInstanceId?: string;
|
|
25
|
+
runId?: string;
|
|
26
|
+
prHeadSha: string;
|
|
27
|
+
revisionDigest: string;
|
|
28
|
+
role: PrReviewReentryRole;
|
|
29
|
+
generation: number;
|
|
30
|
+
createdAt: string;
|
|
31
|
+
expiresAt: string;
|
|
32
|
+
consumedAt?: string;
|
|
33
|
+
consumedCallId?: string;
|
|
34
|
+
}
|
|
35
|
+
declare const AuthorizationFileSchema: z.ZodObject<{
|
|
36
|
+
schemaVersion: z.ZodLiteral<1>;
|
|
37
|
+
sessionId: z.ZodString;
|
|
38
|
+
authorizations: z.ZodArray<z.ZodObject<{
|
|
39
|
+
schemaVersion: z.ZodLiteral<1>;
|
|
40
|
+
authorizationId: z.ZodString;
|
|
41
|
+
sessionId: z.ZodString;
|
|
42
|
+
workflowInstanceId: z.ZodOptional<z.ZodString>;
|
|
43
|
+
runId: z.ZodOptional<z.ZodString>;
|
|
44
|
+
prHeadSha: z.ZodString;
|
|
45
|
+
revisionDigest: z.ZodString;
|
|
46
|
+
role: z.ZodEnum<{
|
|
47
|
+
reviewer: "reviewer";
|
|
48
|
+
test_engineer: "test_engineer";
|
|
49
|
+
}>;
|
|
50
|
+
generation: z.ZodNumber;
|
|
51
|
+
createdAt: z.ZodString;
|
|
52
|
+
expiresAt: z.ZodString;
|
|
53
|
+
consumedAt: z.ZodOptional<z.ZodString>;
|
|
54
|
+
consumedCallId: z.ZodOptional<z.ZodString>;
|
|
55
|
+
}, z.core.$strict>>;
|
|
56
|
+
}, z.core.$strict>;
|
|
57
|
+
type AuthorizationFile = z.infer<typeof AuthorizationFileSchema>;
|
|
58
|
+
declare function reentryAuthorizationFilePath(directory: string, sessionID: string): string;
|
|
59
|
+
declare function renameWithRetryAsync(tempPath: string, targetPath: string): Promise<void>;
|
|
60
|
+
declare function writeAuthorizationFile(filePath: string, file: AuthorizationFile): Promise<void>;
|
|
61
|
+
/** Drop consumed/expired records past the retention bound; keep newest first. */
|
|
62
|
+
declare function pruneAuthorizations(records: readonly PrReviewReentryAuthorizationRecord[], nowMs: number): PrReviewReentryAuthorizationRecord[];
|
|
63
|
+
/**
|
|
64
|
+
* Issue a one-use authorization for the CURRENT active PR_REVIEW workflow.
|
|
65
|
+
* Fails when no active head-bound PR_REVIEW gate exists for the session, or
|
|
66
|
+
* when an unconsumed authorization for the same role and generation already
|
|
67
|
+
* exists (no stockpiling: issue, then immediately Task-dispatch the role).
|
|
68
|
+
*/
|
|
69
|
+
export declare function issuePrReviewReentryAuthorization(directory: string, sessionID: string, request: {
|
|
70
|
+
runId?: string;
|
|
71
|
+
prHeadSha: string;
|
|
72
|
+
role: PrReviewReentryRole;
|
|
73
|
+
}): Promise<PrReviewReentryAuthorizationRecord>;
|
|
74
|
+
/**
|
|
75
|
+
* Atomically consume the one active authorization for this session+role.
|
|
76
|
+
* Re-verifies the binding against the CURRENT PR_REVIEW gate state — any
|
|
77
|
+
* drift (mode change, head change, revision digest change, generation bump)
|
|
78
|
+
* fails closed to null, as does replay, expiry, cross-session use, or wrong
|
|
79
|
+
* role. Returns the consumed record on success.
|
|
80
|
+
*/
|
|
81
|
+
export declare function consumePrReviewReentryAuthorization(directory: string, sessionID: string, request: {
|
|
82
|
+
role: PrReviewReentryRole;
|
|
83
|
+
callID: string;
|
|
84
|
+
}): Promise<PrReviewReentryAuthorizationRecord | null>;
|
|
85
|
+
export declare const _internals: {
|
|
86
|
+
AUTHORIZATION_TTL_MS: number;
|
|
87
|
+
MAX_ACTIVE_AUTHORIZATIONS: number;
|
|
88
|
+
reentryAuthorizationFilePath: typeof reentryAuthorizationFilePath;
|
|
89
|
+
pruneAuthorizations: typeof pruneAuthorizations;
|
|
90
|
+
/** DI seam: the rename implementation (tests inject failure modes). */
|
|
91
|
+
renameImpl: (from: string, to: string) => Promise<void>;
|
|
92
|
+
/** DI seam: retry backoff schedule (tests shrink to avoid real sleeps). */
|
|
93
|
+
renameRetryDelaysMs: number[];
|
|
94
|
+
renameWithRetryAsync: typeof renameWithRetryAsync;
|
|
95
|
+
writeAuthorizationFile: typeof writeAuthorizationFile;
|
|
96
|
+
};
|
|
97
|
+
export {};
|