Skip to content

feat(normalization): land downstream target products - #86

Merged
c-wri merged 16 commits into
mainfrom
feat/economic-facts-reconciliation-checkpoint
Apr 20, 2026
Merged

feat(normalization): land downstream target products#86
c-wri merged 16 commits into
mainfrom
feat/economic-facts-reconciliation-checkpoint

Conversation

@c-wri

@c-wri c-wri commented Apr 20, 2026

Copy link
Copy Markdown
Collaborator

Why:

  • the bounded downstream slice needed to move accepted planner-enabled Coinbase normalization onto authoritative EconomicFacts, ReconciliationState, and Checkpoint products without creating a second architecture center
  • the repo also needed durable docs alignment and hardening fixes discovered during the full red-team review loop so the implemented slice stays provider-neutral, fail-closed, and compatibility-safe for current readers

What:

  • add target assertion, economics, reconciliation, checkpoint, storage, and normalization wiring for the bounded downstream product slice, while keeping current balance and rendering readers on target-derived compatibility outputs
  • promote the implemented downstream runtime truth into the owned docs and workspace product references, retire stale future-tense wording, and keep the bridge mapping aligned with the live compatibility posture
  • harden the slice after review by preserving compatibility annotation payloads, filtering reconciliation inputs to accepted balance bundles, failing closed on projection and repository contract drift, and tightening normalization reporting

Checks:

  • make quality
  • make pr-review
  • make docs-check
  • make naming-check
  • make docs-audit

Issue linkage:

  • None: no matching open issue applied after searching the current open issue set for this bounded downstream slice

Included checkpoints:

  • docs(runtime): retire claim-stage future wording
  • fix(intake): wrap package review reason formatting
  • feat(assertion): add target assertion values and stage leakage guards
  • feat(economics): add economic facts kernels and fact compatibility
  • feat(reconciliation): add state kernels and snapshot compatibility
  • feat(checkpoint): add kernels and reference compatibility
  • chore(format): apply repo-wide ruff formatting
  • fix(checkpoint): harden readiness and support projection
  • feat(normalization): persist downstream target products
  • docs(runtime): promote downstream product authority
  • fix(target-kernels): store lineage refs as product ids
  • fix(compatibility): fail closed on projection contract drift
  • fix(normalization): report target-derived fact counts
  • fix(downstream): harden compatibility contract edges
  • docs(migration): align bridge mapping with runtime
  • fix(storage): reject truncated assertion payloads

c-wri added 16 commits April 20, 2026 09:16
Why:
- the durable owner docs still described the implemented claim stage as future work on the bounded planner-enabled Coinbase slice
- downstream target-product work needs the runtime and planning surfaces to agree on the current authority boundary before new products are added

What:
- mark the completed claim-stage planning section with the repo's completed-work pattern
- update current-state, architecture, migration, contract, and changelog surfaces so ClaimSet is documented as implemented while downstream target products remain future work

Checks:
- make docs-check
- make naming-check
- make docs-audit
Why:
- the checkpoint verification path was blocked by a repo-code pylint failure in intake review formatting
- clearing that blocker is required so the bounded downstream checkpoints can be verified without skipping the standard gates

What:
- wrap the overlap review reason formatting across multiple string segments without changing behavior

Checks:
- make quality
Why:
- the downstream economics, reconciliation, and checkpoint kernels need a frozen assertion-value foundation before they can land safely
- provider and bridge-only terms must be blocked from the new target roots so the bounded slice stays neutral

What:
- add the target assertion value models for quantity, money, owner, and location values
- add assertion model coverage for canonical payloads, tuples, and fingerprint stability
- strengthen the standards guard so only the new target roots are scanned for provider and bridge leakage

Checks:
- make pytest ARGS='-q tests/unit/domain/assertion/test_models.py tests/contract/test_standards_guards.py'
- make quality
Why:
- the bounded downstream slice needs EconomicFacts to become the first authoritative economic meaning product after ClaimSet
- current bridge facts must remain reproducible from the new authority so unchanged Coinbase fixtures keep their compatibility outputs

What:
- add EconomicFacts domain models, repository port, filesystem storage, product path helpers, and the economics builder
- rebuild compatibility TransactionFact rows from EconomicFacts plus claim-side projection fields and preserve annotation parity
- add domain, storage, builder, projection, and annotation tests for the bounded Coinbase slice and fail closed on unsupported accepted activity shapes

