refactor(parser): extract item rules and selection engine #105

Merged
TimCane merged 3 commits from feat/92-extract-item-rules into main 2026-07-07 11:30:58 +01:00
TimCane commented 2026-07-07 11:17:21 +01:00 (Migrated from github.com)

Summary

  • Extract item building out of ReceiptParseEngine into competing rules behind a selection engine (ADR-0006 Phase A, step A4).
  • Add IReceiptRule + ItemCandidate: each rule returns an item reading (or a reject) with a confidence; the engine keeps the highest.
  • Port name shaping (clean, quantity, unit-price column) into ItemText, shared by the rules.
  • Rules: NamelessPriceRejectRule > UnitPriceColumnRule > QuantityNamePriceRule, calibrated so selection reproduces the old first-match order.
  • Item-name shaping is the only logic moved; the classifier's UnitPriceDetail/bare-charge pre-filters stay where A3 left them (a distinct reject: "unreadable amount" vs this layer's "price with no name").
  • Update docs/06 (parsing) and docs/11 (testing); no wire-contract change, so docs/03-05 untouched.

Test plan

  • dotnet build backend/BillSplitter.sln -warnaserror: 0 warnings, 0 errors.
  • dotnet test backend/tests/BillSplitter.Tests: 86 passed, corpus byte-identical (no expected.json changed).

Closes #92

## Summary - Extract item building out of `ReceiptParseEngine` into competing rules behind a selection engine (ADR-0006 Phase A, step A4). - Add `IReceiptRule` + `ItemCandidate`: each rule returns an item reading (or a reject) with a confidence; the engine keeps the highest. - Port name shaping (clean, quantity, unit-price column) into `ItemText`, shared by the rules. - Rules: `NamelessPriceRejectRule` > `UnitPriceColumnRule` > `QuantityNamePriceRule`, calibrated so selection reproduces the old first-match order. - Item-name shaping is the only logic moved; the classifier's `UnitPriceDetail`/bare-charge pre-filters stay where A3 left them (a distinct reject: "unreadable amount" vs this layer's "price with no name"). - Update docs/06 (parsing) and docs/11 (testing); no wire-contract change, so docs/03-05 untouched. ## Test plan - `dotnet build backend/BillSplitter.sln -warnaserror`: 0 warnings, 0 errors. - `dotnet test backend/tests/BillSplitter.Tests`: 86 passed, corpus byte-identical (no `expected.json` changed). Closes #92
Sign in to join this conversation.
No description provided.