feat(trust-score): v0.2 formula module + 67 unit tests (no integration yet) - #4
Open
jlromeiro wants to merge 1 commit into
Open
feat(trust-score): v0.2 formula module + 67 unit tests (no integration yet)#4jlromeiro wants to merge 1 commit into
jlromeiro wants to merge 1 commit into
Conversation
…n yet)
Implements docs/rfc/x402-trust-score.md §5.1 as a pure-function module.
Drop-in replacement for the legacy `Math.min(100, paidCount * 5)` callsites,
but NOT yet wired in — integration is the next chunk of WS-B.
What this commit adds:
lib/trust-score.js
- 5 normalized subscores (P1, P2, D2, H1, R1) all on the 0-100 scale
so published weights match effective contribution
- H1 uses Laplace (add-one) smoothing — paid=0/disp=0 yields 50, not
100. New agents don't inherit perfect hygiene from absence of evidence
- Conditional renormalization (RFC §5.1.3): when h1Active=false (Phase 1
default, no /report endpoint), drops H1 and renormalizes remaining
weights to sum to 1.0. Silent-zero would lower the headline ceiling
without changing published weights — auditability footgun avoided
- Cross-provider bonus: binary-by-operator multiplier capped at 1.5
(RFC §5.1.4). Small operators contribute the same +0.1 increment as
large ones — preserves network leverage for tier-2 operators
- H2 binary gate: any active fraud_flag forces score → 0
- extendReputationFields() computes active_in_n_providers,
loyalty_concentration, and per_provider for the v0.2 ReputationRecord
- defaultPolicy() returns the JSON brokers SHOULD publish in GET /info
test/trust-score.test.js
- 67 assertions, no I/O, follows the test/detection.test.js style
- Each subscore has unit tests with hand-computed exact values
- Composite scenarios covering Phase 1 (H1 inactive) AND Phase 1.5+
(H1 active with /report) for top/mid/new agent profiles
- Edge cases: null reputation, paid=0, H2 gate, empty attestations
- defaultPolicy shape verification
package.json
- test:trust-score script wired into npm test pipeline
What is NOT in this commit (intentionally):
- No changes to index.js (4 callsites: 375, 457, 1273, 1498 still use
paid_count*5)
- No changes to lib/agent-status.js (line 65) or lib/ratelimit.js (line 70)
- No changes to GET /reputation/:pubkey response shape
- No changes to GET /info to expose score_components
- No /report endpoint, no broker extraction (those are WS-C/WS-D scope)
- test/agent-status-handler.test.js still asserts the old paid_count*5
behavior — will be updated in the integration commit when callsites flip
Test run: 67/67 passed via `npm run test:trust-score`.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
Kilo Code Review could not run — your account is out of credits. Add credits or switch to a free model to enable reviews on this change. |
This was referenced May 16, 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
Adds
lib/trust-score.js— a pure-function module implementing the v0.2 score formula fromdocs/rfc/x402-trust-score.md§5.1 — plus 67 unit tests that all pass.No callsites are migrated in this PR. The legacy
Math.min(100, paidCount * 5)calls inindex.js,lib/agent-status.js, andlib/ratelimit.jsare still in place. Integration is the next PR (WS-B part 2 in the internal plan).This PR depends conceptually on #2 (the v0.2 RFC) but is independent at the file level — they don't touch the same files. Either can merge first.
What's in
lib/trust-score.jsFive subscores all normalized to 0-100 BEFORE weighting (so published weights match effective contribution — RFC §5.1.2):
min(100, log10(1 + paid_count) * 20)min(100, sqrt(months_in_network) * 12)(1 − loyalty_concentration) * 100((paid − disp + 1) / (paid + 2)) * 100exp(−idle_days / 60) * 100Plus:
fraud_flagforces score → 0cross_provider_bonus—min(1.5, 1 + 0.1 * (N − 1))where N is the count of distinct attesting operators (binary by operator, not weighted by volume — this is what gives small operators network leverage per the RFC)h1Active=false(Phase 1 default, no/reportendpoint), drops H1 and renormalizes remaining weights to sum to 1.0. Silent-zero would lower the headline ceiling without changing published weights — auditability footgun avoidedextendReputationFields()— computesactive_in_n_providers,loyalty_concentration,per_providerfor the v0.2 ReputationRecorddefaultPolicy()— returns the JSON brokers SHOULD publish inGET /infoTest coverage
test/trust-score.test.js: 67 assertions, no I/O, follows thetest/detection.test.jsstyle (plainnode test/<file>.test.js, no Jest).Sanity-check scenarios for top/mid/new agents in both Phase 1 (H1 inactive, weights renormalized) AND Phase 1.5+ (H1 active with
/report), with hand-computed expected values.Wired into
package.json:npm run test:trust-score(or runs as part ofnpm test).What is NOT in this PR (intentionally)
index.js:375, 457, 1273, 1498callsite changeslib/agent-status.js:65,lib/ratelimit.js:70GET /reputation/:pubkeyv0.2 response shapeGET /infoexposingscore_componentstest/agent-status-handler.test.js:165(asserts old behavior)/reportendpointweight(p)formula (RFC §5.2)Test plan
npm run test:trust-score→ 67/67 passed (verified locally)npm test→ still passes (this PR adds new tests but does not modify any existing test or source code)lib/detection.js,lib/agent-status.js,lib/ratelimit.js,lib/store.js,lib/enforcement.js— none of those files are touchedlib/trust-score.jsexports unchanged after merge (verified viagit diff)🤖 Generated with Claude Code