Changes touching this path
- the land gate gets the predicate it was specified without, and proposal-derived turns out to be the wrong concept: ADR 0075's #2162 amendment said the local land enforces attestations for a proposal-derived change and never defined it, which could not be built at all because loot-first reads no loot change author anywhere and the only author it sees is the GitHub PR login, the very field that amendment had to correct. ADR 0092 replaces the concept rather than implementing it, firing on a change whose author is not in the lander's own key set, the active signing key plus the rotation archive, because what a gate should care about is code the lander did not write and the route it arrived by is incidental, which also catches a colleague's change carried in with no proposal at all, the case ADR 0075 calls a feature. two predicates stay separate on purpose and each names its own question: carry_line asks may I re-author this and must compare the current key since a rotated key cannot sign, while the gate asks did I write this and spans every key the identity has used since a rotation does not make earlier work somebody else's, so a rotated operator's own change is Foreign to the carry and theirs to the gate, and the natural repair of unifying them breaks one caller in either direction. that same Foreign arm is what makes a verdict usable at a land at all, since an attestation binds a version and a foreign suffix is merged rather than replayed, so version ids survive where a replay would have detached every pass in silence and read as not yet verified. the judged set is the ancestor closure of the lane tip minus what main covers rather than carry_line first-parent chain, because a stack containing a merge of its own would otherwise smuggle unapproved work in on a second parent and report green. an absent author counts as foreign and that was already shipped. gating is the repo policy, declared per requirement in the LANDED .lootpipeline and defaulting to advisory, which is what makes the #2162 rule about reading the landed copy load-bearing rather than prudent, while detection is always on and the verdict line states foreign authorship so that advisory never becomes invisible. the predicate itself is not configurable, authorship being a fact rather than a preference. ADR 0091 section 6 is corrected in passing: its sentence that a change step judges the merged tree at a land is an intention, loot-first naming .lootpipeline nowhere and a land running the Land gate phase off the untracked .loot/gates instead. CONTEXT.md gains Foreign authorship, and #2178 is re-specified and shrinks. docs only: no code, no migration, no wire or format byte moves, so this owes no deploy (#2216)
3c7ce4b1 · dbf3dbe6… - every land now states which versions it published that the lander did not write, and refuses nothing - ADR 0092's detection half, part 1 of 2 of this ticket. a version is foreign when its author is not in the lander's own key set, which is new: loot_identity::own_signing_keys reads the active id.pub plus every id.pub.rotated archive that loot id rotate writes, exposed as Workspace::own_signing_keys beside author_pubkey rather than instead of it, because the two answer different questions. carry_line's Foreign asks may I RE-AUTHOR this and only the current key can sign, while the gate asks did I WRITE this and authorship is historical, so a rotated operator's own change is foreign to the carry and theirs to the gate and both are right - each site now names its own question and points at the other, since unifying them breaks a caller in either direction. the judged set is the ancestor closure of the landed change minus the closure of the main it was judged against, read BEFORE the pass because by verdict time main already includes the landed change and the difference would be empty on every land, and it is the whole closure rather than carry_line's first-parent chain because a stack carrying a merge of its own would otherwise have one side waved through. an absent author is foreign, which is carry_line's answer too, so the two predicates disagree only about which keys are mine. the count rides the verdict line as foreign= and a block names the versions, since the count says that and the next question is which. foreign= sits immediately BEFORE pusher= and not after it, which I got wrong first: pusher= carries an arbitrary percent-encoded path and is designed as the tail, workflow.md says the path comes last, and five pusher tests read it with ends_with - appending after it broke exactly those, while inserting before it breaks only a fixed-index reader and the repo has none, and those five pass unmodified. the key set reads only id.pub.rotated and never the private id.rotated spelling, which holds a secret key and has no business answering a question about authorship. a machine that pulled rather than rotated holds no archive, so there your own pre-rotation work reads as foreign, which fails toward asking for an approval nobody owed and never toward waiving one, and the block and workflow.md both say so. red under mutation, counts read each time: the key set ignoring the archive (52 passed and 1 failed), the filter admitting the private archive spelling (52 passed and 1 failed), and an unauthored change read as the lander's own (202 passed and 1 failed), each restored to 53, 53 and 203. ADR 0092's status now says which sections are built, because section 5 - the gating column, review/approve and the refusals - is part 2 and until it lands detection reports and nothing refuses, which is that section's decided default anyway. no migration, no wire or format byte moves, and nothing on a host moves, so this owes no deploy. the workspace suite is green (4189 passed over 133 binaries) (#2178)
8cb77a56 · dbf3dbe6…diff - a land that publishes work you did not write now refuses when the repo asks it to, ADR 0092's gating half and part 2 of 2 of this ticket: a require line in the .lootpipeline on main names a step whose pass or the approval every foreign tip must carry, and with no such line the land stays advisory as decided. the syntax is a directive rather than the column section 5 named, the operator's choice, because a step line's command swallows the rest of the line so a column would have re-laid every step line in a grammar map #2099 owns - a require line has two words, every two-word line was already refused as a malformed step, so it changes the meaning of no line that parsed before, and it can express the approval, which was never a step. only the owner's own keys satisfy require approval, as review/approve: a trusted runner's passes count and its approval does not, or the machine that ran the tests could also sign the second pair of eyes. a require line that names no step, names a step not on change, or repeats refuses the land rather than reading as nothing required, because a typo there is a gate the owner meant to declare. the requirement is read at the judged main and never from the stack being landed, a sealed or burned landed file refuses, the check runs before the break-glass branch so --skip-tests cannot reach it, and own work returns before reading the file at all. only the foreign tips must carry the roles, since a pass on a version certifies the tree at that version, and a role signed by a key this machine does not trust gets its own refusal and repair because re-running would change nothing. not proved end to end: no test drives a real land with a second identity and a projected main, so the decision logic is pinned as pure functions and which copy is read and where the check sits are pinned by censuses on the source. red under mutation, counts read each time: the approval accepting any trusted key (34 passed and 1 failed), untrusted read as missing (33 passed and 2 failed), the landed-copy census fed the working tree (0 passed and 1 failed), the check moved after the break-glass (0 passed and 1 failed), and a require naming no step dropped silently (21 passed and 1 failed), each restored to 35, 35, 1, 1 and 22. ADR 0092 records the directive and what building it found, and workflow.md says how to turn gating on. no migration, no wire or format byte moves and no host behaviour moves, so this owes no deploy, though the primary's release binaries must be rebuilt before a land enforces it. the workspace suite is green (4208 passed over 134 binaries, 9 ignored) (#2178)
946e7f14 · dbf3dbe6…diff - the require gate of the land is proved through a real land: three orchestrator tests run loot-first land under --skip-tests over a mirror main a plain ferry projected and a change signed under a second keyring, applied by bundle and merged in by the lander so it rides the second parent of the merge, with the fake forge standing in for GitHub. an unapproved land refuses naming that version and its loot attest, moves no main and pushes nothing, and lands once the owner attests it through that verb; a require line only on the stack copy of .lootpipeline gates nothing, and a stack that deletes the file main requires from is still gated. red with each piece undone, counts read each time over the five require pins, each restored green: the requirement read at the stack tip (2 passed and 3 failed, the read-from-main census among them), the check wrapped in a skip-tests condition (3 and 2, both censuses green), the owner attestations not consulted (4 and 1), the judged main taken from the lane anchor (3 and 2), the first-parent chain in place of the closure (3 and 2). the ADR 0092 amendment says the gap is closed and by what, and the break-glass census says what it cannot see. no format constant, codec byte or migration moves. the workspace suite is green (4445 passed over 138 binaries, 13 ignored) (#2317)
72d33080 · dbf3dbe6…diff - review sweep 12 over the lane projection guard: items 1 and 2 did not reproduce through the binaries in a scratch repo with its own lanes, since a position graph is its own lineage-filtered load (ADR 0022), so after a lane signed K a primary plain ferry projected nothing and minted no mark for K and the lane ferry still refused, and a lane with nothing of its own caught up while a sibling seal sat unmarked; the guard question stands and both scenarios are pinned. a lane ferry --seal-wip over described work refuses before the reconcile, where it sealed into the catch-up and then refused, leaving a sealed line no PR carries (reproduced on the landed binary). the reap never says landed, since the push that follows a land pass can still be refused, and says projected for a marked version, which a mark is and on main is not. the ferry verb landing false is pinned through the spawned binary. a refused pass carries its notes. the primary recovery recipe names --allow-primary for the verbs that need it there. the #2314 and #2366 lane refusals print one route rule, lane_landing_route, which sends a lane to its PR land only when the PR carries the tip with nothing captured on top. ADR 0039 amendment, ADR 0092 (--skip-gates), CONTEXT.md and concurrent.md corrected. red with each piece undone, counts read each time, each restored green: the verb flag flipped (0 passed and 1 failed), the seal-wip refusal dropped (75 and 1), the reap saying landed (73 and 3), the route ignoring captured work (75 and 1), the route ignoring the PR (75 and 1), notes dropped (75 and 1), the lane recipe on the primary (75 and 1), the guard off (71 and 5), every lane pass refused (73 and 3). the scripts MAINTAIN ask is its own scripts commit. no format constant, codec byte or migration moves. the workspace suite is green (4450 passed over 140 binaries, 13 ignored) (#2370)
18ea6db5 · 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.