Skip to content

Commit 45ebab9

Browse files
committed
docs(proposal): self-driving PR merge via Hypatia autofix + gitbots
Specify how the Hypatia ruleset and estate gitbots can auto-fix the recurring mechanical CI findings and auto-merge low-risk PRs in future, with risk tiers keeping humans in the loop for policy/semantic changes. Anchors the my-lang side and lists the cross-repo (standards, bot-directive) dependencies. Proposal only; enables no automation. https://claude.ai/code/session_014uKLLhZiAGNayhLjdxGXUx
1 parent 552db95 commit 45ebab9

1 file changed

Lines changed: 153 additions & 0 deletions

File tree

Lines changed: 153 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
1+
<!--
2+
SPDX-License-Identifier: MPL-2.0
3+
SPDX-FileCopyrightText: 2026 Jonathan D.A. Jewell (hyperpolymath)
4+
-->
5+
6+
# Proposal: self-driving PR merge via Hypatia autofix + gitbots
7+
8+
**Status:** proposal (no automation enabled by this document)
9+
**Motivation:** PR #84 demonstrated the gap. Every push re-tripped the *same*
10+
pre-existing, mechanical CI findings, none caused by the PR's diff, and a human
11+
had to reason about each one before merge. This proposal specifies how the
12+
Hypatia ruleset and the estate gitbots can drive that loop themselves in
13+
future — safely, with a human kept in the loop for anything semantic.
14+
15+
This is a **design**. Most of the moving parts live outside `my-lang`
16+
(`hyperpolymath/standards` owns the reusable workflows + the Hypatia ruleset;
17+
the gitbots live in the bot-directive repo), so landing it is a cross-repo
18+
effort. This doc is the `my-lang`-side anchor and the checklist.
19+
20+
## 1. What "do this itself" has to mean
21+
22+
Two distinct capabilities, often conflated:
23+
24+
1. **Auto-fix** — mechanically resolve the recurring, deterministic findings so
25+
they stop blocking (timeouts, SHA-pins, baseline-shape drift).
26+
2. **Auto-merge** — once required checks are green, merge without a human
27+
pressing the button.
28+
29+
Auto-merge without auto-fix just blocks forever on the same findings.
30+
Auto-fix without auto-merge still needs a human to push the button. We want
31+
both, **gated** so only low-risk PRs ever merge unattended.
32+
33+
## 2. The recurring findings, classified
34+
35+
From PR #84's scans, every blocking item fell into one of three buckets:
36+
37+
| Finding | Bucket | Where the fix lives | Auto-fixable? |
38+
|---|---|---|---|
39+
| `missing_timeout_minutes` on `cflite_*`, `checker-scaling`, `codeql`, `governance`, `hypatia-scan`, `mirror` | mechanical | `my-lang/.github/workflows/*` | **Yes** — add `timeout-minutes:` |
40+
| `unpinned_action``standards/...governance-reusable.yml@main` | mechanical-ish | `my-lang/.github/workflows/governance.yml` | Yes, but needs a resolver (pin to SHA + keep updated via Renovate/Dependabot) |
41+
| `Validate Hypatia baseline` shape mismatch (object vs array) | contract drift | `standards` validator **or** `my-lang/.hypatia-baseline.json` | Yes, once the canonical schema is agreed |
42+
| `Language / package anti-pattern` on `frontier-practices/*.res` | policy decision | `my-lang` (port to AffineScript) **or** `.hypatia-ignore` | **No** — needs a human decision |
43+
| `scaling (ubuntu-latest)` linearity guard | flaky/threshold | `my-lang/tests/checker_alloc_scaling.rs` | **No** — needs robustness work (issue #85 item 4) |
44+
45+
**Rule of thumb:** the top three are safe for a bot; the bottom two must never
46+
be auto-resolved (auto-exempting a policy or muting a flaky guard is exactly the
47+
silent-divergence failure mode we want to avoid).
48+
49+
## 3. Hypatia ruleset changes (in `standards`)
50+
51+
The Hypatia finding schema already carries an `action` field (`flag`,
52+
`pin_sha`, …). The proposal:
53+
54+
1. Promote the **mechanical** rules from `action: flag` to `action: autofix`,
55+
each with a deterministic, idempotent fixer:
56+
- `missing_timeout_minutes` → insert a default `timeout-minutes:` (repo-
57+
configurable; e.g. 30 for build/test jobs) on jobs that lack one.
58+
- `unpinned_action` → resolve `@<ref>` to the current `@<sha> # <ref>` and
59+
register the action with the repo's updater so it stays current.
60+
- `hypatia_baseline_shape` → normalise `.hypatia-baseline.json` to the
61+
canonical schema (see §4).
62+
2. Keep **policy** and **flaky** rules at `action: flag` (never autofix):
63+
`banned_language_file`, allocation/perf guards, anything `severity: high|critical`.
64+
3. Emit an autofix **patch artifact** (not a direct push) so the gitbot, not
65+
the scanner, owns the commit — keeps provenance and review trail clean.
66+
67+
## 4. Fix the baseline contract (unblocks a whole class)
68+
69+
`Validate Hypatia baseline` fails because the committed
70+
`.hypatia-baseline.json` is an *object* (`{ _comment, fingerprints: [] }`) while
71+
the validator in `standards` asserts an *array* of finding objects. Pick one
72+
canonical shape in `standards`, then:
73+
74+
- update the `standards` schema + validator and **all** consumer baselines, or
75+
- keep the object shape and fix the validator to accept it.
76+
77+
Either way this is a one-time `standards` change that makes the check pass
78+
deterministically across the estate — and is a precondition for auto-merge,
79+
since it's currently a permanent red.
80+
81+
## 5. Gitbot behaviour (bot-directive repo)
82+
83+
A bot (the existing `finishbot` / `seambot` directive style fits) on
84+
`pull_request` + `check_suite` events:
85+
86+
```
87+
on PR open / synchronize:
88+
1. pull Hypatia autofix patch artifact (§3)
89+
2. if patch non-empty AND PR is bot/low-risk tier:
90+
apply patch as a commit, push to PR branch
91+
3. label the PR with its risk tier (see §6)
92+
4. if tier == auto AND no unresolved `flag`/policy findings:
93+
enable GitHub native auto-merge (squash) # merges when checks go green
94+
5. else:
95+
leave for human review; post a one-line summary of blocking flags
96+
on check_suite completed (success):
97+
GitHub native auto-merge does the merge; nothing else to do
98+
```
99+
100+
Use **GitHub-native auto-merge** as the merge primitive (it already respects
101+
branch protection and required checks) rather than a bot calling the merge API —
102+
that keeps the safety rail (protection) authoritative.
103+
104+
## 6. Risk tiers — what may merge unattended
105+
106+
```
107+
tier: auto → dependency bumps, SHA-pin/timeout autofixes, doc-only,
108+
generated-file refreshes. Auto-merge on green.
109+
tier: assisted → bot applies mechanical autofixes, but a human approves merge.
110+
(default for normal feature PRs like #84)
111+
tier: manual → touches policy, security gates, allocation/perf guards,
112+
or carries any `flag`/high/critical finding. No automation.
113+
```
114+
115+
Tier is derived from changed paths + finding severities; never self-selected by
116+
the PR author. This is what stops a feature PR from silently auto-merging.
117+
118+
## 7. `my-lang`-side changes (the only ones landable here)
119+
120+
These are in scope for this repo and can ship as a small follow-up PR:
121+
122+
- [ ] Add `timeout-minutes:` to `cflite_batch.yml`, `cflite_pr.yml`,
123+
`checker-scaling.yml`, `codeql.yml`, `governance.yml`, `hypatia-scan.yml`,
124+
`mirror.yml` (matches the `coverage.yml` precedent from #84).
125+
- [ ] Decide the `frontier-practices/*.res` policy: port to AffineScript, or add
126+
a rationale'd `.hypatia-ignore` entry. (Human decision — issue #85 item 1.)
127+
- [ ] Harden or tier the `#14` allocation-scaling guard so it isn't flaky on CI
128+
runners (issue #85 item 4).
129+
- [ ] Once `standards` exposes the canonical baseline schema, conform
130+
`.hypatia-baseline.json` to it (issue #85 item 2).
131+
- [ ] After branch protection trusts the green set, enable repo setting
132+
**"Allow auto-merge"** so the gitbot can use native auto-merge.
133+
134+
## 8. Cross-repo dependencies (out of `my-lang` scope)
135+
136+
- `hyperpolymath/standards`: Hypatia ruleset `flag→autofix` promotion + fixers
137+
(§3); baseline schema/validator reconciliation (§4); a reusable
138+
`autofix`/auto-merge workflow consumers can call.
139+
- bot-directive repo: the gitbot logic (§5) + risk-tiering (§6).
140+
141+
## 9. Sequencing
142+
143+
1. Land the `standards` baseline-schema fix (§4) — removes the permanent red.
144+
2. Land the `my-lang` mechanical fixes (§7, first item) — clears the
145+
`missing_timeout_minutes` noise.
146+
3. Promote mechanical Hypatia rules to `autofix` in `standards` (§3).
147+
4. Ship the gitbot tiering + native auto-merge enablement (§5, §6).
148+
5. Resolve the two human-decision items (`.res` policy, scaling guard) so the
149+
estate's required set is permanently green — only then is unattended merge of
150+
`assisted`-tier PRs safe to consider.
151+
152+
Nothing here auto-merges anything until steps 1–4 are in place and a human has
153+
signed off on the tiering policy.

0 commit comments

Comments
 (0)