import type { Finding, FindingSeverity, FindingConfidence } from "audit-tools/shared"; import { type ReviewNecessity, type ImplementationCost } from "./reviewNecessity.js"; export declare const REVIEW_REQUEST_SCHEMA_VERSION: "remediate-code-review-request/v1"; /** One reviewable item, with the tool-owned deterministic fields populated. */ export interface ReviewItemEntry { finding_id: string; title: string; severity: FindingSeverity; confidence: FindingConfidence; lens: string; summary: string; affected_files: string[]; necessity: ReviewNecessity; /** Deterministic reason this item landed in its tier. */ rationale: string; implementation_cost: ImplementationCost; } /** A review-necessity tier with its items (most-review-needed tiers first). */ export interface ReviewTierGroup { necessity: ReviewNecessity; label: string; description: string; items: ReviewItemEntry[]; } /** The halt artifact presented to the user (`review_request.json`). */ export interface ReviewRequest { schema_version: typeof REVIEW_REQUEST_SCHEMA_VERSION; plan_id: string; total: number; counts: Record; /** Non-empty tiers only, ordered most-review-needed first. */ tiers: ReviewTierGroup[]; } /** The user's verdict (`review_resolution.json`). */ export interface ReviewResolution { plan_id?: string; /** Finding ids the user disapproved — do NOT act on these. */ disapproved_findings?: string[]; /** Whole tiers the user disapproved (e.g. "decline everything strategic"). */ disapproved_tiers?: ReviewNecessity[]; } export interface ReviewDecision { /** Finding ids approved to proceed to implementation. */ approved_ids: string[]; /** Disapproved items, each with the recorded reason for its terminal disposition. */ declined: Array<{ finding_id: string; reason: string; }>; } /** * Build the tiered review request from a finding set. Deterministic: the same * findings always produce the same tiers/entries. Empty tiers are omitted, but * `counts` always carries all three keys so the caller can report the full * distribution. */ export declare function buildReviewRequest(findings: readonly Finding[], planId: string): ReviewRequest; /** * Whether `resolution` answers THIS `request` (INV-RSM-RESOLUTION-CORRELATE). * An absent resolution or an absent `plan_id` correlates (host-lenient: the * single-run common case writes no plan_id); a PRESENT plan_id that differs * from the request's marks a stale leftover from another run — the caller must * archive it and re-halt rather than apply a cross-run answer. */ export declare function isResolutionForRequest(request: ReviewRequest, resolution: ReviewResolution | null | undefined): boolean; /** * Screen a resolution's id references against the request (uniform id-join * contract): every `disapproved_findings` entry must name an item in the * request, and every `disapproved_tiers` entry must be one of the closed * review-necessity names. A stray id here is not a no-op — the gate's default * is APPROVE, so a typo'd decline would silently become an approval. Empty * arrays = clean. A tier that is valid but empty in this request stays a * harmless no-op (it names a real vocabulary member, not a phantom item). */ export declare function screenResolutionIds(request: ReviewRequest, resolution: ReviewResolution | null | undefined): { unknown_finding_ids: string[]; unknown_tiers: string[]; valid_finding_ids: string[]; }; /** * Apply the user's resolution to a request: every item is either approved (act * on it) or declined (recorded terminal disposition with a reason). An item is * declined if its id is in `disapproved_findings` OR its tier is in * `disapproved_tiers`. Everything else is approved — the default is to act, * because the gate's job is to let the user REMOVE items, not to require * opting every item in. An absent/empty resolution approves everything. * * A resolution carrying a MISMATCHED `plan_id` is rejected (throws): applying a * stale cross-run answer would approve/decline the wrong finding set * (INV-RSM-RESOLUTION-CORRELATE, COR-0b906e37). Callers pre-screen with * {@link isResolutionForRequest} to archive-and-re-halt instead of crashing; * the throw here is the mechanical backstop, not the primary UX. * * Crucially, declined items are returned with an explicit reason so the caller * records a terminal disposition (e.g. `ignored`) rather than silently closing * them — the exact failure this gate exists to prevent. */ export declare function applyReviewResolution(request: ReviewRequest, resolution: ReviewResolution | null | undefined): ReviewDecision; //# sourceMappingURL=reviewGate.d.ts.map