Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 9 additions & 2 deletions docs/architecture.md
Original file line number Diff line number Diff line change
Expand Up @@ -105,8 +105,15 @@ owns the only round-1 threshold, and folding the two together would delete a com
leaving both names in place.

The stages are pinned by `tests/test_round1_preservation.py` against a frozen trace generated
from an independent transcription of the pre-refactor matcher. The PDF path is **not** migrated;
ADR 0020 shares the boundary rule with it, not the implementation.
from an independent transcription of the pre-refactor matcher.

**The PDF path runs the same four stages, and reached them separately.** It has its own retrieval,
evidence, assignment and classification stages in `diff_pdf.py`, its own byte-identity gate
(`tests/test_pdf_canonical_baseline.py`), and its own boundary tests. What the two paths share is
the *rule* — retrieval controls consideration, assignment controls correspondence — not an
implementation, and ADR 0020 deliberately does not unify them: an XML observation is a parsed tree
node and a PDF observation is a reconstructed block, so a shared matcher would have to pick one
representation and lose the other.

### Why the two paths exist at all

Expand Down
14 changes: 9 additions & 5 deletions docs/decisions/0020-matching-stages.md
Original file line number Diff line number Diff line change
Expand Up @@ -245,11 +245,15 @@ the contents of one stage change.
- **Let classification re-consult similarity.** Rejected with a carve-out: classification
legitimately asks *how much* the corresponding texts differ, which is what
`move.body_unchanged` records and needs no score. What it may not do is threshold a
correspondence score. On the XML side that separation now holds: `diff_bill.diff_bills` is
orchestration over the four stages, and the only round-1 cutoff lives in
`apply_similarity_assignment_rule`, an assignment act that runs before classification.
`diff_pdf._hunk_for_paired_blocks` still thresholds inside classification; the PDF track is
not migrated, and this record does not unify the two implementations.
correspondence score. Both pipelines now hold that separation. On the XML side
`diff_bill.diff_bills` is orchestration over the four stages, and the only round-1 cutoff lives
in `apply_similarity_assignment_rule`, an assignment act that runs before classification. On the
PDF side `diff_pdf._hunk_for_paired_blocks` used to call a pair *moved* when the anchors differed
and the bodies cleared `MOVE_THRESHOLD` — a threshold over correspondence evidence, inside
classification. It no longer receives a similarity at all: the rule moved unchanged into
`pdf_round1_move_basis`, an assignment stage, and the function is now the `modified` emitter.
The two pipelines share this boundary rule; they do **not** share an implementation, and this
record does not unify them.
- **Keep `Correspondence` pair-shaped, and revisit if consolidation proves common.** Cost
asymmetry: capability costs a type permitting N sides, while not having it turns any later
change into a migration through every consumer of the matcher's output.
Expand Down