Changes touching this path

  • workspace/reconcile: apply_plan executor owns the four arms (#663) 4ac0277a · dbf3dbe6…
  • loot adopt: the git-first catch-up fast-forwards content-identical work unsigned and names foreign paths (#705) 044c84ac · dbf3dbe6…diff
  • a change records when it was authored, so a projected commit stops reading '6 years ago' on GitHub (ADR 0043) loot changes carried no timestamp, so the git bridge fabricated one: BASE_EPOCH + generation, one second per ancestor depth from a 2020 epoch. All 526 commits sat inside seven minutes of September 2020. Earlier repairs (#626's floor, the missing-generation refusal) fixed ORDERING and never touched the absolute date, which is why this kept coming back. ADR 0028 inherited the no-timestamp constraint rather than choosing it. The real reason is upstream: a version id is blake3 over authored content, and a clock inside that hash gives two peers different ids for identical content, destroying the dedup and convergence of ADR 0001/0004. So authored_at rides the label seam ADR 0029 already cut for change_id -- covered by the finalize signature (no relay can restamp it) but never folded into the version id. The wasm golden vectors prove the separation held: FROZEN_VERSION_ID, FROZEN_OBJ_ADDR and FROZEN_SIGN are byte-identical, and only the version marker and one presence byte moved. Advisory, and never an ordering input: a self-reported clock is a claim, not evidence (ADR 0025). in_order/ids_topo, buoy and path_touch.ordinal are all untouched, the forge indexes nothing on it, and the projection floors it past every git parent so ancestry holds whoever's clock is wrong. Format v11: additive for readers (a v<=10 change decodes as None and an absent timestamp adds nothing to the signed message, so every existing signature still verifies), breaking for writers, so loot-cli and loot-forge go to 0.4.0 in lockstep. Forge migration 0004 stores it as bigint, not timestamptz -- signed data must round-trip bit-exact or pullers reject the change. Only new work gets real dates. Every commit on main predates v11, main is push-fast-forward-only, and backfilling would fabricate the very claim this replaces. Perf-Baseline: reset the change body grew one presence byte, plus eight where a timestamp is present, so bundle_bytes/store_bytes/wire_bytes step once at the v11 boundary eaa56d99 · dbf3dbe6…diff
  • a lane carries its own hold, and custody crosses back whole at finalize (#811) 941cafb9 · dbf3dbe6…diff
  • settling onto a tip is one dance that always clears the tree-hash, and the finalize binding has one home (#862) The settle dance - bring the tree to show a finalized tip, move the position, clear the tree-hash, persist - was hand-assembled at eight sites, and only four remembered the clear. The drift was benign solely through an unstated proof (every no-clear site leaves the Draft clean, so the snapshot fast path cannot fire); a future caller settling with a live draft would have broken silently. Two private Workspace coordinators now own it: settle_advance / settle_seed (Position's advance-vs-seed vocabulary stays visible at the call site) share one tail - clear tree-hash, persist - and a closed SettleTree enum carries the tree half: Materialize { from }, OnePath (resolve's #233 single-path write, which must never widen), or InPlace. Draft moves and signing stay with callers; finalize_working and restart_on remain composite coordinators wrapping draft-handling around a settle. The finalize signature (version-id, change-id, predecessors, authored_at - ADR 0029/0032/0043) was typed verbatim at four sites; a fifth that forgot authored_at would mint a valid-looking, unverifiable signature. sign_version(&Oid) is now the one binding, keyless gate inside, no persist (the carry loop signs N and persists once); public sign_change keeps its interface as sign_version + persist. Decision: #850 (map #849). fast_forward_to, converge_heads's survivor-adopt and resolve_conflict now clear the tree-hash they skipped; the extraction is the fix, no separate tickets. CONTEXT.md gains the Settle glossary entry. d4ed0644 · dbf3dbe6…diff
  • the adopt catch-up decides in the shared reconcile table, and keeps its own hands for the fold (#866) `adopt_harbor` is now the same three steps as the ferry reconcile: prologue (the two "cannot name the target" refusals, the #829 shared-graph ingest, the ADR 0047 hold refresh) then `adopt_view`, then `reconcile::decide`, then adopt's own executor. Ferry and adopt can no longer drift on WHAT to do. A sibling of `apply_plan`, not a mode flag on it: the same `Plan::Merge` means carry for the bridge (ADR 0039) and fold for adopt (ADR 0034), so that distinction stays a named seam rather than a runtime argument. Adopt's hands are `fast_forward_to` and `fold_line_in`, with `fold_line_in`'s internal short-circuits intact (`lane merge` is a live caller of them). The #418 seal-WIP override stays executor-side in both verbs as the typed `RepoError::SealWip`, deduped into one `seal_wip_gate` helper carrying the verb name. Routing it through `Plan::Refuse` would demote a matchable guard+override refusal to a stringly error, and it reads live state at the signing seam beside the mis-seal gate. The View is unchanged at six fields. Adopt becomes the first production caller that passes `covered: true` (its stale doc note is updated), and the first that captures BEFORE computing `covered`, which is legitimate because the table is order-indifferent: `covered` outranks every other field. The capture normalization stays verb-owned and is skipped once `covered` holds, so an already-current catch-up still leaves the operator's capture exactly where it was. One behavior change falls out of the routing: a catch-up with no local line at all (`pinned: None`) now takes the plan's Adopt arm and fast-forwards onto landed main, where it used to fall through to `fold_line_in` and refuse with "nothing to merge into yet, record a change first". Catching up is what the verb is for, and it is what `reconcile_onto` has always done in that state; `fast_forward_to` takes `Option<&Oid>` for the missing `from`. `loot adopt <version>` is untouched: taking a target wholesale makes no reconcile decision. Tests: the choices are the table's, so adopt's repo-materializing tests keep only what is still adopt's own, the prologue, the capture normalization, and each executor hand's effect. Added the second prologue refusal (a landed main the shared graph lost) and two executor smoke tests: the `pinned: None` adopt arm, and the no-op leaving a capture untouched. One duplicate drop-the-redundant-capture test folded into its twin. 46b3f587 · dbf3dbe6…diff
  • a ferry refusal reaches a machine consumer as itself, not as a generic error (#867) Every seam inside `ferry::run` returned `Result<_, String>`, so a pass — which is mostly other people's failures — flattened all of them before the CLI could emit them. A typed `RepoError` the engine had already coded, and the reconcile executor's `Plan::Refuse`, both reached a `--json` consumer as the generic `error` code. The prose was fine; the machine channel was the loss. The nine phase signatures now carry `CliError` end to end, which restores the engine's own slugs for free: engine calls propagate with a bare `?` instead of `.map_err(|e| e.to_string())`, which is precisely what was flattening them. Exactly three slugs join the frozen ADR 0023 contract (amendment recorded): `undescribed_parent` and `foreign_paths` from a new `reconcile::Refusal::code`, built alongside the unchanged wording by BOTH executors — `apply_plan` and #866's adopt catch-up — so two verbs sharing one table cannot become two taxonomies; and `git_mirror` where ferry lifts git2, deliberately coarse because the bit a consumer acts on is retry-the-environment versus obey. `git_mirror.rs` stays stringly inside: inventing a loot taxonomy for git2's errors would be fiction. `rollback_note` keeps the abort's code and grows only its message — a rollback is context about that failure, not a different one. Every refusal's wording is byte-identical; the human channel does not move. Ferry's own handful of refusals stay honestly generic, and so do the tier's remaining flatten sites, which graduate one at a time when a consumer needs them. The one loot-first line is the seam back out: its orchestrator keeps a String channel, so `From<CliError> for String` makes that a `?` rather than a hand-written `.to_string()` at every call. Found while pinning the codes: the uncaptured-WIP ferry test refuses with `foreign_paths`, not `undescribed_parent` as it reads. Both wordings offer `describe -m`, which is why prose was never a taxonomy. 4fc73479 · dbf3dbe6…diff
  • a store knows which machine materialized it: an arrived copy refuses to record until loot rehome, so a bootstrap cannot silently capture every sealed path as deleted (#986) 4c15a2ca · dbf3dbe6…diff
  • a verb that could only publish to main unreviewed is retired: lane merge goes, its fold machinery stays where adopt needs it, and the mirror-free fold that genuinely leaves with it is named rather than glossed (#1048) 3f7635a9 · dbf3dbe6…diff
  • a seal to a holder list that excludes its author refuses and names what nobody could ever open, --allow-lockout is the deliberate way through, and ADR 0038 records why the gate refuses rather than filing a key for the author (#1249) bbb858b0 · dbf3dbe6…diff
  • the consent slices become one Allowances struct a swap cannot compile against, the lockout gate calls the engine predicate it used to mirror, and the site gate steps destructure so a third step stops compiling (#1272) ac6e2096 · dbf3dbe6…diff
  • a signing seam reads the working tree once and walks it once, so describe and land stop buying two whole-tree byte reads to look at file names, and loot-perf grows the capture timing that can see it (#1383) 31995cb5 · dbf3dbe6…diff
  • the implicit capture in front of every bare mutating verb reads the working tree once, so the tree it judges clean is the tree it records, and the doors already committed to capturing ask their refusals before paying for a read (#1395) 7f1fb453 · dbf3dbe6…diff
  • reconcile_onto stops open-coding load_shared_lineage's two halves, because the ingest and the ADR 0047 hold refresh it hand-rebuilds are exactly that seam with nothing between them, which is the drift #1447 removed from the test fixture that claimed to reproduce this very step (#1456) d4ada2ee · 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 merge stops settling a tip whose tree the caller still owes on the next line, because the two sites that open-coded finalize plus materialize_tree now settle through SettleTree::Materialize, and converge's hand-written persist() is the settle tail its own write was spelled out beside, with the one of the three that no test in the crate ever entered now pinned (#1468) 15e33421 · dbf3dbe6…diff
  • the catch-up stops leaving its own consequence to a runbook the reader may never have loaded: adopt now prints the git step IT JUST CREATED, and only when it actually moved the tree and the checkout is measurably behind - naming the paths it wrote, which is exactly the set needing the proof. the ancestry is judged on the LOOT GRAPH through the mark map rather than by asking git, because git cannot answer it: the checkout has not fetched the landed commit. there are two arms by position, since which git command is correct depends on where HEAD is, and neither arm ever recommends git before a catch-up, because git-first WEDGES the primary and loot-side-first is and stays the order. and the land closing note is narrowed so its final word about the primary cannot read as being about the checkout: it now says which thing the fast-forward moves, says HEAD does not move with the dock, and names the verb that says the rest. the finding that changed the procedure is bigger than the ticket: the skill had the FETCH AFTER THE PROOFS, and a land pushes main FROM THE MIRROR, while the only fetches a land runs in the checkout are its pre-land drift and ADR guards - so at the exact moment an operator needs this procedure their origin/main is stale by that very land, every landed path reads as differing, and the freshly landed perf point does not resolve at all. followed literally the skill produced the precise wrong conclusion it exists to prevent, so the fetch is hoisted with the reason recorded, and the printed block fetches first by construction. twelve mutations with counts read, of which two are worth the reading. the tenth is a CONTROL: the skill quote wraps across two indented lines, so with the whitespace flattening removed the citation pin reddens over LAYOUT rather than over words, which is what makes the flattening load-bearing rather than decorative. and the fifth is the one to learn from - the lane guard test PASSED WITH THE GUARD DELETED, because the lane was silent for an unrelated reason, landed main having been recorded on the primary so the lane lineage-filtered graph had never seen it and the ancestry answered false. a pass that survives deleting the thing under test is not a pass, so the arrangement was rebuilt with landed main recorded THROUGH the lane and two explicit preconditions proving the lane reaches the checkout and can answer the ancestry at all - after which the same mutation reddens. what is NOT done is said rather than implied: a bare ferry still says nothing about git, its catch-up being a different path, so the note claims only the dock for it; the block deliberately stays silent on a repeat adopt, because its claim is that THIS run wrote over your tree and a no-op cannot make that claim; and none of this was reproduced live (#1679) c8ebe232 · dbf3dbe6…diff
  • the condition that could not be false is gone, and so is the pair that made it possible: merged stops being a FIELD set by hand at three construction sites and becomes a DERIVED method over the one bit that decides it, so the two cannot disagree - unrepresentable rather than guarded. eighteen reads follow it, and eight of those were conjunctions that are now TAUTOLOGIES, reduced to one term rather than left standing to read as two conditions. the test was rebuilt by moving a DIFFERENT AXIS, because a second catch-up can never reach the block at all: the fixture now puts a real second commit on the checkout main, so the DOCK is still behind and the catch-up genuinely runs, writes the tree and reaches the block, while the CHECKOUT is level and the block declines - and deleting the predicate reddens two tests. the DISCRIMINATION is the part worth reading: under that same mutation the OLD test stays GREEN, which is precisely the defect this ticket describes, demonstrated rather than asserted. the printed recipe stops handing the operator a command that ERRORS. the tree delta now returns what was WRITTEN and what was REMOVED apart, and a removal gets a tree read for its proof, because there is no file to hash, and a checkout for its repair - placed BEFORE the merge, since restoring the file is what lets the merge run at all. the plumbing needed a pin of its own, and that is proved rather than assumed: folding removals back into the written set reddens the workspace pin while the rendering pin stays GREEN. the off-main arm gains its PROOF and withholds only its REMEDY, and says that it withholds it and why, because the byte comparison does not turn on where HEAD is while the repair does - with that limit stated in the same list the module other limits live in, rather than left for a reader to discover. the section this run added about careful sentences gets its own grammar fixed, a stray fragment from an earlier draft removed and a clause given its missing object - and NO count added, with a number that was being carried forward replaced by the property, consecutive sweeps each turning one up. the only-shorthand claim is narrowed at all three sites to the width of the check that backs it, which is a claim about ONE declaration and nothing wider. and the tenth copy of the short-hash helper becomes one, with the unguarded universal above it replaced by what it actually is and an explicit note of what it does not cover (#1911) 53ede622 · dbf3dbe6…diff
  • a land takes into main the ticket changes on the forge that landed main lacks (ADR 0098 §4, the sync half of §5, the #2390 half of §6, and §9): under the harbor after its finalize it asks its remote, when that answers as a forge, for its heads, takes in what they reach, and judges each change they reach that landed main does not; one signed by a key in the own key set of this identity and writing only under tickets/ is folded onto landed main ahead of the ferry reconcile, so the lane is carried onto it, the re-gate sees the tree as it lands and git main takes the lane commit alone, and any other fails the land closed naming the change and its paths outside tickets/. a sync push the forge refuses because a web write arrived during the land now merges that write onto landed main under the subject fold N ticket changes from the forge, with no gate and no git commit, catches the primary up and pushes again, a bounded number of times; the #2390 check accepts a primary ahead of landed main only by ticket-only changes the forge holds; a ticket file both the lane and the forge wrote bounces for loot resolve, or refuses before the pass naming loot pull-grants in the primary when the lane cannot open both sides, and a pass whose carry stops short of the fold projects nothing; a fold merge refuses a file landed main and the forge both wrote. the verdict gains folded=N before pusher=. ADR 0098, the ADR 0063 amendment, CONTEXT.md, workflow.md, the land-change skill, GATES and SOURCE_ROOTS say so, and the pin no_gate_input_reads_the_ticket_root covers the walk of the text gates only. six tests against an in-process forge, whose sync runs in-process, pin it beside four sync unit tests and four forge_fold tests; red under seventeen named mutations, each restored, over twelve loot-first pins and four loot-cli pins: no fold at the land (10 passed and 2 failed), the judgment ignoring paths (9 and 3, and 3 and 1 in loot-cli), an unsigned change read as own (3 and 1 in loot-cli), writes read against any parent (2 and 2 in loot-cli), no race fold (10 and 2), no adopt before a retried push (10 and 2), the #2390 allowance off the forge or without the judgment (11 and 1 each), a pass short of the fold projecting (11 and 1), no check for collisions the lane cannot open (11 and 1), a fold merge picking a side (3 and 1 in loot-cli), the race count dropped (11 and 1), the text walk reaching tickets (11 and 1), the token not the count (10 and 2), the race judging nothing (11 and 1), no attempt bound (11 and 1), and an ancestor head not skipped (3 and 1 in loot-cli). cargo test green, 4671 passed over 143 binaries with 13 ignored. client only, no deploy; loot-first changes, so the primary release binaries owe a rebuild (#2429) 357a8716 · dbf3dbe6…diff
  • review sweep 2 fix-up over #2429 (map #2422): each fold of the forge heads, at the land and at the race fold of its sync, now refuses naming the paths when the tree it reaches differs from landed main outside tickets/, and retires the merges it minted, where the per-change judgment read a merge of landed main with an ancestor of it that keeps the ancestor copy of a code file as writing nothing and folded that revert onto main, past every gate at the race fold. the race fold runs its pass with ferry::RunOpts::no_commit, which refuses a projection that would make a git commit before any ref names it, where a comparison of the mirror main after the pass left an ungated commit there for the next land to publish; a signed change that writes nothing, racing the land, was such a case. folded= is the count when the land read the forge heads, no-forge when the default remote is not a forge, and UNREAD with a FORGE NOT READ block naming why when it read none, where 0 said all three. a refused intake, a failed pass and a race fold that folds nothing drop the forge heads they read into the landing position, which kept them as heads of its own. collisions reads its base through GraphView::common_ancestor_tree, the base merge_tips merges from. the land-change skill says a ticket collision bounces for loot resolve and refuses only when the lane cannot open both sides; GATES and the ADR 0063 amendment state the gate-input property rather than kinds of gate; ADR 0098, workflow.md and CONTEXT.md, which now defines forge-only change and race fold, say what changed. pinned against an in-process forge, with the merges recorded through loot-core since no verb mints one, beside a ferry unit test; red under eleven named mutations, each restored: no property check (0 passed and 2 failed), the race fold without no_commit (0 and 1), the ferry guard off (4 and 1 in loot-cli, 0 and 1), an unreachable forge read as 0 (0 and 1), the token spelled 0 (0 and 1 over each of two pins), no block (0 and 1 over each of two pins), the intake keeping what it read (0 and 1), a failed pass keeping it (0 and 1), the fold keeping its merges (0 and 1), the race fold keeping what it read (0 and 1), and a race fold that took changes in not answering an unread intake (0 and 1). cargo test green, 4683 passed over 142 binaries with 13 ignored, three of them after a re-run: two timing flakes in loot-identity and loot-relay-contract that pass alone, and the Workspace width census, whose derived count this change moved to 406. client only, no deploy; loot-first changes, so the primary release binaries owe a rebuild (#2470) c9c46384 · dbf3dbe6…diff
  • a web ticket write no longer fails the land in a repo holding a Restricted path outside tickets/, and a fold keeps the holders main records (map #2422): the wire redacts a Restricted path holder list (#521), so the browser change carries each such path as Restricted([]), and forge_fold compared entries with ==, so the operator first web ticket read as writing docs/pitch/zk-host.md and every land after it would fail closed. what a change writes, what two lines collide on and what a forge head changes outside tickets/ now compare address and seal (forge_fold::same_entry over Visibility::same_seal, #1005). a fold no longer takes such a change as it is: its merge records fold_tree, the side that wrote each path since the fork and main own entry elsewhere, read off addresses and opening nothing, which replaces merge_tips in mint_fold_merge, a descendant is taken as it is only when that is the tree it holds, and fold_onto refuses a tip that does not record the main entry outside tickets/, address and seal alike. read against the live forge, the judgment takes the operator change (1 forge-only change, 0 refused, the overlay reads 1 and keeps out 0) and the fold merges it with 0 paths outside tickets/ recorded otherwise. item 4 found no defect in the web read: a native run of the browser read over the live head with the mailbox keys lists the ticket open with nothing unopened, and nothing was changed for it. pinned by a judgment and fold test and a fold_tree test in forge_fold, a forge_view test where a browser-filed ticket over a held path reads in the browser and in a lane, and two loot-first land tests that build the ticket with the browser builder over a base holding a Restricted path, one taken in at the intake and one racing the sync, each asserting main keeps the holders. red under named mutations, each restored: entries compared with == (21 passed and 3 failed over forge_fold and forge_view, 0 and 2 over the land tests), a descendant always taken as it is (22 and 1, 1 and 1), that and the fold check relaxed to same_seal (22 and 1, 1 and 1), and fold_tree taking the web entry where main did not write (21 and 2, 0 and 2). cargo test green, 4744 passed over 145 binaries with 13 ignored. no site change and no deploy owed; this land runs with the lane-built loot-first and loot (#2488) d27f227f · 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.