@effect-agent/pr-review 0.1.0-beta.23 → 0.1.0-beta.25
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +83 -195
- package/dist/action.d.mts +27 -18
- package/dist/action.mjs +60 -39
- package/dist/action.mjs.map +1 -1
- package/dist/cli.mjs +3 -3
- package/dist/cli.mjs.map +1 -1
- package/dist/{fan-out-BJBTAYuh.d.mts → fan-out-CMEsbFLk.d.mts} +455 -177
- package/dist/{github-BbwYzNrC.mjs → github-NjgxGqwM.mjs} +2163 -1518
- package/dist/github-NjgxGqwM.mjs.map +1 -0
- package/dist/index.d.mts +30 -20
- package/dist/index.mjs +3 -3
- package/dist/{providers-NyP-4rS6.mjs → providers-CODZQCmL.mjs} +202 -80
- package/dist/providers-CODZQCmL.mjs.map +1 -0
- package/dist/testing.d.mts +3 -1
- package/dist/testing.mjs +3 -2
- package/dist/testing.mjs.map +1 -1
- package/package.json +2 -2
- package/src/action.ts +141 -78
- package/src/cli.ts +6 -1
- package/src/index.ts +1 -0
- package/src/internal/adjudication.ts +415 -0
- package/src/internal/coverage.ts +41 -60
- package/src/internal/factory.ts +4 -4
- package/src/internal/fan-out.ts +208 -14
- package/src/internal/fingerprint.ts +16 -10
- package/src/internal/fixtures.ts +6 -0
- package/src/internal/github-env.ts +9 -0
- package/src/internal/github.ts +243 -7
- package/src/internal/progress.ts +1 -1
- package/src/internal/render.ts +186 -42
- package/src/internal/retirement.ts +16 -17
- package/src/internal/review-agent.ts +39 -4
- package/src/internal/review-state.ts +315 -105
- package/src/internal/review-units.ts +10 -9
- package/src/internal/run.ts +197 -63
- package/dist/github-BbwYzNrC.mjs.map +0 -1
- package/dist/providers-NyP-4rS6.mjs.map +0 -1
package/src/action.ts
CHANGED
|
@@ -3,6 +3,8 @@ import { Config, Console, Effect, FileSystem, Layer, Option, Redacted, Schema }
|
|
|
3
3
|
import { BudgetExceeded, UsageBudgetLimits } from "effect-agent";
|
|
4
4
|
import { FetchHttpClient } from "effect/unstable/http";
|
|
5
5
|
|
|
6
|
+
import { collectReviewAdjudications } from "./internal/adjudication.ts";
|
|
7
|
+
import { splitCarriedScope } from "./internal/coverage.ts";
|
|
6
8
|
import type { ChangedFile } from "./internal/diff.ts";
|
|
7
9
|
import { InvalidEffortInput, parseEffortPosition, type EffortPosition } from "./internal/effort.ts";
|
|
8
10
|
import { PrReview, type RunReviewOptions } from "./internal/factory.ts";
|
|
@@ -21,9 +23,14 @@ import {
|
|
|
21
23
|
} from "./internal/providers.ts";
|
|
22
24
|
import { retireStaleReviews } from "./internal/retirement.ts";
|
|
23
25
|
import {
|
|
26
|
+
adjudicationIdentity,
|
|
27
|
+
concernIdentity,
|
|
28
|
+
findingIdentity,
|
|
29
|
+
fullReviewSelection,
|
|
24
30
|
ReviewExecutionContext,
|
|
25
31
|
ReviewHeadComparison,
|
|
26
32
|
ReviewStateAuthenticator,
|
|
33
|
+
isLineageAncestor,
|
|
27
34
|
type ReviewMode,
|
|
28
35
|
type ReviewState,
|
|
29
36
|
selectReviewRange,
|
|
@@ -259,8 +266,6 @@ const outcomeOutputs = (
|
|
|
259
266
|
["verdict", outcome.review.verdict],
|
|
260
267
|
["input-coverage", outcome.inputCoverage.status],
|
|
261
268
|
["review-assurance", outcome.assurance.status],
|
|
262
|
-
// Compatibility output: the precise outputs above own new integrations.
|
|
263
|
-
["coverage", outcome.coverage.status],
|
|
264
269
|
["review-mode", outcome.reviewMode ?? "full"],
|
|
265
270
|
["review-reason", outcome.reviewReason ?? "direct full review"],
|
|
266
271
|
["inline-comments", String(outcome.plan.comments.length)],
|
|
@@ -280,26 +285,34 @@ const outcomeSummary = (
|
|
|
280
285
|
outcome: ReviewRunOutcome,
|
|
281
286
|
modelLabel: string | undefined,
|
|
282
287
|
conclusion: ReviewCheckConclusion,
|
|
283
|
-
): ReadonlyArray<string> =>
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
]
|
|
288
|
+
): ReadonlyArray<string> => {
|
|
289
|
+
const scope = splitCarriedScope(outcome);
|
|
290
|
+
return [
|
|
291
|
+
"### Pull-request review",
|
|
292
|
+
`- Check conclusion: **${conclusion}**`,
|
|
293
|
+
`- Verdict: **${outcome.review.verdict}**`,
|
|
294
|
+
`- Input coverage: **${outcome.inputCoverage.status}** · scope: ${outcome.reviewMode ?? "full"}`,
|
|
295
|
+
`- 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}`,
|
|
296
|
+
`- Inline comments: ${outcome.plan.comments.length} · demoted findings: ${outcome.plan.demoted.length} · concerns: ${outcome.review.concerns?.length ?? 0}`,
|
|
297
|
+
...(scope.retryablePaths.length === 0
|
|
298
|
+
? []
|
|
299
|
+
: [
|
|
300
|
+
`- Carried forward: ${scope.retryablePaths.length} unreviewed path(s) retried automatically on the next run (reviewer-side gap, not a code defect)`,
|
|
301
|
+
]),
|
|
302
|
+
...(scope.undiffablePaths.length === 0
|
|
303
|
+
? []
|
|
304
|
+
: [
|
|
305
|
+
`- 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`,
|
|
306
|
+
]),
|
|
307
|
+
...(modelLabel === undefined ? [] : [`- Model: \`${modelLabel}\``]),
|
|
308
|
+
...(outcome.usage === undefined
|
|
309
|
+
? []
|
|
310
|
+
: [`- Tokens: ${outcome.usage.inputTokens} in / ${outcome.usage.outputTokens} out`]),
|
|
311
|
+
...(outcome.published === undefined
|
|
312
|
+
? ["- Dry run: nothing posted"]
|
|
313
|
+
: [`- Posted: ${outcome.published.url}`]),
|
|
314
|
+
];
|
|
315
|
+
};
|
|
303
316
|
|
|
304
317
|
/** The result of one action invocation: a typed skip or a settled review. */
|
|
305
318
|
export type ReviewActionResult =
|
|
@@ -332,30 +345,41 @@ const resolveRunUrl = Effect.fn("resolveRunUrl")(function* () {
|
|
|
332
345
|
* The reviewer surface the action harness drives. `PrReview.make` and
|
|
333
346
|
* `PrReview.makeFanOut` provide the state-selection effects. A fingerprint is
|
|
334
347
|
* skip authority only when a profile fingerprint and authenticated review
|
|
335
|
-
* state bind it to settled assurance
|
|
336
|
-
* remains source-compatible but deliberately runs instead of claiming green
|
|
337
|
-
* assurance from unauthenticated prior-review text.
|
|
348
|
+
* state bind it to settled assurance.
|
|
338
349
|
*/
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
readonly snapshot?:
|
|
345
|
-
| Effect.Effect<
|
|
346
|
-
{
|
|
347
|
-
readonly metadata: PullRequestMetadata;
|
|
348
|
-
readonly files: ReadonlyArray<ChangedFile>;
|
|
349
|
-
},
|
|
350
|
-
FingerprintE,
|
|
351
|
-
FingerprintR
|
|
352
|
-
>
|
|
353
|
-
| undefined;
|
|
354
|
-
readonly filterFiles?:
|
|
355
|
-
| ((files: ReadonlyArray<ChangedFile>) => ReadonlyArray<ChangedFile>)
|
|
356
|
-
| undefined;
|
|
350
|
+
interface HarnessedReviewerBase<E, R> {
|
|
351
|
+
/** The action composition root always supplies the selected run context. */
|
|
352
|
+
readonly run: (
|
|
353
|
+
runOptions?: RunReviewOptions,
|
|
354
|
+
) => Effect.Effect<ReviewRunOutcome, E, R | ReviewExecutionContext>;
|
|
357
355
|
}
|
|
358
356
|
|
|
357
|
+
export type HarnessedReviewer<E, R, FingerprintE, FingerprintR> = HarnessedReviewerBase<E, R> &
|
|
358
|
+
(
|
|
359
|
+
| {
|
|
360
|
+
readonly fingerprint?: undefined;
|
|
361
|
+
readonly profileFingerprint?: undefined;
|
|
362
|
+
readonly snapshot?: undefined;
|
|
363
|
+
readonly filterFiles?: undefined;
|
|
364
|
+
}
|
|
365
|
+
| {
|
|
366
|
+
/** Current effective changeset fingerprint; not standalone skip authority. */
|
|
367
|
+
readonly fingerprint: Effect.Effect<string, FingerprintE, FingerprintR>;
|
|
368
|
+
readonly profileFingerprint: Effect.Effect<string, FingerprintE, FingerprintR>;
|
|
369
|
+
readonly snapshot: Effect.Effect<
|
|
370
|
+
{
|
|
371
|
+
readonly metadata: PullRequestMetadata;
|
|
372
|
+
readonly files: ReadonlyArray<ChangedFile>;
|
|
373
|
+
},
|
|
374
|
+
FingerprintE,
|
|
375
|
+
FingerprintR
|
|
376
|
+
>;
|
|
377
|
+
readonly filterFiles?:
|
|
378
|
+
| ((files: ReadonlyArray<ChangedFile>) => ReadonlyArray<ChangedFile>)
|
|
379
|
+
| undefined;
|
|
380
|
+
}
|
|
381
|
+
);
|
|
382
|
+
|
|
359
383
|
const blockingReasons = (input: {
|
|
360
384
|
readonly findings: ReadonlyArray<{ readonly severity: string; readonly title: string }>;
|
|
361
385
|
readonly concerns: ReadonlyArray<{ readonly severity: string; readonly title: string }>;
|
|
@@ -372,10 +396,13 @@ const blockingReasons = (input: {
|
|
|
372
396
|
* Host-derived check conclusion; model verdict prose cannot weaken it.
|
|
373
397
|
*
|
|
374
398
|
* Blocking code findings outrank machinery gaps — they are the actionable
|
|
375
|
-
* signal. A machinery gap (
|
|
376
|
-
* `incomplete` with reasons that explicitly say the failure is
|
|
377
|
-
* uncertainty carried forward for retry, never an invitation to
|
|
378
|
-
*
|
|
399
|
+
* signal. A retryable machinery gap (failed passes, capacity overflow)
|
|
400
|
+
* concludes `incomplete` with reasons that explicitly say the failure is
|
|
401
|
+
* reviewer-side uncertainty carried forward for retry, never an invitation to
|
|
402
|
+
* change code. Undiffable files are the deliberate exception: no retry can
|
|
403
|
+
* settle them, so their reason instructs removal or ignore globs instead of
|
|
404
|
+
* promising an automatic retry. The flat reviewer's constant `unverified`
|
|
405
|
+
* assurance is not a gap.
|
|
379
406
|
*/
|
|
380
407
|
export const concludeReviewOutcome = (
|
|
381
408
|
outcome: ReviewRunOutcome,
|
|
@@ -385,11 +412,19 @@ export const concludeReviewOutcome = (
|
|
|
385
412
|
} => {
|
|
386
413
|
const machinery: Array<string> = [];
|
|
387
414
|
if (outcome.inputCoverage.status === "incomplete" || outcome.assurance.status === "incomplete") {
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
415
|
+
const scope = splitCarriedScope(outcome);
|
|
416
|
+
if (scope.retryableGap) {
|
|
417
|
+
machinery.push(
|
|
418
|
+
scope.retryablePaths.length > 0
|
|
419
|
+
? `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`
|
|
420
|
+
: "review infrastructure did not settle — a reviewer-side gap, not a code defect",
|
|
421
|
+
);
|
|
422
|
+
}
|
|
423
|
+
if (scope.undiffablePaths.length > 0) {
|
|
424
|
+
machinery.push(
|
|
425
|
+
`${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`,
|
|
426
|
+
);
|
|
427
|
+
}
|
|
393
428
|
if (outcome.inputCoverage.status === "incomplete") {
|
|
394
429
|
machinery.push(...outcome.inputCoverage.reasons);
|
|
395
430
|
}
|
|
@@ -408,10 +443,14 @@ export const concludeReviewOutcome = (
|
|
|
408
443
|
return { conclusion: "success", reasons: [] };
|
|
409
444
|
};
|
|
410
445
|
|
|
411
|
-
const concludeReviewState = (state: ReviewState) => {
|
|
446
|
+
const concludeReviewState = (state: ReviewState, adjudicated: ReadonlySet<string>) => {
|
|
412
447
|
const reasons = blockingReasons({
|
|
413
|
-
findings: state.unresolvedFindings
|
|
414
|
-
|
|
448
|
+
findings: state.unresolvedFindings.filter(
|
|
449
|
+
(finding) => !adjudicated.has(findingIdentity(finding)),
|
|
450
|
+
),
|
|
451
|
+
concerns: state.unresolvedConcerns.filter(
|
|
452
|
+
(concern) => !adjudicated.has(concernIdentity(concern)),
|
|
453
|
+
),
|
|
415
454
|
});
|
|
416
455
|
return reasons.length > 0
|
|
417
456
|
? ({ conclusion: "blocking", reasons } as const)
|
|
@@ -423,20 +462,21 @@ const skipCoveredReview = Effect.fn("skipCoveredReview")(function* (input: {
|
|
|
423
462
|
readonly pullRequestNumber: number;
|
|
424
463
|
readonly reason: string;
|
|
425
464
|
readonly state: ReviewState;
|
|
426
|
-
readonly fingerprint?: string | undefined;
|
|
427
465
|
}) {
|
|
428
|
-
|
|
466
|
+
// A maintainer adjudication must lift a preserved blocking conclusion
|
|
467
|
+
// without a code push, so the skip path re-reads adjudications (fail-open;
|
|
468
|
+
// stored ones survive a listing fault) before enforcing the stored state.
|
|
469
|
+
const adjudications = yield* collectReviewAdjudications(input.state.adjudications ?? []);
|
|
470
|
+
const result = concludeReviewState(input.state, new Set(adjudications.map(adjudicationIdentity)));
|
|
429
471
|
yield* Console.log(
|
|
430
472
|
`Skipping review of ${input.repository}#${input.pullRequestNumber}: ${input.reason}.`,
|
|
431
473
|
);
|
|
432
474
|
yield* writeActionOutputs([
|
|
433
475
|
["skipped", "true"],
|
|
434
476
|
["skip-reason", input.reason],
|
|
435
|
-
...(input.fingerprint === undefined ? [] : ([["fingerprint", input.fingerprint]] as const)),
|
|
436
477
|
["conclusion", result.conclusion],
|
|
437
478
|
["input-coverage", "complete"],
|
|
438
479
|
["review-assurance", "settled"],
|
|
439
|
-
["coverage", "complete"],
|
|
440
480
|
["review-mode", "incremental"],
|
|
441
481
|
]);
|
|
442
482
|
yield* writeStepSummary([
|
|
@@ -501,16 +541,13 @@ export const runReviewAction = <E, R, FingerprintE = never, FingerprintR = never
|
|
|
501
541
|
return yield* Effect.gen(function* () {
|
|
502
542
|
let selection: ReturnType<typeof selectReviewRange> | undefined;
|
|
503
543
|
if (reviewer.profileFingerprint !== undefined) {
|
|
504
|
-
const source = yield* PullRequestSource;
|
|
505
544
|
const [snapshot, profileFingerprint, currentFingerprint] = yield* Effect.all([
|
|
506
|
-
reviewer.snapshot
|
|
545
|
+
reviewer.snapshot,
|
|
507
546
|
reviewer.profileFingerprint,
|
|
508
|
-
reviewer.fingerprint
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
Effect.orElseSucceed(() => undefined),
|
|
513
|
-
),
|
|
547
|
+
reviewer.fingerprint.pipe(
|
|
548
|
+
Effect.map((fingerprint): string | undefined => fingerprint),
|
|
549
|
+
Effect.orElseSucceed(() => undefined),
|
|
550
|
+
),
|
|
514
551
|
]);
|
|
515
552
|
const { metadata, files: fullFiles } = snapshot;
|
|
516
553
|
const history = options.priorReviews ?? (yield* PriorReviews);
|
|
@@ -541,7 +578,7 @@ export const runReviewAction = <E, R, FingerprintE = never, FingerprintR = never
|
|
|
541
578
|
recovered.state.settled &&
|
|
542
579
|
currentFingerprint !== undefined &&
|
|
543
580
|
validateReviewState(recovered.state, metadata, profileFingerprint) === undefined &&
|
|
544
|
-
recovered.state.
|
|
581
|
+
recovered.state.settledScopeFingerprint === currentFingerprint
|
|
545
582
|
? recovered.state
|
|
546
583
|
: undefined;
|
|
547
584
|
if (equivalentPatchState !== undefined) {
|
|
@@ -553,11 +590,11 @@ export const runReviewAction = <E, R, FingerprintE = never, FingerprintR = never
|
|
|
553
590
|
? "the current head already has settled stored review assurance"
|
|
554
591
|
: "the effective pull-request patch is unchanged since the last settled review",
|
|
555
592
|
state: equivalentPatchState,
|
|
556
|
-
fingerprint: currentFingerprint,
|
|
557
593
|
});
|
|
558
594
|
}
|
|
559
595
|
let comparison: ReviewHeadComparison | undefined;
|
|
560
596
|
let baseComparison: ReviewHeadComparison | undefined;
|
|
597
|
+
let contentComparison: ReviewHeadComparison | undefined;
|
|
561
598
|
if (
|
|
562
599
|
(options.reviewMode ?? "incremental") === "incremental" &&
|
|
563
600
|
recovered.state !== undefined
|
|
@@ -593,6 +630,21 @@ export const runReviewAction = <E, R, FingerprintE = never, FingerprintR = never
|
|
|
593
630
|
});
|
|
594
631
|
}
|
|
595
632
|
}
|
|
633
|
+
if (
|
|
634
|
+
recovered.state.reviewedHeadSha !== metadata.headSha &&
|
|
635
|
+
(comparison === undefined ||
|
|
636
|
+
!isLineageAncestor(comparison, recovered.state, metadata.headSha))
|
|
637
|
+
) {
|
|
638
|
+
contentComparison = yield* history
|
|
639
|
+
.compareTrees(recovered.state.reviewedHeadSha, metadata.headSha)
|
|
640
|
+
.pipe(Effect.orElseSucceed(() => undefined));
|
|
641
|
+
if (contentComparison !== undefined && reviewer.filterFiles !== undefined) {
|
|
642
|
+
contentComparison = ReviewHeadComparison.make({
|
|
643
|
+
...contentComparison,
|
|
644
|
+
files: reviewer.filterFiles(contentComparison.files),
|
|
645
|
+
});
|
|
646
|
+
}
|
|
647
|
+
}
|
|
596
648
|
}
|
|
597
649
|
selection = {
|
|
598
650
|
...selectReviewRange({
|
|
@@ -603,6 +655,7 @@ export const runReviewAction = <E, R, FingerprintE = never, FingerprintR = never
|
|
|
603
655
|
priorState: recovered.state,
|
|
604
656
|
comparison,
|
|
605
657
|
baseComparison,
|
|
658
|
+
contentComparison,
|
|
606
659
|
lookupFailure: recovered.failure,
|
|
607
660
|
}),
|
|
608
661
|
stateAuthenticator,
|
|
@@ -623,6 +676,17 @@ export const runReviewAction = <E, R, FingerprintE = never, FingerprintR = never
|
|
|
623
676
|
});
|
|
624
677
|
}
|
|
625
678
|
}
|
|
679
|
+
const executionContext =
|
|
680
|
+
selection ??
|
|
681
|
+
(yield* Effect.gen(function* () {
|
|
682
|
+
const source = yield* PullRequestSource;
|
|
683
|
+
const [metadata, files] = yield* Effect.all([source.metadata, source.changedFiles]);
|
|
684
|
+
return fullReviewSelection({
|
|
685
|
+
reason: "explicit custom-reviewer full review without continuity selection",
|
|
686
|
+
files,
|
|
687
|
+
totalFiles: metadata.totalChangedFiles,
|
|
688
|
+
});
|
|
689
|
+
}));
|
|
626
690
|
yield* Console.log(
|
|
627
691
|
`Reviewing ${target.repository}#${target.number} (${options.post === false ? "dry run" : "posting"})...`,
|
|
628
692
|
);
|
|
@@ -639,9 +703,9 @@ export const runReviewAction = <E, R, FingerprintE = never, FingerprintR = never
|
|
|
639
703
|
const headMetadata = yield* source.metadata.pipe(Effect.orElseSucceed(() => undefined));
|
|
640
704
|
yield* progress.value.begin({
|
|
641
705
|
headSha: headMetadata?.headSha,
|
|
642
|
-
reviewMode:
|
|
643
|
-
reviewReason:
|
|
644
|
-
filesInScope:
|
|
706
|
+
reviewMode: executionContext.mode,
|
|
707
|
+
reviewReason: executionContext.reason,
|
|
708
|
+
filesInScope: executionContext.files.length,
|
|
645
709
|
modelLabel: options.modelLabel,
|
|
646
710
|
runUrl,
|
|
647
711
|
});
|
|
@@ -658,12 +722,11 @@ export const runReviewAction = <E, R, FingerprintE = never, FingerprintR = never
|
|
|
658
722
|
),
|
|
659
723
|
)
|
|
660
724
|
: runReview;
|
|
661
|
-
const
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
);
|
|
725
|
+
const executionLayer = Layer.merge(
|
|
726
|
+
Layer.succeed(ReviewExecutionContext)(executionContext),
|
|
727
|
+
selectedPullRequestSourceLayer(executionContext),
|
|
728
|
+
);
|
|
729
|
+
const outcome = yield* reviewEffect.pipe(Effect.provide(executionLayer));
|
|
667
730
|
yield* Console.log(
|
|
668
731
|
`Review finished in ${outcome.turns} turn(s): verdict ${outcome.review.verdict}, ` +
|
|
669
732
|
`${outcome.plan.comments.length} inline comment(s), ${outcome.plan.demoted.length} demoted finding(s).`,
|
package/src/cli.ts
CHANGED
|
@@ -19,6 +19,7 @@ import {
|
|
|
19
19
|
type ReviewProvider,
|
|
20
20
|
} from "./internal/providers.ts";
|
|
21
21
|
import { ReviewPublicationPlan } from "./internal/render.ts";
|
|
22
|
+
import { fullReviewExecutionContextLayer } from "./internal/review-state.ts";
|
|
22
23
|
import type { ReviewRunOutcome } from "./internal/run.ts";
|
|
23
24
|
|
|
24
25
|
// ---------------------------------------------------------------------------
|
|
@@ -158,7 +159,11 @@ const command = CliCommand.make(
|
|
|
158
159
|
return Option.none<ReviewRunOutcome>();
|
|
159
160
|
}
|
|
160
161
|
}
|
|
161
|
-
return Option.some(
|
|
162
|
+
return Option.some(
|
|
163
|
+
yield* reviewer
|
|
164
|
+
.run({ post: flags.post })
|
|
165
|
+
.pipe(Effect.provide(fullReviewExecutionContextLayer("explicit CLI full review"))),
|
|
166
|
+
);
|
|
162
167
|
});
|
|
163
168
|
|
|
164
169
|
let result: Option.Option<ReviewRunOutcome>;
|
package/src/index.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
// The @effect-agent/pr-review public surface. Platform-free: host entrypoints
|
|
2
2
|
// live behind the "./action" and "./cli" subpaths, deterministic test helpers
|
|
3
3
|
// behind "./testing".
|
|
4
|
+
export * from "./internal/adjudication.ts";
|
|
4
5
|
export * from "./internal/anchors.ts";
|
|
5
6
|
export * from "./internal/diff.ts";
|
|
6
7
|
export * from "./internal/coverage.ts";
|