/** * peaks-workflow — the QA phase, derived from the type tables. * * WHY THIS IS A MODULE OF ITS OWN. A measured budget, not taste: the file-size * census records the gated excess by EQUALITY, and `pipeline-verify-gate-support` * already carries its share of that sum. A file under its cap adds nothing to it, * so the reasoning below — which a contributor has to be able to find — is paid * for here, at zero census cost. * * WHY A DERIVATION AT ALL. Two layers answered one question — *does this request * need a QA phase?* — and gave different answers, because neither read the answer * off the type tables that define the contract. One named three request types; * the other asked unconditionally. A request whose table carries no QA row at all * therefore satisfied every prerequisite its own contract lists and was then * refused at commit time for a phase that contract never asked for. * * The tables are the authority. `MINIMAL_TABLE` carries no `qa:` row, which is * what "these types have no QA phase" has always meant, and what * `request transition --role qa --state verdict-issued` has always enforced * against the same table. * * WHY IT IS ARMED. A derivation nobody checks is a restatement with better * manners. A table row can name a QA artifact no gate stands for, and that row * would then build no gate and say nothing about it — the same drift, one layer * down. So the declared gate list is reconciled against every type's QA rows once * per process, and a mismatch THROWS. The cost is deliberate and wider than it * looks: the CLI registers every command eagerly, so an unrepresentable row does * not merely fail `verify-pipeline` — it fails EVERY `peaks` invocation that * reaches this module, the commit leg and `workflow verdict-aggregate` included. * That is the fail-closed * direction, and naming the row keeps the repair one line. */ import { type RequestType } from '../artifacts/artifact-prerequisites.js'; import type { PipelineGate } from './pipeline-verify-types.js'; /** * Every state the QA role can be in, taken from the repository's own state model * rather than restated here. * * WHY IT IS NOT JUST `verdict-issued`. The terminal state is the one the phase's * evidence is resolved at, so an earlier version keyed both the derivation and the * reconciliation to it alone — which left the `qa:running` row a feature's table * already carries outside the arming. A row at any other state would have been * silently unrepresentable. The arming is total over the state axis instead. */ export declare const QA_STATES: readonly import("../artifacts/request-artifact-state-helpers.js").RequestArtifactState[]; /** * Every QA evidence gate the checker can build, each naming the contract path it * stands for. The NAME is the checker's own — `peaks workflow skip` takes gate * names and the violation text prints the description — while the PATH is the * contract's, and it is the half that makes a gate list derivable instead of * restated beside the tables it is supposed to be read from. */ export declare const QA_EVIDENCE_GATES: ReadonlyArray<{ name: string; description: string; relativePath: string; }>; /** * Does this type's table carry a QA phase? * * One derivation, so the gate list and the checker's verdict cannot disagree: the * phase exists for a type exactly when its table carries a QA prerequisite — * counted across every QA state, so a type whose only QA row sits at a * non-terminal state is not read as having no phase at all. */ export declare function typeRequiresQaPhase(requestType: RequestType): boolean; /** * The request types whose table carries NO QA phase — the set a skip may cover. * * DERIVED, not listed. The skip allowlist used to spell `['docs', 'config', 'chore']`, * and `config` carries a QA phase (its table demands `SECURITY_REVIEW` and * `TEST_REPORT`), so a plantable record could bypass a phase the contract requires. * Reading the answer off the same derivation the pipeline uses means a table change * moves the allowlist with it — in both directions, without anyone remembering. */ export declare const QA_FREE_TYPES: ReadonlyArray; /** * Fill in the QA request gate for a phase that HAS one. * * A type whose table carries no QA row has no QA gate to fill, and that is not a * special case to handle at the call site: the artifact is still honoured — its * state and its location are read either way — so a tree that ran QA for a type * whose table does not demand it keeps passing. */ export declare function markQaRequestGate(gates: PipelineGate[], artifactPath: string): void; /** * The QA phase's gate list for one type: the phase gate when the phase exists, * then one gate per piece of evidence the caller resolved from the contract. An * empty list IS the answer for a type with no QA phase. * * The `security-findings` / `performance-findings` gates were removed here * security review or performance review — `peaks-qa/SKILL.md` says so, and the * v2.11.0 D1/D4 trim dropped both from every `qa:verdict-issued` table. The * evidence they used to demand is now checked on the RD side, at the paths the * contract actually names (`audit/security-.md`, `audit/perf.md` and * `rd/security-review.md` / `rd/perf-baseline.md` as the declared legacy tiers * behind them). */ export declare function qaPhaseGates(required: boolean, evidence: ReadonlyArray<{ name: string; description: string; }>): PipelineGate[];