Changes touching this path
- loot evolog --porcelain no longer prints a whole recorded message in its E row: the last column was the message as recorded and a porcelain row is one line, so a message with a body printed that body at column zero as a line which is not a row, and a consumer reading a row per line read it as one and was then wrong about the rows after it by position, while an empty message left the field empty where ADR 0088 V3 puts the dash. each was reproduced by hand through the spawned binary first. the column is the message first line now, through the new render::subject_line, which is the rule the log terminal column already followed and is now one home for both frozen shapes, and col gives it the dash when the message is empty; a tab stays inside it, since V5 puts the free-text column last so a consumer splits the leading fields with a limit and takes the tail whole. the human subject column takes the same first line, so a version with a body renders on one line there too. evolog --json gains a trailing message field carrying the whole message and its subject becomes the first line, the pair log --json already spells: that re-means a shipped value, and the amendment records it rather than leaving two shapes disagreeing about the word. the new spawned pins for a multi-line, a tab-bearing and an empty message went red before the change (1 passed, 3 failed) and are green after (4 passed), with a single-line row as the control that stayed green throughout; they redden with the whole message put back in the column (1 passed, 3 failed; the unit pins 6 passed, 2 failed), with the dash dropped (3 passed, 1 failed; unit 7 passed, 1 failed) and with the json message field removed (3 passed, 1 failed; unit 6 passed, 2 failed). the pre-change release binary and this one print byte-identical porcelain and human rows for a single-line message over one repo. ADR 0023 carries the dated amendment with the shape and what the fix moved, ADR 0088 section 4 no longer lists evolog and says an item leaves when its fix lands, CONTEXT.md names both, and the workspace suite is green (3830 passed) (#1973)
c9a99b16 · dbf3dbe6… - review sweep 15 fix-up: the evolog dash is on an empty FIRST LINE, the subject rule now has one home, and the surface prune says plainly that it discards. loot evolog --porcelain dashes its last column when the message first line is empty, which an empty message and a message whose body starts under a blank one both are, and three places said an empty message: the doc above the encoder, the ADR 0023 amendment of 2026-09-17 and CONTEXT.md. The wording moved rather than the bytes, because dashing on an empty message instead is a porcelain byte change for a message that opens with a newline, and a new spawned pin, a_message_whose_first_line_is_empty_is_the_dash_too, puts a run under the sentence: the file reads 5 passed, and with the whole message put back in the column it is 2 passed, 3 failed, the single-line control among the two that stay green. render::subject_line was billed as the one home while six call sites derived that first line inline, the four the ticket named plus the shortlog author rollup and the missing-object listing, so log --oneline, heads, show, range-diff and those two all ask it now, and the near-cousins that each do something more, the note ellipsis, the revert subject and the loot-first PR title, are named beside it rather than routed. The control is the spawned binary: 28 outputs over two repos, one carrying a multi-line message and one a blank first line, are byte-identical before and after, and with subject_line returning the whole message 10 of 11 of them move and the loot-cli lib suite reads 1219 passed, 4 failed, naming the shortlog rollup and the oneline row among them. The surface stale-debt prune keeps the removal error it discards, which #2018 declined and its closing note then reported as fixed, and the doc above it now says the let _ is deliberate, that apply_change_delta propagates where this one does not, and why: the delta writer snapshots, so a refused removal would be recorded as a deletion the disk never took. The removal census in workspace.rs states what its matcher is blind to, a type-annotated binding, a call split over lines and a path derived from a root-joined one, and names disk_entry::drop_empty_parents, whose remove_dir climbs from a dest its caller joined and which the fold cannot reach, because remove_dir takes an empty directory only and a directory holding a file the writer just wrote is not empty; widening the matcher would not have reached that call, so the blindness is stated instead. CONTEXT.md gives that census its crate and spelling scope. migration_serial records that hold blocks and is not re-entrant, and that it serialises migration runs rather than pg_authid, naming the fixed-name CREATE ROLE in tests/rls.rs that writes the shared catalog outside it; Held loses its Option and its Drop impl, since dropping the field is what the compiler already does. The migration census compares a BTreeSet the way the removal census does: with the const reordered it stays green where the Vec compare it replaced goes red (0 passed, 1 failed), and a name dropped from the const reddens it (0 passed, 1 failed). pg/tests.rs cross-references its own source walk and fn finder to source_walk in loot-cli and states where the pair differs. The folds_case helpers in two test files become folds_case_under, so neither shadows the disk_entry rule it asks. The rewrap leftover in account.tsx that #2018 moved rather than fixed is rewrapped with its neighbours, and so is a second one mid-paragraph in CONTEXT.md that the same rewrap reached. The forge suite is green against a throwaway 17.0 cluster (469 passed over nine binaries, no skip note) and its lock case goes red with the session dropped rather than held (0 passed, 1 failed), the site gate is green (643 passed, every surface under its ceiling), and the workspace suite is green (3833 passed) (#2023)
c38e3299 · dbf3dbe6…diff - sweep 16 fix-up: the removal census header stops denying a spelling its own fixture holds, and the at-most-one-class claim the no-cache decision rested on is replaced by the worst case a contended withdrawal really pays. the census header said it does not strip block comments or string literals and that there are none of either, while the classifier fixture below it spells six removals in string literals, addresses among them, and the expected set names that fixture because of them; the bullet now says the spellings exist, that the set names the fixture for that reason, and that one arriving in a function the set does not already name arrives red where one inside a function it does name would not. the ticket said five, which is why the corrected sentence carries no count at all. the same header said #1897 gave pack_every_loose_object its address so this census could see it, which it cannot: that site asks the helper, spells no removal and is correctly absent, so what the address buys is that a regression there spelled by address would be visible, and one spelled the old way still would not. ADR 0077 and ADR 0075 both said a request resolves at most one class and rested the no-per-request-cache decision on it, which the comment beside the gate refutes: the existence gate is called inside the withdraw retry loop, so a contended withdrawal resolves one per round. the cache question is re-answered on that: the worst case is rounds times one resolution, the loop carries no round cap so it is unbounded in principle, and what bounds it in practice is who can turn it, since a round is lost only to a write another party committed to this row, the production routes that write over an existing row admit only parties to the offer first, and most such writes end the loop rather than prolong it, an amendment away from this signer refusing at the author check and a close making the row terminal. the resolution stays per round rather than cached, because a cache would pin a class for the life of a request where a round decides against the class as it then stands, and the new conformance case the_withdraw_gate_resolves_a_class_for_every_round_it_turns is the run under that sentence: an uncontended withdrawal as the control, an amendment inside the window, and the contended one resolving twice as many classes as the control. with the resolution hoisted out of the loop it goes red against the memory store and against a live cluster alike (0 passed, 2 failed, left 1 right 2; 2 passed restored). ADR 0075 also stops saying the standing arms answer whatever the class says, which inverted its own rule: they admit independently of the class, the predicate asking the class first and falling through to them. visible_to takes the class and the key as one Viewer now, private fields and one resolver, so the pair cannot be mismatched: a literal outside the module is E0451, measured, and the read-cost claims are unchanged at one resolution per call of read, list and the withdraw gate. the evolog human doc said the cell is blank where the message is empty, the fourth home of the wording #2023 moved, and a blank first line blanks it too, with a spawned pin over the human column and an ordinary subject as its control (5 passed, 1 failed with the whole message back in that column). census mutations: a bare removal by address put back in pack_every_loose_object reddens the census naming that function (2 passed, 1 failed), and the fixture dropped from the expected set reddens it too (2 passed, 1 failed). no migration, and the forge binary changes, so this owes a forge deploy; the live forge suite is green against a throwaway 17.0 cluster with the CI env block and LOOT_FORGE_TEST_REQUIRE_DATABASE (476 passed over nine binaries, no skip note) and the workspace suite is green (3846 passed) (#2028)
3168156f · dbf3dbe6…diff - test scratch directories are named by one shared helper, common::scratch, from the process id and a per-process counter rather than the clock, so two tests asking for one tag at once are no longer handed one directory that the second caller empties and refills (the #2258 mechanism): 19 test files under crates/*/tests named a temp_dir path from SystemTime nanoseconds in 21 statements and now call fresh_dir or fresh_path, loot-cli files reaching it through mod common and loot-first exit_codes compiling the same std-only file by path, and revset_everywhere and plaintext_equality_census, which already counted, call it too. scratch_dirs.rs holds the #2258 pin, moved from revset_everywhere and aimed at the shared helper, red under the clock naming in 13 runs of 13 (0 passed and 1 failed, 1 to 16 of 400 directories handed twice), and a guard that walks every .rs file under crates/*/tests and refuses a temp_dir statement that reads the clock, red over the unconverted tree naming the 19 files (1 passed and 1 failed), red with buoy_exit put back (1 and 1) and red when the walk finds nothing (0 and 1), each restored green. no other test changes what it asserts. the workspace suite is green (4533 passed over 140 binaries, 13 ignored, from 4532 over 139: the guard is new and the pin moved into its own binary). test-only, so it owes no deploy (#2358)
6dd1e05b · 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.