Repository navigation
Conversation
Brings the three draft ADRs from the 2026-09-18 cache audit, and the spikes they cite, onto one branch so they can be reviewed together. They were drafted as separate PRs (#180, #181, #182) and revised there during the 2026-09-19/20 design session; this commit is their state at the end of that session, unchanged. - ADR-007: tallyman owns result materialization (no xorq cache nodes in builds); Buckaroo is a displayer; every diff is built as an entry. - ADR-008: every file carries a visible __row_order column and every page request sorts by it. - ADR-009: materialization runs single-partition, and result_digest is a digest of the snapshot's content. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
… ADRs - ADR-009 D6 (new): create runs the query twice and compares digests, so a non-reproducible recipe is known from birth and its file is pinned; a cheap entry gets the same check and is materialized if it fails. Adds a Testing section. The entry's schema is read from the file. - ADR-007 D11 (new): one write at a time per project, by taking the existing project file lock around every write; replaces the per-entry lock. Two tallyman servers on one project is unsupported (#183). - ADR-007 D12 (new): files are deleted only by an explicit user action; the startup warm-up stops rewriting deleted files; no disk budget yet. - ADR-007 D6: tallyman stops remembering Buckaroo sessions and re-posts every time, with a session id derived from project, hash and view kind. - ADR-007 D9: the agreed order of work. Nothing starts before review. - ADR-007 open question 1: whether two kinds of entry survive. Unanswered. - Testing sections for ADR-007 and ADR-008, marking which tests are red on main today. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This was referenced Sep 20, 2026
An adversarial review of the three draft ADRs, and Paddy's decisions on its findings (2026-09-20). Still Proposed; nothing is implemented. - ADR-007 D10 (every diff is built as an entry) moved out to #188, so the set stays about the core structure of the cache. D10 is kept as a stub so that references to D11 and D12 stay valid. The live diff is recorded as the one known exception to the governing rule. - ADR-007 D5: the verify sweep is not a caller of ensure_materialized; it reads and never writes. The ordered-copy gap is recorded as accepted. - ADR-007 D6: the session id is derived from project and content hash (closes #172); the exact condition under which Buckaroo skips a repeat /load_expr; deleting a snapshot ends no session; an unfaithful heal posts force_reload, since evict_session worked by forgetting a record that D6 removes. - ADR-007 D11: three limits of the project lock (per-thread re-entrancy, recalc granularity left open, reads not covered, #118). #186 tracks the waiting it causes. - ADR-007 D12: a file is written only because something is about to read it. The warm-up sentence now states the precise condition. - ADR-007 D2: memoizing the read stops tables piling up, not footer reads. - ADR-008 D2, D7: CSVs do not already work this way. The intermediate is keyed by path and overwritten in place (#168), so D7 cannot land before that fix. CSVs go through source identity and the ordered copy is built from the content-addressed clone. - ADR-008: "repeatable pages" asserts the exact rows; a new test that an edited CSV forks the hash; memory at depth recorded under Consequences as a performance matter, deferred. - ADR-009 D1, D3: single-partition execution does not make an ungrouped float total a function of the rows alone; it depends on the parent file's row-group layout (#187). Row-group size and batch_size are pinned and the manifest records a snapshot format version. - ADR-009 D6: the cheap-entry half moved to #185; the limits of running twice are stated, and the #88 lint is mentioned. - ADR-009: four stale cross-references to ADR-008 fixed. - All three Testing sections: normal TDD. Every test goes in the failing-tests commit; a test of a missing function fails on import. New evidence scripts, each runnable from a clean temp dir: scripts/spike_csv_source_identity.py (ADR-008 D2, D7), scripts/spike_float_layout_digest.py (ADR-009 D1, D3), scripts/spike_deep_page_memory.py (ADR-008 Consequences). Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Keep two kinds of entry (ADR-007 open question 1). ADR-007 gains D13 (a file is cache only if ensure_materialized can re-create it) and D14 (a reset leaves compute_cache alone), closes the ordered-copy gap in D5, and adds the klass hot-reload fix to D6. ADR-008 rewrites D4 as a three-part test for cheap, corrects D6's three-way join claim, and adds D10 (natural order on every order_by), D11 (hoist a non-final sort) and D12 (a raw parquet read is a build error). ADR-009 says how a loaded build gets onto the single-partition connection and extends the format version to ordered copies. Adds seven evidence scripts under scripts/. Items not yet confirmed by Paddy are marked as such in the ADR text. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Contributor
Author
|
Contained in #189: this branch is an ancestor of feat/adr-007-009-cache-redesign. |
This was referenced Sep 24, 2026
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.
Three draft ADRs for review, with the scripts they cite. Docs and scripts only; nothing here is implemented, and implementation does not start until all three have been reviewed.
This replaces #180, #181 and #182, which held one ADR each. The first commit is their content unchanged. The second folds in the last answers from the 2026-09-19/20 design session. The third folds in an adversarial review of this PR and Paddy's decisions on its findings. The fourth (
f777d06) folds in a second review, which read the ADRs against the code and probed each claim with a script. Its decisions and findings are below.What to read
plans/ADR-007-tallyman-owned-materialization.mdplans/ADR-008-row-order-of-reads.md__row_ordercolumn, and every page request sorts by it. It also decides what a cheap entry may contain, how sorts and joins stay deterministic, and which reads are build errors.plans/ADR-009-digest-stability.mdEach ADR opens with a Terms section, and a bare label such as "D5" always means that ADR's own decision. Another ADR's decision is always written with its number and what it decides.
Decisions made in the design session
__row_order:int64,0..N-1, last column, visible. Each materialization overwrites it. A cheap entry that drops it is a build error. Only the exact name is reserved, so a debugging copy such as__row_order_v1survives (ADR-008 D2, D3, D6).Buckaroo's half of the paging fix is filed as buckaroo-data/buckaroo#974.
Decisions made in the second review (fourth commit)
__row_order, so the test has to guarantee the column is still present and unique (ADR-008 D4).order_by. Natural order is a row's position in the file it came from, which__row_orderrecords. Paddy's rule: when a supplied sort is not deterministic, impose the natural order into each order by. It is applied at every sort in a recipe and on every page request, with the remaining sortable columns after it (ADR-008 D10).compute_cache/alone, and source clones are parked, not deleted. A clone is the frozen copy of a source file underdata/.cas/. Each class of file gets a re-create rule, and a file is cache only ifensure_materializedcan re-create it (ADR-007 D13, D14).What the second review found
Each is backed by a script in this PR or by the source it cites.
a.join(b).join(c)shows the expected columns and passesbuild_expr, then raisesIntegrityError: Name collisions: {'__row_order_right'}from the canonical sort. A join entry that kept__row_order_rightfails the same way when joined to a third. The writer now drops that column, and the build turns ibis's message into an instruction (ADR-008 D6)._canonical_sortedextends an author's sort only when it is the top node. Afterorder_by(amount desc), a followingmutate,selectorfilterleaves the rows in parent order, and a top-three entry is written as40, 60, 50. The entry is still classed worthy, so the author pays for a copy that ignores the sort (ADR-008 D11).limitdecides which rows the entry holds.order_by(g).limit(1000)with about 15,000 rows tied at the cut returned 5 different row sets in 5 runs on the default connection, and 1 with the natural order appended (ADR-008 D10).unnestinside a select turned 6 rows into 8 with duplicate__row_order. Window functions,random()and a filter against a second file are also plain selections or filters to that list. The test now has three parts (relation allow-list, exactly one file read, no value operation that multiplies rows, depends on row order or is not pure), is computed once at build and recorded in the manifest, and retires the regex overexpr.yaml(Cache classifier parses xorq build YAML with regex — silent misclassification if the format drifts #12) (ADR-008 D4).xo.deferred_read_parquet(abs_path)is what tallyman's own hints recommend. It gets no clone, no digest and no ordered copy, so the entry has no__row_order. A raw parquet read becomes a build error (ADR-008 D12). Nine test files call it today.reset_toparks entries and snapshots in the bullpen (the directory a reset moves retired files into) butgc_casdeletes clones outright. After a reset to an earlier step and forward again, a cheap entry fails immediately withAt least one path is requiredalthough the live source is unchanged, and a worthy entry fails at its next heal. This is independent of this PR, and it is the state the "accepted gap" in ADR-007 D5 would have left reachable. D5 no longer accepts it (ADR-007 D13).shutil.copy2, which is a second, non-atomic writer of snapshots (ADR-007 D14).load_exprmakes its own backend objects, so a build loaded beside atarget_partitions = 1connection still ran on 14 partitions: 5 distinct digests in 5 runs. Rebinding it withreplace_sources, orSETon each backend it made, gave 1 (ADR-009 D1).reload_project_sessionsfinds open grids in that record, and Buckaroo has no route that lists sessions. With derived session ids the reload posts/reload_expr/<id>per entry and treats a 404 as "not open" (ADR-007 D6).scan_parquet().with_row_index()numbers a 184-row-group source in file order, which answers ADR-008 open question 1's "needs checking". The design also closes viewer: expensive-parent children render an empty buckaroo grid on a cross-machine clone — /load_expr replays the build, whose snapshot key is bound to the build-time path #77 (an empty grid on a clone at another path), because the snapshot's name is now the entry's content hash on every machine.Also changed: a create always runs the query and replaces any file at the path, and only a heal uses the existence shortcut (ADR-007 D4). A heal runs the query once (ADR-009 D6). The format version covers the ordered copies polars writes (ADR-009 D3). Under
saltidentity mode a worthy entry is written without the canonical sort while the early return inrewrite_for_buildstays (ADR-007 Consequences).Not yet confirmed by Paddy
Each is marked "not yet confirmed" in the ADR text, so any can be struck.
__row_order_right(ADR-008 D6), and the ban on raw parquet reads (ADR-008 D12).compute_cache/, with a digest recorded when the copy is first written (ADR-007 D13).Moved out of this set
Already tracked, and cited: #168 (CSV source identity), #118 (
Already borrowedon concurrent reads), #12, #76, #77 and #22.Not filed as issues, and recorded in the ADRs only: the clone loss across a reset (above), the klass reload gap, and the memory a deep sorted page holds (ADR-008 Consequences; a performance matter, taken up after correctness).
Still open
__row_order, andoriginal_row_orderis renamed to__row_order. Both are adopted as defaults and not confirmed in so many words (ADR-008 open questions 1 and 2).Evidence
Every figure in the ADRs comes from a script in this PR, each of which runs from a clean temp dir:
scripts/spike_bare_read_chaining.py(ADR-007 D3)scripts/spike_reset_roundtrip.py(ADR-007 D13, D14)scripts/spike_stream_order.py(ADR-007 open question 1, ADR-009 D1)scripts/spike_window_read_order.py(ADR-008, the problem and the rejected engine setting)scripts/spike_row_order_paging.py(ADR-008 D3, D5, D6)scripts/spike_csv_source_identity.py(ADR-008 D2, D7)scripts/spike_deep_page_memory.py(ADR-008 Consequences)scripts/spike_cheap_classifier.py(ADR-008 D4)scripts/spike_row_order_joins.py(ADR-008 D6)scripts/spike_sort_grafting.py(ADR-008 D5, D10, D11)scripts/spike_ordered_copy_layout.py(ADR-008 D2, ADR-009 D3)scripts/spike_float_aggregate_digest.py(ADR-009 D1)scripts/spike_float_layout_digest.py(ADR-009 D1, D3)scripts/spike_single_partition_loaded_build.py(ADR-009 D1)scripts/spike_logical_digest.py(ADR-009 D2, D3)Checked locally:
ruff checkacross the repo, andruff format --checkon the fifteen spike scripts. The seven new scripts were each run and reproduce the figures cited. The eight from earlier commits were not re-run in this round. Every script path the ADRs cite resolves, and the source line references added in this round were checked against the code. Docs and scripts only, so pytest was not run and CI was not watched.🤖 Generated with Claude Code