Skip to content

task: enumerate the mechanisms that could enforce a ledger row for upstream-owned files #369

Description

@tucktuck101

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:

  • 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.
  • Nothing, plus a scheduled drift report. The precedent exists in this repo: task: make project-board membership automatic, and detect it when it drifts #293 argues for exactly this shape for board membership, on the grounds that a control whose failure is invisible provides no assurance.

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.

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

  • 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.
  • The "nothing, plus a drift report" option is assessed on its merits rather than as a null option, since task: make project-board membership automatic, and detect it when it drifts #293 makes that argument for a comparable control in this repository.

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

.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.

Out of scope


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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    area:ciGitHub Actions, checks, automationarea:processHow the cohort works: templates, labels, conventionsby:agentFiled or authored by an AI agent, not a humantype:taskBounded work — one branch, one PR. The default type.

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions