@permissionbrick/auto-review-mcp 0.1.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/dist/launch.js ADDED
@@ -0,0 +1,62 @@
1
+ /**
2
+ * Shared helper to ensure exactly one detached background coordinator is
3
+ * running, used by both the stdio proxy and the poller CLI. The first caller on
4
+ * a given port starts it; everyone else attaches to it. It outlives any caller.
5
+ */
6
+ import { spawn } from "node:child_process";
7
+ import { openSync } from "node:fs";
8
+ import { tmpdir } from "node:os";
9
+ import { join } from "node:path";
10
+ import { fileURLToPath } from "node:url";
11
+ import { setTimeout as sleep } from "node:timers/promises";
12
+ const SERVER_PATH = fileURLToPath(new URL("./server.js", import.meta.url));
13
+ /** Returns the coordinator's reported state if healthy, else null. */
14
+ export async function pingHealth(base) {
15
+ try {
16
+ const r = await fetch(`${base}/healthz`, { signal: AbortSignal.timeout(1500) });
17
+ if (!r.ok)
18
+ return null;
19
+ const body = (await r.json());
20
+ return { repo: body.status?.repo ?? null };
21
+ }
22
+ catch {
23
+ return null;
24
+ }
25
+ }
26
+ /** Ensure a single background coordinator is running; resolves when it is healthy. */
27
+ export async function ensureCoordinator(cfg) {
28
+ const log = cfg.log ?? (() => { });
29
+ const base = `http://${cfg.host}:${cfg.port}`;
30
+ const existing = await pingHealth(base);
31
+ if (existing) {
32
+ if (cfg.repo && existing.repo && existing.repo !== cfg.repo) {
33
+ log(`WARNING: coordinator already running for repo '${existing.repo}', ` +
34
+ `not '${cfg.repo}'. The running repo wins; point both agents at the same repo.`);
35
+ }
36
+ return;
37
+ }
38
+ const logFile = join(tmpdir(), `auto-review-coordinator-${cfg.port}.log`);
39
+ const out = openSync(logFile, "a");
40
+ log(`starting shared coordinator (logs: ${logFile})`);
41
+ const serverArgs = [
42
+ SERVER_PATH,
43
+ "--host", cfg.host,
44
+ "--port", String(cfg.port),
45
+ "--poll-seconds", String(cfg.pollSeconds),
46
+ "--max-diff-bytes", String(cfg.maxDiffBytes),
47
+ ];
48
+ if (cfg.repo)
49
+ serverArgs.push("--repo", cfg.repo);
50
+ const child = spawn(process.execPath, serverArgs, {
51
+ detached: true,
52
+ stdio: ["ignore", out, out],
53
+ });
54
+ child.unref();
55
+ for (let i = 0; i < 100; i++) {
56
+ if (await pingHealth(base))
57
+ return;
58
+ await sleep(100);
59
+ }
60
+ throw new Error(`coordinator did not become healthy at ${base} within 10s (see ${logFile})`);
61
+ }
62
+ //# sourceMappingURL=launch.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"launch.js","sourceRoot":"","sources":["../src/launch.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,396 @@
1
+ /**
2
+ * The shared rendezvous between the developer agent and the reviewer agent.
3
+ *
4
+ * A single instance is shared across both MCP sessions. It holds the one batch
5
+ * currently moving through the loop and coordinates the two blocking calls
6
+ * (developer's `request_review` and reviewer's `get_next_review`) using an
7
+ * event-driven wait: any state change wakes the waiters, who re-check their
8
+ * condition. Handoffs are therefore instant; the bounded wait window only
9
+ * controls how long an *idle* waiter holds before returning `keep_waiting`.
10
+ */
11
+ import { GitError, GitRepo } from "./git.js";
12
+ /** Promise-chain mutex: serialises the short critical sections (git + state). */
13
+ class Mutex {
14
+ tail = Promise.resolve();
15
+ async lock() {
16
+ let release;
17
+ const next = new Promise((r) => (release = r));
18
+ const prev = this.tail;
19
+ this.tail = this.tail.then(() => next);
20
+ await prev;
21
+ return release;
22
+ }
23
+ }
24
+ const ACTIVE_STATUSES = new Set(["queued", "in_review"]);
25
+ export class Orchestrator {
26
+ opts;
27
+ /** The repo the session operates on; set by the developer via initializeSession. */
28
+ git = null;
29
+ active = null;
30
+ complete = false;
31
+ completedCount = 0;
32
+ lastResolved = null;
33
+ seq = 0;
34
+ /** Resolvers waiting for any state change. */
35
+ waiters = new Set();
36
+ mutex = new Mutex();
37
+ log;
38
+ constructor(opts) {
39
+ this.opts = opts;
40
+ this.log = opts.log ?? (() => { });
41
+ }
42
+ /**
43
+ * Point the workflow at a git repository (set by the developer agent at
44
+ * runtime, or pre-set from --repo at startup). Validates the path, then
45
+ * resets the session so a fresh review loop starts in the new repo. Held in
46
+ * memory until the server stops or this is called again.
47
+ */
48
+ async initializeSession(repoPath) {
49
+ const candidate = new GitRepo(repoPath);
50
+ try {
51
+ await candidate.assertRepo();
52
+ }
53
+ catch (err) {
54
+ return { status: "error", message: err.message };
55
+ }
56
+ const release = await this.mutex.lock();
57
+ try {
58
+ this.git = candidate;
59
+ // Fresh session.
60
+ this.active = null;
61
+ this.complete = false;
62
+ this.completedCount = 0;
63
+ this.lastResolved = null;
64
+ this.notify();
65
+ const head = await candidate.head();
66
+ this.log(`session initialised for ${repoPath} (HEAD ${head ? head.slice(0, 8) : "none"})`);
67
+ return {
68
+ status: "ok",
69
+ repo: repoPath,
70
+ head,
71
+ message: "Review session ready. Implement a batch, then call request_review.",
72
+ };
73
+ }
74
+ finally {
75
+ release();
76
+ }
77
+ }
78
+ // ---- wait primitives ----
79
+ /** Resolve either when notified or after `ms`. */
80
+ waitForChange(ms) {
81
+ return new Promise((resolve) => {
82
+ const w = () => {
83
+ clearTimeout(timer);
84
+ this.waiters.delete(w);
85
+ resolve();
86
+ };
87
+ const timer = setTimeout(() => {
88
+ this.waiters.delete(w);
89
+ resolve();
90
+ }, ms);
91
+ this.waiters.add(w);
92
+ });
93
+ }
94
+ /** Block until `pred()` is true or the window elapses. Returns pred()'s final value. */
95
+ async waitUntil(pred, windowMs) {
96
+ if (pred())
97
+ return true;
98
+ const deadline = Date.now() + windowMs;
99
+ while (!pred()) {
100
+ const remaining = deadline - Date.now();
101
+ if (remaining <= 0)
102
+ return false;
103
+ await this.waitForChange(remaining);
104
+ }
105
+ return true;
106
+ }
107
+ notify() {
108
+ for (const w of [...this.waiters])
109
+ w();
110
+ }
111
+ nextId() {
112
+ this.seq += 1;
113
+ return `batch-${this.seq}`;
114
+ }
115
+ /** True while a batch is queued or in review (i.e. the reviewer has work). */
116
+ pendingForReview() {
117
+ return (this.active !== null &&
118
+ (this.active.status === "queued" || this.active.status === "in_review"));
119
+ }
120
+ // ---- developer side ----
121
+ /**
122
+ * Snapshot the working tree, register/refresh the active batch, and block
123
+ * until the reviewer rules on it (or the wait window elapses).
124
+ */
125
+ async requestReview(summary, commitMessage) {
126
+ const release = await this.mutex.lock();
127
+ let batchId;
128
+ try {
129
+ if (!this.git) {
130
+ return {
131
+ status: "not_initialized",
132
+ message: "No repository configured yet. Call initialize_review_session with the absolute path " +
133
+ "to the git repo you are working in, then call request_review again.",
134
+ };
135
+ }
136
+ const snap = await this.git.captureDiff(this.opts.maxDiffBytes);
137
+ if (snap.isEmpty) {
138
+ return {
139
+ status: "nothing_to_review",
140
+ message: "No changes versus HEAD. Implement a batch of work, then call request_review again.",
141
+ };
142
+ }
143
+ const reusable = this.active &&
144
+ ACTIVE_STATUSES.has(this.active.status) &&
145
+ this.active.diffHash === snap.diffHash;
146
+ if (!reusable) {
147
+ const batch = {
148
+ id: this.nextId(),
149
+ summary,
150
+ commitMessage,
151
+ diff: snap.diff,
152
+ diffStat: snap.diffStat,
153
+ diffHash: snap.diffHash,
154
+ truncated: snap.truncated,
155
+ status: "queued",
156
+ createdAt: Date.now(),
157
+ };
158
+ this.active = batch;
159
+ this.log(`developer submitted ${batch.id} (${snap.fullBytes} byte diff): ${commitMessage}`);
160
+ this.notify(); // wake a waiting reviewer
161
+ }
162
+ else {
163
+ // identical diff while a review is pending → keep refreshed text, resume waiting
164
+ this.active.summary = summary;
165
+ this.active.commitMessage = commitMessage;
166
+ }
167
+ batchId = this.active.id;
168
+ }
169
+ finally {
170
+ release();
171
+ }
172
+ return this.waitForVerdict(batchId);
173
+ }
174
+ /**
175
+ * Wait until `batchId` reaches a verdict (or the window elapses) and return
176
+ * it. Reads the verdict WITHOUT clearing the batch, so it is safe to call
177
+ * from several places at once — a re-polling developer, the `await-verdict`
178
+ * poll command, or a retry after a client timeout. The batch is only replaced
179
+ * when the developer submits the next one.
180
+ */
181
+ async waitForVerdict(batchId) {
182
+ const resolved = await this.waitUntil(() => {
183
+ const b = this.active;
184
+ return (!!b && b.id === batchId && (b.status === "approved" || b.status === "changes_requested"));
185
+ }, this.opts.pollMs);
186
+ if (!resolved) {
187
+ return {
188
+ status: "keep_waiting",
189
+ batch_id: batchId,
190
+ message: "The reviewer has not finished yet. Call request_review again (same arguments) to keep waiting.",
191
+ };
192
+ }
193
+ const b = this.active;
194
+ if (!b || b.id !== batchId) {
195
+ return {
196
+ status: "keep_waiting",
197
+ batch_id: batchId,
198
+ message: "The batch was superseded; call request_review again to re-sync.",
199
+ };
200
+ }
201
+ if (b.status === "approved") {
202
+ return {
203
+ status: "approved",
204
+ batch_id: b.id,
205
+ commit_sha: b.commitSha,
206
+ commit_message: b.commitMessage,
207
+ };
208
+ }
209
+ return {
210
+ status: "changes_requested",
211
+ batch_id: b.id,
212
+ issue: b.issue ?? "(no description provided)",
213
+ category: b.category ?? "code",
214
+ };
215
+ }
216
+ /**
217
+ * Block until the current batch has a verdict — used by the `await-verdict`
218
+ * poll command after the developer already submitted via request_review
219
+ * (whose MCP call may have been cut off by a client timeout). Does not
220
+ * re-snapshot the tree or resubmit.
221
+ */
222
+ async awaitVerdict() {
223
+ const b = this.active;
224
+ if (!b) {
225
+ return {
226
+ status: "no_active_batch",
227
+ message: "No batch is awaiting a verdict. Submit one with the request_review tool first.",
228
+ };
229
+ }
230
+ return this.waitForVerdict(b.id);
231
+ }
232
+ async signalComplete(note) {
233
+ const release = await this.mutex.lock();
234
+ try {
235
+ this.complete = true;
236
+ this.notify();
237
+ this.log(`developer signalled workflow complete${note ? `: ${note}` : ""}`);
238
+ return {
239
+ status: "ok",
240
+ message: "Workflow marked complete. The reviewer will be told to stop.",
241
+ };
242
+ }
243
+ finally {
244
+ release();
245
+ }
246
+ }
247
+ // ---- reviewer side ----
248
+ /** Block until a batch is queued for review (or the workflow completes / window elapses). */
249
+ async getNextReview() {
250
+ // Fast path / idempotent re-poll under the lock.
251
+ const tryClaim = async () => {
252
+ const release = await this.mutex.lock();
253
+ try {
254
+ if (this.active && this.active.status === "queued") {
255
+ this.active.status = "in_review";
256
+ this.log(`reviewer picked up ${this.active.id}`);
257
+ }
258
+ if (this.active && this.active.status === "in_review") {
259
+ const b = this.active;
260
+ return {
261
+ status: "review_ready",
262
+ batch_id: b.id,
263
+ summary: b.summary,
264
+ commit_message: b.commitMessage,
265
+ diff: b.diff,
266
+ diff_stat: b.diffStat,
267
+ truncated: b.truncated,
268
+ };
269
+ }
270
+ if (this.complete && !this.pendingForReview()) {
271
+ return {
272
+ status: "workflow_complete",
273
+ message: "The developer signalled the task is finished. Nothing left to review.",
274
+ };
275
+ }
276
+ return null;
277
+ }
278
+ finally {
279
+ release();
280
+ }
281
+ };
282
+ const immediate = await tryClaim();
283
+ if (immediate)
284
+ return immediate;
285
+ const ready = await this.waitUntil(() => this.pendingForReview() || this.complete, this.opts.pollMs);
286
+ if (!ready) {
287
+ return {
288
+ status: "keep_waiting",
289
+ message: "No batch is ready yet. Call get_next_review again to keep waiting.",
290
+ };
291
+ }
292
+ const claimed = await tryClaim();
293
+ return (claimed ?? {
294
+ status: "keep_waiting",
295
+ message: "No batch is ready yet. Call get_next_review again to keep waiting.",
296
+ });
297
+ }
298
+ /** Record the verdict for the in-review batch and (on approval) commit it. */
299
+ async submitReview(batchId, verdict, issue, category) {
300
+ const release = await this.mutex.lock();
301
+ try {
302
+ const b = this.active;
303
+ if (!b || b.status !== "in_review") {
304
+ return {
305
+ status: "error",
306
+ message: "There is no batch currently in review. Call get_next_review to receive a batch first.",
307
+ };
308
+ }
309
+ if (b.id !== batchId) {
310
+ return {
311
+ status: "error",
312
+ message: `batch_id mismatch: the batch in review is '${b.id}', not '${batchId}'. Use the batch_id from get_next_review.`,
313
+ };
314
+ }
315
+ if (verdict === "approved") {
316
+ if (!this.git) {
317
+ return { status: "error", message: "No repository configured; cannot commit." };
318
+ }
319
+ let sha;
320
+ try {
321
+ sha = await this.git.commit(b.commitMessage);
322
+ }
323
+ catch (err) {
324
+ const detail = err instanceof GitError ? (err.stderr ?? err.message) : String(err);
325
+ this.log(`commit FAILED for ${b.id}: ${detail}`);
326
+ // Keep the batch in review so the reviewer can retry or request changes.
327
+ return {
328
+ status: "error",
329
+ message: `Approval recorded but the commit failed (the batch is still in review). ` +
330
+ `Fix the cause or submit changes_requested instead. git said: ${detail}`,
331
+ };
332
+ }
333
+ b.status = "approved";
334
+ b.commitSha = sha;
335
+ b.resolvedAt = Date.now();
336
+ this.completedCount += 1;
337
+ this.lastResolved = b;
338
+ this.log(`reviewer APPROVED ${b.id} → committed ${sha.slice(0, 8)}`);
339
+ this.notify();
340
+ return { status: "recorded", verdict: "approved", batch_id: b.id, commit_sha: sha };
341
+ }
342
+ // changes_requested
343
+ if (!issue || issue.trim() === "") {
344
+ return {
345
+ status: "error",
346
+ message: "changes_requested requires a non-empty 'issue' describing what to fix.",
347
+ };
348
+ }
349
+ b.status = "changes_requested";
350
+ b.issue = issue;
351
+ b.category = category ?? "code";
352
+ b.resolvedAt = Date.now();
353
+ this.lastResolved = b;
354
+ this.log(`reviewer requested changes on ${b.id} (${b.category}): ${issue}`);
355
+ this.notify();
356
+ return { status: "recorded", verdict: "changes_requested", batch_id: b.id };
357
+ }
358
+ finally {
359
+ release();
360
+ }
361
+ }
362
+ // ---- shared ----
363
+ status() {
364
+ const phase = !this.active
365
+ ? "idle"
366
+ : this.active.status === "queued"
367
+ ? "awaiting_review"
368
+ : this.active.status === "in_review"
369
+ ? "reviewing"
370
+ : "idle"; // a resolved batch sitting until the next submit
371
+ return {
372
+ phase,
373
+ complete: this.complete,
374
+ active_batch: this.active
375
+ ? {
376
+ batch_id: this.active.id,
377
+ status: this.active.status,
378
+ summary: this.active.summary,
379
+ commit_message: this.active.commitMessage,
380
+ }
381
+ : null,
382
+ last_verdict: this.lastResolved
383
+ ? {
384
+ batch_id: this.lastResolved.id,
385
+ status: this.lastResolved.status,
386
+ issue: this.lastResolved.issue,
387
+ category: this.lastResolved.category,
388
+ commit_sha: this.lastResolved.commitSha,
389
+ }
390
+ : null,
391
+ completed_batches: this.completedCount,
392
+ repo: this.git ? this.git.dir : null,
393
+ };
394
+ }
395
+ }
396
+ //# sourceMappingURL=orchestrator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"orchestrator.js","sourceRoot":"","sources":["../src/orchestrator.ts"],"names":[],"mappings":"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"}