Changes touching this path

  • the pre-land perf gate: counters block at 0 percent, timing warns, and a lane pins itself (#637) 52a2341e · dbf3dbe6…
  • loot-first: exec the perf gate from a binary built from the position (#712) The gate measured in-process, exercising whatever loot-core was compiled into the running loot-first.exe while PinnedCheckout stamped the point with the position revision — and nothing rebuilds before the gate, so a stale binary reported perf: no move for a revision that provably moved a counter (#638's live find). The alarm failed OFF, silently. Now loot-first land builds loot-perf-gate from the landing position's own tree (cargo build --release --locked -p loot-perf --bin loot-perf-gate — cargo's staleness check is the provenance proof) and execs it. A land mode on the bin (--land <change> --stash <file>) keeps the split the record demands: the verdict decides before cargo test, and the would-be record line is stashed outside the tree for the land to append verbatim as its last act, so the recorded bytes are produced end to end by the position's own code. loot-first deliberately no longer links loot-perf: no compiled-in harness, no way to measure the wrong code. --locked keeps #698 held: a stale Cargo.lock is refused, never rewritten into the signed change; target/ stays outside the seal (verified live — loot status clean across the build). Measured cost: +0.16 s build on an already-built position, 3.1 s when the gate's own crates changed, 12.6 s from a stone-cold lane — against the unchanged 2.2-2.6 s measurement and the multi-minute cargo test that follows. 0d9c6195 · dbf3dbe6…diff
  • land gate: never rewrite the tree being signed, never trust a stashless verdict (#698, #723) 132e06ba · dbf3dbe6…diff
  • the perf record becomes a directory of one-file points, so two lands no longer collide on the last line, and a point names its PR (#740) The record was the repo's worst conflict surface: every land appended to the tail of docs/benchmarks/series.jsonl, so two lands always collided on the last line — 6 of the 38 conflict-resolution commits on main name that one file. It is now docs/benchmarks/series/<change>.json, one file per point, so lands touch disjoint paths. The pre-#740 jsonl stays where it is and is read as the older head of the same series; migrating it would have been one last whole-file rewrite of exactly the file this was about. A point also carries the PR it landed under. A bounce recovery mints a new change id, so one shipped thing can leave four points, each measuring a genuinely different tree — none may be suppressed, and the PR is what says they are one thing. It is also the record's only join back to git log: landed_change is the durable change id, while the projected trailer carries the version id, so no id in the record has ever matched anything in git. The land's write is still a verbatim copy of the gate binary's stash (#712); the stash itself stays a single-line jsonl, since it is a temp handoff merged by nobody. The file-name rule is duplicated in loot-first, which may not link loot-perf, and pinned by a test on both sides. c393beef · 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
  • the gate measures the constructor, not a copy of its constants: loot-perf-gate starts from Fixtures::gated() (#915) `Fixtures::gated()` is documented as what the pre-land gate measures and had no production caller — the gate binary rebuilt an equivalent by hand out of COUNTERS_SIZE/TIMING_SIZE/NEGOTIATION_SIZE/NEGOTIATION_DEPTH. Two independent statements, and `fixture.rs`'s workload_id test — the one guarding the field #607 selects baselines on — asserted against the one the shipped gate never constructed. They agreed only because #847 edited both by hand. The binary now starts at `Fixtures::gated()` and applies `--counters` / `--timing` as modifications of it (`with_counters` / `with_timing`), so a change to the constructor reaches the gate by construction rather than by whoever edits next knowing this file exists. The negotiation half deliberately gets no setter: its depth IS the measurement (#847), and that asymmetry is the design. 5a08bb26 · dbf3dbe6…diff
  • the perf gate stops reporting a run that measured nothing as a clean pass, and the load probe stops letting one bursty draw discard the measurement, because the two bracketing reads were folded by max and the second sat in the harness's own wake (#1389) 542d5442 · 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
  • the three surfaces describing the perf gate stop disagreeing about what an absent metric means, because an explained absence is reported and exits 4 exactly as an unexplained one does, and each surface now points at the one that owns a fact rather than restating it — including the exit code itself, named once in loot-perf and read from that name by both the gate binary and the land (#1403) dc3ccf75 · 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
  • a perf half added tomorrow cannot go undocumented, because one table now drives the gate's parse, its usage line, its module doc and both operator docs — and the figures that had drifted from whatever owns them, including a timing resolution quoted ten times better than the shipped tolerance, point at the owner instead of restating it (#1436) 4568d998 · 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
  • 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
  • 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
  • adding one opt-in perf half stops costing thirteen hand-edits and starts costing two, because Fixtures keys its opt-in halves by the OPT_IN_HALVES row that already described them instead of ten Option<Workload> fields with three constructors re-listing every None, and loot-perf-gate builds its whole valued-flag set and both its usage strings out of that same table, so the hand-typed [&str; 17] arity is gone and a throwaway row the strict parse refused by name before this change is accepted with no second edit after it (#1599) Subsumes #1474, whose done-bar is the whole claim and was run in both directions before anything else. A throwaway half written the old way, with all eleven structural sites edited, was still refused by the shipped binary as an unknown argument --throwaway at exit 2, which is the #1465 experience live. After this change the same half is one contiguous row in OPT_IN_HALVES, and the binary accepts the flag, prints it in the derived usage line as [--throwaway <files>], and carries on past the parse to the pin stage. What moved: - Fixtures now holds one [Option<Workload>; OPT_IN_HALF_COUNT] array in OPT_IN_HALVES order rather than ten Option<Workload> fields. gated / split / uniform stop re-listing every None; with_X, the X() accessor and the free take_X function become Fixtures::with, Fixtures::half and OptInHalf::take, all keyed by OptInHalf::slot. - OptInHalf::of and OptInHalf::take, both fn pointers, become one Axis field. Axis is #847s rule written as data: the flag carries the half own axis and the other dimension is pinned in the row, so the ten one-line take_X functions that each re-implemented that rule are gone and a reader can see which dimension is which without leaving the table. - loot-perf-gate VALUED_FLAGS array, with the hand-typed [&str; 17] that walked 13 to 17 across five halves in one night, becomes valued_flags(): the union of RESIZES_A_HALF, TOUCHES_NO_FIXTURE and the table. The union is the point, because #1403 distinction is that --counters and --timing resize a half the gate already takes while an opt-in flag adds one. Both USAGE copies are derived too: the const becomes usage(), formatted from each row flag and axis word, and the module-doc synopsis enumerates no half at all. - OPT_IN_HALF_COUNT is OPT_IN_HALVES.len(), so no count of the halves is typed by hand anywhere. The invariant did not move, verified by running the gate rather than by reading it. An unflagged dry run of a release binary built from this tree prints workload counters=small_files/200+timing=small_files/2000+negotiation=small_files/24x96, carries no opt-in metric, and reports perf: no move against its baseline. A flagged run takes --compressible, --open and --graph-load together and produces compressed_read, repo_open and graph_load in their own batches under the id tail +compressed=compressible_files/64+open=small_files/200+graph_load=small_files/200x16, which is one row per Axis variant and both axis directions. New pins, each broken before being trusted: - every_half_takes_the_fixture_it_always_did writes out all ten halves workload ids at one flag value, because this is a refactor and a fixture id is the key #607 selects baselines on. Swapping the two dimensions of Axis::Changes reddens it with the value, small_files/64x200 against small_files/200x64. - taking_one_half_takes_exactly_that_half and no_two_halves_share_a_flag_or_an_id_key cover the slot keying over every ordered pair; a slot() that always answered 0 reddens both with values. - a_flag_moves_its_own_axis_and_pins_the_other makes the claim ten per-half tests each made by hand, once over the table and in both directions. - the_module_doc_synopsis_enumerates_no_half inverts the assertion #1436 wrote: that one held a hand-kept copy equal to the table, this one holds the copy to not existing. - every_valued_flag_is_classified_exactly_once replaces the old classification test, which is now true by construction, with what derivation cannot give: that the three classes are disjoint and their union is the whole set. Adding --reps to RESIZES_A_HALF reddens it. No assertion that OPT_IN_HALF_COUNT equals the table length is written, and a comment says why: it is that length, so no edit could redden it, and a check that cannot fail is worse than no check (#1578). 8e0284b8 · 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 perf skill index stops stating a gated status that nothing checked, because the work-counters row now carries a sentence generated from Work::ALL and gate::COUNTERS rather than one written by hand, which is how it came to read not recorded and not gated for a whole land after #1602 gated two of them in the very commit that corrected three other passages of the same file, and the four claims from the same arc that outran their code are fixed at both copies each: the loot-count module doc now carries the amendment ADR 0073 made to its verbatim twin in ADR 0072, ADR 0072 counts five counters beside a list of five and states the allocator split without a count at all, a fabricated test citation gives way to the test that really pins the gated id, and the land-time on-cost in ADR 0073 is about 56 microseconds derived from the table 80 lines below it rather than 2.8 (#1629) f5a642e0 · 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
  • the last two readers of the deleted argv shape ask the door instead, and the blocker this ticket named was not the one holding them out: the static lifetime was never in the way, because OPT_IN_HALVES is a const whose flag fields are already static, so the valued union is a const fn fold at an arity derived from the three class lists and a half without a class becomes a build failure rather than a runtime one - what actually kept the perf binaries from naming the door is that loot-net is a dev-dependencies row in their manifest, deliberately since #847, because a real edge would link axum, reqwest and tokio into the gate binary every land builds. so the door moves once more, to loot-core, which every binary-shipping crate already names directly and which is pure std, making this #1628's own criterion applied one crate further rather than a second door - loot-net keeps a re-export shim so no caller changed. the recursive delete is demonstrated rather than argued: --size 64 pinned-checkout scratch bound the scratch slot to 64 and a file planted under a temp tree at 64/counters-repo is gone after a run driven by the real production path, proved non-vacuous by aiming the same call elsewhere and watching the assertion fail; it now binds the checkout the operator typed. the gate's poisoning is worse than this ticket described and its example argv is corrected rather than repeated, since that one is already refused by the strict single-position parse - the argv that genuinely passes needs the forged operand followed by another flag, and before this it wrote a 925 byte measured record to a file named --reps in the working directory while the land-and-stash pairing guard passed, because the stash it checked had been forged out of the message operand. after, it exits 2 naming the pairing and never measures. both call sites were extracted from main first, following #1628's remedy, so a pin can reach what main asks rather than only the door's traversal - and every pin was reverted to prove it red except one that pins fresh rather than the binding, which is documented as such and proven non-vacuous separately. the exemption list is emptied and re-adding a name now costs deleting a working census, since the roll call asserts set equality (#1682) d7e849b0 · 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 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
  • 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
  • a prose pass narrows claims that read wider than the code, and LineDelta::rendered goes crate-private. ADR 0007, CONTEXT.md and the object_and_key_at doc say the reveal gate is asked at every read through the grant key door, not at every read, since grant_sealed keeps its escrow fallback by design; the Refit enum count, the family list in CONTEXT.md and the refit.rs header, and a stale claim that every planner runs the draft check, now point at the enum and the wildcard-free minted_edges match instead of a count; role_display gets back the blank doc line rustdoc folded into the last bullet, verified in the built HTML, and a record type added to ReservedRecord replaces a third record type; the Landmark entry records the one-line rendering from #1519; the revset named door and the hunkpick PATCH constant state the exceptions a reader finds (grep writing its own refusal, restore spelling -p out under the main.rs census); the ChangeGraph insert doc stops saying the callers do not insert parents-first, names DagRepo::apply_sync for an apply_bundle DagRepo does not have, and says why the ordered ingest_shared_lineage splice stays on insert; ADR 0023 now says what #1870 wrote in the delta_shape header, that the reveal_at split is about the field and not the number, which embargoed@ can carry. nineteen assertion messages lose the run of spaces a rewrap left inside the literal. LineDelta::rendered and Rendered become pub(crate), with a compile_fail probe and a positive control: the probe was red before the narrowing (2 passed, 1 failed), and making the method pub again reddens it (3 passed, 1 failed). items 2, 8 and 14 need no fix here: the #1515 raise is real because #1516 lowered the ceiling between the two raises, #1968 dropped the width narrative, and #1860 withdrew the figures. cargo doc warnings are unchanged for loot-core, loot-codec and loot-cli. no migration, no wire or format byte moves, and no forge or relay byte moves, so this owes no deploy. the workspace suite is green (3913 passed over 123 binaries, 7 ignored) (#1848) eb966bdb · 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

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.