Skip to content

Commit 40ef6bf

Browse files
fix(ci): disarm the Inbox Steward notification amplifier (#451)
`check_suite:[completed]` and `workflow_run:[completed]` made this fire **once per CI completion** on every watched workflow — the mechanism behind the 2026-07-20/21 notification burst (**3,041 CheckSuite notifications in a ~19-hour window**, none since). The workflow is `disabled_manually` today, which is why it stopped. That makes the risk **latent, not resolved** — these triggers plus `contents: write`/`pull-requests: write` mean re-enabling restarts the multiplier. Removed so that re-enabling is safe. `pull_request`, `pull_request_review` and `workflow_dispatch` retained. **Verified:** YAML parses; trigger map is now exactly `pull_request, pull_request_review, workflow_dispatch`. 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
1 parent 34406ad commit 40ef6bf

16 files changed

Lines changed: 87 additions & 43 deletions

File tree

.github/workflows/dogfood-gate.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ jobs:
4343
4444
- name: Validate A2ML manifests
4545
if: steps.detect.outputs.count > 0
46-
uses: hyperpolymath/a2ml-validate-action@05bcb78917c09702e90ed18004298a6728753914 # main
46+
uses: hyperpolymath/a2ml-ecosystem/validate-action@aa4b836bd969df2bc58128cb8e3d20bbc88d5e79 # main
4747
with:
4848
path: '.'
4949
strict: 'false'
@@ -105,7 +105,7 @@ jobs:
105105
106106
- name: Validate K9 contracts
107107
if: steps.detect.outputs.k9_count > 0
108-
uses: hyperpolymath/k9-validate-action@bddcd9109ee96f9ea3fdb4bf51084fe9cd0909ce # main
108+
uses: hyperpolymath/k9-ecosystem/validate-action@89f3c2702f4f650a92aa7411502f38da06abd562 # main
109109
with:
110110
path: '.'
111111
strict: 'false'

.github/workflows/inbox-steward.yml

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -21,15 +21,12 @@ on:
2121
types: [opened, synchronize, ready_for_review, converted_to_draft, review_requested]
2222
pull_request_review:
2323
types: [submitted, dismissed]
24-
check_suite:
25-
types: [completed]
26-
workflow_run:
27-
workflows:
28-
- Dogfood Gate
29-
- Scorecard Enforcer
30-
- Hypatia Security Scan
31-
- Static Analysis Gate
32-
types: [completed]
24+
# AMPLIFIER REMOVED 2026-07-29. check_suite:[completed] and
25+
# workflow_run:[completed] made this fire once per CI completion on every
26+
# watched workflow -- a multiplier on every unit of estate CI activity, and
27+
# the mechanism behind the 3,041-notification burst of 2026-07-20/21.
28+
# The workflow is currently disabled_manually; these triggers are removed so
29+
# that RE-ENABLING it is safe. PR/review events and workflow_dispatch remain.
3330
# Manual trigger
3431
workflow_dispatch:
3532
inputs:
@@ -430,6 +427,7 @@ jobs:
430427
summary:
431428
name: Generate stewardship summary
432429
runs-on: ubuntu-latest
430+
timeout-minutes: 5
433431
needs: [identify-passed-prs, validate-prs, auto-merge-prs]
434432
if: always()
435433

.github/workflows/push-email-notify.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ jobs:
1313
name: Email on push
1414
if: ${{ vars.PUSH_EMAIL_ENABLED == 'true' }}
1515
runs-on: ubuntu-latest
16+
timeout-minutes: 10
1617
steps:
1718
- name: Send push notification email
1819
uses: dawidd6/action-send-mail@c50dc4cc848ade21f848990889906d804fae78c5 # pinned

bots/accessibilitybot/src/analyzers/contrast.rs

Lines changed: 21 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,21 @@ use crate::analyzers::Analyzer;
1010
use crate::fleet::{Finding, ImpactAssessment, Severity, WcagLevel};
1111
use regex::Regex;
1212
use std::path::Path;
13+
use std::sync::LazyLock;
14+
15+
// Compiled once. These were rebuilt on every call (hypatia expect_in_hot_path).
16+
static COLOR_RE: LazyLock<Regex> =
17+
LazyLock::new(|| Regex::new(r"(?i)(?:^|;|\{)\s*color\s*:\s*([^;}\n]+)").expect("valid regex"));
18+
static BG_RE: LazyLock<Regex> =
19+
LazyLock::new(|| Regex::new(r"(?i)background(?:-color)?\s*:\s*([^;}\n]+)").expect("valid regex"));
20+
static BLOCK_RE: LazyLock<Regex> =
21+
LazyLock::new(|| Regex::new(r"([^{]+)\{([^}]+)\}").expect("valid regex"));
22+
static STYLE_RE: LazyLock<Regex> =
23+
LazyLock::new(|| Regex::new(r#"style\s*=\s*"([^"]+)""#).expect("valid regex"));
24+
static COLOR_RE_4: LazyLock<Regex> =
25+
LazyLock::new(|| Regex::new(r"(?i)(?:^|;)\s*color\s*:\s*([^;]+)").expect("valid regex"));
26+
static BG_RE_5: LazyLock<Regex> =
27+
LazyLock::new(|| Regex::new(r"(?i)background(?:-color)?\s*:\s*([^;]+)").expect("valid regex"));
1328

1429
/// Contrast analyzer for CSS color pairs
1530
pub struct ContrastAnalyzer;
@@ -133,15 +148,11 @@ pub fn contrast_ratio(fg: (u8, u8, u8), bg: (u8, u8, u8)) -> f64 {
133148
/// Analyze CSS content for contrast issues
134149
fn analyze_css(path: &Path, content: &str) -> Vec<Finding> {
135150
let mut findings = Vec::new();
136-
let color_re = Regex::new(
137-
r"(?i)(?:^|;|\{)\s*color\s*:\s*([^;}\n]+)"
138-
).expect("valid regex");
139-
let bg_re = Regex::new(
140-
r"(?i)background(?:-color)?\s*:\s*([^;}\n]+)"
141-
).expect("valid regex");
151+
let color_re = &*COLOR_RE;
152+
let bg_re = &*BG_RE;
142153

143154
// Extract color/background-color pairs within CSS rule blocks
144-
let block_re = Regex::new(r"([^{]+)\{([^}]+)\}").expect("valid regex");
155+
let block_re = &*BLOCK_RE;
145156

146157
for caps in block_re.captures_iter(content) {
147158
let selector = caps[1].trim();
@@ -211,9 +222,9 @@ fn analyze_css(path: &Path, content: &str) -> Vec<Finding> {
211222
/// Analyze inline styles in HTML for contrast issues
212223
fn analyze_inline_styles(path: &Path, content: &str) -> Vec<Finding> {
213224
let mut findings = Vec::new();
214-
let style_re = Regex::new(r#"style\s*=\s*"([^"]+)""#).expect("valid regex");
215-
let color_re = Regex::new(r"(?i)(?:^|;)\s*color\s*:\s*([^;]+)").expect("valid regex");
216-
let bg_re = Regex::new(r"(?i)background(?:-color)?\s*:\s*([^;]+)").expect("valid regex");
225+
let style_re = &*STYLE_RE;
226+
let color_re = &*COLOR_RE_4;
227+
let bg_re = &*BG_RE_5;
217228

218229
for (line_num, line) in content.lines().enumerate() {
219230
if let Some(style_caps) = style_re.captures(line) {

0 commit comments

Comments
 (0)