Repository navigation
D-CODEGRAPH-0: wide closure, merge-on-read refresh, versioned DR index (D-DYNBAG-4) - #1923
Conversation
locate finds a global id's (tile ordinal, local) across the listed tiles and refuses an id held by two tiles or none. extends says whether a map only appended to an older one: prepare keeps the supplied order, so an appended id never renumbers an existing position. Tests live in tests/dr.rs, since dr.rs must not name its parent module. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01X6y3drwKSE2zSgoexheLFX
…fold, refresh closure_wide runs the same semi-naive fixpoint over any number of positions, one row at a time; rows keep only nonzero 256-position blocks, with a multi-word presence mask per row (no tile cap). DeltaLog appends ADD / RETIRE edges; refold absorbs them only when called; refresh recomputes only the rows that reached a retired edge's source and seeds additions incrementally. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01X6y3drwKSE2zSgoexheLFX
…dt64 Axis::for_survivors Cube::new_tiled places ids at tile_ordinal * 256 + local through MapTable::locate (D-DYNBAG-4's global -> (tile, local) map). closure_wide folds base + delta log and never refuses for width. add_edge / retire_edge append to a per-relation log; refresh_closure recomputes only affected rows; refold runs only when called. rebase adopts a new frame only if every tile's map extends the old one: a resize is a new frame, never in place (D-DYNBAG §4.3). Axis::for_survivors is §4.1's width rule. The narrow single-tile path is unchanged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01X6y3drwKSE2zSgoexheLFX
…ds whole rows Pos is u32; the tile layout comes from dt64's Axis::for_survivors, one tile keeps the single-tile path bit for bit, more tiles use Cube::new_tiled. Closures are WideRows from closure_wide. impact copied only the first word of a closure row, which was wrong once a graph has more than 64 positions; it now reads the whole row. TooMany and ClosureWidth are gone; their two tests are re-pinned to the new truth (a 70-function chain closes across words; 300 symbols open across two tiles). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01X6y3drwKSE2zSgoexheLFX
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01X6y3drwKSE2zSgoexheLFX
…bol width xlog tests/wide_closure.rs: narrow vs wide bit-identical up to 64 positions; a 694-position three-tile graph with cross-tile cycles against a DFS written in the test; absent blocks allocate nothing (with its anti-vacuity twin); refresh equals a rebuild after every step, with rows_recomputed == |A|; refold is explicit and preserves the closure; rebase accepts appends and refuses a reorder; growth is a new frame. codegraph: on a multi-tile store the cube's support mask covers every reserved position (12 words for 694 symbols) and callers panicked on the width mismatch; partners now trims to the symbol width. Found by running on mask-risc's real store; queries_work_across_tiles pins it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01X6y3drwKSE2zSgoexheLFX
One accessor returns a relation's effective lanes: the base when its log is empty, otherwise a cached fold of base and log, dropped on every add_edge, retire_edge, refold and rebase. Terminals (support, bag_count), the narrow closure, closure_wide and materialize_rows read through it, so views no longer see stale edges until an explicit refold. Reads never modify the base or the log; refold stays the only thing that replaces the base. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01X6y3drwKSE2zSgoexheLFX
…g is a multiset Codegraph::refresh_crate re-reads one crate's rows and updates the resident graph without rebuilding: rows carry their crate, positions never renumber, new symbols extend the last tile under a new frame (growth past the reservation is NeedsReopen), edge changes go to the cube's delta log grouped by relation and in ascending (src tile, src, dst) order, cached closures are refreshed. refold() absorbs the logs only when called. A call graph is a bag: two call sites of one pair are two edges. The delta log fold counts occurrences (ADD +1, RETIRE -1, floored at 0) and the refresh diffs multisets; the closure sees an edge only while its count is above 0. Found because a refresh to rev2 counted one call site of area_of where a clean open counts two. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01X6y3drwKSE2zSgoexheLFX
Measured on mask-risc's store (17,155 rows), release: refresh_crate of an unchanged crate 24,589-36,259 us, of which reading the rows file is 14,078-19,708 us. A millisecond result is a failed gate: the reader builds one String per field (about 120,000 allocations) and refresh re-interns and diffs through string-keyed maps. Recorded here before the fix. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01X6y3drwKSE2zSgoexheLFX
…sed references Rows are stored as u32 ids into one interner plus a predicate code; parsing allocates only for names not seen before. refresh_crate skips a crate whose rows file digest is unchanged (no delta) and diffs changed crates with sorted u64 keys. references compares ids, not strings. Measured on mask-risc's store (17,155 rows), release: reading the rows file 14-20 ms -> 6.8-10.3 ms; refresh of an unchanged crate 25-36 ms -> 1.5-1.7 ms; references 122 us -> 45 us; impact 286 ns. Still a failed gate: the remaining cost is reading and hashing the 2.5 MB text file, which only a format change on the ruff_charon side removes. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01X6y3drwKSE2zSgoexheLFX
…h it Operator ruling: versioned, replayable immutability is the DR global -> local index itself; reading an older version is the same lookup with the version as part of the key. dt64::dr: each tile's mapping is an append-only log keyed by RouteVersion. An extension logs a longer length (no copy), a replacement adds a generation, a removal logs an event; nothing is updated in place. MapTable and RouteLog share one RouteVersion sequence through a VersionClock. map(frame, tile) reads the layout the frame was sealed at; map_at(version, tile) reads any version by number; a frame from another table or a future version is refused. Reads return a borrowed TileMap that respects the version's length and allocate nothing. xlog: Cube::rebase drops its private per-tile snapshot and reads the old layout through the index; a cube keeps answering after the table advances. Re-pinned to the new rule (old assertion kept as a comment): dt64 tests/dr.rs (two), xlog tests/cube.rs, xlog-relcomp-probe an_old_map_frame_replays_its_own_layout (method admission is still gated by the bind store's route versions, not the tile map). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01X6y3drwKSE2zSgoexheLFX
…AG-4), binary lanes Plans: d-codegraph-0-wide-closure-v1, d-dynbag-4-dr-versioned-mapping-v1, d-codegraph-0-binary-lanes-v1. STATUS_BOARD: D-DYNBAG-4 in PR (partial), D-CODEGRAPH-0-C2 in PR, D-CODEGRAPH-0-BIN queued. Gap-map entry: the wave's rulings, results, measured numbers, the failed refresh gate and what fixes it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01X6y3drwKSE2zSgoexheLFX
|
Important
This repository does not receive automatic reviews because it has fewer than 10 stars.
|
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: dbe4505767
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
…h next-step proposal) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01X6y3drwKSE2zSgoexheLFX
…e::stage/commit, binds keep their global id refresh_crate now stages the interner (SymbolStage), the positions (PosStage), the grown tile map (not handed to the table), the edge batch (Cube::stage, checked without changing the cube) and the closure refresh (Cube::stage_closure). A refusal at any of these changes nothing: no interner entry, position, last_owner, table version, frame, log entry, lane, mask or digest. The commit (table advance + seal, Cube::commit, absorb, closures, lanes) has no error path. Cube::rebase checks before it changes anything. Node::Bind keeps the global id it binds, and an extending rebase or commit places a value that was unmapped when the view was built (codex P2 on #1923). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01X6y3drwKSE2zSgoexheLFX
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01X6y3drwKSE2zSgoexheLFX
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01X6y3drwKSE2zSgoexheLFX
…2 BIN amendment, P3 DT64 authority census); pin egglog Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01X6y3drwKSE2zSgoexheLFX
…ow that cited the floating line Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01X6y3drwKSE2zSgoexheLFX
…ble, smallest adapter, falsifiers; no code) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01X6y3drwKSE2zSgoexheLFX
…its merge point Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01X6y3drwKSE2zSgoexheLFX
…1a5sw D-TGL: F-LAND / F-DISCARD lab, Thought-Git lifecycle contract, post-merge record for #1923
Summary
This removes slice C's 64-position limit and follows your rulings: wider call chains, presence bits for thin provisioning, sparse writes merged on read, and versioned replayable immutability kept in the DR index itself. Since the architecture review, it also makes
refresh_crateatomic, closes codex's finding about binds to unmapped ids, and runs the codegraph tests in CI.dt64 (
dr)MapTable::locatemaps a global id to a (tile, local) pair, which closes D-DYNBAG-4's open map item.LocalMap::extendschecks that a map only appends ids.LocalMap::viewlets a caller check a map before handing it to the table.Axis::for_survivorspicks the tile width from the survivor count (D-DYNBAG §4.1).RouteVersion:MapTableandRouteLogshare one sequence through aVersionClock.map(frame, tile)reads the layout the frame was sealed at, andmap_at(version, tile)reads any version by number.TileMapand allocate nothing.xlog
closure_widehandles any number of positions. Each row stores only its non-empty 256-position blocks, with a multi-word presence mask and no tile cap. The narrow path for 64 positions or fewer is unchanged.Cube::new_tiledspans several tiles.refresh_closurerecomputes only the rows that reached a retired edge's source.refoldruns only when called.rebaseaccepts a new frame only if every tile extends its old map, and checks everything before it changes anything. Its private snapshot is gone; it reads the old layout through the index.Cube::stage/Cube::stage_closure/Cube::commit.stagechecks a batch of edge operations without changing the cube or the table: the grown map must extend the current one, and every id must be placed.stage_closurecomputes the closure as it will be after the batch.commitapplies the batch and cannot refuse.codegraph
Posisu32.refresh_crateis atomic: prepare, then validate, then commit.SymbolStage);last_owner(PosStage);Cube::stage);Cube::commit, absorbing the stages, lanes) has no error path.NeedsReopen;referencescompares ids instead of strings.Bugs found by measurement and fixed
impactcopied only the first 64 bits of each closure row, which became wrong past 64 positions.callerspanicked on a multi-tile store, because the cube's mask covers every reserved position while codegraph's masks cover only the symbols.NeedsReopen;Test Plan
Tests: dt64, xlog,
xlog-relcomp-probe, codegraph andegglog-r2il-probe(at the egglog pin) all pass.cargo clippy --all-targets -- -D warningsand fmt are clean on each touched crate.CI:
rust-test.ymlnow runscrates/lance-graph-codegraph. It is excluded from the workspace and ran in no workflow before.Atomic refresh falsifiers (
graph.rsmod atomic). Each compares a full-state snapshot: interner, positions,last_owner, lanes, digests, table version, revisions and tile history, cube frame and every delta log, masks, cached closures.NeedsReopen, an injected stage refusal and an injected closure refusal each leave the snapshot unchanged, and no version is issued.m::bkeeps 4 call sites, as in a clean open.Bind and staging tests (
tests/versioned_map.rs):Disable runs. Each guard added since the review fails exactly its own test:
rebase;commit;extendscheck instage.Earlier falsifiers, unchanged:
rows_recomputed == |A|;refoldpreserves the closure;rebaserefuses a reorder;Every earlier guard was disable-verified. Re-pinned tests keep their old assertion as a comment.
Measured on mask-risc's store (695 symbols, 3 tiles), release build:
impactcallersreferencesThe refresh fails because it reads and hashes the 2.5 MB text rows file. The fix is D-CODEGRAPH-0-BIN: binary lanes with a header digest.
Decisions recorded (not implemented here)
d-codegraph-0-binary-lanes-v1Amendment A (§8):(artifact, FunDeclId);INVOKES_WORDto a registered DT64 reference;d-dt64-method-authority-census-v1(D-DT64-AUTH). DT64 is the one method authority.LABadapters.5deaa5637a306c48c998f88d5d08792d2dbfd037.Board
d-codegraph-0-wide-closure-v1,d-dynbag-4-dr-versioned-mapping-v1,d-codegraph-0-binary-lanes-v1(amended) andd-dt64-method-authority-census-v1.entries_index.py --check,append_only_gate.py, the supersession index andplan_dids.pyall pass.Not to be merged automatically.
🤖 Generated with Claude Code
https://claude.ai/code/session_01X6y3drwKSE2zSgoexheLFX