From 2fb3e5b3482e004fabc2931859ee8dbb1a851cd4 Mon Sep 17 00:00:00 2001 From: kavemang Date: Sat, 26 Sep 2026 17:30:24 -0500 Subject: [PATCH] Clarify parity disposition and authority refresh flow --- Tools/PARITY_GOVERNANCE.md | 12 ++++++++++++ Tools/parity_ledger.py | 14 +++++++++++++- Tools/tests/test_parity_ledger.py | 2 ++ 3 files changed, 27 insertions(+), 1 deletion(-) diff --git a/Tools/PARITY_GOVERNANCE.md b/Tools/PARITY_GOVERNANCE.md index 9e7be1b425..13838b39e8 100644 --- a/Tools/PARITY_GOVERNANCE.md +++ b/Tools/PARITY_GOVERNANCE.md @@ -151,6 +151,18 @@ The `add-unpaired-function` diagnostic defines "new" by absence of the platform-qualified owner, name, and arity from the base declaration inventory, not by a changed source line. +The ledger can report that diagnostic while its checked-in twin map still +describes the old source tree. Its pipe-separated finding identity is only a +source-drift diagnostic; it is **not** the platform-qualified, NUL-separated +authority identity accepted by `parity_dispositions.json`. Writing a disposition +does not make a scan against the old map pass. After choosing a remedy below, +run the guarded `--refresh-derived` flow above. That flow derives the current +authority, checks any new one-sided identity against the typed registry and +exact base, and restores both snapshots if the ratchet rejects the change. +Use the identity in the derived `unpaired_functions` set for a disposition, +including its platform prefix; do not copy the `add-unpaired-function|...` +diagnostic into the registry. + 1. Implement and test its Swift/Kotlin twin (required for shared bug fixes and final shared features). 2. Manually add an `experimental` disposition with exact identity/platform, diff --git a/Tools/parity_ledger.py b/Tools/parity_ledger.py index e297408693..2535f1cd80 100644 --- a/Tools/parity_ledger.py +++ b/Tools/parity_ledger.py @@ -2558,8 +2558,15 @@ def build_compact_baseline(result: ScanResult) -> dict: if finding.rule in HARD_FINDING_RULES: continue if finding.rule not in BASELINE_REASONS: + if finding.rule.startswith("add-unpaired-"): + raise ValueError( + f"finding {finding.identity} is source drift against the checked-in twin map, " + "not compact-baseline debt; add an exact typed disposition for the " + "platform-qualified authority identity, then run --refresh-derived" + ) raise ValueError( - f"finding {finding.identity} has no reviewed compact-baseline disposition" + f"finding {finding.identity} cannot enter the compact baseline; " + "resolve the source or authority drift before refreshing derived snapshots" ) grouped[(finding.rule, _finding_domain(finding.path))].append(finding.identity) return { @@ -2815,6 +2822,11 @@ def main(argv: list[str] | None = None) -> int: print("\nActionable source drift:") for item in actionable: print(f" {item.output()}") + print( + "These pipe-separated finding identities are diagnostics, not typed-disposition " + "identities. For an intentional one-sided declaration, use its platform-qualified " + "authority identity in the registry, then run --refresh-derived." + ) print(f"\nScanned {_summary(result)}") return 1 diff --git a/Tools/tests/test_parity_ledger.py b/Tools/tests/test_parity_ledger.py index 00b609719a..1d82af0152 100644 --- a/Tools/tests/test_parity_ledger.py +++ b/Tools/tests/test_parity_ledger.py @@ -180,6 +180,8 @@ def test_compact_authority_drift_names_new_one_sided_declaration(self) -> None: self.assertIn("kotlin", output) self.assertIn("android/app/src/main/java/com/noop/analytics/Engine.kt", output) self.assertIn("aFreshlyInventedOneSidedHelper/1#1", output) + self.assertIn("--refresh-derived", output) + self.assertIn("platform-qualified authority identity", output) def test_compact_authority_drift_uses_declaration_inventory_for_new_functions(self) -> None: self.write_clean_tree()