# Credit Report v0 — evidence and exposure, no score Contract `0.1.0`; methodology `acb-evidence/0.1.0`. Full generated reports: [RSoft](../examples/v0/rsoft-credit-report.json), [Morpho](../examples/v0/morpho-credit-report.json). Contextual responses: [RSoft assess](../examples/v0/rsoft-assess-response.json), [Morpho assess](../examples/v0/morpho-assess-response.json). These are reconstructed from the accepted bundle, not live queries or fabricated source observations. ## Exact minimum report `ReportSnapshot` has the following required fields. Nullable subfields remain null when unobservable; nothing is filled with a confidence percentage or global score. | Field | Content | Why a capital-risk caller needs it | | --- | --- | --- | | `schema_version`, `methodology_version` | Versioned interpretation/wire contracts | Reproduce a policy decision and detect changed methodology. | | `snapshot_id`, `supersedes` | Canonical report hash and nullable earlier snapshot ID | Bind a decision to the exact evidence state; trace corrections. | | `as_of` | Latest source retrieval, with each source's own time retained | Avoid mistaking a historical report for current coverage. | | `subject` | Canonical subject, identifiers, evidence-linked identity links/control epochs | Avoid lending against another agent's or a former controller's history. | | `coverage` | Source scope/status, event ranges, observed/reported records, lifecycle measurability and limitations | Distinguish absence of observed problems from inability to observe them. | | `observed_counts` | Scoped open/completed/late/defaulted/liquidated counts, nullable | Understand observed obligations without equating activity with success or unknown with zero. | | `obligations` | Attributed obligation/position IDs, economic grouping, asset/type/status, principal/outstanding, interval endpoints, due/late semantics, collateral/guarantee, payer/funding, relationship/control and evidence/unknowns | Determine what was actually owed, how long it was carried, how it closed and what the history does not establish. | | `events` | Timestamped source-attributed transfer/protocol events with amounts, nullable principal allocation, actors and transaction/log/block references | Audit claimed disbursements/settlements and retain partial events without inventing complete loans. | | `diagnostics` | Per-asset exact exposure-derived and experimental history-pattern metrics, with parameters/unknowns | Prevent tiny/repetitive history from masquerading as comparable economic risk. | | `history_quality_flags` | Factual, scoped flags with basis, parameters and evidence references | Make limitations easy for a machine policy to find; flags do not decide the loan. | | `conflicting_evidence` | Competing assertions, sources and resolution | Prevent a caller from relying on silently selected favorable claims. | | `unknowns` | Material unobservable facts | Express limits without fabricating clean history. | | `evidence` | Source IDs, URLs, retrieval times, immutable raw/request locators, SHA-256, evidence category and finality caveat | Independently inspect the basis of each conclusion and reproduce the calculation. | `EvidenceObservation.basis` distinguishes issuer assertion, RPC observation and indexer observation; `Obligation.exposure_basis` distinguishes a principal ledger from issuer-lifecycle interpretation corroborated by transfers. These categories are **not numerical confidence estimates**. An RPC-observed settlement can support an issuer-attributed loan without proving all contractual terms or principal allocation. An obligation's actual interval duration is `end - start`; episode duration is the union of intervals with positive outstanding principal. For a single closed RSoft interval this equals `ended_at - started_at`. A partial/open ledger measures only its captured horizon; never automatically extend it to the report's as-of. A missing interval ledger is null. The duration distribution reports minimum/median/maximum across measured reconciled episodes, not advertised contractual term. `GET credit-report` has context-free evidence metrics. `POST assess` adds the echoed proposal and `ExposureComparison`, and populates reference-dependent diagnostics in its embedded report. The largest borrower-mediated satisfied principal in captured history (`diagnostics.largest_satisfied_principal`) is distinct from the largest structurally comparable, independently supported principal (`comparison.largest_satisfied_comparable_principal`). RSoft's former is `"5"`; the latter is null. A satisfied count can include issuer assertions; the status and basis remain visible on every obligation. ## Exact exposure mathematics For each source-supported constant-outstanding interval `[t_k, t_{k+1})`: ```text E_asset_seconds = Σ (P_outstanding,k × (t_{k+1} − t_k)) E_asset_days = E_asset_seconds / 86400 ``` Amounts enter as decimal strings and are converted to exact rational numbers. Timestamps/deltas use nonnegative integer seconds. Internal calculations and comparisons use `fractions.Fraction`, without float or display-rounded threshold comparisons. Money must fit the asset's atomic precision. Output derived fractional metrics use decimal strings rounded half-even to 12 fractional places, with trailing zeros removed. Native seconds totals for six-decimal USDC are exact; repeating days/ratios are rounded displays. No timestamped FX evidence exists, so no metric is labeled USD. Ledgers must be contiguous, ordered, nonnegative and non-overlapping per obligation. Zero-length intervals contribute zero. Unknown principal allocation, missing opening balance or missing spans make the full lifecycle unmeasurable; a transfer or debt-share repayment cannot fill the gap. A repayment reduces principal only when source semantics explicitly allocate it. Original draw principal and current outstanding principal are distinct. Explicitly linked economic shards sum outstanding principal **at each instant**. Linked rollover legs retain continuous risk without double-counting the same time/principal. Adapters must canonicalize duplicate evidence of the same obligation; duplicate obligation IDs/events fail validation. This version does not discover arbitrary economically duplicate source records or common controllers. Grouping requires an explicit economic exposure ID, basis and provenance; it is not inferred from convenient similar-looking amounts. Any missing leg prevents that group's lifecycle from qualifying. Examples: 1,000 outstanding for 10 days followed by 600 for 20 days is **22,000 asset-days**, not 30,000. Two sequential 15-day refinancing legs of 1,000 total **30,000**, not 60,000 asset-days. A 1,000-unit instantaneous loan has zero principal-time exposure. Settlement amount can include interest/fees; summing it as repaid principal is forbidden without allocation evidence. RSoft calculation is **conditional on its four issuer-linked lifecycle assertions**: 5 USDC remains outstanding between each matched disbursement/settlement block. Captures do not prove absence of unobserved intermediate principal changes or signed discharge. The exact arithmetic does not turn this weaker semantic basis into fully verified economic risk. ## Diagnostic definitions All diagnostics are experimental, non-calibrated facts, not creditworthiness, fraud probabilities or a replacement score. The universe is the captured, reconciled lifecycle episodes in one asset, **including all relationship classes**, with exposure attributed by class and eligibility handled separately. Counts/shares never convert UNKNOWN controllers into independent counterparties. Incomplete lifecycle aggregates are null; known measured counts can still state how many source records were measured. | Metric | Deterministic definition | | --- | --- | | `raw_obligation_count` | Number of source obligation records represented by complete captured ledgers before economic episode reconciliation. Null when full obligation enumeration is unsupported, as for Morpho. | | `measured_obligation_count` / `economic_episode_count` | Records represented in measured groups / distinct explicitly reconciled groups. A missing group leg excludes that whole group from measurement. | | `principal_volume` | Sum of reconciled episode **peak outstanding** principals. This is an episode-risk notional, not gross draw turnover or USD payment volume; sequential refinancing within one episode is not summed as new principal. | | `median_principal` | Ordinary median of reconciled episode peak principals. Even samples average the two middle values. | | `largest_satisfied_principal` | Maximum episode peak principal with every terminal leg SATISFIED or ISSUER_REPORTED_SATISFIED and closed from BORROWER_FUNDS or BORROWER_WALLET_SOURCE_UNKNOWN. Related/test and issuer basis remain disclosed; this is not independent comparable exposure. Zero means none in a completely measurable scoped universe; null means unmeasurable. | | `duration_distribution` | Minimum/median/maximum actual positive-outstanding episode durations in seconds. Zero-length episodes have zero duration. | | `cumulative_exposure_asset_seconds/days` | Exact sum of measured `E` within asset; null if incomplete. | | `exposure_by_relationship_asset_seconds` | Same sum partitioned into INDEPENDENT, RELATED, TEST, UNKNOWN. Mixed group classification is UNKNOWN; comparison still inspects each constituent. | | `economically_weighted_obligation_count` | `ΣE / (proposed_principal × proposed_duration)` — **uncapped exposure-equivalent units**. Null without proposal or incomplete history. It is not a success count. | | `related_party_count_share`, `unknown_relationship_count_share` | Source-record counts in those reconciled classes divided by measured raw count. Count-based diagnostic only; exposure partition is separately available. | | `counterparty_wallet_hhi` | `Σ(exposure attributed to wallet / total exposure)²`; null if any episode has no unique wallet or total exposure is zero. Wallets do not establish controllers. | | `counterparty_controller_hhi` | Same formula for positively identified economic controllers; null if any controller is unknown. | | `independent_controller_count` | Distinct positively identified controllers for INDEPENDENT episodes; null if controller identification in the universe is incomplete. | | `repeated_amount_modal_share` | Frequency of most common episode peak principal divided by episode count. | | `repeated_duration_modal_share` | Frequency of most common episode duration divided by episode count. | | `repeated_start_gap_modal_share` | Most common gap between chronologically ordered episode starts, including zero gaps, divided by number of gaps. Null with fewer than two starts. | | `micro_obligation_count_share` | Fraction of reconciled episodes with peak principal ≤ 1% of proposed principal. Null without proposal/known denominator. | | `history_inflation_ratio` | `raw_obligation_count / economically_weighted_obligation_count`, within the same measured universe and proposal. Zero denominator yields null plus explanation, never infinity or invented zero. | The weighted-count definition intentionally refines the Phase 0 candidate `Σ min(1, E_i/E_ref)`: a per-record cap can be gamed by unknown splitting. The uncapped exposure-equivalent sum is additive and invariant even when artificial shards have not been recognized. It may exceed the raw obligation count for a single very large exposure; it is not a count of independent successful loans. Reconciliation still matters for principal peaks, durations, terminal closure and comparability. Raw counts may increase history-inflation diagnostics but never increase eligibility. ## Factual flag rules Every emitted flag includes `basis`, string-valued `parameters`, and source `evidence_refs`. Parameters include the reference asset/principal/duration for proposal-dependent flags. Versioned defaults below are arbitrary experimental thresholds, not calibrated adverse-risk boundaries: | Flag | Trigger | | --- | --- | | `MICRO_OBLIGATION_CONCENTRATION` | At least 50% of measured episodes have peak principal ≤ 1% of proposed principal. | | `ABNORMALLY_SHORT_DURATION` | Median measured episode duration < 1% of proposed duration. | | `LOW_ECONOMIC_EXPOSURE` | Total measured native exposure < 1% of proposed native exposure, with at least one measured episode. | | `HISTORY_INFLATION_DETECTED` | Raw count ≥ 100 and exposure-equivalents are zero or history-inflation ratio ≥ 100. Zero-exposure ratio stays undefined. | | `SYNTHETIC_ACTIVITY_PATTERN` | At least 10 episodes, amount modal share ≥ 0.9 and start-gap modal share ≥ 0.9. Intent remains unknown. | | `RELATED_COUNTERPARTY_CONCENTRATION` | At least 50% of measured source obligations have positively evidenced RELATED classification. | | `INSUFFICIENT_COVERAGE` | A named source has partial/error coverage or a lifecycle ledger is missing; also attached for a coverage-blocked assessment. A nonessential reputation-source failure can coexist with partial comparable lending history. | | `INSUFFICIENT_COMPARABLE_HISTORY` | Assessment state is partially comparable or insufficient comparable. Basis/parameters explain the comparison shortfall. | No flag declares a person/agent a fraudster. A high diagnostic ratio can occur on legitimate short-lived credit; RSoft's ratio for the 100-USDC/day proposal is about 13,660, but its raw count of four does **not** trigger the minimum-100 history-inflation flag. Neither history-inflation nor synthetic-pattern flags are asserted for that real case. ## Comparison state rules The engine compares native assets exactly, never by ticker or assumed stablecoin parity. The constant-principal proposed exposure is `E_ref = P × D`, with `P > 0`, `D > 0`. Evaluate in this order: 1. **INSUFFICIENT_COVERAGE** if no named coverage has a measurable lifecycle, or any material conflict has `resolution == "UNRESOLVED"`. Also use this state when potentially relevant matching-asset/type groups exist but every group has an unmeasured leg. No source error is silently recoded as absence of debt. A failure in an unrelated reputation source alone does not erase otherwise measurable issuer lifecycles. 2. Form candidate groups only when **every leg** has exactly the proposed asset and obligation type. Unknown ledgers exclude the whole group. Related/test legs exclude the group from positive comparable candidates. An eligible positive candidate has nonzero measured exposure; all terminal (non-REFINANCED) legs are SATISFIED or ISSUER_REPORTED_SATISFIED and have BORROWER_FUNDS or BORROWER_WALLET_SOURCE_UNKNOWN closure. At least one terminal leg must exist. 3. A **structurally comparable** group additionally requires every terminal leg to be `SATISFIED` and `BORROWER_FUNDS`, and every leg to have positive INDEPENDENT evidence, matching secured boolean, guarantee ABSENT, AUTHENTICATED_TERMS or PROTOCOL_RULES, PRINCIPAL_LEDGER basis and evidenced ongoing control epoch starting no later than the leg. Ended/unknown control epochs do not qualify. The largest principal among these groups is returned even if the proposal is larger/longer; null means no structurally comparable group was established. 4. **COMPARABLE_HISTORY_OBSERVED** if at least one structurally comparable group has total native `E ≥ E_ref` and aggregate outstanding principal continuously ≥ `P` for at least `D` seconds. The sustained-principal rule prevents a brief high peak followed by a long tiny tail from claiming matching scale. Return constituent IDs for each qualifying group. A pool of unrelated small/short loans is never pooled into a synthetic long/large loan. 5. **PARTIALLY_COMPARABLE_HISTORY** if no fully comparable group exists but at least one positive candidate from step 2 exists. It may fail scale, terms, independence, funding, security, guarantee or control requirements. Return these constituent IDs separately, excluding fully comparable IDs. 6. **INSUFFICIENT_COMPARABLE_HISTORY** otherwise, within the available named coverage. This includes wholly RELATED/TEST, zero-duration, open, guarantor-funded, liquidation-funded or nonmatching-type evidence without another positive candidate. It is not evidence that the subject is uncreditworthy. The report still discloses open/adverse/unknown observations even if a qualifying historical episode exists. The state does not net historical success against other debts or adverse events, prove solvency, or approve the proposed transaction. Experimental patterns do not mechanically change the state; their factual exclusions and exact economic exposure do. The caller owns its policy and should consider source age, coverage and all adverse/unknown evidence. ## Real reconstruction results and provenance RSoft: four issuer-reported satisfied **5-USDC** requests, eight matched transfers. Block-measured durations by explorer record order are **258, 52, 194, 2 seconds**. Principal volume is 20 USDC; median and largest issuer-reported satisfied principal are 5. Repayment transfers total **21.063726 USDC**, with interest/fee allocation unknown; that total is not principal repaid. ```text 5 × (258 + 52 + 194 + 2) = 2530 USDC-seconds 2530 / 86400 = 0.029282407407 USDC-days (12-place display) ``` All relationships are UNKNOWN; wallet HHI is 1 and economic-controller HHI is null. Signed terms, effective due schedule, actual collateral posting, guarantee status, ultimate repayment funding and historical control are unknown. The issuer's advertised term/clock is retained separately. No fraud inference is made. For 100 USDC over one day unsecured, the state is PARTIALLY_COMPARABLE_HISTORY. Morpho: 20 captured indexed events out of a reported **2,770 subject records** (14 Repay, five Borrow, one SupplyCollateral), all returned rows in one market. One 5-USDC Repay is corroborated against the captured Base receipt's Morpho contract/topic, market, borrower, amount, shares, log and block timestamp. Other events remain indexer-attributed. Repay asset amounts may include accrued interest; the collateral amount was not selected in the captured query. Opening balance, inception, full pagination, principal allocation, episode boundaries/current debt and complete closures are absent. Therefore principal-time, completed counts, largest satisfied exposure and weighted count remain **null**; assessment returns INSUFFICIENT_COVERAGE. No repayment-to-loan pairing is invented. Selected primary sources, **original retrieval dates** (UTC; the captures were made during September 23 Honolulu time): | Source | URL | Retrieved | | --- | --- | --- | | RSoft request explorer | https://rsoft-agentic-bank.com/api/v1/loan/explorer?page=1&limit=100 | 2026-09-24 03:46:00 UTC | | RSoft loan detail | https://rsoft-agentic-bank.com/api/v1/loan/status/req_0a9e39fa202821907f21ca10 | 2026-09-24 03:58:54 UTC | | RSoft active-loan assertion | https://rsoft-agentic-bank.com/api/v1/loan/active/0x4cffda4ff0a6c4918609067d2f77aad6dfc9ae9b | 2026-09-24 03:58:54 UTC | | Morpho subject query | https://api.morpho.org/graphql | 2026-09-24 03:49:19 UTC; exact query in pinned `.meta.json` | | Base receipt RPC | https://mainnet.base.org | Per-request timestamps/hashes in each report's evidence manifest; Morpho receipt 2026-09-24 03:49:19 UTC | | Morpho event definitions | https://raw.githubusercontent.com/morpho-org/morpho-blue/main/src/libraries/EventsLib.sol | 2026-09-24 03:46:56 UTC; captured bytes pinned, not live `main` | | Morpho deployment addresses | https://docs.morpho.org/get-started/resources/addresses/ | 2026-09-24 03:49:19 UTC | Every source used by the engine has an exact URL, timestamp and hash in the report, including the issuer identity assertion, registry owner call and all eight RSoft receipt/block pairs. The adapter reads raw captures directly, not Phase 0 normalized reports. `phase0-manifest.json` pins original bodies **and** metadata; mismatches fail. This reproduces observations, not source truth or independent consensus verification. ## Adversarial acceptance cases [`tests/fixtures/adversarial.json`](../tests/fixtures/adversarial.json) contains synthetic recipes only. `tests/synthetic.py` expands them, separated from real evidence adapters. | Fixture | Required result | | --- | --- | | 1,000,000 × 0.01 instant borrow/repay | Count 1,000,000; native exposure 0; exposure-equivalents 0; ratio null; micro/inflation/pattern flags; no comparable history from an instant episode. | | One 1,000-unit obligation for 30 days | 30,000 native asset-days; one reference-equivalent for the same proposal; fully comparable only under synthetic stipulations of independence/terms/funding/control. | | Same exposure split into 1,000 shards | Same exposure and weighted count; known grouping also preserves peak principal and sustained duration. Unrecognized grouping cannot increase weighted exposure or invent large comparable principal. | | RELATED recycling | Related exposure remains visible; independent comparable history excluded. | | TEST transactions | Separately classified exposure; no independent comparable history. | | Unknown counterparties | UNKNOWN share 1, controller concentration/count null; partial evidence, never automatic independence. | | Partial repayment | 1,000 × 10 days + 600 × 20 days = 22,000 asset-days; 600 outstanding; no satisfied history. | | Guarantor-funded closure | Closure/payer preserved; not borrower-funded successful history. | | Liquidation-funded closure | Liquidation status preserved; not borrower repayment success. | | Refinancing/rollover | Two 15-day legs reconcile to 30,000 asset-days and one episode; only final repayment is satisfaction. Open/missing final or earlier legs cannot create a fully satisfied comparable lifecycle. | Tests also cover deterministic outputs, no-network reconstruction, original-file immutability, schema/example drift, partial/incomplete groups, exact fractions, source tampering, receipt/block mismatches, extra/invalid request fields, currency precision, duplicates, random shard conservation, security/control/terms gates and peak-versus-sustained duration. Run `python3 -m unittest discover -s tests -v`; no live source access or external dependency is required.