Repository navigation
Capture JSON sources as json-leaf-text/v1 - #54
Conversation
Built-in HTTP captures have emitted evidence-window v2 since 0.2.0a3, but the projection reader still accepted only v1, so groundnut-equivalence refused any new HTML, PDF or JSON run. Admit v1 and v2 and keep comparing the complete window, including producer identity. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
ClinicalTrials.gov API v2, bioRxiv/medRxiv and Europe PMC publish primary records only as JSON. json-leaf-text/v1 parses strictly and renders one `<path>: <value>` line per leaf, keeping number literals as written; invalid, duplicate-key, over-deep or over-large JSON fails closed. Capture declarations admit application/json while media matching stays strict. HTML, PDF and plain-text extraction are unchanged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Add the application/json fixture to the evidence-window v2 equivalence test now that JSON sources capture as json-leaf-text/v1. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Each nesting level held a full copy of its path prefix, so memory grew with depth times key length: a 6 KiB gzip body reached 886 MiB resident and a 30 KiB one exhausted a 3 GiB cap. Keep the open path as a list of steps, cache joined prefixes only while short, and build each line, key and value only up to the remaining budget. Output is unchanged; tests compare the renderer with a reference rendering at every cut point and bound peak memory with tracemalloc. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The depth cap ran only after json.loads, whose C parser recurses once per container: a 10 KB body of brackets crashed a thread with a 512 KiB stack. Scan bracket depth outside strings before parsing and fail closed beyond 64. The scan uses possessive quantifiers, so an unterminated string of escaped quotes stays linear instead of the quadratic time a backtracking pattern takes. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Classify a JSON window as hollow at up to 4,096 characters when it matches a block-page pattern, the bound HTML uses, and as sparse under 256 otherwise. Give v1 its own frozen copy of the patterns so an HTML edit cannot reclassify stored v1 windows on replay. Reject number literals with non-ASCII digits, which the pure-Python scanner fallback would otherwise accept. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Up to 0.2.0a3 the resolver stored application/json as raw http-text/v2. Say what changes: new hashes, bodies that now fail closed, small envelopes no longer complete, and equivalence reporting different against old raw-JSON snapshots. Add an unreleased MIGRATION entry. Pin with a fixture archived by 0.2.0a3 that old raw-JSON snapshots replay byte-for-byte. Fix the capture docs: the full NCT04368728 record overflows the extraction cap, so cite ?fields=protocolSection and retain fields; undeclared JSON that cannot be extracted reports its own failure. Cover HTTP charset and UTF-8 BOM handling. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Important
This repository does not receive automatic reviews because it has fewer than 10 stars. ⚙️ Run configuration
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
Owner decision on the size cap: keep the current 8,388,608-character extracted-text cap. (This is a character cap, not an 8 MiB response-byte cap.) Do not raise it for the large ClinicalTrials.gov example and do not introduce another extractor format in this PR. Use explicit filtered URLs where their selected fields cover the claim being cited. Fork CI approved after inspecting the code/workflow changes. Independent review and local tests are running; this comment records the scope decision, not yet a merge approval. |
|
Review update: no blocking production-code finding from the code review or independent JSON review. The original head passed 584 tests locally, but CI on Python 3.12.14 exposed four failures in the test that expected the stdlib’s permissive Unicode-digit behaviour. I pushed the narrow repair in The same commit records the owner decision in READ-TIME-CAPTURE: retain the character cap; “complete” applies to the explicitly selected protocol response, never to omitted results/full-record coverage. #53 is now reviewed and merged, with 483 local tests and green CI. It was merged with ancestry preserved, so this stack does not need a history rewrite just to remove #53’s diff. Waiting for the updated #54 CI before merging; no pipeline pin or existing run configuration has been changed. |
b1rdmania
left a comment
There was a problem hiding this comment.
Reviewed the JSON extraction/capture/replay changes and exact final head 57208cf, including an independent review. 584 local tests pass and CI is green on Python 3.12.14. The scanner regression repair preserves the ASCII-guard check; an independent mutation check confirms it catches removal of that guard. Keep the existing character cap and the documented filtered-response evidence boundary. No blocking findings; no release/pipeline adoption implied by this merge.
The merge-base changed after approval.
What changed
Adds JSON source support.
application/jsonresponses becomejson-leaf-text/v1evidence windows:<path>: <value>line per leaf, in document order;The extractor identity (
charset,max_characters,max_depth: 64,max_values: 1000000) is recorded on evidence-window v2.Fail-closed checks run in this order: the value bound and a linear, string-aware nesting scan (both before parsing), then strict parsing.
source_media_unsupported.source_too_large.Rendering memory is bounded by the character budget, not by depth × key length.
The v1 window rules are frozen and re-applied on replay:
empty: an empty root;hollow: 4,096 characters or fewer, matching v1's own frozen block patterns;sparse: under 256 characters;complete.Capture declarations admit
application/json. The declaration-to-response media match stays strict.Behaviour change: up to 0.2.0a3, the resolver stored
application/jsonas rawhttp-text/v2. Now:complete.Existing raw-JSON snapshots replay unchanged; fixtures archived by 0.2.0a3 pin this. Comparing a new capture with an old raw-JSON snapshot reports
different. See docs/MIGRATION.md (Unreleased).Evidence
The ClinicalTrials.gov API v2, the bioRxiv/medRxiv API and Europe PMC REST publish primary records only as JSON. Their HTML pages are script shells (the ClinicalTrials.gov study page captures as a 175-character sparse window) or return 403. In the IC pipeline that leaves current trial status and preprint abstracts uncapturable; see research-pipelin3/claude-research-pipeline#105. Synthetic fixtures with the same shape are in
tests/test_json_sources.py.Acceptance:
COMPLETED,47079);Review hardening, measured through the default
HttpResolver:Owner decision needed
The full NCT04368728 record renders to 8.88M characters, over the 8,388,608-character cap (about 4x growth from repeated paths), so it captures as
truncated.?fields=protocolSection, withfieldsretained forclinicaltrials.gov, renders to 206,529 characters and captures complete. The docs use that form.Options:
Lane
Contract impact
json-leaf-text/v1,application/jsonadmitted in the existing declaration schemas, and fixed failure details. The change from raw JSON capture is disclosed in EVIDENCE-WINDOWS and MIGRATION.Determinism and disclosure
Validation
No version bump or release; that's your call. The MIGRATION entry is under "Unreleased".