Skip to content

feat(prd-7): populate TransactionFacts from PipelineState doc_fields (#55)#90

Merged
elasticdotventures merged 3 commits into
mainfrom
feat/prd7-transaction-facts-population
May 12, 2026
Merged

feat(prd-7): populate TransactionFacts from PipelineState doc_fields (#55)#90
elasticdotventures merged 3 commits into
mainfrom
feat/prd7-transaction-facts-population

Conversation

@promptexecutionerr
Copy link
Copy Markdown
Collaborator

Summary

  • Adds DocumentFields struct to PipelineState<S> so to_transaction_facts() emits non-None fields — legal gate now produces real Z3 signal instead of Unknown on every rule
  • Threads doc_fields through all 5 state-transition constructors (validate, verify_legal both arms, classify, reconcile, request_review)
  • Replaces the placeholder test_verify_legal_integration with two real AC scenarios: BASEXCLUDED passes au_gst::rule_38_190, INPUT fails it
  • Adds From<&TransactionInput> for DocumentFields in ingest.rs (amount parsed via .parse().ok(), no unwrap)

Closes #55. Unblocks PRD-7 Phase 2 (Z3 upgrade) and Phase 3 (audit sheet).

Test plan

  • cargo test -p ledger-core — all 152 tests pass
  • test_verify_legal_integration — BASEXCLUDED→Ok(Classified), INPUT→Err(NeedsReview) against au_gst::rule_38_190
  • Existing HSM, constraint, commit-gate, and type-mesh tests unaffected

@copilot please review

🤖 Generated with Claude Code

Adds DocumentFields to PipelineState<S> so to_transaction_facts()
emits non-None fields, making verify_legal() produce real Z3 signal
instead of Unknown on every rule. Closes #55.

- Add DocumentFields struct (vendor_jurisdiction, supply_type, tax_code,
  amount as Decimal, is_business_activity, is_ordinary, is_necessary)
- Add doc_fields field + with_doc_fields() builder to PipelineState<S>
- Thread doc_fields through all 5 state-transition constructors
- Fix to_transaction_facts() to map doc_fields into TransactionFacts
- Replace placeholder test_verify_legal_integration with two real
  scenarios: BASEXCLUDED passes au_gst::rule_38_190, INPUT fails it
- Add From<&TransactionInput> for DocumentFields in ingest.rs

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR extends ledger-core’s typed pipeline state to carry structured document-derived fields, so the legal verification stage can emit meaningful TransactionFacts (instead of always passing fact-free defaults that lead to Z3Result::Unknown).

Changes:

  • Added DocumentFields and threaded it through PipelineState<S> construction and all state transitions.
  • Implemented PipelineState<Validated>::to_transaction_facts() to populate TransactionFacts from doc_fields.
  • Replaced the placeholder legal integration test with two concrete scenarios for au_gst::rule_38_190().

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 4 comments.

File Description
crates/ledger-core/src/pipeline.rs Adds DocumentFields to pipeline state and maps it into TransactionFacts; updates legal integration tests accordingly.
crates/ledger-core/src/ingest.rs Adds From<&TransactionInput> for DocumentFields (currently populating amount).

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

pub source_ref: String,
pub confidence: f32,
pub issues: Vec<crate::validation::Issue>,
pub meta: crate::validation::MetaCtx,
Comment on lines +669 to +679
// US SaaS with BASEXCLUDED → legal gate passes → Ok(Classified)
let state = PipelineState::<Ingested>::new("doc1", "WF--BH--2026-01")
.with_doc_fields(DocumentFields {
vendor_jurisdiction: Some("US".to_string()),
supply_type: Some("SaaS".to_string()),
tax_code: Some("BASEXCLUDED".to_string()),
..DocumentFields::default()
})
.validate(Vec::new());
assert!(state.verify_legal(&solver, &rules).is_ok());

Comment thread crates/ledger-core/src/pipeline.rs Outdated
Comment on lines +680 to +689
// US SaaS with INPUT → legal gate fails → Err(NeedsReview)
let state = PipelineState::<Ingested>::new("doc2", "WF--BH--2026-01")
.with_doc_fields(DocumentFields {
vendor_jurisdiction: Some("US".to_string()),
supply_type: Some("SaaS".to_string()),
tax_code: Some("INPUT".to_string()),
..DocumentFields::default()
})
.validate(Vec::new());
assert!(state.verify_legal(&solver, &rules).is_err());
Comment thread crates/ledger-core/src/ingest.rs Outdated
Comment on lines +112 to +113
Self {
amount: row.amount.trim().parse().ok(),
@elasticdotventures
Copy link
Copy Markdown
Member

@copilot apply changes based on the comments in this thread

perform detailed comprehensive fix.

Copilot AI and others added 2 commits May 12, 2026 09:45
…al assertions

Agent-Logs-Url: https://github.com/PromptExecution/ledgrrr/sessions/fbd0329a-cc5e-411b-9a4e-89ae31919880

Co-authored-by: elasticdotventures <35611074+elasticdotventures@users.noreply.github.com>
Agent-Logs-Url: https://github.com/PromptExecution/ledgrrr/sessions/fbd0329a-cc5e-411b-9a4e-89ae31919880

Co-authored-by: elasticdotventures <35611074+elasticdotventures@users.noreply.github.com>
Copy link
Copy Markdown
Contributor

Copilot AI commented May 12, 2026

@copilot apply changes based on the comments in this thread

perform detailed comprehensive fix.

Implemented the full review-thread fixes in commits 535d33d and def2f0f: added #[serde(default)] for PipelineState.doc_fields backward compatibility, strengthened legal integration assertions to prove satisfied vs violated outcomes, and replaced silent amount parsing with a fallible TryFrom<&TransactionInput> + explicit parse error tests. cargo test -p ledger-core is passing.

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.

prd-7 phase 1: auto-populate TransactionFacts from pipeline state

4 participants