ci: resolve the allowlist baseline against the real base branch

The allowlist-closed diff hardcoded `origin main`, but ship-ci.yml also runs
this workflow for PRs into release/** and for pushes to release/**, where a
main baseline diffs against the wrong branch and can fail changes that have
nothing to do with the allowlist. It now resolves the base:

  PR   -> github.event.pull_request.base.ref (the branch it merges into)
  push -> github.ref_name (the branch itself; its tip already contains the
          change, so the diff is a no-op — enforcement happens at PR time)

Also from review, all documentation drift introduced by my own earlier
commits:

- The layer count said "three" in the module docstring, the workflow comment,
  the docs, and the changelog. There are four (allowlist-closed was added).
- The changelog listed three scanned modules; there are five.
- The docs and changelog stated the rule for keys core *reads*, omitting
  writes — which are equally gated, and land in every pack we emit.
- The CI summary line labelled grandfathered keys "pending spec", implying
  adoption is the only resolution. For original_audio it is not: the fix is
  removal. Relabelled "grandfathered (tracked debt)".
- feedpak-spec-exceptions.yml said an entry clears when core "stops reading"
  the key; the rule is "no longer reads or writes".
- Replaced a bitwise `&` over two bools with two named results and an
  explicit `and` — both checks must run (a stale READERS list and an
  undeclared key are separate failures; short-circuiting would hide one), and
  `&` reads like a typo.

Signed-off-by: topkoa <topkoa@gmail.com>
This commit is contained in:
topkoa
2026-07-13 00:32:24 -04:00
parent d806d12c22
commit ab2e68a638
5 changed files with 775 additions and 751 deletions
+7 -2
View File
@@ -305,7 +305,7 @@ def check_key_coverage(spec: Path) -> bool:
print(f" spec declares {len(declared)} keys; core reads {len(reads)}, writes {len(writes)}")
if exceptions:
print(f" allowlisted (pending spec): {', '.join(sorted(exceptions))}")
print(f" grandfathered (tracked debt): {', '.join(sorted(exceptions))}")
print(f" key-coverage: {'OK' if ok else 'FAILED'}")
return ok
@@ -417,7 +417,12 @@ def main() -> int:
return 1
print("[1/4] key-coverage — core reads/writes only keys the spec declares")
ok1 = check_readers_complete() & check_key_coverage(spec)
# Both run, always: a stale READERS list and an undeclared key are separate
# failures, and reporting only the first would hide the second. Hence two
# calls and an explicit `and` over the results, not a short-circuiting one.
readers_ok = check_readers_complete()
coverage_ok = check_key_coverage(spec)
ok1 = readers_ok and coverage_ok
print("[2/4] allowlist-closed — the grandfather list may shrink, never grow")
ok2 = check_allowlist_closed(args.baseline_exceptions, args.bootstrap_allowlist)
print("[3/4] forward — core ingests the spec's example packs")