@effect-agent/pr-review 0.1.0-beta.9 → 0.1.0-beta.91

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 (59) hide show
  1. package/NOTICE +26 -0
  2. package/README.md +170 -168
  3. package/dist/Review.d.mts +294 -0
  4. package/dist/Review.mjs +702 -0
  5. package/dist/Review.mjs.map +1 -0
  6. package/dist/ReviewRepository-Wd_4qCaO.d.mts +71 -0
  7. package/dist/ReviewRepository.d.mts +2 -0
  8. package/dist/ReviewRepository.mjs +15 -0
  9. package/dist/ReviewRepository.mjs.map +1 -0
  10. package/dist/index.d.mts +3 -717
  11. package/dist/index.mjs +3 -66
  12. package/dist/repository-D7NN3225.mjs +101 -0
  13. package/dist/repository-D7NN3225.mjs.map +1 -0
  14. package/dist/rolldown-runtime-D7D4PA-g.mjs +13 -0
  15. package/package.json +1 -54
  16. package/src/Review.ts +1052 -0
  17. package/src/ReviewRepository.ts +9 -0
  18. package/src/index.ts +2 -21
  19. package/src/internal/repository.ts +156 -0
  20. package/dist/action.d.mts +0 -190
  21. package/dist/action.mjs +0 -423
  22. package/dist/action.mjs.map +0 -1
  23. package/dist/cli.d.mts +0 -1
  24. package/dist/cli.mjs +0 -103
  25. package/dist/cli.mjs.map +0 -1
  26. package/dist/fan-out-C6gq3CFg.d.mts +0 -1081
  27. package/dist/github-Lfa_ox-u.mjs +0 -1673
  28. package/dist/github-Lfa_ox-u.mjs.map +0 -1
  29. package/dist/index.mjs.map +0 -1
  30. package/dist/providers-CaOnz7mK.mjs +0 -987
  31. package/dist/providers-CaOnz7mK.mjs.map +0 -1
  32. package/dist/testing.d.mts +0 -131
  33. package/dist/testing.mjs +0 -230
  34. package/dist/testing.mjs.map +0 -1
  35. package/src/action.ts +0 -697
  36. package/src/cli.ts +0 -214
  37. package/src/internal/action-entry.ts +0 -42
  38. package/src/internal/coverage.ts +0 -245
  39. package/src/internal/diff.ts +0 -134
  40. package/src/internal/effort.ts +0 -86
  41. package/src/internal/factory.ts +0 -374
  42. package/src/internal/fan-out-scripted.ts +0 -164
  43. package/src/internal/fan-out.ts +0 -450
  44. package/src/internal/fingerprint.ts +0 -74
  45. package/src/internal/fixtures.ts +0 -131
  46. package/src/internal/github-env.ts +0 -142
  47. package/src/internal/github.ts +0 -761
  48. package/src/internal/ignore.ts +0 -88
  49. package/src/internal/profiles.ts +0 -79
  50. package/src/internal/providers.ts +0 -91
  51. package/src/internal/render.ts +0 -428
  52. package/src/internal/retirement.ts +0 -332
  53. package/src/internal/review-agent.ts +0 -385
  54. package/src/internal/review-state.ts +0 -488
  55. package/src/internal/review-units.ts +0 -167
  56. package/src/internal/run.ts +0 -397
  57. package/src/internal/scripted.ts +0 -108
  58. package/src/internal/source.ts +0 -110
  59. package/src/testing.ts +0 -8
package/NOTICE ADDED
@@ -0,0 +1,26 @@
1
+ This package includes adaptations of the review instructions from PR-Agent:
2
+
3
+ https://github.com/The-PR-Agent/pr-agent
4
+ Pinned source: 9e6d6a5b40f9ce90bcc085466ba7a42c0837c37a
5
+
6
+ MIT License
7
+
8
+ Copyright (c) 2026 The PR Agent
9
+
10
+ Permission is hereby granted, free of charge, to any person obtaining a copy
11
+ of this software and associated documentation files (the "Software"), to deal
12
+ in the Software without restriction, including without limitation the rights
13
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14
+ copies of the Software, and to permit persons to whom the Software is
15
+ furnished to do so, subject to the following conditions:
16
+
17
+ The above copyright notice and this permission notice shall be included in all
18
+ copies or substantial portions of the Software.
19
+
20
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26
+ SOFTWARE.
package/README.md CHANGED
@@ -1,174 +1,176 @@
1
1
  # @effect-agent/pr-review
2
2
 
3
- A bounded, fail-closed GitHub pull-request reviewer built on the effect-agent
4
- public surface. One read-only Agent reviews a pull request through typed
5
- ports; the host validates every finding anchor against the real diff and
6
- posts one review after the run settles.
7
-
8
- **Deployment class E (ephemeral).** One `AgentRuntime.run` per invocation, no
9
- durability claim, and review posting is never exactly-once: a failed or
10
- truncated run posts nothing.
11
-
12
- ## Use
13
-
14
- ```ts
15
- import { Effect, Layer } from "effect";
16
- import {
17
- PrReview,
18
- gitHubReviewLayers,
19
- resolveReviewTarget,
20
- makeOpenAiReviewModel,
21
- openAiClientLayer,
22
- } from "@effect-agent/pr-review";
23
-
24
- const reviewer = PrReview.make({ model: makeOpenAiReviewModel() });
25
-
26
- const program = Effect.gen(function* () {
27
- const target = yield* resolveReviewTarget({ repository: "acme/api", number: 123 });
28
- return yield* reviewer
29
- .run({ post: true })
30
- .pipe(Effect.provide(Layer.merge(gitHubReviewLayers(target), openAiClientLayer)));
31
- });
32
- ```
33
-
34
- The run's requirement channel keeps every real dependency visible: the
35
- `PullRequestSource` and `ReviewPublisher` ports, the provider client, and the
36
- handler Layer of any extra tool you add. Anthropic is equally supported
37
- (`makeAnthropicReviewModel`, `anthropicClientLayer`), and the factory accepts
38
- any Effect AI Model.
39
-
40
- ## Adapt
41
-
42
- ```ts
43
- const reviewer = PrReview.make({
44
- model: makeAnthropicReviewModel("claude-sonnet-5"),
45
- guidance: (mission) => [
46
- "This is an Effect codebase. Flag naked Promises in public APIs.",
47
- mission.changedFileCount > 50 ? "Large PR: prioritize breadth over nit depth." : "",
48
- ],
49
- ignore: ["**/*.lock", "dist/**"],
50
- maxFindings: 10,
51
- policy: { maxTurns: 20, maxToolCalls: 40, maxDuration: "10 minutes", toolConcurrency: 2 },
52
- extraTools: [MyReadonlyTool], // must be annotated ToolExecutionClass "readonly"
53
- });
54
- ```
55
-
56
- Every knob widens what goes INTO the review. What leaves it is not
57
- configurable: model output is untrusted input, so finding anchors are
58
- re-validated against the parsed unified diff (invalid ones are demoted into
59
- the review body with the reason named, never trusted), the findings bound is
60
- enforced host-side, and publication happens only through the
61
- `ReviewPublisher` port after the run settles. `PrReview.makeFanOut` builds
62
- the delegating variant bounded per-unit child reviewers (S1 attached
63
- ephemeral delegation) merged under the same output contract and the same
64
- publication path; the shared `guidance` and `maxFindings` shape the
65
- coordinator's merge as well as the children.
66
-
67
- ## What a posted review looks like
68
-
69
- The body opens with a host-derived callout tier `[!CAUTION]` when any
70
- finding is blocking, `[!IMPORTANT]` for important findings, an ℹ️ blockquote
71
- for nits, `✅` for a clean approval computed from the validated severities,
72
- never from model prose. Below the summary, non-anchored `concerns` (deletion
73
- plans, rollout sequencing, coverage gaps, scope questions things with no
74
- diff line to point at) render as severity-tagged sections. The footer names
75
- the model binding, the observed token usage, and links to the workflow run;
76
- an invisible metadata comment pins the reviewed head commit so later readers
77
- know when line callouts have gone stale.
78
-
79
- ## Swap a port
80
-
81
- Tools observe the pull request only through `PullRequestSource`; publication
82
- happens only through `ReviewPublisher`. Provide your own Layers to review
83
- anything diff-shaped or publish anywhere else — the GitHub REST adapters are
84
- one implementation, not the contract.
85
-
86
- ## Test what you adapted
3
+ A provider-neutral agent that reviews an exact base-to-head change using a complete change
4
+ index, paged diffs, and immutable source tools. One conversation follows related behavior across
5
+ files. There are no separate patch batches, candidate pipeline, voting, or repository execution.
6
+
7
+ ## Evidence and findings
8
+
9
+ The initial prompt includes every admitted path and its character range in one literal diff
10
+ artifact. Changes up to 32,000 characters are included directly. Larger changes use `read_diff`:
11
+ start at offset zero and follow `nextOffset`, or select a file's start offset from the index.
12
+ Pages contain at most 32,000 UTF-16 characters and can cross file boundaries or split lines.
13
+ Original unified patches, hunk coordinates, deletions, renames, and mode metadata remain intact.
14
+
15
+ `read_file` reads up to 200 lines and 20,000 characters at the exact base or head.
16
+ `find_files` searches filenames. `search_code` searches literal, case-sensitive source text to
17
+ find definitions, callers, consumers, and tests, including unchanged code. Its path filter is a
18
+ filename substring; cursor zero starts the search. Each page scans twenty authorized files,
19
+ returns up to five matching lines per file, and provides `nextCursor` for more files.
20
+ `truncated` identifies omitted matching lines and `unreadablePaths` identifies failed reads.
21
+ A partial or failed search cannot establish that a caller is absent.
22
+
23
+ The reviewer starts with the promised consumer outcome and traces supported execution paths,
24
+ including unchanged callers and consumers. It distinguishes missing promised behavior from
25
+ optional feature expansion. Before recording a defect, it checks the
26
+ strongest relevant guard, documented exception, or alternative interpretation and establishes
27
+ why the supported trigger still causes concrete impact. It checks base/head causation, boundary
28
+ values, cleanup, concurrency, and whether changed tests would detect the claimed failure.
29
+ New features must satisfy their stated contracts, including validation, limits, isolation,
30
+ and aggregation; a bypass can be a defect even when the old code also accepted that input.
31
+ Unrelated old bugs, speculation, style, compiler diagnostics, and generic test requests are
32
+ excluded. Incremental reviews limit new findings to their exact delta.
33
+
34
+ The shared finding rubric, parent review procedure, and host-supplied repository policy are
35
+ separate instructions. Policy findings identify the specific rule and applicable exceptions,
36
+ citing instruction paths and lines when available. An explicitly reviewable architecture
37
+ contract can warrant a finding without a runtime failure; its supplied severity takes precedence.
38
+
39
+ `record_finding` is the only way to add findings to the report. The model is instructed to record
40
+ each distinct root cause once and recover the saved ledger with `review_status` after `new_context`,
41
+ without re-recording an issue with revised wording or severity. Counterevidence must be checked
42
+ before recording because the ledger has no retraction or revision operation. `submit_review` is the
43
+ required native completion tool and accepts only `blockedOn` and `resolutions` metadata.
44
+ The host builds the final report directly from the ledger, so completion never rewrites or merges
45
+ findings. Extra completion fields fail validation.
46
+
47
+ The host validates changed paths and RIGHT-side line anchors, demotes invalid anchors to
48
+ top-level findings, and removes only exact repeated records. Distinct defects at the same path
49
+ and line remain separate. Up to 24 findings are retained, prioritizing blocking over important
50
+ over minor findings. Overflow always marks the result incomplete, regardless of later completion.
51
+ Finding paths, titles, and bodies retain their 512, 200, and 2,000-character bounds.
52
+
53
+ ## Coverage and limits
54
+
55
+ Requests admit up to 1,000 distinct changed paths, 2,000,000 characters per patch, and 8,000,000
56
+ patch characters overall. These are host input limits, separate from the model's working context.
57
+ Source hosts can apply additional authorization and admission bounds.
58
+
59
+ The host tracks diff ranges available to completed model requests. Merely issuing a read, repeating
60
+ a page, skipping ahead, or failing a tool does not establish complete coverage. `pendingPaths`
61
+ includes partially read files. `review_status` recovers saved findings and outstanding ranges;
62
+ its optional cursor pages through the current pending list. While a range remains unread,
63
+ `submit_review` returns a recoverable error with the next unread offset. The same run continues
64
+ under its original budgets. A native budget stop preserves the pending paths and findings as
65
+ incomplete; repeated completion refusals cannot restart the run or reset its allowance.
66
+ Reading all ranges is necessary, but it does not prove that the model assessed every behavior.
67
+
68
+ `review_status` also keeps a bounded investigation notebook for the lifetime of the review.
69
+ Replace it with `notes: { text, expectedRevision }`; text is limited to 4,000 characters and
70
+ stale revisions fail without overwriting newer notes. The response supplies the current text and
71
+ revision. Notes preserve unresolved questions, exact evidence references, and next checks across
72
+ rollover. They are model-authored context, never proof of coverage or a source of findings.
73
+ Only the accepted-update count (`notesUpdates`) leaves the review; note text is not persisted in
74
+ the outcome. Children cannot update the parent's notebook.
75
+
76
+ Completion means a source-based assessment of the admitted changes and material supported
77
+ hypotheses, not proof of correctness or an exhaustive audit of every dependency. The model can
78
+ report `blockedOn` only for specific unavailable evidence, naming the affected behavior and its
79
+ attempts to retrieve that evidence. It must still review the remaining patches. The bounded
80
+ reason is retained in the outcome and summary, forces incompleteness, and prevents resolutions.
81
+ Excluded artifacts, lack of live execution, and hypothetical uncertainty do not themselves
82
+ block assessment of the admitted change.
83
+
84
+ Every parent conversation has 128 model turns, 512 tool calls, four concurrent tools, and a five-minute deadline.
85
+ The default `compaction: "rollover"` strategy uses a 48,000-token working context to bound
86
+ context growth during large reviews. Hosts can select `compaction: "prune"`
87
+ and an integer `contextTokenLimit` from 16,000 to 128,000. These settings do not widen host input
88
+ admission or create new spending, turn, or tool allowances. Invalid options fail before model work.
89
+
90
+ Native rollover starts a fresh window without a summarizer call. Its bounded recovery excerpt
91
+ may omit unseen tool results, so undelivered diff pages remain unread and must be fetched again.
92
+ Already delivered ranges and saved findings survive. Both strategies support calling `new_context`
93
+ alone with a handoff; original instructions and the complete change index remain available.
94
+
95
+ Every measured outcome includes `compactions`, an array of emitted native `CompactionPerformed`
96
+ events containing only `kind`, `turn`, `tokensBeforeEstimate`, and `tokensAfterEstimate`.
97
+ An empty array means no event was emitted; absence means the outcome supplied no measurement.
98
+ The array is bounded to 512 entries and includes events retained before a typed failure. It does
99
+ not expose source or handoff text, and events alone do not distinguish automatic from requested
100
+ rollovers. Boundaries that fail before event emission are not counted.
101
+
102
+ Without `costControl`, the engine applies a cumulative 416,000-token policy with a 160,000-token
103
+ completion reserve. A host cost estimator alone does not disable it. With `costControl`, the
104
+ host reserves the full possible charge before each provider call, replacing that token quota.
105
+ The [GitHub Action](../../action/README.md) supplies spending admission for supported OpenAI models.
106
+ Recorded findings survive a cost stop without requiring another paid call. `reservedCostMicrousd`
107
+ reports maximum additional charges for sent requests whose usage remains unknown.
108
+
109
+ Token, turn, tool, or cost exhaustion is incomplete. Expected failures preserve recorded findings
110
+ and completed model attempts, including their accounting when no finding was recorded. Context/input-token
111
+ refusals return an incomplete token-exhausted outcome before paid inference when possible.
112
+ Failures before any model attempt, finding, or budget refusal remain typed. Defects and interruption propagate, and every
113
+ resource belongs to the review's Scope. Excluded host `unreviewedPaths` remain separately disclosed.
114
+ An empty result never proves that the repository is defect-free.
115
+
116
+ ## Optional research children
117
+
118
+ The default reviewer runs alone. Experiments can provide `research: { model, concurrency: 2 }`
119
+ to expose native `delegate_research`. Concurrency is either one or two (default two), with at
120
+ most two children established per review. Each child has six ordinary model turns, twelve tool
121
+ calls, a 60-second deadline, and a 32,000-token context using native pruning. The runtime can
122
+ reserve a final completion response after structural exhaustion. The host configures the child
123
+ model's output limit; the eval uses 4,000 tokens.
124
+
125
+ A delegation supplies one unresolved, falsifiable question whose answer could change a finding,
126
+ and one to three distinct admitted changed paths. Instructions ask neutrally for supporting or
127
+ refuting evidence and discourage generic second reviews; children use the same finding rubric.
128
+ The host selects their exact patches, rejecting more than 32,000 total patch characters.
129
+ Children receive the immutable revisions and current saved findings, and can use only the
130
+ three repository read tools, `record_finding`, and `finish_research`. The completion contains
131
+ an evidence summary and incomplete flag; findings go directly to the same canonical ledger.
132
+ Children cannot delegate further, establish parent diff coverage, or resolve prior reviews.
133
+
134
+ Native reservations and child fibers belong to the review's Scope. Child compaction cannot
135
+ change the parent's unread ranges. Child model requirements remain visible in the review's
136
+ Effect requirements, and usage contributes to the existing accounting. A host supplying
137
+ `costControl` must use the same admission service for both model layers, so all requests draw
138
+ from one spending cap. Without host admission, the parent and child native token policies are
139
+ separate; the parent token quota is not a combined spending cap.
140
+
141
+ Research-enabled runs break equal-severity finding ties by their complete serialized values
142
+ before retaining 24, so child completion order cannot select the survivors. Exact duplicates
143
+ are still the only records removed. A rejected delegation, failed or interrupted child,
144
+ unfinished join, child-reported incomplete result, or child budget exhaustion makes the parent
145
+ incomplete and suppresses resolutions. Defects and external interruption still propagate.
146
+
147
+ Measured outcomes include `research` counters: `delegations` counts declared delegation calls;
148
+ `started`, `completed`, `failed`, and `interrupted` count emitted native child events; `incomplete`
149
+ counts completed child results that report incomplete or exhausted work. Zero counts are measured
150
+ zero, while an absent field means no measurement was supplied. Counts contain no child source,
151
+ summary, or transcript; prestart refusals have a declaration but no child event.
152
+
153
+ ## Follow-ups and hosting
154
+
155
+ Hosts can supply up to eight prior `ReviewFollowUp` values, each up to 32,000 characters. The
156
+ reviewer verifies every blocker in a follow-up against current source before returning its exact
157
+ ID and fixing evidence. Unknown or duplicate resolution IDs fail verification. Incomplete,
158
+ exhausted, pending-path, or excluded-path results return no resolutions. History selection,
159
+ credentials, dismissal authorization, and publication belong to the host.
87
160
 