Checks:
- make pytest ARGS='-q tests/unit/domain/economics/test_models.py tests/unit/infrastructure/storage/test_economic_facts_repository.py tests/unit/application/economics/test_builder.py tests/unit/application/compatibility/test_economic_facts_projection.py tests/unit/application/normalization/test_annotations.py src/tallylot/adapters/outputs/cointracking_csv/tests/test_adapter.py'
- make quality
Why:
- the bounded downstream slice needs ReconciliationState to become the authoritative continuity and exact-balance target surface after EconomicFacts
- retained balance readers must keep their current snapshot shape while the new target kernel takes ownership of the underlying truth

What:
- generalize assessment scope handling beyond claim-only scopes while preserving claim-scope ids and behavior
- add ReconciliationState models, repository port and filesystem storage, reconciliation builder, compatibility snapshot projection, and product path helpers
- add domain, repository, builder, compatibility, and balance-surface tests including economics-only partial segments and exact-balance proposal mapping

Checks:
- make pytest ARGS='-q tests/unit/domain/assessment/test_models.py tests/unit/domain/reconciliation/test_models.py tests/unit/infrastructure/storage/test_reconciliation_state_repository.py tests/unit/application/reconciliation/test_builder.py tests/unit/application/compatibility/test_reconciliation_projection.py tests/unit/application/balances/test_check.py tests/unit/application/balances/test_inspect.py tests/unit/application/balances/test_summary.py'
- make quality
Why:
- the bounded downstream slice needs Checkpoint to become the authoritative accepted statement-backed checkpoint truth after ReconciliationState
- retained balance-reference readers must keep their current source-document shape while the new checkpoint kernel owns the accepted truth

What:
- add Checkpoint domain models, repository port and filesystem storage, checkpoint builder, compatibility balance-reference projection, and checkpoint application surface
- export the new checkpoint compatibility projection and storage repository from their owning package roots
- add domain, repository, builder, and compatibility tests for checkpoint ids, accepted assertions, grouped as-of kernels, and source-document balance-reference parity

Checks:
- make pytest ARGS='-q tests/unit/domain/checkpoint/test_models.py tests/unit/infrastructure/storage/test_checkpoint_repository.py tests/unit/application/checkpoint/test_builder.py tests/unit/application/compatibility/test_checkpoint_projection.py tests/unit/application/balances/test_check.py tests/unit/application/balances/test_summary.py tests/unit/application/outputs/test_render_output.py src/tallylot/adapters/outputs/cointracking_csv/tests/test_adapter.py'
- make quality
Why:
- repo-wide Ruff formatting is now present in the working tree and must be reconciled explicitly rather than left as ambient drift
- keeping the formatter sweep as the last checkpoint preserves the bounded downstream slice history while still leaving the branch in a consistent formatted state

What:
- apply the repo-wide Ruff formatting sweep across the remaining tracked files in the branch worktree
- keep the previously verified downstream checkpoints intact and separate from this formatting-only checkpoint

Checks:
- commit hook selective verification
Why:
- the new reconciliation and checkpoint builders still treated unresolved observation ids as filing-ready support and could misclassify checkpoint continuity at same-time rollforwards
- checkpoint compatibility also needed deterministic support-ref resolution and state-ref deduping before the downstream slice can safely become authoritative

What:
- require reconciliation proposals to carry only evidence refs that resolve through the evidence set and mark unresolved support as partial
- dedupe reconciliation state refs per checkpoint, require expected QuantityValue on ready targets, and treat same-time nonzero rollforwards as reconciled continuity
- add coverage for unknown observation refs, equal-time rollforwards, duplicate state refs, and support-ref resolution from observation ids

Checks:
- make pytest ARGS='-q tests/unit/application/reconciliation/test_builder.py tests/unit/application/checkpoint/test_builder.py tests/unit/application/compatibility/test_checkpoint_projection.py'
- make quality
Why:
- planner-enabled Coinbase normalization still stopped at claim authority, which left the downstream target kernels unwired and kept the compatibility outputs on the older bridge-only path
- the new downstream refs also needed path-safe product ids and locked contract coverage so the bounded slice could persist cleanly without drifting adapter-pack or replay expectations

What:
- persist EconomicFacts, ReconciliationState, and Checkpoint products during planner-enabled Coinbase normalization and mirror target-derived compatibility facts, snapshots, and references back into the capture outputs
- extract downstream product orchestration into a dedicated normalization helper, tighten the statement-backed checkpoint and reconciliation seams, and switch downstream product ids to path-safe hashed forms
- add downstream normalization integration coverage and refresh the affected adapter-pack goldens for the new summary fields, checkpoint reference behavior, and populated fact effective timestamps

