Repository navigation
Fleet-wide stub drift auto-remediation: DRY_RUN-gated, pilot-first PRs that re-sync consumer stubs to canon #1148
Description
Close the detect→remediate gap in the fleet stub-drift reconciliation loop. Drift detection (fleet_stub_drift.sh, driven by fleet_monitor.sh) and CI-time drift-guard (#983) already exist and emit the DRIFTED set; the drift-guard on the template (#983) and the bootstrap wrapper (#972) landed the detect and initial-scaffold steps. What is missing is automated remediation: when a consumer repo's thin-caller stub (today: initiative-planner.yml, initiative-driver.yml) drifts from the canonical org template, a human must manually open a fix PR (#863, #910, #944 are current open cases). This initiative adds a remediation driver that, for each DRIFTED stub, opens an auditable PR in the consumer repo carrying the canonical bytes — as a proposal through the normal PR-review pipeline, never a direct push.
Built from existing components: the DRIFTED set (fleet_stub_drift.json), the canonical source of record (petry-projects/.github standards/workflows/.yml — the exact bytes/SHA drift is measured against), the cross-repo branch+contents-PUT+PR pattern already in seed-repo-template.sh, and a never-overwrite allowlist mirroring template_stub_drift.sh's TEMPLATE_DRIFT_ALLOWLIST. Because the tracked fleet stubs are deployed verbatim, PUTting the canonical bytes makes the consumer blob SHA equal canon — remediation is deterministic and reproducible.
Success metrics (how we know it worked): (1) for the pilot repo, 100% of its DRIFTED tracked stubs are corrected by a single auto-opened PR within one monitor cycle, and re-running the monitor reports them ALIGNED; (2) manual toil per drift issue drops from ~30 min (branch, copy content, open PR) to zero human effort to author the PR; (3) zero allowlisted / intentionally-customized files are ever modified; and, once fleet-wide is enabled, (4) a fleet-wide steady-state metric — mean time-to-ALIGNED across the fleet after a stub drifts — trends down versus the manual baseline.
Cost cap / blast-radius bound: DRY_RUN is the default at every layer; live remediation is restricted to a single named pilot repo until an explicit human go/no-go, with a per-run cap of at most one PR per consumer repo and a small REMEDIATE_MAX_REPOS ceiling on repos touched per run. Scheduled monitor runs never remediate live — going live requires an explicit workflow_dispatch input.
Safety posture (per the idea's adversarial review): no new attack surface beyond existing cross-repo dev-lead ops; PRs are deterministic, auditable proposals reviewed by the normal pipeline; the allowlist protects customized files; pilot-first + human go/no-go bound the rollout.
Related: #983 (drift-guard CI, landed), #972 (bootstrap wrapper, landed), #1008/#1036 (canary-rollout onboarding of the same reusables). Current DRIFTED cases usable as validation targets: #863, #910, #944.
Untracked prerequisites
- Confirm the credential the remediation step runs under has cross-repo
contents:write+pull_requests:writeon target consumer repos. seed-repo-template.sh assumes a GH_TOKEN withreposcope, but actions-fleet-monitor.yml runs fleet_monitor.sh under a read-oriented GH_TOKEN (with GH_PAT_FALLBACK) and only uses GH_PAT_WORKFLOWS for repository_dispatch — not cross-repo file writes. Identify/confirm the GitHub App or PAT with write on consumers before live remediation.
Planned from idea discussion #1043 by the BMAD Scrum Master initiative-planner. Inert until a maintainer adds initiative:auto.
Activity
don-petry commentedon Jul 14, 2026
Reconciled + activated (2026-07-13)
Verified against
main: detection (fleet_stub_drift.sh,template_stub_drift.sh) exists; no remediation driver exists — all 4 phases are genuine. Activating.[DEFERRED-Q for maintainer] — the untracked prerequisite: which credential runs the live remediation step?
fleet_monitor.shruns under a read-oriented GH_TOKEN (+ GH_PAT_FALLBACK) and only uses GH_PAT_WORKFLOWS forrepository_dispatch, not cross-repo file writes. Live remediation needs a GitHub App or PAT withcontents:write+pull_requests:writeon consumer repos. This blocks only Phase 3/4 (live pilot); Phase 1 (#1149 pure plan builder) and Phase 2 (#1150 DRY_RUN driver, idempotent) proceed without it. Please confirm the write credential before the Phase-4 go/no-go.Activated for dev-lead (DRY_RUN-safe): #1149, #1150. #1151 (pilot scope) and #1152 (live wiring behind human go/no-go) will queue behind them and are gated on the credential above.
Adding
initiative:auto. — Claude Codedon-petry commentedon Jul 14, 2026
[DEFERRED-Q RESOLVED] Live-remediation credential =
${{ secrets.GH_PAT }}Maintainer decision (2026-07-13): the Phase 3/4 live cross-repo remediation step runs under
${{ secrets.GH_PAT }}, which carriescontents:write+pull_requests:writeon the consumer repos (the same class of PATseed-repo-template.shassumes). This replaces the read-orientedGH_TOKEN/GH_PAT_FALLBACKthat scheduledfleet_monitor.shruns under.Wiring guidance for #1152 (the fleet-monitor wiring): pass
GH_PATonly into the opt-in,workflow_dispatch-gated live-remediation job — scheduled monitor runs stay read-only and never remediate. Phase 1 (#1149) and Phase 2 (#1150, DRY_RUN) need no write credential and can proceed now. The Phase-4 go/no-go remains a human decision. — Claude Codedon-petry commentedon Jul 16, 2026
Epic complete — fleet-wide stub-drift auto-remediation delivered (Phases 1–4)
All four phases merged:
Safety posture (delivered, DRY-run-safe): the loop proposes canonical stub bytes as one PR per repo (never direct-push), and is dormant by default. Live remediation requires ALL of — an explicit
workflow_dispatch remediate=live+ theGH_PAT_WORKFLOWScredential + a configuredvars.FLEET_REMEDIATE_PILOT_REPO— with a per-run cap; any missing precondition degrades to dry-run with a::warning::, andcontinue-on-errormeans it can never fail the daily monitor. Scheduled/workflow_call runs are DRY_RUN unconditionally.Still gated (separate human step, not part of this epic): enabling an actual live pilot run — set
vars.FLEET_REMEDIATE_PILOT_REPOand dispatch the monitor withremediate=live. That first live pilot is its own go decision. Go/no-go for the wiring recorded on #1152.