ci(fork-sync): sync-PR composite audit workflow (H10) (#2441)#2447
Merged
alexey-pelykh merged 1 commit intomainfrom Apr 21, 2026
Merged
ci(fork-sync): sync-PR composite audit workflow (H10) (#2441)#2447alexey-pelykh merged 1 commit intomainfrom
alexey-pelykh merged 1 commit intomainfrom
Conversation
Final child issue of the #2433 hardening epic. Adds a composite audit workflow that runs ONLY on upstream sync PRs — re-invokes the universal H7/H8/H9 gates with verbose reporting and aggregates their verdicts into a single reviewer-facing check. The underlying H7/H8/H9 gates are already enforced on every PR via ci.yml. This workflow is additive reporting — it does not bypass or replace any existing gate. Value-add is purely UX: reviewers triaging a 500-to-2500-commit sync PR get all three audit verdicts + an attestation diff in one place, instead of hunting through 7 separate CI jobs. Scope: - .github/workflows/sync-pr-audit.yml (128 LOC): triggers on PR title prefix `sync:`; runs H7 strict + inventory, H8, H9, and H9 diff in sequence with continue-on-error + if:always() so failures don't short-circuit the composite view - scripts/check-attestations-diff.mjs (184 LOC): AST-parses MODULE_ATTESTATIONS at base and head via TypeScript compiler, reports per-entry category transitions in markdown tables. Uses shared ts-guard-utils helpers (isTestLikeTypeScriptFile, unwrapExpression). - CONTRIBUTING.md § Sync PR workflow: documents trigger semantics, report composition, branch-protection caveat Branch protection posture: advisory by default. GitHub branch protection treats skipped required checks as blocking, so this workflow cannot be a blanket required check. Recommended path: GitHub Rulesets with conditional requirements (required only when PR title matches `sync:*`). The underlying H7/H8/H9 gates on ci.yml remain enforced universally, so merge is still blocked when they fail. Validation (fresh-context subprocess, session 346848b0) initially found 5 blockers + 1 non-blocking: 1. Broken awk script → replaced with AST-parsing check-attestations-diff.mjs 2. bash `set -e` / pipefail broke exit-code capture → continue-on-error + if:always() 3. Missing CONTRIBUTING.md section → added 4. Branch-protection interaction undocumented → documented in workflow header + CONTRIBUTING.md 5. Unused pull-requests:write permission → dropped (+ non-blocking stale awk comment in workflow → also fixed) All addressed; re-validated CLEAN. Polish (fresh-context subprocess, session 2811e6be): CLEAN after 3 iterations. Net -30 LOC (-7%) via DRY refactors: - Diff script: reused isTestLikeTypeScriptFile + unwrapExpression from ts-guard-utils (eliminated duplicate test-suffix filter + AST unwrap) - Merged Composite summary + Composite exit into single step - Dropped broken h9_diff row in summary (diff is advisory, not gated) - Extracted shared failure condition to single $failed variable - Aligned convention with sibling scripts (runAsScript vs direct main) Dry-run verification: - `node scripts/check-attestations-diff.mjs 028566c 511ae3a` correctly reports all attestation additions from the #2437 landing commit (93 modules × up to 28 symbols each) - `node scripts/check-attestations-diff.mjs main main` correctly reports "No attestation changes between base and HEAD" - Real dry-run on a future sync PR: will verify after merge Closes #2441. With this, all 4 active-path child issues of the #2433 epic (H7 via #2435, H8 via #2436, H9 via #2437, H10 via this PR) are delivered. HQ ADR 0005 H10 update + epic closure notes will follow in a companion HQ commit.
This was referenced Apr 21, 2026
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.
Summary
Final child issue of the #2433 hardening epic. Adds a composite audit workflow that runs ONLY on upstream sync PRs — re-invokes the universal H7/H8/H9 gates with verbose reporting and aggregates their verdicts + an attestation diff into a single reviewer-facing check.
This workflow does NOT bypass or replace any existing gate. The underlying H7/H8/H9 gates already run on every PR via
ci.yml. This workflow is additive UX — triage a 500-to-2500-commit sync PR in one place instead of hunting through 7+ separate CI jobs.Trigger
PR title starts with
sync:(matches project convention:sync: upstream to v2026.3.22,sync: upstream to v2026.3.13-1, etc.).What the audit reports
scripts/check-throwing-stub-callers.mjsscripts/check-throwing-stub-callers.mjs --inventoryscripts/check-stub-debt.mjsscripts/check-attestations.mjsscripts/check-attestations-diff.mjs(new)Each gate runs with
continue-on-error: true+if: always()so a single failure does NOT short-circuit the others — reviewers see all three verdicts.Branch protection posture
Advisory by default. GitHub branch protection treats skipped required checks as blocking, so this workflow cannot be a blanket required check (it skips on non-sync PRs). Recommended enforcement path: GitHub Rulesets with conditional requirements (required only when PR title matches
sync:*). The underlying H7/H8/H9 gates onci.ymlremain enforced universally.Changes
.github/workflows/sync-pr-audit.yml(128 LOC): trigger + composite jobscripts/check-attestations-diff.mjs(184 LOC): AST-parsesMODULE_ATTESTATIONSat base and head, reports per-entry category transitions in markdown tables. Uses sharedts-guard-utilshelpers (isTestLikeTypeScriptFile,unwrapExpression).CONTRIBUTING.md§ Sync PR workflow: trigger semantics, report composition, branch-protection caveatVerification
pnpm checknode scripts/check-attestations-diff.mjs 028566c42b 511ae3a539node scripts/check-attestations-diff.mjs main mainNo attestation changes between base and HEADFresh-context validation (session 346848b0)
Initial pass found 5 blockers + 1 non-blocking:
check-attestations-diff.mjsset -e/pipefailbroke exit-code capture on gate failure → continue-on-error + if:always() patternpull-requests: writepermission → dropped (now onlycontents: read)All addressed; re-validated CLEAN.
Polish iterations (session 2811e6be, 3 iterations)
CLEAN after DRY refactors:
ts-guard-utilshelpers in diff script (eliminated duplicate test-suffix filter + AST unwrap logic)$failedvariable (DRY)runAsScriptvs directmaininvocation)Net: -30 LOC (-7%) from initial version.
Epic closure
With this PR, all 4 active-path children of #2433 are delivered:
Deferred (with revisit triggers): #2438 (mock ablation), #2439 (reflective factory), #2440 (mock allowlist).
Test plan
pnpm checkcleanCloses #2441.