/** * `pr:` evidence-atom validator. * * Resolves a GitHub pull request via the `gh` CLI and decides whether the PR * satisfies the `implemented`, `testsPassed`, and `qaPassed` gates (T9838). * Closes the release-verb dogfood gap (T9764): tasks that ship via the * standard PR + admin-merge flow previously had no zero-friction way to record * evidence retroactively — * `tool:test` re-runs the entire monorepo suite and `note:` is rejected for * hard gates on critical verifications. * * A PR atom counts as evidence when: * 1. `state === 'MERGED'` — the PR was actually shipped to main. * 2. `mergedAt` is non-null — defends against API races. * 3. Every required-workflow check has `conclusion === 'SUCCESS'` (or * `'SKIPPED'`) — there are zero `FAILURE` checks among the * required workflows configured by branch protection. * * Results are cached under `/.cleo/cache/evidence/pr-.json`, * keyed on `(prNumber, mergedAt)` so re-verifies skip the network round trip. * * @task T9764 * @epic T9762 * @saga T9758 */ import { type GhPrViewPayload } from '@cleocode/contracts'; /** * Result of resolving a `pr:` atom. * * On success carries the data needed to materialise an `EvidenceAtom` of * `kind: 'pr'`. On failure carries a human-readable reason plus the same * `codeName` vocabulary used by the rest of the evidence pipeline so error * presentation stays uniform. * * @task T9764 */ export type PrAtomResolution = { ok: true; prNumber: number; mergeCommitSha: string; mergedAt: string; successCount: number; totalChecks: number; cacheHit: boolean; } | { ok: false; reason: string; codeName: 'E_EVIDENCE_INVALID' | 'E_EVIDENCE_INSUFFICIENT' | 'E_EVIDENCE_TESTS_FAILED' | 'E_EVIDENCE_TOOL_FAILED'; }; /** * Filesystem location for the cached PR validation result. * * Path: `/.cleo/cache/evidence/pr-.json`. * * @task T9764 */ export declare function prCacheEntryPath(projectRoot: string, prNumber: number): string; /** * Function signature for fetching a GitHub PR's metadata. * * Returning `null` signals a fetch failure (binary missing, auth error, * malformed JSON). Returning a payload that fails {@link ghPrViewSchema} * also yields a `E_EVIDENCE_TOOL_FAILED` outcome. * * @task T9764 */ export type FetchGhPrPayload = (prNumber: number, cwd: string) => Promise<{ ok: true; payload: unknown; } | { ok: false; reason: string; }>; /** * Default `gh pr view` invocation. Calls `gh pr view --json * state,mergedAt,mergeable,headRefOid,statusCheckRollup` via `execFileSync` * for parity with the rest of the release module's `gh` usage. * * @task T9764 */ export declare const defaultFetchGhPrPayload: FetchGhPrPayload; /** * Resolve the list of required-workflow names for the current project. * * Precedence (most specific wins): * 1. `CLEO_PR_REQUIRED_WORKFLOWS` env var (comma-separated) — CI/operator * override. * 2. `.cleo/project-context.json` `release.prRequiredWorkflows` * ({@link PR_REQUIRED_WORKFLOWS_CONTEXT_KEY}) — committed per-project config. * An explicit empty array means NO required workflows (gh#1104). * 3. {@link PR_REQUIRED_WORKFLOWS} default (the cleocode contract-repo gates). * * @task T9764 * @task T12014 (gh#1104) */ export declare function resolveRequiredWorkflows(env?: NodeJS.ProcessEnv, projectContext?: Record | null): string[]; /** * Inspect the `statusCheckRollup` and decide whether the required checks * are green. * * Required-check names from {@link PR_REQUIRED_WORKFLOWS} match against * EITHER the rollup entry's `workflowName` (top-level workflow like * `"Lockfile Check"`) OR its `name` (individual job, like `"Contracts * Dep Lint"` which lives under `workflowName === "CI"`). GitHub branch * protection lists required contexts by job name OR workflow name, and * the rollup may surface them at either granularity. * * ## Per-required-entry success rule * * For each entry in {@link PR_REQUIRED_WORKFLOWS}: * 1. At least one rollup check must match by name OR workflowName. * 2. At least one matching check must have `conclusion === 'SUCCESS'`. * 3. The match's status must be `COMPLETED` (not pending). * * Workflow-level matches (e.g. `"CI"` matches every job under CI) are * intentionally LENIENT: when ANY job under the workflow is `SUCCESS`, * the workflow counts as satisfied even if other (non-required-by-name) * jobs inside the same workflow are `FAILURE`. This mirrors GitHub's * branch-protection behavior, which gates merge on the * `required_status_checks[contexts]` list — administrators may merge * past non-required job failures, and `pr:` evidence accepts that * reality. To enforce stricter rules, narrow the required list via the * {@link PR_REQUIRED_WORKFLOWS_ENV_VAR} env var to specific job names. * * @internal * @task T9764 */ export declare function evaluateRollup(rollup: GhPrViewPayload['statusCheckRollup'], requiredWorkflows: readonly string[]): { ok: true; successCount: number; totalChecks: number; } | { ok: false; reason: string; }; /** * Options for {@link resolvePrEvidenceAtom}. Allows test injection of a * mock `gh` wrapper plus an env override so tests do not have to mutate * `process.env`. * * @task T9764 */ export interface ResolvePrEvidenceAtomOptions { /** Mock `gh` wrapper for tests; defaults to {@link defaultFetchGhPrPayload}. */ readonly fetchGhPrPayload?: FetchGhPrPayload; /** Env (defaults to `process.env`). */ readonly env?: NodeJS.ProcessEnv; /** When `true`, bypass cache reads. Cache writes always happen. */ readonly bypassCache?: boolean; /** * Parsed `.cleo/project-context.json` (or `null`). Tier between env and the * built-in default for required-workflow resolution (gh#1104). @task T12014 */ readonly projectContext?: Record | null; } /** * Validate a `pr:` atom end-to-end. * * Steps: * 1. Cache lookup — return immediately on a fresh hit. * 2. Fetch `gh pr view --json …`. * 3. Schema-validate the payload. * 4. Reject non-merged PRs (`state !== 'MERGED'` or null `mergedAt`). * 5. Evaluate the status-check rollup against required workflows. * 6. Persist the result to cache and return. * * @param prNumber - PR number (positive integer). * @param projectRoot - Absolute path to the project root (for cache + cwd). * @param opts - Optional overrides for testing. * @returns Validation result envelope. * * @task T9764 */ export declare function resolvePrEvidenceAtom(prNumber: number, projectRoot: string, opts?: ResolvePrEvidenceAtomOptions): Promise; //# sourceMappingURL=pr-evidence.d.ts.map