feat(security): per-package remediation so clean fixes auto-merge - #84
Merged
Conversation
…R-007) The worker bundled every fix into one severity-scoped PR across all packages, and the gate rolled up to a single verdict — so ONE package that fails to build (DriveIQ's docker-extension/ui) held the WHOLE batch of 66 fixes, including ~60 that build clean. Nothing auto-merged. Now remediation is scoped per package/manifest: - security-fix-worker gains a `package_dir` input: filters alerts to that manifest dir, branches `security/fix-<slug>`, fixes only that unit. Empty = whole-repo (backward compatible). - escalate-remediate replaces the per-severity ladder with a per-package sweep: it discovers each manifest dir with a fixable alert and dispatches the worker once per package, processing ALL of them (no early stop). Each package is gated and auto-merged on its own. Result on DriveIQ: frontend + backend fixes auto-merge with no human; only docker-extension/ui (genuinely broken build) is held — with the reason already surfaced on its PR. The residual "floor" for the ADR-006 hard-stop persistence is the first package that stays held. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
ry-ops
added a commit
that referenced
this pull request
Jun 25, 2026
…85) Per-package PRs (#84) were all held NO-GO for the SAME unrelated reason: the worker scoped the FIX to one package, but the gate still built ALL packages and rolled up — so docker-extension/ui's pre-existing build break (vite/plugin-react peer conflict) held DriveIQ's backend and frontend PRs too, even though neither touched it. The per-package split was defeated. run-gate.mjs gains `--scope <dir>`: gate ONLY the package at that manifest dir. The reusable gate workflow takes a `scope` input and the worker passes `package_dir`, so each per-package PR is verified against its own package alone. Verified: on a synthetic monorepo where backend breaks, `--scope frontend` returns GO (would auto-merge) while `--scope backend` returns NO-GO — no cross-contamination. Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
The worker bundled all fixes into one severity-scoped PR across every package, and the gate rolled up to a single verdict (any package FAIL → whole PR NO-GO). On DriveIQ that meant one broken package (
docker-extension/ui) held all 66 fixes hostage — including ~60 that build clean. Nothing auto-merged, which is the opposite of the autonomous behavior intended.Fix — per-package scope
Remediation is now scoped to one buildable unit at a time:
security-fix-worker.ymlgains apackage_dirinput: filters alerts to that manifest dir (dirname(manifest_path),.at root), branchessecurity/fix-<slug>, and fixes only that package. Emptypackage_dir= whole-repo (backward compatible). PR title/merge reflect the scope.escalate-remediate.mjsreplaces the per-severity ladder with a per-package sweep: discovers each manifest dir with a fixable alert and dispatches the worker once per package (severity=all), processing all of them with no early stop. Each package is independently gated and auto-merged on its own.Outcome
On DriveIQ:
frontend+backendfixes auto-merge with no human; onlydocker-extension/ui(genuine build break) is held — and it already says why (gate-observability fix #82). The ADR-006 hard-stop persistence now tracks the first package that stays held as the repo's residual.Verified: manifest→package grouping correct (frontend, backend [requirements.txt + uv.lock], docker-extension/ui, root each route to their own branch); build clean, 42 tests pass.
🤖 Generated with Claude Code