@effect-agent/pr-review 0.1.0-beta.6 → 0.1.0-beta.9
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 +10 -0
- package/dist/action.d.mts +9 -4
- package/dist/action.mjs +22 -5
- package/dist/action.mjs.map +1 -1
- package/dist/cli.mjs +4 -3
- package/dist/cli.mjs.map +1 -1
- package/dist/{fan-out-cMt8_Olv.d.mts → fan-out-C6gq3CFg.d.mts} +136 -46
- package/dist/{github-CcCtaWZD.mjs → github-Lfa_ox-u.mjs} +349 -44
- package/dist/github-Lfa_ox-u.mjs.map +1 -0
- package/dist/index.d.mts +15 -14
- package/dist/index.mjs +3 -3
- package/dist/{providers-5J9VeLkX.mjs → providers-CaOnz7mK.mjs} +5 -4
- package/dist/{providers-5J9VeLkX.mjs.map → providers-CaOnz7mK.mjs.map} +1 -1
- package/dist/testing.d.mts +3 -2
- package/dist/testing.mjs +5 -3
- package/dist/testing.mjs.map +1 -1
- package/package.json +20 -20
- package/src/action.ts +32 -1
- package/src/cli.ts +2 -1
- package/src/index.ts +1 -0
- package/src/internal/action-entry.ts +1 -0
- package/src/internal/fan-out-scripted.ts +2 -1
- package/src/internal/fan-out.ts +65 -74
- package/src/internal/fixtures.ts +5 -1
- package/src/internal/github-env.ts +20 -6
- package/src/internal/github.ts +232 -2
- package/src/internal/retirement.ts +332 -0
- package/src/internal/review-agent.ts +6 -3
- package/dist/github-CcCtaWZD.mjs.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"providers-5J9VeLkX.mjs","names":["severityRank","resolveReviewGuidance"],"sources":["../src/internal/coverage.ts","../src/internal/effort.ts","../src/internal/ignore.ts","../src/internal/render.ts","../src/internal/run.ts","../src/internal/factory.ts","../src/internal/github-env.ts","../src/internal/providers.ts"],"sourcesContent":["import { Option, Schema } from \"effect\";\nimport type { RunEvent } from \"effect-agent\";\n\nimport type { ChangedFile } from \"./diff.ts\";\nimport { FileReviewDelegationFailure, FileReviewRequest, FileReviewUnitResult } from \"./fan-out.ts\";\nimport { FileDiffQuery } from \"./review-agent.ts\";\nimport { planReviewUnits } from \"./review-units.ts\";\n\n// ---------------------------------------------------------------------------\n// Host-owned coverage. Model summaries are untrusted prose; the check result\n// is based on deterministic unit planning plus the semantic Tool events that\n// prove which required review operations actually settled successfully.\n// ---------------------------------------------------------------------------\n\nexport const ReviewShape = Schema.Literals([\"flat\", \"fan-out\"]);\nexport type ReviewShape = typeof ReviewShape.Type;\n\nexport class FailedReviewUnit extends Schema.Class<FailedReviewUnit>(\n \"@effect-agent/pr-review/FailedReviewUnit\",\n)({\n unitId: Schema.NonEmptyString.check(Schema.isMaxLength(32)),\n errorTag: Schema.NonEmptyString.check(Schema.isMaxLength(256)),\n}) {}\n\nexport class ReviewCoverage extends Schema.Class<ReviewCoverage>(\n \"@effect-agent/pr-review/ReviewCoverage\",\n)({\n status: Schema.Literals([\"complete\", \"incomplete\"]),\n requiredPaths: Schema.Array(Schema.NonEmptyString.check(Schema.isMaxLength(512))).check(\n Schema.isMaxLength(300),\n ),\n reviewedPaths: Schema.Array(Schema.NonEmptyString.check(Schema.isMaxLength(512))).check(\n Schema.isMaxLength(300),\n ),\n unreviewedPaths: Schema.Array(Schema.NonEmptyString.check(Schema.isMaxLength(512))).check(\n Schema.isMaxLength(300),\n ),\n failedUnits: Schema.Array(FailedReviewUnit).check(Schema.isMaxLength(8)),\n reasons: Schema.Array(Schema.NonEmptyString.check(Schema.isMaxLength(1_000))).check(\n Schema.isMaxLength(20),\n ),\n}) {}\n\ninterface ToolTrace {\n readonly declared: Map<string, Extract<RunEvent, { readonly _tag: \"ToolCallDeclared\" }>>;\n readonly succeeded: Map<string, Extract<RunEvent, { readonly _tag: \"ToolCallSucceeded\" }>>;\n readonly failed: Map<string, Extract<RunEvent, { readonly _tag: \"ToolCallFailed\" }>>;\n}\n\nconst toolTrace = (events: ReadonlyArray<RunEvent>): ToolTrace => {\n const declared = new Map<string, Extract<RunEvent, { readonly _tag: \"ToolCallDeclared\" }>>();\n const succeeded = new Map<string, Extract<RunEvent, { readonly _tag: \"ToolCallSucceeded\" }>>();\n const failed = new Map<string, Extract<RunEvent, { readonly _tag: \"ToolCallFailed\" }>>();\n for (const event of events) {\n if (event._tag === \"ToolCallDeclared\") declared.set(event.toolCallId, event);\n if (event._tag === \"ToolCallSucceeded\") succeeded.set(event.toolCallId, event);\n if (event._tag === \"ToolCallFailed\") failed.set(event.toolCallId, event);\n }\n return { declared, succeeded, failed };\n};\n\nconst sortedUnique = (values: Iterable<string>): ReadonlyArray<string> =>\n [...new Set(values)].sort((left, right) => (left < right ? -1 : left > right ? 1 : 0));\n\nconst boundedListReason = (label: string, values: Iterable<string>): string => {\n const items = sortedUnique(values);\n const prefix = `${label} (${items.length}): `;\n let rendered = prefix;\n for (let index = 0; index < items.length; index += 1) {\n const item = items[index] ?? \"\";\n const separator = index === 0 ? \"\" : \", \";\n const omitted = items.length - index - 1;\n const suffix = omitted === 0 ? \"\" : ` … (+${omitted} more)`;\n if (`${rendered}${separator}${item}${suffix}`.length > 1_000) {\n const omission = `… (+${items.length - index} more)`;\n return `${rendered.slice(0, 1_000 - omission.length)}${omission}`;\n }\n rendered = `${rendered}${separator}${item}`;\n }\n return rendered;\n};\n\nconst flatCoverage = (\n files: ReadonlyArray<ChangedFile>,\n totalFiles: number,\n trace: ToolTrace,\n): ReviewCoverage => {\n const requiredPaths = sortedUnique(files.map((file) => file.path));\n const reviewed = new Set<string>();\n const failedPaths = new Set<string>();\n for (const [toolCallId, declaration] of trace.declared) {\n if (declaration.toolName !== \"read_file_diff\") continue;\n const query = Schema.decodeUnknownOption(FileDiffQuery)(declaration.parameters);\n if (Option.isNone(query)) continue;\n if (trace.succeeded.has(toolCallId)) reviewed.add(query.value.path);\n if (trace.failed.has(toolCallId)) failedPaths.add(query.value.path);\n }\n const undiffable = files.filter((file) => file.patch === undefined).map((file) => file.path);\n const unreviewed = requiredPaths.filter(\n (path) => !reviewed.has(path) || undiffable.includes(path) || failedPaths.has(path),\n );\n const reasons: Array<string> = [];\n if (files.length < totalFiles) {\n reasons.push(`review range exposed ${files.length} of ${totalFiles} required files`);\n }\n if (undiffable.length > 0) {\n reasons.push(boundedListReason(\"required paths have no textual diff\", undiffable));\n }\n if (failedPaths.size > 0) {\n reasons.push(boundedListReason(\"diff reads failed\", failedPaths));\n }\n if (unreviewed.length > 0) {\n reasons.push(boundedListReason(\"required paths were not successfully reviewed\", unreviewed));\n }\n return ReviewCoverage.make({\n status: reasons.length === 0 ? \"complete\" : \"incomplete\",\n requiredPaths,\n reviewedPaths: sortedUnique(reviewed),\n unreviewedPaths: sortedUnique(unreviewed),\n failedUnits: [],\n reasons,\n });\n};\n\nconst fanOutCoverage = (\n files: ReadonlyArray<ChangedFile>,\n totalFiles: number,\n trace: ToolTrace,\n): ReviewCoverage => {\n const plan = planReviewUnits(files, { totalChangedFiles: totalFiles });\n const declarationsByUnit = new Map<\n string,\n Array<{ readonly id: string; readonly paths: ReadonlyArray<string> }>\n >();\n for (const [toolCallId, declaration] of trace.declared) {\n if (declaration.toolName !== \"delegate_file_review\") continue;\n const request = Schema.decodeUnknownOption(FileReviewRequest)(declaration.parameters);\n if (Option.isNone(request)) continue;\n const declarations = declarationsByUnit.get(request.value.unitId) ?? [];\n declarations.push({ id: toolCallId, paths: request.value.paths });\n declarationsByUnit.set(request.value.unitId, declarations);\n }\n\n const reviewed = new Set<string>();\n const unreviewed = new Set<string>([...plan.undiffablePaths, ...plan.unassignedPaths]);\n const failedUnits: Array<FailedReviewUnit> = [];\n const reasons: Array<string> = [];\n for (const unit of plan.units) {\n const declarations = declarationsByUnit.get(unit.unitId) ?? [];\n const expectedPaths = [...unit.paths];\n const exact = declarations.filter(\n (declaration) =>\n declaration.paths.length === expectedPaths.length &&\n declaration.paths.every((path, index) => path === expectedPaths[index]),\n );\n const successful = exact.filter((declaration) => {\n const event = trace.succeeded.get(declaration.id);\n if (event === undefined || trace.failed.has(declaration.id)) return false;\n const result = Schema.decodeUnknownOption(FileReviewUnitResult)(event.result);\n return Option.isSome(result) && result.value.unitId === unit.unitId;\n });\n if (declarations.length === 1 && exact.length === 1 && successful.length === 1) {\n for (const path of unit.paths) reviewed.add(path);\n continue;\n }\n for (const path of unit.paths) unreviewed.add(path);\n const failure = declarations\n .map((declaration) => trace.failed.get(declaration.id))\n .find((event) => event !== undefined);\n const returnedFailure = declarations\n .map((declaration) => trace.succeeded.get(declaration.id))\n .filter((event) => event !== undefined)\n .map((event) => Schema.decodeUnknownOption(FileReviewDelegationFailure)(event.result))\n .find(Option.isSome);\n failedUnits.push(\n FailedReviewUnit.make({\n unitId: unit.unitId,\n errorTag:\n failure?.errorTag ??\n (returnedFailure !== undefined\n ? returnedFailure.value._tag === \"FileReviewUnitFailed\"\n ? `${returnedFailure.value._tag}:${returnedFailure.value.childErrorTag}`\n : returnedFailure.value._tag\n : undefined) ??\n (declarations.length === 0\n ? \"UnitNotAssigned\"\n : declarations.length > 1\n ? \"UnitAssignedMultipleTimes\"\n : exact.length === 0\n ? \"UnitAssignmentMismatch\"\n : \"UnitDidNotSettleSuccessfully\"),\n }),\n );\n }\n if (plan.truncated) {\n reasons.push(`review range exposed ${files.length} of ${totalFiles} required files`);\n }\n if (plan.undiffablePaths.length > 0) {\n reasons.push(boundedListReason(\"required paths have no textual diff\", plan.undiffablePaths));\n }\n if (plan.unassignedPaths.length > 0) {\n reasons.push(boundedListReason(\"fan-out capacity left paths unassigned\", plan.unassignedPaths));\n }\n if (failedUnits.length > 0) {\n reasons.push(\n boundedListReason(\n \"review units did not complete\",\n failedUnits.map((unit) => `${unit.unitId} (${unit.errorTag})`),\n ),\n );\n }\n return ReviewCoverage.make({\n status: reasons.length === 0 ? \"complete\" : \"incomplete\",\n requiredPaths: sortedUnique(files.map((file) => file.path)),\n reviewedPaths: sortedUnique(reviewed),\n unreviewedPaths: sortedUnique(unreviewed),\n failedUnits,\n reasons,\n });\n};\n\n/** Assess one settled run without trusting its prose summary or verdict. */\nexport const assessReviewCoverage = (input: {\n readonly shape: ReviewShape;\n readonly files: ReadonlyArray<ChangedFile>;\n readonly totalFiles: number;\n readonly anchorFiles: ReadonlyArray<ChangedFile>;\n readonly totalAnchorFiles: number;\n readonly events: ReadonlyArray<RunEvent>;\n}): ReviewCoverage => {\n const trace = toolTrace(input.events);\n const coverage =\n input.shape === \"fan-out\"\n ? fanOutCoverage(input.files, input.totalFiles, trace)\n : flatCoverage(input.files, input.totalFiles, trace);\n if (input.anchorFiles.length >= input.totalAnchorFiles) return coverage;\n return ReviewCoverage.make({\n ...coverage,\n status: \"incomplete\",\n reasons: [\n ...coverage.reasons,\n `full pull-request anchor surface exposed ${input.anchorFiles.length} of ${input.totalAnchorFiles} required files`,\n ],\n });\n};\n","import { Schema } from \"effect\";\n\n// ---------------------------------------------------------------------------\n// Reasoning effort, stored as a POSITION on [0, 1] rather than a rung name.\n// A rung name is only meaningful inside the provider that published it: the\n// same word can be one provider's floor and another's midpoint, and a stored\n// name silently changes meaning when the model under the setting changes. A\n// position has no such problem: 0 is whatever the provider calls its cheapest\n// offered rung and 1 its most expensive, and resolution is a lookup into that\n// provider's own ladder — the result is always a rung the provider offers.\n// ---------------------------------------------------------------------------\n\n/** A point on the effort axis: 0 = cheapest offered rung, 1 = most expensive. */\nexport type EffortPosition = number;\n\n/**\n * Names accepted on user-facing surfaces (the action input, the CLI flag),\n * mapped to fixed points on the axis. These same names anchor every offered\n * rung during resolution, so a named input always lands on its same-named\n * rung when the provider offers it — `high` never resolves to `medium` just\n * because a ladder is short.\n */\nexport const EFFORT_ALIASES = {\n low: 0,\n medium: 0.25,\n high: 0.5,\n xhigh: 0.75,\n max: 1,\n} as const satisfies Readonly<Record<string, EffortPosition>>;\n\n/** A rung name every provider ladder must draw from. */\nexport type EffortAliasName = keyof typeof EFFORT_ALIASES;\n\nconst aliasPosition: Readonly<Record<string, EffortPosition | undefined>> = EFFORT_ALIASES;\n\n/** An effort input that is neither a known name nor a number on [0, 1]. */\nexport class InvalidEffortInput extends Schema.TaggedError<InvalidEffortInput>()(\n \"InvalidEffortInput\",\n {\n input: Schema.String,\n },\n) {\n override get message() {\n return (\n `Invalid effort '${this.input}': expected one of ` +\n `${Object.keys(EFFORT_ALIASES).join(\", \")} or a number between 0 and 1.`\n );\n }\n}\n\nexport const isEffortPosition = (value: number): boolean =>\n Number.isFinite(value) && value >= 0 && value <= 1;\n\n/**\n * Parse a user-supplied effort into a position: a name (`high`) or a bare\n * number (`0.75`). Returns undefined for anything else so the caller can fail\n * typed — a typo must stay visible, never silently become a level.\n */\nexport const parseEffortPosition = (raw: string): EffortPosition | undefined => {\n const normalized = raw.trim().toLowerCase();\n const named = aliasPosition[normalized];\n if (named !== undefined) return named;\n if (normalized === \"\") return undefined;\n const numeric = Number(normalized);\n return isEffortPosition(numeric) ? numeric : undefined;\n};\n\n/**\n * Land a position on one provider's offered ladder: the highest offered rung\n * whose canonical alias position is at or below the requested position.\n * Anchoring on the alias positions (instead of scaling by ladder index) keeps\n * two properties at once: a named input lands on its same-named rung whenever\n * the provider offers it, and anything between rungs rounds DOWN so\n * resolution never costs more than was asked for.\n */\nexport const resolveEffortRung = <const Rung extends EffortAliasName>(\n position: EffortPosition,\n rungs: readonly [Rung, ...ReadonlyArray<Rung>],\n): Rung => {\n const clamped = Math.min(1, Math.max(0, position));\n let selected = rungs[0];\n for (const rung of rungs) {\n if (EFFORT_ALIASES[rung] <= clamped) selected = rung;\n }\n return selected;\n};\n","import { Effect, Layer } from \"effect\";\n\nimport { PullRequestMetadata, PullRequestSource, ReviewInputViolation } from \"./source.ts\";\n\n// ---------------------------------------------------------------------------\n// Configured ignore globs, applied at the source port. Ignored files are\n// removed from the reviewer's entire observation surface — the changeset\n// list, diffs, and head reads — so the model never spends budget on them and\n// can never anchor a finding to them. Filtering fails closed: reading an\n// ignored path is a ReviewInputViolation, exactly like a path outside the\n// changeset.\n// ---------------------------------------------------------------------------\n\nconst REGEX_SPECIALS = /[.+^${}()|[\\]\\\\]/g;\n\n// Placeholders for the directory-crossing wildcard while single-segment\n// wildcards are rewritten; NUL/SOH cannot appear in a valid repository path.\nconst CROSSING_SLASH = \"\\u0000\";\nconst CROSSING = \"\\u0001\";\n\n/**\n * The supported glob vocabulary is deliberately minimal: `**` crosses\n * directory separators, `*` and `?` stay within one path segment, everything\n * else is literal. Every string compiles — there is no invalid pattern.\n */\nconst globToRegExpSource = (pattern: string): string =>\n pattern\n .replace(REGEX_SPECIALS, String.raw`\\$&`)\n .replaceAll(\"**/\", CROSSING_SLASH)\n .replaceAll(\"**\", CROSSING)\n .replaceAll(\"*\", \"[^/]*\")\n .replaceAll(\"?\", \"[^/]\")\n .replaceAll(CROSSING_SLASH, \"(?:.*/)?\")\n .replaceAll(CROSSING, \".*\");\n\n/** Compile ignore globs into one predicate over repository-relative paths. */\nexport const compileIgnoreGlobs = (\n patterns: ReadonlyArray<string>,\n): ((path: string) => boolean) => {\n if (patterns.length === 0) return () => false;\n const expressions = patterns.map((pattern) => new RegExp(`^(?:${globToRegExpSource(pattern)})$`));\n return (path) => expressions.some((expression) => expression.test(path));\n};\n\n/**\n * Decorate the ambient PullRequestSource with configured ignore globs. The\n * resulting Layer requires the undecorated source, so callers provide their\n * real adapter beneath it. Metadata's changed-file total is reduced by the\n * ignored count: from the reviewer's perspective the ignored files do not\n * exist, and truncation reporting stays about the reviewer's own bound.\n */\nexport const ignoringPullRequestSourceLayer = (\n patterns: ReadonlyArray<string>,\n): Layer.Layer<PullRequestSource, never, PullRequestSource> =>\n Layer.effect(PullRequestSource)(\n Effect.gen(function* () {\n const source = yield* PullRequestSource;\n const ignored = compileIgnoreGlobs(patterns);\n const changedFiles = source.changedFiles.pipe(\n Effect.map((files) => files.filter((file) => !ignored(file.path))),\n );\n const anchorFiles = source.anchorFiles.pipe(\n Effect.map((files) => files.filter((file) => !ignored(file.path))),\n );\n const metadata = Effect.gen(function* () {\n const [meta, files] = yield* Effect.all([source.metadata, source.anchorFiles]);\n const ignoredCount = files.filter((file) => ignored(file.path)).length;\n return PullRequestMetadata.make({\n ...meta,\n totalChangedFiles: Math.max(0, meta.totalChangedFiles - ignoredCount),\n });\n });\n return PullRequestSource.of({\n metadata,\n changedFiles,\n anchorFiles,\n readFile: (path) =>\n ignored(path)\n ? Effect.fail(\n ReviewInputViolation.make({\n input: path,\n reason: \"Path is excluded from this review by configuration.\",\n }),\n )\n : source.readFile(path),\n });\n }),\n );\n","import { Schema } from \"effect\";\n\nimport type { ReviewCoverage } from \"./coverage.ts\";\nimport { commentableLines, type ChangedFile } from \"./diff.ts\";\nimport { renderFingerprintMarker } from \"./fingerprint.ts\";\nimport { ReviewFinding, type CodeReview, type ReviewConcern } from \"./review-agent.ts\";\nimport type { ReviewScopeMode, ReviewStateMarker } from \"./review-state.ts\";\n\n// ---------------------------------------------------------------------------\n// Publication planning: pure, deterministic, and fail-closed. Model output is\n// untrusted input, so every finding anchor is validated against the parsed\n// diff before it may become an inline comment; findings that fail validation\n// are demoted into the review body instead of being dropped or trusted. This\n// module is deliberately not configurable — customization widens what goes\n// into a review, never what leaves it unvalidated.\n// ---------------------------------------------------------------------------\n\nexport const ReviewEvent = Schema.Literals([\"COMMENT\", \"APPROVE\", \"REQUEST_CHANGES\"]);\nexport type ReviewEvent = typeof ReviewEvent.Type;\n\n/** One inline comment exactly as the GitHub review API accepts it. */\nexport class ReviewCommentDraft extends Schema.Class<ReviewCommentDraft>(\n \"@effect-agent/pr-review/ReviewCommentDraft\",\n)({\n path: Schema.NonEmptyString,\n /** The last (or only) commented line, RIGHT side of the diff. */\n line: Schema.Int.check(Schema.isGreaterThan(0)),\n /** Present only for multi-line comments; strictly less than `line`. */\n startLine: Schema.optionalKey(Schema.Int.check(Schema.isGreaterThan(0))),\n body: Schema.NonEmptyString,\n}) {}\n\n/** The complete, validated review ready for one GitHub reviews API call. */\nexport class ReviewPublicationPlan extends Schema.Class<ReviewPublicationPlan>(\n \"@effect-agent/pr-review/ReviewPublicationPlan\",\n)({\n event: ReviewEvent,\n body: Schema.String.check(Schema.isMaxLength(60_000)),\n comments: Schema.Array(ReviewCommentDraft),\n /** Findings whose anchors failed diff validation; folded into `body`. */\n demoted: Schema.Array(ReviewFinding),\n /** The head commit the diffs were fetched at; pins the posted review. */\n commitSha: Schema.NonEmptyString.check(Schema.isMaxLength(64)),\n}) {}\n\nconst severityEmoji: Record<ReviewFinding[\"severity\"], string> = {\n blocking: \"🛑\",\n important: \"⚠️\",\n nit: \"💅\",\n};\n\nconst severityRank: Record<ReviewFinding[\"severity\"], number> = {\n blocking: 0,\n important: 1,\n nit: 2,\n};\n\nconst severityLabel: Record<ReviewFinding[\"severity\"], string> = {\n blocking: `${severityEmoji.blocking} blocking`,\n important: `${severityEmoji.important} important`,\n nit: `${severityEmoji.nit} nit`,\n};\n\n/** A fence long enough that the suggestion content can never close it early. */\nconst suggestionFence = (suggestion: string): string => {\n let fence = \"```\";\n while (suggestion.includes(fence)) fence = `${fence}\\``;\n return fence;\n};\n\nconst renderCommentBody = (finding: ReviewFinding): string => {\n const parts = [`**[${severityLabel[finding.severity]}] ${finding.title}**`, \"\", finding.body];\n if (finding.suggestion !== undefined) {\n const fence = suggestionFence(finding.suggestion);\n parts.push(\"\", `${fence}suggestion`, finding.suggestion, fence);\n }\n return parts.join(\"\\n\");\n};\n\nconst renderDemoted = (finding: ReviewFinding, reason: string): string => {\n const location = `\\`${finding.path}:${finding.startLine}${\n finding.endLine !== finding.startLine ? `-${finding.endLine}` : \"\"\n }\\``;\n return `- ${location} **[${severityLabel[finding.severity]}] ${finding.title}** — ${finding.body} _(demoted: ${reason})_`;\n};\n\nconst countNoun = (count: number, noun: string): string =>\n `${count} ${noun}${count === 1 ? \"\" : \"s\"}`;\n\n/** The validated finding + concern severities, tallied for callout and event. */\nconst severityCounts = (\n review: CodeReview,\n carriedFindings: ReadonlyArray<ReviewFinding> = [],\n carriedConcerns: ReadonlyArray<ReviewConcern> = [],\n) => {\n const severities = [\n ...review.findings.map((finding) => finding.severity),\n ...(review.concerns ?? []).map((concern) => concern.severity),\n ...carriedFindings.map((finding) => finding.severity),\n ...carriedConcerns.map((concern) => concern.severity),\n ];\n return {\n blocking: severities.filter((severity) => severity === \"blocking\").length,\n important: severities.filter((severity) => severity === \"important\").length,\n total: severities.length,\n };\n};\n\n/**\n * The opening callout: the review's overall tier, derived HOST-SIDE from the\n * validated severities (never from model prose), described by what GitHub\n * renders it as. `[!CAUTION]` is a red banner, `[!IMPORTANT]` a purple one;\n * the blockquote tiers read as informational.\n */\nconst renderVerdictCallout = (\n review: CodeReview,\n options: {\n readonly carriedFindings?: ReadonlyArray<ReviewFinding> | undefined;\n readonly carriedConcerns?: ReadonlyArray<ReviewConcern> | undefined;\n readonly coverage?: ReviewCoverage | undefined;\n },\n): string => {\n const counts = severityCounts(review, options.carriedFindings, options.carriedConcerns);\n if (options.coverage?.status === \"incomplete\") {\n const suffix =\n counts.blocking > 0 ? ` It also has ${countNoun(counts.blocking, \"blocking finding\")}.` : \"\";\n return `> [!CAUTION]\\n> Review coverage is incomplete — the check must not pass.${suffix}`;\n }\n if (counts.blocking > 0) {\n return `> [!CAUTION]\\n> ${countNoun(counts.blocking, \"blocking finding\")} — do not merge before addressing ${counts.blocking === 1 ? \"it\" : \"them\"}.`;\n }\n if (counts.important > 0) {\n return `> [!IMPORTANT]\\n> ${countNoun(counts.important, \"important finding\")} to address before merging.`;\n }\n if (counts.total > 0) {\n return \"> ℹ️ Minor suggestions only — mergeable as-is.\";\n }\n return review.verdict === \"approve\"\n ? \"> ✅ No issues found.\"\n : \"> ℹ️ No findings — see the summary.\";\n};\n\nconst renderConcern = (concern: ReviewConcern): string =>\n [`### ${severityEmoji[concern.severity]} ${concern.title}`, \"\", concern.body].join(\"\\n\");\n\nconst renderCarriedFinding = (finding: ReviewFinding): string =>\n `- \\`${finding.path}:${finding.startLine}${finding.endLine === finding.startLine ? \"\" : `-${finding.endLine}`}\\` **[${severityLabel[finding.severity]}] ${finding.title}** — ${finding.body}`;\n\n/** HTML comments must not contain `--`; interpolated values are sanitized. */\nconst commentSafe = (value: string): string => value.replaceAll(\"--\", \"- -\");\n\n/**\n * The invisible staleness note addressed to whoever reads the review later —\n * a human or a downstream agent: which commit the findings were written\n * against, and that line callouts age the moment new commits land.\n */\nconst renderReviewMetadata = (options: {\n readonly headSha: string;\n readonly baseRef?: string | undefined;\n readonly headRef?: string | undefined;\n readonly filesVisible: number;\n readonly totalChangedFiles: number;\n readonly reviewMode?: ReviewScopeMode | undefined;\n readonly baselineSha?: string | undefined;\n}): string =>\n [\n \"<!-- effect-agent-pr-review metadata\",\n `reviewed-head: ${commentSafe(options.headSha)}`,\n ...(options.baseRef !== undefined && options.headRef !== undefined\n ? [`base-ref: ${commentSafe(options.baseRef)}`, `head-ref: ${commentSafe(options.headRef)}`]\n : []),\n // The observation surface, not a coverage claim: the host cannot know\n // which visible files the model actually examined, and the summary is\n // where unreviewed units are named.\n `files-visible: ${options.filesVisible} of ${options.totalChangedFiles}`,\n ...(options.reviewMode === undefined ? [] : [`review-mode: ${options.reviewMode}`]),\n ...(options.baselineSha === undefined\n ? []\n : [`incremental-baseline: ${commentSafe(options.baselineSha)}`]),\n \"Findings were written against the head commit above; if commits have landed\",\n \"since, treat file and line callouts as potentially stale and re-diff first.\",\n \"-->\",\n ].join(\"\\n\");\n\n/**\n * Why one finding cannot become an inline comment, or undefined when it can.\n * Exported so tests can pin each rule individually.\n */\nexport const anchorViolation = (\n finding: ReviewFinding,\n files: ReadonlyArray<ChangedFile>,\n): string | undefined => {\n const file = files.find((candidate) => candidate.path === finding.path);\n if (file === undefined) return \"path is not part of the changeset\";\n if (file.patch === undefined) return \"file has no textual diff\";\n if (finding.endLine < finding.startLine) return \"endLine precedes startLine\";\n if (finding.endLine - finding.startLine + 1 > 100) return \"range is implausibly large\";\n const anchors = commentableLines(file.patch);\n for (let line = finding.startLine; line <= finding.endLine; line += 1) {\n if (!anchors.has(line)) return `line ${line} is not part of the diff`;\n }\n return undefined;\n};\n\n/**\n * Turn one validated review into the exact GitHub publication payload.\n * `applyVerdict: false` (the safe default) always posts a COMMENT review;\n * `true` maps the model's verdict onto APPROVE / REQUEST_CHANGES.\n */\nexport const planPublication = (\n review: CodeReview,\n files: ReadonlyArray<ChangedFile>,\n options: {\n readonly applyVerdict: boolean;\n /** Head commit the changeset was fetched at (pins the posted review). */\n readonly headSha: string;\n /** GitHub's changed-file total, for honest truncation reporting. */\n readonly totalChangedFiles: number;\n /** Base/head refs for the staleness metadata comment. */\n readonly baseRef?: string | undefined;\n readonly headRef?: string | undefined;\n /** Provider binding descriptor rendered into the footer. */\n readonly modelLabel?: string | undefined;\n /** Workflow-run URL rendered into the footer. */\n readonly runUrl?: string | undefined;\n /** Observed run usage rendered into the footer. */\n readonly usage?: { readonly inputTokens: number; readonly outputTokens: number } | undefined;\n /** What the usage observed: the whole run, or the coordinator only. */\n readonly usageScope?: \"run\" | \"coordinator\" | undefined;\n /**\n * Changeset fingerprint embedded invisibly in the review body so a later\n * run can skip re-reviewing an unchanged changeset.\n */\n readonly fingerprint?: string | undefined;\n /** Host-owned coverage; incomplete coverage is rendered and fails the check. */\n readonly coverage?: ReviewCoverage | undefined;\n /** Unchanged unresolved items carried from the prior successfully reviewed head. */\n readonly carriedFindings?: ReadonlyArray<ReviewFinding> | undefined;\n readonly carriedConcerns?: ReadonlyArray<ReviewConcern> | undefined;\n /** Selected review scope, made visible whenever orchestration chose it. */\n readonly reviewMode?: ReviewScopeMode | undefined;\n readonly reviewReason?: string | undefined;\n readonly baselineSha?: string | undefined;\n readonly reviewFilesVisible?: number | undefined;\n readonly reviewTotalFiles?: number | undefined;\n /** Authenticated continuity state is emitted only after complete host-owned coverage. */\n readonly stateMarker?: ReviewStateMarker | undefined;\n /** Visible reason continuity state was omitted; the next run will review fully. */\n readonly stateNotice?: string | undefined;\n },\n): ReviewPublicationPlan => {\n const comments: Array<ReviewCommentDraft> = [];\n const demoted: Array<{ readonly finding: ReviewFinding; readonly reason: string }> = [];\n for (const finding of review.findings) {\n const violation = anchorViolation(finding, files);\n if (violation === undefined) {\n comments.push(\n ReviewCommentDraft.make({\n path: finding.path,\n line: finding.endLine,\n ...(finding.endLine > finding.startLine ? { startLine: finding.startLine } : {}),\n body: renderCommentBody(finding),\n }),\n );\n } else {\n demoted.push({ finding, reason: violation });\n }\n }\n\n // Rendered most-severe first so the size cap below sheds the least severe.\n const sortedConcerns = [...(review.concerns ?? [])].sort(\n (a, b) => severityRank[a.severity] - severityRank[b.severity],\n );\n const sortedDemoted = [...demoted].sort(\n (a, b) => severityRank[a.finding.severity] - severityRank[b.finding.severity],\n );\n\n const footerParts = [\"Automated review by @effect-agent/pr-review\"];\n if (options.modelLabel !== undefined) footerParts.push(options.modelLabel);\n // Usage renders only under an EXPLICIT scope: this planner cannot know\n // whether a budget snapshot observed the whole run or only a fan-out\n // coordinator, and omitting the number is honest where mislabeling is not.\n if (options.usage !== undefined && options.usageScope !== undefined) {\n const scope = options.usageScope === \"coordinator\" ? \" (coordinator)\" : \"\";\n footerParts.push(\n `${options.usage.inputTokens} in / ${options.usage.outputTokens} out tokens${scope}`,\n );\n }\n if (options.runUrl !== undefined) footerParts.push(`[run](${options.runUrl})`);\n footerParts.push(`reviewed at ${options.headSha.slice(0, 7)}`);\n const footer = `_${footerParts.join(\" · \")}._`;\n\n const renderHead = (concernsKept: number, demotedKept: number, omitted: number): string => {\n const carriedFindings = options.carriedFindings ?? [];\n const carriedConcerns = options.carriedConcerns ?? [];\n const parts = [\n renderVerdictCallout(review, {\n carriedFindings,\n carriedConcerns,\n coverage: options.coverage,\n }),\n ];\n if (options.reviewMode !== undefined && options.reviewReason !== undefined) {\n parts.push(\n \"\",\n options.reviewMode === \"incremental\"\n ? `**Incremental scope:** reviewed ${options.reviewFilesVisible ?? files.length} file(s) ${options.reviewReason}. Unchanged accepted scope was preserved and not reopened.`\n : `**Full-diff scope:** ${options.reviewReason}.`,\n );\n }\n if (options.stateNotice !== undefined) {\n parts.push(\n \"\",\n `⚠️ Continuity state was not stored (${options.stateNotice.slice(0, 1_000)}); the next run will safely review the full diff.`,\n );\n }\n parts.push(\"\", review.summary);\n if (options.coverage?.status === \"incomplete\") {\n parts.push(\n \"\",\n \"### 🛑 Incomplete coverage\",\n \"\",\n ...options.coverage.reasons.map((reason) => `- ${reason}`),\n );\n }\n if (carriedFindings.length > 0) {\n parts.push(\n \"\",\n \"### Unresolved findings carried from unchanged scope\",\n \"\",\n ...carriedFindings.map(renderCarriedFinding),\n );\n }\n if (carriedConcerns.length > 0) {\n parts.push(\"\", \"### Unresolved concerns carried to the final audit\");\n for (const concern of carriedConcerns) parts.push(\"\", renderConcern(concern));\n }\n for (const concern of sortedConcerns.slice(0, concernsKept)) {\n parts.push(\"\", renderConcern(concern));\n }\n if (files.length < options.totalChangedFiles) {\n parts.push(\n \"\",\n `⚠️ Reviewed ${files.length} of ${options.totalChangedFiles} changed files — the changeset exceeded the reviewer's file bound.`,\n );\n }\n if (demotedKept > 0) {\n parts.push(\n \"\",\n \"### Findings without a valid diff anchor\",\n ...sortedDemoted\n .slice(0, demotedKept)\n .map(({ finding, reason }) => renderDemoted(finding, reason)),\n );\n }\n if (omitted > 0) {\n parts.push(\n \"\",\n `⚠️ ${countNoun(omitted, \"review item\")} omitted — the body exceeded GitHub's review size cap.`,\n );\n }\n parts.push(\"\", footer);\n return parts.join(\"\\n\");\n };\n\n // The model's verdict may not contradict the reported severities (model\n // output is untrusted input): any blocking item forces REQUEST_CHANGES, a\n // review with no blocking item can never REQUEST_CHANGES, and an approval\n // is honored only when nothing blocking or important was reported — the\n // event always agrees with the callout tier. Demoted findings and concerns\n // count like anchored findings: anchor validation validates LOCATIONS, not\n // truth, so severity is equally model-claimed for all three, and counting\n // them only ever moves the event toward the closed direction.\n const counts = severityCounts(\n review,\n options.carriedFindings ?? [],\n options.carriedConcerns ?? [],\n );\n const event: ReviewEvent = !options.applyVerdict\n ? \"COMMENT\"\n : options.coverage?.status === \"incomplete\" || counts.blocking > 0\n ? \"REQUEST_CHANGES\"\n : review.verdict === \"approve\" && counts.important === 0\n ? \"APPROVE\"\n : \"COMMENT\";\n\n // The invisible tail (metadata + fingerprint marker) must survive the body\n // cap, so the cap reserves exactly the room it needs.\n const tail = [\n renderReviewMetadata({\n headSha: options.headSha,\n baseRef: options.baseRef,\n headRef: options.headRef,\n filesVisible: options.reviewFilesVisible ?? files.length,\n totalChangedFiles: options.reviewTotalFiles ?? options.totalChangedFiles,\n reviewMode: options.reviewMode,\n baselineSha: options.baselineSha,\n }),\n ...(options.fingerprint === undefined ? [] : [renderFingerprintMarker(options.fingerprint)]),\n ...(options.stateMarker === undefined ? [] : [options.stateMarker]),\n ].join(\"\\n\");\n const headBudget = 60_000 - tail.length - 1;\n\n // Shed whole trailing items — demoted bullets first (they already failed\n // validation), then concerns — instead of slicing markdown mid-block. Every\n // omission is announced, and `plan.demoted` keeps the full data regardless.\n let concernsKept = sortedConcerns.length;\n let demotedKept = sortedDemoted.length;\n let omitted = 0;\n let head = renderHead(concernsKept, demotedKept, omitted);\n while (head.length > headBudget && (demotedKept > 0 || concernsKept > 0)) {\n if (demotedKept > 0) demotedKept -= 1;\n else concernsKept -= 1;\n omitted += 1;\n head = renderHead(concernsKept, demotedKept, omitted);\n }\n // Last resort for a pathological summary; unreachable while the CodeReview\n // schema caps the summary well below the budget.\n const body = `${head.slice(0, headBudget)}\\n${tail}`;\n\n return ReviewPublicationPlan.make({\n event,\n body,\n comments,\n demoted: demoted.map(({ finding }) => finding),\n commitSha: options.headSha,\n });\n};\n","import { Effect, Option, Schema } from \"effect\";\nimport {\n makeUsageBudget,\n toRunBudgetHook,\n UsageBudgetLimits,\n UsageTotals,\n AgentRuntime,\n type RuntimeBinding,\n} from \"effect-agent\";\nimport { type Tool } from \"effect/unstable/ai\";\n\nimport { assessReviewCoverage, ReviewCoverage, type ReviewShape } from \"./coverage.ts\";\nimport type { ChangedFile } from \"./diff.ts\";\nimport { computeChangesetFingerprint } from \"./fingerprint.ts\";\nimport { PublishedReview, ReviewPublisher } from \"./github.ts\";\nimport { planPublication, ReviewPublicationPlan } from \"./render.ts\";\nimport {\n clampMaxFindings,\n CodeReview,\n ReviewConcern,\n ReviewFinding,\n ReviewMission,\n} from \"./review-agent.ts\";\nimport {\n fromStoredConcern,\n fromStoredFinding,\n ReviewExecutionContext,\n ReviewState,\n toStoredConcern,\n toStoredFinding,\n} from \"./review-state.ts\";\nimport { rankAndDedupeFindings } from \"./review-units.ts\";\nimport { PullRequestSource, type PullRequestMetadata } from \"./source.ts\";\n\n// ---------------------------------------------------------------------------\n// One review run, end to end: read the pull request, run the bounded agent,\n// validate the review against the real diff, then (optionally) publish.\n// Publication happens strictly AFTER the agent loop so no model turn can\n// observe or influence the mutation, and a failed run publishes nothing.\n// ---------------------------------------------------------------------------\n\n/**\n * Run-level usage bounds on top of the definition's AgentPolicy. Real diffs\n * are token-heavy, so the input budget is research-sized with cost as the\n * safety net.\n */\nexport const reviewBudgetLimits = UsageBudgetLimits.make({\n maxInputTokens: 400_000,\n maxOutputTokens: 16_000,\n maxToolCalls: 24,\n maxCostMicrousd: 2_000_000,\n maxDurationMillis: 480_000,\n});\n\n/**\n * Run-level bounds for the fan-out coordinator. This budget observes only\n * the COORDINATOR'S own usage — delegated children are bounded separately by\n * the delegation's `SubagentPolicy` reservation and the child definition's\n * own `AgentPolicy`, never silently by the parent's budget. The duration\n * ceiling is wider because delegation Tool Calls hold the parent turn open\n * while bounded children run.\n */\nexport const fanOutReviewBudgetLimits = UsageBudgetLimits.make({\n maxInputTokens: 400_000,\n maxOutputTokens: 16_000,\n maxToolCalls: 24,\n maxCostMicrousd: 2_000_000,\n maxDurationMillis: 900_000,\n});\n\n/** Everything one review run produced, publication receipt included. */\nexport class ReviewRunOutcome extends Schema.Class<ReviewRunOutcome>(\n \"@effect-agent/pr-review/ReviewRunOutcome\",\n)({\n review: CodeReview,\n /** All currently unresolved findings, including unchanged carried scope. */\n activeFindings: Schema.Array(ReviewFinding).check(Schema.isMaxLength(20)),\n /** All currently unresolved concerns, including concerns carried to final audit. */\n activeConcerns: Schema.Array(ReviewConcern).check(Schema.isMaxLength(10)),\n /** Host-owned structural coverage used by the Actions check conclusion. */\n coverage: ReviewCoverage,\n plan: ReviewPublicationPlan,\n published: Schema.optionalKey(PublishedReview),\n turns: Schema.Int.check(Schema.isGreaterThan(0)),\n /**\n * The run budget's observed usage. For the fan-out reviewer this observes\n * the COORDINATOR only — delegated children are bounded and accounted\n * separately by their reservations.\n */\n usage: Schema.optionalKey(UsageTotals),\n /**\n * What `usage` observed: the whole run, or a fan-out coordinator only.\n * Absent when the caller declared no scope — consumers must not present\n * unscoped usage as whole-run totals.\n */\n usageScope: Schema.optionalKey(Schema.Literals([\"run\", \"coordinator\"])),\n reviewMode: Schema.optionalKey(Schema.Literals([\"incremental\", \"full\"])),\n reviewReason: Schema.optionalKey(Schema.String.check(Schema.isMaxLength(1_000))),\n state: Schema.optionalKey(ReviewState),\n}) {}\n\nexport interface ExecuteReviewOptions {\n /** Post the review to GitHub; `false` stops after planning (dry run). */\n readonly post: boolean;\n /** Map the model's verdict onto APPROVE/REQUEST_CHANGES instead of COMMENT. */\n readonly applyVerdict: boolean;\n /** Run-level usage bounds; defaults to `reviewBudgetLimits`. */\n readonly limits?: UsageBudgetLimits | undefined;\n /**\n * Host-side findings bound (fail-closed backstop for the instruction-level\n * bound): a review carrying more findings is ranked by severity, deduped by\n * anchor, and trimmed — never published oversized. Clamped to the schema cap.\n */\n readonly maxFindings?: number | undefined;\n /**\n * Prompt signature for changeset fingerprinting. When present, the\n * changeset fingerprint is computed and embedded invisibly in the review\n * body so later runs can skip an unchanged changeset.\n */\n readonly signature?: ((mission: ReviewMission) => string) | undefined;\n /** Provider binding descriptor rendered into the review footer. */\n readonly modelLabel?: string | undefined;\n /** Workflow-run URL rendered into the review footer. */\n readonly runUrl?: string | undefined;\n /**\n * What the run budget observes: the whole run, or a fan-out coordinator\n * only. Without a declared scope the footer omits usage entirely — this\n * generic path cannot know what a caller's binding shape observes, and an\n * unlabeled number would read as whole-run totals.\n */\n readonly usageScope?: \"run\" | \"coordinator\" | undefined;\n /** Host-owned coverage shape; defaults to the flat reviewer. */\n readonly reviewShape?: ReviewShape | undefined;\n}\n\n/** Build the mission one review run frames from the source's snapshot. */\nexport const buildReviewMission = (\n metadata: PullRequestMetadata,\n files: ReadonlyArray<ChangedFile>,\n): ReviewMission =>\n ReviewMission.make({\n repository: metadata.repository,\n number: metadata.number,\n title: metadata.title,\n body: metadata.body,\n baseRef: metadata.baseRef,\n headRef: metadata.headRef,\n changedFileCount: files.length,\n });\n\n/** Enforce the configured findings bound on an already-validated review. */\nexport const enforceFindingsBound = (review: CodeReview, maxFindings: number): CodeReview =>\n review.findings.length <= maxFindings\n ? review\n : CodeReview.make({\n summary: review.summary,\n verdict: review.verdict,\n findings: rankAndDedupeFindings(review.findings).slice(0, maxFindings),\n ...(review.concerns !== undefined ? { concerns: review.concerns } : {}),\n });\n\nconst findingKey = (finding: ReviewFinding): string =>\n `${finding.path}\\u0000${finding.startLine}\\u0000${finding.endLine}\\u0000${finding.severity}\\u0000${finding.title}`;\n\nconst severityRank: Record<ReviewConcern[\"severity\"], number> = {\n blocking: 0,\n important: 1,\n nit: 2,\n};\n\nconst rankAndDedupeConcerns = (\n concerns: ReadonlyArray<ReviewConcern>,\n): ReadonlyArray<ReviewConcern> => {\n const byContent = new Map<string, ReviewConcern>();\n for (const concern of concerns) {\n const key = `${concern.title}\\u0000${concern.body}`;\n const previous = byContent.get(key);\n if (\n previous === undefined ||\n severityRank[concern.severity] < severityRank[previous.severity]\n ) {\n byContent.set(key, concern);\n }\n }\n return [...byContent.values()]\n .sort((left, right) => severityRank[left.severity] - severityRank[right.severity])\n .slice(0, 10);\n};\n\n/**\n * Execute one review with any explicit Agent Binding whose contract is\n * `ReviewMission -> CodeReview` — the flat reviewer or the fan-out\n * coordinator; the toolkit stays generic because publication only depends on\n * the shared output contract. The binding stays a parameter (D-027): tests\n * pass scripted models, hosts pass live provider bindings, and the model\n * Layer's requirements stay visible in this Effect's `R`.\n */\nexport const executeReview = <\n Instructions,\n Tools extends Record<string, Tool.Any>,\n Provider,\n ModelProvides,\n ModelRequires,\n>(\n binding: RuntimeBinding<\n typeof ReviewMission,\n typeof CodeReview,\n Instructions,\n Tools,\n Provider,\n ModelProvides,\n ModelRequires\n >,\n options: ExecuteReviewOptions,\n) =>\n Effect.gen(function* () {\n const source = yield* PullRequestSource;\n const metadata = yield* source.metadata;\n const files = yield* source.changedFiles;\n const anchorFiles = yield* source.anchorFiles;\n const executionContext = Option.getOrUndefined(\n yield* Effect.serviceOption(ReviewExecutionContext),\n );\n const mission = buildReviewMission(metadata, files);\n const fullMission = buildReviewMission(metadata, anchorFiles);\n const fingerprint =\n options.signature === undefined\n ? undefined\n : yield* computeChangesetFingerprint(anchorFiles, options.signature(fullMission));\n\n const budget = yield* makeUsageBudget(options.limits ?? reviewBudgetLimits);\n const detached = yield* AgentRuntime.start(binding, mission, {\n budget: toRunBudgetHook(budget),\n estimateCostMicrousd: () => Effect.succeed(500),\n });\n const result = yield* detached.await;\n const events = yield* detached.events;\n\n // The engine validated the terminal JSON against the output schema; this\n // decode recovers the typed value on this side of the generic boundary.\n const decoded = yield* Schema.decodeUnknownEffect(CodeReview)(result.output);\n const review = enforceFindingsBound(decoded, clampMaxFindings(options.maxFindings));\n const usage = yield* budget.snapshot;\n const affectedPaths = new Set(\n executionContext?.affectedPaths ??\n files.flatMap((file) =>\n file.previousPath === undefined ? [file.path] : [file.path, file.previousPath],\n ),\n );\n const priorState =\n executionContext?.mode === \"incremental\" ? executionContext.priorState : undefined;\n const carriedCandidates =\n priorState?.unresolvedFindings\n .filter((finding) => !affectedPaths.has(finding.path))\n .map(fromStoredFinding) ?? [];\n const activeFindings = rankAndDedupeFindings([...carriedCandidates, ...review.findings]).slice(\n 0,\n clampMaxFindings(options.maxFindings),\n );\n const activeFindingKeys = new Set(activeFindings.map(findingKey));\n const currentFindingKeys = new Set(review.findings.map(findingKey));\n const carriedFindings = carriedCandidates.filter(\n (finding) =>\n activeFindingKeys.has(findingKey(finding)) && !currentFindingKeys.has(findingKey(finding)),\n );\n // Non-anchored concerns cannot be mapped safely to one affected path, so\n // incremental runs carry them conservatively until the explicit final audit.\n const carriedConcernCandidates = priorState?.unresolvedConcerns.map(fromStoredConcern) ?? [];\n const activeConcerns = rankAndDedupeConcerns([\n ...carriedConcernCandidates,\n ...(review.concerns ?? []),\n ]);\n const currentConcernKeys = new Set(\n (review.concerns ?? []).map((concern) => `${concern.title}\\u0000${concern.body}`),\n );\n const activeConcernKeys = new Set(\n activeConcerns.map((concern) => `${concern.title}\\u0000${concern.body}`),\n );\n const carriedConcerns = carriedConcernCandidates.filter((concern) => {\n const key = `${concern.title}\\u0000${concern.body}`;\n return activeConcernKeys.has(key) && !currentConcernKeys.has(key);\n });\n const reviewTotalFiles = executionContext?.totalFiles ?? metadata.totalChangedFiles;\n const coverage = assessReviewCoverage({\n shape: options.reviewShape ?? \"flat\",\n files,\n totalFiles: reviewTotalFiles,\n anchorFiles,\n totalAnchorFiles: metadata.totalChangedFiles,\n events,\n });\n const stateCandidate =\n executionContext !== undefined &&\n coverage.status === \"complete\" &&\n fingerprint !== undefined &&\n metadata.baseSha !== undefined &&\n executionContext.stateAuthenticator?.status === \"available\"\n ? ReviewState.make({\n version: 1,\n repository: metadata.repository,\n pullRequestNumber: metadata.number,\n baseRef: metadata.baseRef,\n baseSha: metadata.baseSha,\n headRef: metadata.headRef,\n reviewedHeadSha: metadata.headSha,\n profileFingerprint: executionContext.profileFingerprint,\n acceptedScopeFingerprint: fingerprint,\n reviewedPathCount: anchorFiles.length,\n unresolvedFindings: activeFindings.map(toStoredFinding),\n unresolvedConcerns: activeConcerns.map(toStoredConcern),\n lastReviewMode: executionContext.mode,\n })\n : undefined;\n const continuity =\n stateCandidate === undefined || executionContext?.stateAuthenticator === undefined\n ? {\n state: undefined,\n marker: undefined,\n notice:\n executionContext?.stateAuthenticator?.status === \"unavailable\" &&\n coverage.status === \"complete\"\n ? (executionContext.stateAuthenticator.unavailableReason ??\n \"authenticated continuity state is unavailable\")\n : undefined,\n }\n : yield* executionContext.stateAuthenticator.render(stateCandidate).pipe(\n Effect.match({\n onFailure: (error) => ({\n state: undefined,\n marker: undefined,\n notice:\n error._tag === \"ReviewStateMarkerTooLarge\"\n ? `authenticated continuity state exceeded its ${error.maximumChars}-character bound`\n : `authenticated continuity state could not be signed: ${error.reason}`,\n }),\n onSuccess: (marker) => ({ state: stateCandidate, marker, notice: undefined }),\n }),\n );\n const plan = planPublication(review, anchorFiles, {\n applyVerdict: options.applyVerdict,\n headSha: metadata.headSha,\n totalChangedFiles: metadata.totalChangedFiles,\n baseRef: metadata.baseRef,\n headRef: metadata.headRef,\n modelLabel: options.modelLabel,\n runUrl: options.runUrl,\n usage,\n usageScope: options.usageScope,\n fingerprint: coverage.status === \"complete\" ? fingerprint : undefined,\n coverage,\n carriedFindings,\n carriedConcerns,\n reviewMode: executionContext?.mode,\n reviewReason: executionContext?.reason,\n baselineSha: executionContext?.baselineSha,\n reviewFilesVisible: files.length,\n reviewTotalFiles,\n stateMarker: continuity.marker,\n stateNotice: continuity.notice,\n });\n\n const scope =\n options.usageScope === undefined ? {} : ({ usageScope: options.usageScope } as const);\n if (!options.post) {\n return ReviewRunOutcome.make({\n review,\n activeFindings,\n activeConcerns,\n coverage,\n plan,\n turns: result.turns,\n usage,\n ...scope,\n ...(executionContext === undefined\n ? {}\n : { reviewMode: executionContext.mode, reviewReason: executionContext.reason }),\n ...(continuity.state === undefined ? {} : { state: continuity.state }),\n });\n }\n const publisher = yield* ReviewPublisher;\n const published = yield* publisher.publish(plan);\n return ReviewRunOutcome.make({\n review,\n activeFindings,\n activeConcerns,\n coverage,\n plan,\n published,\n turns: result.turns,\n usage,\n ...scope,\n ...(executionContext === undefined\n ? {}\n : { reviewMode: executionContext.mode, reviewReason: executionContext.reason }),\n ...(continuity.state === undefined ? {} : { state: continuity.state }),\n });\n });\n","import { Effect, Layer } from \"effect\";\nimport {\n Agent,\n AgentPolicy,\n getToolExecutionClass,\n IdGenerator,\n SubagentReservationsMemoryLive,\n type AgentPolicyInput,\n type UsageBudgetLimits,\n} from \"effect-agent\";\nimport { Toolkit, type LanguageModel, type Model, type Tool } from \"effect/unstable/ai\";\n\nimport {\n fanOutHandlersLayerFor,\n FanOutCoordinatorToolkitLayer,\n FileReviewToolkitLayer,\n makeFanOutReviewSuite,\n} from \"./fan-out.ts\";\nimport { computeChangesetFingerprint } from \"./fingerprint.ts\";\nimport { compileIgnoreGlobs, ignoringPullRequestSourceLayer } from \"./ignore.ts\";\nimport {\n clampMaxFindings,\n CodeReview,\n defaultReviewPolicy,\n ListChangedFiles,\n makeReviewInstructions,\n ReadFile,\n ReadFileDiff,\n ReviewMission,\n ReviewToolkitLayer,\n resolveGuidance as resolveReviewGuidance,\n type ReviewGuidance,\n} from \"./review-agent.ts\";\nimport { buildProfileMission, computeProfileFingerprint } from \"./review-state.ts\";\nimport {\n buildReviewMission,\n executeReview,\n fanOutReviewBudgetLimits,\n reviewBudgetLimits,\n} from \"./run.ts\";\nimport { PullRequestSource } from \"./source.ts\";\n\n// ---------------------------------------------------------------------------\n// The configuration factory: one call turns a Model and optional adaptation\n// knobs into a bound, runnable reviewer. Every knob widens what goes INTO the\n// review — guidance, extra read-only tools, execution bounds, ignore globs —\n// and none weakens what leaves it: anchor validation, the findings bound, and\n// publication-after-settlement are applied by the run path unconditionally.\n// ---------------------------------------------------------------------------\n\n/** Options shared by both reviewer shapes. */\nexport interface PrReviewSharedOptions {\n /**\n * Host-side and instruction-level findings bound, clamped to the CodeReview\n * schema cap of 20.\n */\n readonly maxFindings?: number | undefined;\n /**\n * Glob patterns (`**` crosses directories, `*`/`?` stay in one segment)\n * removed from the reviewer's observation surface entirely.\n */\n readonly ignore?: ReadonlyArray<string> | undefined;\n /** Map the model's verdict onto APPROVE/REQUEST_CHANGES instead of COMMENT. */\n readonly applyVerdict?: boolean | undefined;\n /** Run-level usage bounds; defaults to the shape's packaged limits. */\n readonly budget?: UsageBudgetLimits | undefined;\n /**\n * Human-readable descriptor of the bound model (provider, model id, effort)\n * rendered into the review footer and included in the fingerprint\n * signature, so changing the binding re-reviews instead of skipping.\n */\n readonly modelLabel?: string | undefined;\n}\n\n/** Options accepted by `PrReview.make` (the flat reviewer). */\nexport interface PrReviewOptions<\n Provider,\n ModelProvides,\n ModelRequires,\n Extra extends ReadonlyArray<Tool.Any>,\n> extends PrReviewSharedOptions {\n /** The Effect AI Model to bind; its Layer requirements stay visible in `R`. */\n readonly model: Model.Model<Provider, LanguageModel.LanguageModel | ModelProvides, ModelRequires>;\n /** Domain guidance injected between the mission framing and the procedure. */\n readonly guidance?: ReviewGuidance | undefined;\n /** Full override of the flat reviewer's execution bounds. */\n readonly policy?: AgentPolicyInput | undefined;\n /**\n * Additional tools merged into the reviewer's toolkit. Every extra tool\n * must be annotated `ToolExecutionClass: \"readonly\"` — construction fails\n * otherwise — and its handler Layer is the caller's to provide, so the new\n * dependency stays visible in the run's `R`.\n */\n readonly extraTools?: Extra | undefined;\n}\n\n/** How one run should publish. */\nexport interface RunReviewOptions {\n /** Post the review to GitHub; `false` (default) stops after planning. */\n readonly post?: boolean | undefined;\n /** Workflow-run URL rendered into the review footer. */\n readonly runUrl?: string | undefined;\n}\n\nconst EMPTY_TOOLS: ReadonlyArray<Tool.Any> = [];\n\nconst requireReadonly = (tools: ReadonlyArray<Tool.Any>): void => {\n for (const tool of tools) {\n const executionClass = getToolExecutionClass(tool);\n if (executionClass !== \"readonly\") {\n throw new Error(\n `PrReview.make: extra tool '${tool.name}' declares execution class '${executionClass}'. ` +\n `The packaged reviewer's tool surface is read-only; annotate the tool with ` +\n `ToolExecutionClass \"readonly\" or run it outside the reviewer.`,\n );\n }\n }\n};\n\nconst provideIgnore = <A, E, R>(\n effect: Effect.Effect<A, E, R>,\n ignore: ReadonlyArray<string> | undefined,\n) =>\n ignore !== undefined && ignore.length > 0\n ? effect.pipe(Effect.provide(ignoringPullRequestSourceLayer(ignore)))\n : effect;\n\n/**\n * The changeset fingerprint of what this reviewer WOULD review right now:\n * the ignore-filtered changeset hashed with the prompt signature. Identical\n * fingerprints mean an identical review input surface — the basis for\n * skipping re-reviews after content-free head changes (base auto-merges,\n * equivalent rebases).\n */\nconst makeFingerprint = (\n signature: (mission: ReturnType<typeof buildReviewMission>) => string,\n ignore: ReadonlyArray<string> | undefined,\n) =>\n provideIgnore(\n Effect.gen(function* () {\n const source = yield* PullRequestSource;\n const metadata = yield* source.metadata;\n const files = yield* source.changedFiles;\n return yield* computeChangesetFingerprint(\n files,\n signature(buildReviewMission(metadata, files)),\n );\n }),\n ignore,\n );\n\nconst makeProfileFingerprint = (\n signature: (mission: ReviewMission) => string,\n ignore: ReadonlyArray<string> | undefined,\n) =>\n provideIgnore(\n Effect.gen(function* () {\n const source = yield* PullRequestSource;\n const metadata = yield* source.metadata;\n const files = yield* source.anchorFiles;\n return yield* computeProfileFingerprint(signature(buildProfileMission(metadata, files)));\n }),\n ignore,\n );\n\nconst makeReviewSnapshot = (ignore: ReadonlyArray<string> | undefined) =>\n provideIgnore(\n Effect.gen(function* () {\n const source = yield* PullRequestSource;\n return {\n metadata: yield* source.metadata,\n files: yield* source.anchorFiles,\n };\n }),\n ignore,\n );\n\n/**\n * Build the flat reviewer: one bounded read-only agent over the whole\n * changeset. Returns the model-agnostic definition, the explicit binding, and\n * a `run` whose error and requirement channels stay fully inferred — the\n * pull-request source, the publisher, extra tool handlers, and the Model\n * Layer's requirements all remain visible to the caller.\n */\nconst make = <\n Provider,\n ModelProvides,\n ModelRequires,\n const Extra extends ReadonlyArray<Tool.Any> = readonly [],\n>(\n options: PrReviewOptions<Provider, ModelProvides, ModelRequires, Extra>,\n) => {\n // Safe when `extraTools` is omitted: the generic default fixes Extra to the\n // empty tuple, which is exactly what the fallback value is.\n const extraTools = options.extraTools ?? (EMPTY_TOOLS as Extra);\n requireReadonly(extraTools);\n\n const definition = Agent.define(\"pr-reviewer\", {\n input: ReviewMission,\n output: CodeReview,\n instructions: makeReviewInstructions({\n guidance: options.guidance,\n maxFindings: options.maxFindings,\n }),\n toolkit: Toolkit.make(ListChangedFiles, ReadFileDiff, ReadFile, ...extraTools),\n policy: options.policy === undefined ? defaultReviewPolicy : AgentPolicy.make(options.policy),\n description:\n \"Review one pull request read-only: list the changeset, read annotated diffs and head-file context, and return a structured, line-anchored code review.\",\n metadata: { deploymentClass: \"E\", surface: \"read-only\" },\n });\n // `Agent.withModel` types the model through a conditional that stays\n // deferred inside this generic body, so the binding is built structurally —\n // the identical frozen `{ definition, model }` pair the runtime accepts.\n const binding = Object.freeze({ definition, model: options.model });\n\n // Everything that shapes this reviewer's output: the rendered instructions\n // (mission, guidance, findings bound, contract) plus the verdict mapping.\n const signature = (mission: ReviewMission): string =>\n [\n definition.instructions(mission),\n `applyVerdict=${String(options.applyVerdict ?? false)}`,\n ...(options.modelLabel === undefined ? [] : [`model=${options.modelLabel}`]),\n ].join(\"\\u0000\");\n const profileSignature = (mission: ReviewMission): string =>\n [\n \"pr-review-profile-v1-flat\",\n JSON.stringify(resolveReviewGuidance(options.guidance, mission)),\n JSON.stringify(options.policy ?? {}),\n JSON.stringify(extraTools.map((tool) => tool.name)),\n JSON.stringify(options.ignore ?? []),\n `maxFindings=${clampMaxFindings(options.maxFindings)}`,\n `applyVerdict=${String(options.applyVerdict ?? false)}`,\n ...(options.modelLabel === undefined ? [] : [`model=${options.modelLabel}`]),\n ].join(\"\\u0000\");\n\n const run = (runOptions: RunReviewOptions = {}) =>\n provideIgnore(\n executeReview(binding, {\n post: runOptions.post ?? false,\n applyVerdict: options.applyVerdict ?? false,\n limits: options.budget ?? reviewBudgetLimits,\n maxFindings: clampMaxFindings(options.maxFindings),\n signature,\n modelLabel: options.modelLabel,\n runUrl: runOptions.runUrl,\n usageScope: \"run\",\n reviewShape: \"flat\",\n }).pipe(Effect.provide(Layer.mergeAll(ReviewToolkitLayer, IdGenerator.layer)), Effect.scoped),\n options.ignore,\n );\n\n return {\n definition,\n binding,\n run,\n fingerprint: makeFingerprint(signature, options.ignore),\n profileFingerprint: makeProfileFingerprint(profileSignature, options.ignore),\n snapshot: makeReviewSnapshot(options.ignore),\n filterFiles: (files: ReadonlyArray<import(\"./diff.ts\").ChangedFile>) => {\n const ignored = compileIgnoreGlobs(options.ignore ?? []);\n return files.filter((file) => !ignored(file.path));\n },\n } as const;\n};\n\n/** Options accepted by `PrReview.makeFanOut` (the delegating reviewer). */\nexport interface PrReviewFanOutOptions<\n Provider,\n ModelProvides,\n ModelRequires,\n> extends PrReviewSharedOptions {\n /** The Effect AI Model bound to both the coordinator and its children. */\n readonly model: Model.Model<Provider, LanguageModel.LanguageModel | ModelProvides, ModelRequires>;\n /**\n * Static guidance injected into every child reviewer's instructions. The\n * coordinator's mission never crosses the delegation boundary, so\n * mission-dependent guidance cannot exist for children.\n */\n readonly guidance?: string | ReadonlyArray<string> | undefined;\n}\n\n/**\n * Build the fan-out reviewer: a coordinator that delegates bounded per-unit\n * file reviews to attached ephemeral children and merges their findings under\n * the same output contract and the same fail-closed publication path as the\n * flat reviewer. Child and coordinator execution bounds are packaged and not\n * configurable here — the delegation reservation mirrors the child policy,\n * and letting the two drift apart is a published-API hazard.\n */\nconst makeFanOut = <Provider, ModelProvides, ModelRequires>(\n options: PrReviewFanOutOptions<Provider, ModelProvides, ModelRequires>,\n) => {\n const suite = makeFanOutReviewSuite({\n guidance: options.guidance,\n maxFindings: options.maxFindings,\n });\n // Structural bindings for the same reason as in `make` above.\n const binding = Object.freeze({ definition: suite.parent, model: options.model });\n const childBinding = Object.freeze({ definition: suite.child, model: options.model });\n\n // The coordinator's rendered instructions (mission, guidance, findings\n // bound, contract) plus the review-shaping options they do not carry: the\n // child guidance, the host knobs, and the model binding descriptor.\n const guidanceLines =\n options.guidance === undefined\n ? []\n : typeof options.guidance === \"string\"\n ? [options.guidance]\n : options.guidance;\n const signature = (mission: ReviewMission): string =>\n [\n suite.parent.instructions(mission),\n `childGuidance=${JSON.stringify(guidanceLines)}`,\n `applyVerdict=${String(options.applyVerdict ?? false)}`,\n ...(options.modelLabel === undefined ? [] : [`model=${options.modelLabel}`]),\n ].join(\" \");\n const profileSignature = (_mission: ReviewMission): string =>\n [\n \"pr-review-profile-v1-fan-out\",\n JSON.stringify(guidanceLines),\n JSON.stringify(options.ignore ?? []),\n `maxFindings=${clampMaxFindings(options.maxFindings)}`,\n `applyVerdict=${String(options.applyVerdict ?? false)}`,\n ...(options.modelLabel === undefined ? [] : [`model=${options.modelLabel}`]),\n ].join(\"\\u0000\");\n const delegationLayer = fanOutHandlersLayerFor(suite.delegation)(childBinding).pipe(\n Layer.provide(\n Layer.mergeAll(FileReviewToolkitLayer, SubagentReservationsMemoryLive, IdGenerator.layer),\n ),\n );\n\n const run = (runOptions: RunReviewOptions = {}) =>\n provideIgnore(\n executeReview(binding, {\n post: runOptions.post ?? false,\n applyVerdict: options.applyVerdict ?? false,\n limits: options.budget ?? fanOutReviewBudgetLimits,\n maxFindings: clampMaxFindings(options.maxFindings),\n signature,\n modelLabel: options.modelLabel,\n runUrl: runOptions.runUrl,\n usageScope: \"coordinator\",\n reviewShape: \"fan-out\",\n }).pipe(\n Effect.provide(\n Layer.mergeAll(FanOutCoordinatorToolkitLayer, delegationLayer, IdGenerator.layer),\n ),\n Effect.scoped,\n ),\n options.ignore,\n );\n\n return {\n definition: suite.parent,\n binding,\n childBinding,\n run,\n fingerprint: makeFingerprint(signature, options.ignore),\n profileFingerprint: makeProfileFingerprint(profileSignature, options.ignore),\n snapshot: makeReviewSnapshot(options.ignore),\n filterFiles: (files: ReadonlyArray<import(\"./diff.ts\").ChangedFile>) => {\n const ignored = compileIgnoreGlobs(options.ignore ?? []);\n return files.filter((file) => !ignored(file.path));\n },\n } as const;\n};\n\n/**\n * The packaged pull-request reviewer factory.\n *\n * - `make` — one flat reviewer over the whole changeset.\n * - `makeFanOut` — a coordinator delegating bounded per-unit child reviews.\n */\nexport const PrReview = { make, makeFanOut } as const;\n","import { Config, Effect, FileSystem, Layer, Option, Schema } from \"effect\";\nimport { FetchHttpClient } from \"effect/unstable/http\";\n\nimport type { PriorReviews, ReviewPublisher } from \"./github.ts\";\nimport {\n GitHubReviewTarget,\n gitHubPriorReviewsLayer,\n gitHubPullRequestSourceLayer,\n gitHubReviewPublisherLayer,\n} from \"./github.ts\";\nimport type { PullRequestSource } from \"./source.ts\";\n\n// ---------------------------------------------------------------------------\n// GitHub Actions environment resolution: which pull request to review, from\n// explicit values first and the standard Actions environment second\n// (GITHUB_REPOSITORY, GITHUB_EVENT_PATH, GITHUB_API_URL, GITHUB_TOKEN).\n// Platform-free: FileSystem and Config are Effect services supplied by the\n// host entrypoint.\n// ---------------------------------------------------------------------------\n\n/** The pull request could not be resolved from options or the environment. */\nexport class ReviewTargetUnresolved extends Schema.TaggedError<ReviewTargetUnresolved>()(\n \"ReviewTargetUnresolved\",\n {\n reason: Schema.String,\n },\n) {\n override get message() {\n return this.reason;\n }\n}\n\n/** The slice of a GitHub Actions event payload this package understands. */\nexport const GitHubEventWire = Schema.Struct({\n pull_request: Schema.optionalKey(\n Schema.Struct({\n number: Schema.Int,\n draft: Schema.optionalKey(Schema.Boolean),\n }),\n ),\n repository: Schema.optionalKey(Schema.Struct({ full_name: Schema.String })),\n});\nexport type GitHubEventWire = typeof GitHubEventWire.Type;\n\nconst decodeEvent = Schema.decodeUnknownEffect(Schema.fromJsonString(GitHubEventWire));\n\n/** Read and decode the GITHUB_EVENT_PATH payload, or none outside Actions. */\nexport const readGitHubEvent = Effect.fn(\"readGitHubEvent\")(function* () {\n const eventPath = yield* Config.string(\"GITHUB_EVENT_PATH\").pipe(Config.withDefault(\"\"));\n if (eventPath === \"\") return Option.none<GitHubEventWire>();\n const fs = yield* FileSystem.FileSystem;\n const raw = yield* fs\n .readFileString(eventPath)\n .pipe(\n Effect.mapError((error) =>\n ReviewTargetUnresolved.make({ reason: `Cannot read event payload: ${error.message}` }),\n ),\n );\n const event = yield* decodeEvent(raw).pipe(\n Effect.mapError((error) =>\n ReviewTargetUnresolved.make({ reason: `Cannot decode event payload: ${error.message}` }),\n ),\n );\n return Option.some(event);\n});\n\nexport interface ResolvedReviewTarget {\n readonly repository: string;\n readonly number: number;\n}\n\n/**\n * Resolve the review target: explicit values win, then GITHUB_REPOSITORY and\n * the pull_request event payload. Fails typed when no target can be named.\n */\nexport const resolveReviewTarget = Effect.fn(\"resolveReviewTarget\")(function* (options: {\n readonly repository?: string | undefined;\n readonly number?: number | undefined;\n}) {\n let repository = options.repository ?? \"\";\n if (repository === \"\") {\n repository = yield* Config.string(\"GITHUB_REPOSITORY\").pipe(Config.withDefault(\"\"));\n }\n let number = options.number;\n if (number === undefined || repository === \"\") {\n const event = yield* readGitHubEvent();\n if (Option.isSome(event)) {\n number ??= event.value.pull_request?.number;\n if (repository === \"\") repository = event.value.repository?.full_name ?? \"\";\n }\n }\n if (repository === \"\" || number === undefined) {\n return yield* ReviewTargetUnresolved.make({\n reason:\n \"No pull request to review: pass an explicit repository and number, or run inside a GitHub Actions pull_request event.\",\n });\n }\n return { repository, number } satisfies ResolvedReviewTarget;\n});\n\n/**\n * Build the GitHub source and publisher Layers for one resolved target,\n * reading GITHUB_API_URL and GITHUB_TOKEN from configuration. The returned\n * Layer is the complete GitHub side of a review run.\n */\nexport const gitHubReviewLayers = (\n target: ResolvedReviewTarget,\n): Layer.Layer<PullRequestSource | ReviewPublisher | PriorReviews, Config.ConfigError> =>\n Layer.unwrap(\n Effect.gen(function* () {\n const apiUrl = yield* Config.string(\"GITHUB_API_URL\").pipe(\n Config.withDefault(\"https://api.github.com\"),\n );\n const token = yield* Config.option(Config.redacted(\"GITHUB_TOKEN\"));\n const targetLayer = GitHubReviewTarget.layer({\n apiUrl,\n repository: target.repository,\n number: target.number,\n token,\n });\n const deps = Layer.merge(targetLayer, FetchHttpClient.layer);\n return Layer.mergeAll(\n gitHubPullRequestSourceLayer.pipe(Layer.provide(deps)),\n gitHubReviewPublisherLayer.pipe(Layer.provide(deps)),\n gitHubPriorReviewsLayer.pipe(Layer.provide(deps)),\n );\n }),\n );\n","import { AnthropicClient, AnthropicLanguageModel } from \"@effect/ai-anthropic\";\nimport { OpenAiClient, OpenAiLanguageModel } from \"@effect/ai-openai\";\nimport { Config, Layer } from \"effect\";\nimport { FetchHttpClient } from \"effect/unstable/http\";\n\nimport { resolveEffortRung, type EffortAliasName, type EffortPosition } from \"./effort.ts\";\n\n// ---------------------------------------------------------------------------\n// Built-in provider bindings for the two host entrypoints (CLI and Action).\n// The library itself stays provider-agnostic — the configuration factory\n// takes any Effect AI Model — and these helpers exist so the batteries-\n// included paths need one flag and one credential, nothing more. Client\n// Layers carry their redacted credentials from configuration; the\n// application supplies them at the edge (D-027).\n// ---------------------------------------------------------------------------\n\nexport type ReviewProvider = \"openai\" | \"anthropic\";\n\nexport const DEFAULT_PROVIDER: ReviewProvider = \"openai\";\n\nexport const DEFAULT_MODEL: Record<ReviewProvider, string> = {\n openai: \"gpt-5.6-sol\",\n anthropic: \"claude-sonnet-5\",\n};\n\nexport const PROVIDER_CREDENTIAL_ENV: Record<ReviewProvider, string> = {\n openai: \"OPENAI_API_KEY\",\n anthropic: \"ANTHROPIC_API_KEY\",\n};\n\n/**\n * Each provider's offered reasoning-effort ladder, cheapest first. The rungs\n * that turn reasoning off (`none`, `minimal`) are deliberately not offered —\n * no review run wants them. An `EffortPosition` resolves into the running\n * provider's own ladder, so the same stored position survives a provider or\n * model change.\n */\nexport const PROVIDER_EFFORT_RUNGS = {\n openai: [\"low\", \"medium\", \"high\", \"xhigh\"],\n anthropic: [\"low\", \"medium\", \"high\"],\n} as const satisfies Record<\n ReviewProvider,\n readonly [EffortAliasName, ...ReadonlyArray<EffortAliasName>]\n>;\n\n/** One OpenAI review model binding with the package's structured-output settings. */\nexport const makeOpenAiReviewModel = (model?: string, effort?: EffortPosition) =>\n OpenAiLanguageModel.model(model ?? DEFAULT_MODEL.openai, {\n max_output_tokens: 8_000,\n store: false,\n strictJsonSchema: true,\n ...(effort === undefined\n ? {}\n : { reasoning: { effort: resolveEffortRung(effort, PROVIDER_EFFORT_RUNGS.openai) } }),\n });\n\n/** One Anthropic review model binding with the package's output settings. */\nexport const makeAnthropicReviewModel = (model?: string, effort?: EffortPosition) =>\n AnthropicLanguageModel.model(model ?? DEFAULT_MODEL.anthropic, {\n max_tokens: 8_000,\n ...(effort === undefined\n ? {}\n : { output_config: { effort: resolveEffortRung(effort, PROVIDER_EFFORT_RUNGS.anthropic) } }),\n });\n\n/**\n * The human-readable descriptor of one provider binding, e.g.\n * `openai/gpt-5.6-sol (effort high)`. Rendered into the review footer and\n * included in the changeset-fingerprint signature, so a provider, model, or\n * effort change re-reviews instead of skipping.\n */\nexport const describeReviewModel = (\n provider: ReviewProvider,\n model?: string,\n effort?: EffortPosition,\n): string => {\n const base = `${provider}/${model ?? DEFAULT_MODEL[provider]}`;\n return effort === undefined\n ? base\n : `${base} (effort ${resolveEffortRung(effort, PROVIDER_EFFORT_RUNGS[provider])})`;\n};\n\n/** The OpenAI client Layer, credential from `OPENAI_API_KEY`. */\nexport const openAiClientLayer = OpenAiClient.layerConfig({\n apiKey: Config.redacted(PROVIDER_CREDENTIAL_ENV.openai),\n}).pipe(Layer.provide(FetchHttpClient.layer));\n\n/** The Anthropic client Layer, credential from `ANTHROPIC_API_KEY`. */\nexport const anthropicClientLayer = AnthropicClient.layerConfig({\n apiKey: Config.redacted(PROVIDER_CREDENTIAL_ENV.anthropic),\n}).pipe(Layer.provide(FetchHttpClient.layer));\n"],"mappings":";;;;;;;;AAcA,MAAa,cAAc,OAAO,SAAS,CAAC,QAAQ,SAAS,CAAC;AAG9D,IAAa,mBAAb,cAAsC,OAAO,MAC3C,0CACF,CAAC,CAAC;CACA,QAAQ,OAAO,eAAe,MAAM,OAAO,YAAY,EAAE,CAAC;CAC1D,UAAU,OAAO,eAAe,MAAM,OAAO,YAAY,GAAG,CAAC;AAC/D,CAAC,CAAC,CAAC,CAAC;AAEJ,IAAa,iBAAb,cAAoC,OAAO,MACzC,wCACF,CAAC,CAAC;CACA,QAAQ,OAAO,SAAS,CAAC,YAAY,YAAY,CAAC;CAClD,eAAe,OAAO,MAAM,OAAO,eAAe,MAAM,OAAO,YAAY,GAAG,CAAC,CAAC,CAAC,CAAC,MAChF,OAAO,YAAY,GAAG,CACxB;CACA,eAAe,OAAO,MAAM,OAAO,eAAe,MAAM,OAAO,YAAY,GAAG,CAAC,CAAC,CAAC,CAAC,MAChF,OAAO,YAAY,GAAG,CACxB;CACA,iBAAiB,OAAO,MAAM,OAAO,eAAe,MAAM,OAAO,YAAY,GAAG,CAAC,CAAC,CAAC,CAAC,MAClF,OAAO,YAAY,GAAG,CACxB;CACA,aAAa,OAAO,MAAM,gBAAgB,CAAC,CAAC,MAAM,OAAO,YAAY,CAAC,CAAC;CACvE,SAAS,OAAO,MAAM,OAAO,eAAe,MAAM,OAAO,YAAY,GAAK,CAAC,CAAC,CAAC,CAAC,MAC5E,OAAO,YAAY,EAAE,CACvB;AACF,CAAC,CAAC,CAAC,CAAC;AAQJ,MAAM,aAAa,WAA+C;CAChE,MAAM,2BAAW,IAAI,IAAsE;CAC3F,MAAM,4BAAY,IAAI,IAAuE;CAC7F,MAAM,yBAAS,IAAI,IAAoE;CACvF,KAAK,MAAM,SAAS,QAAQ;EAC1B,IAAI,MAAM,SAAS,oBAAoB,SAAS,IAAI,MAAM,YAAY,KAAK;EAC3E,IAAI,MAAM,SAAS,qBAAqB,UAAU,IAAI,MAAM,YAAY,KAAK;EAC7E,IAAI,MAAM,SAAS,kBAAkB,OAAO,IAAI,MAAM,YAAY,KAAK;CACzE;CACA,OAAO;EAAE;EAAU;EAAW;CAAO;AACvC;AAEA,MAAM,gBAAgB,WACpB,CAAC,GAAG,IAAI,IAAI,MAAM,CAAC,CAAC,CAAC,MAAM,MAAM,UAAW,OAAO,QAAQ,KAAK,OAAO,QAAQ,IAAI,CAAE;AAEvF,MAAM,qBAAqB,OAAe,WAAqC;CAC7E,MAAM,QAAQ,aAAa,MAAM;CAEjC,IAAI,WAAW,GADG,MAAM,IAAI,MAAM,OAAO;CAEzC,KAAK,IAAI,QAAQ,GAAG,QAAQ,MAAM,QAAQ,SAAS,GAAG;EACpD,MAAM,OAAO,MAAM,UAAU;EAC7B,MAAM,YAAY,UAAU,IAAI,KAAK;EACrC,MAAM,UAAU,MAAM,SAAS,QAAQ;EACvC,MAAM,SAAS,YAAY,IAAI,KAAK,QAAQ,QAAQ;EACpD,IAAI,GAAG,WAAW,YAAY,OAAO,SAAS,SAAS,KAAO;GAC5D,MAAM,WAAW,OAAO,MAAM,SAAS,MAAM;GAC7C,OAAO,GAAG,SAAS,MAAM,GAAG,MAAQ,SAAS,MAAM,IAAI;EACzD;EACA,WAAW,GAAG,WAAW,YAAY;CACvC;CACA,OAAO;AACT;AAEA,MAAM,gBACJ,OACA,YACA,UACmB;CACnB,MAAM,gBAAgB,aAAa,MAAM,KAAK,SAAS,KAAK,IAAI,CAAC;CACjE,MAAM,2BAAW,IAAI,IAAY;CACjC,MAAM,8BAAc,IAAI,IAAY;CACpC,KAAK,MAAM,CAAC,YAAY,gBAAgB,MAAM,UAAU;EACtD,IAAI,YAAY,aAAa,kBAAkB;EAC/C,MAAM,QAAQ,OAAO,oBAAoB,aAAa,CAAC,CAAC,YAAY,UAAU;EAC9E,IAAI,OAAO,OAAO,KAAK,GAAG;EAC1B,IAAI,MAAM,UAAU,IAAI,UAAU,GAAG,SAAS,IAAI,MAAM,MAAM,IAAI;EAClE,IAAI,MAAM,OAAO,IAAI,UAAU,GAAG,YAAY,IAAI,MAAM,MAAM,IAAI;CACpE;CACA,MAAM,aAAa,MAAM,QAAQ,SAAS,KAAK,UAAU,KAAA,CAAS,CAAC,CAAC,KAAK,SAAS,KAAK,IAAI;CAC3F,MAAM,aAAa,cAAc,QAC9B,SAAS,CAAC,SAAS,IAAI,IAAI,KAAK,WAAW,SAAS,IAAI,KAAK,YAAY,IAAI,IAAI,CACpF;CACA,MAAM,UAAyB,CAAC;CAChC,IAAI,MAAM,SAAS,YACjB,QAAQ,KAAK,wBAAwB,MAAM,OAAO,MAAM,WAAW,gBAAgB;CAErF,IAAI,WAAW,SAAS,GACtB,QAAQ,KAAK,kBAAkB,uCAAuC,UAAU,CAAC;CAEnF,IAAI,YAAY,OAAO,GACrB,QAAQ,KAAK,kBAAkB,qBAAqB,WAAW,CAAC;CAElE,IAAI,WAAW,SAAS,GACtB,QAAQ,KAAK,kBAAkB,iDAAiD,UAAU,CAAC;CAE7F,OAAO,eAAe,KAAK;EACzB,QAAQ,QAAQ,WAAW,IAAI,aAAa;EAC5C;EACA,eAAe,aAAa,QAAQ;EACpC,iBAAiB,aAAa,UAAU;EACxC,aAAa,CAAC;EACd;CACF,CAAC;AACH;AAEA,MAAM,kBACJ,OACA,YACA,UACmB;CACnB,MAAM,OAAO,gBAAgB,OAAO,EAAE,mBAAmB,WAAW,CAAC;CACrE,MAAM,qCAAqB,IAAI,IAG7B;CACF,KAAK,MAAM,CAAC,YAAY,gBAAgB,MAAM,UAAU;EACtD,IAAI,YAAY,aAAa,wBAAwB;EACrD,MAAM,UAAU,OAAO,oBAAoB,iBAAiB,CAAC,CAAC,YAAY,UAAU;EACpF,IAAI,OAAO,OAAO,OAAO,GAAG;EAC5B,MAAM,eAAe,mBAAmB,IAAI,QAAQ,MAAM,MAAM,KAAK,CAAC;EACtE,aAAa,KAAK;GAAE,IAAI;GAAY,OAAO,QAAQ,MAAM;EAAM,CAAC;EAChE,mBAAmB,IAAI,QAAQ,MAAM,QAAQ,YAAY;CAC3D;CAEA,MAAM,2BAAW,IAAI,IAAY;CACjC,MAAM,6BAAa,IAAI,IAAY,CAAC,GAAG,KAAK,iBAAiB,GAAG,KAAK,eAAe,CAAC;CACrF,MAAM,cAAuC,CAAC;CAC9C,MAAM,UAAyB,CAAC;CAChC,KAAK,MAAM,QAAQ,KAAK,OAAO;EAC7B,MAAM,eAAe,mBAAmB,IAAI,KAAK,MAAM,KAAK,CAAC;EAC7D,MAAM,gBAAgB,CAAC,GAAG,KAAK,KAAK;EACpC,MAAM,QAAQ,aAAa,QACxB,gBACC,YAAY,MAAM,WAAW,cAAc,UAC3C,YAAY,MAAM,OAAO,MAAM,UAAU,SAAS,cAAc,MAAM,CAC1E;EACA,MAAM,aAAa,MAAM,QAAQ,gBAAgB;GAC/C,MAAM,QAAQ,MAAM,UAAU,IAAI,YAAY,EAAE;GAChD,IAAI,UAAU,KAAA,KAAa,MAAM,OAAO,IAAI,YAAY,EAAE,GAAG,OAAO;GACpE,MAAM,SAAS,OAAO,oBAAoB,oBAAoB,CAAC,CAAC,MAAM,MAAM;GAC5E,OAAO,OAAO,OAAO,MAAM,KAAK,OAAO,MAAM,WAAW,KAAK;EAC/D,CAAC;EACD,IAAI,aAAa,WAAW,KAAK,MAAM,WAAW,KAAK,WAAW,WAAW,GAAG;GAC9E,KAAK,MAAM,QAAQ,KAAK,OAAO,SAAS,IAAI,IAAI;GAChD;EACF;EACA,KAAK,MAAM,QAAQ,KAAK,OAAO,WAAW,IAAI,IAAI;EAClD,MAAM,UAAU,aACb,KAAK,gBAAgB,MAAM,OAAO,IAAI,YAAY,EAAE,CAAC,CAAC,CACtD,MAAM,UAAU,UAAU,KAAA,CAAS;EACtC,MAAM,kBAAkB,aACrB,KAAK,gBAAgB,MAAM,UAAU,IAAI,YAAY,EAAE,CAAC,CAAC,CACzD,QAAQ,UAAU,UAAU,KAAA,CAAS,CAAC,CACtC,KAAK,UAAU,OAAO,oBAAoB,2BAA2B,CAAC,CAAC,MAAM,MAAM,CAAC,CAAC,CACrF,KAAK,OAAO,MAAM;EACrB,YAAY,KACV,iBAAiB,KAAK;GACpB,QAAQ,KAAK;GACb,UACE,SAAS,aACR,oBAAoB,KAAA,IACjB,gBAAgB,MAAM,SAAS,yBAC7B,GAAG,gBAAgB,MAAM,KAAK,GAAG,gBAAgB,MAAM,kBACvD,gBAAgB,MAAM,OACxB,KAAA,OACH,aAAa,WAAW,IACrB,oBACA,aAAa,SAAS,IACpB,8BACA,MAAM,WAAW,IACf,2BACA;EACZ,CAAC,CACH;CACF;CACA,IAAI,KAAK,WACP,QAAQ,KAAK,wBAAwB,MAAM,OAAO,MAAM,WAAW,gBAAgB;CAErF,IAAI,KAAK,gBAAgB,SAAS,GAChC,QAAQ,KAAK,kBAAkB,uCAAuC,KAAK,eAAe,CAAC;CAE7F,IAAI,KAAK,gBAAgB,SAAS,GAChC,QAAQ,KAAK,kBAAkB,0CAA0C,KAAK,eAAe,CAAC;CAEhG,IAAI,YAAY,SAAS,GACvB,QAAQ,KACN,kBACE,iCACA,YAAY,KAAK,SAAS,GAAG,KAAK,OAAO,IAAI,KAAK,SAAS,EAAE,CAC/D,CACF;CAEF,OAAO,eAAe,KAAK;EACzB,QAAQ,QAAQ,WAAW,IAAI,aAAa;EAC5C,eAAe,aAAa,MAAM,KAAK,SAAS,KAAK,IAAI,CAAC;EAC1D,eAAe,aAAa,QAAQ;EACpC,iBAAiB,aAAa,UAAU;EACxC;EACA;CACF,CAAC;AACH;;AAGA,MAAa,wBAAwB,UAOf;CACpB,MAAM,QAAQ,UAAU,MAAM,MAAM;CACpC,MAAM,WACJ,MAAM,UAAU,YACZ,eAAe,MAAM,OAAO,MAAM,YAAY,KAAK,IACnD,aAAa,MAAM,OAAO,MAAM,YAAY,KAAK;CACvD,IAAI,MAAM,YAAY,UAAU,MAAM,kBAAkB,OAAO;CAC/D,OAAO,eAAe,KAAK;EACzB,GAAG;EACH,QAAQ;EACR,SAAS,CACP,GAAG,SAAS,SACZ,4CAA4C,MAAM,YAAY,OAAO,MAAM,MAAM,iBAAiB,gBACpG;CACF,CAAC;AACH;;;;;;;;;;AC9NA,MAAa,iBAAiB;CAC5B,KAAK;CACL,QAAQ;CACR,MAAM;CACN,OAAO;CACP,KAAK;AACP;AAKA,MAAM,gBAAsE;;AAG5E,IAAa,qBAAb,cAAwC,OAAO,YAAgC,CAAC,CAC9E,sBACA,EACE,OAAO,OAAO,OAChB,CACF,CAAC,CAAC;CACA,IAAa,UAAU;EACrB,OACE,mBAAmB,KAAK,MAAM,qBAC3B,OAAO,KAAK,cAAc,CAAC,CAAC,KAAK,IAAI,EAAE;CAE9C;AACF;AAEA,MAAa,oBAAoB,UAC/B,OAAO,SAAS,KAAK,KAAK,SAAS,KAAK,SAAS;;;;;;AAOnD,MAAa,uBAAuB,QAA4C;CAC9E,MAAM,aAAa,IAAI,KAAK,CAAC,CAAC,YAAY;CAC1C,MAAM,QAAQ,cAAc;CAC5B,IAAI,UAAU,KAAA,GAAW,OAAO;CAChC,IAAI,eAAe,IAAI,OAAO,KAAA;CAC9B,MAAM,UAAU,OAAO,UAAU;CACjC,OAAO,iBAAiB,OAAO,IAAI,UAAU,KAAA;AAC/C;;;;;;;;;AAUA,MAAa,qBACX,UACA,UACS;CACT,MAAM,UAAU,KAAK,IAAI,GAAG,KAAK,IAAI,GAAG,QAAQ,CAAC;CACjD,IAAI,WAAW,MAAM;CACrB,KAAK,MAAM,QAAQ,OACjB,IAAI,eAAe,SAAS,SAAS,WAAW;CAElD,OAAO;AACT;;;ACxEA,MAAM,iBAAiB;AAIvB,MAAM,iBAAiB;AACvB,MAAM,WAAW;;;;;;AAOjB,MAAM,sBAAsB,YAC1B,QACG,QAAQ,gBAAgB,OAAO,GAAG,KAAK,CAAC,CACxC,WAAW,OAAO,cAAc,CAAC,CACjC,WAAW,MAAM,QAAQ,CAAC,CAC1B,WAAW,KAAK,OAAO,CAAC,CACxB,WAAW,KAAK,MAAM,CAAC,CACvB,WAAW,gBAAgB,UAAU,CAAC,CACtC,WAAW,UAAU,IAAI;;AAG9B,MAAa,sBACX,aACgC;CAChC,IAAI,SAAS,WAAW,GAAG,aAAa;CACxC,MAAM,cAAc,SAAS,KAAK,YAAY,IAAI,OAAO,OAAO,mBAAmB,OAAO,EAAE,GAAG,CAAC;CAChG,QAAQ,SAAS,YAAY,MAAM,eAAe,WAAW,KAAK,IAAI,CAAC;AACzE;;;;;;;;AASA,MAAa,kCACX,aAEA,MAAM,OAAO,iBAAiB,CAAC,CAC7B,OAAO,IAAI,aAAa;CACtB,MAAM,SAAS,OAAO;CACtB,MAAM,UAAU,mBAAmB,QAAQ;CAC3C,MAAM,eAAe,OAAO,aAAa,KACvC,OAAO,KAAK,UAAU,MAAM,QAAQ,SAAS,CAAC,QAAQ,KAAK,IAAI,CAAC,CAAC,CACnE;CACA,MAAM,cAAc,OAAO,YAAY,KACrC,OAAO,KAAK,UAAU,MAAM,QAAQ,SAAS,CAAC,QAAQ,KAAK,IAAI,CAAC,CAAC,CACnE;CACA,MAAM,WAAW,OAAO,IAAI,aAAa;EACvC,MAAM,CAAC,MAAM,SAAS,OAAO,OAAO,IAAI,CAAC,OAAO,UAAU,OAAO,WAAW,CAAC;EAC7E,MAAM,eAAe,MAAM,QAAQ,SAAS,QAAQ,KAAK,IAAI,CAAC,CAAC,CAAC;EAChE,OAAO,oBAAoB,KAAK;GAC9B,GAAG;GACH,mBAAmB,KAAK,IAAI,GAAG,KAAK,oBAAoB,YAAY;EACtE,CAAC;CACH,CAAC;CACD,OAAO,kBAAkB,GAAG;EAC1B;EACA;EACA;EACA,WAAW,SACT,QAAQ,IAAI,IACR,OAAO,KACL,qBAAqB,KAAK;GACxB,OAAO;GACP,QAAQ;EACV,CAAC,CACH,IACA,OAAO,SAAS,IAAI;CAC5B,CAAC;AACH,CAAC,CACH;;;ACtEF,MAAa,cAAc,OAAO,SAAS;CAAC;CAAW;CAAW;AAAiB,CAAC;;AAIpF,IAAa,qBAAb,cAAwC,OAAO,MAC7C,4CACF,CAAC,CAAC;CACA,MAAM,OAAO;;CAEb,MAAM,OAAO,IAAI,MAAM,OAAO,cAAc,CAAC,CAAC;;CAE9C,WAAW,OAAO,YAAY,OAAO,IAAI,MAAM,OAAO,cAAc,CAAC,CAAC,CAAC;CACvE,MAAM,OAAO;AACf,CAAC,CAAC,CAAC,CAAC;;AAGJ,IAAa,wBAAb,cAA2C,OAAO,MAChD,+CACF,CAAC,CAAC;CACA,OAAO;CACP,MAAM,OAAO,OAAO,MAAM,OAAO,YAAY,GAAM,CAAC;CACpD,UAAU,OAAO,MAAM,kBAAkB;;CAEzC,SAAS,OAAO,MAAM,aAAa;;CAEnC,WAAW,OAAO,eAAe,MAAM,OAAO,YAAY,EAAE,CAAC;AAC/D,CAAC,CAAC,CAAC,CAAC;AAEJ,MAAM,gBAA2D;CAC/D,UAAU;CACV,WAAW;CACX,KAAK;AACP;AAEA,MAAMA,iBAA0D;CAC9D,UAAU;CACV,WAAW;CACX,KAAK;AACP;AAEA,MAAM,gBAA2D;CAC/D,UAAU,GAAG,cAAc,SAAS;CACpC,WAAW,GAAG,cAAc,UAAU;CACtC,KAAK,GAAG,cAAc,IAAI;AAC5B;;AAGA,MAAM,mBAAmB,eAA+B;CACtD,IAAI,QAAQ;CACZ,OAAO,WAAW,SAAS,KAAK,GAAG,QAAQ,GAAG,MAAM;CACpD,OAAO;AACT;AAEA,MAAM,qBAAqB,YAAmC;CAC5D,MAAM,QAAQ;EAAC,MAAM,cAAc,QAAQ,UAAU,IAAI,QAAQ,MAAM;EAAK;EAAI,QAAQ;CAAI;CAC5F,IAAI,QAAQ,eAAe,KAAA,GAAW;EACpC,MAAM,QAAQ,gBAAgB,QAAQ,UAAU;EAChD,MAAM,KAAK,IAAI,GAAG,MAAM,aAAa,QAAQ,YAAY,KAAK;CAChE;CACA,OAAO,MAAM,KAAK,IAAI;AACxB;AAEA,MAAM,iBAAiB,SAAwB,WAA2B;CAIxE,OAAO,KAAK,KAHU,QAAQ,KAAK,GAAG,QAAQ,YAC5C,QAAQ,YAAY,QAAQ,YAAY,IAAI,QAAQ,YAAY,GACjE,IACoB,MAAM,cAAc,QAAQ,UAAU,IAAI,QAAQ,MAAM,OAAO,QAAQ,KAAK,cAAc,OAAO;AACxH;AAEA,MAAM,aAAa,OAAe,SAChC,GAAG,MAAM,GAAG,OAAO,UAAU,IAAI,KAAK;;AAGxC,MAAM,kBACJ,QACA,kBAAgD,CAAC,GACjD,kBAAgD,CAAC,MAC9C;CACH,MAAM,aAAa;EACjB,GAAG,OAAO,SAAS,KAAK,YAAY,QAAQ,QAAQ;EACpD,IAAI,OAAO,YAAY,CAAC,EAAA,CAAG,KAAK,YAAY,QAAQ,QAAQ;EAC5D,GAAG,gBAAgB,KAAK,YAAY,QAAQ,QAAQ;EACpD,GAAG,gBAAgB,KAAK,YAAY,QAAQ,QAAQ;CACtD;CACA,OAAO;EACL,UAAU,WAAW,QAAQ,aAAa,aAAa,UAAU,CAAC,CAAC;EACnE,WAAW,WAAW,QAAQ,aAAa,aAAa,WAAW,CAAC,CAAC;EACrE,OAAO,WAAW;CACpB;AACF;;;;;;;AAQA,MAAM,wBACJ,QACA,YAKW;CACX,MAAM,SAAS,eAAe,QAAQ,QAAQ,iBAAiB,QAAQ,eAAe;CACtF,IAAI,QAAQ,UAAU,WAAW,cAG/B,OAAO,2EADL,OAAO,WAAW,IAAI,gBAAgB,UAAU,OAAO,UAAU,kBAAkB,EAAE,KAAK;CAG9F,IAAI,OAAO,WAAW,GACpB,OAAO,mBAAmB,UAAU,OAAO,UAAU,kBAAkB,EAAE,oCAAoC,OAAO,aAAa,IAAI,OAAO,OAAO;CAErJ,IAAI,OAAO,YAAY,GACrB,OAAO,qBAAqB,UAAU,OAAO,WAAW,mBAAmB,EAAE;CAE/E,IAAI,OAAO,QAAQ,GACjB,OAAO;CAET,OAAO,OAAO,YAAY,YACtB,yBACA;AACN;AAEA,MAAM,iBAAiB,YACrB;CAAC,OAAO,cAAc,QAAQ,UAAU,GAAG,QAAQ;CAAS;CAAI,QAAQ;AAAI,CAAC,CAAC,KAAK,IAAI;AAEzF,MAAM,wBAAwB,YAC5B,OAAO,QAAQ,KAAK,GAAG,QAAQ,YAAY,QAAQ,YAAY,QAAQ,YAAY,KAAK,IAAI,QAAQ,UAAU,QAAQ,cAAc,QAAQ,UAAU,IAAI,QAAQ,MAAM,OAAO,QAAQ;;AAGzL,MAAM,eAAe,UAA0B,MAAM,WAAW,MAAM,KAAK;;;;;;AAO3E,MAAM,wBAAwB,YAS5B;CACE;CACA,kBAAkB,YAAY,QAAQ,OAAO;CAC7C,GAAI,QAAQ,YAAY,KAAA,KAAa,QAAQ,YAAY,KAAA,IACrD,CAAC,aAAa,YAAY,QAAQ,OAAO,KAAK,aAAa,YAAY,QAAQ,OAAO,GAAG,IACzF,CAAC;CAIL,kBAAkB,QAAQ,aAAa,MAAM,QAAQ;CACrD,GAAI,QAAQ,eAAe,KAAA,IAAY,CAAC,IAAI,CAAC,gBAAgB,QAAQ,YAAY;CACjF,GAAI,QAAQ,gBAAgB,KAAA,IACxB,CAAC,IACD,CAAC,yBAAyB,YAAY,QAAQ,WAAW,GAAG;CAChE;CACA;CACA;AACF,CAAC,CAAC,KAAK,IAAI;;;;;AAMb,MAAa,mBACX,SACA,UACuB;CACvB,MAAM,OAAO,MAAM,MAAM,cAAc,UAAU,SAAS,QAAQ,IAAI;CACtE,IAAI,SAAS,KAAA,GAAW,OAAO;CAC/B,IAAI,KAAK,UAAU,KAAA,GAAW,OAAO;CACrC,IAAI,QAAQ,UAAU,QAAQ,WAAW,OAAO;CAChD,IAAI,QAAQ,UAAU,QAAQ,YAAY,IAAI,KAAK,OAAO;CAC1D,MAAM,UAAU,iBAAiB,KAAK,KAAK;CAC3C,KAAK,IAAI,OAAO,QAAQ,WAAW,QAAQ,QAAQ,SAAS,QAAQ,GAClE,IAAI,CAAC,QAAQ,IAAI,IAAI,GAAG,OAAO,QAAQ,KAAK;AAGhD;;;;;;AAOA,MAAa,mBACX,QACA,OACA,YAsC0B;CAC1B,MAAM,WAAsC,CAAC;CAC7C,MAAM,UAA+E,CAAC;CACtF,KAAK,MAAM,WAAW,OAAO,UAAU;EACrC,MAAM,YAAY,gBAAgB,SAAS,KAAK;EAChD,IAAI,cAAc,KAAA,GAChB,SAAS,KACP,mBAAmB,KAAK;GACtB,MAAM,QAAQ;GACd,MAAM,QAAQ;GACd,GAAI,QAAQ,UAAU,QAAQ,YAAY,EAAE,WAAW,QAAQ,UAAU,IAAI,CAAC;GAC9E,MAAM,kBAAkB,OAAO;EACjC,CAAC,CACH;OAEA,QAAQ,KAAK;GAAE;GAAS,QAAQ;EAAU,CAAC;CAE/C;CAGA,MAAM,iBAAiB,CAAC,GAAI,OAAO,YAAY,CAAC,CAAE,CAAC,CAAC,MACjD,GAAG,MAAMA,eAAa,EAAE,YAAYA,eAAa,EAAE,SACtD;CACA,MAAM,gBAAgB,CAAC,GAAG,OAAO,CAAC,CAAC,MAChC,GAAG,MAAMA,eAAa,EAAE,QAAQ,YAAYA,eAAa,EAAE,QAAQ,SACtE;CAEA,MAAM,cAAc,CAAC,6CAA6C;CAClE,IAAI,QAAQ,eAAe,KAAA,GAAW,YAAY,KAAK,QAAQ,UAAU;CAIzE,IAAI,QAAQ,UAAU,KAAA,KAAa,QAAQ,eAAe,KAAA,GAAW;EACnE,MAAM,QAAQ,QAAQ,eAAe,gBAAgB,mBAAmB;EACxE,YAAY,KACV,GAAG,QAAQ,MAAM,YAAY,QAAQ,QAAQ,MAAM,aAAa,aAAa,OAC/E;CACF;CACA,IAAI,QAAQ,WAAW,KAAA,GAAW,YAAY,KAAK,SAAS,QAAQ,OAAO,EAAE;CAC7E,YAAY,KAAK,eAAe,QAAQ,QAAQ,MAAM,GAAG,CAAC,GAAG;CAC7D,MAAM,SAAS,IAAI,YAAY,KAAK,KAAK,EAAE;CAE3C,MAAM,cAAc,cAAsB,aAAqB,YAA4B;EACzF,MAAM,kBAAkB,QAAQ,mBAAmB,CAAC;EACpD,MAAM,kBAAkB,QAAQ,mBAAmB,CAAC;EACpD,MAAM,QAAQ,CACZ,qBAAqB,QAAQ;GAC3B;GACA;GACA,UAAU,QAAQ;EACpB,CAAC,CACH;EACA,IAAI,QAAQ,eAAe,KAAA,KAAa,QAAQ,iBAAiB,KAAA,GAC/D,MAAM,KACJ,IACA,QAAQ,eAAe,gBACnB,mCAAmC,QAAQ,sBAAsB,MAAM,OAAO,WAAW,QAAQ,aAAa,8DAC9G,wBAAwB,QAAQ,aAAa,EACnD;EAEF,IAAI,QAAQ,gBAAgB,KAAA,GAC1B,MAAM,KACJ,IACA,uCAAuC,QAAQ,YAAY,MAAM,GAAG,GAAK,EAAE,kDAC7E;EAEF,MAAM,KAAK,IAAI,OAAO,OAAO;EAC7B,IAAI,QAAQ,UAAU,WAAW,cAC/B,MAAM,KACJ,IACA,8BACA,IACA,GAAG,QAAQ,SAAS,QAAQ,KAAK,WAAW,KAAK,QAAQ,CAC3D;EAEF,IAAI,gBAAgB,SAAS,GAC3B,MAAM,KACJ,IACA,wDACA,IACA,GAAG,gBAAgB,IAAI,oBAAoB,CAC7C;EAEF,IAAI,gBAAgB,SAAS,GAAG;GAC9B,MAAM,KAAK,IAAI,oDAAoD;GACnE,KAAK,MAAM,WAAW,iBAAiB,MAAM,KAAK,IAAI,cAAc,OAAO,CAAC;EAC9E;EACA,KAAK,MAAM,WAAW,eAAe,MAAM,GAAG,YAAY,GACxD,MAAM,KAAK,IAAI,cAAc,OAAO,CAAC;EAEvC,IAAI,MAAM,SAAS,QAAQ,mBACzB,MAAM,KACJ,IACA,eAAe,MAAM,OAAO,MAAM,QAAQ,kBAAkB,mEAC9D;EAEF,IAAI,cAAc,GAChB,MAAM,KACJ,IACA,4CACA,GAAG,cACA,MAAM,GAAG,WAAW,CAAC,CACrB,KAAK,EAAE,SAAS,aAAa,cAAc,SAAS,MAAM,CAAC,CAChE;EAEF,IAAI,UAAU,GACZ,MAAM,KACJ,IACA,MAAM,UAAU,SAAS,aAAa,EAAE,uDAC1C;EAEF,MAAM,KAAK,IAAI,MAAM;EACrB,OAAO,MAAM,KAAK,IAAI;CACxB;CAUA,MAAM,SAAS,eACb,QACA,QAAQ,mBAAmB,CAAC,GAC5B,QAAQ,mBAAmB,CAAC,CAC9B;CACA,MAAM,QAAqB,CAAC,QAAQ,eAChC,YACA,QAAQ,UAAU,WAAW,gBAAgB,OAAO,WAAW,IAC7D,oBACA,OAAO,YAAY,aAAa,OAAO,cAAc,IACnD,YACA;CAIR,MAAM,OAAO;EACX,qBAAqB;GACnB,SAAS,QAAQ;GACjB,SAAS,QAAQ;GACjB,SAAS,QAAQ;GACjB,cAAc,QAAQ,sBAAsB,MAAM;GAClD,mBAAmB,QAAQ,oBAAoB,QAAQ;GACvD,YAAY,QAAQ;GACpB,aAAa,QAAQ;EACvB,CAAC;EACD,GAAI,QAAQ,gBAAgB,KAAA,IAAY,CAAC,IAAI,CAAC,wBAAwB,QAAQ,WAAW,CAAC;EAC1F,GAAI,QAAQ,gBAAgB,KAAA,IAAY,CAAC,IAAI,CAAC,QAAQ,WAAW;CACnE,CAAC,CAAC,KAAK,IAAI;CACX,MAAM,aAAa,MAAS,KAAK,SAAS;CAK1C,IAAI,eAAe,eAAe;CAClC,IAAI,cAAc,cAAc;CAChC,IAAI,UAAU;CACd,IAAI,OAAO,WAAW,cAAc,aAAa,OAAO;CACxD,OAAO,KAAK,SAAS,eAAe,cAAc,KAAK,eAAe,IAAI;EACxE,IAAI,cAAc,GAAG,eAAe;OAC/B,gBAAgB;EACrB,WAAW;EACX,OAAO,WAAW,cAAc,aAAa,OAAO;CACtD;CAGA,MAAM,OAAO,GAAG,KAAK,MAAM,GAAG,UAAU,EAAE,IAAI;CAE9C,OAAO,sBAAsB,KAAK;EAChC;EACA;EACA;EACA,SAAS,QAAQ,KAAK,EAAE,cAAc,OAAO;EAC7C,WAAW,QAAQ;CACrB,CAAC;AACH;;;;;;;;AC7XA,MAAa,qBAAqB,kBAAkB,KAAK;CACvD,gBAAgB;CAChB,iBAAiB;CACjB,cAAc;CACd,iBAAiB;CACjB,mBAAmB;AACrB,CAAC;;;;;;;;;AAUD,MAAa,2BAA2B,kBAAkB,KAAK;CAC7D,gBAAgB;CAChB,iBAAiB;CACjB,cAAc;CACd,iBAAiB;CACjB,mBAAmB;AACrB,CAAC;;AAGD,IAAa,mBAAb,cAAsC,OAAO,MAC3C,0CACF,CAAC,CAAC;CACA,QAAQ;;CAER,gBAAgB,OAAO,MAAM,aAAa,CAAC,CAAC,MAAM,OAAO,YAAY,EAAE,CAAC;;CAExE,gBAAgB,OAAO,MAAM,aAAa,CAAC,CAAC,MAAM,OAAO,YAAY,EAAE,CAAC;;CAExE,UAAU;CACV,MAAM;CACN,WAAW,OAAO,YAAY,eAAe;CAC7C,OAAO,OAAO,IAAI,MAAM,OAAO,cAAc,CAAC,CAAC;;;;;;CAM/C,OAAO,OAAO,YAAY,WAAW;;;;;;CAMrC,YAAY,OAAO,YAAY,OAAO,SAAS,CAAC,OAAO,aAAa,CAAC,CAAC;CACtE,YAAY,OAAO,YAAY,OAAO,SAAS,CAAC,eAAe,MAAM,CAAC,CAAC;CACvE,cAAc,OAAO,YAAY,OAAO,OAAO,MAAM,OAAO,YAAY,GAAK,CAAC,CAAC;CAC/E,OAAO,OAAO,YAAY,WAAW;AACvC,CAAC,CAAC,CAAC,CAAC;;AAqCJ,MAAa,sBACX,UACA,UAEA,cAAc,KAAK;CACjB,YAAY,SAAS;CACrB,QAAQ,SAAS;CACjB,OAAO,SAAS;CAChB,MAAM,SAAS;CACf,SAAS,SAAS;CAClB,SAAS,SAAS;CAClB,kBAAkB,MAAM;AAC1B,CAAC;;AAGH,MAAa,wBAAwB,QAAoB,gBACvD,OAAO,SAAS,UAAU,cACtB,SACA,WAAW,KAAK;CACd,SAAS,OAAO;CAChB,SAAS,OAAO;CAChB,UAAU,sBAAsB,OAAO,QAAQ,CAAC,CAAC,MAAM,GAAG,WAAW;CACrE,GAAI,OAAO,aAAa,KAAA,IAAY,EAAE,UAAU,OAAO,SAAS,IAAI,CAAC;AACvE,CAAC;AAEP,MAAM,cAAc,YAClB,GAAG,QAAQ,KAAK,QAAQ,QAAQ,UAAU,QAAQ,QAAQ,QAAQ,QAAQ,QAAQ,SAAS,QAAQ,QAAQ;AAE7G,MAAM,eAA0D;CAC9D,UAAU;CACV,WAAW;CACX,KAAK;AACP;AAEA,MAAM,yBACJ,aACiC;CACjC,MAAM,4BAAY,IAAI,IAA2B;CACjD,KAAK,MAAM,WAAW,UAAU;EAC9B,MAAM,MAAM,GAAG,QAAQ,MAAM,QAAQ,QAAQ;EAC7C,MAAM,WAAW,UAAU,IAAI,GAAG;EAClC,IACE,aAAa,KAAA,KACb,aAAa,QAAQ,YAAY,aAAa,SAAS,WAEvD,UAAU,IAAI,KAAK,OAAO;CAE9B;CACA,OAAO,CAAC,GAAG,UAAU,OAAO,CAAC,CAAC,CAC3B,MAAM,MAAM,UAAU,aAAa,KAAK,YAAY,aAAa,MAAM,SAAS,CAAC,CACjF,MAAM,GAAG,EAAE;AAChB;;;;;;;;;AAUA,MAAa,iBAOX,SASA,YAEA,OAAO,IAAI,aAAa;CACtB,MAAM,SAAS,OAAO;CACtB,MAAM,WAAW,OAAO,OAAO;CAC/B,MAAM,QAAQ,OAAO,OAAO;CAC5B,MAAM,cAAc,OAAO,OAAO;CAClC,MAAM,mBAAmB,OAAO,eAC9B,OAAO,OAAO,cAAc,sBAAsB,CACpD;CACA,MAAM,UAAU,mBAAmB,UAAU,KAAK;CAClD,MAAM,cAAc,mBAAmB,UAAU,WAAW;CAC5D,MAAM,cACJ,QAAQ,cAAc,KAAA,IAClB,KAAA,IACA,OAAO,4BAA4B,aAAa,QAAQ,UAAU,WAAW,CAAC;CAEpF,MAAM,SAAS,OAAO,gBAAgB,QAAQ,UAAU,kBAAkB;CAC1E,MAAM,WAAW,OAAO,aAAa,MAAM,SAAS,SAAS;EAC3D,QAAQ,gBAAgB,MAAM;EAC9B,4BAA4B,OAAO,QAAQ,GAAG;CAChD,CAAC;CACD,MAAM,SAAS,OAAO,SAAS;CAC/B,MAAM,SAAS,OAAO,SAAS;CAI/B,MAAM,UAAU,OAAO,OAAO,oBAAoB,UAAU,CAAC,CAAC,OAAO,MAAM;CAC3E,MAAM,SAAS,qBAAqB,SAAS,iBAAiB,QAAQ,WAAW,CAAC;CAClF,MAAM,QAAQ,OAAO,OAAO;CAC5B,MAAM,gBAAgB,IAAI,IACxB,kBAAkB,iBAChB,MAAM,SAAS,SACb,KAAK,iBAAiB,KAAA,IAAY,CAAC,KAAK,IAAI,IAAI,CAAC,KAAK,MAAM,KAAK,YAAY,CAC/E,CACJ;CACA,MAAM,aACJ,kBAAkB,SAAS,gBAAgB,iBAAiB,aAAa,KAAA;CAC3E,MAAM,oBACJ,YAAY,mBACT,QAAQ,YAAY,CAAC,cAAc,IAAI,QAAQ,IAAI,CAAC,CAAC,CACrD,IAAI,iBAAiB,KAAK,CAAC;CAChC,MAAM,iBAAiB,sBAAsB,CAAC,GAAG,mBAAmB,GAAG,OAAO,QAAQ,CAAC,CAAC,CAAC,MACvF,GACA,iBAAiB,QAAQ,WAAW,CACtC;CACA,MAAM,oBAAoB,IAAI,IAAI,eAAe,IAAI,UAAU,CAAC;CAChE,MAAM,qBAAqB,IAAI,IAAI,OAAO,SAAS,IAAI,UAAU,CAAC;CAClE,MAAM,kBAAkB,kBAAkB,QACvC,YACC,kBAAkB,IAAI,WAAW,OAAO,CAAC,KAAK,CAAC,mBAAmB,IAAI,WAAW,OAAO,CAAC,CAC7F;CAGA,MAAM,2BAA2B,YAAY,mBAAmB,IAAI,iBAAiB,KAAK,CAAC;CAC3F,MAAM,iBAAiB,sBAAsB,CAC3C,GAAG,0BACH,GAAI,OAAO,YAAY,CAAC,CAC1B,CAAC;CACD,MAAM,qBAAqB,IAAI,KAC5B,OAAO,YAAY,CAAC,EAAA,CAAG,KAAK,YAAY,GAAG,QAAQ,MAAM,QAAQ,QAAQ,MAAM,CAClF;CACA,MAAM,oBAAoB,IAAI,IAC5B,eAAe,KAAK,YAAY,GAAG,QAAQ,MAAM,QAAQ,QAAQ,MAAM,CACzE;CACA,MAAM,kBAAkB,yBAAyB,QAAQ,YAAY;EACnE,MAAM,MAAM,GAAG,QAAQ,MAAM,QAAQ,QAAQ;EAC7C,OAAO,kBAAkB,IAAI,GAAG,KAAK,CAAC,mBAAmB,IAAI,GAAG;CAClE,CAAC;CACD,MAAM,mBAAmB,kBAAkB,cAAc,SAAS;CAClE,MAAM,WAAW,qBAAqB;EACpC,OAAO,QAAQ,eAAe;EAC9B;EACA,YAAY;EACZ;EACA,kBAAkB,SAAS;EAC3B;CACF,CAAC;CACD,MAAM,iBACJ,qBAAqB,KAAA,KACrB,SAAS,WAAW,cACpB,gBAAgB,KAAA,KAChB,SAAS,YAAY,KAAA,KACrB,iBAAiB,oBAAoB,WAAW,cAC5C,YAAY,KAAK;EACf,SAAS;EACT,YAAY,SAAS;EACrB,mBAAmB,SAAS;EAC5B,SAAS,SAAS;EAClB,SAAS,SAAS;EAClB,SAAS,SAAS;EAClB,iBAAiB,SAAS;EAC1B,oBAAoB,iBAAiB;EACrC,0BAA0B;EAC1B,mBAAmB,YAAY;EAC/B,oBAAoB,eAAe,IAAI,eAAe;EACtD,oBAAoB,eAAe,IAAI,eAAe;EACtD,gBAAgB,iBAAiB;CACnC,CAAC,IACD,KAAA;CACN,MAAM,aACJ,mBAAmB,KAAA,KAAa,kBAAkB,uBAAuB,KAAA,IACrE;EACE,OAAO,KAAA;EACP,QAAQ,KAAA;EACR,QACE,kBAAkB,oBAAoB,WAAW,iBACjD,SAAS,WAAW,aACf,iBAAiB,mBAAmB,qBACrC,kDACA,KAAA;CACR,IACA,OAAO,iBAAiB,mBAAmB,OAAO,cAAc,CAAC,CAAC,KAChE,OAAO,MAAM;EACX,YAAY,WAAW;GACrB,OAAO,KAAA;GACP,QAAQ,KAAA;GACR,QACE,MAAM,SAAS,8BACX,+CAA+C,MAAM,aAAa,oBAClE,uDAAuD,MAAM;EACrE;EACA,YAAY,YAAY;GAAE,OAAO;GAAgB;GAAQ,QAAQ,KAAA;EAAU;CAC7E,CAAC,CACH;CACN,MAAM,OAAO,gBAAgB,QAAQ,aAAa;EAChD,cAAc,QAAQ;EACtB,SAAS,SAAS;EAClB,mBAAmB,SAAS;EAC5B,SAAS,SAAS;EAClB,SAAS,SAAS;EAClB,YAAY,QAAQ;EACpB,QAAQ,QAAQ;EAChB;EACA,YAAY,QAAQ;EACpB,aAAa,SAAS,WAAW,aAAa,cAAc,KAAA;EAC5D;EACA;EACA;EACA,YAAY,kBAAkB;EAC9B,cAAc,kBAAkB;EAChC,aAAa,kBAAkB;EAC/B,oBAAoB,MAAM;EAC1B;EACA,aAAa,WAAW;EACxB,aAAa,WAAW;CAC1B,CAAC;CAED,MAAM,QACJ,QAAQ,eAAe,KAAA,IAAY,CAAC,IAAK,EAAE,YAAY,QAAQ,WAAW;CAC5E,IAAI,CAAC,QAAQ,MACX,OAAO,iBAAiB,KAAK;EAC3B;EACA;EACA;EACA;EACA;EACA,OAAO,OAAO;EACd;EACA,GAAG;EACH,GAAI,qBAAqB,KAAA,IACrB,CAAC,IACD;GAAE,YAAY,iBAAiB;GAAM,cAAc,iBAAiB;EAAO;EAC/E,GAAI,WAAW,UAAU,KAAA,IAAY,CAAC,IAAI,EAAE,OAAO,WAAW,MAAM;CACtE,CAAC;CAGH,MAAM,YAAY,QAAO,OADA,gBAAA,CACU,QAAQ,IAAI;CAC/C,OAAO,iBAAiB,KAAK;EAC3B;EACA;EACA;EACA;EACA;EACA;EACA,OAAO,OAAO;EACd;EACA,GAAG;EACH,GAAI,qBAAqB,KAAA,IACrB,CAAC,IACD;GAAE,YAAY,iBAAiB;GAAM,cAAc,iBAAiB;EAAO;EAC/E,GAAI,WAAW,UAAU,KAAA,IAAY,CAAC,IAAI,EAAE,OAAO,WAAW,MAAM;CACtE,CAAC;AACH,CAAC;;;ACpSH,MAAM,cAAuC,CAAC;AAE9C,MAAM,mBAAmB,UAAyC;CAChE,KAAK,MAAM,QAAQ,OAAO;EACxB,MAAM,iBAAiB,sBAAsB,IAAI;EACjD,IAAI,mBAAmB,YACrB,MAAM,IAAI,MACR,8BAA8B,KAAK,KAAK,8BAA8B,eAAe,2IAGvF;CAEJ;AACF;AAEA,MAAM,iBACJ,QACA,WAEA,WAAW,KAAA,KAAa,OAAO,SAAS,IACpC,OAAO,KAAK,OAAO,QAAQ,+BAA+B,MAAM,CAAC,CAAC,IAClE;;;;;;;;AASN,MAAM,mBACJ,WACA,WAEA,cACE,OAAO,IAAI,aAAa;CACtB,MAAM,SAAS,OAAO;CACtB,MAAM,WAAW,OAAO,OAAO;CAC/B,MAAM,QAAQ,OAAO,OAAO;CAC5B,OAAO,OAAO,4BACZ,OACA,UAAU,mBAAmB,UAAU,KAAK,CAAC,CAC/C;AACF,CAAC,GACD,MACF;AAEF,MAAM,0BACJ,WACA,WAEA,cACE,OAAO,IAAI,aAAa;CACtB,MAAM,SAAS,OAAO;CAGtB,OAAO,OAAO,0BAA0B,UAAU,oBAAoB,OAF9C,OAAO,UAEiD,OAD3D,OAAO,WACyD,CAAC,CAAC;AACzF,CAAC,GACD,MACF;AAEF,MAAM,sBAAsB,WAC1B,cACE,OAAO,IAAI,aAAa;CACtB,MAAM,SAAS,OAAO;CACtB,OAAO;EACL,UAAU,OAAO,OAAO;EACxB,OAAO,OAAO,OAAO;CACvB;AACF,CAAC,GACD,MACF;;;;;;;;AASF,MAAM,QAMJ,YACG;CAGH,MAAM,aAAa,QAAQ,cAAe;CAC1C,gBAAgB,UAAU;CAE1B,MAAM,aAAa,MAAM,OAAO,eAAe;EAC7C,OAAO;EACP,QAAQ;EACR,cAAc,uBAAuB;GACnC,UAAU,QAAQ;GAClB,aAAa,QAAQ;EACvB,CAAC;EACD,SAAS,QAAQ,KAAK,kBAAkB,cAAc,UAAU,GAAG,UAAU;EAC7E,QAAQ,QAAQ,WAAW,KAAA,IAAY,sBAAsB,YAAY,KAAK,QAAQ,MAAM;EAC5F,aACE;EACF,UAAU;GAAE,iBAAiB;GAAK,SAAS;EAAY;CACzD,CAAC;CAID,MAAM,UAAU,OAAO,OAAO;EAAE;EAAY,OAAO,QAAQ;CAAM,CAAC;CAIlE,MAAM,aAAa,YACjB;EACE,WAAW,aAAa,OAAO;EAC/B,gBAAgB,OAAO,QAAQ,gBAAgB,KAAK;EACpD,GAAI,QAAQ,eAAe,KAAA,IAAY,CAAC,IAAI,CAAC,SAAS,QAAQ,YAAY;CAC5E,CAAC,CAAC,KAAK,IAAQ;CACjB,MAAM,oBAAoB,YACxB;EACE;EACA,KAAK,UAAUC,gBAAsB,QAAQ,UAAU,OAAO,CAAC;EAC/D,KAAK,UAAU,QAAQ,UAAU,CAAC,CAAC;EACnC,KAAK,UAAU,WAAW,KAAK,SAAS,KAAK,IAAI,CAAC;EAClD,KAAK,UAAU,QAAQ,UAAU,CAAC,CAAC;EACnC,eAAe,iBAAiB,QAAQ,WAAW;EACnD,gBAAgB,OAAO,QAAQ,gBAAgB,KAAK;EACpD,GAAI,QAAQ,eAAe,KAAA,IAAY,CAAC,IAAI,CAAC,SAAS,QAAQ,YAAY;CAC5E,CAAC,CAAC,KAAK,IAAQ;CAEjB,MAAM,OAAO,aAA+B,CAAC,MAC3C,cACE,cAAc,SAAS;EACrB,MAAM,WAAW,QAAQ;EACzB,cAAc,QAAQ,gBAAgB;EACtC,QAAQ,QAAQ,UAAU;EAC1B,aAAa,iBAAiB,QAAQ,WAAW;EACjD;EACA,YAAY,QAAQ;EACpB,QAAQ,WAAW;EACnB,YAAY;EACZ,aAAa;CACf,CAAC,CAAC,CAAC,KAAK,OAAO,QAAQ,MAAM,SAAS,oBAAoB,YAAY,KAAK,CAAC,GAAG,OAAO,MAAM,GAC5F,QAAQ,MACV;CAEF,OAAO;EACL;EACA;EACA;EACA,aAAa,gBAAgB,WAAW,QAAQ,MAAM;EACtD,oBAAoB,uBAAuB,kBAAkB,QAAQ,MAAM;EAC3E,UAAU,mBAAmB,QAAQ,MAAM;EAC3C,cAAc,UAA0D;GACtE,MAAM,UAAU,mBAAmB,QAAQ,UAAU,CAAC,CAAC;GACvD,OAAO,MAAM,QAAQ,SAAS,CAAC,QAAQ,KAAK,IAAI,CAAC;EACnD;CACF;AACF;;;;;;;;;AA0BA,MAAM,cACJ,YACG;CACH,MAAM,QAAQ,sBAAsB;EAClC,UAAU,QAAQ;EAClB,aAAa,QAAQ;CACvB,CAAC;CAED,MAAM,UAAU,OAAO,OAAO;EAAE,YAAY,MAAM;EAAQ,OAAO,QAAQ;CAAM,CAAC;CAChF,MAAM,eAAe,OAAO,OAAO;EAAE,YAAY,MAAM;EAAO,OAAO,QAAQ;CAAM,CAAC;CAKpF,MAAM,gBACJ,QAAQ,aAAa,KAAA,IACjB,CAAC,IACD,OAAO,QAAQ,aAAa,WAC1B,CAAC,QAAQ,QAAQ,IACjB,QAAQ;CAChB,MAAM,aAAa,YACjB;EACE,MAAM,OAAO,aAAa,OAAO;EACjC,iBAAiB,KAAK,UAAU,aAAa;EAC7C,gBAAgB,OAAO,QAAQ,gBAAgB,KAAK;EACpD,GAAI,QAAQ,eAAe,KAAA,IAAY,CAAC,IAAI,CAAC,SAAS,QAAQ,YAAY;CAC5E,CAAC,CAAC,KAAK,GAAG;CACZ,MAAM,oBAAoB,aACxB;EACE;EACA,KAAK,UAAU,aAAa;EAC5B,KAAK,UAAU,QAAQ,UAAU,CAAC,CAAC;EACnC,eAAe,iBAAiB,QAAQ,WAAW;EACnD,gBAAgB,OAAO,QAAQ,gBAAgB,KAAK;EACpD,GAAI,QAAQ,eAAe,KAAA,IAAY,CAAC,IAAI,CAAC,SAAS,QAAQ,YAAY;CAC5E,CAAC,CAAC,KAAK,IAAQ;CACjB,MAAM,kBAAkB,uBAAuB,MAAM,UAAU,CAAC,CAAC,YAAY,CAAC,CAAC,KAC7E,MAAM,QACJ,MAAM,SAAS,wBAAwB,gCAAgC,YAAY,KAAK,CAC1F,CACF;CAEA,MAAM,OAAO,aAA+B,CAAC,MAC3C,cACE,cAAc,SAAS;EACrB,MAAM,WAAW,QAAQ;EACzB,cAAc,QAAQ,gBAAgB;EACtC,QAAQ,QAAQ,UAAU;EAC1B,aAAa,iBAAiB,QAAQ,WAAW;EACjD;EACA,YAAY,QAAQ;EACpB,QAAQ,WAAW;EACnB,YAAY;EACZ,aAAa;CACf,CAAC,CAAC,CAAC,KACD,OAAO,QACL,MAAM,SAAS,+BAA+B,iBAAiB,YAAY,KAAK,CAClF,GACA,OAAO,MACT,GACA,QAAQ,MACV;CAEF,OAAO;EACL,YAAY,MAAM;EAClB;EACA;EACA;EACA,aAAa,gBAAgB,WAAW,QAAQ,MAAM;EACtD,oBAAoB,uBAAuB,kBAAkB,QAAQ,MAAM;EAC3E,UAAU,mBAAmB,QAAQ,MAAM;EAC3C,cAAc,UAA0D;GACtE,MAAM,UAAU,mBAAmB,QAAQ,UAAU,CAAC,CAAC;GACvD,OAAO,MAAM,QAAQ,SAAS,CAAC,QAAQ,KAAK,IAAI,CAAC;EACnD;CACF;AACF;;;;;;;AAQA,MAAa,WAAW;CAAE;CAAM;AAAW;;;;AChW3C,IAAa,yBAAb,cAA4C,OAAO,YAAoC,CAAC,CACtF,0BACA,EACE,QAAQ,OAAO,OACjB,CACF,CAAC,CAAC;CACA,IAAa,UAAU;EACrB,OAAO,KAAK;CACd;AACF;;AAGA,MAAa,kBAAkB,OAAO,OAAO;CAC3C,cAAc,OAAO,YACnB,OAAO,OAAO;EACZ,QAAQ,OAAO;EACf,OAAO,OAAO,YAAY,OAAO,OAAO;CAC1C,CAAC,CACH;CACA,YAAY,OAAO,YAAY,OAAO,OAAO,EAAE,WAAW,OAAO,OAAO,CAAC,CAAC;AAC5E,CAAC;AAGD,MAAM,cAAc,OAAO,oBAAoB,OAAO,eAAe,eAAe,CAAC;;AAGrF,MAAa,kBAAkB,OAAO,GAAG,iBAAiB,CAAC,CAAC,aAAa;CACvE,MAAM,YAAY,OAAO,OAAO,OAAO,mBAAmB,CAAC,CAAC,KAAK,OAAO,YAAY,EAAE,CAAC;CACvF,IAAI,cAAc,IAAI,OAAO,OAAO,KAAsB;CAE1D,MAAM,MAAM,QAAO,OADD,WAAW,WAAA,CAE1B,eAAe,SAAS,CAAC,CACzB,KACC,OAAO,UAAU,UACf,uBAAuB,KAAK,EAAE,QAAQ,8BAA8B,MAAM,UAAU,CAAC,CACvF,CACF;CACF,MAAM,QAAQ,OAAO,YAAY,GAAG,CAAC,CAAC,KACpC,OAAO,UAAU,UACf,uBAAuB,KAAK,EAAE,QAAQ,gCAAgC,MAAM,UAAU,CAAC,CACzF,CACF;CACA,OAAO,OAAO,KAAK,KAAK;AAC1B,CAAC;;;;;AAWD,MAAa,sBAAsB,OAAO,GAAG,qBAAqB,CAAC,CAAC,WAAW,SAG5E;CACD,IAAI,aAAa,QAAQ,cAAc;CACvC,IAAI,eAAe,IACjB,aAAa,OAAO,OAAO,OAAO,mBAAmB,CAAC,CAAC,KAAK,OAAO,YAAY,EAAE,CAAC;CAEpF,IAAI,SAAS,QAAQ;CACrB,IAAI,WAAW,KAAA,KAAa,eAAe,IAAI;EAC7C,MAAM,QAAQ,OAAO,gBAAgB;EACrC,IAAI,OAAO,OAAO,KAAK,GAAG;GACxB,WAAW,MAAM,MAAM,cAAc;GACrC,IAAI,eAAe,IAAI,aAAa,MAAM,MAAM,YAAY,aAAa;EAC3E;CACF;CACA,IAAI,eAAe,MAAM,WAAW,KAAA,GAClC,OAAO,OAAO,uBAAuB,KAAK,EACxC,QACE,wHACJ,CAAC;CAEH,OAAO;EAAE;EAAY;CAAO;AAC9B,CAAC;;;;;;AAOD,MAAa,sBACX,WAEA,MAAM,OACJ,OAAO,IAAI,aAAa;CACtB,MAAM,SAAS,OAAO,OAAO,OAAO,gBAAgB,CAAC,CAAC,KACpD,OAAO,YAAY,wBAAwB,CAC7C;CACA,MAAM,QAAQ,OAAO,OAAO,OAAO,OAAO,SAAS,cAAc,CAAC;CAClE,MAAM,cAAc,mBAAmB,MAAM;EAC3C;EACA,YAAY,OAAO;EACnB,QAAQ,OAAO;EACf;CACF,CAAC;CACD,MAAM,OAAO,MAAM,MAAM,aAAa,gBAAgB,KAAK;CAC3D,OAAO,MAAM,SACX,6BAA6B,KAAK,MAAM,QAAQ,IAAI,CAAC,GACrD,2BAA2B,KAAK,MAAM,QAAQ,IAAI,CAAC,GACnD,wBAAwB,KAAK,MAAM,QAAQ,IAAI,CAAC,CAClD;AACF,CAAC,CACH;;;AC7GF,MAAa,mBAAmC;AAEhD,MAAa,gBAAgD;CAC3D,QAAQ;CACR,WAAW;AACb;AAEA,MAAa,0BAA0D;CACrE,QAAQ;CACR,WAAW;AACb;;;;;;;;AASA,MAAa,wBAAwB;CACnC,QAAQ;EAAC;EAAO;EAAU;EAAQ;CAAO;CACzC,WAAW;EAAC;EAAO;EAAU;CAAM;AACrC;;AAMA,MAAa,yBAAyB,OAAgB,WACpD,oBAAoB,MAAM,SAAS,cAAc,QAAQ;CACvD,mBAAmB;CACnB,OAAO;CACP,kBAAkB;CAClB,GAAI,WAAW,KAAA,IACX,CAAC,IACD,EAAE,WAAW,EAAE,QAAQ,kBAAkB,QAAQ,sBAAsB,MAAM,EAAE,EAAE;AACvF,CAAC;;AAGH,MAAa,4BAA4B,OAAgB,WACvD,uBAAuB,MAAM,SAAS,cAAc,WAAW;CAC7D,YAAY;CACZ,GAAI,WAAW,KAAA,IACX,CAAC,IACD,EAAE,eAAe,EAAE,QAAQ,kBAAkB,QAAQ,sBAAsB,SAAS,EAAE,EAAE;AAC9F,CAAC;;;;;;;AAQH,MAAa,uBACX,UACA,OACA,WACW;CACX,MAAM,OAAO,GAAG,SAAS,GAAG,SAAS,cAAc;CACnD,OAAO,WAAW,KAAA,IACd,OACA,GAAG,KAAK,WAAW,kBAAkB,QAAQ,sBAAsB,SAAS,EAAE;AACpF;;AAGA,MAAa,oBAAoB,aAAa,YAAY,EACxD,QAAQ,OAAO,SAAS,wBAAwB,MAAM,EACxD,CAAC,CAAC,CAAC,KAAK,MAAM,QAAQ,gBAAgB,KAAK,CAAC;;AAG5C,MAAa,uBAAuB,gBAAgB,YAAY,EAC9D,QAAQ,OAAO,SAAS,wBAAwB,SAAS,EAC3D,CAAC,CAAC,CAAC,KAAK,MAAM,QAAQ,gBAAgB,KAAK,CAAC"}
|
|
1
|
+
{"version":3,"file":"providers-CaOnz7mK.mjs","names":["severityRank","resolveReviewGuidance"],"sources":["../src/internal/coverage.ts","../src/internal/effort.ts","../src/internal/ignore.ts","../src/internal/render.ts","../src/internal/run.ts","../src/internal/factory.ts","../src/internal/github-env.ts","../src/internal/providers.ts"],"sourcesContent":["import { Option, Schema } from \"effect\";\nimport type { RunEvent } from \"effect-agent\";\n\nimport type { ChangedFile } from \"./diff.ts\";\nimport { FileReviewDelegationFailure, FileReviewRequest, FileReviewUnitResult } from \"./fan-out.ts\";\nimport { FileDiffQuery } from \"./review-agent.ts\";\nimport { planReviewUnits } from \"./review-units.ts\";\n\n// ---------------------------------------------------------------------------\n// Host-owned coverage. Model summaries are untrusted prose; the check result\n// is based on deterministic unit planning plus the semantic Tool events that\n// prove which required review operations actually settled successfully.\n// ---------------------------------------------------------------------------\n\nexport const ReviewShape = Schema.Literals([\"flat\", \"fan-out\"]);\nexport type ReviewShape = typeof ReviewShape.Type;\n\nexport class FailedReviewUnit extends Schema.Class<FailedReviewUnit>(\n \"@effect-agent/pr-review/FailedReviewUnit\",\n)({\n unitId: Schema.NonEmptyString.check(Schema.isMaxLength(32)),\n errorTag: Schema.NonEmptyString.check(Schema.isMaxLength(256)),\n}) {}\n\nexport class ReviewCoverage extends Schema.Class<ReviewCoverage>(\n \"@effect-agent/pr-review/ReviewCoverage\",\n)({\n status: Schema.Literals([\"complete\", \"incomplete\"]),\n requiredPaths: Schema.Array(Schema.NonEmptyString.check(Schema.isMaxLength(512))).check(\n Schema.isMaxLength(300),\n ),\n reviewedPaths: Schema.Array(Schema.NonEmptyString.check(Schema.isMaxLength(512))).check(\n Schema.isMaxLength(300),\n ),\n unreviewedPaths: Schema.Array(Schema.NonEmptyString.check(Schema.isMaxLength(512))).check(\n Schema.isMaxLength(300),\n ),\n failedUnits: Schema.Array(FailedReviewUnit).check(Schema.isMaxLength(8)),\n reasons: Schema.Array(Schema.NonEmptyString.check(Schema.isMaxLength(1_000))).check(\n Schema.isMaxLength(20),\n ),\n}) {}\n\ninterface ToolTrace {\n readonly declared: Map<string, Extract<RunEvent, { readonly _tag: \"ToolCallDeclared\" }>>;\n readonly succeeded: Map<string, Extract<RunEvent, { readonly _tag: \"ToolCallSucceeded\" }>>;\n readonly failed: Map<string, Extract<RunEvent, { readonly _tag: \"ToolCallFailed\" }>>;\n}\n\nconst toolTrace = (events: ReadonlyArray<RunEvent>): ToolTrace => {\n const declared = new Map<string, Extract<RunEvent, { readonly _tag: \"ToolCallDeclared\" }>>();\n const succeeded = new Map<string, Extract<RunEvent, { readonly _tag: \"ToolCallSucceeded\" }>>();\n const failed = new Map<string, Extract<RunEvent, { readonly _tag: \"ToolCallFailed\" }>>();\n for (const event of events) {\n if (event._tag === \"ToolCallDeclared\") declared.set(event.toolCallId, event);\n if (event._tag === \"ToolCallSucceeded\") succeeded.set(event.toolCallId, event);\n if (event._tag === \"ToolCallFailed\") failed.set(event.toolCallId, event);\n }\n return { declared, succeeded, failed };\n};\n\nconst sortedUnique = (values: Iterable<string>): ReadonlyArray<string> =>\n [...new Set(values)].sort((left, right) => (left < right ? -1 : left > right ? 1 : 0));\n\nconst boundedListReason = (label: string, values: Iterable<string>): string => {\n const items = sortedUnique(values);\n const prefix = `${label} (${items.length}): `;\n let rendered = prefix;\n for (let index = 0; index < items.length; index += 1) {\n const item = items[index] ?? \"\";\n const separator = index === 0 ? \"\" : \", \";\n const omitted = items.length - index - 1;\n const suffix = omitted === 0 ? \"\" : ` … (+${omitted} more)`;\n if (`${rendered}${separator}${item}${suffix}`.length > 1_000) {\n const omission = `… (+${items.length - index} more)`;\n return `${rendered.slice(0, 1_000 - omission.length)}${omission}`;\n }\n rendered = `${rendered}${separator}${item}`;\n }\n return rendered;\n};\n\nconst flatCoverage = (\n files: ReadonlyArray<ChangedFile>,\n totalFiles: number,\n trace: ToolTrace,\n): ReviewCoverage => {\n const requiredPaths = sortedUnique(files.map((file) => file.path));\n const reviewed = new Set<string>();\n const failedPaths = new Set<string>();\n for (const [toolCallId, declaration] of trace.declared) {\n if (declaration.toolName !== \"read_file_diff\") continue;\n const query = Schema.decodeUnknownOption(FileDiffQuery)(declaration.parameters);\n if (Option.isNone(query)) continue;\n if (trace.succeeded.has(toolCallId)) reviewed.add(query.value.path);\n if (trace.failed.has(toolCallId)) failedPaths.add(query.value.path);\n }\n const undiffable = files.filter((file) => file.patch === undefined).map((file) => file.path);\n const unreviewed = requiredPaths.filter(\n (path) => !reviewed.has(path) || undiffable.includes(path) || failedPaths.has(path),\n );\n const reasons: Array<string> = [];\n if (files.length < totalFiles) {\n reasons.push(`review range exposed ${files.length} of ${totalFiles} required files`);\n }\n if (undiffable.length > 0) {\n reasons.push(boundedListReason(\"required paths have no textual diff\", undiffable));\n }\n if (failedPaths.size > 0) {\n reasons.push(boundedListReason(\"diff reads failed\", failedPaths));\n }\n if (unreviewed.length > 0) {\n reasons.push(boundedListReason(\"required paths were not successfully reviewed\", unreviewed));\n }\n return ReviewCoverage.make({\n status: reasons.length === 0 ? \"complete\" : \"incomplete\",\n requiredPaths,\n reviewedPaths: sortedUnique(reviewed),\n unreviewedPaths: sortedUnique(unreviewed),\n failedUnits: [],\n reasons,\n });\n};\n\nconst fanOutCoverage = (\n files: ReadonlyArray<ChangedFile>,\n totalFiles: number,\n trace: ToolTrace,\n): ReviewCoverage => {\n const plan = planReviewUnits(files, { totalChangedFiles: totalFiles });\n const declarationsByUnit = new Map<\n string,\n Array<{ readonly id: string; readonly paths: ReadonlyArray<string> }>\n >();\n for (const [toolCallId, declaration] of trace.declared) {\n if (declaration.toolName !== \"delegate_file_review\") continue;\n const request = Schema.decodeUnknownOption(FileReviewRequest)(declaration.parameters);\n if (Option.isNone(request)) continue;\n const declarations = declarationsByUnit.get(request.value.unitId) ?? [];\n declarations.push({ id: toolCallId, paths: request.value.paths });\n declarationsByUnit.set(request.value.unitId, declarations);\n }\n\n const reviewed = new Set<string>();\n const unreviewed = new Set<string>([...plan.undiffablePaths, ...plan.unassignedPaths]);\n const failedUnits: Array<FailedReviewUnit> = [];\n const reasons: Array<string> = [];\n for (const unit of plan.units) {\n const declarations = declarationsByUnit.get(unit.unitId) ?? [];\n const expectedPaths = [...unit.paths];\n const exact = declarations.filter(\n (declaration) =>\n declaration.paths.length === expectedPaths.length &&\n declaration.paths.every((path, index) => path === expectedPaths[index]),\n );\n const successful = exact.filter((declaration) => {\n const event = trace.succeeded.get(declaration.id);\n if (event === undefined || trace.failed.has(declaration.id)) return false;\n const result = Schema.decodeUnknownOption(FileReviewUnitResult)(event.result);\n return Option.isSome(result) && result.value.unitId === unit.unitId;\n });\n if (declarations.length === 1 && exact.length === 1 && successful.length === 1) {\n for (const path of unit.paths) reviewed.add(path);\n continue;\n }\n for (const path of unit.paths) unreviewed.add(path);\n const failure = declarations\n .map((declaration) => trace.failed.get(declaration.id))\n .find((event) => event !== undefined);\n const returnedFailure = declarations\n .map((declaration) => trace.succeeded.get(declaration.id))\n .filter((event) => event !== undefined)\n .map((event) => Schema.decodeUnknownOption(FileReviewDelegationFailure)(event.result))\n .find(Option.isSome);\n failedUnits.push(\n FailedReviewUnit.make({\n unitId: unit.unitId,\n errorTag:\n failure?.errorTag ??\n (returnedFailure !== undefined\n ? returnedFailure.value._tag === \"FileReviewUnitFailed\"\n ? `${returnedFailure.value._tag}:${returnedFailure.value.childErrorTag}`\n : returnedFailure.value._tag\n : undefined) ??\n (declarations.length === 0\n ? \"UnitNotAssigned\"\n : declarations.length > 1\n ? \"UnitAssignedMultipleTimes\"\n : exact.length === 0\n ? \"UnitAssignmentMismatch\"\n : \"UnitDidNotSettleSuccessfully\"),\n }),\n );\n }\n if (plan.truncated) {\n reasons.push(`review range exposed ${files.length} of ${totalFiles} required files`);\n }\n if (plan.undiffablePaths.length > 0) {\n reasons.push(boundedListReason(\"required paths have no textual diff\", plan.undiffablePaths));\n }\n if (plan.unassignedPaths.length > 0) {\n reasons.push(boundedListReason(\"fan-out capacity left paths unassigned\", plan.unassignedPaths));\n }\n if (failedUnits.length > 0) {\n reasons.push(\n boundedListReason(\n \"review units did not complete\",\n failedUnits.map((unit) => `${unit.unitId} (${unit.errorTag})`),\n ),\n );\n }\n return ReviewCoverage.make({\n status: reasons.length === 0 ? \"complete\" : \"incomplete\",\n requiredPaths: sortedUnique(files.map((file) => file.path)),\n reviewedPaths: sortedUnique(reviewed),\n unreviewedPaths: sortedUnique(unreviewed),\n failedUnits,\n reasons,\n });\n};\n\n/** Assess one settled run without trusting its prose summary or verdict. */\nexport const assessReviewCoverage = (input: {\n readonly shape: ReviewShape;\n readonly files: ReadonlyArray<ChangedFile>;\n readonly totalFiles: number;\n readonly anchorFiles: ReadonlyArray<ChangedFile>;\n readonly totalAnchorFiles: number;\n readonly events: ReadonlyArray<RunEvent>;\n}): ReviewCoverage => {\n const trace = toolTrace(input.events);\n const coverage =\n input.shape === \"fan-out\"\n ? fanOutCoverage(input.files, input.totalFiles, trace)\n : flatCoverage(input.files, input.totalFiles, trace);\n if (input.anchorFiles.length >= input.totalAnchorFiles) return coverage;\n return ReviewCoverage.make({\n ...coverage,\n status: \"incomplete\",\n reasons: [\n ...coverage.reasons,\n `full pull-request anchor surface exposed ${input.anchorFiles.length} of ${input.totalAnchorFiles} required files`,\n ],\n });\n};\n","import { Schema } from \"effect\";\n\n// ---------------------------------------------------------------------------\n// Reasoning effort, stored as a POSITION on [0, 1] rather than a rung name.\n// A rung name is only meaningful inside the provider that published it: the\n// same word can be one provider's floor and another's midpoint, and a stored\n// name silently changes meaning when the model under the setting changes. A\n// position has no such problem: 0 is whatever the provider calls its cheapest\n// offered rung and 1 its most expensive, and resolution is a lookup into that\n// provider's own ladder — the result is always a rung the provider offers.\n// ---------------------------------------------------------------------------\n\n/** A point on the effort axis: 0 = cheapest offered rung, 1 = most expensive. */\nexport type EffortPosition = number;\n\n/**\n * Names accepted on user-facing surfaces (the action input, the CLI flag),\n * mapped to fixed points on the axis. These same names anchor every offered\n * rung during resolution, so a named input always lands on its same-named\n * rung when the provider offers it — `high` never resolves to `medium` just\n * because a ladder is short.\n */\nexport const EFFORT_ALIASES = {\n low: 0,\n medium: 0.25,\n high: 0.5,\n xhigh: 0.75,\n max: 1,\n} as const satisfies Readonly<Record<string, EffortPosition>>;\n\n/** A rung name every provider ladder must draw from. */\nexport type EffortAliasName = keyof typeof EFFORT_ALIASES;\n\nconst aliasPosition: Readonly<Record<string, EffortPosition | undefined>> = EFFORT_ALIASES;\n\n/** An effort input that is neither a known name nor a number on [0, 1]. */\nexport class InvalidEffortInput extends Schema.TaggedError<InvalidEffortInput>()(\n \"InvalidEffortInput\",\n {\n input: Schema.String,\n },\n) {\n override get message() {\n return (\n `Invalid effort '${this.input}': expected one of ` +\n `${Object.keys(EFFORT_ALIASES).join(\", \")} or a number between 0 and 1.`\n );\n }\n}\n\nexport const isEffortPosition = (value: number): boolean =>\n Number.isFinite(value) && value >= 0 && value <= 1;\n\n/**\n * Parse a user-supplied effort into a position: a name (`high`) or a bare\n * number (`0.75`). Returns undefined for anything else so the caller can fail\n * typed — a typo must stay visible, never silently become a level.\n */\nexport const parseEffortPosition = (raw: string): EffortPosition | undefined => {\n const normalized = raw.trim().toLowerCase();\n const named = aliasPosition[normalized];\n if (named !== undefined) return named;\n if (normalized === \"\") return undefined;\n const numeric = Number(normalized);\n return isEffortPosition(numeric) ? numeric : undefined;\n};\n\n/**\n * Land a position on one provider's offered ladder: the highest offered rung\n * whose canonical alias position is at or below the requested position.\n * Anchoring on the alias positions (instead of scaling by ladder index) keeps\n * two properties at once: a named input lands on its same-named rung whenever\n * the provider offers it, and anything between rungs rounds DOWN so\n * resolution never costs more than was asked for.\n */\nexport const resolveEffortRung = <const Rung extends EffortAliasName>(\n position: EffortPosition,\n rungs: readonly [Rung, ...ReadonlyArray<Rung>],\n): Rung => {\n const clamped = Math.min(1, Math.max(0, position));\n let selected = rungs[0];\n for (const rung of rungs) {\n if (EFFORT_ALIASES[rung] <= clamped) selected = rung;\n }\n return selected;\n};\n","import { Effect, Layer } from \"effect\";\n\nimport { PullRequestMetadata, PullRequestSource, ReviewInputViolation } from \"./source.ts\";\n\n// ---------------------------------------------------------------------------\n// Configured ignore globs, applied at the source port. Ignored files are\n// removed from the reviewer's entire observation surface — the changeset\n// list, diffs, and head reads — so the model never spends budget on them and\n// can never anchor a finding to them. Filtering fails closed: reading an\n// ignored path is a ReviewInputViolation, exactly like a path outside the\n// changeset.\n// ---------------------------------------------------------------------------\n\nconst REGEX_SPECIALS = /[.+^${}()|[\\]\\\\]/g;\n\n// Placeholders for the directory-crossing wildcard while single-segment\n// wildcards are rewritten; NUL/SOH cannot appear in a valid repository path.\nconst CROSSING_SLASH = \"\\u0000\";\nconst CROSSING = \"\\u0001\";\n\n/**\n * The supported glob vocabulary is deliberately minimal: `**` crosses\n * directory separators, `*` and `?` stay within one path segment, everything\n * else is literal. Every string compiles — there is no invalid pattern.\n */\nconst globToRegExpSource = (pattern: string): string =>\n pattern\n .replace(REGEX_SPECIALS, String.raw`\\$&`)\n .replaceAll(\"**/\", CROSSING_SLASH)\n .replaceAll(\"**\", CROSSING)\n .replaceAll(\"*\", \"[^/]*\")\n .replaceAll(\"?\", \"[^/]\")\n .replaceAll(CROSSING_SLASH, \"(?:.*/)?\")\n .replaceAll(CROSSING, \".*\");\n\n/** Compile ignore globs into one predicate over repository-relative paths. */\nexport const compileIgnoreGlobs = (\n patterns: ReadonlyArray<string>,\n): ((path: string) => boolean) => {\n if (patterns.length === 0) return () => false;\n const expressions = patterns.map((pattern) => new RegExp(`^(?:${globToRegExpSource(pattern)})$`));\n return (path) => expressions.some((expression) => expression.test(path));\n};\n\n/**\n * Decorate the ambient PullRequestSource with configured ignore globs. The\n * resulting Layer requires the undecorated source, so callers provide their\n * real adapter beneath it. Metadata's changed-file total is reduced by the\n * ignored count: from the reviewer's perspective the ignored files do not\n * exist, and truncation reporting stays about the reviewer's own bound.\n */\nexport const ignoringPullRequestSourceLayer = (\n patterns: ReadonlyArray<string>,\n): Layer.Layer<PullRequestSource, never, PullRequestSource> =>\n Layer.effect(PullRequestSource)(\n Effect.gen(function* () {\n const source = yield* PullRequestSource;\n const ignored = compileIgnoreGlobs(patterns);\n const changedFiles = source.changedFiles.pipe(\n Effect.map((files) => files.filter((file) => !ignored(file.path))),\n );\n const anchorFiles = source.anchorFiles.pipe(\n Effect.map((files) => files.filter((file) => !ignored(file.path))),\n );\n const metadata = Effect.gen(function* () {\n const [meta, files] = yield* Effect.all([source.metadata, source.anchorFiles]);\n const ignoredCount = files.filter((file) => ignored(file.path)).length;\n return PullRequestMetadata.make({\n ...meta,\n totalChangedFiles: Math.max(0, meta.totalChangedFiles - ignoredCount),\n });\n });\n return PullRequestSource.of({\n metadata,\n changedFiles,\n anchorFiles,\n readFile: (path) =>\n ignored(path)\n ? Effect.fail(\n ReviewInputViolation.make({\n input: path,\n reason: \"Path is excluded from this review by configuration.\",\n }),\n )\n : source.readFile(path),\n });\n }),\n );\n","import { Schema } from \"effect\";\n\nimport type { ReviewCoverage } from \"./coverage.ts\";\nimport { commentableLines, type ChangedFile } from \"./diff.ts\";\nimport { renderFingerprintMarker } from \"./fingerprint.ts\";\nimport { ReviewFinding, type CodeReview, type ReviewConcern } from \"./review-agent.ts\";\nimport type { ReviewScopeMode, ReviewStateMarker } from \"./review-state.ts\";\n\n// ---------------------------------------------------------------------------\n// Publication planning: pure, deterministic, and fail-closed. Model output is\n// untrusted input, so every finding anchor is validated against the parsed\n// diff before it may become an inline comment; findings that fail validation\n// are demoted into the review body instead of being dropped or trusted. This\n// module is deliberately not configurable — customization widens what goes\n// into a review, never what leaves it unvalidated.\n// ---------------------------------------------------------------------------\n\nexport const ReviewEvent = Schema.Literals([\"COMMENT\", \"APPROVE\", \"REQUEST_CHANGES\"]);\nexport type ReviewEvent = typeof ReviewEvent.Type;\n\n/** One inline comment exactly as the GitHub review API accepts it. */\nexport class ReviewCommentDraft extends Schema.Class<ReviewCommentDraft>(\n \"@effect-agent/pr-review/ReviewCommentDraft\",\n)({\n path: Schema.NonEmptyString,\n /** The last (or only) commented line, RIGHT side of the diff. */\n line: Schema.Int.check(Schema.isGreaterThan(0)),\n /** Present only for multi-line comments; strictly less than `line`. */\n startLine: Schema.optionalKey(Schema.Int.check(Schema.isGreaterThan(0))),\n body: Schema.NonEmptyString,\n}) {}\n\n/** The complete, validated review ready for one GitHub reviews API call. */\nexport class ReviewPublicationPlan extends Schema.Class<ReviewPublicationPlan>(\n \"@effect-agent/pr-review/ReviewPublicationPlan\",\n)({\n event: ReviewEvent,\n body: Schema.String.check(Schema.isMaxLength(60_000)),\n comments: Schema.Array(ReviewCommentDraft),\n /** Findings whose anchors failed diff validation; folded into `body`. */\n demoted: Schema.Array(ReviewFinding),\n /** The head commit the diffs were fetched at; pins the posted review. */\n commitSha: Schema.NonEmptyString.check(Schema.isMaxLength(64)),\n}) {}\n\nconst severityEmoji: Record<ReviewFinding[\"severity\"], string> = {\n blocking: \"🛑\",\n important: \"⚠️\",\n nit: \"💅\",\n};\n\nconst severityRank: Record<ReviewFinding[\"severity\"], number> = {\n blocking: 0,\n important: 1,\n nit: 2,\n};\n\nconst severityLabel: Record<ReviewFinding[\"severity\"], string> = {\n blocking: `${severityEmoji.blocking} blocking`,\n important: `${severityEmoji.important} important`,\n nit: `${severityEmoji.nit} nit`,\n};\n\n/** A fence long enough that the suggestion content can never close it early. */\nconst suggestionFence = (suggestion: string): string => {\n let fence = \"```\";\n while (suggestion.includes(fence)) fence = `${fence}\\``;\n return fence;\n};\n\nconst renderCommentBody = (finding: ReviewFinding): string => {\n const parts = [`**[${severityLabel[finding.severity]}] ${finding.title}**`, \"\", finding.body];\n if (finding.suggestion !== undefined) {\n const fence = suggestionFence(finding.suggestion);\n parts.push(\"\", `${fence}suggestion`, finding.suggestion, fence);\n }\n return parts.join(\"\\n\");\n};\n\nconst renderDemoted = (finding: ReviewFinding, reason: string): string => {\n const location = `\\`${finding.path}:${finding.startLine}${\n finding.endLine !== finding.startLine ? `-${finding.endLine}` : \"\"\n }\\``;\n return `- ${location} **[${severityLabel[finding.severity]}] ${finding.title}** — ${finding.body} _(demoted: ${reason})_`;\n};\n\nconst countNoun = (count: number, noun: string): string =>\n `${count} ${noun}${count === 1 ? \"\" : \"s\"}`;\n\n/** The validated finding + concern severities, tallied for callout and event. */\nconst severityCounts = (\n review: CodeReview,\n carriedFindings: ReadonlyArray<ReviewFinding> = [],\n carriedConcerns: ReadonlyArray<ReviewConcern> = [],\n) => {\n const severities = [\n ...review.findings.map((finding) => finding.severity),\n ...(review.concerns ?? []).map((concern) => concern.severity),\n ...carriedFindings.map((finding) => finding.severity),\n ...carriedConcerns.map((concern) => concern.severity),\n ];\n return {\n blocking: severities.filter((severity) => severity === \"blocking\").length,\n important: severities.filter((severity) => severity === \"important\").length,\n total: severities.length,\n };\n};\n\n/**\n * The opening callout: the review's overall tier, derived HOST-SIDE from the\n * validated severities (never from model prose), described by what GitHub\n * renders it as. `[!CAUTION]` is a red banner, `[!IMPORTANT]` a purple one;\n * the blockquote tiers read as informational.\n */\nconst renderVerdictCallout = (\n review: CodeReview,\n options: {\n readonly carriedFindings?: ReadonlyArray<ReviewFinding> | undefined;\n readonly carriedConcerns?: ReadonlyArray<ReviewConcern> | undefined;\n readonly coverage?: ReviewCoverage | undefined;\n },\n): string => {\n const counts = severityCounts(review, options.carriedFindings, options.carriedConcerns);\n if (options.coverage?.status === \"incomplete\") {\n const suffix =\n counts.blocking > 0 ? ` It also has ${countNoun(counts.blocking, \"blocking finding\")}.` : \"\";\n return `> [!CAUTION]\\n> Review coverage is incomplete — the check must not pass.${suffix}`;\n }\n if (counts.blocking > 0) {\n return `> [!CAUTION]\\n> ${countNoun(counts.blocking, \"blocking finding\")} — do not merge before addressing ${counts.blocking === 1 ? \"it\" : \"them\"}.`;\n }\n if (counts.important > 0) {\n return `> [!IMPORTANT]\\n> ${countNoun(counts.important, \"important finding\")} to address before merging.`;\n }\n if (counts.total > 0) {\n return \"> ℹ️ Minor suggestions only — mergeable as-is.\";\n }\n return review.verdict === \"approve\"\n ? \"> ✅ No issues found.\"\n : \"> ℹ️ No findings — see the summary.\";\n};\n\nconst renderConcern = (concern: ReviewConcern): string =>\n [`### ${severityEmoji[concern.severity]} ${concern.title}`, \"\", concern.body].join(\"\\n\");\n\nconst renderCarriedFinding = (finding: ReviewFinding): string =>\n `- \\`${finding.path}:${finding.startLine}${finding.endLine === finding.startLine ? \"\" : `-${finding.endLine}`}\\` **[${severityLabel[finding.severity]}] ${finding.title}** — ${finding.body}`;\n\n/** HTML comments must not contain `--`; interpolated values are sanitized. */\nconst commentSafe = (value: string): string => value.replaceAll(\"--\", \"- -\");\n\n/**\n * The invisible staleness note addressed to whoever reads the review later —\n * a human or a downstream agent: which commit the findings were written\n * against, and that line callouts age the moment new commits land.\n */\nconst renderReviewMetadata = (options: {\n readonly headSha: string;\n readonly baseRef?: string | undefined;\n readonly headRef?: string | undefined;\n readonly filesVisible: number;\n readonly totalChangedFiles: number;\n readonly reviewMode?: ReviewScopeMode | undefined;\n readonly baselineSha?: string | undefined;\n}): string =>\n [\n \"<!-- effect-agent-pr-review metadata\",\n `reviewed-head: ${commentSafe(options.headSha)}`,\n ...(options.baseRef !== undefined && options.headRef !== undefined\n ? [`base-ref: ${commentSafe(options.baseRef)}`, `head-ref: ${commentSafe(options.headRef)}`]\n : []),\n // The observation surface, not a coverage claim: the host cannot know\n // which visible files the model actually examined, and the summary is\n // where unreviewed units are named.\n `files-visible: ${options.filesVisible} of ${options.totalChangedFiles}`,\n ...(options.reviewMode === undefined ? [] : [`review-mode: ${options.reviewMode}`]),\n ...(options.baselineSha === undefined\n ? []\n : [`incremental-baseline: ${commentSafe(options.baselineSha)}`]),\n \"Findings were written against the head commit above; if commits have landed\",\n \"since, treat file and line callouts as potentially stale and re-diff first.\",\n \"-->\",\n ].join(\"\\n\");\n\n/**\n * Why one finding cannot become an inline comment, or undefined when it can.\n * Exported so tests can pin each rule individually.\n */\nexport const anchorViolation = (\n finding: ReviewFinding,\n files: ReadonlyArray<ChangedFile>,\n): string | undefined => {\n const file = files.find((candidate) => candidate.path === finding.path);\n if (file === undefined) return \"path is not part of the changeset\";\n if (file.patch === undefined) return \"file has no textual diff\";\n if (finding.endLine < finding.startLine) return \"endLine precedes startLine\";\n if (finding.endLine - finding.startLine + 1 > 100) return \"range is implausibly large\";\n const anchors = commentableLines(file.patch);\n for (let line = finding.startLine; line <= finding.endLine; line += 1) {\n if (!anchors.has(line)) return `line ${line} is not part of the diff`;\n }\n return undefined;\n};\n\n/**\n * Turn one validated review into the exact GitHub publication payload.\n * `applyVerdict: false` (the safe default) always posts a COMMENT review;\n * `true` maps the model's verdict onto APPROVE / REQUEST_CHANGES.\n */\nexport const planPublication = (\n review: CodeReview,\n files: ReadonlyArray<ChangedFile>,\n options: {\n readonly applyVerdict: boolean;\n /** Head commit the changeset was fetched at (pins the posted review). */\n readonly headSha: string;\n /** GitHub's changed-file total, for honest truncation reporting. */\n readonly totalChangedFiles: number;\n /** Base/head refs for the staleness metadata comment. */\n readonly baseRef?: string | undefined;\n readonly headRef?: string | undefined;\n /** Provider binding descriptor rendered into the footer. */\n readonly modelLabel?: string | undefined;\n /** Workflow-run URL rendered into the footer. */\n readonly runUrl?: string | undefined;\n /** Observed run usage rendered into the footer. */\n readonly usage?: { readonly inputTokens: number; readonly outputTokens: number } | undefined;\n /** What the usage observed: the whole run, or the coordinator only. */\n readonly usageScope?: \"run\" | \"coordinator\" | undefined;\n /**\n * Changeset fingerprint embedded invisibly in the review body so a later\n * run can skip re-reviewing an unchanged changeset.\n */\n readonly fingerprint?: string | undefined;\n /** Host-owned coverage; incomplete coverage is rendered and fails the check. */\n readonly coverage?: ReviewCoverage | undefined;\n /** Unchanged unresolved items carried from the prior successfully reviewed head. */\n readonly carriedFindings?: ReadonlyArray<ReviewFinding> | undefined;\n readonly carriedConcerns?: ReadonlyArray<ReviewConcern> | undefined;\n /** Selected review scope, made visible whenever orchestration chose it. */\n readonly reviewMode?: ReviewScopeMode | undefined;\n readonly reviewReason?: string | undefined;\n readonly baselineSha?: string | undefined;\n readonly reviewFilesVisible?: number | undefined;\n readonly reviewTotalFiles?: number | undefined;\n /** Authenticated continuity state is emitted only after complete host-owned coverage. */\n readonly stateMarker?: ReviewStateMarker | undefined;\n /** Visible reason continuity state was omitted; the next run will review fully. */\n readonly stateNotice?: string | undefined;\n },\n): ReviewPublicationPlan => {\n const comments: Array<ReviewCommentDraft> = [];\n const demoted: Array<{ readonly finding: ReviewFinding; readonly reason: string }> = [];\n for (const finding of review.findings) {\n const violation = anchorViolation(finding, files);\n if (violation === undefined) {\n comments.push(\n ReviewCommentDraft.make({\n path: finding.path,\n line: finding.endLine,\n ...(finding.endLine > finding.startLine ? { startLine: finding.startLine } : {}),\n body: renderCommentBody(finding),\n }),\n );\n } else {\n demoted.push({ finding, reason: violation });\n }\n }\n\n // Rendered most-severe first so the size cap below sheds the least severe.\n const sortedConcerns = [...(review.concerns ?? [])].sort(\n (a, b) => severityRank[a.severity] - severityRank[b.severity],\n );\n const sortedDemoted = [...demoted].sort(\n (a, b) => severityRank[a.finding.severity] - severityRank[b.finding.severity],\n );\n\n const footerParts = [\"Automated review by @effect-agent/pr-review\"];\n if (options.modelLabel !== undefined) footerParts.push(options.modelLabel);\n // Usage renders only under an EXPLICIT scope: this planner cannot know\n // whether a budget snapshot observed the whole run or only a fan-out\n // coordinator, and omitting the number is honest where mislabeling is not.\n if (options.usage !== undefined && options.usageScope !== undefined) {\n const scope = options.usageScope === \"coordinator\" ? \" (coordinator)\" : \"\";\n footerParts.push(\n `${options.usage.inputTokens} in / ${options.usage.outputTokens} out tokens${scope}`,\n );\n }\n if (options.runUrl !== undefined) footerParts.push(`[run](${options.runUrl})`);\n footerParts.push(`reviewed at ${options.headSha.slice(0, 7)}`);\n const footer = `_${footerParts.join(\" · \")}._`;\n\n const renderHead = (concernsKept: number, demotedKept: number, omitted: number): string => {\n const carriedFindings = options.carriedFindings ?? [];\n const carriedConcerns = options.carriedConcerns ?? [];\n const parts = [\n renderVerdictCallout(review, {\n carriedFindings,\n carriedConcerns,\n coverage: options.coverage,\n }),\n ];\n if (options.reviewMode !== undefined && options.reviewReason !== undefined) {\n parts.push(\n \"\",\n options.reviewMode === \"incremental\"\n ? `**Incremental scope:** reviewed ${options.reviewFilesVisible ?? files.length} file(s) ${options.reviewReason}. Unchanged accepted scope was preserved and not reopened.`\n : `**Full-diff scope:** ${options.reviewReason}.`,\n );\n }\n if (options.stateNotice !== undefined) {\n parts.push(\n \"\",\n `⚠️ Continuity state was not stored (${options.stateNotice.slice(0, 1_000)}); the next run will safely review the full diff.`,\n );\n }\n parts.push(\"\", review.summary);\n if (options.coverage?.status === \"incomplete\") {\n parts.push(\n \"\",\n \"### 🛑 Incomplete coverage\",\n \"\",\n ...options.coverage.reasons.map((reason) => `- ${reason}`),\n );\n }\n if (carriedFindings.length > 0) {\n parts.push(\n \"\",\n \"### Unresolved findings carried from unchanged scope\",\n \"\",\n ...carriedFindings.map(renderCarriedFinding),\n );\n }\n if (carriedConcerns.length > 0) {\n parts.push(\"\", \"### Unresolved concerns carried to the final audit\");\n for (const concern of carriedConcerns) parts.push(\"\", renderConcern(concern));\n }\n for (const concern of sortedConcerns.slice(0, concernsKept)) {\n parts.push(\"\", renderConcern(concern));\n }\n if (files.length < options.totalChangedFiles) {\n parts.push(\n \"\",\n `⚠️ Reviewed ${files.length} of ${options.totalChangedFiles} changed files — the changeset exceeded the reviewer's file bound.`,\n );\n }\n if (demotedKept > 0) {\n parts.push(\n \"\",\n \"### Findings without a valid diff anchor\",\n ...sortedDemoted\n .slice(0, demotedKept)\n .map(({ finding, reason }) => renderDemoted(finding, reason)),\n );\n }\n if (omitted > 0) {\n parts.push(\n \"\",\n `⚠️ ${countNoun(omitted, \"review item\")} omitted — the body exceeded GitHub's review size cap.`,\n );\n }\n parts.push(\"\", footer);\n return parts.join(\"\\n\");\n };\n\n // The model's verdict may not contradict the reported severities (model\n // output is untrusted input): any blocking item forces REQUEST_CHANGES, a\n // review with no blocking item can never REQUEST_CHANGES, and an approval\n // is honored only when nothing blocking or important was reported — the\n // event always agrees with the callout tier. Demoted findings and concerns\n // count like anchored findings: anchor validation validates LOCATIONS, not\n // truth, so severity is equally model-claimed for all three, and counting\n // them only ever moves the event toward the closed direction.\n const counts = severityCounts(\n review,\n options.carriedFindings ?? [],\n options.carriedConcerns ?? [],\n );\n const event: ReviewEvent = !options.applyVerdict\n ? \"COMMENT\"\n : options.coverage?.status === \"incomplete\" || counts.blocking > 0\n ? \"REQUEST_CHANGES\"\n : review.verdict === \"approve\" && counts.important === 0\n ? \"APPROVE\"\n : \"COMMENT\";\n\n // The invisible tail (metadata + fingerprint marker) must survive the body\n // cap, so the cap reserves exactly the room it needs.\n const tail = [\n renderReviewMetadata({\n headSha: options.headSha,\n baseRef: options.baseRef,\n headRef: options.headRef,\n filesVisible: options.reviewFilesVisible ?? files.length,\n totalChangedFiles: options.reviewTotalFiles ?? options.totalChangedFiles,\n reviewMode: options.reviewMode,\n baselineSha: options.baselineSha,\n }),\n ...(options.fingerprint === undefined ? [] : [renderFingerprintMarker(options.fingerprint)]),\n ...(options.stateMarker === undefined ? [] : [options.stateMarker]),\n ].join(\"\\n\");\n const headBudget = 60_000 - tail.length - 1;\n\n // Shed whole trailing items — demoted bullets first (they already failed\n // validation), then concerns — instead of slicing markdown mid-block. Every\n // omission is announced, and `plan.demoted` keeps the full data regardless.\n let concernsKept = sortedConcerns.length;\n let demotedKept = sortedDemoted.length;\n let omitted = 0;\n let head = renderHead(concernsKept, demotedKept, omitted);\n while (head.length > headBudget && (demotedKept > 0 || concernsKept > 0)) {\n if (demotedKept > 0) demotedKept -= 1;\n else concernsKept -= 1;\n omitted += 1;\n head = renderHead(concernsKept, demotedKept, omitted);\n }\n // Last resort for a pathological summary; unreachable while the CodeReview\n // schema caps the summary well below the budget.\n const body = `${head.slice(0, headBudget)}\\n${tail}`;\n\n return ReviewPublicationPlan.make({\n event,\n body,\n comments,\n demoted: demoted.map(({ finding }) => finding),\n commitSha: options.headSha,\n });\n};\n","import { Effect, Option, Schema } from \"effect\";\nimport {\n makeUsageBudget,\n toRunBudgetHook,\n UsageBudgetLimits,\n UsageTotals,\n AgentRuntime,\n type RuntimeBinding,\n} from \"effect-agent\";\nimport { type Tool } from \"effect/unstable/ai\";\n\nimport { assessReviewCoverage, ReviewCoverage, type ReviewShape } from \"./coverage.ts\";\nimport type { ChangedFile } from \"./diff.ts\";\nimport { computeChangesetFingerprint } from \"./fingerprint.ts\";\nimport { PublishedReview, ReviewPublisher } from \"./github.ts\";\nimport { planPublication, ReviewPublicationPlan } from \"./render.ts\";\nimport {\n clampMaxFindings,\n CodeReview,\n ReviewConcern,\n ReviewFinding,\n ReviewMission,\n} from \"./review-agent.ts\";\nimport {\n fromStoredConcern,\n fromStoredFinding,\n ReviewExecutionContext,\n ReviewState,\n toStoredConcern,\n toStoredFinding,\n} from \"./review-state.ts\";\nimport { rankAndDedupeFindings } from \"./review-units.ts\";\nimport { PullRequestSource, type PullRequestMetadata } from \"./source.ts\";\n\n// ---------------------------------------------------------------------------\n// One review run, end to end: read the pull request, run the bounded agent,\n// validate the review against the real diff, then (optionally) publish.\n// Publication happens strictly AFTER the agent loop so no model turn can\n// observe or influence the mutation, and a failed run publishes nothing.\n// ---------------------------------------------------------------------------\n\n/**\n * Run-level usage bounds on top of the definition's AgentPolicy. Real diffs\n * are token-heavy, so the input budget is research-sized with cost as the\n * safety net.\n */\nexport const reviewBudgetLimits = UsageBudgetLimits.make({\n maxInputTokens: 400_000,\n maxOutputTokens: 16_000,\n maxToolCalls: 24,\n maxCostMicrousd: 2_000_000,\n maxDurationMillis: 480_000,\n});\n\n/**\n * Run-level bounds for the fan-out coordinator. This budget observes only\n * the COORDINATOR'S own usage — delegated children are bounded separately by\n * the delegation's `SubagentPolicy` reservation and the child definition's\n * own `AgentPolicy`, never silently by the parent's budget. The duration\n * ceiling is wider because delegation Tool Calls hold the parent turn open\n * while bounded children run.\n */\nexport const fanOutReviewBudgetLimits = UsageBudgetLimits.make({\n maxInputTokens: 400_000,\n maxOutputTokens: 16_000,\n maxToolCalls: 24,\n maxCostMicrousd: 2_000_000,\n maxDurationMillis: 900_000,\n});\n\n/** Everything one review run produced, publication receipt included. */\nexport class ReviewRunOutcome extends Schema.Class<ReviewRunOutcome>(\n \"@effect-agent/pr-review/ReviewRunOutcome\",\n)({\n review: CodeReview,\n /** All currently unresolved findings, including unchanged carried scope. */\n activeFindings: Schema.Array(ReviewFinding).check(Schema.isMaxLength(20)),\n /** All currently unresolved concerns, including concerns carried to final audit. */\n activeConcerns: Schema.Array(ReviewConcern).check(Schema.isMaxLength(10)),\n /** Host-owned structural coverage used by the Actions check conclusion. */\n coverage: ReviewCoverage,\n plan: ReviewPublicationPlan,\n published: Schema.optionalKey(PublishedReview),\n turns: Schema.Int.check(Schema.isGreaterThan(0)),\n /**\n * The run budget's observed usage. For the fan-out reviewer this observes\n * the COORDINATOR only — delegated children are bounded and accounted\n * separately by their reservations.\n */\n usage: Schema.optionalKey(UsageTotals),\n /**\n * What `usage` observed: the whole run, or a fan-out coordinator only.\n * Absent when the caller declared no scope — consumers must not present\n * unscoped usage as whole-run totals.\n */\n usageScope: Schema.optionalKey(Schema.Literals([\"run\", \"coordinator\"])),\n reviewMode: Schema.optionalKey(Schema.Literals([\"incremental\", \"full\"])),\n reviewReason: Schema.optionalKey(Schema.String.check(Schema.isMaxLength(1_000))),\n state: Schema.optionalKey(ReviewState),\n}) {}\n\nexport interface ExecuteReviewOptions {\n /** Post the review to GitHub; `false` stops after planning (dry run). */\n readonly post: boolean;\n /** Map the model's verdict onto APPROVE/REQUEST_CHANGES instead of COMMENT. */\n readonly applyVerdict: boolean;\n /** Run-level usage bounds; defaults to `reviewBudgetLimits`. */\n readonly limits?: UsageBudgetLimits | undefined;\n /**\n * Host-side findings bound (fail-closed backstop for the instruction-level\n * bound): a review carrying more findings is ranked by severity, deduped by\n * anchor, and trimmed — never published oversized. Clamped to the schema cap.\n */\n readonly maxFindings?: number | undefined;\n /**\n * Prompt signature for changeset fingerprinting. When present, the\n * changeset fingerprint is computed and embedded invisibly in the review\n * body so later runs can skip an unchanged changeset.\n */\n readonly signature?: ((mission: ReviewMission) => string) | undefined;\n /** Provider binding descriptor rendered into the review footer. */\n readonly modelLabel?: string | undefined;\n /** Workflow-run URL rendered into the review footer. */\n readonly runUrl?: string | undefined;\n /**\n * What the run budget observes: the whole run, or a fan-out coordinator\n * only. Without a declared scope the footer omits usage entirely — this\n * generic path cannot know what a caller's binding shape observes, and an\n * unlabeled number would read as whole-run totals.\n */\n readonly usageScope?: \"run\" | \"coordinator\" | undefined;\n /** Host-owned coverage shape; defaults to the flat reviewer. */\n readonly reviewShape?: ReviewShape | undefined;\n}\n\n/** Build the mission one review run frames from the source's snapshot. */\nexport const buildReviewMission = (\n metadata: PullRequestMetadata,\n files: ReadonlyArray<ChangedFile>,\n): ReviewMission =>\n ReviewMission.make({\n repository: metadata.repository,\n number: metadata.number,\n title: metadata.title,\n body: metadata.body,\n baseRef: metadata.baseRef,\n headRef: metadata.headRef,\n changedFileCount: files.length,\n });\n\n/** Enforce the configured findings bound on an already-validated review. */\nexport const enforceFindingsBound = (review: CodeReview, maxFindings: number): CodeReview =>\n review.findings.length <= maxFindings\n ? review\n : CodeReview.make({\n summary: review.summary,\n verdict: review.verdict,\n findings: rankAndDedupeFindings(review.findings).slice(0, maxFindings),\n ...(review.concerns !== undefined ? { concerns: review.concerns } : {}),\n });\n\nconst findingKey = (finding: ReviewFinding): string =>\n `${finding.path}\\u0000${finding.startLine}\\u0000${finding.endLine}\\u0000${finding.severity}\\u0000${finding.title}`;\n\nconst severityRank: Record<ReviewConcern[\"severity\"], number> = {\n blocking: 0,\n important: 1,\n nit: 2,\n};\n\nconst rankAndDedupeConcerns = (\n concerns: ReadonlyArray<ReviewConcern>,\n): ReadonlyArray<ReviewConcern> => {\n const byContent = new Map<string, ReviewConcern>();\n for (const concern of concerns) {\n const key = `${concern.title}\\u0000${concern.body}`;\n const previous = byContent.get(key);\n if (\n previous === undefined ||\n severityRank[concern.severity] < severityRank[previous.severity]\n ) {\n byContent.set(key, concern);\n }\n }\n return [...byContent.values()]\n .sort((left, right) => severityRank[left.severity] - severityRank[right.severity])\n .slice(0, 10);\n};\n\n/**\n * Execute one review with any explicit Agent Binding whose contract is\n * `ReviewMission -> CodeReview` — the flat reviewer or the fan-out\n * coordinator; the toolkit stays generic because publication only depends on\n * the shared output contract. The binding stays a parameter (D-027): tests\n * pass scripted models, hosts pass live provider bindings, and the model\n * Layer's requirements stay visible in this Effect's `R`.\n */\nexport const executeReview = <\n Instructions,\n Tools extends Record<string, Tool.Any>,\n Provider,\n ModelProvides,\n ModelRequires,\n>(\n binding: RuntimeBinding<\n typeof ReviewMission,\n typeof CodeReview,\n Instructions,\n Tools,\n Provider,\n ModelProvides,\n ModelRequires\n >,\n options: ExecuteReviewOptions,\n) =>\n Effect.gen(function* () {\n const source = yield* PullRequestSource;\n const metadata = yield* source.metadata;\n const files = yield* source.changedFiles;\n const anchorFiles = yield* source.anchorFiles;\n const executionContext = Option.getOrUndefined(\n yield* Effect.serviceOption(ReviewExecutionContext),\n );\n const mission = buildReviewMission(metadata, files);\n const fullMission = buildReviewMission(metadata, anchorFiles);\n const fingerprint =\n options.signature === undefined\n ? undefined\n : yield* computeChangesetFingerprint(anchorFiles, options.signature(fullMission));\n\n const budget = yield* makeUsageBudget(options.limits ?? reviewBudgetLimits);\n const detached = yield* AgentRuntime.start(binding, mission, {\n budget: toRunBudgetHook(budget),\n estimateCostMicrousd: () => Effect.succeed(500),\n });\n const result = yield* detached.await;\n const events = yield* detached.events;\n\n // The engine validated the terminal JSON against the output schema; this\n // decode recovers the typed value on this side of the generic boundary.\n const decoded = yield* Schema.decodeUnknownEffect(CodeReview)(result.output);\n const review = enforceFindingsBound(decoded, clampMaxFindings(options.maxFindings));\n const usage = yield* budget.snapshot;\n const affectedPaths = new Set(\n executionContext?.affectedPaths ??\n files.flatMap((file) =>\n file.previousPath === undefined ? [file.path] : [file.path, file.previousPath],\n ),\n );\n const priorState =\n executionContext?.mode === \"incremental\" ? executionContext.priorState : undefined;\n const carriedCandidates =\n priorState?.unresolvedFindings\n .filter((finding) => !affectedPaths.has(finding.path))\n .map(fromStoredFinding) ?? [];\n const activeFindings = rankAndDedupeFindings([...carriedCandidates, ...review.findings]).slice(\n 0,\n clampMaxFindings(options.maxFindings),\n );\n const activeFindingKeys = new Set(activeFindings.map(findingKey));\n const currentFindingKeys = new Set(review.findings.map(findingKey));\n const carriedFindings = carriedCandidates.filter(\n (finding) =>\n activeFindingKeys.has(findingKey(finding)) && !currentFindingKeys.has(findingKey(finding)),\n );\n // Non-anchored concerns cannot be mapped safely to one affected path, so\n // incremental runs carry them conservatively until the explicit final audit.\n const carriedConcernCandidates = priorState?.unresolvedConcerns.map(fromStoredConcern) ?? [];\n const activeConcerns = rankAndDedupeConcerns([\n ...carriedConcernCandidates,\n ...(review.concerns ?? []),\n ]);\n const currentConcernKeys = new Set(\n (review.concerns ?? []).map((concern) => `${concern.title}\\u0000${concern.body}`),\n );\n const activeConcernKeys = new Set(\n activeConcerns.map((concern) => `${concern.title}\\u0000${concern.body}`),\n );\n const carriedConcerns = carriedConcernCandidates.filter((concern) => {\n const key = `${concern.title}\\u0000${concern.body}`;\n return activeConcernKeys.has(key) && !currentConcernKeys.has(key);\n });\n const reviewTotalFiles = executionContext?.totalFiles ?? metadata.totalChangedFiles;\n const coverage = assessReviewCoverage({\n shape: options.reviewShape ?? \"flat\",\n files,\n totalFiles: reviewTotalFiles,\n anchorFiles,\n totalAnchorFiles: metadata.totalChangedFiles,\n events,\n });\n const stateCandidate =\n executionContext !== undefined &&\n coverage.status === \"complete\" &&\n fingerprint !== undefined &&\n metadata.baseSha !== undefined &&\n executionContext.stateAuthenticator?.status === \"available\"\n ? ReviewState.make({\n version: 1,\n repository: metadata.repository,\n pullRequestNumber: metadata.number,\n baseRef: metadata.baseRef,\n baseSha: metadata.baseSha,\n headRef: metadata.headRef,\n reviewedHeadSha: metadata.headSha,\n profileFingerprint: executionContext.profileFingerprint,\n acceptedScopeFingerprint: fingerprint,\n reviewedPathCount: anchorFiles.length,\n unresolvedFindings: activeFindings.map(toStoredFinding),\n unresolvedConcerns: activeConcerns.map(toStoredConcern),\n lastReviewMode: executionContext.mode,\n })\n : undefined;\n const continuity =\n stateCandidate === undefined || executionContext?.stateAuthenticator === undefined\n ? {\n state: undefined,\n marker: undefined,\n notice:\n executionContext?.stateAuthenticator?.status === \"unavailable\" &&\n coverage.status === \"complete\"\n ? (executionContext.stateAuthenticator.unavailableReason ??\n \"authenticated continuity state is unavailable\")\n : undefined,\n }\n : yield* executionContext.stateAuthenticator.render(stateCandidate).pipe(\n Effect.match({\n onFailure: (error) => ({\n state: undefined,\n marker: undefined,\n notice:\n error._tag === \"ReviewStateMarkerTooLarge\"\n ? `authenticated continuity state exceeded its ${error.maximumChars}-character bound`\n : `authenticated continuity state could not be signed: ${error.reason}`,\n }),\n onSuccess: (marker) => ({ state: stateCandidate, marker, notice: undefined }),\n }),\n );\n const plan = planPublication(review, anchorFiles, {\n applyVerdict: options.applyVerdict,\n headSha: metadata.headSha,\n totalChangedFiles: metadata.totalChangedFiles,\n baseRef: metadata.baseRef,\n headRef: metadata.headRef,\n modelLabel: options.modelLabel,\n runUrl: options.runUrl,\n usage,\n usageScope: options.usageScope,\n fingerprint: coverage.status === \"complete\" ? fingerprint : undefined,\n coverage,\n carriedFindings,\n carriedConcerns,\n reviewMode: executionContext?.mode,\n reviewReason: executionContext?.reason,\n baselineSha: executionContext?.baselineSha,\n reviewFilesVisible: files.length,\n reviewTotalFiles,\n stateMarker: continuity.marker,\n stateNotice: continuity.notice,\n });\n\n const scope =\n options.usageScope === undefined ? {} : ({ usageScope: options.usageScope } as const);\n if (!options.post) {\n return ReviewRunOutcome.make({\n review,\n activeFindings,\n activeConcerns,\n coverage,\n plan,\n turns: result.turns,\n usage,\n ...scope,\n ...(executionContext === undefined\n ? {}\n : { reviewMode: executionContext.mode, reviewReason: executionContext.reason }),\n ...(continuity.state === undefined ? {} : { state: continuity.state }),\n });\n }\n const publisher = yield* ReviewPublisher;\n const published = yield* publisher.publish(plan);\n return ReviewRunOutcome.make({\n review,\n activeFindings,\n activeConcerns,\n coverage,\n plan,\n published,\n turns: result.turns,\n usage,\n ...scope,\n ...(executionContext === undefined\n ? {}\n : { reviewMode: executionContext.mode, reviewReason: executionContext.reason }),\n ...(continuity.state === undefined ? {} : { state: continuity.state }),\n });\n });\n","import { Effect, Layer } from \"effect\";\nimport {\n Agent,\n AgentPolicy,\n getToolExecutionClass,\n IdGenerator,\n SubagentReservationsMemoryLive,\n type AgentPolicyInput,\n type UsageBudgetLimits,\n} from \"effect-agent\";\nimport { Toolkit, type LanguageModel, type Model, type Tool } from \"effect/unstable/ai\";\n\nimport {\n fanOutHandlersLayerFor,\n FanOutCoordinatorToolkitLayer,\n FileReviewToolkitLayer,\n makeFanOutReviewSuite,\n} from \"./fan-out.ts\";\nimport { computeChangesetFingerprint } from \"./fingerprint.ts\";\nimport { compileIgnoreGlobs, ignoringPullRequestSourceLayer } from \"./ignore.ts\";\nimport {\n clampMaxFindings,\n CodeReview,\n defaultReviewPolicy,\n ListChangedFiles,\n makeReviewInstructions,\n ReadFile,\n ReadFileDiff,\n ReviewMission,\n ReviewToolkitLayer,\n resolveGuidance as resolveReviewGuidance,\n type ReviewGuidance,\n} from \"./review-agent.ts\";\nimport { buildProfileMission, computeProfileFingerprint } from \"./review-state.ts\";\nimport {\n buildReviewMission,\n executeReview,\n fanOutReviewBudgetLimits,\n reviewBudgetLimits,\n} from \"./run.ts\";\nimport { PullRequestSource } from \"./source.ts\";\n\n// ---------------------------------------------------------------------------\n// The configuration factory: one call turns a Model and optional adaptation\n// knobs into a bound, runnable reviewer. Every knob widens what goes INTO the\n// review — guidance, extra read-only tools, execution bounds, ignore globs —\n// and none weakens what leaves it: anchor validation, the findings bound, and\n// publication-after-settlement are applied by the run path unconditionally.\n// ---------------------------------------------------------------------------\n\n/** Options shared by both reviewer shapes. */\nexport interface PrReviewSharedOptions {\n /**\n * Host-side and instruction-level findings bound, clamped to the CodeReview\n * schema cap of 20.\n */\n readonly maxFindings?: number | undefined;\n /**\n * Glob patterns (`**` crosses directories, `*`/`?` stay in one segment)\n * removed from the reviewer's observation surface entirely.\n */\n readonly ignore?: ReadonlyArray<string> | undefined;\n /** Map the model's verdict onto APPROVE/REQUEST_CHANGES instead of COMMENT. */\n readonly applyVerdict?: boolean | undefined;\n /** Run-level usage bounds; defaults to the shape's packaged limits. */\n readonly budget?: UsageBudgetLimits | undefined;\n /**\n * Human-readable descriptor of the bound model (provider, model id, effort)\n * rendered into the review footer and included in the fingerprint\n * signature, so changing the binding re-reviews instead of skipping.\n */\n readonly modelLabel?: string | undefined;\n}\n\n/** Options accepted by `PrReview.make` (the flat reviewer). */\nexport interface PrReviewOptions<\n Provider,\n ModelProvides,\n ModelRequires,\n Extra extends ReadonlyArray<Tool.Any>,\n> extends PrReviewSharedOptions {\n /** The Effect AI Model to bind; its Layer requirements stay visible in `R`. */\n readonly model: Model.Model<Provider, LanguageModel.LanguageModel | ModelProvides, ModelRequires>;\n /** Domain guidance injected between the mission framing and the procedure. */\n readonly guidance?: ReviewGuidance | undefined;\n /** Full override of the flat reviewer's execution bounds. */\n readonly policy?: AgentPolicyInput | undefined;\n /**\n * Additional tools merged into the reviewer's toolkit. Every extra tool\n * must be annotated `ToolExecutionClass: \"readonly\"` — construction fails\n * otherwise — and its handler Layer is the caller's to provide, so the new\n * dependency stays visible in the run's `R`.\n */\n readonly extraTools?: Extra | undefined;\n}\n\n/** How one run should publish. */\nexport interface RunReviewOptions {\n /** Post the review to GitHub; `false` (default) stops after planning. */\n readonly post?: boolean | undefined;\n /** Workflow-run URL rendered into the review footer. */\n readonly runUrl?: string | undefined;\n}\n\nconst EMPTY_TOOLS: ReadonlyArray<Tool.Any> = [];\n\nconst requireReadonly = (tools: ReadonlyArray<Tool.Any>): void => {\n for (const tool of tools) {\n const executionClass = getToolExecutionClass(tool);\n if (executionClass !== \"readonly\") {\n throw new Error(\n `PrReview.make: extra tool '${tool.name}' declares execution class '${executionClass}'. ` +\n `The packaged reviewer's tool surface is read-only; annotate the tool with ` +\n `ToolExecutionClass \"readonly\" or run it outside the reviewer.`,\n );\n }\n }\n};\n\nconst provideIgnore = <A, E, R>(\n effect: Effect.Effect<A, E, R>,\n ignore: ReadonlyArray<string> | undefined,\n) =>\n ignore !== undefined && ignore.length > 0\n ? effect.pipe(Effect.provide(ignoringPullRequestSourceLayer(ignore)))\n : effect;\n\n/**\n * The changeset fingerprint of what this reviewer WOULD review right now:\n * the ignore-filtered changeset hashed with the prompt signature. Identical\n * fingerprints mean an identical review input surface — the basis for\n * skipping re-reviews after content-free head changes (base auto-merges,\n * equivalent rebases).\n */\nconst makeFingerprint = (\n signature: (mission: ReturnType<typeof buildReviewMission>) => string,\n ignore: ReadonlyArray<string> | undefined,\n) =>\n provideIgnore(\n Effect.gen(function* () {\n const source = yield* PullRequestSource;\n const metadata = yield* source.metadata;\n const files = yield* source.changedFiles;\n return yield* computeChangesetFingerprint(\n files,\n signature(buildReviewMission(metadata, files)),\n );\n }),\n ignore,\n );\n\nconst makeProfileFingerprint = (\n signature: (mission: ReviewMission) => string,\n ignore: ReadonlyArray<string> | undefined,\n) =>\n provideIgnore(\n Effect.gen(function* () {\n const source = yield* PullRequestSource;\n const metadata = yield* source.metadata;\n const files = yield* source.anchorFiles;\n return yield* computeProfileFingerprint(signature(buildProfileMission(metadata, files)));\n }),\n ignore,\n );\n\nconst makeReviewSnapshot = (ignore: ReadonlyArray<string> | undefined) =>\n provideIgnore(\n Effect.gen(function* () {\n const source = yield* PullRequestSource;\n return {\n metadata: yield* source.metadata,\n files: yield* source.anchorFiles,\n };\n }),\n ignore,\n );\n\n/**\n * Build the flat reviewer: one bounded read-only agent over the whole\n * changeset. Returns the model-agnostic definition, the explicit binding, and\n * a `run` whose error and requirement channels stay fully inferred — the\n * pull-request source, the publisher, extra tool handlers, and the Model\n * Layer's requirements all remain visible to the caller.\n */\nconst make = <\n Provider,\n ModelProvides,\n ModelRequires,\n const Extra extends ReadonlyArray<Tool.Any> = readonly [],\n>(\n options: PrReviewOptions<Provider, ModelProvides, ModelRequires, Extra>,\n) => {\n // Safe when `extraTools` is omitted: the generic default fixes Extra to the\n // empty tuple, which is exactly what the fallback value is.\n const extraTools = options.extraTools ?? (EMPTY_TOOLS as Extra);\n requireReadonly(extraTools);\n\n const definition = Agent.define(\"pr-reviewer\", {\n input: ReviewMission,\n output: CodeReview,\n instructions: makeReviewInstructions({\n guidance: options.guidance,\n maxFindings: options.maxFindings,\n }),\n toolkit: Toolkit.make(ListChangedFiles, ReadFileDiff, ReadFile, ...extraTools),\n policy: options.policy === undefined ? defaultReviewPolicy : AgentPolicy.make(options.policy),\n description:\n \"Review one pull request read-only: list the changeset, read annotated diffs and head-file context, and return a structured, line-anchored code review.\",\n metadata: { deploymentClass: \"E\", surface: \"read-only\" },\n });\n // `Agent.withModel` types the model through a conditional that stays\n // deferred inside this generic body, so the binding is built structurally —\n // the identical frozen `{ definition, model }` pair the runtime accepts.\n const binding = Object.freeze({ definition, model: options.model });\n\n // Everything that shapes this reviewer's output: the rendered instructions\n // (mission, guidance, findings bound, contract) plus the verdict mapping.\n const signature = (mission: ReviewMission): string =>\n [\n definition.instructions(mission),\n `applyVerdict=${String(options.applyVerdict ?? false)}`,\n ...(options.modelLabel === undefined ? [] : [`model=${options.modelLabel}`]),\n ].join(\"\\u0000\");\n const profileSignature = (mission: ReviewMission): string =>\n [\n \"pr-review-profile-v1-flat\",\n JSON.stringify(resolveReviewGuidance(options.guidance, mission)),\n JSON.stringify(options.policy ?? {}),\n JSON.stringify(extraTools.map((tool) => tool.name)),\n JSON.stringify(options.ignore ?? []),\n `maxFindings=${clampMaxFindings(options.maxFindings)}`,\n `applyVerdict=${String(options.applyVerdict ?? false)}`,\n ...(options.modelLabel === undefined ? [] : [`model=${options.modelLabel}`]),\n ].join(\"\\u0000\");\n\n const run = (runOptions: RunReviewOptions = {}) =>\n provideIgnore(\n executeReview(binding, {\n post: runOptions.post ?? false,\n applyVerdict: options.applyVerdict ?? false,\n limits: options.budget ?? reviewBudgetLimits,\n maxFindings: clampMaxFindings(options.maxFindings),\n signature,\n modelLabel: options.modelLabel,\n runUrl: runOptions.runUrl,\n usageScope: \"run\",\n reviewShape: \"flat\",\n }).pipe(Effect.provide(Layer.mergeAll(ReviewToolkitLayer, IdGenerator.layer)), Effect.scoped),\n options.ignore,\n );\n\n return {\n definition,\n binding,\n run,\n fingerprint: makeFingerprint(signature, options.ignore),\n profileFingerprint: makeProfileFingerprint(profileSignature, options.ignore),\n snapshot: makeReviewSnapshot(options.ignore),\n filterFiles: (files: ReadonlyArray<import(\"./diff.ts\").ChangedFile>) => {\n const ignored = compileIgnoreGlobs(options.ignore ?? []);\n return files.filter((file) => !ignored(file.path));\n },\n } as const;\n};\n\n/** Options accepted by `PrReview.makeFanOut` (the delegating reviewer). */\nexport interface PrReviewFanOutOptions<\n Provider,\n ModelProvides,\n ModelRequires,\n> extends PrReviewSharedOptions {\n /** The Effect AI Model bound to both the coordinator and its children. */\n readonly model: Model.Model<Provider, LanguageModel.LanguageModel | ModelProvides, ModelRequires>;\n /**\n * Static guidance injected into every child reviewer's instructions. The\n * coordinator's mission never crosses the delegation boundary, so\n * mission-dependent guidance cannot exist for children.\n */\n readonly guidance?: string | ReadonlyArray<string> | undefined;\n}\n\n/**\n * Build the fan-out reviewer: a coordinator that delegates bounded per-unit\n * file reviews to attached ephemeral children and merges their findings under\n * the same output contract and the same fail-closed publication path as the\n * flat reviewer. Child and coordinator execution bounds are packaged and not\n * configurable here — the delegation reservation mirrors the child policy,\n * and letting the two drift apart is a published-API hazard.\n */\nconst makeFanOut = <Provider, ModelProvides, ModelRequires>(\n options: PrReviewFanOutOptions<Provider, ModelProvides, ModelRequires>,\n) => {\n const suite = makeFanOutReviewSuite({\n guidance: options.guidance,\n maxFindings: options.maxFindings,\n });\n // Structural bindings for the same reason as in `make` above.\n const binding = Object.freeze({ definition: suite.parent, model: options.model });\n const childBinding = Object.freeze({ definition: suite.child, model: options.model });\n\n // The coordinator's rendered instructions (mission, guidance, findings\n // bound, contract) plus the review-shaping options they do not carry: the\n // child guidance, the host knobs, and the model binding descriptor.\n const guidanceLines =\n options.guidance === undefined\n ? []\n : typeof options.guidance === \"string\"\n ? [options.guidance]\n : options.guidance;\n const signature = (mission: ReviewMission): string =>\n [\n suite.parent.instructions(mission),\n `childGuidance=${JSON.stringify(guidanceLines)}`,\n `applyVerdict=${String(options.applyVerdict ?? false)}`,\n ...(options.modelLabel === undefined ? [] : [`model=${options.modelLabel}`]),\n ].join(\" \");\n const profileSignature = (_mission: ReviewMission): string =>\n [\n \"pr-review-profile-v1-fan-out\",\n JSON.stringify(guidanceLines),\n JSON.stringify(options.ignore ?? []),\n `maxFindings=${clampMaxFindings(options.maxFindings)}`,\n `applyVerdict=${String(options.applyVerdict ?? false)}`,\n ...(options.modelLabel === undefined ? [] : [`model=${options.modelLabel}`]),\n ].join(\"\\u0000\");\n const delegationLayer = fanOutHandlersLayerFor(suite.delegation)(childBinding).pipe(\n Layer.provide(\n Layer.mergeAll(FileReviewToolkitLayer, SubagentReservationsMemoryLive, IdGenerator.layer),\n ),\n );\n\n const run = (runOptions: RunReviewOptions = {}) =>\n provideIgnore(\n executeReview(binding, {\n post: runOptions.post ?? false,\n applyVerdict: options.applyVerdict ?? false,\n limits: options.budget ?? fanOutReviewBudgetLimits,\n maxFindings: clampMaxFindings(options.maxFindings),\n signature,\n modelLabel: options.modelLabel,\n runUrl: runOptions.runUrl,\n usageScope: \"coordinator\",\n reviewShape: \"fan-out\",\n }).pipe(\n Effect.provide(\n Layer.mergeAll(FanOutCoordinatorToolkitLayer, delegationLayer, IdGenerator.layer),\n ),\n Effect.scoped,\n ),\n options.ignore,\n );\n\n return {\n definition: suite.parent,\n binding,\n childBinding,\n run,\n fingerprint: makeFingerprint(signature, options.ignore),\n profileFingerprint: makeProfileFingerprint(profileSignature, options.ignore),\n snapshot: makeReviewSnapshot(options.ignore),\n filterFiles: (files: ReadonlyArray<import(\"./diff.ts\").ChangedFile>) => {\n const ignored = compileIgnoreGlobs(options.ignore ?? []);\n return files.filter((file) => !ignored(file.path));\n },\n } as const;\n};\n\n/**\n * The packaged pull-request reviewer factory.\n *\n * - `make` — one flat reviewer over the whole changeset.\n * - `makeFanOut` — a coordinator delegating bounded per-unit child reviews.\n */\nexport const PrReview = { make, makeFanOut } as const;\n","import { Config, Effect, FileSystem, Layer, Option, Schema } from \"effect\";\nimport type { HttpClient } from \"effect/unstable/http\";\n\nimport type { PriorReviews, ReviewPublisher } from \"./github.ts\";\nimport {\n GitHubReviewTarget,\n gitHubPriorReviewsLayer,\n gitHubPullRequestSourceLayer,\n gitHubReviewPublisherLayer,\n gitHubReviewRetirementHostLayer,\n} from \"./github.ts\";\nimport type { ReviewRetirementHost } from \"./retirement.ts\";\nimport type { PullRequestSource } from \"./source.ts\";\n\n// ---------------------------------------------------------------------------\n// GitHub Actions environment resolution: which pull request to review, from\n// explicit values first and the standard Actions environment second\n// (GITHUB_REPOSITORY, GITHUB_EVENT_PATH, GITHUB_API_URL, GITHUB_TOKEN).\n// Platform-free: FileSystem and Config are Effect services supplied by the\n// host entrypoint.\n// ---------------------------------------------------------------------------\n\n/** The pull request could not be resolved from options or the environment. */\nexport class ReviewTargetUnresolved extends Schema.TaggedError<ReviewTargetUnresolved>()(\n \"ReviewTargetUnresolved\",\n {\n reason: Schema.String,\n },\n) {\n override get message() {\n return this.reason;\n }\n}\n\n/** The slice of a GitHub Actions event payload this package understands. */\nexport const GitHubEventWire = Schema.Struct({\n pull_request: Schema.optionalKey(\n Schema.Struct({\n number: Schema.Int,\n draft: Schema.optionalKey(Schema.Boolean),\n }),\n ),\n repository: Schema.optionalKey(Schema.Struct({ full_name: Schema.String })),\n});\nexport type GitHubEventWire = typeof GitHubEventWire.Type;\n\nconst decodeEvent = Schema.decodeUnknownEffect(Schema.fromJsonString(GitHubEventWire));\n\n/** Read and decode the GITHUB_EVENT_PATH payload, or none outside Actions. */\nexport const readGitHubEvent = Effect.fn(\"readGitHubEvent\")(function* () {\n const eventPath = yield* Config.string(\"GITHUB_EVENT_PATH\").pipe(Config.withDefault(\"\"));\n if (eventPath === \"\") return Option.none<GitHubEventWire>();\n const fs = yield* FileSystem.FileSystem;\n const raw = yield* fs\n .readFileString(eventPath)\n .pipe(\n Effect.mapError((error) =>\n ReviewTargetUnresolved.make({ reason: `Cannot read event payload: ${error.message}` }),\n ),\n );\n const event = yield* decodeEvent(raw).pipe(\n Effect.mapError((error) =>\n ReviewTargetUnresolved.make({ reason: `Cannot decode event payload: ${error.message}` }),\n ),\n );\n return Option.some(event);\n});\n\nexport interface ResolvedReviewTarget {\n readonly repository: string;\n readonly number: number;\n}\n\n/**\n * Resolve the review target: explicit values win, then GITHUB_REPOSITORY and\n * the pull_request event payload. Fails typed when no target can be named.\n */\nexport const resolveReviewTarget = Effect.fn(\"resolveReviewTarget\")(function* (options: {\n readonly repository?: string | undefined;\n readonly number?: number | undefined;\n}) {\n let repository = options.repository ?? \"\";\n if (repository === \"\") {\n repository = yield* Config.string(\"GITHUB_REPOSITORY\").pipe(Config.withDefault(\"\"));\n }\n let number = options.number;\n if (number === undefined || repository === \"\") {\n const event = yield* readGitHubEvent();\n if (Option.isSome(event)) {\n number ??= event.value.pull_request?.number;\n if (repository === \"\") repository = event.value.repository?.full_name ?? \"\";\n }\n }\n if (repository === \"\" || number === undefined) {\n return yield* ReviewTargetUnresolved.make({\n reason:\n \"No pull request to review: pass an explicit repository and number, or run inside a GitHub Actions pull_request event.\",\n });\n }\n return { repository, number } satisfies ResolvedReviewTarget;\n});\n\n/**\n * Build the GitHub source and publisher Layers for one resolved target,\n * reading GITHUB_API_URL and GITHUB_TOKEN from configuration. The returned\n * Layer is the complete GitHub side of a review run.\n */\nexport const gitHubReviewLayers = (\n target: ResolvedReviewTarget,\n): Layer.Layer<\n PullRequestSource | ReviewPublisher | PriorReviews | ReviewRetirementHost,\n Config.ConfigError,\n HttpClient.HttpClient\n> =>\n Layer.unwrap(\n Effect.gen(function* () {\n const apiUrl = yield* Config.string(\"GITHUB_API_URL\").pipe(\n Config.withDefault(\"https://api.github.com\"),\n );\n const graphqlUrl = yield* Config.string(\"GITHUB_GRAPHQL_URL\").pipe(\n Config.withDefault(\n apiUrl === \"https://api.github.com\"\n ? \"https://api.github.com/graphql\"\n : apiUrl.replace(/\\/api\\/v3$/, \"/api/graphql\"),\n ),\n );\n const token = yield* Config.option(Config.redacted(\"GITHUB_TOKEN\"));\n const targetLayer = GitHubReviewTarget.layer({\n apiUrl,\n graphqlUrl,\n repository: target.repository,\n number: target.number,\n token,\n });\n return Layer.mergeAll(\n gitHubPullRequestSourceLayer.pipe(Layer.provide(targetLayer)),\n gitHubReviewPublisherLayer.pipe(Layer.provide(targetLayer)),\n gitHubPriorReviewsLayer.pipe(Layer.provide(targetLayer)),\n gitHubReviewRetirementHostLayer.pipe(Layer.provide(targetLayer)),\n );\n }),\n );\n","import { AnthropicClient, AnthropicLanguageModel } from \"@effect/ai-anthropic\";\nimport { OpenAiClient, OpenAiLanguageModel } from \"@effect/ai-openai\";\nimport { Config, Layer } from \"effect\";\nimport { FetchHttpClient } from \"effect/unstable/http\";\n\nimport { resolveEffortRung, type EffortAliasName, type EffortPosition } from \"./effort.ts\";\n\n// ---------------------------------------------------------------------------\n// Built-in provider bindings for the two host entrypoints (CLI and Action).\n// The library itself stays provider-agnostic — the configuration factory\n// takes any Effect AI Model — and these helpers exist so the batteries-\n// included paths need one flag and one credential, nothing more. Client\n// Layers carry their redacted credentials from configuration; the\n// application supplies them at the edge (D-027).\n// ---------------------------------------------------------------------------\n\nexport type ReviewProvider = \"openai\" | \"anthropic\";\n\nexport const DEFAULT_PROVIDER: ReviewProvider = \"openai\";\n\nexport const DEFAULT_MODEL: Record<ReviewProvider, string> = {\n openai: \"gpt-5.6-sol\",\n anthropic: \"claude-sonnet-5\",\n};\n\nexport const PROVIDER_CREDENTIAL_ENV: Record<ReviewProvider, string> = {\n openai: \"OPENAI_API_KEY\",\n anthropic: \"ANTHROPIC_API_KEY\",\n};\n\n/**\n * Each provider's offered reasoning-effort ladder, cheapest first. The rungs\n * that turn reasoning off (`none`, `minimal`) are deliberately not offered —\n * no review run wants them. An `EffortPosition` resolves into the running\n * provider's own ladder, so the same stored position survives a provider or\n * model change.\n */\nexport const PROVIDER_EFFORT_RUNGS = {\n openai: [\"low\", \"medium\", \"high\", \"xhigh\"],\n anthropic: [\"low\", \"medium\", \"high\"],\n} as const satisfies Record<\n ReviewProvider,\n readonly [EffortAliasName, ...ReadonlyArray<EffortAliasName>]\n>;\n\n/** One OpenAI review model binding with the package's structured-output settings. */\nexport const makeOpenAiReviewModel = (model?: string, effort?: EffortPosition) =>\n OpenAiLanguageModel.model(model ?? DEFAULT_MODEL.openai, {\n max_output_tokens: 8_000,\n store: false,\n strictJsonSchema: true,\n ...(effort === undefined\n ? {}\n : { reasoning: { effort: resolveEffortRung(effort, PROVIDER_EFFORT_RUNGS.openai) } }),\n });\n\n/** One Anthropic review model binding with the package's output settings. */\nexport const makeAnthropicReviewModel = (model?: string, effort?: EffortPosition) =>\n AnthropicLanguageModel.model(model ?? DEFAULT_MODEL.anthropic, {\n max_tokens: 8_000,\n ...(effort === undefined\n ? {}\n : { output_config: { effort: resolveEffortRung(effort, PROVIDER_EFFORT_RUNGS.anthropic) } }),\n });\n\n/**\n * The human-readable descriptor of one provider binding, e.g.\n * `openai/gpt-5.6-sol (effort high)`. Rendered into the review footer and\n * included in the changeset-fingerprint signature, so a provider, model, or\n * effort change re-reviews instead of skipping.\n */\nexport const describeReviewModel = (\n provider: ReviewProvider,\n model?: string,\n effort?: EffortPosition,\n): string => {\n const base = `${provider}/${model ?? DEFAULT_MODEL[provider]}`;\n return effort === undefined\n ? base\n : `${base} (effort ${resolveEffortRung(effort, PROVIDER_EFFORT_RUNGS[provider])})`;\n};\n\n/** The OpenAI client Layer, credential from `OPENAI_API_KEY`. */\nexport const openAiClientLayer = OpenAiClient.layerConfig({\n apiKey: Config.redacted(PROVIDER_CREDENTIAL_ENV.openai),\n}).pipe(Layer.provide(FetchHttpClient.layer));\n\n/** The Anthropic client Layer, credential from `ANTHROPIC_API_KEY`. */\nexport const anthropicClientLayer = AnthropicClient.layerConfig({\n apiKey: Config.redacted(PROVIDER_CREDENTIAL_ENV.anthropic),\n}).pipe(Layer.provide(FetchHttpClient.layer));\n"],"mappings":"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"}
|
package/dist/testing.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { An as ChangedFile, En as PullRequestSource, Tn as PullRequestMetadata, Wt as CodeReview, Y as ReviewPublisher, bt as ReviewHeadComparison, d as FileReviewReport, mt as ReviewPublicationPlan, q as PriorReviews, wt as ReviewState } from "./fan-out-C6gq3CFg.mjs";
|
|
2
2
|
import { Effect, Layer, Option, Ref, Schema } from "effect";
|
|
3
3
|
import { LanguageModel, Model, Response } from "effect/unstable/ai";
|
|
4
4
|
//#region src/internal/fan-out-scripted.d.ts
|
|
@@ -39,7 +39,8 @@ type OfflineUnitOutcome =
|
|
|
39
39
|
} |
|
|
40
40
|
/**
|
|
41
41
|
* Declare more Tool Calls than the child's AgentPolicy allows in one turn —
|
|
42
|
-
* the child fails typed (AgentPolicyError "tool-calls"
|
|
42
|
+
* none executes and the child fails typed (AgentPolicyError "tool-calls",
|
|
43
|
+
* the reviewer's deliberate `onExhaustion: "fail"` pin).
|
|
43
44
|
*/
|
|
44
45
|
{
|
|
45
46
|
readonly _tag: "budget-runaway";
|
package/dist/testing.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { Effect, Layer, Option, Ref, Schema, Stream } from "effect";
|
|
1
|
+
import { Lt as CodeReview, _n as ChangedFile, a as PublishedReview, dn as MAX_FILE_CHARS, fn as PullRequestMetadata, gn as normalizeRepoRelativePath, hn as ReviewInputViolation, i as PriorReviews, nt as FileReviewReport, o as ReviewPublisher, pn as PullRequestSource, r as PriorReviewLookupFailure } from "./github-Lfa_ox-u.mjs";
|
|
2
|
+
import { DateTime, Effect, Layer, Option, Ref, Schema, Stream } from "effect";
|
|
3
3
|
import { LanguageModel, Model } from "effect/unstable/ai";
|
|
4
4
|
//#region src/internal/scripted.ts
|
|
5
5
|
const OFFLINE_LIST_CALL_ID = "list-1";
|
|
@@ -212,7 +212,9 @@ const collectingReviewPublisherLayer = (published) => Layer.succeed(ReviewPublis
|
|
|
212
212
|
reviewId: plans.length,
|
|
213
213
|
url: `memory://review/${plans.length}`,
|
|
214
214
|
event: plan.event,
|
|
215
|
-
inlineComments: plan.comments.length
|
|
215
|
+
inlineComments: plan.comments.length,
|
|
216
|
+
authorNodeId: "BOT_memory-reviewer",
|
|
217
|
+
submittedAt: DateTime.makeUnsafe(`2026-01-01T00:00:${String(plans.length).padStart(2, "0")}Z`)
|
|
216
218
|
}))) }));
|
|
217
219
|
/** Static `PriorReviews` service for tests: fixed history and comparisons. */
|
|
218
220
|
const staticPriorReviews = (fingerprint, options = {}) => PriorReviews.of({
|