# SPDX-License-Identifier: MPL-2.0
# Estate-wide Reusable-Workflow Convergence Campaign — 2026-05-26 (closeout)
# Copyright (c) 2026 Jonathan D.A. Jewell (hyperpolymath)
#
# Machine-readable companion to audit-reusables-convergence-2026-05-26.adoc.
# Schema follows the existing docs/audits/ a2ml convention.

[manifest]
schema             = "audit/reusables-convergence/v1"
date               = "2026-05-26"
session_id         = "20f9dd81-1ded-474b-b579-61e1b8aba08b"
campaign_kind      = "estate_reusable_convergence + stale_BP_cleanup + stuck_PR_recovery"
authoring_actor    = "claude-opus-4-7 (1M context)"
authorising_actor  = "hyperpolymath (org admin)"
human_companion    = "audit-reusables-convergence-2026-05-26.adoc"
supersedes_section = "standards#199 inventory (its survey methodology remains canonical)"

[motivation]
primary    = "Land the remaining 5 reusable-workflow extractions identified by standards#199 (mirror, secret-scanner, codeql, hypatia-scan, scorecard) plus their per-repo wrapper sweeps."
secondary  = "Unblock the standards/main PR queue (~19 PRs reporting state=blocked despite green CI)."
tertiary   = "Recover the 7 still-open rust-ci wrapper PRs from the prior session (project_rust_ci_wrapper_sweep_2026_05_26)."
pattern    = "estate-template-propagation-pattern"
prior_applications = ["standards#168 governance/language-policy", "standards#174 rust-ci + elixir-ci"]

[branch_protection_discovery]
finding            = "standards/main required a status-check context ('Check Required Files') that no workflow produces; every open PR examined was mergeable=true mergeable_state=blocked."
prs_unblocked      = 19
fix_method         = "gh api -X DELETE repos/hyperpolymath/standards/branches/main/protection/required_status_checks/contexts -f 'contexts[]=Check Required Files'"
permanent_change   = true
post_fix_required_contexts = 14
pre_fix_required_contexts  = 15

[outcome]
reusables_merged          = 2     # #187, #190
reusables_ci_burnin       = 3     # #192, #193, #205
wrapper_prs_filed_total   = 569
wrapper_prs_filed_mirror  = 288
wrapper_prs_filed_secret  = 281
wrapper_prs_admin_merged  = 0
auto_merge_on_pct         = 100.0
stuck_pr_recovery_total   = 7
stuck_pr_recovery_landed  = 7
bp_rule_cleanups_total    = 7

[reusables.187_mirror]
state                  = "merged"
squash_sha             = "e6b2884722350515934d443daf23442f2195796f"
sweep_filed            = 288
sweep_ok               = 288
sweep_fatal            = 0
rate_limit_triggered   = false

[reusables.190_secret_scanner]
state                  = "merged"
squash_sha             = "3e4bd4c93911750727e2e4c66dff859e00079da0"
sweep_filed            = 281
sweep_ok_initial       = 208
sweep_rate_limited     = 72
sweep_recovered_slow   = 58
sweep_recovered_final  = 14
sweep_ok_final         = 281
sweep_fatal_final      = 0
incident_carryover     = "Carries the shell-secrets guardrail added after the 2026-05-21 Cloudflare API-token leak."

[reusables.192_codeql]
state                  = "ci_burnin"
estate_deploys         = 273
worker_path            = "/tmp/codeql-worker.sh"
inventory_path         = "/tmp/codeql-deploys-noforks.tsv"
pin_sha_pending        = true

[reusables.193_hypatia_scan]
state                  = "ci_burnin"
estate_deploys         = 180
worker_path            = "/tmp/hypatia-worker.sh"
inventory_path         = "/tmp/hypatia-deploys-noforks.tsv"
pin_sha_pending        = true
note                   = "Down from ~264 because the prior admin-merge wave landed those wrappers."

[reusables.205_scorecard]
state                  = "ci_burnin"
estate_deploys         = 258
worker_path            = "/tmp/scorecard-worker.sh"
inventory_path         = "/tmp/scorecard-deploys-noforks.tsv"
pin_sha_pending        = true

[rate_limit_incident]
api                    = "GitHub GraphQL createPullRequest"
limit_type             = "secondary"
hit_at_pr_count        = 208
affected_branches      = 72
remediation_strategy_1 = "Fast-retry — ineffective (limit sticky)"
remediation_strategy_2 = "Slow-serial retry @ 30s/call → 58/72 recovered as limit lifted partway"
remediation_strategy_3 = "Final batch retry @ 4s/call → 14/14 recovered"
empirical_threshold    = "~5 createPullRequest calls per 30s sustainable; ~280 in <30 min triggers the block"
recommendation         = "Future bulk-PR sweeps: throttle to 5 calls per 30s steady-state."

[stuck_pr_recovery.rust_ci]
total                  = 7
landed                 = 7
bp_cleared             = 3   # 007#17, presswerk#41, rsr-template-repo#70
refiled                = 4   # absolute-zero, kategoria-pipeline, nextgen-typing, proof-burrower
secondary_bp_clears    = 3   # kategoria-pipeline, nextgen-typing, proof-burrower (same stale cluster)
worker_path            = "/tmp/wrapper-rebase/refile-one.sh"

[[stuck_pr_recovery.rust_ci.bp_cleared]]
repo = "hyperpolymath/007"
old_pr = 17
dropped_contexts = ["check-critical", ".github/dependabot.yml", "rhodibot", "validate"]
final_state = "merged"

