@effect-agent/pr-review 0.1.0-beta.28 → 0.1.0-beta.29

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 (52) hide show
  1. package/README.md +9 -204
  2. package/dist/index.d.mts +87 -914
  3. package/dist/index.mjs +163 -71
  4. package/dist/index.mjs.map +1 -1
  5. package/package.json +3 -18
  6. package/src/index.ts +1 -25
  7. package/src/review.ts +212 -0
  8. package/dist/action.d.mts +0 -215
  9. package/dist/action.mjs +0 -505
  10. package/dist/action.mjs.map +0 -1
  11. package/dist/cli.d.mts +0 -1
  12. package/dist/cli.mjs +0 -106
  13. package/dist/cli.mjs.map +0 -1
  14. package/dist/fan-out-C3yG1cx3.d.mts +0 -1526
  15. package/dist/github-CCuLgyqb.mjs +0 -3437
  16. package/dist/github-CCuLgyqb.mjs.map +0 -1
  17. package/dist/logging-Q4j0oub-.mjs +0 -75
  18. package/dist/logging-Q4j0oub-.mjs.map +0 -1
  19. package/dist/providers-Br9FRn7j.mjs +0 -1349
  20. package/dist/providers-Br9FRn7j.mjs.map +0 -1
  21. package/dist/testing.d.mts +0 -86
  22. package/dist/testing.mjs +0 -184
  23. package/dist/testing.mjs.map +0 -1
  24. package/src/action.ts +0 -906
  25. package/src/cli.ts +0 -235
  26. package/src/internal/action-entry.ts +0 -45
  27. package/src/internal/adjudication.ts +0 -415
  28. package/src/internal/anchors.ts +0 -20
  29. package/src/internal/coverage.ts +0 -357
  30. package/src/internal/diff.ts +0 -193
  31. package/src/internal/effort.ts +0 -86
  32. package/src/internal/factory.ts +0 -357
  33. package/src/internal/fan-out-scripted.ts +0 -77
  34. package/src/internal/fan-out.ts +0 -1148
  35. package/src/internal/fingerprint.ts +0 -89
  36. package/src/internal/fixtures.ts +0 -148
  37. package/src/internal/github-env.ts +0 -164
  38. package/src/internal/github.ts +0 -1218
  39. package/src/internal/ignore.ts +0 -88
  40. package/src/internal/logging.ts +0 -124
  41. package/src/internal/profiles.ts +0 -91
  42. package/src/internal/progress.ts +0 -433
  43. package/src/internal/providers.ts +0 -133
  44. package/src/internal/render.ts +0 -819
  45. package/src/internal/retirement.ts +0 -337
  46. package/src/internal/review-agent.ts +0 -543
  47. package/src/internal/review-state.ts +0 -782
  48. package/src/internal/review-units.ts +0 -493
  49. package/src/internal/run.ts +0 -611
  50. package/src/internal/scripted.ts +0 -108
  51. package/src/internal/source.ts +0 -110
  52. package/src/testing.ts +0 -8
