Skip to content

fix(automerge): gate fleet CI templates (templates/ci-workflows/**)#117

Merged
topcoder1 merged 1 commit into
mainfrom
claude/gate-fleet-ci-templates
Jul 16, 2026
Merged

fix(automerge): gate fleet CI templates (templates/ci-workflows/**)#117
topcoder1 merged 1 commit into
mainfrom
claude/gate-fleet-ci-templates

Conversation

@topcoder1

Copy link
Copy Markdown
Owner

Closes an inverted blast radius in the risk-tier regex.

The gap

The regex knew .github/workflows/** — the rendered artifact — but not templates/ci-workflows/**, its source. So each repo's copy of pr-review.yml was gated across 45 repos, while the template that feeds all 45 was not.

Not theoretical: dotclaude#157 edited the caller template every repo inherits and auto-merged ~90s after opening, unreviewed. I twice told the user it needed their click; the enforcement disagreed. Same class as the .github/dependabot.yml gap (6 fleet PRs self-merged in ~90s, 2026-07-10): policy prose ≠ enforcement glob.

Why the central regex, not risk-paths.yml

Repo-specific paths normally belong in a caller's .github/risk-paths.yml (techrecon#405). That lever does not exist here: dotclaude installs no pr-classify.yml (no classify check runs on it), so no risk:* label is ever applied and the global regex is the only gate.

It's also not a repo quirk. The policy already treats .github/workflows as production infra; this is the source of that file fleet-wide — the same category, one level up.

scripts/ is the sharper half: merge-workflow-only-pr.sh drops branch protection, rotate-*-key.sh rotates fleet credentials.

Lockstep contract honored

file change
.github/workflows/claude-author-automerge.yml +^templates/ci-workflows/.*
selftest/test_automerge_risk_patterns.sh mirrored
selftest/risk_patterns_corpus.txt +4 RISKY, +3 SAFE

3 SAFE counter-cases pin that the glob does not over-block neighbours: templates/email/welcome.html, templates/ci-workflows-notes.md, docs/ci-workflows/overview.md.

⚠️ Merge order

Merge dotclaude#159 FIRST (the BB half). The corpus is shared; its 4 new RISKY: entries assert against bb-automerge.py, which lives in dotclaude. test_bb_automerge_risk_patterns.sh resolves it from $HOME/.claude/..., so it is local-only and not run in CI — this repo's CI will stay green while a local BB run goes red. test_workflow_guards.py deliberately excludes it.

Verification

  • GH selftest: 4 new RISKY match, 3 SAFE don't → OK: all risk-pattern cases pass
  • BB selftest, unpatched bb-automerge.py: 4 FAILs (risky->safe) — drift caught exactly as the shared corpus intends
  • BB selftest, patched: PASS — all 173 cases (was 166)

Auto-merge rationale: MANUAL MERGE — fleet automerge policy enforcement; topcoder1/ci-workflows PRs are always manual by design.

🤖 Generated with Claude Code

The risk-tier regex knew .github/workflows/** (the rendered artifact) but not
templates/ci-workflows/** (its SOURCE). Inverted blast radius: each repo's copy
of pr-review.yml was gated on 45 repos, while the template feeding all 45 was
not — so dotclaude#157 (which edited the caller template every repo inherits)
auto-merged ~90s after opening, with no human review.

dotclaude installs no pr-classify.yml, so .github/risk-paths.yml cannot gate it
there; the global regex is the only lever. This is not a repo-specific quirk:
the policy already treats .github/workflows as production infra, and this is
the source of that file fleet-wide.

scripts/ is the sharper half — merge-workflow-only-pr.sh drops branch
protection and rotate-*-key.sh rotates fleet credentials.

Mirrored per the lockstep contract: reusable regex + selftest mirror + shared
corpus (4 RISKY). 3 SAFE counter-cases pin that the glob does not over-block
neighbours (templates/email/**, templates/ci-workflows-notes.md,
docs/ci-workflows/**).

BB half ships in dotclaude (bb-automerge.py) — MERGE THAT FIRST; the corpus is
shared, and test_bb_automerge_risk_patterns.sh is local-only (not in CI), so it
goes red locally until both land. Verified: BB unpatched = 4 FAILs, patched =
PASS 173/173.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
@github-actions github-actions Bot added the risk:blocked Risk class: blocked label Jul 16, 2026
@github-actions

Copy link
Copy Markdown

Risk class: blocked — manual merge required.

This PR touches one of the blocked path categories from .github/risk-paths.yml (Dockerfiles, docker-compose, .github/workflows/**, **/.env*, **/secrets*, infra/, terraform/, k8s/, or the classifier config itself).

Auto-merge is refused by claude-author-automerge.yml. A maintainer should review the diff and click "Squash and merge" themselves.

(This is a policy notice, not a code-quality failure. The classify job itself does not fail — required CI checks remain authoritative for "is the code green.")

@github-actions

Copy link
Copy Markdown

Coverage Floor — mode: enforce

metric value
measured 100.0%
floor (current) 99.0%
target 100.0%
last bumped 2026-05-12

@claude

claude Bot commented Jul 16, 2026

Copy link
Copy Markdown

No issues found. Regex added in lockstep across workflow + selftest; corpus RISKY/SAFE cases verified (incl. the templates/ci-workflows-notes.md near-miss that must not match).

@topcoder1
topcoder1 merged commit 28dca25 into main Jul 16, 2026
13 checks passed
@topcoder1
topcoder1 deleted the claude/gate-fleet-ci-templates branch July 16, 2026 07:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

risk:blocked Risk class: blocked

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant