ADR-0041: Cross-Harness Severity Ladder
Accepted Town-crier Cross-Harness ContractDate: Ratified TC-0036 2026-07-03 (both owners); our skills migrated same day; ADR crystallizes 2026-07-10. Tracks: kendo TC-0036 (the ladder + riders R1–R4), TC-0040 (enum schema on the wire) — script instance, project 13, contract-decision. Reasoning: project_town_crier_contract_decision_log memory; /registry/general-review-voice.md (the ladder as the General executes it).
Status note. A cross-harness contract: for findings from independently-run harnesses to compose — to confirm or deny one another on a shared thread (ADR-0040) — a "Major" from one harness must mean the same as a "Major" from another. Ratified with Jasper on the contract-decision log (
TC-0036, Done = binding record); our review skills (general-review-voice,/pr-review-sweep,/bus-review) were migrated onto it the same day. This ADR crystallizes the ratified end-state per ADR-0015. It is the vocabulary layer: the tiers it defines are what ADR-0039's gate derives from and what rides ADR-0040's submit.
Context
Several harnesses review the same PR on one serialized thread (ADR-0040). For their findings to compose — for a second harness's turn to confirm or deny a first harness's finding — they need a shared severity scale. Before TC-0036, each harness carried its own vocabulary (the war room's was Blocker/Concern/Nit; others differed), so a cross-harness "confirm" was apples-to-oranges: the same defect could be a Concern here and a Major there, and the merge gate had no common tier to key on. Detection stays per-harness — each finds defects its own way, and that diversity is the value — but the scale that names a finding's consequence must be shared. That is the whole of this ADR.
Decision
1. A four-tier, first-match ladder (top-down; first match wins)
- 🛑 Blocker — ship test: on a realistic path — wrong output, a security / privacy / data-integrity breach, a regression of a working flow, or an unmet stated acceptance criterion.
- 🔴 Major — edge / latent / contract test: real impact via a plausible edge case; a latent footgun likely to become a blocker; or a violated established contract/convention at real cost.
- 🟡 Minor — objective-quality test: correctness-neutral but an objective improvement (reuse over duplication, dead code, a non-critical test gap, readability).
- ⚪ Nit — taste / cosmetic / preference. Author's call.
- Praise (outside the ladder) — load-bearing decisions worth naming, brief. Standard wins ("uses a DTO") don't qualify; non-obvious correctness wins do.
2. One ladder for all categories
Severity is consequence, never type. Security, performance, and test-gap findings all tier on the same scale by what happens if the finding is true — a cosmetic security-adjacent nit is a Nit, not a Blocker-because-security.
3. Severity is assigned as-if-true
A finding is tiered as if it is true; uncertainty is never laundered into a lower tier ("it's probably a bug so I'll call it a Minor to be safe" is forbidden). Uncertainty lives in the confidence tag (§4), not the severity.
4. Two tags: confidence and provenance
- confidence ∈
Confirmed(apath:linecitation or a reproduced command backs the claim) /Unconfirmed(plausible-as-if-true, with the verification stated). A second harness's turn promotes or kills an Unconfirmed finding — this is the decorrelated-verification value (ADR-0040 §4 guarantees the second turn is a different author). - provenance ∈
introduced(the defect line is in the diff) /adjacent(in code the diff touches) /pre-existing. Strict: onlyintroducedlines carry blocking weight; boy-scout observations on adjacent/pre-existing code stay legal as suggestions, never as blocking findings — a small PR is not buried under a file's pre-existing sins.
5. Tie-break: round down, except round up for the high-stakes set
When torn between two tiers, round down — except anything touching security, data-integrity, an acceptance criterion, or a regression of a working flow (R3), which rounds up. The asymmetry biases toward catching the consequences that are expensive to miss.
6. The ratified riders (R1–R4)
- R1 — verdict binding. Interim (TC-0036): Blocker was the only verdict-forcing tier (Confirmed Blocker →
REQUEST_CHANGES; Unconfirmed Blocker caps atCOMMENT+ a validation ask; Majors/Minors/Nits inform, never force). Superseded operationally by ADR-0039: the merge gate now derivesBLOCKED/HELDfrom findings and binds bus machinery (suppresses consensus auto-resolve), while the R1 principle it preserves — the gate never forces a harness's stance — carries through unchanged. - R2 — invisible acceptance criteria. The acceptance-criterion Blocker clause (§1) applies only when the criteria are visible from the PR/thread; otherwise it is explicitly N/A, stated, never silently skipped or guessed.
- R3 — regressions round up. A regression of a working flow joins the round-up set (§5) — folded into the ladder above.
- R4 — approve-with-residuals. An
APPROVEthat carries actionable Minors/Nits marks them non-blocking, author's choice (fold here or follow-up); the reviewer never arms auto-merge on another's PR; at thread-resolve, surviving residuals carry to a disposition (fixed / follow-up / declined — never undecided). Operationalized by ADR-0039's disposition lifecycle (dispositions[]+ residual-drain).
7. The scale is the registered vocabulary
TC-0040 enum-backs tier / confidence / provenance on the submit wire (ADR-0039 §1), retiring the copied BADGE_RE prose-parsing every harness carried. The enums are the single registered naming. Honest limit: the schema forces vocabulary, not calibration — a wrong tier on a real finding still ships; correct tiering stays the confirm/deny turn, now disputing tiers on specific finding rows rather than parsing prose.
Options Considered
| Option | Verdict | Reason |
|---|---|---|
| Per-harness vocabularies (status quo) | Rejected | Findings can't compose; a cross-harness confirm/deny is apples-to-oranges; the merge gate has no shared tier to key on. |
| Severity by category (security always Blocker, etc.) | Rejected | Severity is consequence, not type (§2). A cosmetic security-adjacent nit is not a Blocker. |
| Downgrade-with-note for uncertain findings | Rejected | Launders confidence into severity. The as-if-true tier + separate confidence tag (§3–4) is the honest split. |
| Confidence as a 3+-level scale / category as a third tag | Rejected | Jasper's tag call: confidence YES (2-level), provenance YES (strict), category NO — a third axis with no consumer is noise. |
| Shared four-tier ladder, as-if-true, confidence+provenance tags, enum-on-wire | Accepted | Findings compose across harnesses; the gate can derive from shared tiers; as-if-true kills confidence-laundering; provenance-strict protects small PRs. |
Consequences
Positive
- Findings compose across harnesses — a "confirm" means the same thing on both sides.
- The merge gate can exist — ADR-0039 derives
BLOCKED/HELDfrom tiers because the tiers are shared and enum-registered. - As-if-true kills the confidence-laundering failure mode — uncertain findings keep their real severity and carry an explicit confidence tag instead of being quietly demoted.
- Provenance-strict protects small PRs — a diff isn't buried under a file's pre-existing debt.
Negative
- It is a shared contract — a harness that tiers to its own scale breaks composition. Mitigation: enum on the wire + the confirm/deny turn disputes mis-tiers.
- Calibration is not enforced — only vocabulary. A mis-tiered finding ships; the schema can't catch it.
Risks
- Mis-tiering ships. Mitigation: the decorrelated confirm/deny turn (ADR-0040 §4) is the calibration backstop — not the schema.
Enforcement
| What | Mechanism | Level |
|---|---|---|
tier / confidence / provenance enum-validated on the submit wire | SubmitReviewRequestRequest + FormRequestsTest (via ADR-0039) | 1 / 3 |
| The ladder + tags + riders as the review register | /registry/general-review-voice.md · /pr-review-sweep · /bus-review skills | 4 |
| Cross-harness ratification (both owners), riders folded | contract-decision log TC-0036 (kendo-script project 13) | 5 |
Implementation
| Territory | State | Notes |
|---|---|---|
| town-crier | RATIFIED + IN USE | TC-0036 signed both owners 2026-07-03; our general-review-voice + /pr-review-sweep + /bus-review migrated same day; enum-enforced on the wire via TC-0040 / ADR-0039. Foreign harnesses declare structured findings on the same enums (verified live 2026-07-09/10). |
References
- Originating tickets:
TC-0036(ladder + R1–R4),TC-0040(enum schema) — kendo-script project 13,contract-decisionlabel. - Related ADRs: Cross-Harness Merge Gate (ADR-0039 — derives the gate from these tiers, operationalizes R1/R4), Cross-Harness Thread & Turn-Lock Protocol (ADR-0040 — the thread the reviews ride; its no-two-turns rule is what makes confidence promotion decorrelated), ADR Governance (ADR-0015).
- Reasoning / execution:
project_town_crier_contract_decision_logmemory;/registry/general-review-voice.md.