test(core): execute UWR profile KAT vectors - #17
Merged
Conversation
Execute the afi-config uwr-profile v0 KAT vectors (PR #17, fe32916) against computeUwrScore and applyTimeDecay per UP-11 (PR-UWR-KAT-EXEC). Additions only: byte-identical vendored vectors + provenance sidecars + two executor suites. Object.is bit-exact for 41/42 vectors; dual-pinned characterized exception for uwr-score-anchor-0650. Testnet-provisional; execution does not wire anything. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
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
Executes the afi-config UWR profile KAT vectors against the afi-core engines — the executable half of the UP-11 KAT/golden gate. Additions only: 6 new files, 0 modified, no dependency/lockfile/tsconfig/CI changes.
validators/__tests__/computeUwrScore.kat.test.ts— 10 score vectors vscomputeUwrScore(16 tests)src/decay/__tests__/applyTimeDecay.kat.test.ts— 32 decay vectors vsapplyTimeDecay(36 tests)kats/fixture dirsAuthorization chain
afi-governance/decisions/uwr-profile-pin-v0.1.md): KAT vectors (pure data) live in afi-config; KAT execution against afi-core code is "a separately-authorized afi-core PR (PR-UWR-KAT-EXEC), following the established vendored-golden-with-source-pin pattern used by afi-mint for the emissions goldens."computeUwrScore/applyTimeDecay(vendored-golden-with-source-pin pattern)" — marked "No — separate authorization."Provenance pins
Vendored from
AFI-Protocol/afi-configkats/uwr-profile/v0/at merge commitfe329164919f0c1c9dc24bb5c279978fb680e983(PR #17), content commit7809af4b0308f7db47488947770a0ab9f236268d:compute-uwr-score.kat.json(10 vectors)276be9e9348b4e0c2e92e5a9c59d05b50bfeb75dff2f63956038b1d5c01109184e2ddddb2606c11405d2420c35b7decb5eb36546apply-time-decay.kat.json(32 vectors)1199f705ee65eef70e6c0c58fffcd10206693cf01a1240cc9f8cc8ed70b22f4aa00e7cdfe1176f4f1d3c6b1e10e886b0cfe81b78Executed against afi-core
254185381c3c9be91da303454c1f7a27e8818983(main, PR #16 merge). The KATs'engine.sourceCommit: 390b440pin:UniversalWeightingRule.tsis blob-identical between390b440and2541853;GreeksDecayTemplate.tsdiffers only by the PR #16 kernel delegation, proven bit-exact inapplyTimeDecay.mathEquivalence.test.ts— documented in the sidecars, vendored bytes left untouched per change control.Drift detection: always-on sha256 self-integrity checks against pinned constants (hermetic in CI), plus
it.skipIf-guarded full byte-compares against a sibling afi-config checkout on dev machines. Failure messages state the governance implication: divergence requires a new scoped authorization; never silently re-vendor.Comparison policy (owned by this PR)
Both KAT files deliberately define no float-comparison policy;
comparisonPolicyNoteassigns it to PR-UWR-KAT-EXEC scope. Policy adopted:Object.isbit-exact, all 32 vectors — per the file'sexactnessRule(dyadic base scores × integer half-life multiples ⇒ every expected value exact in binary64).Object.isbit-exact for 9/10 vectors.uwr-score-anchor-0650— dual-pinned characterized exception. The engine's multiply-accumulate order over axes (0.6, 0.7, 0.6, 0.7) with 0.25 weights yields0.6499999999999999, exactly 1 ULP below the decimal anchor 0.65. This is deterministic, correctly-rounded IEEE-754 binary64 arithmetic (no transcendentals) — identical on every conforming engine, not flake. The test asserts both |actual − 0.65| ≤ 1 ULP andObject.is(actual, 0.6499999999999999), pinning the engine's true output verbatim so any future engine change fails loudly (drift-detection strength equal to bit-exact). 0.65 is not decision-pinned (only the 0.1875 golden anchor and the 0.25 weights are decision-named). Rejected alternatives: editing the vendored expected value (violates afi-config change control) and blanket tolerances (weaken the 41 vectors that can be exact). Optional future item for the owner (separately authorized, not this PR): a one-vector afi-config erratum swapping the 0650 axes to e.g. (0.5, 0.6, 0.7, 0.8) would collapse the exception to uniform bit-exactness.uwr-score-d2m2-golden-anchor(0.1875) — the decision-named D2 M2 golden replay anchor — reproduces bit-exactly and is called out in a dedicated test (UP-5/UP-11 byte-stability criterion).What this does NOT unlock
Execution ≠ wiring. This PR runs KAT vectors in tests and nothing more:
IValidatorScorer/ValidatorDaemonand all reward/mint paths untouched; no eligibility assertions anywhere (the 0.5 =minDecayScoreThresholdcoincidence in the decay data stays commentary).*.test.ts; the executed config is built from the KAT's own weights block;defaultUwrConfigunchanged.GreeksDecayTemplatesurface only.x-afiStatus: draft-non-implementation). Each follow-up requires its own scoped authorization.Validation
git check-ignoreon new paths: nothing ignored (fixture dirs namedkats/, notvendor*/)cmp+sha256sum: vendored copies byte-identical to afi-config @fe32916, hashes match pinsnpm run test:run: 196 passed (existing 144 unchanged + 16 score-KAT + 36 decay-KAT), including live sibling byte-comparesnpm run build,npm run typecheck,scripts/esm-check.sh: clean (tests are tsc-excluded; no config edits)git status: exactly 6 additions, 0 modifications;git diff --statemptyUniversalWeightingRule.tsconfirmed blob-identical390b440↔2541853,GreeksDecayTemplate.tsdelta confirmed to be exactly the PR refactor(decay): delegate applyTimeDecay kernel to afi-math (PR-7, bit-exact) #16 delegation); (2) additions-only scope audit (status purity, no config/CI/lockfile edits, novendor*/, KAT JSON referenced only from tests/sidecars, all six sibling repos byte-verified clean); (3) language guards (0 banned-phrase hits; required testnet-provisional / execution≠wiring / separately-authorized / never-silently-re-vendor language present; UP-8 stated OPEN); (4) test-strength review + mutation testing in an isolated copy — 4/4 mutations killed (vendored-byte flip, 0650 pin change, decay expected-value edit, weights swap), baseline green both with and without a sibling checkout (skip path verified)🤖 Generated with Claude Code