quickjab index <repo> — the lazy commit-based .git/be indexRuling (gritzko 2026-08-13): beagle-lite indexes many git repos to do what it can for git users; weave building needs each blob's history, so the first index is blob<->path. Indexing is COMMIT-BASED (read a commit, its tree, index everything, then next), LAZY (a watermark row per ref; on request recheck, reindex the gap, answer from the index), and lives in the repo's own .git/be/. Tracked repos are listed in $HOME/.config/be/tracks, a plain list of absolute paths.
The record structure and widths are ruled; the substrate exists (quickjab index.c = the 3 native leaves an abc.index LSM stands on, lane-typed pup stacks; dog/git = the read-only ODB waist quickjab git.c binds as git.open/getHex/getSafe/close). be/ has the JS precedents to mirror, NOT to import: metaidx.js (the lazy self-updating lane + mark-written-LAST discipline), mtimeidx.js (HEAD mark staleness = ancestry check, drop marks only, rows stay valid), ingest.js idxWriter (DOG-027: <=200 rows per batch, one 4 KB memtable page).
<repo>/.git/be/; everything in .git/be/ is derived, rm -rf-safe, rebuilt from the ODB.path_hl:40|rev:20|BLOB val = blob_hl:60|vnib:4 — the rev's contentpath_hl:40|rev:20|CMMT val = commit_hl:60|vnib:4 — the commit that introduced the revpath_hl:40|rev:20|PARS val = par1:20|par2:20|par3:20|vnib:4 — parent revs of the SAME path; empty slot = all-ones; 4th+ parent = second PARS rowcommit_hl:60|CPAR val = parent_hl:60|ord:4 — commit->parent edge, one row per parent, first-parent ord 0blob_hl:60|B2P val = path_hl:40|rev:20|vnib:4 — blob->(path,rev), one row per occurrenceref_hl:60|MARK val = tip commit_hl:60|vnib:4 — per-ref watermark, written LAST after a completed batchquickjab index $HOME/src/linux indexes that repo; a second run is a fast no-op (watermark hit).
index verb: resolve the arg to a repo (root, .git dir or gitfile — what git.open already takes), append its absolute path to $HOME/.config/be/tracks (create dirs as needed, dedup on read), open the ODB, index, report a one-line summary (commits/revs/rows indexed, or "up to date").index, assert the six record kinds, the rev chain of one file, B2P rows, the no-op second run, and the gap run after adding a commit.git.open/getHex/getSafe/close (git.c), git.tree + git.parseCommit over GITu8sDrainTree / GITu8sDrainCommit / GITu8sCommitTree (cont.c + pack.c), and abc.index("wh128", {dir, ext}) — the dog Pup stack handle — already exists in cont.c, so no JS lane handle had to be ported from be/ either.index/refs.js), which is where quickjab RULES they belong: git.c's own header says "Refs stay ABOVE this waist (test/gitverify.js reads HEAD/packed-refs as text) — the waist is ODB only", and dog/git/ carries no ref-store reader at all (GIT.h's GITParseRef parses a refNAME). The file mirrors quickjab's own sanctioned reader, quickjab/test/gitverify.js, cut to head() + resolve(). A ragel packed-refs machine does not exist in dog/, so hand-rolling one in C was refused.vnib is RESERVED (0) wherever the ruled table does not name the low nibble; CPAR's is the parent ordinal. An empty PARS slot is all-ones (REV_MAX), and a 4th+ parent rev rides a second PARS row.WALK_CAP REMOVED: PRESENCE IS THE BOUNDARY. There is no walk ceiling. One pass over the lane yields the set of commits it already holds (their CPAR rows); the walk climbs from the tip and never enters one. Each run therefore indexes exactly the commits no run has indexed yet — a history of ANY size converges over successive runs, an interrupted run keeps every commit it sealed, and a rebase needs no special case (the rewritten commits are simply not in the lane, so they are what gets walked).log.js parentsOf() drops it, isIndexed() counts it. (The other case the ruling names — a commit whose parents are all pruned — cannot arise here: CPAR rows are emitted for every parent of every walked commit, pruning only ever applies to TREES.){rev, blob, commit} per PATH (st.top), not one entry per REV. That replaced a string-keyed per-rev map and is the difference between a bounded and an unbounded indexer at linux scale.0o160000) are dropped — a submodule's commit lives in another ODB and is no blob. Deletions are NOT revs: a pruning walk of the commit's own tree sees present paths only, which is the ruled algorithm as written; deleted paths would need a both-sides tree diff and are out of scope here.$HOME/.config/be/tracksabc.index already IS that handlequickjab index on a real repo: first run indexes, second run no-opsWALK_CAP (2^18 commits) never converges~~ — SUPERSEDED by the ruling of 2026-08-13. WALK_CAP is gone; presence of a commit's records is the boundary, so any history converges and an interrupted run resumes where its records end. See the LITE-007 field evidence.byPB map — one entry per rev — putting RSS at 2.5 GB. The no-op path pays none of it (8 ms). Bounding it wants typed-array open addressing, the quickjab/test/gitverify.js ShaSet precedent; not built.index walks the CURRENT TIP as ruled.Landed in ///lite (worktree work/LITE-006), zero quickjab edits.
index/index.js — the verb: the tracks list, the wh128 record family, the lazy mark contract, the Kahn commit walk, the pruning tree descent and the rev/PARS derivation.index/refs.js — HEAD/loose/packed-refs resolution above the ODB waist (mirrors quickjab/test/gitverify.js).main.js — index dispatched before the flag scan; README.mkd — the usage line.test/index/run.sh + test/index/rows.js — 39 checks, PASS.End to end: the fixture (5 commits incl. a merge and a same-blob-new-path move) → indexed 5 commits, 5 revs, 23 rows, rerun up to date, gap run indexed 1 commits, 1 revs, 6 rows. libdog (340 commits) → indexed 340 commits, 1713 revs, 6566 rows in 0.59 s, rerun 13 ms. gitoxide (15841 commits) → indexed 15841 commits, 71415 revs, 295705 rows in 15.7 s, rerun 8 ms. One file's prefix scan matches git log -- CMakeLists.txt exactly (36 revs, same commits, same order), reverts included.
Suggested commit message: LITE-006: quickjab index — the lazy .git/be commit index