|
| 1 | +// SPDX-License-Identifier: PMPL-1.0-or-later |
| 2 | += Exemption mechanisms in the hyperpolymath estate |
| 3 | +:toc: |
| 4 | + |
| 5 | +Three concentric exemption layers exist in the estate. Each addresses a |
| 6 | +different question and lives in a different file. Mixing them up is the |
| 7 | +single most common cause of "I added an ignore file but CI still fails" |
| 8 | +confusion. |
| 9 | + |
| 10 | +== Quick decision tree |
| 11 | + |
| 12 | +[source] |
| 13 | +---- |
| 14 | +Are you trying to stop bots from WRITING to a path? |
| 15 | + -> use the estate-wide bot_exclusion_registry.a2ml |
| 16 | +
|
| 17 | +Are you trying to stop the governance gate from FAILING on a |
| 18 | +pre-existing finding? |
| 19 | + -> use the per-repo .hypatia-baseline.json |
| 20 | +
|
| 21 | +Are you trying to make a finding GO AWAY for one specific PR only? |
| 22 | + -> currently unsupported. See "per-PR exemptions" below. |
| 23 | +---- |
| 24 | + |
| 25 | +== Layer 1: Estate-wide bot write denylist |
| 26 | + |
| 27 | +**File:** `hyperpolymath/standards/.machine_readable/bot_exclusion_registry.a2ml` |
| 28 | + |
| 29 | +**Scope:** All bots, all repos. Authoritative across the entire estate. |
| 30 | + |
| 31 | +**Purpose:** Tells bots what they may not *write* to. Read-only scanning |
| 32 | +is always allowed; only write actions (Write, Commit, CreatePr, |
| 33 | +CreateBranch, etc.) are gated. |
| 34 | + |
| 35 | +**Format:** A2ML (TOML-shaped). Three axes: |
| 36 | +1. `external-repos` — exact `owner/repo` matches that bots must skip. |
| 37 | +2. `vendored-directory-patterns` — globs that should never be edited. |
| 38 | +3. `remote-origin-patterns` — bail-if-origin-matches patterns. |
| 39 | + |
| 40 | +**Consumer:** Every bot via `shared-context::ExclusionRegistry::check()`. |
| 41 | +The registry is fail-closed: if the file fails to load, all bot writes |
| 42 | +are denied. |
| 43 | + |
| 44 | +**Edit when:** A new repo should be off-limits to bots, or a new |
| 45 | +vendored subtree should never be modified. |
| 46 | + |
| 47 | +**Don't use for:** Suppressing CI findings. This layer doesn't touch |
| 48 | +CI at all. |
| 49 | + |
| 50 | +== Layer 2: Per-repo Hypatia finding baseline |
| 51 | + |
| 52 | +**File:** `.hypatia-baseline.json` at the calling repo's root. |
| 53 | + |
| 54 | +**Scope:** One repo. Acknowledged findings only — not a "ignore these |
| 55 | +forever" file. |
| 56 | + |
| 57 | +**Purpose:** Tells the governance gate which Hypatia findings have been |
| 58 | +seen, triaged, and accepted as known debt. Findings matched by a baseline |
| 59 | +entry don't block CI; they're surfaced in the run summary as |
| 60 | +"acknowledged." |
| 61 | + |
| 62 | +**Format:** JSON array of `{severity, rule_module, type, file | file_pattern, ...}` |
| 63 | +objects. See `docs/HYPATIA-BASELINE-FORMAT.adoc` for the full schema. |
| 64 | + |
| 65 | +**Consumer:** `apply-baseline.sh` invoked from |
| 66 | +`hyperpolymath/standards/.github/workflows/governance-reusable.yml`. |
| 67 | +Suppresses matching findings from the gate, downgrades severity if |
| 68 | +`severity_override` is set, fails on expired entries. |
| 69 | + |
| 70 | +**Edit when:** |
| 71 | +* Pre-existing debt is tracked for migration (link a `tracking_issue`). |
| 72 | +* Vendored / third-party code triggers a rule the team can't fix. |
| 73 | +* Test fixtures intentionally violate a rule (with `note` explaining). |
| 74 | + |
| 75 | +**Don't use for:** |
| 76 | +* Newly-introduced findings on freshly-authored code. The rule exists |
| 77 | + for a reason; baselining the new file defeats it. Fix the code. |
| 78 | +* One-off PR-scoped suppression. Baseline edits are merged to main; they |
| 79 | + affect all subsequent PRs. See Layer 3. |
| 80 | + |
| 81 | +== Layer 3: Per-PR exemptions (NOT YET IMPLEMENTED) |
| 82 | + |
| 83 | +There is currently no supported per-PR exemption mechanism. PR authors |
| 84 | +attempting one (e.g. by inventing a `.hypatia-ignore` file) will find |
| 85 | +nothing reads it, and the gate will still fail. **Do not invent new |
| 86 | +file conventions.** If you need per-PR exemption, file an issue against |
| 87 | +`hyperpolymath/standards` proposing a designed mechanism. |
| 88 | + |
| 89 | +If a mechanism is added, it should be one of: |
| 90 | + |
| 91 | +1. **PR-body marker**, e.g. a fenced block: |
| 92 | ++ |
| 93 | +[source,markdown] |
| 94 | +---- |
| 95 | +```hypatia-exempt |
| 96 | +- rule: code_safety/obj_magic |
| 97 | + file: bots/sustainabot/bot-integration/src/Analysis.res |
| 98 | + reason: Pre-migration debt; tracked in #148 |
| 99 | +``` |
| 100 | +---- |
| 101 | ++ |
| 102 | +Pros: lives with the PR, vanishes when the PR closes, reviewable in |
| 103 | +the same UI as the change. Cons: requires a PR-body parser. |
| 104 | + |
| 105 | +2. **Label-driven**, e.g. apply `gate:exempt:code_safety` and require an |
| 106 | +exemption-justification comment from a CODEOWNER. |
| 107 | + |
| 108 | +3. **Sidecar file under `.github/pr-exemptions/`** — committed for one |
| 109 | +PR's lifetime, deleted at merge by a workflow. |
| 110 | + |
| 111 | +A formal proposal should pick one and document it explicitly. |
| 112 | + |
| 113 | +== Anti-patterns to reject |
| 114 | + |
| 115 | +These have been attempted and should be refused at review: |
| 116 | + |
| 117 | +* `.hypatia-ignore` (any format) — never read by anything. Reject; point |
| 118 | + the author at `.hypatia-baseline.json`. |
| 119 | +* Adding `pragma: ignore-rule` comments in source. Hypatia scans by AST |
| 120 | + and ignores comments; suppression has to be data-driven, not |
| 121 | + source-comment driven. |
| 122 | +* Setting `continue-on-error: true` on the governance gate. This makes |
| 123 | + CI lie. Use a baseline entry with `severity_override: advisory` |
| 124 | + instead — keeps the finding visible while unblocking the gate. |
| 125 | +* Adding the offending path to `.gitignore`. The file still exists in |
| 126 | + history; Hypatia and other estate scanners still see it. |
| 127 | +* Forking `hyperpolymath/standards` to disable the rule for one repo. |
| 128 | + If a rule is wrong for one repo, the rule needs scoping in the |
| 129 | + upstream, not a fork. |
| 130 | + |
| 131 | +== Cross-references |
| 132 | + |
| 133 | +* `docs/HYPATIA-BASELINE-FORMAT.adoc` — the baseline file format. |
| 134 | +* `.machine_readable/hypatia-baseline.schema.json` — machine schema. |
| 135 | +* `hyperpolymath/standards#????` — proposal that landed this consumer. |
| 136 | +* `hyperpolymath/hypatia` — the scanner that emits findings. |
0 commit comments