Changes touching this path

  • a sparse view scopes what the working tree materializes, and nothing about what syncs (#39) fa6c6749 · dbf3dbe6…
  • an ingest records which paths it did not write, because that is the last moment absence and deletion are different facts, so a capture after --no-surface stops recording the content it just fetched as removed (#1227) cbf4a65f · dbf3dbe6…diff
  • three papercuts from the alpha sweep: a defaulted diff on a clean tree agrees with status instead of exiting 1, evolog's when column shows the authored clock instead of the git-bridge stamp while porcelain keeps the frozen one, and view stops claiming a deletion it never performs and counts what it left on disk 19473311 · dbf3dbe6…diff
  • loot view --prune removes the paths a narrowed view stopped covering and refuses whole, naming every one, when any of them holds an edit no change records, taking nothing out of history so a clear writes them all back de9f395a · dbf3dbe6…diff
  • the REPRESENTATION is extracted and the PREDICATE is not, because the overlap between a pathspec and a view is exactly the storage while the difference is exactly the RULE: a pathspec bare docs also keeps docs/adr/x.md, the git dash-dash affordance, and a view line has only the glob. that difference must STAY, and not because the two live in different places - a view line is STANDING MATERIALIZATION POLICY, so an implicit slash-star-star would silently WIDEN every one-word line already sitting in somebody .loot/view, and the widening would surface as FILES APPEARING ON DISK rather than as an error. the affordance is right where an operator types a spec and reads the answer in one breath and wrong for stored policy. the decisive evidence for the shape is that policy.rs ALREADY SOLVES THIS TWICE - IgnoreLine and Rule each pair a glob with its text as written in one struct - so Pathspec and View were the two OUTLIERS rather than a new abstraction being invented. desynchronisation is now impossible BY THE COMPILER rather than by a comment: the pair fields are private to policy, the list is private, and push is the only place a Pattern is built, taking ONE string and deriving both halves - proven by two mutations that FAIL TO COMPILE, E0616 reaching for the private list and E0451 constructing a mismatched pair. the prose invariant that said the two cannot disagree because new pushes them together - exactly the comment this ticket exists to remove - now points at the structure. one allocation per pattern per path leaves the match loop, a format in a loop that runs once per tree entry becomes a strip_prefix, and NO SPEEDUP IS CLAIMED ANYWHERE because nothing was measured: the machine was building throughout, which is the CPU condition that makes the harness load arm skip SILENTLY. six mutations with counts read, and the oracle was checked rather than assumed - which found TWO UNPINNED BEHAVIOURS the pre-existing suite was green under: that the prefix arm stops at a whole path COMPONENT, where every other negative case in the module missed by more than one character, and the rule difference itself, now one test that reddens if the two are unified in EITHER direction (#1552) fe21c932 · dbf3dbe6…diff
  • the two arms of a pathspec compare one spelling now, a .lootignore subtree line spelled with a backslash stops ignoring nothing, and the symptom the ticket reported is measured as unreachable through the CLI. delta::Pathspec::matches read its bare-directory prefix arm off the pattern text as typed while its glob arm read a normalized one, so at the library door --path docs\adr kept docs/adr and nothing beneath it; and Pathspec::new trimmed a trailing / off the raw argument, so docs\ was neither trimmed nor matched by either arm and kept nothing at all. both arms ask policy::unix_separators now, which is where the rule lives, and Pattern::normalized is borrowed off the compiled pattern of the glob rather than stored beside it, so the text a reader compares and the glob that matches it are one string rather than a third value to keep in step. the headline of the ticket is FALSE at the CLI, and that is the main finding: PATHSPEC declares --path a path flag with a Slot::Path tail, the argv door rebases every such token (#1330), and that rebase ends in treepath::store_key, so a pathspec reaching the matcher from a real process is /-separated already on Windows and on POSIX alike, and the one route that skips the rebase, no repo above the cwd, ends in the not-a-loot-repo refusal of the verb itself before any path is matched. measured through the spawned binary on this Windows machine over status, diff, the positional form and a run from a subdirectory: every spelling already selected identically. so no separator hint is added to refuse_unmatched, because a hint naming a cause that cannot be the cause is worse than none; what the refusal does name now is the pattern in the spelling it is compared in, since Pathspec::new normalizes before the trim it always applied. the reachable instance is the one the acceptance criteria sent me to look for: Ignore::parse_recorded read its trailing-slash subtree affordance off the line as typed, so build\ missed strip_suffix and compiled to the glob build/, which matches no path at all, and the line ignored NOTHING where build/ prunes - fail-OPEN, the files staying in the snapshot and sealing internal, the tier a relay reads by design. .loot/view is correct and is pinned rather than claimed: View::matches is a glob match and nothing else, so it has no second arm to disagree with. red first on the tree as it stood: the delta pin fails at the bare-directory arm (0 passed, 1 failed), and reproducing the reported symptom through a process takes the library and the door together - with treepath::store_key dropped from normalize_rel and Pathspec put back, status --path docs\adr refuses where the slash twin narrows, while either half alone leaves the process pin green, which is the measurement that says the CLI was never broken. mutations: normalized returning the text as typed reddens the Patterns pin (26 passed, 1 failed, left docs\adr right docs/adr); the trim taken off the normalized spelling reddens the trailing-separator arm (41 passed, 1 failed); the subtree affordance read off the raw line reddens the ignore pin (25 passed, 1 failed, left false right true at build/a.o); and a second spelling of the rule, in delta.rs or in policy.rs, reddens the locality census (1 failed each). that census asserts at most one spelling rather than exactly one, because rewriting the normalizer without that literal keeps every behaviour pin green (34 passed) and an exactly-once census would tax a refactor instead of guarding against a second home; a not-gone-blind guard sits beside it. CONTEXT.md carries both halves, the store_key spelling of the rebase as the reason the pathspec defect was inert and the .lootignore separator as the fail-open one that was not. no migration, and no forge or site byte moves, so this owes no deploy. the workspace suite is green (3852 passed over 119 binaries, 7 ignored) (#1859) 67f8adf1 · dbf3dbe6…diff
  • review sweep 17 fix-up: the separator-rule census checks what its name claims now and reads every caller of a pattern door, two more callers ask policy::unix_separators instead of answering the separator by hand, and the one class of path whose protection depends on that answer is pinned rather than lucky. clean::Sieve::keep spelled the replacement itself and compared the key against the recorded store keys and against an Ignore built from operator-typed -e values, the #1859 class in a third file at a verb that DELETES what it declines to protect; ferry::ingest_commit did the same for the .lootignore and .lootattributes it reads out of a git commit, a fourth home the ticket did not name and one that is inert because git hands over /-separated paths. both ask the normalizer now, whose body is the expression each replaced, so no path moves - measured through the spawned binary before and after on a scratch repo over ten invocations, -x, -X, the default, three backslash-spelled -e values with their slash twins, and a --force run with the tree it left, whose transcripts are byte-identical. what was NOT pinned is the half that matters: the protected set holds /-separated store keys while the walk hands keep a native rel, so only a recorded path with a separator in it can catch a key nobody normalized, and the clean fixture held none - sub/recorded-deep.txt is in it now, and let key = rel.to_string() reddens four cases over that file, the removal matrix among them, having taken a recorded path as a candidate (10 passed, 4 failed), where the whole file was green under that same mutation before. the census is renamed and derived on both halves rather than trusted: the files are every .rs under this crate src, production halves only, and the doors are read off policy.rs, a function there taking rel or path as a &str, so a new door joins by existing; an offence is the pair per function rather than the spelling alone, because a backslash pass on the way to a display line or a map key is the other axis and a spelling-only census would have to name its exceptions. mutations: the hand-spelling put back reddens it naming src/clean.rs fn keep, and put back in ferry naming src/ferry.rs fn ingest_commit (0 passed, 1 failed each); the door reader blinded reddens its anchors; the needle blinded reddens the fixture (left empty, right the one site); and the floor call dropped reddens source_walk own consumer census, whose derived count line this land repastes with the new consumer. #1859 AC4 is measured rather than argued, as #2028 did: from another module of the crate, Patterns and Pattern literals are E0451 on their fields and reaching for .list is E0616, throwaway probes, and the doc says privacy is what holds the pair and that a literal inside the module is not closed by it. a_recorded_inert_pattern_moves_no_paths_tier runs its claim over the paths its own rule list mints, with the inert line and without it, over the tier and over publish-ness, and the separator honoured reddens it naming a derived probe (27 passed, 4 failed); ADR 0038 and CONTEXT.md stop citing a three-path sample for no path changes tier and rest that on the parse. ADR 0038 and view.rs stop rating the .loot/view gap oppositely: closed on the tier axis, and the cost is materialization, which view.rs holds and the ADR now points at. conformance.rs stops resting its counted pair on a comment and points at ClassReads, where every other MetadataStore method is unreachable and the trait defaults none, so a third read in AccessClass::of panics there instead of undercounting here - measured, it does (0 passed, 1 failed). propose::visible_to and Viewer are pub(crate), with the field privacy named as what holds the pair and the in-module literal named as what it does not. seven string literals in cli_smoke.rs that carried a raw newline where the file spells the escape are fixed, five more than the ticket named, from a scan of the whole file. no migration, and no forge behaviour moves - a visibility narrowing, doc prose and one test fixture - so this owes no deploy. the live loot-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 (3859 passed over 120 binaries, 7 ignored) (#2033) 4720219d · 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.