Checks:
- make quality
- make pr-review
Why:
- the owner docs still described EconomicFacts, ReconciliationState, and Checkpoint as future work, which no longer matched the bounded downstream runtime slice on this branch
- the durable docs also needed neutral wording so the runtime authority reads as plain current-state truth instead of delivery-timing commentary

What:
- mark the downstream economics, reconciliation, and checkpoint planning sections complete and point them at the owner docs that carry the active runtime truth
- update architecture, current-state, migration, product-output, and changelog surfaces to describe the downstream kernels and target-derived compatibility views in neutral runtime language

Checks:
- make docs-check
- make naming-check
- make docs-audit
Why:
- the new target kernels were carrying upstream lineage as workspace file paths,
  which drifted from the frozen product-header contract and kept
  compatibility-shaped refs inside the authoritative products

What:
- keep `ClaimSet`, `EconomicFacts`, `ReconciliationState`, and `Checkpoint`
  lineage fields on product ids inside the target kernels and builders
- preserve the existing file-based normalization response refs for the current
  operator-facing compatibility surface
- refresh the affected bounded Coinbase adapter-pack normalization summaries so
  their deterministic downstream ids match the corrected target-id recipe
- tighten builder, domain, repository, and projection tests around the id-based
  lineage contract

Checks:
- make pytest ARGS="-q tests/unit/application/claim/test_coinbase_builder.py tests/unit/application/claim/test_compatibility_projection.py tests/unit/application/economics/test_builder.py tests/unit/application/reconciliation/test_builder.py tests/unit/application/checkpoint/test_builder.py tests/unit/application/compatibility/test_economic_facts_projection.py tests/unit/application/compatibility/test_reconciliation_projection.py tests/unit/application/compatibility/test_checkpoint_projection.py tests/unit/application/normalization/test_annotations.py tests/unit/application/normalization/test_claim_set_integration.py tests/unit/domain/claim/test_models.py tests/unit/domain/reconciliation/test_models.py tests/unit/domain/checkpoint/test_models.py tests/unit/infrastructure/storage/test_claim_set_repository.py tests/unit/infrastructure/storage/test_reconciliation_state_repository.py tests/unit/infrastructure/storage/test_checkpoint_repository.py"
- make ruff ARGS="check src/tallylot/application/claim/coinbase_builder.py src/tallylot/application/economics/builder.py src/tallylot/application/normalization/downstream_products.py src/tallylot/application/normalization/translation.py src/tallylot/application/reconciliation/builder.py src/tallylot/application/checkpoint/builder.py tests/unit/application/claim/test_coinbase_builder.py tests/unit/application/claim/test_compatibility_projection.py tests/unit/application/economics/test_builder.py tests/unit/application/reconciliation/test_builder.py tests/unit/application/checkpoint/test_builder.py tests/unit/application/compatibility/test_economic_facts_projection.py tests/unit/application/compatibility/test_reconciliation_projection.py tests/unit/application/compatibility/test_checkpoint_projection.py tests/unit/application/normalization/test_annotations.py tests/unit/application/normalization/test_claim_set_integration.py tests/unit/domain/claim/test_models.py tests/unit/domain/reconciliation/test_models.py tests/unit/domain/checkpoint/test_models.py tests/unit/infrastructure/storage/test_claim_set_repository.py tests/unit/infrastructure/storage/test_reconciliation_state_repository.py tests/unit/infrastructure/storage/test_checkpoint_repository.py"
- make refresh-adapter-goldens ARGS="--pack coinbase/mixed_statement_aux_pdfs --pack coinbase/retail_buy_renamed"
- make pytest ARGS="-q tests/contract/test_source_adapter_packs.py -k 'mixed_statement_aux_pdfs or retail_buy_renamed'"
Why:
- target-derived compatibility outputs still had a few hidden coupling points
  where unrelated state could leak into projection results or impossible
  contract breaks could surface as generic import or lookup failures

What:
- require matching `ClaimSet` lineage and declared projection sidecars before
  rebuilding `TransactionFact` compatibility rows from `EconomicFacts`
- scope checkpoint compatibility support lookup to the reconciliation states
  the checkpoint actually references and raise explicit errors when required
  state or support detail is missing
- lazy-load the normalization package's workflow exports so annotation imports
  do not create a circular import through normalization orchestration
- add focused projection tests for lineage mismatch, missing sidecars, and
  unrelated-state isolation

