feat(normalization): land downstream target products - #86
Merged
Conversation
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
marked this pull request as ready for review
April 20, 2026 19:50
c-wri
enabled auto-merge
April 20, 2026 19:50
c-wri
disabled auto-merge
April 20, 2026 19:54
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.
Why:
EconomicFacts,ReconciliationState, andCheckpointproducts without creating a second architecture centerWhat:
Checks:
Issue linkage:
Included checkpoints:
docs(runtime): retire claim-stage future wordingfix(intake): wrap package review reason formattingfeat(assertion): add target assertion values and stage leakage guardsfeat(economics): add economic facts kernels and fact compatibilityfeat(reconciliation): add state kernels and snapshot compatibilityfeat(checkpoint): add kernels and reference compatibilitychore(format): apply repo-wide ruff formattingfix(checkpoint): harden readiness and support projectionfeat(normalization): persist downstream target productsdocs(runtime): promote downstream product authorityfix(target-kernels): store lineage refs as product idsfix(compatibility): fail closed on projection contract driftfix(normalization): report target-derived fact countsfix(downstream): harden compatibility contract edgesdocs(migration): align bridge mapping with runtimefix(storage): reject truncated assertion payloads