You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
What mechanisms could enforce "a change to an upstream-owned file requires a ledger row", and what does each cost a contributor?
#301 asks whether the divergence register is machine-checked and what that costs. It weighs one implementation — extending launchpad-pr-check.yml — against the cost of a contributor fixing a typo in an upstream-owned file and getting a red check. The mechanism set was never enumerated, and at least one candidate is materially different in cost and has not been named anywhere in the thread:
CODEOWNERS on upstream-owned paths. This does not check for a ledger row; it routes the review to whoever owns the boundary. Different assurance, much lower contributor friction, no script to maintain, and it composes with branch protection rather than with CI. Whether it can express "everything except launchpad/" is the open question — CODEOWNERS pattern semantics are last-match-wins and its negation support is limited.
A CI check on the PR diff, the assumed option — the cost being that it fires on every legitimate upstream-file edit, not only on new divergence.
A pre-push or pre-commit hook via the existing lefthook.yml, which fails earlier and locally but is bypassable and is itself one of the contested files.
A post-merge assertion rather than a pre-merge gate: notice that an unregistered divergence exists and report it, instead of blocking the PR that created it. Weaker, but it never blocks anyone and it catches divergence that arrives by a path no gate covers.
Measured 2026-08-22: no CODEOWNERS file governs the boundary and no check enforces it.
Objective
A recorded enumeration of enforcement mechanisms for the upstream-file boundary, each with what it assures, what it costs a contributor, and whether it can express the launchpad/-excluded path set.
Under ADR-0022 a contested file with no ledger row is never presented for adjudication at all — it falls into the 99% adopted wholesale. That makes ledger completeness a correctness property, not a documentation nicety, and it makes the enforcement mechanism load-bearing rather than optional. #301 cannot weigh cost against assurance while the cheapest candidate is missing from its options. It also depends on the required-checks gap filed alongside this one: a pre-merge gate that cannot be made required is a suggestion, and that reorders the candidates.
Definition of done
Each candidate is described by what it assures and what it costs, including the failure mode of each.
Whether CODEOWNERS can express "all upstream-owned paths, excluding launchpad/ and .github/workflows/launchpad-*" is established by testing a pattern set, not by reading about it.
For each pre-merge candidate it is stated whether it can actually block, given no status check is currently required on launchpad.
The false-positive rate of the CI-check option is estimated against real history — how many merged PRs touched an upstream-owned file without creating new divergence.
#301 chooses between a bespoke check and nothing, having never considered the mechanism that is a two-line file. The likely outcome is the check — contributors hit it on unrelated edits, it acquires exceptions, and the exceptions are where lost ledger rows come from. Which is the failure the check existed to prevent, arriving through the check itself.
Impacted components
.github/workflows/launchpad-pr-check.yml
.github/CODEOWNERS (does not exist)
lefthook.yml
launchpad/upstream-sync/DIVERGENCE-REGISTER.md (does not exist yet)
Unblocks the options half of #301. Depends on the required-checks gap filed alongside.
Implementing any mechanism or committing a CODEOWNERS file.
Writing the ledger.
Filed by an AI agent (Claude Opus 5) on behalf of @tucktuck101 on 2026-08-22, as part of a knowledge-gap sweep over #273. This issue asks a question. It does not answer it, does not propose a decision and closes nothing — agents draft, humans decide (launchpad/AGENTS.md §5.1). Three headings beyond 02-task.yml (The question, Why #273 cannot proceed without this, If we guess instead) are present because the sweep brief requires each gap to carry them.
Parent PRD
#273
The question
What mechanisms could enforce "a change to an upstream-owned file requires a ledger row", and what does each cost a contributor?
#301 asks whether the divergence register is machine-checked and what that costs. It weighs one implementation — extending
launchpad-pr-check.yml— against the cost of a contributor fixing a typo in an upstream-owned file and getting a red check. The mechanism set was never enumerated, and at least one candidate is materially different in cost and has not been named anywhere in the thread:CODEOWNERSon upstream-owned paths. This does not check for a ledger row; it routes the review to whoever owns the boundary. Different assurance, much lower contributor friction, no script to maintain, and it composes with branch protection rather than with CI. Whether it can express "everything exceptlaunchpad/" is the open question —CODEOWNERSpattern semantics are last-match-wins and its negation support is limited.lefthook.yml, which fails earlier and locally but is bypassable and is itself one of the contested files.Measured 2026-08-22: no
CODEOWNERSfile governs the boundary and no check enforces it.Objective
A recorded enumeration of enforcement mechanisms for the upstream-file boundary, each with what it assures, what it costs a contributor, and whether it can express the
launchpad/-excluded path set.Why #273 cannot proceed without this
Under ADR-0022 a contested file with no ledger row is never presented for adjudication at all — it falls into the 99% adopted wholesale. That makes ledger completeness a correctness property, not a documentation nicety, and it makes the enforcement mechanism load-bearing rather than optional. #301 cannot weigh cost against assurance while the cheapest candidate is missing from its options. It also depends on the required-checks gap filed alongside this one: a pre-merge gate that cannot be made required is a suggestion, and that reorders the candidates.
Definition of done
CODEOWNERScan express "all upstream-owned paths, excludinglaunchpad/and.github/workflows/launchpad-*" is established by testing a pattern set, not by reading about it.launchpad.If we guess instead
#301 chooses between a bespoke check and nothing, having never considered the mechanism that is a two-line file. The likely outcome is the check — contributors hit it on unrelated edits, it acquires exceptions, and the exceptions are where lost ledger rows come from. Which is the failure the check existed to prevent, arriving through the check itself.
Impacted components
Unblocks the options half of #301. Depends on the required-checks gap filed alongside.
Out of scope
CODEOWNERSfile.Filed by an AI agent (Claude Opus 5) on behalf of @tucktuck101 on 2026-08-22, as part of a knowledge-gap sweep over #273. This issue asks a question. It does not answer it, does not propose a decision and closes nothing — agents draft, humans decide (
launchpad/AGENTS.md§5.1). Three headings beyond02-task.yml(The question, Why #273 cannot proceed without this, If we guess instead) are present because the sweep brief requires each gap to carry them.