Checks:
- make pytest ARGS="-q tests/unit/application/compatibility/test_economic_facts_projection.py tests/unit/application/compatibility/test_checkpoint_projection.py tests/unit/application/normalization/test_annotations.py tests/unit/application/normalization/test_downstream_target_integration.py"
- make ruff ARGS="check src/tallylot/application/compatibility/economic_facts.py src/tallylot/application/compatibility/checkpoints.py src/tallylot/application/normalization/__init__.py tests/unit/application/compatibility/test_economic_facts_projection.py tests/unit/application/compatibility/test_checkpoint_projection.py"
Why:
- once the bounded Coinbase slice swaps in target-derived compatibility facts,
  the normalization response should describe the actual emitted fact output
  rather than the pre-projection bridge count

What:
- report `fact_count` from the final normalization outputs after any
  downstream target-derived compatibility replacement
- lock the downstream normalization integration tests against the written
  `facts.csv` row count

Checks:
- make pytest ARGS="-q tests/unit/application/normalization/test_downstream_target_integration.py tests/unit/application/normalization/test_normalization_service.py"
- make ruff ARGS="check src/tallylot/application/normalization/normalize_source.py tests/unit/application/normalization/test_downstream_target_integration.py"
Why:
- the downstream slice was silently dropping compatibility annotation payloads and letting unaccepted balance bundles participate in reconciliation, which weakened the declared economics, reconciliation, and checkpoint contract under red-team review
- contract drift on referenced claim ids also surfaced as raw lookup errors instead of explicit bounded failures

What:
- preserve review markers and adapter metadata through the claim-side compatibility sidecar and downstream compatibility projections
- restrict reconciliation balance-target inputs to accepted balance bundles and raise explicit errors for missing referenced claims
- strengthen existing projection and normalization parity coverage with non-empty annotation payloads plus rejected-balance filtering regressions

Checks:
- make pytest ARGS="tests/unit/application/claim/test_compatibility_projection.py tests/unit/application/economics/test_builder.py tests/unit/application/reconciliation/test_builder.py tests/unit/application/normalization/test_annotations.py -q"
- make ruff ARGS="check src/tallylot/application/claim/contracts.py src/tallylot/application/claim/coinbase_builder.py src/tallylot/application/compatibility/claim_sets.py src/tallylot/application/compatibility/economic_facts.py src/tallylot/application/economics/builder.py src/tallylot/application/reconciliation/builder.py tests/unit/application/claim/test_compatibility_projection.py tests/unit/application/economics/test_builder.py tests/unit/application/reconciliation/test_builder.py tests/unit/application/normalization/test_annotations.py"
- make pr-review
Why:
- the bridge-to-target owner doc still described the downstream contract as not yet landed, which contradicted the implemented runtime status surfaces on this branch
- the product-output reference also needed to reflect the compatibility annotation payloads now carried in the claim-side sidecar

What:
- update the migration mapping doc to describe `facts.csv`, `balance_snapshots.csv`, and `balance_references.csv` as target-derived compatibility views for the bounded implemented slice
- clarify that `draft_projection_fields.json` also carries the retained compatibility annotation payloads used by downstream bridge rebuilding

Checks:
- make docs-check
- make naming-check
- make docs-audit
Why:
- malformed checkpoint and reconciliation payloads could still trip raw list indexing in the new repository readers instead of failing with deterministic validation errors
- the full PR review loop surfaced that gap while exercising the lower-coverage persistence seams with synthetic malformed payloads

What:
- validate required tagged assertion-value items before reading quantity, money, or location payload elements in the checkpoint and reconciliation repositories
- add malformed-payload repository tests and keep them typed so the static-analysis lanes stay green while covering the failure mode

Checks:
- make pytest ARGS="tests/unit/infrastructure/storage/test_reconciliation_state_repository.py tests/unit/infrastructure/storage/test_checkpoint_repository.py -q"
- make mypy
- make pyright
- make ruff ARGS="check tests/unit/infrastructure/storage/test_reconciliation_state_repository.py tests/unit/infrastructure/storage/test_checkpoint_repository.py src/tallylot/infrastructure/storage/reconciliation_states.py src/tallylot/infrastructure/storage/checkpoints.py"
- make pr-review
@c-wri
c-wri marked this pull request as ready for review April 20, 2026 19:50
@c-wri
c-wri enabled auto-merge April 20, 2026 19:50
@c-wri
c-wri disabled auto-merge April 20, 2026 19:54
@c-wri
c-wri merged commit 5827bef into main Apr 20, 2026
122 of 168 checks passed
@c-wri
c-wri deleted the feat/economic-facts-reconciliation-checkpoint branch April 20, 2026 19:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant