Repository navigation
MDM batches never fail on size at the end of a run - #906
Merged
Merged
Conversation
…place A match proposal stored the whole save request twice, as `command` and as `effects`, so it grew to about seven times its records and a GLEIF batch's proposal reached 19.7 MB, over the 16 MB bound, at the end of a long run. Migration 013 stores `effects_sha256` instead; save_batch compares the request's hash to it, and a proposal stored before keeps its effects and is checked as before. The 16 MB bound applies to the stored body; a proposal as sent may be 64 MB. mdm.prepare cuts a batch by a records byte budget (1 MiB) as well as by 1,000 records. The bounds live in `mdm/clean/limits.py`; every Python site reads it and a test holds the SQL functions to the same numbers. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FFKdv4nqKXKM9d5Cf2hEFk
The Stage measures a batch request before any SQL and refuses one over the bound with its size and the remedy. Each limit has its own name; messages read the constants; the deferred-record bound is tested; a changed request against a proposal stored before 013 is refused. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FFKdv4nqKXKM9d5Cf2hEFk
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FFKdv4nqKXKM9d5Cf2hEFk
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FFKdv4nqKXKM9d5Cf2hEFk
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FFKdv4nqKXKM9d5Cf2hEFk
paulananth
pushed a commit
that referenced
this pull request
Oct 11, 2026
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FFKdv4nqKXKM9d5Cf2hEFk
paulananth
pushed a commit
that referenced
this pull request
Oct 11, 2026
A Company bundle held its up to 1,000 records in one batch (about 1.4 MB for a real cm27 chunk). It is now cut by the same rule as mdm.prepare (#906): at most limits.BATCH_RECORDS records and, past the first record, limits.BATCH_RECORD_BYTES. The cut has one home, limits.batches(rows, encode), used by both creators (GoF consult: extract one function, no pattern). The bundle writes records.{n}.jsonl, one consumer per bundle, batch ids company:{bundle}:{n}, checkpoints n/n+1 and one publication key for every batch. verify_company_bundle rebuilds the records from the workers and compares every batch file with the same cut. The 1..1000 bound on the documents list reads limits.BATCH_RECORDS. Tests: the preparation tests read every batch; a new test cuts a bundle to one record per batch and checks checkpoints, one consumer, one publication key, verification and equal records; the limits tests call limits.batches. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
paulananth
added a commit
that referenced
this pull request
Oct 11, 2026
* L4: the Company main reading compared over a whole capture, in shards --limit 0 reads every receipt-pinned submission; --shard k/n splits them across processes; each source.read unit removes its own artifacts once verified. A 10-submission shard gives the same evidence as before. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FFKdv4nqKXKM9d5Cf2hEFk * L4: the whole capture's Company main reading is equal to the retained loader All 76,230 pinned submissions, 76,230 Company rows and 8,065,661 filing rows, every main table equal (4 shards, 17:51-18:43 ET). The ticket records the landed-parquet finding and the remaining L4 parts; L6 closes with #904. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FFKdv4nqKXKM9d5Cf2hEFk * L4: per-CIK preparation costs and batch size checked One Company on the raw path costs 0.57 s with a census read per chunk; mastering one bundle as one batch or one record per batch gives identical results. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FFKdv4nqKXKM9d5Cf2hEFk * L4: the refined plan for Name Frequency and preparation from the raw capture Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FFKdv4nqKXKM9d5Cf2hEFk * L4 (in progress): Name Frequency and Company preparation read the raw capture Name Frequency counts a population of main submissions documents named by receipt key, each read from the capture through the new census-raw.yaml (two a unit) and checked against its receipt; the switched-off cascade is refused when on. Company preparation reads its bundle's documents, the census and the exchange catalog through census-main, census, catalog and combine-census, every worker verified and retained. Both commands take the capture in place of landing manifests. Still in progress: the landed preparation tests are being rewritten for the raw capture; the whole-population census and chunk comparisons are running. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FFKdv4nqKXKM9d5Cf2hEFk * L4: Name Frequency from the raw capture equals cm27; approvals recorded The raw census equals cm27's census.json on 43,338 filers and 43,245 entries (entries, GLEIF, normalizers and version equal; 24 minutes). The SEC capture fixture moves to tests/support/sec_capture.py. The operator approved the Company main and census-main readings and the Dataset Contract (2026-10-10 19:25 ET). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FFKdv4nqKXKM9d5Cf2hEFk * L4: verify every combine worker; chunk 1 masters as the landed bundle verify_company_bundle re-built records from the last combine worker only; it now re-builds them from every unit's combine output, with each record's bronze origin, through the same helpers preparation uses. cm27 chunk 1 from the raw capture: 966 rows equal to the landed ones; mastered, 919 Companies, 919 bindings, 47 reviews, golden fields equal. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FFKdv4nqKXKM9d5Cf2hEFk * L4: chunks 2-7 equal from the raw capture; bundle size finding Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FFKdv4nqKXKM9d5Cf2hEFk * L4: Company preparation tests read the raw capture Fourteen tests prepare from a receipt-bound raw capture; the landed preparation tests and their landed oracle are removed (equivalence is held by the recorded whole-capture and chunk evidence). The installed caller test prepares from a raw capture too. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FFKdv4nqKXKM9d5Cf2hEFk * L4: the installed preparation caller passes on the raw capture Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FFKdv4nqKXKM9d5Cf2hEFk * L4: retire company_source.py and the landed Company contracts The SEC Company governance constants live in mdm/clean/sec_company.py, read by preparation and the tests. company_source.py, the five landed contracts, the landed qualification scripts and the landed oracle tests are deleted; the operations spec and the data-onboarding skill describe the raw-capture preparation. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FFKdv4nqKXKM9d5Cf2hEFk * L4 scratch: the Rust question research note and the mastering timing harness Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FFKdv4nqKXKM9d5Cf2hEFk * L4 ticket: preparation creator, comparable rows ticked; the configured pipeline deferred to 20c Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FFKdv4nqKXKM9d5Cf2hEFk * L4 ticket: census-raw read approved; rebased onto #906 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FFKdv4nqKXKM9d5Cf2hEFk * L4 ticket: GoF consult for the Company batch cut; next steps Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FFKdv4nqKXKM9d5Cf2hEFk * L4: Company preparation cuts its bundle as mdm.prepare does A Company bundle held its up to 1,000 records in one batch (about 1.4 MB for a real cm27 chunk). It is now cut by the same rule as mdm.prepare (#906): at most limits.BATCH_RECORDS records and, past the first record, limits.BATCH_RECORD_BYTES. The cut has one home, limits.batches(rows, encode), used by both creators (GoF consult: extract one function, no pattern). The bundle writes records.{n}.jsonl, one consumer per bundle, batch ids company:{bundle}:{n}, checkpoints n/n+1 and one publication key for every batch. verify_company_bundle rebuilds the records from the workers and compares every batch file with the same cut. The 1..1000 bound on the documents list reads limits.BATCH_RECORDS. Tests: the preparation tests read every batch; a new test cuts a bundle to one record per batch and checks checkpoints, one consumer, one publication key, verification and equal records; the limits tests call limits.batches. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * L4 ticket: the batch cut implemented and tested; landed provenance names deferred to the next SEC mapping Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * L4 review fixes: one raw-capture reader, the manifest bound in limits, dead code Three-axis review (Standards, Spec, GoF) of #905: - The raw capture was read twice (receipts, the bronze key check, the CIK from a key, the execute-then-verify of a source.read unit), and Company preparation imported Name Frequency's private helpers. One module, mdm/clean/raw_capture.py, now holds them; both callers use it. - Company preparation refuses a batch file over limits.RECORDS_FILE_BYTES and a manifest over limits.MANIFEST_BYTES, as mdm.prepare does. The 32 MB manifest bound, written in three places, is limits.MANIFEST_BYTES. - Dead code: the unused SourceRejected import and CATALOG_BYTES, a wrong noqa, write_name_frequency's unused policy parameter. ZERO is named CENSUS_DIGEST; the population bound is a named constant. - The custom-parsing experiment compared configuration with company_source.py and gleif_source.py, both retired; it is removed and the dated results note says so. The source-contract spec cites source.yaml for the identifier example; the CLI help no longer says 1..1000; the local-operations doc names the capture folder one way. Equal output: six real Companies prepared with f1508d9 and with this commit into the same folder give the same bundle byte for byte. 82 preparation, Name Frequency, limits, worker-artifact and engine tests pass. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * L4 ticket: the three-axis review and its fixes Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * L4 ticket: the 7 bundles re-prepared with the cut, equal records Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * L4: the installed proof on the raw-capture bundles passes; ticket closed 6,414 Companies; GLEIF 3,716 records, 3,052 bound; bindings 9216cc18, equal to the checkout replay; recovery on attempt 2; the second pass changed nothing (26.5 min). Report evidence/installed-company-proof-raw-20261011.json. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * whole-source-census ticket: the installed population proof is done Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Aneena Ananth <aneenaananth@MacBook-Air.local> Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
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.
MDM batches never fail on size at the end of a run
The installed Company proof failed at the GLEIF merge: a match proposal of 19.7 MB, over
mdm.record_match_proposal's 16 MB bound. The same failure happens on main with the old landed bundles, so it is not caused by the raw-capture work (#905). Size failures like this have recurred; this fixes the cause.Why proposals were too big
How one SEC batch grows on its way through the Stage (919 records):
A GLEIF batch of 1,000 records (about 1.9 MB) made a 19.7 MB proposal.
commandand aseffects.effectsis read only bysave_batch's equality check.What changes
effects_sha256in place ofeffects, andsave_batchcompares the request's hash to it.effectsand is checked as before.mdm.preparecuts a batch at 1 MiB of records as well as at 1,000 records. Batch ids now count batches, so a re-prepared input that is byte-cut gets new ids.edgar_warehouse/mdm/clean/limits.pyholds the bounds once; every Python site reads it, and a test holds the SQL functions to the same numbers.Company preparation's own one-batch bundle gets the same byte cut on the L4 branch, which rewrites that file.
Evidence
9216cc18…, equal to the checkout replay; a killed worker's item verified on its next attempt; the second pass changed nothing. Report.planning/workstreams/mdm-batch-size/evidence/installed-company-proof-20261011.json.caffeinate).Review
Three axes:
🤖 Generated with Claude Code
https://claude.ai/code/session_01FFKdv4nqKXKM9d5Cf2hEFk