[[stuck_pr_recovery.rust_ci.bp_cleared]]
repo = "hyperpolymath/presswerk"
old_pr = 41
dropped_contexts = ["gitleaks", "governance / Code quality + docs", "governance / Guix primary / Nix fallback policy", "governance / Language / package anti-pattern policy", "governance / Security policy checks", "governance / Well-Known (RFC 9116 + RSR)", "governance / Workflow security linter", "Hypatia Neurosymbolic Analysis", "rust-secrets", "trufflehog"]
final_state = "merged"

[[stuck_pr_recovery.rust_ci.bp_cleared]]
repo = "hyperpolymath/rsr-template-repo"
old_pr = 70
dropped_contexts = ["analysis", "antipattern-check", "check", "dispatch", "docs", ".github/dependabot.yml", "lint", "mirror-codeberg", "mirror-gitlab", "mirror-sourcehut", "validate"]
final_state = "merged"

[[stuck_pr_recovery.rust_ci.refiled]]
repo = "hyperpolymath/absolute-zero"
old_pr = 45
new_pr = 53
final_state = "merged"
merge_method = "manual (no required-checks BP, so auto-merge unavailable)"

[[stuck_pr_recovery.rust_ci.refiled]]
repo = "hyperpolymath/kategoria-pipeline"
old_pr = 12
new_pr = 16
final_state = "merged"
merge_method = "auto-merge after secondary BP cleanup"

[[stuck_pr_recovery.rust_ci.refiled]]
repo = "hyperpolymath/nextgen-typing"
old_pr = 9
new_pr = 15
final_state = "merged"
merge_method = "auto-merge after secondary BP cleanup"

[[stuck_pr_recovery.rust_ci.refiled]]
repo = "hyperpolymath/proof-burrower"
old_pr = 15
new_pr = 21
final_state = "merged"
merge_method = "auto-merge after secondary BP cleanup"

[stale_bp_context_clusters]
note = "Each cluster is a set of required-status-check contexts that no workflow currently produces; dropping them is a no-op for actual gating but unblocks the queue."

[stale_bp_context_clusters.standards_main]
context = "Check Required Files"

[stale_bp_context_clusters.governance_legacy]
contexts = ["governance / Code quality + docs", "governance / Guix primary / Nix fallback policy", "governance / Language / package anti-pattern policy", "governance / Security policy checks", "governance / Well-Known (RFC 9116 + RSR)", "governance / Workflow security linter", "Hypatia Neurosymbolic Analysis", "gitleaks", "rust-secrets", "trufflehog"]

[stale_bp_context_clusters.rust_ci_legacy]
contexts = ["check-critical", ".github/dependabot.yml", "rhodibot", "validate"]

[stale_bp_context_clusters.mirror_legacy]
contexts = ["mirror-codeberg", "mirror-gitlab", "mirror-sourcehut"]

[stale_bp_context_clusters.rsr_template_legacy]
contexts = ["analysis", "antipattern-check", "check", "dispatch", "docs", "lint"]

[follow_up_NOT_discharged]
reusables_ci_burnin    = "#192/#193/#205 will auto-merge when CI greens. Their wrapper sweeps then fire via the pre-built workers + inventories on /tmp."
stale_bp_estate_sweep  = "Only 7 repos had stale BP contexts dropped this session. A future sweep enumerating gh api repos/<o>/<r>/branches/main/protection/required_status_checks across the estate would surface the rest."
cloudflare_token_leak  = "Status unverified at Cloudflare. Code fix #161 merged. History rewrite paused pending user confirmation of rotation."

[provenance]
session_log_jsonl   = "~/.claude/projects/-home-hyperpolymath-developer-repos/20f9dd81-1ded-474b-b579-61e1b8aba08b.jsonl"
sweep_workers       = ["/tmp/mirror-wrapper-worker.sh", "/tmp/secret-scanner-worker.sh", "/tmp/codeql-worker.sh", "/tmp/hypatia-worker.sh", "/tmp/scorecard-worker.sh"]
recovery_workers    = ["/tmp/wrapper-rebase/refile-one.sh", "/tmp/retry-pr-create.sh", "/tmp/slow-retry-72.sh"]
sweep_logs          = ["/tmp/mirror-sweep-logs/", "/tmp/secret-sweep-logs/", "/tmp/wrapper-rebase/"]
inventories         = ["/tmp/{mirror,secret,codeql,hypatia,scorecard}-deploys-noforks.tsv"]

[memory_references]
session_campaign       = "session_2026_05_26_reusables_campaign.md"
session_metadata       = "session_2026_05_26_estate_metadata_campaign.md"
admin_merge_predecessor = "project_admin_merge_wrappers_2026_05_26.md"
rust_ci_predecessor    = "project_rust_ci_wrapper_sweep_2026_05_26.md"
auto_merge_policy      = "feedback_always_automerge_prs.md"
fanout_rule            = "feedback_fanout_needs_bash_allowlist.md"
rate_limit_lesson      = "feedback_github_secondary_rate_limit_burst.md"
gpg_signing_rule       = "feedback_all_commits_gpg_signed.md"
template_pattern       = "estate-template-propagation-pattern"

[sibling_reusables]
landed_prior = ["standards#168 governance + deno-ci", "standards#174 rust-ci + elixir-ci"]
landed_this_session = ["standards#187 mirror", "standards#190 secret-scanner"]
ci_burnin_this_session = ["standards#192 codeql", "standards#193 hypatia-scan", "standards#205 scorecard"]
remaining_unclassified = []