88
161
  ```ts
89
- import {
90
- fixturePullRequestSourceLayer,
91
- collectingReviewPublisherLayer,
92
- makeOfflineReviewerModel,
93
- makePromptKeyedModel,
94
- } from "@effect-agent/pr-review/testing";
162
+ const reviewer = makeReviewer({ model, guidance, costControl });
163
+ const program = reviewer.review(request).pipe(Effect.provideService(ReviewRepository, repository));
95
164
  ```
96
165
 
97
- Deterministic in-memory adapters for both ports plus prompt-keyed scripted
98
- models that walk the real tool surface no network, no credentials, every
99
- ordinary gate.
100
-
101
- ## Incremental Action reviews
102
-
103
- A completely covered posted Action review carries bounded, versioned,
104
- HMAC-authenticated continuity state:
105
- the exact PR/base/head lineage, profile and accepted-scope fingerprints, and
106
- the still-unresolved findings and concerns. A later Action run validates the
107
- state and reviews the GitHub comparison from that reviewed head to the
108
- current head, not the complete base...HEAD diff. Unchanged accepted scope is
109
- not sent back to the model; unchanged unresolved findings remain active;
110
- changed or reverted paths invalidate their prior findings. Non-anchored
111
- concerns are carried conservatively until a full audit because they cannot be
112
- mapped safely to one path.
113
-
114
- The state marker must be terminal, signed with the configured stable
115
- `PR_REVIEW_STATE_SECRET`, authored by the default GitHub Actions bot, and
116
- pinned to the reviewed commit. State lookup, authentication, schema, identity,
117
- ancestry, profile, and comparison checks are
118
- fail-closed for scope selection: missing, stale, incompatible, or truncated
119
- state/comparisons produce a visible full-diff fallback. An ancestor base
120
- advance remains incremental and adds overlapping PR paths as affected
121
- context; a materially changed base lineage falls back to full. Re-running the
122
- same covered head skips model execution by default while preserving its
123
- stored blocking/success conclusion.
124
-
125
- After a new state-bearing Action review posts, prior marker-bearing bot reviews
126
- are retired by default: their bodies become collapsed, superseded history,
127
- resolved findings are struck through, and matching inline comments are
128
- minimized as outdated. Only strictly older reviews from the same GitHub actor
129
- are eligible, so copied markers and newer concurrent reviews are untouched.
130
- The machine-state comments remain byte-identical and terminal, so an edited
131
- body still participates in incremental state recovery.
132
- This cosmetic pass is fail-open and can be disabled with the Action input
133
- `retire-stale-reviews: "false"`.
134
-
135
- Authentication is an explicit Effect service supplied by the Action host;
136
- WebCrypto import/sign/verify failures stay typed. The terminal marker is
137
- schema-branded and capped at 24,000 characters. If signing fails or state
138
- exceeds that bound, the completed review is posted without continuity state
139
- and with a bounded warning, so the next run safely performs a full review.
140
-
141
- `review-mode: final` is the explicit bounded merge-readiness audit. It reviews
142
- the full current PR diff and resets the incremental baseline; normal
143
- `synchronize` events use `incremental` and do not perform this audit.
144
-
145
- ## Hosts
146
-
147
- - **GitHub Actions**: the repository ships a prebuilt node-runtime action
148
- supporting a committed review-profile document via `guidance-file` (this
149
- repository's own profile lives at `.github/review-guidance.md`)
150
- (`action/` at the repo root) — `uses` it with an API-key secret and nothing
151
- else. For custom reviewers in CI, `@effect-agent/pr-review/action` exports
152
- `runReviewAction` (event resolution, typed draft/non-PR skips, bounded range
153
- selection, step outputs, and conservative check gate) to harness your own
154
- `reviewer.run`.
155
- - **CLI**: `bun src/cli.ts --repo owner/name --pr 123 [--post] [--provider anthropic] [--fan-out]`
156
- (also exported as the `./cli` entry).
157
-
158
- Environment: `OPENAI_API_KEY` or `ANTHROPIC_API_KEY` for the model,
159
- `PR_REVIEW_STATE_SECRET` to authenticate incremental state,
160
- `GITHUB_TOKEN` to post (optional for public-repository reads), and the
161
- standard `GITHUB_REPOSITORY` / `GITHUB_EVENT_PATH` / `GITHUB_API_URL`
162
- variables inside Actions.
163
-
164
- ## Bounds, spelled out
165
-
166
- Finite `AgentPolicy` on every definition plus run-level `UsageBudgetLimits`
167
- (tokens, tool calls, cost, duration). Reading a file head version beyond 200k
168
- characters is refused typed. The changeset surface is bounded at 300 files:
169
- files beyond the bound are not fetched, and the review body reports
170
- `Reviewed N of M changed files` instead of claiming completeness. Fan-out
171
- capacity overflow is reported in the review summary, never dropped. Any
172
- blocking active finding fails the Action check. Any required-file coverage
173
- gap — undiffable/unassigned paths, failed units (including policy exhaustion),
174
- truncation, or coordinator/run failure — is non-success rather than green.
166
+ `ReviewRepository` implementations provide typed Effect operations for `readFile`, `findFiles`,
167
+ and `searchCode`. Hosts authorize source sent to models, pin immutable revisions, enforce read
168
+ bounds, and treat all source and model output as untrusted. The reviewer has no ambient filesystem
169
+ or network access. `ReviewSource.fromText` applies the shared source-range bounds.
170
+
171
+ The navigable diff approach is informed by [Pullfrog's review workflow](https://github.com/pullfrog/pullfrog/blob/0212dedb0f92b8ba4020c17dc30d3eced32415d7/modes.ts)
172
+ and [Codex's review task](https://github.com/openai/codex/blob/588b781ab4924ce7352488394028e63d74cf807f/codex-rs/core/src/tasks/review.rs).
173
+ These designs do not establish accuracy. The [eval bench](../../tooling/pr-review-eval/README.md)
174
+ measures first-trial detection, false positives, and incomplete runs against adjudicated cases.
175
+ Portions of the original review instructions were adapted from
176
+ [PR-Agent](https://github.com/The-PR-Agent/pr-agent); see `NOTICE` for its MIT attribution.