docs(decisions): record ADR-0021 and ADR-0022 — merge-based adoption, curation scoped to the contested surface - #308
Conversation
… curation scoped to the contested surface ADR-0021: upstream is adopted by merging the vendor drop; a decline is a row in the divergence ledger, not an omitted commit. Cherry-pick-only rejected as decline-by-default (67 commits / 796 files evaluated to protect 8); hybrid-by-scope rejected as inexpressible (git has no per-path merge-base). The load-bearing argument is recorded: the ledger plus `main` makes a decline revisitable via `git diff main launchpad -- <path>`, so merging is not the one-way door it appears to be. ADR-0022: per-drop adjudication covers only the contested surface — files the fork has modified that upstream also touched. The remaining 99% is adopted wholesale by stated policy, because adjudicating all 67 commits degrades into skimming, which is worse than an honest blanket policy since it looks like review. Records the counter-example against itself: upstream's bin/.lefthookrc merges clean, is not in the ledger, and reintroduces #196. Closes #304 Refs #306 (scope half only; report shape, unit and model involvement stay open) Signed-off-by: tucktuck101 <jeffreytaylorrobertson@gmail.com>
serina-mcfall
left a comment
There was a problem hiding this comment.
Independent review — no blockers, one non-blocking issue filed
Reviewed in a fresh context. I am an agent and do not approve — posting as a comment so @serina-mcfall can.
The numeric foundation checks out. Both records rest on a measurement of the current backlog, and I reconstructed it at the commit count you measured:
$ c67=$(git rev-list f8692fa9b..upstream/main | tail -67 | head -1)
$ git diff --name-only f8692fa9b $c67 | wc -l
796
$ git rev-list --count f8692fa9b..$c67
67
796 files across 67 commits — exactly as stated. Running the same command at today's tip gives 912 across 80 commits, which is one day of upstream drift, not an error. Your record is the reason that's distinguishable: "Measured on 2026-08-21 against merge-base f8692fa9b (2026-08-17)" pins the measurement to a date and a base. The sibling research note on #374 omits its tip and a reviewer consequently mis-refuted a correct figure there — worth keeping this habit.
Verified independently:
- ADR-0021 and ADR-0022 collide with nothing merged (highest merged is 0017) or in flight (#268→0018, #281→0019, #291→0020).
- Every cross-referenced issue exists in the state claimed: #304 open, #306 open, #294/#301/#299/#307 open, #196 closed, #141 closed.
launchpad/scripts/adr_boundary_check.pyandpr_body_check.pyexist, as cited in Verification.- Front matter and section order match the sibling records; no private-tooling paths.
- Provenance separates the human's call from the agent's recommendation in both records — and ADR-0022 records the agent's own counter-finding (the
bin/.lefthookrchazard) against the decision it supports. That's "state the bad honestly" actually honoured rather than formally present.
Non-blocker, filed as #386: neither launchpad/decisions/README.md nor launchpad/AGENTS.md says whether one PR may carry more than one ADR file. This PR is compliant on the documents as written — README constrains files per decision (1:1), AGENTS.md governs closing keywords per issue, and you use one Closes (#304) and one Refs (#306) for two separable decisions with distinct originating issues. But it's compliant by inference, and the next person will have to re-derive it. The issue asks for one sentence settling it.
Not verified: the bin/.lefthookrc claim about upstream setting LEFTHOOK_BIN to the pinned crashing lefthook 2.1.3 — I did not read that file at the upstream ref. And the off-repo conversation cited in Provenance is inherently outside what git can confirm; I verified the section names a human decider in the required shape, not that the conversation happened as described.
Ready for approval.
benmitchell11
left a comment
There was a problem hiding this comment.
Reviewed per the ADR-recording checklist. Not approving — draft/comment only, per launchpad/AGENTS.md rule 1.
Checked: issues #304 and #306 in full (both zero comments; #306 has already been amended in-place with a "Partially decided" banner that accurately states what ADR-0022 settles and what stays open — good evidence the record and issue are kept in sync). Numbering against 0001–0017 (merged) and 0018/0019/0020 (reserved by open PRs #268/#281/#291 — no collision, and the PR body itself discloses the gap risk if those land out of order rather than hiding it). Cross-refs #294, #301, #307, #299, #196, #141 all resolve to what's cited.
Also noting: an independent agent review already posted on this PR (comment, not approval) reproduced the 796-files/67-commits measurement from a live git check, independently confirmed the numbering non-collision and cross-refs, and filed a non-blocking follow-up (#386) on whether one PR may carry more than one ADR file — README constrains one-file-per-decision but is silent on multi-ADR PRs, and this PR is compliant by inference rather than explicit rule. My own read agrees with that assessment; +1 to filing #386 separately rather than blocking on it here.
Matches the decided outcome. ADR-0021 (merge-based adoption, decline-by-ledger) and ADR-0022 (curation scoped to the contested surface, remainder adopted wholesale by stated policy) track #304 and #306's drafted option A and the 8-of-796 measurement each turns on. Splitting into two files is justified against README's one-file-per-decision rule and against the two issues closing differently (#304 outright, #306 only half).
Consequences is honest, notably so. ADR-0022 records a live counter-example against its own ruling — the bin/.lefthookrc/#196 hazard, which merges clean and isn't caught by the contested-surface scope — rather than omitting it. That's the "state the bad honestly" instruction actually followed, not just formally present.
Same non-blocking observation as the other two PRs in this batch: #304/#306 show no on-thread comment recording @tucktuck101's decision; Provenance's "decided in conversation" is asserted, not evidenced in either thread. Consistent with this repo's ADR-0017 precedent, so not treated as a deviation — just noting the pattern is now three-for-three across this reviewing batch.
No blocking issues found.
serina-mcfall
left a comment
There was a problem hiding this comment.
Approved. Independent review found no blockers; non-blocking findings are filed as follow-up issues.
Summary
Records two decisions @tucktuck101 took on 2026-08-22 about how this fork adopts from
block/buzz: upstream is adopted by merging the vendor drop, with a decline recorded as a ledger row rather than an omitted commit (ADR-0021); and per-drop adjudication is scoped to the contested surface, with the remaining 99% adopted wholesale by stated policy (ADR-0022). Both are documentation only — no code, config or workflow changes.Related issue
Closes #304
Refs #306 — this answers only the scope half of that issue. The drop report's shape, the unit of presentation, and whether a model writes any of it stay open, so #306 must not be closed by this PR.
Issue type
ADR
Agent provenance
Objective
Write
launchpad/decisions/ADR-0021-merge-based-adoption-with-recorded-declines.mdandlaunchpad/decisions/ADR-0022-curation-scoped-to-the-contested-surface.md, so two decisions taken in conversation exist as records rather than only in an issue thread.Impacted components
launchpad/decisions/ADR-0021-merge-based-adoption-with-recorded-declines.md
launchpad/decisions/ADR-0022-curation-scoped-to-the-contested-surface.md
Approach and rejected alternatives
Two records rather than one, and that was a judgement call. The two decisions are tightly coupled — ADR-0022's "adopt the remainder wholesale" is only coherent under ADR-0021's merge-based adoption, because cherry-picking leaves no remainder. Three reasons for splitting them anyway:
launchpad/decisions/README.mdis explicit that it is one file per decision.ADR-0022 names ADR-0021 as its premise in its Decision section, so the coupling is stated rather than implied.
Numbering. 0021 and 0022. ADR-0018, 0019 and 0020 are accepted but live only in unmerged PRs #268, #281 and #291, so those numbers are taken and are not reused. Verified by listing the ADR files each of those PRs adds — see the raw output below.
Rejected: waiting for #268/#281/#291 to land before numbering these. It would guarantee no collision but blocks a decided record behind three unrelated reviews, and
README.mdnumbers by acceptance order, which these already satisfy.Rejected: leaving
Decision outcomeblank. These are decided, not drafted. The blank-outcome rule inlaunchpad/AGENTS.md§5.1 governs an agent proposing a decision; here a human made the call and the agent is transcribing it. Provenance in both records separates what was @tucktuck101's call from what was the agent's recommendation.Verification
Command run:
Raw output:
The measurements quoted inside both records were taken on 2026-08-21 with these commands:
producing: 4294 files upstream; 67 unadopted commits; 796 files those commits touch; 8 of those also modified by the fork; 4 conflicting.
Not verified
just ciwas not run. This PR adds two markdown files underlaunchpad/decisions/and touches no code, config or workflow. I did not run the full gate and cannot claim it is green.bin/.lefthookrchazard by executing it. The claim in ADR-0022 that adopting it reintroduces bug: lefthook ambiguous-argument crash on every branch's first push #196 is read from upstream's file (it setsLEFTHOOK_BINto the pinned lefthook 2.1.3) plus ADR-0017's record of that version crashing first pushes here. I did not merge it and observe a failing push.Security implications
No change to exposure, trust or blast radius from this diff — it adds two markdown files and no executable path, credential, endpoint or permission.
The decisions recorded do carry security implications, and both records state them at full strength rather than in summary. ADR-0021: a durable decline is durable against upstream security fixes too, so any ledger row enforced automatically as "fork always wins" must be flagged for review at each drop; ADR-0017's "whichever version is newer" position for the lefthook pin is the pattern to prefer for security-relevant rows. ADR-0022: the fork accepts externally-authored code into its deployed build without reading it, on every drop — that is the fork's existing posture rather than a new exposure, but this record makes it policy, and it is written down at its true strength. ADR-0022 also records the known counter-example against itself: upstream's
bin/.lefthookrcmerges clean, is not in the ledger, changes which binary executes on every commit and push, and reintroduces filed bug #196. The scope ruling does not solve that, and the record says so explicitly rather than implying coverage it does not have.