Skip to content

ci(fork-sync): sync-PR composite audit workflow (H10) (#2441)#2447

Merged
alexey-pelykh merged 1 commit intomainfrom
ci/2441-sync-pr-audit-workflow
Apr 21, 2026
Merged

ci(fork-sync): sync-PR composite audit workflow (H10) (#2441)#2447
alexey-pelykh merged 1 commit intomainfrom
ci/2441-sync-pr-audit-workflow

Conversation

@alexey-pelykh
Copy link
Copy Markdown

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

Section Source
H7 throwing-stub-callers (strict) scripts/check-throwing-stub-callers.mjs
H7 inventory (verbose) scripts/check-throwing-stub-callers.mjs --inventory
H8 baselines scripts/check-stub-debt.mjs
H9 attestations scripts/check-attestations.mjs
H9 attestation diff (base...HEAD) scripts/check-attestations-diff.mjs (new)
Composite summary + exit step summary + job exit code

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 on ci.yml remain enforced universally.

Changes

  • .github/workflows/sync-pr-audit.yml (128 LOC): trigger + composite job
  • scripts/check-attestations-diff.mjs (184 LOC): AST-parses MODULE_ATTESTATIONS at base and head, reports per-entry category transitions in markdown tables. Uses shared ts-guard-utils helpers (isTestLikeTypeScriptFile, unwrapExpression).
  • CONTRIBUTING.md § Sync PR workflow: trigger semantics, report composition, branch-protection caveat

Verification

Command Result
pnpm check clean (format + typecheck + lint + custom gates)
node scripts/check-attestations-diff.mjs 028566c42b 511ae3a539 correctly reports 93-module attestation additions from the #2437 landing commit
node scripts/check-attestations-diff.mjs main main No attestation changes between base and HEAD
YAML parse valid (8 steps, 1 job)

Fresh-context validation (session 346848b0)

Initial pass found 5 blockers + 1 non-blocking:

  1. Broken awk script produced empty output on all MODULE_ATTESTATIONS diffs → replaced with AST-parsing check-attestations-diff.mjs
  2. set -e / pipefail broke exit-code capture on gate failure → continue-on-error + if:always() pattern
  3. CONTRIBUTING.md § Sync PR workflow section missing → added
  4. Branch-protection interaction undocumented → documented in workflow header + CONTRIBUTING.md
  5. Unused pull-requests: write permission → dropped (now only contents: read)
  6. Stale awk comment in workflow → fixed

All addressed; re-validated CLEAN.

Polish iterations (session 2811e6be, 3 iterations)

CLEAN after DRY refactors:

  • Reused shared ts-guard-utils helpers in diff script (eliminated duplicate test-suffix filter + AST unwrap logic)
  • Merged Composite summary + Composite exit into single step
  • Extracted shared failure condition to $failed variable (DRY)
  • Aligned convention with sibling scripts (runAsScript vs direct main invocation)

Net: -30 LOC (-7%) from initial version.

Epic closure

With this PR, all 4 active-path children of #2433 are delivered:

H Issue PR Status
H7 AST gate #2435 #2444 ✅ merged
H8 mock baseline #2436 #2445 ✅ merged
H9 attestations #2437 #2446 ✅ merged
H10 composite gate #2441 this PR

Deferred (with revisit triggers): #2438 (mock ablation), #2439 (reflective factory), #2440 (mock allowlist).

Test plan

  • Workflow YAML parses cleanly
  • Diff script produces correct output on synthetic cases (additions, removals, no-change)
  • Pre-commit pnpm check clean
  • Adversarial validation: CLEAN after fixes
  • Polish: CLEAN after simplify iterations
  • Real dry-run on a future sync PR: will verify after merge

Closes #2441.

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.
@alexey-pelykh alexey-pelykh enabled auto-merge (squash) April 21, 2026 07:00
@alexey-pelykh alexey-pelykh merged commit 9801df6 into main Apr 21, 2026
15 checks passed
@alexey-pelykh alexey-pelykh deleted the ci/2441-sync-pr-audit-workflow branch April 21, 2026 07:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

ci(fork-sync): sync-PR composite gate workflow (Option 7)

1 participant