Repository navigation
feat(fto): claim tree, features and all-elements claim chart model (ADR 0008) - #19
Merged
Merged
Conversation
…DR 0008) Pure domain model for FTO comparison, tested on real US/EP claims (no API, DB or UI yet). Claim sources (verified 2026-10-04): - US: per-patent grant full-text XML (PTGRXML) via ODP grantDocumentMetaData.fileLocationURI, present for 60/60 sampled patents (2007-2026). Numbering and dependencies come from office markup (<claim num>, <claim-ref>); initial features follow nested <claim-text> clauses, with exact character spans (handles <b>1</b>. preambles). - EP: EPO OPS claims, flat paragraphs per language. Numbering and dependencies are parsed from wording (ranges, "or", "any preceding claim") and marked ops_text_parsed. OPS states no language of the proceedings, so EPC Art. 70(1) authenticity is left unknown and every EP set warns that it may be a translation. Model and conclusions: - Features start as "proposed" (clause structure is not legal claim elements); a path with unconfirmed features never concludes "reads". - Findings: literally_present / present_by_equivalent / absent / undetermined; equivalence is a supplied professional judgment, never computed. - All-elements rule. Multiple-dependent references are alternatives (37 CFR 1.75(c); EPC Rule 43(4)): each is its own path, and the claim reads if any path reads. My first version merged parent features cumulatively, which over-requires features and could wrongly say "does not read" (the dangerous direction). Fixed. - Conclusions are computed exactly by recursion over claims instead of path enumeration (EP-1819002-B1 claim 15 has 2,304 paths). A randomized test (150 scenarios x 15 claims) matches full enumeration exactly. Hand-checked against the text: claim counts (15/8/6 EP, 14/16/11/7 US) and every EP dependency. Mutation check: switching "all alternatives fail" to "any fails" breaks the targeted test and the property test. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
corlin
added a commit
that referenced
this pull request
Oct 4, 2026
## What Claim text for the comparison model (#19), stored with the ADR 0006 pattern. The design is in **ADR 0009**. - Global, append-only table `patent_claim_documents` (worker SELECT+INSERT, app SELECT, no tenant columns). - `ClaimDocumentFetcher` (worker): fetch → archive the raw bytes → record. A source failure writes nothing; "not found" is recorded. ## US: two-step fetch with safety checks (all verified live) 1. ODP lookup by patent number → `grantDocumentMetaData.fileLocationURI`. 2. That URL answers with **one 302 to a signed, time-limited `data.uspto.gov` URL**. The client follows only USPTO dataset URLs, and only a redirect to `data.uspto.gov/files/` (SSRF guard). It **sends the API key only to `api.uspto.gov`**, and records the redirect **without its signature**, which is a temporary credential. Only the `<claims>` element goes into the DB. The **full XML names inventors**, so it's archived in object storage under the open ADR 0006 retention question. ## EP OPS claims for the exact publication. A 404 (an A1 publication, or an unknown number) is recorded as `not_found`. ## What the stored text represents (important for FTO) - **US = claims as granted.** Reexamination, IPR and correction certificates can later amend or cancel claims, and they're **not** in the grant XML. Stored as `text_represents = "as_granted"`. - **EP = that specific publication.** A `B2`/`B3` replaces the `B1` text. Stored as `"as_published"`. - The US `fileCreateDateTime` is a **file** time, not a data date (a 2007 grant shows 2024-09-29). - Fetching post-grant changes (PTAB/reexamination; automatic selection of B2/B3) is follow-up work. ## Verification - **Live:** all **16** coverage-set patents fetched and parsed, with **no parse failures**. The only warnings are informational: "preceding claims" ×31 (expanded into alternatives) and long features ×9. - **Unit tests:** allowlist, redirect host, no leakage of the key or signature, EP 404. - **Postgres tests:** grants; US and EP end to end with the stored text **parsed back by the ADR 0008 parsers**; three not-found shapes; failures write nothing. ## Validation - `./scripts/test-postgres.sh`: **111 passed** (+8) - `.venv/bin/pytest apps/api/tests/unit/`: 417 passed (+4) - `pnpm test:web`: 62 passed; `pnpm build:web`: ok - `verify-source-lock`, `verify-scaffold`, `verify-p0-02`, `verify-p0-e2e`, `docker compose config`: ok 🤖 Generated with [Claude Code](https://claude.com/claude-code)
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.
What
The core FTO domain model, as pure functions tested on real US/EP claims. No API, DB or UI yet (ADR 0008).
modules/fto/us_claims.pymodules/fto/ep_claims.pymodules/fto/model.pymodules/fto/chart.pyClaim sources (verified)
PTGRXML, same API key). It was present for 60/60 sampled patents (2007–2026). Numbering and dependencies come from the office's markup. The initial features follow the nested<claim-text>clauses, with exact character spans, including<b>1</b>.preambles.ops_text_parsed.Conclusions
proposed. Drafters' clauses aren't the same as legal claim elements. A path with unconfirmed features never concludes "reads", and features over 400 characters are flagged for splitting.literally_present/present_by_equivalent/absent/undetermined. Equivalence is a supplied professional judgment, never computed.EP-1819002-B1claim 15 has 2,304 paths. A randomized test (150 scenarios × 15 claims) matches full enumeration exactly.Verification
fixtures/fto/README.md).Validation
.venv/bin/pytest apps/api/tests/unit/: 413 passed (14 new)./scripts/test-postgres.sh: 103 passedpnpm test:web: 62 passed;pnpm build:web: okverify-source-lock,verify-scaffold,verify-p0-02,verify-p0-e2e,docker compose config: okNext
Claim-text acquisition adapters (US XML, EP OPS) with storage; product-feature input; feature confirmation workflow; then API/UI and jurisdiction rule packs.
🤖 Generated with Claude Code