package/dist/action.mjs DELETED
@@ -1,505 +0,0 @@
1
- import { Cr as normalizeRepoRelativePath, Dn as selectReviewRange, En as isLineageAncestor, Mn as validateReviewState, Nn as webCryptoReviewStateAuthenticatorLayer, On as selectedPullRequestSourceLayer, St as splitCarriedScope, Tn as fullReviewSelection, Yt as retireStaleReviews, a as PriorReviews, bn as concernIdentity, br as PullRequestSource, in as ReviewHeadComparison, jn as unavailableReviewStateAuthenticatorLayer, jt as collectReviewAdjudications, ln as ReviewStateAuthenticator, rn as ReviewExecutionContext, vn as adjudicationIdentity, xn as findingIdentity } from "./github-CCuLgyqb.mjs";
2
- import { D as PrReview, J as parseEffortPosition, K as InvalidEffortInput, N as fanOutReviewBudgetLimits, P as reviewBudgetLimits, _ as readGitHubEvent, b as ReviewProgressReporter, c as anthropicClientLayer, d as makeOpenAiReviewModel, f as openAiClientLayer, g as gitHubReviewLayers, l as describeReviewModel, n as DEFAULT_PROVIDER, p as validateReviewServiceTier, u as makeAnthropicReviewModel, v as resolveReviewTarget } from "./providers-Br9FRn7j.mjs";
3
- import { n as compactReviewLoggingLayer } from "./logging-Q4j0oub-.mjs";
4
- import { Config, Console, Effect, FileSystem, Layer, Option, Redacted, Schema } from "effect";
5
- import { BudgetExceeded, UsageBudgetLimits } from "effect-agent";
6
- import { FetchHttpClient } from "effect/unstable/http";
7
- import { NodeRuntime, NodeServices } from "@effect/platform-node";
8
- //#region src/action.ts
9
- const ReviewCheckConclusion = Schema.Literals([
10
- "success",
11
- "blocking",
12
- "incomplete"
13
- ]);
14
- /** The host-derived blocking or incomplete conclusion failed the check. */
15
- var ReviewGateFailed = class extends Schema.TaggedError()("ReviewGateFailed", {
16
- conclusion: Schema.Literals(["blocking", "incomplete"]),
17
- reasons: Schema.Array(Schema.NonEmptyString.check(Schema.isMaxLength(1e3))).check(Schema.isMinLength(1))
18
- }) {
19
- get message() {
20
- return `Review check concluded '${this.conclusion}': ${this.reasons.join("; ")}`;
21
- }
22
- };
23
- /** A configured max-duration that cannot bound a run; configuration faults fail loudly. */
24
- var InvalidMaxDurationInput = class extends Schema.TaggedError()("InvalidMaxDurationInput", { minutes: Schema.Int }) {
25
- get message() {
26
- return `Invalid max-duration-minutes '${this.minutes}': expected a positive number of minutes.`;
27
- }
28
- };
29
- /** Read the PR_REVIEW_* input surface (all optional, all defaulted). */
30
- const resolveActionInputs = Effect.fn("resolveActionInputs")(function* () {
31
- const provider = yield* Config.literals(["openai", "anthropic"], "PR_REVIEW_PROVIDER").pipe(Config.withDefault(DEFAULT_PROVIDER));
32
- const model = yield* Config.option(Config.nonEmptyString("PR_REVIEW_MODEL"));
33
- const effortRaw = yield* Config.option(Config.nonEmptyString("PR_REVIEW_EFFORT"));
34
- let effort;
35
- if (Option.isSome(effortRaw)) {
36
- effort = parseEffortPosition(effortRaw.value);
37
- if (effort === void 0) return yield* InvalidEffortInput.make({ input: effortRaw.value });
38
- }
39
- const serviceTier = yield* validateReviewServiceTier(provider, Option.getOrUndefined(yield* Config.option(Config.literals(["fast"], "PR_REVIEW_SERVICE_TIER"))));
40
- const maxDurationMinutes = Option.getOrUndefined(yield* Config.option(Config.int("PR_REVIEW_MAX_DURATION_MINUTES")));
41
- if (maxDurationMinutes !== void 0 && maxDurationMinutes <= 0) return yield* InvalidMaxDurationInput.make({ minutes: maxDurationMinutes });
42
- const post = yield* Config.boolean("PR_REVIEW_POST").pipe(Config.withDefault(true));
43
- const applyVerdict = yield* Config.boolean("PR_REVIEW_APPLY_VERDICT").pipe(Config.withDefault(false));
44
- const fanOut = yield* Config.boolean("PR_REVIEW_FAN_OUT").pipe(Config.withDefault(true));
45
- const guidance = yield* Config.option(Config.nonEmptyString("PR_REVIEW_GUIDANCE"));
46
- const guidanceFile = yield* Config.option(Config.nonEmptyString("PR_REVIEW_GUIDANCE_FILE"));
47
- const ignoreRaw = yield* Config.string("PR_REVIEW_IGNORE").pipe(Config.withDefault(""));
48
- const maxFindings = yield* Config.option(Config.int("PR_REVIEW_MAX_FINDINGS"));
49
- const reviewMode = yield* Config.literals(["incremental", "final"], "PR_REVIEW_MODE").pipe(Config.withDefault("incremental"));
50
- const skipUnchanged = yield* Config.boolean("PR_REVIEW_SKIP_UNCHANGED").pipe(Config.withDefault(true));
51
- const retireStaleReviews = yield* Config.boolean("PR_REVIEW_RETIRE_STALE_REVIEWS").pipe(Config.withDefault(true));
52
- const progressComment = yield* Config.boolean("PR_REVIEW_PROGRESS_COMMENT").pipe(Config.withDefault(true));
53
- return {
54
- provider,
55
- model: Option.getOrUndefined(model),
56
- effort,
57
- serviceTier,
58
- post,
59
- applyVerdict,
60
- fanOut,
61
- guidance: Option.getOrUndefined(guidance),
62
- guidanceFile: Option.getOrUndefined(guidanceFile),
63
- ignore: ignoreRaw.split(",").map((pattern) => pattern.trim()).filter((pattern) => pattern.length > 0),
64
- maxFindings: Option.getOrUndefined(maxFindings),
65
- maxDurationMinutes,
66
- reviewMode,
67
- skipUnchanged,
68
- retireStaleReviews,
69
- progressComment
70
- };
71
- });
72
- /** A guidance file larger than this is refused, never silently truncated. */
73
- const MAX_GUIDANCE_FILE_CHARS = 2e4;
74
- /** A configured guidance file could not be used; configuration faults fail loudly. */
75
- var GuidanceFileUnreadable = class extends Schema.TaggedError()("GuidanceFileUnreadable", {
76
- path: Schema.String,
77
- reason: Schema.String
78
- }) {
79
- get message() {
80
- return `Cannot use guidance file '${this.path}': ${this.reason}`;
81
- }
82
- };
83
- /**
84
- * Resolve the effective review guidance: the committed guidance file (a
85
- * repository-owned review profile) first, with any inline guidance appended.
86
- * A configured-but-unreadable file fails typed — a review silently running
87
- * without its profile would be worse than a red job.
88
- */
89
- const resolveGuidance = Effect.fn("resolveGuidance")(function* (inputs) {
90
- const filePath = inputs.guidanceFile;
91
- if (filePath === void 0) return inputs.guidance;
92
- const relative = yield* normalizeRepoRelativePath(filePath).pipe(Effect.mapError((violation) => GuidanceFileUnreadable.make({
93
- path: filePath,
94
- reason: violation.reason
95
- })));
96
- const fs = yield* FileSystem.FileSystem;
97
- const unreadable = (error) => GuidanceFileUnreadable.make({
98
- path: relative,
99
- reason: `${error._tag}: ${error.message}`.slice(0, 2048)
100
- });
101
- const stat = yield* fs.stat(relative).pipe(Effect.mapError(unreadable));
102
- const oversized = GuidanceFileUnreadable.make({
103
- path: relative,
104
- reason: `File is larger than the ${MAX_GUIDANCE_FILE_CHARS}-character guidance bound.`
105
- });
106
- if (stat.size > BigInt(2e4) * 4n) return yield* oversized;
107
- const content = yield* fs.readFileString(relative).pipe(Effect.mapError(unreadable));
108
- if (content.length > 2e4) return yield* oversized;
109
- const combined = [content.trim(), inputs.guidance ?? ""].filter((part) => part.length > 0).join("\n");
110
- return combined.length > 0 ? combined : void 0;
111
- });
112
- /** One step-output line; values must be single-line by construction. */
113
- const outputLine = (name, value) => `${name}=${value.replaceAll("\n", " ").slice(0, 1e3)}\n`;
114
- /** Append step outputs to GITHUB_OUTPUT when present (no-op locally). */
115
- const writeActionOutputs = Effect.fn("writeActionOutputs")(function* (entries) {
116
- const outputPath = yield* Config.string("GITHUB_OUTPUT").pipe(Config.withDefault(""));
117
- if (outputPath === "") return;
118
- yield* (yield* FileSystem.FileSystem).writeFileString(outputPath, entries.map(([name, value]) => outputLine(name, value)).join(""), { flag: "a" });
119
- });
120
- /** Append markdown to the GITHUB_STEP_SUMMARY report when present (no-op locally). */
121
- const writeStepSummary = Effect.fn("writeStepSummary")(function* (lines) {
122
- const summaryPath = yield* Config.string("GITHUB_STEP_SUMMARY").pipe(Config.withDefault(""));
123
- if (summaryPath === "") return;
124
- yield* (yield* FileSystem.FileSystem).writeFileString(summaryPath, `${lines.join("\n")}\n`, { flag: "a" });
125
- });
126
- const outcomeOutputs = (outcome, conclusion) => [
127
- ["skipped", "false"],
128
- ["conclusion", conclusion],
129
- ["verdict", outcome.review.verdict],
130
- ["input-coverage", outcome.inputCoverage.status],
131
- ["review-assurance", outcome.assurance.status],
132
- ["review-mode", outcome.reviewMode ?? "full"],
133
- ["review-reason", outcome.reviewReason ?? "direct full review"],
134
- ["inline-comments", String(outcome.plan.comments.length)],
135
- ["demoted-findings", String(outcome.plan.demoted.length)],
136
- ["concerns", String(outcome.review.concerns?.length ?? 0)],
137
- ["unreviewed-paths", String(outcome.unreviewedPaths.length)],
138
- ...outcome.usage === void 0 ? [] : [["input-tokens", String(outcome.usage.inputTokens)], ["output-tokens", String(outcome.usage.outputTokens)]],
139
- ["review-url", outcome.published?.url ?? ""]
140
- ];
141
- const outcomeSummary = (outcome, modelLabel, conclusion) => {
142
- const scope = splitCarriedScope(outcome);
143
- return [
144
- "### Pull-request review",
145
- `- Check conclusion: **${conclusion}**`,
146
- `- Verdict: **${outcome.review.verdict}**`,
147
- `- Input coverage: **${outcome.inputCoverage.status}** · scope: ${outcome.reviewMode ?? "full"}`,
148
- `- Review assurance: **${outcome.assurance.status}** · general discovery ${outcome.assurance.completedGeneralDiscoveryPasses}/${outcome.assurance.requiredGeneralDiscoveryPasses} · specialist ${outcome.assurance.completedSpecialistPasses}/${outcome.assurance.requiredSpecialistPasses} · verification ${outcome.assurance.completedVerificationPasses}/${outcome.assurance.requiredVerificationPasses}`,
149
- `- Inline comments: ${outcome.plan.comments.length} · demoted findings: ${outcome.plan.demoted.length} · concerns: ${outcome.review.concerns?.length ?? 0}`,
150
- ...scope.retryablePaths.length === 0 ? [] : [`- Carried forward: ${scope.retryablePaths.length} unreviewed path(s) retried automatically on the next run (reviewer-side gap, not a code defect)`],
151
- ...scope.undiffablePaths.length === 0 ? [] : [`- Unreviewable: ${scope.undiffablePaths.length} path(s) with no reviewable diff (binary or oversized) — remove them from the pull request or exclude them with ignore globs`],
152
- ...modelLabel === void 0 ? [] : [`- Model: \`${modelLabel}\``],
153
- ...outcome.usage === void 0 ? [] : [`- Tokens: ${outcome.usage.inputTokens} in / ${outcome.usage.outputTokens} out`],
154
- ...outcome.published === void 0 ? ["- Dry run: nothing posted"] : [`- Posted: ${outcome.published.url}`]
155
- ];
156
- };
157
- const skip = (reason) => Effect.gen(function* () {
158
- yield* Console.log(`Skipping review: ${reason}`);
159
- yield* writeActionOutputs([["skipped", "true"], ["skip-reason", reason]]);
160
- yield* writeStepSummary(["### Pull-request review skipped", `- Reason: ${reason}`]);
161
- return {
162
- _tag: "Skipped",
163
- reason
164
- };
165
- });
166
- /** The Actions run URL for the review footer, or undefined outside Actions. */
167
- const resolveRunUrl = Effect.fn("resolveRunUrl")(function* () {
168
- const runId = yield* Config.string("GITHUB_RUN_ID").pipe(Config.withDefault(""));
169
- const repository = yield* Config.string("GITHUB_REPOSITORY").pipe(Config.withDefault(""));
170
- if (runId === "" || repository === "") return void 0;
171
- return `${yield* Config.string("GITHUB_SERVER_URL").pipe(Config.withDefault("https://github.com"))}/${repository}/actions/runs/${runId}`;
172
- });
173
- const blockingReasons = (input) => [...input.findings.filter((finding) => finding.severity === "blocking").map((finding) => `blocking finding: ${finding.title}`), ...input.concerns.filter((concern) => concern.severity === "blocking").map((concern) => `blocking concern: ${concern.title}`)];
174
- /**
175
- * Host-derived check conclusion; model verdict prose cannot weaken it.
176
- *
177
- * Blocking code findings outrank machinery gaps — they are the actionable
178
- * signal. A retryable machinery gap (failed passes, capacity overflow)
179
- * concludes `incomplete` with reasons that explicitly say the failure is
180
- * reviewer-side uncertainty carried forward for retry, never an invitation to
181
- * change code. Undiffable files are the deliberate exception: no retry can
182
- * settle them, so their reason instructs removal or ignore globs instead of
183
- * promising an automatic retry. The flat reviewer's constant `unverified`
184
- * assurance is not a gap.
185
- */
186
- const concludeReviewOutcome = (outcome) => {
187
- const machinery = [];
188
- if (outcome.inputCoverage.status === "incomplete" || outcome.assurance.status === "incomplete") {
189
- const scope = splitCarriedScope(outcome);
190
- if (scope.retryableGap) machinery.push(scope.retryablePaths.length > 0 ? `review infrastructure did not settle — a reviewer-side gap, not a code defect; ${scope.retryablePaths.length} path(s) are carried forward and retried automatically on the next run` : "review infrastructure did not settle — a reviewer-side gap, not a code defect");
191
- if (scope.undiffablePaths.length > 0) machinery.push(`${scope.undiffablePaths.length} path(s) have no reviewable diff (binary or oversized) and no retry can settle them — remove them from the pull request or exclude them with ignore globs`);
192
- if (outcome.inputCoverage.status === "incomplete") machinery.push(...outcome.inputCoverage.reasons);
193
- if (outcome.assurance.status === "incomplete") machinery.push(...outcome.assurance.reasons);
194
- }
195
- const blocking = blockingReasons({
196
- findings: outcome.activeFindings,
197
- concerns: outcome.activeConcerns
198
- });
199
- if (blocking.length > 0) return {
200
- conclusion: "blocking",
201
- reasons: [...blocking, ...machinery]
202
- };
203
- if (machinery.length > 0) return {
204
- conclusion: "incomplete",
205
- reasons: machinery
206
- };
207
- return {
208
- conclusion: "success",
209
- reasons: []
210
- };
211
- };
212
- const concludeReviewState = (state, adjudicated) => {
213
- const reasons = blockingReasons({
214
- findings: state.unresolvedFindings.filter((finding) => !adjudicated.has(findingIdentity(finding))),
215
- concerns: state.unresolvedConcerns.filter((concern) => !adjudicated.has(concernIdentity(concern)))
216
- });
217
- return reasons.length > 0 ? {
218
- conclusion: "blocking",
219
- reasons
220
- } : {
221
- conclusion: "success",
222
- reasons: []
223
- };
224
- };
225
- const skipCoveredReview = Effect.fn("skipCoveredReview")(function* (input) {
226
- const adjudications = yield* collectReviewAdjudications(input.state.adjudications ?? []);
227
- const result = concludeReviewState(input.state, new Set(adjudications.map(adjudicationIdentity)));
228
- yield* Console.log(`Skipping review of ${input.repository}#${input.pullRequestNumber}: ${input.reason}.`);
229
- yield* writeActionOutputs([
230
- ["skipped", "true"],
231
- ["skip-reason", input.reason],
232
- ["conclusion", result.conclusion],
233
- ["input-coverage", "complete"],
234
- ["review-assurance", "settled"],
235
- ["review-mode", "incremental"]
236
- ]);
237
- yield* writeStepSummary([
238
- "### Pull-request review skipped",
239
- `- Reason: ${input.reason}`,
240
- `- Preserved check conclusion: **${result.conclusion}**`
241
- ]);
242
- if (result.conclusion === "blocking") return yield* ReviewGateFailed.make({
243
- conclusion: "blocking",
244
- reasons: result.reasons
245
- });
246
- return {
247
- _tag: "Skipped",
248
- reason: input.reason
249
- };
250
- });
251
- /**
252
- * Harness one already-built reviewer inside the Actions environment: resolve
253
- * the target from the event, provide the GitHub source/publisher/prior
254
- * reviews, validate/select bounded continuity scope, write step outputs, and apply
255
- * the host-derived coverage/blocker gate. Draft and non-PR skips are values;
256
- * an unchanged reviewed head preserves and enforces its stored conclusion. The reviewer's
257
- * remaining requirements — its model client, any extra tool handlers — stay
258
- * visible in `R` for the caller.
259
- */
260
- const runReviewAction = (reviewer, options = {}) => Effect.gen(function* () {
261
- const event = yield* readGitHubEvent();
262
- if (Option.isSome(event)) {
263
- if (event.value.pull_request === void 0) return yield* skip("the triggering event carries no pull request");
264
- if (event.value.pull_request.draft === true) return yield* skip("the pull request is a draft");
265
- }
266
- const target = yield* resolveReviewTarget({});
267
- return yield* Effect.gen(function* () {
268
- let selection;
269
- if (reviewer.profileFingerprint !== void 0) {
270
- const [snapshot, profileFingerprint, currentFingerprint] = yield* Effect.all([
271
- reviewer.snapshot,
272
- reviewer.profileFingerprint,
273
- reviewer.fingerprint.pipe(Effect.map((fingerprint) => fingerprint), Effect.orElseSucceed(() => void 0))
274
- ]);
275
- const { metadata, files: fullFiles } = snapshot;
276
- const history = options.priorReviews ?? (yield* PriorReviews);
277
- const stateAuthenticator = yield* ReviewStateAuthenticator;
278
- const recovered = stateAuthenticator.status === "unavailable" ? {
279
- state: void 0,
280
- failure: stateAuthenticator.unavailableReason ?? "an authenticated review-state secret is not configured"
281
- } : yield* history.latestState.pipe(Effect.match({
282
- onFailure: (failure) => ({
283
- state: void 0,
284
- failure: failure.reason
285
- }),
286
- onSuccess: (state) => ({
287
- state: Option.getOrUndefined(state),
288
- failure: void 0
289
- })
290
- }));
291
- const equivalentPatchState = (options.reviewMode ?? "incremental") === "incremental" && options.skipUnchanged !== false && recovered.state !== void 0 && recovered.state.settled && currentFingerprint !== void 0 && validateReviewState(recovered.state, metadata, profileFingerprint) === void 0 && recovered.state.settledScopeFingerprint === currentFingerprint ? recovered.state : void 0;
292
- if (equivalentPatchState !== void 0) return yield* skipCoveredReview({
293
- repository: target.repository,
294
- pullRequestNumber: target.number,
295
- reason: equivalentPatchState.reviewedHeadSha === metadata.headSha ? "the current head already has settled stored review assurance" : "the effective pull-request patch is unchanged since the last settled review",
296
- state: equivalentPatchState
297
- });
298
- let comparison;
299
- let baseComparison;
300
- let contentComparison;
301
- let contentComparisonFailure;
302
- if ((options.reviewMode ?? "incremental") === "incremental" && recovered.state !== void 0) {
303
- if (recovered.state.reviewedHeadSha === metadata.headSha) comparison = ReviewHeadComparison.make({
304
- status: "identical",
305
- baseSha: metadata.headSha,
306
- headSha: metadata.headSha,
307
- mergeBaseSha: metadata.headSha,
308
- files: [],
309
- truncated: false
310
- });
311
- else {
312
- comparison = yield* history.compareHeads(recovered.state.reviewedHeadSha, metadata.headSha).pipe(Effect.orElseSucceed(() => void 0));
313
- if (comparison !== void 0 && reviewer.filterFiles !== void 0) comparison = ReviewHeadComparison.make({
314
- ...comparison,
315
- files: reviewer.filterFiles(comparison.files)
316
- });
317
- }
318
- if (metadata.baseSha !== void 0 && recovered.state.baseSha !== metadata.baseSha) {
319
- baseComparison = yield* history.compareHeads(recovered.state.baseSha, metadata.baseSha).pipe(Effect.orElseSucceed(() => void 0));
320
- if (baseComparison !== void 0 && reviewer.filterFiles !== void 0) baseComparison = ReviewHeadComparison.make({
321
- ...baseComparison,
322
- files: reviewer.filterFiles(baseComparison.files)
323
- });
324
- }
325
- if (recovered.state.reviewedHeadSha !== metadata.headSha && (comparison === void 0 || !isLineageAncestor(comparison, recovered.state, metadata.headSha))) {
326
- const comparisonPaths = new Set(fullFiles.flatMap((file) => file.previousPath === void 0 ? [file.path] : [file.path, file.previousPath]));
327
- for (const finding of recovered.state.unresolvedFindings) comparisonPaths.add(finding.path);
328
- for (const concern of recovered.state.unresolvedConcerns) for (const path of concern.evidencePaths ?? []) comparisonPaths.add(path);
329
- for (const path of recovered.state.unreviewedPaths) comparisonPaths.add(path);
330
- const treeResult = yield* history.compareTrees(recovered.state.reviewedHeadSha, metadata.headSha, [...comparisonPaths]).pipe(Effect.match({
331
- onFailure: (failure) => ({
332
- comparison: void 0,
333
- failure: failure.reason
334
- }),
335
- onSuccess: (treeComparison) => ({
336
- comparison: treeComparison,
337
- failure: void 0
338
- })
339
- }));
340
- contentComparison = treeResult.comparison;
341
- contentComparisonFailure = treeResult.failure;
342
- }
343
- }
344
- selection = {
345
- ...selectReviewRange({
346
- requestedMode: options.reviewMode ?? "incremental",
347
- current: metadata,
348
- fullFiles,
349
- profileFingerprint,
350
- priorState: recovered.state,
351
- comparison,
352
- baseComparison,
353
- contentComparison,
354
- contentComparisonFailure,
355
- lookupFailure: recovered.failure
356
- }),
357
- stateAuthenticator
358
- };
359
- if (options.skipUnchanged !== false && selection.mode === "incremental" && selection.files.length === 0 && selection.priorState !== void 0 && selection.priorState.settled) return yield* skipCoveredReview({
360
- repository: target.repository,
361
- pullRequestNumber: target.number,
362
- reason: "no changed review scope since the last settled review head",
363
- state: selection.priorState
364
- });
365
- }
366
- const executionContext = selection ?? (yield* Effect.gen(function* () {
367
- const source = yield* PullRequestSource;
368
- const [metadata, files] = yield* Effect.all([source.metadata, source.changedFiles]);
369
- return fullReviewSelection({
370
- reason: "explicit custom-reviewer full review without continuity selection",
371
- files,
372
- totalFiles: metadata.totalChangedFiles
373
- });
374
- }));
375
- yield* Console.log(`Reviewing ${target.repository}#${target.number} (${options.post === false ? "dry run" : "posting"})...`);
376
- const runUrl = yield* resolveRunUrl();
377
- const progress = options.progressComment === true && options.post !== false ? Option.some(yield* ReviewProgressReporter) : Option.none();
378
- if (Option.isSome(progress)) {
379
- const headMetadata = yield* (yield* PullRequestSource).metadata.pipe(Effect.orElseSucceed(() => void 0));
380
- yield* progress.value.begin({
381
- headSha: headMetadata?.headSha,
382
- reviewMode: executionContext.mode,
383
- reviewReason: executionContext.reason,
384
- filesInScope: executionContext.files.length,
385
- modelLabel: options.modelLabel,
386
- runUrl
387
- });
388
- }
389
- const runReview = reviewer.run({
390
- post: options.post ?? true,
391
- runUrl
392
- });
393
- const reviewEffect = Option.isSome(progress) ? runReview.pipe(Effect.tapCause(() => progress.value.settle({
394
- outcome: "failed",
395
- runUrl,
396
- modelLabel: options.modelLabel
397
- }))) : runReview;
398
- const executionLayer = Layer.merge(Layer.succeed(ReviewExecutionContext)(executionContext), selectedPullRequestSourceLayer(executionContext));
399
- const outcome = yield* reviewEffect.pipe(Effect.provide(executionLayer));
400
- yield* Console.log(`Review finished in ${outcome.turns} turn(s): verdict ${outcome.review.verdict}, ${outcome.plan.comments.length} inline comment(s), ${outcome.plan.demoted.length} demoted finding(s).`);
401
- if (outcome.published !== void 0) {
402
- yield* Console.log(`Posted ${outcome.published.event} review: ${outcome.published.url}`);
403
- if (options.retireStaleReviews !== false && outcome.state !== void 0) if (outcome.published.authorNodeId === null || outcome.published.submittedAt === null) yield* Console.warn("Skipping stale-review retirement because GitHub did not return the posted review's actor and submission time.");
404
- else {
405
- const report = yield* retireStaleReviews({
406
- currentReviewId: outcome.published.reviewId,
407
- currentReviewUrl: outcome.published.url,
408
- currentAuthorNodeId: outcome.published.authorNodeId,
409
- currentSubmittedAt: outcome.published.submittedAt,
410
- currentState: outcome.state
411
- });
412
- yield* Console.log(`Review retirement: ${report.reviewsRetired} prior review(s), ${report.findingsResolved} resolved finding(s), ${report.commentsMinimized} minimized inline comment(s), ${report.failures} failure(s).`);
413
- }
414
- }
415
- const check = concludeReviewOutcome(outcome);
416
- if (Option.isSome(progress)) yield* progress.value.settle({
417
- outcome: "reviewed",
418
- conclusion: check.conclusion,
419
- verdict: outcome.review.verdict,
420
- inlineComments: outcome.plan.comments.length,
421
- reviewUrl: outcome.published?.url,
422
- runUrl,
423
- modelLabel: options.modelLabel
424
- });
425
- yield* writeActionOutputs(outcomeOutputs(outcome, check.conclusion));
426
- yield* writeStepSummary(outcomeSummary(outcome, options.modelLabel, check.conclusion));
427
- if (check.conclusion !== "success") return yield* ReviewGateFailed.make({
428
- conclusion: check.conclusion,
429
- reasons: check.reasons
430
- });
431
- return {
432
- _tag: "Completed",
433
- outcome
434
- };
435
- }).pipe(Effect.provide(gitHubReviewLayers(target)));
436
- });
437
- /**
438
- * The packaged, environment-driven action program: inputs from PR_REVIEW_*,
439
- * reviewer built from the packaged factory, provider client from the
440
- * matching credential environment variable.
441
- */
442
- const reviewActionProgram = Effect.gen(function* () {
443
- const inputs = yield* resolveActionInputs();
444
- const stateSecret = Option.map(yield* Config.option(Config.nonEmptyString("PR_REVIEW_STATE_SECRET")), Redacted.make);
445
- const stateAuthenticatorLayer = Option.match(stateSecret, {
446
- onNone: () => unavailableReviewStateAuthenticatorLayer("an authenticated review-state secret is not configured"),
447
- onSome: webCryptoReviewStateAuthenticatorLayer
448
- });
449
- const guidance = yield* resolveGuidance(inputs);
450
- const modelLabel = describeReviewModel(inputs.provider, inputs.model, inputs.effort, inputs.serviceTier);
451
- const defaults = inputs.fanOut ? fanOutReviewBudgetLimits : reviewBudgetLimits;
452
- const budget = inputs.maxDurationMinutes === void 0 ? defaults : UsageBudgetLimits.make({
453
- ...defaults,
454
- maxDurationMillis: inputs.maxDurationMinutes * 6e4
455
- });
456
- const shared = {
457
- guidance,
458
- ignore: inputs.ignore,
459
- maxFindings: inputs.maxFindings,
460
- applyVerdict: inputs.applyVerdict,
461
- modelLabel,
462
- budget
463
- };
464
- const harness = {
465
- post: inputs.post,
466
- skipUnchanged: inputs.skipUnchanged,
467
- reviewMode: inputs.reviewMode,
468
- retireStaleReviews: inputs.retireStaleReviews,
469
- progressComment: inputs.progressComment,
470
- modelLabel
471
- };
472
- if (inputs.provider === "anthropic") {
473
- const model = makeAnthropicReviewModel(inputs.model, inputs.effort);
474
- const reviewer = inputs.fanOut ? PrReview.makeFanOut({
475
- ...shared,
476
- model
477
- }) : PrReview.make({
478
- ...shared,
479
- model
480
- });
481
- return yield* runReviewAction(reviewer, harness).pipe(Effect.provide(Layer.merge(stateAuthenticatorLayer, anthropicClientLayer)));
482
- }
483
- const model = makeOpenAiReviewModel(inputs.model, inputs.effort, inputs.serviceTier);
484
- const reviewer = inputs.fanOut ? PrReview.makeFanOut({
485
- ...shared,
486
- model
487
- }) : PrReview.make({
488
- ...shared,
489
- model
490
- });
491
- return yield* runReviewAction(reviewer, harness).pipe(Effect.provide(Layer.merge(stateAuthenticatorLayer, openAiClientLayer)));
492
- });
493
- /** Run the packaged action program on Node; the bundled action entrypoint. */
494
- const main = () => NodeRuntime.runMain(reviewActionProgram.pipe(Effect.tapError((error) => Console.error(Schema.is(BudgetExceeded)(error) ? `Budget exceeded: ${error.limit} observed ${error.observedValue}, limit ${error.limitValue}.` : String(error))), Effect.scoped, Effect.provide(Layer.mergeAll(NodeServices.layer, FetchHttpClient.layer, compactReviewLoggingLayer))), { disableErrorReporting: true });
495
- /** The packaged GitHub Actions surface. */
496
- const PrReviewAction = {
497
- inputs: resolveActionInputs,
498
- run: runReviewAction,
499
- program: reviewActionProgram,
500
- main
501
- };
502
- //#endregion
503
- export { GuidanceFileUnreadable, InvalidMaxDurationInput, MAX_GUIDANCE_FILE_CHARS, PrReviewAction, ReviewCheckConclusion, ReviewGateFailed, concludeReviewOutcome, main, resolveActionInputs, resolveGuidance, reviewActionProgram, runReviewAction, writeActionOutputs, writeStepSummary };
504
-
505
- //# sourceMappingURL=action.mjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"action.mjs","names":[],"sources":["../src/action.ts"],"sourcesContent":["import { NodeRuntime, NodeServices } from \"@effect/platform-node\";\nimport { Config, Console, Effect, FileSystem, Layer, Option, Redacted, Schema } from \"effect\";\nimport { BudgetExceeded, UsageBudgetLimits } from \"effect-agent\";\nimport { FetchHttpClient } from \"effect/unstable/http\";\n\nimport { collectReviewAdjudications } from \"./internal/adjudication.ts\";\nimport { splitCarriedScope } from \"./internal/coverage.ts\";\nimport type { ChangedFile } from \"./internal/diff.ts\";\nimport { InvalidEffortInput, parseEffortPosition, type EffortPosition } from \"./internal/effort.ts\";\nimport { PrReview, type RunReviewOptions } from \"./internal/factory.ts\";\nimport { readGitHubEvent, resolveReviewTarget, gitHubReviewLayers } from \"./internal/github-env.ts\";\nimport { PriorReviews } from \"./internal/github.ts\";\nimport { compactReviewLoggingLayer } from \"./internal/logging.ts\";\nimport { ReviewProgressReporter } from \"./internal/progress.ts\";\nimport {\n anthropicClientLayer,\n DEFAULT_PROVIDER,\n describeReviewModel,\n makeAnthropicReviewModel,\n makeOpenAiReviewModel,\n openAiClientLayer,\n validateReviewServiceTier,\n type OpenAiServiceTier,\n type ReviewProvider,\n} from \"./internal/providers.ts\";\nimport { retireStaleReviews } from \"./internal/retirement.ts\";\nimport {\n adjudicationIdentity,\n concernIdentity,\n findingIdentity,\n fullReviewSelection,\n ReviewExecutionContext,\n ReviewHeadComparison,\n ReviewStateAuthenticator,\n type ReviewTreeComparison,\n isLineageAncestor,\n type ReviewMode,\n type ReviewState,\n selectReviewRange,\n selectedPullRequestSourceLayer,\n unavailableReviewStateAuthenticatorLayer,\n validateReviewState,\n webCryptoReviewStateAuthenticatorLayer,\n} from \"./internal/review-state.ts\";\nimport { fanOutReviewBudgetLimits, reviewBudgetLimits } from \"./internal/run.ts\";\nimport type { ReviewRunOutcome } from \"./internal/run.ts\";\nimport {\n normalizeRepoRelativePath,\n PullRequestSource,\n type PullRequestMetadata,\n} from \"./internal/source.ts\";\n\n// ---------------------------------------------------------------------------\n// The GitHub Actions entrypoint (deployment class E: one bounded ephemeral\n// run, no exactly-once posting). Bounded continuity state travels in GitHub\n// review bodies and is validated before reuse. Inputs arrive as\n// PR_REVIEW_* environment variables set by the action manifest; the target\n// pull request comes from the standard Actions event environment. A non-PR\n// or draft event is a typed skip — green job, nothing posted. Publication\n// happens only after the run settles, so a failed or truncated run posts\n// nothing.\n// ---------------------------------------------------------------------------\n\nexport const ReviewCheckConclusion = Schema.Literals([\"success\", \"blocking\", \"incomplete\"]);\nexport type ReviewCheckConclusion = typeof ReviewCheckConclusion.Type;\n\n/** The host-derived blocking or incomplete conclusion failed the check. */\nexport class ReviewGateFailed extends Schema.TaggedError<ReviewGateFailed>()(\"ReviewGateFailed\", {\n conclusion: Schema.Literals([\"blocking\", \"incomplete\"]),\n reasons: Schema.Array(Schema.NonEmptyString.check(Schema.isMaxLength(1_000))).check(\n Schema.isMinLength(1),\n ),\n}) {\n override get message() {\n return `Review check concluded '${this.conclusion}': ${this.reasons.join(\"; \")}`;\n }\n}\n\n/** A configured max-duration that cannot bound a run; configuration faults fail loudly. */\nexport class InvalidMaxDurationInput extends Schema.TaggedError<InvalidMaxDurationInput>()(\n \"InvalidMaxDurationInput\",\n {\n minutes: Schema.Int,\n },\n) {\n override get message() {\n return `Invalid max-duration-minutes '${this.minutes}': expected a positive number of minutes.`;\n }\n}\n\n/** Everything the packaged action reads from its environment. */\nexport interface ResolvedActionInputs {\n readonly provider: ReviewProvider;\n readonly model: string | undefined;\n readonly effort: EffortPosition | undefined;\n readonly serviceTier: OpenAiServiceTier | undefined;\n readonly post: boolean;\n readonly applyVerdict: boolean;\n readonly fanOut: boolean;\n readonly guidance: string | undefined;\n readonly guidanceFile: string | undefined;\n readonly ignore: ReadonlyArray<string>;\n readonly maxFindings: number | undefined;\n readonly maxDurationMinutes: number | undefined;\n readonly reviewMode: ReviewMode;\n readonly skipUnchanged: boolean;\n readonly retireStaleReviews: boolean;\n readonly progressComment: boolean;\n}\n\n/** Read the PR_REVIEW_* input surface (all optional, all defaulted). */\nexport const resolveActionInputs = Effect.fn(\"resolveActionInputs\")(function* () {\n const provider = yield* Config.literals([\"openai\", \"anthropic\"], \"PR_REVIEW_PROVIDER\").pipe(\n Config.withDefault<ReviewProvider>(DEFAULT_PROVIDER),\n );\n const model = yield* Config.option(Config.nonEmptyString(\"PR_REVIEW_MODEL\"));\n const effortRaw = yield* Config.option(Config.nonEmptyString(\"PR_REVIEW_EFFORT\"));\n let effort: EffortPosition | undefined;\n if (Option.isSome(effortRaw)) {\n effort = parseEffortPosition(effortRaw.value);\n if (effort === undefined) {\n return yield* InvalidEffortInput.make({ input: effortRaw.value });\n }\n }\n const serviceTier = yield* validateReviewServiceTier(\n provider,\n Option.getOrUndefined(\n yield* Config.option(Config.literals([\"fast\"], \"PR_REVIEW_SERVICE_TIER\")),\n ),\n );\n const maxDurationMinutes = Option.getOrUndefined(\n yield* Config.option(Config.int(\"PR_REVIEW_MAX_DURATION_MINUTES\")),\n );\n if (maxDurationMinutes !== undefined && maxDurationMinutes <= 0) {\n return yield* InvalidMaxDurationInput.make({ minutes: maxDurationMinutes });\n }\n const post = yield* Config.boolean(\"PR_REVIEW_POST\").pipe(Config.withDefault(true));\n const applyVerdict = yield* Config.boolean(\"PR_REVIEW_APPLY_VERDICT\").pipe(\n Config.withDefault(false),\n );\n const fanOut = yield* Config.boolean(\"PR_REVIEW_FAN_OUT\").pipe(Config.withDefault(true));\n const guidance = yield* Config.option(Config.nonEmptyString(\"PR_REVIEW_GUIDANCE\"));\n const guidanceFile = yield* Config.option(Config.nonEmptyString(\"PR_REVIEW_GUIDANCE_FILE\"));\n const ignoreRaw = yield* Config.string(\"PR_REVIEW_IGNORE\").pipe(Config.withDefault(\"\"));\n const maxFindings = yield* Config.option(Config.int(\"PR_REVIEW_MAX_FINDINGS\"));\n const reviewMode = yield* Config.literals([\"incremental\", \"final\"], \"PR_REVIEW_MODE\").pipe(\n Config.withDefault<ReviewMode>(\"incremental\"),\n );\n const skipUnchanged = yield* Config.boolean(\"PR_REVIEW_SKIP_UNCHANGED\").pipe(\n Config.withDefault(true),\n );\n const retireStaleReviews = yield* Config.boolean(\"PR_REVIEW_RETIRE_STALE_REVIEWS\").pipe(\n Config.withDefault(true),\n );\n const progressComment = yield* Config.boolean(\"PR_REVIEW_PROGRESS_COMMENT\").pipe(\n Config.withDefault(true),\n );\n return {\n provider,\n model: Option.getOrUndefined(model),\n effort,\n serviceTier,\n post,\n applyVerdict,\n fanOut,\n guidance: Option.getOrUndefined(guidance),\n guidanceFile: Option.getOrUndefined(guidanceFile),\n ignore: ignoreRaw\n .split(\",\")\n .map((pattern) => pattern.trim())\n .filter((pattern) => pattern.length > 0),\n maxFindings: Option.getOrUndefined(maxFindings),\n maxDurationMinutes,\n reviewMode,\n skipUnchanged,\n retireStaleReviews,\n progressComment,\n } satisfies ResolvedActionInputs;\n});\n\n/** A guidance file larger than this is refused, never silently truncated. */\nexport const MAX_GUIDANCE_FILE_CHARS = 20_000;\n\n/** A configured guidance file could not be used; configuration faults fail loudly. */\nexport class GuidanceFileUnreadable extends Schema.TaggedError<GuidanceFileUnreadable>()(\n \"GuidanceFileUnreadable\",\n {\n path: Schema.String,\n reason: Schema.String,\n },\n) {\n override get message() {\n return `Cannot use guidance file '${this.path}': ${this.reason}`;\n }\n}\n\n/**\n * Resolve the effective review guidance: the committed guidance file (a\n * repository-owned review profile) first, with any inline guidance appended.\n * A configured-but-unreadable file fails typed — a review silently running\n * without its profile would be worse than a red job.\n */\nexport const resolveGuidance = Effect.fn(\"resolveGuidance\")(function* (inputs: {\n readonly guidance: string | undefined;\n readonly guidanceFile: string | undefined;\n}) {\n const filePath = inputs.guidanceFile;\n if (filePath === undefined) return inputs.guidance;\n // The profile path is operator configuration, but it stays fail-closed\n // like every other path in this package: workspace-relative only, and the\n // size bound is checked before the file is read into memory.\n const relative = yield* normalizeRepoRelativePath(filePath).pipe(\n Effect.mapError((violation) =>\n GuidanceFileUnreadable.make({ path: filePath, reason: violation.reason }),\n ),\n );\n const fs = yield* FileSystem.FileSystem;\n const unreadable = (error: { readonly _tag: string; readonly message: string }) =>\n GuidanceFileUnreadable.make({\n path: relative,\n reason: `${error._tag}: ${error.message}`.slice(0, 2_048),\n });\n const stat = yield* fs.stat(relative).pipe(Effect.mapError(unreadable));\n const oversized = GuidanceFileUnreadable.make({\n path: relative,\n reason: `File is larger than the ${MAX_GUIDANCE_FILE_CHARS}-character guidance bound.`,\n });\n if (stat.size > BigInt(MAX_GUIDANCE_FILE_CHARS) * 4n) {\n return yield* oversized;\n }\n const content = yield* fs.readFileString(relative).pipe(Effect.mapError(unreadable));\n if (content.length > MAX_GUIDANCE_FILE_CHARS) {\n return yield* oversized;\n }\n const combined = [content.trim(), inputs.guidance ?? \"\"]\n .filter((part) => part.length > 0)\n .join(\"\\n\");\n return combined.length > 0 ? combined : undefined;\n});\n\n/** One step-output line; values must be single-line by construction. */\nconst outputLine = (name: string, value: string): string =>\n `${name}=${value.replaceAll(\"\\n\", \" \").slice(0, 1_000)}\\n`;\n\n/** Append step outputs to GITHUB_OUTPUT when present (no-op locally). */\nexport const writeActionOutputs = Effect.fn(\"writeActionOutputs\")(function* (\n entries: ReadonlyArray<readonly [name: string, value: string]>,\n) {\n const outputPath = yield* Config.string(\"GITHUB_OUTPUT\").pipe(Config.withDefault(\"\"));\n if (outputPath === \"\") return;\n const fs = yield* FileSystem.FileSystem;\n yield* fs.writeFileString(\n outputPath,\n entries.map(([name, value]) => outputLine(name, value)).join(\"\"),\n {\n flag: \"a\",\n },\n );\n});\n\n/** Append markdown to the GITHUB_STEP_SUMMARY report when present (no-op locally). */\nexport const writeStepSummary = Effect.fn(\"writeStepSummary\")(function* (\n lines: ReadonlyArray<string>,\n) {\n const summaryPath = yield* Config.string(\"GITHUB_STEP_SUMMARY\").pipe(Config.withDefault(\"\"));\n if (summaryPath === \"\") return;\n const fs = yield* FileSystem.FileSystem;\n yield* fs.writeFileString(summaryPath, `${lines.join(\"\\n\")}\\n`, { flag: \"a\" });\n});\n\nconst outcomeOutputs = (\n outcome: ReviewRunOutcome,\n conclusion: ReviewCheckConclusion,\n): ReadonlyArray<readonly [string, string]> => [\n [\"skipped\", \"false\"],\n [\"conclusion\", conclusion],\n [\"verdict\", outcome.review.verdict],\n [\"input-coverage\", outcome.inputCoverage.status],\n [\"review-assurance\", outcome.assurance.status],\n [\"review-mode\", outcome.reviewMode ?? \"full\"],\n [\"review-reason\", outcome.reviewReason ?? \"direct full review\"],\n [\"inline-comments\", String(outcome.plan.comments.length)],\n [\"demoted-findings\", String(outcome.plan.demoted.length)],\n [\"concerns\", String(outcome.review.concerns?.length ?? 0)],\n [\"unreviewed-paths\", String(outcome.unreviewedPaths.length)],\n ...(outcome.usage === undefined\n ? []\n : ([\n [\"input-tokens\", String(outcome.usage.inputTokens)],\n [\"output-tokens\", String(outcome.usage.outputTokens)],\n ] as const)),\n [\"review-url\", outcome.published?.url ?? \"\"],\n];\n\nconst outcomeSummary = (\n outcome: ReviewRunOutcome,\n modelLabel: string | undefined,\n conclusion: ReviewCheckConclusion,\n): ReadonlyArray<string> => {\n const scope = splitCarriedScope(outcome);\n return [\n \"### Pull-request review\",\n `- Check conclusion: **${conclusion}**`,\n `- Verdict: **${outcome.review.verdict}**`,\n `- Input coverage: **${outcome.inputCoverage.status}** · scope: ${outcome.reviewMode ?? \"full\"}`,\n `- Review assurance: **${outcome.assurance.status}** · general discovery ${outcome.assurance.completedGeneralDiscoveryPasses}/${outcome.assurance.requiredGeneralDiscoveryPasses} · specialist ${outcome.assurance.completedSpecialistPasses}/${outcome.assurance.requiredSpecialistPasses} · verification ${outcome.assurance.completedVerificationPasses}/${outcome.assurance.requiredVerificationPasses}`,\n `- Inline comments: ${outcome.plan.comments.length} · demoted findings: ${outcome.plan.demoted.length} · concerns: ${outcome.review.concerns?.length ?? 0}`,\n ...(scope.retryablePaths.length === 0\n ? []\n : [\n `- Carried forward: ${scope.retryablePaths.length} unreviewed path(s) retried automatically on the next run (reviewer-side gap, not a code defect)`,\n ]),\n ...(scope.undiffablePaths.length === 0\n ? []\n : [\n `- Unreviewable: ${scope.undiffablePaths.length} path(s) with no reviewable diff (binary or oversized) — remove them from the pull request or exclude them with ignore globs`,\n ]),\n ...(modelLabel === undefined ? [] : [`- Model: \\`${modelLabel}\\``]),\n ...(outcome.usage === undefined\n ? []\n : [`- Tokens: ${outcome.usage.inputTokens} in / ${outcome.usage.outputTokens} out`]),\n ...(outcome.published === undefined\n ? [\"- Dry run: nothing posted\"]\n : [`- Posted: ${outcome.published.url}`]),\n ];\n};\n\n/** The result of one action invocation: a typed skip or a settled review. */\nexport type ReviewActionResult =\n | { readonly _tag: \"Skipped\"; readonly reason: string }\n | { readonly _tag: \"Completed\"; readonly outcome: ReviewRunOutcome };\n\nconst skip = (reason: string) =>\n Effect.gen(function* () {\n yield* Console.log(`Skipping review: ${reason}`);\n yield* writeActionOutputs([\n [\"skipped\", \"true\"],\n [\"skip-reason\", reason],\n ]);\n yield* writeStepSummary([\"### Pull-request review skipped\", `- Reason: ${reason}`]);\n return { _tag: \"Skipped\", reason } satisfies ReviewActionResult;\n });\n\n/** The Actions run URL for the review footer, or undefined outside Actions. */\nconst resolveRunUrl = Effect.fn(\"resolveRunUrl\")(function* () {\n const runId = yield* Config.string(\"GITHUB_RUN_ID\").pipe(Config.withDefault(\"\"));\n const repository = yield* Config.string(\"GITHUB_REPOSITORY\").pipe(Config.withDefault(\"\"));\n if (runId === \"\" || repository === \"\") return undefined;\n const server = yield* Config.string(\"GITHUB_SERVER_URL\").pipe(\n Config.withDefault(\"https://github.com\"),\n );\n return `${server}/${repository}/actions/runs/${runId}`;\n});\n\n/**\n * The reviewer surface the action harness drives. `PrReview.make` and\n * `PrReview.makeFanOut` provide the state-selection effects. A fingerprint is\n * skip authority only when a profile fingerprint and authenticated review\n * state bind it to settled assurance.\n */\ninterface HarnessedReviewerBase<E, R> {\n /** The action composition root always supplies the selected run context. */\n readonly run: (\n runOptions?: RunReviewOptions,\n ) => Effect.Effect<ReviewRunOutcome, E, R | ReviewExecutionContext>;\n}\n\nexport type HarnessedReviewer<E, R, FingerprintE, FingerprintR> = HarnessedReviewerBase<E, R> &\n (\n | {\n readonly fingerprint?: undefined;\n readonly profileFingerprint?: undefined;\n readonly snapshot?: undefined;\n readonly filterFiles?: undefined;\n }\n | {\n /** Current effective changeset fingerprint; not standalone skip authority. */\n readonly fingerprint: Effect.Effect<string, FingerprintE, FingerprintR>;\n readonly profileFingerprint: Effect.Effect<string, FingerprintE, FingerprintR>;\n readonly snapshot: Effect.Effect<\n {\n readonly metadata: PullRequestMetadata;\n readonly files: ReadonlyArray<ChangedFile>;\n },\n FingerprintE,\n FingerprintR\n >;\n readonly filterFiles?:\n | ((files: ReadonlyArray<ChangedFile>) => ReadonlyArray<ChangedFile>)\n | undefined;\n }\n );\n\nconst blockingReasons = (input: {\n readonly findings: ReadonlyArray<{ readonly severity: string; readonly title: string }>;\n readonly concerns: ReadonlyArray<{ readonly severity: string; readonly title: string }>;\n}): ReadonlyArray<string> => [\n ...input.findings\n .filter((finding) => finding.severity === \"blocking\")\n .map((finding) => `blocking finding: ${finding.title}`),\n ...input.concerns\n .filter((concern) => concern.severity === \"blocking\")\n .map((concern) => `blocking concern: ${concern.title}`),\n];\n\n/**\n * Host-derived check conclusion; model verdict prose cannot weaken it.\n *\n * Blocking code findings outrank machinery gaps — they are the actionable\n * signal. A retryable machinery gap (failed passes, capacity overflow)\n * concludes `incomplete` with reasons that explicitly say the failure is\n * reviewer-side uncertainty carried forward for retry, never an invitation to\n * change code. Undiffable files are the deliberate exception: no retry can\n * settle them, so their reason instructs removal or ignore globs instead of\n * promising an automatic retry. The flat reviewer's constant `unverified`\n * assurance is not a gap.\n */\nexport const concludeReviewOutcome = (\n outcome: ReviewRunOutcome,\n): {\n readonly conclusion: ReviewCheckConclusion;\n readonly reasons: ReadonlyArray<string>;\n} => {\n const machinery: Array<string> = [];\n if (outcome.inputCoverage.status === \"incomplete\" || outcome.assurance.status === \"incomplete\") {\n const scope = splitCarriedScope(outcome);\n if (scope.retryableGap) {\n machinery.push(\n scope.retryablePaths.length > 0\n ? `review infrastructure did not settle — a reviewer-side gap, not a code defect; ${scope.retryablePaths.length} path(s) are carried forward and retried automatically on the next run`\n : \"review infrastructure did not settle — a reviewer-side gap, not a code defect\",\n );\n }\n if (scope.undiffablePaths.length > 0) {\n machinery.push(\n `${scope.undiffablePaths.length} path(s) have no reviewable diff (binary or oversized) and no retry can settle them — remove them from the pull request or exclude them with ignore globs`,\n );\n }\n if (outcome.inputCoverage.status === \"incomplete\") {\n machinery.push(...outcome.inputCoverage.reasons);\n }\n if (outcome.assurance.status === \"incomplete\") {\n machinery.push(...outcome.assurance.reasons);\n }\n }\n const blocking = blockingReasons({\n findings: outcome.activeFindings,\n concerns: outcome.activeConcerns,\n });\n if (blocking.length > 0) {\n return { conclusion: \"blocking\", reasons: [...blocking, ...machinery] };\n }\n if (machinery.length > 0) return { conclusion: \"incomplete\", reasons: machinery };\n return { conclusion: \"success\", reasons: [] };\n};\n\nconst concludeReviewState = (state: ReviewState, adjudicated: ReadonlySet<string>) => {\n const reasons = blockingReasons({\n findings: state.unresolvedFindings.filter(\n (finding) => !adjudicated.has(findingIdentity(finding)),\n ),\n concerns: state.unresolvedConcerns.filter(\n (concern) => !adjudicated.has(concernIdentity(concern)),\n ),\n });\n return reasons.length > 0\n ? ({ conclusion: \"blocking\", reasons } as const)\n : ({ conclusion: \"success\", reasons: [] } as const);\n};\n\nconst skipCoveredReview = Effect.fn(\"skipCoveredReview\")(function* (input: {\n readonly repository: string;\n readonly pullRequestNumber: number;\n readonly reason: string;\n readonly state: ReviewState;\n}) {\n // A maintainer adjudication must lift a preserved blocking conclusion\n // without a code push, so the skip path re-reads adjudications (fail-open;\n // stored ones survive a listing fault) before enforcing the stored state.\n const adjudications = yield* collectReviewAdjudications(input.state.adjudications ?? []);\n const result = concludeReviewState(input.state, new Set(adjudications.map(adjudicationIdentity)));\n yield* Console.log(\n `Skipping review of ${input.repository}#${input.pullRequestNumber}: ${input.reason}.`,\n );\n yield* writeActionOutputs([\n [\"skipped\", \"true\"],\n [\"skip-reason\", input.reason],\n [\"conclusion\", result.conclusion],\n [\"input-coverage\", \"complete\"],\n [\"review-assurance\", \"settled\"],\n [\"review-mode\", \"incremental\"],\n ]);\n yield* writeStepSummary([\n \"### Pull-request review skipped\",\n `- Reason: ${input.reason}`,\n `- Preserved check conclusion: **${result.conclusion}**`,\n ]);\n if (result.conclusion === \"blocking\") {\n return yield* ReviewGateFailed.make({\n conclusion: \"blocking\",\n reasons: result.reasons,\n });\n }\n return { _tag: \"Skipped\", reason: input.reason } satisfies ReviewActionResult;\n});\n\n/**\n * Harness one already-built reviewer inside the Actions environment: resolve\n * the target from the event, provide the GitHub source/publisher/prior\n * reviews, validate/select bounded continuity scope, write step outputs, and apply\n * the host-derived coverage/blocker gate. Draft and non-PR skips are values;\n * an unchanged reviewed head preserves and enforces its stored conclusion. The reviewer's\n * remaining requirements — its model client, any extra tool handlers — stay\n * visible in `R` for the caller.\n */\nexport const runReviewAction = <E, R, FingerprintE = never, FingerprintR = never>(\n reviewer: HarnessedReviewer<E, R, FingerprintE, FingerprintR>,\n options: {\n readonly post?: boolean | undefined;\n /** Skip model execution when the current head already has complete stored coverage. */\n readonly skipUnchanged?: boolean | undefined;\n /** Incremental by default; `final` deliberately re-reviews the full PR diff. */\n readonly reviewMode?: ReviewMode | undefined;\n /** Model binding descriptor for the Actions step summary. */\n readonly modelLabel?: string | undefined;\n /** Explicit test/custom-host history override; GitHub owns the default adapter. */\n readonly priorReviews?: PriorReviews[\"Service\"] | undefined;\n /** Retire marker-bearing prior reviews after a successful post (default true). */\n readonly retireStaleReviews?: boolean | undefined;\n /**\n * Maintain one sticky \"review in progress\" issue comment, updated in\n * place when the run settles. Default false here for custom-harness\n * compatibility; the packaged action enables it by default. Dry runs\n * (`post: false`) never post progress.\n */\n readonly progressComment?: boolean | undefined;\n } = {},\n) =>\n Effect.gen(function* () {\n const event = yield* readGitHubEvent();\n if (Option.isSome(event)) {\n if (event.value.pull_request === undefined) {\n return yield* skip(\"the triggering event carries no pull request\");\n }\n if (event.value.pull_request.draft === true) {\n return yield* skip(\"the pull request is a draft\");\n }\n }\n const target = yield* resolveReviewTarget({});\n // One layer build for state selection AND the run, so both observe\n // the same cached pull-request snapshot.\n return yield* Effect.gen(function* () {\n let selection: ReturnType<typeof selectReviewRange> | undefined;\n if (reviewer.profileFingerprint !== undefined) {\n const [snapshot, profileFingerprint, currentFingerprint] = yield* Effect.all([\n reviewer.snapshot,\n reviewer.profileFingerprint,\n reviewer.fingerprint.pipe(\n Effect.map((fingerprint): string | undefined => fingerprint),\n Effect.orElseSucceed(() => undefined),\n ),\n ]);\n const { metadata, files: fullFiles } = snapshot;\n const history = options.priorReviews ?? (yield* PriorReviews);\n const stateAuthenticator = yield* ReviewStateAuthenticator;\n const recovered =\n stateAuthenticator.status === \"unavailable\"\n ? {\n state: undefined,\n failure:\n stateAuthenticator.unavailableReason ??\n \"an authenticated review-state secret is not configured\",\n }\n : yield* history.latestState.pipe(\n Effect.match({\n onFailure: (failure) => ({ state: undefined, failure: failure.reason }),\n onSuccess: (state) => ({\n state: Option.getOrUndefined(state),\n failure: undefined,\n }),\n }),\n );\n const equivalentPatchState =\n (options.reviewMode ?? \"incremental\") === \"incremental\" &&\n options.skipUnchanged !== false &&\n recovered.state !== undefined &&\n // Only a fully settled run may be skipped over: an unsettled state\n // carries retryable scope the next run must actually retry.\n recovered.state.settled &&\n currentFingerprint !== undefined &&\n validateReviewState(recovered.state, metadata, profileFingerprint) === undefined &&\n recovered.state.settledScopeFingerprint === currentFingerprint\n ? recovered.state\n : undefined;\n if (equivalentPatchState !== undefined) {\n return yield* skipCoveredReview({\n repository: target.repository,\n pullRequestNumber: target.number,\n reason:\n equivalentPatchState.reviewedHeadSha === metadata.headSha\n ? \"the current head already has settled stored review assurance\"\n : \"the effective pull-request patch is unchanged since the last settled review\",\n state: equivalentPatchState,\n });\n }\n let comparison: ReviewHeadComparison | undefined;\n let baseComparison: ReviewHeadComparison | undefined;\n let contentComparison: ReviewTreeComparison | undefined;\n let contentComparisonFailure: string | undefined;\n if (\n (options.reviewMode ?? \"incremental\") === \"incremental\" &&\n recovered.state !== undefined\n ) {\n if (recovered.state.reviewedHeadSha === metadata.headSha) {\n comparison = ReviewHeadComparison.make({\n status: \"identical\",\n baseSha: metadata.headSha,\n headSha: metadata.headSha,\n mergeBaseSha: metadata.headSha,\n files: [],\n truncated: false,\n });\n } else {\n comparison = yield* history\n .compareHeads(recovered.state.reviewedHeadSha, metadata.headSha)\n .pipe(Effect.orElseSucceed(() => undefined));\n if (comparison !== undefined && reviewer.filterFiles !== undefined) {\n comparison = ReviewHeadComparison.make({\n ...comparison,\n files: reviewer.filterFiles(comparison.files),\n });\n }\n }\n if (metadata.baseSha !== undefined && recovered.state.baseSha !== metadata.baseSha) {\n baseComparison = yield* history\n .compareHeads(recovered.state.baseSha, metadata.baseSha)\n .pipe(Effect.orElseSucceed(() => undefined));\n if (baseComparison !== undefined && reviewer.filterFiles !== undefined) {\n baseComparison = ReviewHeadComparison.make({\n ...baseComparison,\n files: reviewer.filterFiles(baseComparison.files),\n });\n }\n }\n if (\n recovered.state.reviewedHeadSha !== metadata.headSha &&\n (comparison === undefined ||\n !isLineageAncestor(comparison, recovered.state, metadata.headSha))\n ) {\n const comparisonPaths = new Set(\n fullFiles.flatMap((file) =>\n file.previousPath === undefined ? [file.path] : [file.path, file.previousPath],\n ),\n );\n for (const finding of recovered.state.unresolvedFindings) {\n comparisonPaths.add(finding.path);\n }\n for (const concern of recovered.state.unresolvedConcerns) {\n for (const path of concern.evidencePaths ?? []) comparisonPaths.add(path);\n }\n for (const path of recovered.state.unreviewedPaths) comparisonPaths.add(path);\n const treeResult = yield* history\n .compareTrees(recovered.state.reviewedHeadSha, metadata.headSha, [...comparisonPaths])\n .pipe(\n Effect.match({\n onFailure: (failure) => ({\n comparison: undefined,\n failure: failure.reason,\n }),\n onSuccess: (treeComparison) => ({\n comparison: treeComparison,\n failure: undefined,\n }),\n }),\n );\n contentComparison = treeResult.comparison;\n contentComparisonFailure = treeResult.failure;\n }\n }\n selection = {\n ...selectReviewRange({\n requestedMode: options.reviewMode ?? \"incremental\",\n current: metadata,\n fullFiles,\n profileFingerprint,\n priorState: recovered.state,\n comparison,\n baseComparison,\n contentComparison,\n contentComparisonFailure,\n lookupFailure: recovered.failure,\n }),\n stateAuthenticator,\n };\n if (\n options.skipUnchanged !== false &&\n selection.mode === \"incremental\" &&\n selection.files.length === 0 &&\n selection.priorState !== undefined &&\n selection.priorState.settled\n ) {\n const reason = \"no changed review scope since the last settled review head\";\n return yield* skipCoveredReview({\n repository: target.repository,\n pullRequestNumber: target.number,\n reason,\n state: selection.priorState,\n });\n }\n }\n const executionContext =\n selection ??\n (yield* Effect.gen(function* () {\n const source = yield* PullRequestSource;\n const [metadata, files] = yield* Effect.all([source.metadata, source.changedFiles]);\n return fullReviewSelection({\n reason: \"explicit custom-reviewer full review without continuity selection\",\n files,\n totalFiles: metadata.totalChangedFiles,\n });\n }));\n yield* Console.log(\n `Reviewing ${target.repository}#${target.number} (${options.post === false ? \"dry run\" : \"posting\"})...`,\n );\n const runUrl = yield* resolveRunUrl();\n // Progress is a cosmetic, fail-open narration surface: it says a run is\n // working the moment execution starts and is overwritten in place when\n // the run settles. It never gates or delays the review itself.\n const progress =\n options.progressComment === true && options.post !== false\n ? Option.some(yield* ReviewProgressReporter)\n : Option.none<ReviewProgressReporter[\"Service\"]>();\n if (Option.isSome(progress)) {\n const source = yield* PullRequestSource;\n const headMetadata = yield* source.metadata.pipe(Effect.orElseSucceed(() => undefined));\n yield* progress.value.begin({\n headSha: headMetadata?.headSha,\n reviewMode: executionContext.mode,\n reviewReason: executionContext.reason,\n filesInScope: executionContext.files.length,\n modelLabel: options.modelLabel,\n runUrl,\n });\n }\n const runReview = reviewer.run({ post: options.post ?? true, runUrl });\n const reviewEffect = Option.isSome(progress)\n ? runReview.pipe(\n Effect.tapCause(() =>\n progress.value.settle({\n outcome: \"failed\",\n runUrl,\n modelLabel: options.modelLabel,\n }),\n ),\n )\n : runReview;\n const executionLayer = Layer.merge(\n Layer.succeed(ReviewExecutionContext)(executionContext),\n selectedPullRequestSourceLayer(executionContext),\n );\n const outcome = yield* reviewEffect.pipe(Effect.provide(executionLayer));\n yield* Console.log(\n `Review finished in ${outcome.turns} turn(s): verdict ${outcome.review.verdict}, ` +\n `${outcome.plan.comments.length} inline comment(s), ${outcome.plan.demoted.length} demoted finding(s).`,\n );\n if (outcome.published !== undefined) {\n yield* Console.log(`Posted ${outcome.published.event} review: ${outcome.published.url}`);\n if (options.retireStaleReviews !== false && outcome.state !== undefined) {\n if (outcome.published.authorNodeId === null || outcome.published.submittedAt === null) {\n yield* Console.warn(\n \"Skipping stale-review retirement because GitHub did not return the posted review's actor and submission time.\",\n );\n } else {\n const report = yield* retireStaleReviews({\n currentReviewId: outcome.published.reviewId,\n currentReviewUrl: outcome.published.url,\n currentAuthorNodeId: outcome.published.authorNodeId,\n currentSubmittedAt: outcome.published.submittedAt,\n currentState: outcome.state,\n });\n yield* Console.log(\n `Review retirement: ${report.reviewsRetired} prior review(s), ` +\n `${report.findingsResolved} resolved finding(s), ` +\n `${report.commentsMinimized} minimized inline comment(s), ` +\n `${report.failures} failure(s).`,\n );\n }\n }\n }\n const check = concludeReviewOutcome(outcome);\n if (Option.isSome(progress)) {\n yield* progress.value.settle({\n outcome: \"reviewed\",\n conclusion: check.conclusion,\n verdict: outcome.review.verdict,\n inlineComments: outcome.plan.comments.length,\n reviewUrl: outcome.published?.url,\n runUrl,\n modelLabel: options.modelLabel,\n });\n }\n yield* writeActionOutputs(outcomeOutputs(outcome, check.conclusion));\n yield* writeStepSummary(outcomeSummary(outcome, options.modelLabel, check.conclusion));\n if (check.conclusion !== \"success\") {\n return yield* ReviewGateFailed.make({\n conclusion: check.conclusion,\n reasons: check.reasons,\n });\n }\n return { _tag: \"Completed\", outcome } satisfies ReviewActionResult;\n }).pipe(Effect.provide(gitHubReviewLayers(target)));\n });\n\n/**\n * The packaged, environment-driven action program: inputs from PR_REVIEW_*,\n * reviewer built from the packaged factory, provider client from the\n * matching credential environment variable.\n */\nexport const reviewActionProgram = Effect.gen(function* () {\n const inputs = yield* resolveActionInputs();\n const stateSecret = Option.map(\n yield* Config.option(Config.nonEmptyString(\"PR_REVIEW_STATE_SECRET\")),\n Redacted.make,\n );\n const stateAuthenticatorLayer = Option.match(stateSecret, {\n onNone: () =>\n unavailableReviewStateAuthenticatorLayer(\n \"an authenticated review-state secret is not configured\",\n ),\n onSome: webCryptoReviewStateAuthenticatorLayer,\n });\n const guidance = yield* resolveGuidance(inputs);\n const modelLabel = describeReviewModel(\n inputs.provider,\n inputs.model,\n inputs.effort,\n inputs.serviceTier,\n );\n const defaults = inputs.fanOut ? fanOutReviewBudgetLimits : reviewBudgetLimits;\n const budget =\n inputs.maxDurationMinutes === undefined\n ? defaults\n : UsageBudgetLimits.make({\n ...defaults,\n maxDurationMillis: inputs.maxDurationMinutes * 60_000,\n });\n const shared = {\n guidance,\n ignore: inputs.ignore,\n maxFindings: inputs.maxFindings,\n applyVerdict: inputs.applyVerdict,\n modelLabel,\n budget,\n };\n const harness = {\n post: inputs.post,\n skipUnchanged: inputs.skipUnchanged,\n reviewMode: inputs.reviewMode,\n retireStaleReviews: inputs.retireStaleReviews,\n progressComment: inputs.progressComment,\n modelLabel,\n };\n if (inputs.provider === \"anthropic\") {\n const model = makeAnthropicReviewModel(inputs.model, inputs.effort);\n const reviewer = inputs.fanOut\n ? PrReview.makeFanOut({ ...shared, model })\n : PrReview.make({ ...shared, model });\n return yield* runReviewAction(reviewer, harness).pipe(\n Effect.provide(Layer.merge(stateAuthenticatorLayer, anthropicClientLayer)),\n );\n }\n const model = makeOpenAiReviewModel(inputs.model, inputs.effort, inputs.serviceTier);\n const reviewer = inputs.fanOut\n ? PrReview.makeFanOut({ ...shared, model })\n : PrReview.make({ ...shared, model });\n return yield* runReviewAction(reviewer, harness).pipe(\n Effect.provide(Layer.merge(stateAuthenticatorLayer, openAiClientLayer)),\n );\n});\n\n/** Run the packaged action program on Node; the bundled action entrypoint. */\nexport const main = (): void =>\n NodeRuntime.runMain(\n reviewActionProgram.pipe(\n Effect.tapError((error) =>\n Console.error(\n Schema.is(BudgetExceeded)(error)\n ? `Budget exceeded: ${error.limit} observed ${error.observedValue}, limit ${error.limitValue}.`\n : String(error),\n ),\n ),\n Effect.scoped,\n Effect.provide(\n Layer.mergeAll(NodeServices.layer, FetchHttpClient.layer, compactReviewLoggingLayer),\n ),\n ),\n { disableErrorReporting: true },\n );\n\n/** The packaged GitHub Actions surface. */\nexport const PrReviewAction = {\n inputs: resolveActionInputs,\n run: runReviewAction,\n program: reviewActionProgram,\n main,\n} as const;\n"],"mappings":"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"}
package/dist/cli.d.mts DELETED
@@ -1 +0,0 @@
1
- export {}