1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
//! `forge-merge-by-hand` — merging a pull request by POSTing to the forge API.
//!
//! `POST /repos/{owner}/{repo}/pulls/{n}/merge` merges. It does not look at
//! check runs, and it answers `200` identically whether the run concluded
//! success, concluded failure, or has not started. The forge's own web UI
//! greys the button out; the API has no such courtesy, and neither does a
//! shell.
//!
//! `gh pr merge` at least prints the check state it saw. A `curl` to the merge
//! endpoint prints an HTTP code, so the one fact that decides whether the
//! merge was safe never enters the transcript at all.
//!
//! ## What makes this a rule rather than advice in a prompt
//!
//! The failure is silent, which is this crate's admission test. A merge onto
//! red is indistinguishable at the call site from a merge onto green — same
//! request, same `200`, same one-line result — so no correcting loop can form
//! from the outcome. It is found later, in `main`, by someone else.
//!
//! It is also the shape a model reaches for once it has improvised the
//! procedure by hand: the poll loop and the merge are both `curl`, the pair
//! works, and every later merge in the session repeats it rather than
//! re-reading the instruction that named a skill for exactly this.
//!
//! ## Measured 2026-09-10, and it is getting worse
//!
//! 221 matches in 34,905 Bash calls across five weeks, per 1,000 calls:
//!
//! ```text
//! 2026-08-10 0.3
//! 2026-08-17 4.7
//! 2026-08-24 4.9
//! 2026-08-31 13.8
//! 2026-09-07 7.1
//! ```
//!
//! That is the opposite of the shapes this crate deliberately does NOT guard.
//! `--no-verify` fell 25.9 → 5.4 and `git add -A` 42.5 → 5.4 once they had
//! consequences a loop could see; both were left alone for it. This one starts
//! near zero and climbs roughly twentyfold, because improvising the procedure
//! WORKS: the merge succeeds, the session continues, and the shape is repeated
//! for every later merge rather than the instruction naming a skill being
//! re-read. Nothing in the outcome argues against it.
//!
//! Ships at `Advise` rather than `Observe` for that reason. The ladder's first
//! rung exists to get a baseline before a rule speaks, and the backtester has
//! now supplied one retroactively — which is what it is for. `Advise` is the
//! untried intervention: this has never once been said out loud at the moment
//! it happened, only written down somewhere read hours earlier.
//!
//! Not `Deny`. Merging through the API is legitimate when the checks really
//! were read first, and a rule that cannot tell the two apart must not be the
//! one to refuse.
//!
//! ## No `confirm`, for `gh-pr-merge-auto`'s reason
//!
//! The question worth asking — did the checks for this head SHA conclude
//! successfully? — is a network round-trip to a forge that may be behind mTLS
//! and may be slow. This runs before every shell command the model issues, and
//! a hook that can hang is worse than a hook that is occasionally imprecise.
//! The reason states the condition; the reader settles it.
//!
//! ## Deliberately not `gh pr merge`
//!
//! That command is the LAST STEP of the documented procedure, so firing on it
//! would fire on correct use. Only the raw endpoint is matched, because
//! reaching for the endpoint is itself the evidence that the procedure was
//! skipped — there is no other reason to hand-write it.
use crate;
use crateParsed;
pub const RULE: Rule = Rule ;