Appendix B - 16. Model-graded finding severity (distance-graded gate)
The Structure of Model-graded finding severity (distance-graded gate) — its shape at a glance:
Projected from the catalogue entry system-models / Model-graded finding severity (distance-graded gate).
On this page: Intent · Motivation · Applicability · Structure · Sample Code · Consequences · Example use within DocAble · Related Patterns
Intent
Intent — Grade each lint finding's severity — block, warn, or silence — by the finding's distance, in a typed component model, from the files the commit actually changed, computed by one central join the gate runs over every finding rather than by each lint scoping itself. The pre-commit hook reads the model at check time and dogfoods it to run a mechanism. (Our instance grades a governed-doc commit's deploy-scope lints against the component-and-zone model.)
Motivation
A whole-tree lint reports findings from all over the tree. Two ways to gate on it both fail, and both recur:
- All-or-nothing blocking. The gate blocks on any finding the lint reports. A commit that touches one file gets blocked by a pre-existing finding three subsystems away — noise it can't fix and didn't cause. Agents learn to bypass the gate, and the gate stops protecting anything.
- Every lint scopes itself. Each lint re-decides "is this finding relevant to this change?" — one reads a scan-root, another inlines a relevance guess, a third does nothing. Now the relevance logic lives in N places and drifts N ways. Fix the scoping rule once and it holds for one lint; the others keep their private, subtly-wrong copies. A new lint arrives with no scoping at all and re-opens the all-or-nothing problem.
The shared failure: findings graded uniformly wrong. The gate either over-blocks on unrelated findings or under-warns on relevant ones, and no single place owns the answer to "how close is this finding to what the commit changed?"
Applicability
- A typed component model the gate can read at check time — a map from repo path to component, and a way to ask which components a set of paths touches.
- A structured-finding contract that already ships. The lints must emit findings as typed records — site, causing input, kind, fix-guidance — and the gate must be able to parse them. In the instance this contract existed before the mechanism: the lints already built typed findings and already supported a JSON emission mode a shared parser reads. The central join consumes a substrate that ships today rather than inventing a contract; the only per-lint change is populating the causing-input field where a lint had buried the causing file inside its message string.
- A downstream backstop — a no-baseline gate (at deploy, say) that catches every finding regardless of grade, so SILENT means deferred, not unchecked-forever.
- A cost budget. The central join needs each lint to run whole-tree so the gate sees every site to grade. Where a lint's whole-tree cost stays under a declared threshold, it goes through the central grader; a lint over the threshold keeps a cheaper self-scoped path and forgoes the SOFT warn — the placement is a recorded lookup, not a per-lint judgment.
Structure
The Structure diagram appears at the top of this page.
Sample Code
Consequences
- One grader, one blast radius. Centralizing the join means a bug in the grader touches every lint, where a per-lint bug was contained. The trade buys a single well-tested surface with an exhaustive invariant suite over N private re-derivations, and the additive-restrictive property bounds the worst case to a fail-safe.
- SOFT debt accumulates. A SOFT warn never forces a fix, so a component collects pre-existing findings shown on every commit that touches it. Cap the per-commit output and let the downstream backstop force the drain; a rising SOFT count in a component is a signal a hygiene pass is due, not a leak.
- Whole-tree cost per governed commit. Grading every finding means running the lints whole-tree, more compute than a self-scoped run. Measure it; keep the cheap members central and route only the expensive ones to a self-scoped path.
- The contract is now load-bearing. A lint that stops emitting a well-formed structured finding degrades to opaque HARD — safe, but noisy. The emission contract earns a check of its own.
Example use within DocAble
- A pre-commit hook that grades a governed-doc commit's whole-tree lint findings — a doc-staleness check and an index-comprehensiveness check — against the component-and-zone model. The hook runs each lint in structured-emit mode, parses the findings through a shared parser that already shipped, and grades them HARD / SOFT / SILENT in one central join. It fixed a recurring incident where a commit touching one doc was blocked by stale findings elsewhere in the tree. A commit that adds an unindexed doc still blocks — the finding's site is an untouched index file, but its causing input is the doc the commit added, so it grades HARD by causation.
Related Patterns
- Enabler — component & zone model: the typed model the grader reads at check time. This is the sharpest instance of a model consumed to run a mechanism — the gate dogfoods the component map on every governed commit, not as documentation but as the thing that decides severity.
- Enabler — meta-model consumption: the read-don't-snapshot discipline the grader follows when it imports the model at check time rather than baking a copy.
- Counterpart — drift & parity gates: both are hard gates reading a model at check time, but a parity gate asks does the model match reality? — a fixed pass/fail per model row. This asks how close is this finding to the change? and returns a graded answer.
- See also — pre-commit hook: the gate this grader runs inside. The hook owns the staged set and the commit process; this mechanism is what the hook does with a finding once a lint reports it.
- See also — symbol-anchored traceability graph: a sibling that consumes the models to grade a join's health. Both turn a model into a live check rather than a read-only reference; that maps code onto model nodes and re-derives the edges, this maps findings onto model components and grades their distance.