Changes touching this path

  • loot-perf: the harness crate with fixture, measurement, and record seams (#634) ef9fd595 · dbf3dbe6…
  • loot-perf: the CLI tier — hyperfine-timed push, receiver-counted wire bytes, raw samples and load on the record (#635) 3588811d · dbf3dbe6…diff
  • loot-perf: name the fixture commit for what it is (#638) Perf-Baseline: reset the fixture commit message is part of the serialized change record, so naming it moves bundle_bytes by 21 bytes on a fixed tree 44bee9fb · dbf3dbe6…diff
  • the change graph gets one read view, and the two forwarding bands over it retire (#868) 826c3339 · dbf3dbe6…diff
  • the gate learns to see the wire: negotiation counters on a fixture with real history depth, and wire_bytes stops pretending (#847) 8fd4e950 · dbf3dbe6…diff
  • every open of a compressed object stops building a fresh zstd context and asking for a 64 MiB buffer, because the decompressor is now thread-local and the buffer is the frame's own declared size clamped by the same zip-bomb ceiling, and the harness gains the first fixture whose objects are actually compressed - without which nothing could have seen the 72.6% it removed (#1424) 7c16d4d4 · dbf3dbe6…diff
  • a push's follow-up batches stop re-walking every change and every manifest to locate their 32 addresses, because the membership and key answers that walk produced are now taken once per transfer, which makes bundle_wanted_batched's own O(total_objects x num_batches) disclaimer true for the first time, measured at -44.1% by a new bundle_batched timing that is the only number in the harness reaching a follow-up bundle 5d7fdccf · dbf3dbe6…diff
  • loot diff stops decrypting every path on both of its sides to fill in a bool, because the visibility gate now asks the cipher-free can_open #1422 built for exactly this beside the reader-scoped expiry check it must keep asking, measured at -58.7% by the first fixture in either tier that touches diff at all (#1426) 699a58e8 · dbf3dbe6…diff
  • five claims from this run's review sweep get pins instead of louder prose: sealed.rs's header names can_open beside the chokepoint it did not weaken, is_canonical is held to encode_graph(decode_graph(bytes)) == bytes over every golden with the rewrite predicate no longer said in two files, the #988 separator arm is pinned by bytes encode_graph cannot write instead of an if that never ran, the inflate guard's third arm gets the test its prose stood in for - which measures that arm as a narrowing of where a lie is refused rather than of whether - and a refusal that could only print one number twice prints both (#1431) 102fbec6 · dbf3dbe6…diff
  • the harness stops being blind to history depth, because closure_complete is now timed in process over a 1024-change chain whose control refuses the run unless the walk reads the manifest 1024 parent edges back, and #1421 - parked flat inside a ~470 ms process - re-measures on it at -57.9% against a 5.3% floor (#1428) a59dd358 · dbf3dbe6…diff
  • one whole-tree decrypt stops being spent to answer a question the first differing path already settled, and working_preview gets the in-process sample that can see it, because the cli tier could only ever ask a 476 ms process to resolve half a percent of itself (#1423) f5ce12eb · dbf3dbe6…diff
  • content whose embargo has already lifted stops reading as sealed, because promoting due keys out of escrow is now the construction of the reader every content read hangs off instead of a doc-comment obligation six callers hoisted by hand, and deleting four of those hoists left all 2438 tests green while loot surface told an author to request a grant from herself (#1464) e59e46b3 · dbf3dbe6…diff
  • a verb stops reading every loose object in the store before it can open one, because the open now indexes the object directory and reads the file at the address it is asked for, so one complete index still answers membership, the persist's candidate set, gc's sweep and ADR 0038's burn while a burned address keeps no route back through the directory it came from, and the sixth opt-in half that can see any of this refuses a fixture whose object directory does not hold the objects it claims (#1545) 5c98eff6 · dbf3dbe6…diff
  • a push's first bundle stops asking the object store about every change it has already decided not to send, because the entry's ride decision is taken before the probe rather than after it, so an entry whose bytes and key both stay home is skipped instead of being looked up and discarded — the shape #1425 removed from the follow-up bundles only — and that arm stops being unmeasurable, because --batched passes have = &[] and can therefore never enter it, so a new --push-shape half passes the change one behind the tip and refuses outright any fixture whose have does not resolve to the history behind it (#1546) a8d1806a · dbf3dbe6…diff
  • a push stops walking its whole object store to answer one yes-or-no, because the unsigned-tip refusal now asks whether anything is offered at all and stops at the first thing it finds, instead of building the entire unfiltered offer and then discarding it — on every push whose relay declared heads — to walk again scoped to them; and that walk stops being unmeasurable, because no cli sample can reach it at all: the tier gives every push repetition a fresh relay, so have is always empty there and the discarding branch is never entered, which a new --offer-guard half over a 128-change history reads at 34.3 ms against 17.6 us (#1559) dca66add · dbf3dbe6…diff
  • a pull, a wants answer and the relay's cache restore stop faulting the whole loose object store in from disk, because the receiver's membership question is now asked of the index that put's dedup, the persist's candidate set, gc's sweep and ADR 0038's burn already answer rather than through the read #1545 made lazy, so a held address whose file vanished under a live process is no longer re-fetched, which was a five-commit-old accident that would have asked a relay to resurrect what another process had just burned, while an address absent from the object directory at open is still named and a withheld one still asks forever (#1565) 113b4588 · dbf3dbe6…diff
  • the implicit-capture door stops faulting the whole object store in from disk before every bare mutating verb, because the closure walk it gates on asks the index the membership question it always meant, and that door reaches a skip only through false so a held-but-unreadable address can no longer switch it into the narrower policy #891 wrote for an incomplete closure, while the half that watches the walk stops timing a store with no files in it (#1576) 732d63fa · dbf3dbe6…diff
  • a per-change cost inside the repo open stops being unmeasurable, because the open now has a depth axis beside #1545's width axis: a --graph-load half over a chain of N changes, whose control refuses a depth-1 fixture outright instead of letting it report the absence of a workload as the absence of an effect, which is what parked #1547 and #1548 while both were correct (#1571) 10730151 · dbf3dbe6…diff
  • the per-path custody gate stops building a heap key before it can ask its question, because the grant manifest is indexed as a map of oid to a map of grantee rather than one map under an (oid, grantee) pair, so grant_for probes both levels by borrow and the 4,000 Strings a timed visible_paths call allocated and threw away are gone, taking the visibility pair a loot diff makes over a 2000-path tree from 0.7026 ms to 0.6069 ms in both directions (#1550) ebe1b5c0 · dbf3dbe6…diff
  • a corrected census stops being replaced by a fresh one, because ADR 0012's table drops the completeness claim that had already missed a consumer on the day it landed and states its rule instead, the swallowing publication read that consumer used is deleted along with it so outside loot-core there is no route to one left to enumerate, and HUNT-PERF's list of which perf halves re-open their fixture per repetition, which refuted itself inside a single sentence, is deleted in favour of each half's own doc rather than pinned as prose, which is #1587's half of the same defect (#1593) 4995641a · dbf3dbe6…diff
  • head count and grant count stop being fixed at trivial values in every fixture, because the harness now carries a fan whose heads the union folds one complete manifest apiece and a tree whose custody manifest the per-path gate has to descend, each built only after its own ceiling was measured first at 2,000 exact heap allocations per additional head and a 30x step from an empty manifest to one grant per object, while the three axes whose ceilings came back flat are recorded on the issue instead of built and the head fixture is a correctness instrument too, because a chain admits exactly one topological order and every fixture here was a chain (#1601) b98b1efc · dbf3dbe6…diff
  • the land gate stops watching only what a run produces and starts watching what it does, because two work counters now ride the untimed batch it was already measuring so they cost no fixture, no repetition and no workload_id move and orphan no baseline, while the twelve opt-in timings stay ungated on the argument that a timing is dropped by the load policy exactly on the busy machine a land runs on, and the count feature stays off by default because turning it on in a manifest was measured to change the loot.exe a plain workspace build produces (#1602) f641ea1d · dbf3dbe6…diff
  • the aspect a half refuses under stops being a const in the measure module and becomes a field of the row itself, built by a macro so a row names its fixture and never the sentence, because that was edit site 9 and the census that called it fictional had missed three module-level consts and five of the eight function-local ones while #1601 went on to pay it twice more; the five defaults each Workload constructor re-listed collapse into one plain base; and the two-edit promise is restated with the scope a throwaway half on a new axis measured, seventeen structural sites down to twelve, the last silent one now failing a test because a dimension added without an arm in Workload::id makes two fixtures report one workload_id (#1633) c2a454dc · dbf3dbe6…diff
  • a timing without a control stops compiling: timed_min takes its controls as a const-sized array and a const assert refuses an empty one, every prove_ returns a Proven token whose constructor is private so the argument cannot be forged, and snapshot_delta - the one timing the gate judges and the only one of the thirteen that called no control at all - gets a first control, proved non-vacuous by breaking tree_edited to return the tree unedited and watching it go red rather than produce a happy number; the clock is handed to the body rather than wrapping the repetition because locally_missing and closure_complete re-open their store outside the timed region while for repo_open and graph_load that same call is the measurement, so a combinator that timed the whole repetition would have silently destroyed both shapes, and the holes and complete checks move inside the body so they cover every repetition instead of whichever reading happened to be last; the refusal is post-monomorphization, so cargo check passes on a tree cargo build rejects, which is written into the doc beside a compile_fail pin and its positive arm because a compile_fail example passes on any compile error; and three of this ticket's own citations were wrong and are corrected rather than worked around, since TIMING lives in gate.rs and not in the bin, the prove_ call sites number 24 and not 68, and the five blind instruments in one night that ADR 0072 was said to record are not in it at all - a mis-citation two other places in the tree already make, left to a follow-up rather than widened into this change (#1654) f03656a4 · dbf3dbe6…diff
  • the two censuses that each carried the other's blind spot stop being two walks and become one, and the defect turns out to be four walks rather than two: flags.rs cut production at the first line starting with cfg(test) and never restored it, so 55.5 percent of loot-cli src sat exempt from its second clause at 36164 of 65168 lines - and the 60.0 percent this ticket claimed was measured with a looser predicate than the walk actually used, which is the ticket committing the very class it was filed about - while ADR 0074's guard scanned from any marker forward to the next brace and lost 635 production lines to semicolon-terminated items and to markers sitting inside doc comments; a third walk in main.rs split on the marker string, and a fourth in custody_lock broke at the first marker line and was right only by luck, because all three write_session callers happen to sit above their own files' first marker. the shared walker classifies every char as code, comment or literal before it looks for a marker at all, and ends an item at the first semicolon at depth zero while counting parens and brackets alike, because endpoint.rs's const ALL takes an array of thirteen routes whose semicolon lives inside the type and ended the item early in the first draft, keeping fifteen lines of test table as production. the floor is a discrimination rather than a count, since a count passes on both original bugs: it asserts that a known production line below a marker is kept and a known test line is cut, and it was broken in both directions to prove it can fail. every blindness was demonstrated by planting a live violation in production source and watching both censuses stay green before the change and exit 101 after it; and Clock::time now refuses a second call on one repetition rather than silently reporting only the last region measured (#1665) 12e18beb · dbf3dbe6…diff
  • six sentences that read wider than their subject are narrowed rather than deleted, because in at least two of them the sentence is the argument: the verb tier's width figure stops being typed at all and is generated off the impl blocks with the predicate written beside it, since this ticket's own 244 is not reproducible under any predicate - pub fn alone gives 202, every fn including test-gated gives 320, production-only gives 309 - which is the ticket committing a mild form of the class it was filed about, as was its claim that the figure had gone stale a second time when git log -S finds the sentence written once and never corrected; finalized_anchor is repointed to the two hops it really takes rather than dropped from the list of delegates; the duplicated surface tail is extracted and not deleted because BOTH copies are live, one a trait method the bench calls and one the escrow-promoted twin, so establish-which-is-live had the answer both; thiserror leaves two manifests that never derive it, each row replaced by why the absence is deliberate now that RepoError is loot-codec's type re-exported; the push-shape row is documented and pinned rather than renamed, because a metric string is output and this change is behaviour-neutral, and the new pin found the drift is two rows and not one; and the whole cost of opening a repo is narrowed in all three live copies rather than the single one named here, since correcting one of three is the trap #1629 records, while ADR 0012's copy stays because its subject is the loose-object slice and not the harness. one finding was simply wrong and is reported as wrong with no edit, since run_checks has a production caller and fourteen tests and the file this ticket cited does not exist. and load_from turns out not to be what the open calls at all: assemble asks load_from_needing with the verb's declared RepoNeed since #1536, so the timed call is the widest spelling rather than the live one, which is now said in both places that time it (#1656) 44b5b98a · dbf3dbe6…diff
  • loot ferry parses both policy files once per commit instead of once per changed path, and the instrument had to be built before the fix because PolicyLoads sat on Attributes::load while both ferry doors call parse, so the counter read a structural zero over this whole path and would have read zero after the fix too - a 0-valued counter being indistinguishable from one watching code that does not run. The tally moves to Attributes::parse and Ignore::parse_recorded rather than being routed through a counted door, because the fix itself removes those door calls: a counter on them would read zero afterwards, which is the same blindness relocated. That changes what the counter MEANS, from policy file reads to policy re-derivations, so all three existing pins were re-read rather than adjusted until green - status moves 2/3 to 3/4 with the +1 being its single Ignore::load now counted, and the point is that the GROWTH half passed untouched (narrow equals wide) while only the constant moved, so the test is re-pinned and not re-decided; the tier-exclusion test is still green because the in-process tier links loot-core and never loot-cli, so ADR 0073's exclusion needs no re-taking; and lane_new_sweep's note that policy_loads is one per read_tree_at is repointed to two, since read_tree_at calls both loads. The instrument was proved non-vacuous against the UNFIXED code first, at 18, 66 and 258 parses over four commits of two, eight and thirty-two changed paths, which is exactly 2 plus 2 times commits times width; after, it is 2 plus 2 times commits, so 258 falls to 10 at width 32 and stays 10 as width grows. The most useful thing learned here is a red proof that inverts an assumption: blinding the instrument by putting the tally back on load makes the counter read a constant 1 everywhere, so the constancy pin passes AND the parses-greater-than-zero guard passes, and only the GROWTH assertion catches it - a positive-value pin does not protect against a blinded instrument, which is what ADR 0072's controls bullet credited it with, and that bullet is corrected rather than left standing. This ticket's own wall clock does not reproduce and is corrected rather than repeated: the removed re-parse is 4.63 microseconds per path in release against this repo's real policy files, not 22.0, so a full-history ferry is about 1.9 seconds rather than 8,819 milliseconds - 22.0 is close to the debug reading of 31.53, so the hunt appears to have measured a debug build, and a figure taken under a different build is not a smaller version of the same number. ignored_under is deleted rather than kept as a pure forward once the parse is hoisted, and ADR 0028 is amended because it argued its delete-arm decision partly on an Ignore::parse per deleted path, a cost that no longer exists - the decision stands on the attribution argument, which was load-bearing anyway. seal_under takes a parsed Attributes and narrows pub to pub(crate) since Attributes is crate-private, and its doc said it keeps the bridge from re-parsing the policy twice per path, which was true about the wrong unit: it halved a cost that should never have been per-path. One honest regression is recorded rather than hidden: a deletions-only commit now costs 2 parses where it cost 0, because the hoist is unconditional (#1704) 1822132f · dbf3dbe6…diff
  • bundle_impl stops visiting every manifest entry of every held-back change to answer a wants question, and this ticket's proposed fix was the wrong one: reaching the existing wanted_finalized_entries index would have moved the cost rather than removed it, because that function is the SAME O(changes times entries) walk - #1425's saving was amortising one walk across many batches, not making the walk cheaper - and it moves nothing at all on the relay /fetch path, which builds one bundle and never batches. It also cannot serve batch zero on its own terms: it has no have, so no send set and no attestations, and it is wants-scoped while bundle_impl's key lane fires for non-want entries of sending changes. The missing piece was never an index, it was a STOP RULE, so both walks got one. bundle_impl becomes two passes over one topological order, the send set unchanged and a second wants lane over held-back changes that is skipped outright when wants is absent or empty and stops as soon as every want is settled, and wanted_finalized_entries gets the same rule walked newest-first. The consequence worth naming is that held-back manifests are no longer materialized at all, which is the cost d6be741 removed from the repo open and this path was re-paying at push time; it is pinned over a saved-and-reopened repo through Manifest::is_materialized with a control that was proved to fire, since an in-memory repo defers nothing and would have made the pin vacuous. Byte-identity is differenced against one_pass_bundle, a statement-for-statement transcription of the base walk, over ten have-and-wants shapes, because the whole claim is that this is a cost change and not a behaviour change. This ticket's 512.6 ms does not reproduce: at 436 paths and 128 changes the release cost is 7.43 ms, which extrapolates in depth to about 58 ms at the ticket's 1000, roughly nine times smaller, and three confounds compound - the debug-build suspicion #1704 raised, #1701's probe memoisation landing in between, and this half keeping its objects in memory. The shape was real and the growth was real, so the fix is worth 86.0 percent at 64 by 128 and 92.5 percent at 436 by 128 on the named half, but the number that ranked this finding was wrong and saying so is worth more than repeating it. A defect this change introduced was caught by its own review and is recorded rather than quietly fixed: ride_entry returned true on a store refusal without consulting bytes_ride, so a non-want entered settled, and a sent change naming one burned or withheld address made the settled count reach the wants count with a real want still unanswered - silently skipping the #803 recovery lane and breaking byte-identity. The fixture had no unproducible address, so the headline pin was blind to it; the fixture now carries a burned one in the send set and the defect was proved red before the fix. Four loot-perf doc sites went stale by this change and are amended here rather than left: they described the held-back walk as the cost this half watches ACCUMULATE, where it is now the cost it holds GONE - the half is not blind, since re-nesting the loops returns the reading, but a future comparison is against 126 microseconds and not the number the row was born with (#1702) 68a0bded · dbf3dbe6…diff
  • ancestor_closure stops re-walking the whole ancestry once per seed, and unlike its two siblings from the same hunt this ticket's numbers REPRODUCE in release - 94.97 ms against a claimed 101.1 and 383.9x against a claimed 424x, both within ten percent - so the debug-build correction #1704 and #1702 each needed does not apply here and the ranking that placed this finding stands. What does repeat is the other family trait: this ticket also said the fix already exists one file away, and that was wrong again, though for a narrower reason than #1702's. GraphView::ancestor_closure is NOT set-identical, proved by running rather than assumed - it seeds its out set with whatever it is handed, so an unrecognized seed comes back inside its own closure where the per-seed loop skipped it through graph.get(h).is_some(). A probe printed DagRepo 0 against GraphView 1 for a stranger alone and 6 against 7 mixed, differing by exactly the stranger, and this is not a corner because sync.rs hands it a PEER's declared heads. A dangling parent reached mid-walk is kept by both, which is why the fix is the shared walk plus a SEED filter and not either one alone. The instrument was blind for a reason worth naming precisely: --push-shape passed vec![parent], which is the shape of a /haves REPLY, where sync.rs passes that id's whole closure - so the half was already not describing the code, making this #1576's extend-in-place case rather than #1425's honest-but-narrow one, and #1702 had re-based the same readings one commit earlier so there was no unbroken series to protect. Widening it moved the instrument 4.9x against the UNCHANGED engine, 273 microseconds to 1.33 ms at 200 by 128, which is the non-vacuity proof taken before any fix was trusted. After, the quadratic term is gone: per doubling of depth the cost grew 2.8x, 4.0x and 4.3x before and grows 1.2x, 1.4x and 1.6x after, and at depth 512 the half reads 22.713 ms against 0.608. The evidence is therefore a THREE-point chain and not a pair - the landing position's 273 microseconds, the widened fixture on the old engine at 1.33 ms, and the widened fixture on the new engine at 283 - and only the last two are the A/B, because the first is a different fixture; reporting the outer pair alone reads as a regression, so that rule is written into HUNT-PERF.md rather than left for the next reader to rediscover. The control on the widened have is the part most worth recording: the first version was a count-nonzero floor, and a two-element have of parent and root clears a floor of two, passes coverage, and still seeds a 127-deep walk twice - about ninety-nine percent of the blindness back with every control green. It is now set equality against the have's own closure, the fixed point sync.rs actually passes, with a negative arm proving that closure is a fixed point and a red proof that reverting to the floor fails on the two-seed case (#1700) 04859438 · dbf3dbe6…diff
  • the second review sweep's fix-up, and the item that mattered most was a correction to a correction: #1704's amendment to ADR 0072 refuted a sentence the bullet does not contain. The bullet credits an EXACT-VALUE pin, and the amendment answered that a positive-value pin is not the protection it credits - true about a greater-than-zero guard, untrue about the thing being amended, which is doc scope-drift inside the ADR whose subject is that class. Blinding the instrument settles it by running rather than by reading: with the tally back on Attributes::load, status_derives_its_policy_a_fixed_number_of_times fails on its VALUE half, and the ticket's own arithmetic was wrong in the same direction as the amendment - the blind arm reads 2 and not 1, because status still reaches Attributes::load once, while 1 is the ferry fixture's reading. Both numbers are now named in the text, the greater-than-zero finding is kept because it is real and newly demonstrated, and the head count stays at two of the four with the reason narrowed: what is still missing is a refusing FIXTURE, not a refusing pin, since two pins were each measured refusing a mis-placed tally. ferry.rs claimed the pin asserts the 2 plus term, which was wrong twice over - nothing asserted a constant at all, and the 2 being described is the per-commit coefficient rather than the pass-level term - so rather than correct the sentence the constant is now ASSERTED, as parses equals PER_PASS plus PER_COMMIT times ingested over both sweeps, fitted to measurement rather than predicted. Its red proof is the regression the old comment claimed was already pinned: a third unconditional parse per commit moves the readings to 14/14/14 and 8/14/26, where the constancy half passes AND the growth half passes and only the new assertion fires. offers_any_object's note that no address is ever reached twice is repointed because it is false in exactly the case the memo two screens up is built for - a store where every named address answers Err never returns early and re-probes each repeated address per change - and that arm is left uncovered with its cost stated as unmeasured rather than justified. The 291-against-283 disagreement turns out not to be one: four fresh runs read 296.3, 289.6, 293.2 and 283.6 microseconds, so both recorded figures sit inside the instrument's own run-to-run spread of about 4.5 percent, which is wider than the 8 microseconds they differed by. Recording a POINT was the defect, so it is now a dated spread of about 290 with its four raw readings written in one place, and measure.rs carries no number at all but points at PUSH_SHAPE - killing the duplicate rather than syncing it. PUSH_SHAPE_DEPTH's pre-#1700 pair gains the marker the three sibling sites already carried (#1717) d895d727 · dbf3dbe6…diff
  • the adopt and ferry re-read stops deep-copying a pool it is about to drop, and the instrument that can SEE that was built first, because NONE existed: measure.rs had no reference to ingest anywhere, and both depth-capable halves time DagRepo::load_from, which is the OPEN - ingest_shared_lineage re-reads the shared graph AFTER it, so no fixture built on load_from executes a line of it at any depth. the new opt-in half sizes #778 own reproduction: a dock owns the store and records one change of its own, then a lane over the SAME shared store lands a depth-change line into the graph file while the dock heads file stays put, so an open of the dock is filtered back to its one change and the landed line is exactly what the ingest must splice. the instrument is proved by a POSITIVE CONTROL rather than by an argument that it ought to work - the clone line made knowingly expensive moves the number 168.3 to 188.5 to 203.7 ms at one, two and five copies, while the graph-load half on the SAME knowingly-wrong binary reads 10.30 ms UNMOVED. the ceiling was measured before the percentage was trusted: a second discarded read_graph takes depth 1024 from 171.2 to 322.9 ms, so the EAGER graph decode is about 89% of the timed region, because this seam uses read_graph while the open uses the deferred read_graph_required of #1536 - a real and much larger finding, deliberately NOT made here, written down at the call site with its correctness question, which is that the deferred manifest holds an Arc into the buffer this function drops. the change itself is the #1547 arrangement at the other site of the same shape: collect the walk order as IDS, then MOVE the nodes out with remove instead of cloning them. the re-read semantics are untouched on purpose - same node set, same emitted order, same insert rather than from_parents_first, because this is a splice into a LIVE graph, and refresh_objects_loose and the keyring catch-up still run AFTER the splice, which is #778 ordering. it MOVED: interleaved, ten reps a side, every run exit 0 and carrying a VALUE rather than reading skipped, with the idle probe at 2 to 8 percent - min of ten per round goes 185.1 to 145.6 ms at depth 1024 and 375.1 to 291.9 at 2048, sets DISJOINT at both, and the graph-load half flat as the negative control. the magnitude is qualified rather than quoted flat: an earlier pair of the same two engine sides read minus 10.0 and minus 10.9 percent, and re-running all four binaries interleaved reproduces each level to within one percent, so the shift is CODEGEN LAYOUT rather than machine state - direction certain, sets never overlapping, minus 10 percent the conservative figure, recorded at the code. and one doc claim is REFUTED rather than restated: the function said the parents-before-children order is why head tracking stays exact, and the mutation that reversed the order came back GREEN, because the splice goes through insert, which is right under any arrival order - so the sentence now says what the order actually buys, and no pin was added to assert a courtesy (#1572) ff123eb9 · dbf3dbe6…diff
  • a published speedup that exceeded a ceiling measured three paragraphs below it is WITHDRAWN rather than explained, and the instrument that measured the ceiling is REFUTED BY MEASUREMENT rather than by argument: a discarded second read_graph measures the MARGINAL cost of an extra decode while the pool is still alive, not the first call share - it reads 151.5 ms against a whole region of 148.4 on one after binary and 162.5 against 157.7 on a second, over 100 percent of the quantity it is a fraction of, twice, on separately built binaries. the replacement stops the function instead of doubling the read, and its bands SUM to the region: read_graph plus pool build 154.3 ms at 89.8 percent, walk and splice 16.2, objects and keyring 1.4, against a region of 171.9 - so the ~89 percent decode finding SURVIVES the loss of the instrument that first produced it, and on that pair the change removes 13.9 of the 16.2 ms it could touch, a delta that FITS. the magnitude itself is re-measured across 156 gate runs in one sitting on an idle machine, every run exit 0, discarded 0 batches, carrying a VALUE rather than reading skipped, with the harness own probe at 1 to 9 percent and no exit 3 or 4 anywhere: three independently built before-and-after pairs read minus 13.6, minus 8.1 and minus 10.6 percent at depth 1024, disjoint at both depths in every pair, with graph-load flat across the same invocations - so the answer is published as minus 8 percent conservative and about minus 10 middle, and the spread is the BINARY rather than the machine. the residual is stated and NOT reconciled: the clean pair 22.5 ms exceeds the 16.2 ms band it should sit inside, and the clean pair own band cannot be measured without making it un-clean, with corroborating evidence that the instrument perturbs what it measures - the stop-instrumented after binary reads a read-and-pool band ABOVE its own whole region, an early return costing more than the work it skips, six rounds out of six. what would settle it is named as an exact allocation counter over the region that no half records today, and it is left as instrument work rather than done here. the copy in the fixture now quotes NO figure at all, keeping only the shape, because a figure quoted anywhere else is a copy. the in-loop guard stops checking the OTHER guard than the one its prose names and is asked every rep of the position under measurement - proved by a mutation pair where a no-op ingest is caught RED at 156 passed 2 failed and, with the same guard disabled, GREEN at 158 passed 0 failed, which demonstrates the blindness rather than arguing it. the ADR masthead stops enumerating its own amendments and points at the inline marks that already carry their tickets, the fixture stops claiming the ancestry is the real path when its root is parentless and the walk stop predicate never fires, the Err arm stops asserting a merge as the cause it never established and hands over the selector quoted refusal instead, and the shallow header stops calling a convention mechanical when nothing enforces it (#1888) dc524dd2 · dbf3dbe6…diff
  • the open two biggest arms become COUNTABLE, so a regression in them can fail a land instead of passing all three checks: store.rs held no instrumentation whatsoever, no Work, no tally, no bump - and that NEGATIVE was re-verified before anything was built on it, because a negative that has quietly become false is exactly how this class of blindness starts. every line number had moved and every one is re-derived: the graph read at 2200 rather than 1993, the keyring read at 2228 rather than 2019, the two call sites at 4467 and 4510 rather than 3468 and 3502. the unit is READS, one counter rather than a pair, and the reasoning is recorded rather than assumed. a byte count is NOT 0%-gatable here, being a function of fixture contents and encoding, so every format change would fail a land for a reason its author cannot act on - and tolerancing it instead re-creates precisely the load-sensitive alarm ADR 0073 rejected the timings for. at this seam a byte count would also be blind to its own stated reason, since the lazy half of #1536 already landed and read_graph_required still reads the file WHOLE while deferring the per-change manifests, so bytes READ did not move for #1536 and will not, while bytes DECODED are a different counter at a different seam whose value depends on which manifests a verb happens to touch. the object pair precedent does not transfer either: those are two because a MEMO sits between them, and nothing analogous splits a metadata read. disjointness is BUILT rather than assumed, because object files are whole files in the store too - the object store now reads through its own door, same body, same retry budget, no tally - and the two of that door four sites which tally NOTHING today are named in the code and deliberately left alone, since closing that gap would move an already-gated number. the tally sits OUTSIDE the retry loop, because inside it would count attempts and read 1 idle against 17 busy, and that placement is pinned DETERMINISTICALLY rather than by timing luck, since an absent path walks the whole budget by construction. the structural-zero bar is met by SHAPE rather than by not-zero: across a tenfold fixture the object counters go 60 to 600 and 20 to 200 while the store counter STANDS STILL AT 24 - per-open and not per-object - and no tally left on the object door, nor one that had picked up a per-path read, can produce that pair of lines. four mutations with counts read, and the discrimination one is a discrimination rather than a constant because it ALSO fails the excluded-counters pin, catching it from both directions. the gate was then run for real in a release build: exit 0, the workload id UNMOVED so no baseline is orphaned, and the new metric absent from the baseline, so the first armed land records it and the land after that is armed. and ADR 0073 consequence clause is amended exactly where it read as full coverage, with the correction stated in as many words, alongside its table row, its status header, and six other surfaces carrying the same claim (#1662) 904f6996 · dbf3dbe6…diff
  • the five-blind-instruments claim was recorded NOWHERE, and three sites cited an ADR that does not carry it - so the roster is derived from in-tree evidence and recorded ONCE, a five-row table whose rows are ticket, instrument, what it could not see, and the in-tree doc that records it. four of the rows came from a fixture doc that already named them, and the fifth from the counter crate description of a control that blessed a shape reading the tree ZERO times. and ONE NIGHT is wrong too: landing times on main put four of them across 2026-09-05 between 01:37 and 06:16 and the fifth at 14:00 THE SAME DAY, so it is one RUN rather than one night, which is what a sibling comment already called it. the count FIVE now appears in exactly one sentence, directly above its own table, where it is derivable as the row count - every other site states the property and cites the heading, carrying NO number of its own. that is the house answer this run reached two commits earlier: name the instances and stop counting. re-grepping found the same defect well beyond the three sites the ticket named - two more uncited fives, one of them attributing the finding to THIS run, three more citations of an ADR 0072 controls section that does not exist, and two comments reading three shipped instruments where a fourth had landed between the last two they name. the pin is what makes it hold: the citations must RESOLVE, so the heading must exist exactly once in the named ADR, the count word must equal the table row count with each ticket appearing once, and all six citing files must name the heading while NONE carries a count of its own - with the heading and the needle assembled at runtime so the file cannot satisfy the scan with its own constants. six mutations, each at ten passed and one failed, including a CONTROL that removes the whitespace-flattening and goes red, which proves the match is not trivially contiguous since three of the six citations wrap across comment lines. two of the six are each other DISCRIMINATION, one reddening only the count arm and the other only the citer arm. and what the pin does NOT do is stated in its own header rather than found out later: it does not check that the five rows are TRUE, each being a ticket and a code site checkable only by hand, and its citer list is hand-maintained, because deriving it by scanning would invert the check and wrongly demand a citation from the one site this ticket said to leave alone (#1664) 6a9d9cac · dbf3dbe6…diff
  • the harness gains the dimension that dominated it, and the axis is PROVED against the binary that carried the cost rather than added after the fix and trusted: a clone at the parent commit, running the same fixture through the same timed call, reads 171.0, 388.8 and 870.6 ms at 218, 436 and 872 paths a change where the lane reads 10.5, 18.0 and 35.4 - so the axis MOVES, 16.3 then 21.4 then 24.6 times, and the pre-fix side grows 2.27 then 2.24, linear in the axis, which is the changes-times-paths term. at 436 by 1024 it is 0.87 microseconds an entry against the ~1.02 implied by the original 507 ms over 494,810 entries, so the fixture STANDS IN for the real open rather than gesturing at it. the GRAPH_LOAD question is MEASURED rather than assumed, and the ticket own correction is confirmed while its stronger framing is refuted: at its pinned width the parent binary reads 155.6 ms against the lane 9.7, a sixteen-fold step, so that half WOULD have moved - its weakness is MAGNITUDE and FRAMING, 200 paths against this repo ~436 average and an id_key that presents it as graph load, not structure. only REPO_OPEN is structurally blind, because depth one pins the dimension at its identity value and one change cannot observe a quantity summed across the graph at any width. the control has three arms and none is implied by another - floors, then INTERCEPT on what the opened graph actually binds, then RESPONSE, where the same generator at HALF the declared breadth must carry exactly that many fewer entries - and the response arm is the one a count cannot supply, since a fixture pinned at one width passes the intercept whenever the flag happens to name that width. that independence is MEASURED and not argued: a discrimination pair reddens one arm each, and a diagnostic re-order shows the first mutation still trips the intercept when the response arm is asked first. the after column is deliberately NOT called flat, because it is not: 1.73 then 1.95, since a wider manifest is more bytes to FRAME even when nothing decodes them, and the row doc says so. the negative control the comment supplied is taken and then made DETERMINISTIC rather than left as a timing - a topology-only walk holds node count, parent edges and head count IDENTICAL across a doubling that moves the open by 97 percent. no counter is folded in, because #1662 is the counter half of this territory and the two are alternatives to choose between. and the blind-instrument roster is deliberately NOT given a row: that table is scoped to one run and says so, so the new kind joins the paragraph already carrying the later members, leaving the count sentence and its pin untouched (#1670) 5334741c · dbf3dbe6…diff
  • three sweeps running, the commit that DELETES an asserted-complete list writes a new one in the sentence that replaces it - so the recurrence itself is recorded as a named shape rather than fixed a fourth time and forgotten: the replacement is where the next list gets written, because the author is mid-sentence explaining what the true set IS. and this change caught itself committing the class TWICE while writing, which is the evidence rather than an embarrassment - an amendment draft saying the page said twelve in FOUR places where it was five, and a draft of the replacement paragraph writing six of the NINETEEN artifacts. both numbers are gone. the six-item metadata list becomes the PROPERTY: the set is the StoreArtifact trait, RepoStore::read routes every implementor through one door, and what keeps the conclusion true as the set GROWS is each impl path resolving to a named file under the store root - verified across all nineteen, none into the object directory. the conclusion that carries the 0% gate is kept verbatim, because it was never the wrong part. a THIRD copy of that enumeration, which the ticket did not name, was found and folded in. the twelves take a RULE rather than a sweep: drop the numeral where the sentence is a present-tense claim about the current table, KEEP it where the sentence narrates what ADR 0073 decided or refused as an EVENT. fifteen sites fixed, six deliberately LEFT - including the ADR title, which is the name the decision was accepted under, and a dated amendment recording what one mechanical edit touched, since correcting THAT is precisely the defect this ticket warns about. one of the twelves was already off by one and now states the property instead. the durable guard refuses a cardinal standing before opt-in halves across derived directories, and its LIMITS are in its own header rather than discovered later. the mutation that matters most is M2: writing todays CORRECT number, fourteen, is still RED, which is what stops the next reader fixing it to a value that expires. and the control that mattered is M3: the first draft tokenized raw text, so a count split by an 80-column comment wrap read clean - it PASSED OVER ITS OWN DOC COMMENT, which was quoting the offending phrase - and with the comment-marker strip removed and the defect still in place the pin goes GREEN, which is what proves the strip load-bearing rather than decorative. the fourth count of the roster population is deleted and all three of its escape routes closed, and the ADR stops citing a miscounting line as its authority for the run-versus-night correction, making the landing times the authority and citing that line only for the NAME. the negative-control heading is narrowed to what was actually measured, on the fixture rather than on the metric, and the two unreconciled readings of one measurement are reconciled once - where the ticket own framing was itself slightly off, since the two are the same commit pair measured in two sessions (#1907) b781aefd · dbf3dbe6…diff
  • the trait surface stops being a second materialize loop and becomes a one-line adapter over the walk loot surface runs, so a withheld object no longer fails it and the land gate counters fixture now measures that walk: the two promoted walks share one classifier deciding which failed reads are invisibility and which are faults, a burned read kept distinct because the surface walk labels it rather than counting it as sealed. a new test drives a withheld object through the trait and went red with object not found before the change, and red again when the adapter was reverted or the classifier arm broken. every gated counter reads the same before and after on the gated fixture, as expected for a fixture with no view and every object held. the 1703 sentence calling the gate a different loop is corrected to what it still cannot see, and the stale two-of-five counts in measure.rs, work_counters.rs and the ADR 0073 heading are replaced by what defines each set rather than a new number (#1927) f930875a · dbf3dbe6…diff
  • the policy counter is renamed PolicyParses and policy_parses because it has counted parses since #1704, and the policy.rs block and the ADR 0073 row now point at the variant doc instead of restating why; no stored perf record carried the old key, because the gate does not record this counter. PUSH_SHAPE_DEPTH, OFFER_GUARD_DEPTH and MISSING_DEPTH are literals rather than aliases because their reasons have diverged, and each is still 128. ride_entry takes one RideState instead of three maps, while the one_pass_bundle oracle keeps its own transcribed walk and memo so the byte-identity test still compares two walks, and still went red when the key arm was disabled. the gated counters read 743, 200 and 24 before and after (#1718) bbd04ef4 · dbf3dbe6…diff
  • a deposit plan builds the tree it ships once instead of once per custody lane, and the first act had to be an instrument that could see the difference: no counter a land can read moved over a repeated whole-graph pass, so Work::GraphSorts now tallies ChangeGraph::in_order and is gated at 0% beside the object pair and store_file_reads, reading 8 on the gated fixture and one string across the drift pin repetitions. THE TICKET ASKED FOR THE TALLY TO REUSE Work::TreeWalks INSIDE finalized_tree and for ADR 0073 to re-decide that exclusion, and that was refused rather than followed: tree_walks counts a whole-tree FILESYSTEM walk of a working tree and this is a graph pass, and the in-process tier links loot-core and never loot-cli while nothing in loot-core outside its own tests calls the deposit lanes, so a tally there would have read zero on that tier anyway and the pin would have stayed green while its stated reason went false. the exclusion therefore stands unmoved on its own measurement, and the ADR records the trigger that did not fire rather than a re-decision it did not force. measured in the counter and not in wall clock: a forge plan over a fixture carrying an embargoed path, a Restricted path and the Internal default read 3 sorts before and 1 after, a relay plan 2 before and 1 after, the three lanes now taking the finalized tree as an argument plan_deposits builds once. the tips membership test inside that build became a set lookup rather than a Vec scan, which no counter can see and which is named as such rather than claimed. red under mutation, counts read each time: the shared build removed so each lane derives its own again failed the new pin (0 passed and 1 failed, graph_sorts 3 against 1, and with the forge arm relaxed the relay arm failed at 2 against 1), the tally dropped from in_order failed the anti-vacuity pin (10 passed and 1 failed) and the new pin (0 passed and 1 failed), and graph_sorts dropped from gate::COUNTERS failed four at once (7 passed and 4 failed), each restored to 11 and 1 passed. the two generated membership sentences in CONTEXT.md and HUNT-PERF.md are pasted by hand as their pins demanded, the hand-written workspace width in verbs/mod.rs moves to 390, the visibility census gains the two argument bindings the by-reference lanes create, and a count in loot-count that was wrong in the commit that wrote it is replaced by the property. no migration, no wire or format byte moves and no host behaviour moves, so this owes no deploy, though the gate records a new metric from the next land. the workspace suite is green (4174 passed over 132 binaries, 8 ignored) (#2225) fe6a089f · dbf3dbe6…diff
  • the residual #1888 could not settle is settled by counting instead of timing, and the answer is that the clean pair was never in excess: a new measure half counts allocations over the whole of ingest_shared_lineage and splits the call into the eager graph read and the walk and splice, two bands that sum to the region EXACTLY, counter by counter, because the region is those two doors with a map lookup between them - the property no stop instrument can have, and #1888 recorded its own stop reading an early return as costing more than the work it skips in six rounds out of six. at the width the half pins, the pre-#1572 clone spelling put back reads 6488, 12512, 24552 and 96803 allocations at depths 8, 16, 32 and 128 against 4289, 8113, 15754 and 61606 shipped: a removal of 1.37 per manifest entry at every depth in that table and of 33.9 to 36.4 percent of the region, both arms linear with per-entry slopes agreeing to four significant figures, so the same fit carries the depth #1888 measured at to about 281000 removed allocations out of 771000, or 36.5 percent of the times the region reaches the heap. THE TIMED BAND WAS NEVER A CEILING ON THIS CHANGE: the walk and splice the stop instrument left 16.2 ms, a tenth of the region by time, makes 37 percent of it by allocation, so a clean delta of 13.6 percent sits BELOW the share of the work the change removes rather than above it, and nothing is left over to explain. the published magnitude does not move, because a count does not convert to milliseconds and this instrument prefers none of the three timings - what is withdrawn is the reason to distrust the largest of them. no opt-in half is added and Fixtures::gated is untouched, because a land builds release, where the allocation control refuses rather than reporting a false zero, so this reading is a test one taken by hand: its own binary installs the allocator no library may install, opens on require_allocation_counting, and carries an ignored sweep. HUNT-PERF gains the marginal-cost trap it was missing, with the measured instance where a discarded second read reads over 100 percent of the region it is supposed to be a fraction of, the band decomposition that replaces it, and the note that a summing decomposition is still a perturbing one. red under mutation, counts read each time: the clone spelling restored failed the splice-band pin (2 passed and 1 failed, 190 allocations against 73 entries), the pool read moved outside its band failed the sum control in all three (0 passed and 3 failed, 65 against 272), the global allocator removed failed all three on the control itself (0 passed and 3 failed), and a fixture ignoring the declared width failed the scaling pin (2 passed and 1 failed, 0 entries added), each restored to 3 passed. no migration, no wire or format byte moves and no host behaviour moves, so this owes no deploy. the workspace suite is green (4177 passed over 133 binaries, 9 ignored) (#1890) 4c6b019a · dbf3dbe6…diff
  • the attribution the #2223 refutation asserted is now measured and the conclusion stands, because a nested count region says which span the surviving reads belong to: with this body live the open inside vouch_if_on_disk reads 0 files over 200 paths, and with the ceiling in place that same span reads 199 on status and 200 on surface, so the reads move rather than go away and a header only body would add its own opens on top of them. the size axis gains the fourth column the ticket asked for and the effect does not run away with it: at 1 MB objects over a 210 MB store the ceiling leads by about 8.5 ms on either verb, under a fiftieth of the verb, against 14.24 and 20.91 and 69.00 and 455.60 ms for status and 16.67 and 22.92 and 67.37 and 461.02 for surface. THE 3.3x DISCREPANCY IS RECONCILED AND THE GUESS ABOUT IT WAS WRONG: the loose store weighs 213,800 and 3,285,800 and 26,223,400 bytes here, the three figures the ticket body records, to the byte, so both arms ran the same incompressible fixture and compressibility explains nothing; what differs is that the ticket timed the process, which reads 22.7 and 29.8 and 77.6 ms over these same fixtures and meets it at the two smaller sizes, while its largest reading of 226.2 ms reproduces in neither arrangement against seven repetitions spanning 69.00 to 71.96 ms and a first unwarmed reading of 71.13. so the 11x move it was filed on rests on one reading, and the move these fixtures carry over that range is about 3.4x. #2226 gains the depth axis its own cost model lives on, swept without touching MISSING_DEPTH so no fixture and no workload_id moves: at width 200 the walk is linear in depth over 1.16 and 4.66 and 18.49 and 74.04 ms at depths 8 and 32 and 128 and 512, the probe deleted binary reads 1.08 and 4.38 and 17.38 and 68.82, and the probe share does not move across that sweep, which it would not, because probes and manifest entries are both O(changes x paths). that doc now cites #2240, records what the half is, and says the probe is two map lookups rather than one. ONE SWEEP ITEM IS REFUTED RATHER THAN FIXED: the short line in gate.rs is not a rewrap leftover, it is short because the 33 character intra doc link after it does not fit at this column norm, and the same file carries a 44 column line for the same link higher up. the cheapest item had the only seam and it is pinned: the WORK_COUNTERS exclusion table read as the excluded variants and nothing else, which is the definer #2234 sent a reader to, and it is now read back against Work::ALL filtered by gate::COUNTERS. red under mutation, counts read each time: graph_sorts dropped from gate::COUNTERS failed the new pin (0 passed and 1 failed, three variants named against four owed), the PolicyParses row deleted failed it (0 passed and 1 failed, two against three), and the table header renamed so the scan reaches no rows failed the anti vacuity guard (0 passed and 1 failed), each restored to 1 passed and the file to 12 passed. the two ADR 0073 enumerations are deleted rather than corrected, the CONTEXT and gate paragraphs are reflowed with identical word streams, and no code outside a test changes, so this owes no deploy. the workspace suite is green (4178 passed over 133 binaries, 9 ignored) (#2242) d6bf7f55 · dbf3dbe6…diff
  • the figure the #1890 verdict rests on is now a column in the table it was missing from, taken the way that table was taken: the pre-#1572 clone spelling put back and the ignored sweep run once per arm, which reads the splice band at 41.3, 39.2, 38.0 and 37.2 percent of its own region on the before binary against 11.2, 6.2, 3.4 and 1.3 shipped, so the 37 percent the conclusion turned on is readable from the tree instead of from a session transcript, and the re-take reproduced every before and after cell already there to within one allocation. THE VERDICT IS NARROWED TO WHAT THE COUNT SHOWS: withdrawing the band ceiling and confirming the clean delta are separate acts and only the first was done, because a count does not convert to milliseconds - what is retired is a contradiction between two readings rather than the spread among the timings, and the published magnitude stays where they left it. two precision defects in the #2242 retraction go with it: the move over that size range is about 4.8x in the call and about 3.4x as a process and the sentence now names which, and rests on one reading is withdrawn because #2223 records no repetition count for its whole-verb rows, so what is known is that the figure does not reproduce and not how it was taken. the sweep doc had its axes inverted against the code under it and now states the property instead, that the shapes fall into runs holding one axis while the other moves, and the list class is answered for the third time in this run by replacing the two named untimed controls with the questions that decide membership. the duplicated in-loop guards are extracted: prove_the_position_has_not_ingested and prove_the_tip_was_spliced are asked by the timing and the count alike, each refusal written once and true of both. the named positive control is refused rather than built, because an in-tree knowingly worse arm means a wrong body in production code, and the before column now published stands in its place. sdk records the node type-stripping floor its .ts import imposes in engines, where npm reads it. red under mutation, counts read each time: the position control inverted failed all three allocation pins (0 passed and 3 failed, naming a position holding 1 change), and the splice control fed a false answer failed all three on its new text (0 passed and 3 failed), each restored to 3 passed. no migration, no wire or format byte moves and no host behaviour moves, so this owes no deploy. the workspace suite is green (4179 passed over 133 binaries, 9 ignored) (#2247) c8b11725 · dbf3dbe6…diff
  • the tutorial interrupt red #1916 read as a removal that lied is a tree made again after the sweep: on the linux runner std remove_dir_all answers success only once the root is gone, the captured transcript prints the first prompt ahead of the handler line, and walk, still running on the main thread beside the handler, opened with a create_dir_all over alice that minted the root back before ask beat the heartbeat into it. two delays injected into that sequencing reproduced the red and its alice, heartbeat remnant on this desktop with confirm_gone in place, so that check alone would not have closed it; Sandbox::create now makes alice before the handler is armed, the same two delays pass, and a unit pin drives the sweep, the walk and the beat in that order. what stays open is said at the fix: other writers, the relay thread and the loot subprocesses among them, can still put a path back mid-step. the CI run recorded the two readings and not the sequencing, so the mechanism is established by reading and by the reproduction rather than observed there, and workflow.md stops calling the report and the look one moment. the loot-s3 client keeps its 60 s budget for want of any measured rate to its bucket, but a request that runs out now names it and what it covers, where reqwest said error sending request or error decoding response body with no word of a deadline. the sdk doc stops claiming the native policy: the formula is copied, native allows the send budget between answer chunks where the sdk allows idleMs, the rounding differs, wire.rs now points back at the copy, and the unit test reads the floor from its constant. smaller: the engine.rs verdict compares the band against the band, the measure.rs refusals state a property instead of counting callers, the fixture generator import note sits at the import, and transportFailure takes a role rather than a string. red under mutation, counts read each time: create_dir_all put back in walk (11 passed and 1 failed, holding alice and heartbeat), the s3 timeout naming removed (12 passed and 2 failed), the sdk upload rounded down (6 passed and 1 failed), each restored to 12, 14 and 7 passed. no migration and no wire or format byte moves; the forge and relay deployables word a timed out object store request differently once next deployed, and no code in the tree matches on that text, so this owes no deploy. the workspace suite is green (4192 passed over 133 binaries, 9 ignored) and the sdk suite is green (137 passed over 13 files) (#2254) bdeb6a0c · dbf3dbe6…diff
  • the graph rewrite a finalize pays reads the graph file back deferred and copies each manifest stored frames where Manifest::frames proves them to be what encoding its map writes (no backslash key, keys strictly ascending in Path order, UTF-8 holder names), and falls back to the eager read otherwise, so save_to no longer decodes every path of every change in history to add one change. the new --graph-rewrite opt-in half times that whole save at 200 paths; paired, three interleaved rounds, the gate reading load idle at 1 to 4 percent: 48.18 to 48.48 ms down to 12.65 to 12.72 ms at depth 256, 183.43 to 183.49 down to 39.14 to 39.47 ms at 1024, and 750.3 to 759.4 down to 179.5 to 182.6 ms at 4096. counted by the new graph_rewrite_allocations test, the save at depth 1024 allocates 6,039 and 6,061 times on two runs against 695,198. the file written is byte-identical to the decoding rewrite, pinned over every golden and a lone y//ab key (copied), the legacy separator and the #2273 shapes (not copied, rebuilt from the eager read), and a key or holder name that is not UTF-8 (not copied, and the save still refuses it). red under mutation, counts read each time: the eager read put back (1 passed and 1 failed), the holder check dropped, the ascent check dropped and the eager fallback dropped (1 and 1 each), the counts check dropped (0 and 2), restored to 2 passed each. riding along: HUNT-PERF names the new half, and the visibility census names the moved and new bindings. no migration and no format byte moves, so this owes no deploy. the workspace suite is green (4278 passed over 137 binaries, 11 ignored) (#2280) e7d666e0 · dbf3dbe6…diff
  • LineagePool::read, the one read of the shared graph file an adopt or ferry pass catches up from, reads it through read_graph_deferred, the door #2280 added, and leaves every manifest undecoded, so an ingest no longer decodes every path of every change in history to splice nodes whose manifests it never reads; before moving any node the splice asks the new Manifest::decodes, which steps the frames for a key or holder name that is not UTF-8, and refuses the ingest naming the change when a node it would splice holds one, which the eager read refused, so the #2275 panic gains no new route. paired --ingest readings, one loot-perf-gate --features count built per arm, interleaved, the gate reading load idle at 1 to 6 percent (peak 9): 162.7 to 164.6 ms down to 12.04 to 12.39 ms at depth 1024 and 331.4 to 331.5 down to 26.9 to 27.6 ms at 2048, the check costing 0.2 to 0.7 ms at 1024; counted at depth 128 and width 200 the region allocates 1,057 times against 61,604, the read band 279 against 60,826 and the splice band 778 on both arms. the memory trade the splice comment left open is measured and taken: over a copy of this repo graph file (85.7 MB) the deferred read peaks at 171.3 MB against 308.5 and holds 87.9 against 222.2 while the pool lives, and once the pool drops a splice of ten nodes keeps the 85.7 MB buffer where the eager read kept 1.2 MB, one buffer per read that splices, for the rest of the verb. two new pins: over canonical, nested, legacy separator and the three #2273 shapes a spliced node stays undecoded and answers the eager read tree, addresses and saved tree, with tier_counts answering as the open does where two backslash-free keys name one path; and a key or holder name that is not UTF-8 refuses the splice and splices nothing. lineage_allocations now pins that the ingest count does not follow the entries. red under mutation, counts read each time: the eager read put back (0 passed and 2 failed in the engine pins, 2 and 1 in lineage_allocations), the splice check dropped (1 and 1), the holder check dropped (1 and 1), restored to 2 passed and 3 passed. no migration and no format byte moves, so this owes no deploy. the workspace suite is green (4282 passed over 136 binaries, 11 ignored) (#2282) 2350f8dd · dbf3dbe6…diff
  • loot blame and loot log --path read the one path they ask of each change through the new GraphView::address_at, which answers off the manifest frames through the new Manifest::address_of where the frames provably are the map (no backslash key, keys strictly ascending in Path order, checked by the keys_ascend step Manifest::addresses uses) and from the decoded map otherwise, so a history walk no longer decodes every manifest on the lineage to read one entry of each, and blame no longer clones each tree; has_path keeps decoding, since its remaining production caller asks many paths of each of a few changes. the new --path-history opt-in half times address_at over every change of a re-opened chain at 200 paths, asking the path that orders last; paired, one loot-perf-gate --features count built per arm with the frame arm never taken as the before, interleaved, the gate reading load idle at 1 to 4 percent (peak 7): 34.87 to 34.97 ms down to 4.46 to 4.53 ms at depth 256, 138.8 to 139.3 down to 18.01 to 18.03 at 1024, and 279.2 to 280.6 down to 35.9 to 36.2 at 2048; counted by the new path_history_allocations test at width 200, the walk allocates 484,352 times at depth 1024 against 0. through the binary, against the landing position binary over a repo 1,025 changes deep and 203 paths wide, min of 15 over two rounds: loot blame 160.4 to 160.6 ms down to 33.7 to 33.8, loot log --path 164.8 to 165.8 down to 43.7 to 44.0, plain loot log 28.9 to 29.2 on both, and every output compared was byte identical with its exit code and stderr: blame plain, --porcelain, --json, with a selector and on an absent path, log --path on flat, nested, dotted and absent paths, and shortlog --path. new pins: over every golden, a file whose Path order is not its byte order, the legacy separator file and the three #2273 shapes, address_of answers what the eager map answers for every key and for probes that are not keys, decoding nothing exactly where the frames are the map, and it answers off the frames past a holder name that is not UTF-8; a spawned blame and log --path find a/b.txt beside a-b.txt and a.txt. red under mutation, counts read each time: the frame arm never taken (0 passed and 1 failed in the codec pin, 1 and 1 in path_history_allocations), the ascent check dropped (0 and 1, on the answer), the counts check dropped (0 and 1, on the control, since Windows reads a backslash as a separator), byte order in the stop (0 and 1 in the codec pin, 0 and 1 in the spawned pin), each restored to green. riding along: HUNT-PERF names the new half. no migration and no format byte moves, so this owes no deploy. the workspace suite is green (4289 passed over 137 binaries, 12 ignored) (#2283) 045c7e42 · dbf3dbe6…diff

Renames are not followed. loot's tree maps a path to an address, so a rename is a delete and an add. This list is the history of the name, not of the bytes.