Skip to content

prd: the change agent — own the block/buzz → launchpad-26/buzz relationship, including conflict resolution #273

Open
16 of 20 issues completed

Description

@tucktuck101

Delivered through

This umbrella PRD is delivered by the feature issues above (rescope 2026-08-24: Milestone > PRD > Feature > Task). It closes when the last of them ships.

Problem

This fork carries deliberate divergence from block/buzz — including product-code changes, not just cohort process files — and nothing owns the job of keeping it current. Upstream moves daily; the fork has not merged upstream since 2026-08-17.

That leaves two costs. The gap compounds: every day of drift makes the eventual merge larger and its conflicts harder, on a ~3,800-file upstream. And the cost lands on the wrong person at the wrong time — a contributor part-way through a feature discovers a conflict that has nothing to do with their work, in files they did not touch and whose divergence they may not know the reason for.

What is needed is a change agent that owns the block/buzz → launchpad-26/buzz relationship: it keeps the mirror current, absorbs the conflict work, resolves what it can safely resolve, and escalates the rest with enough context for a human to decide quickly. Contributors should learn about upstream only when they need to act on it.

Conflict resolution is the product here, not a side effect of syncing. The fork's divergence is intentional and expected to grow.

Evidence

Measured against launchpad-26/buzz and block/buzz on 2026-08-21:

  • launchpad is 255 ahead, 60 behind upstream/main. Merge-base is 2026-08-17; upstream committed as recently as 2026-08-20. No upstream commit has been merged into launchpad in that window.

  • All 255 divergent commits are cohort-authored (Serina 192, tucktuck101 53, joshuavial 4, Ben Mitchell 6). None came from upstream.

  • Of 324 files the fork has changed, 282 are inside the launchpad/ scope and 42 are upstream files: ~17 process/meta (AGENTS.md, CONTRIBUTING.md, issue templates, .claude/skills/*), ~9 build/tooling (Justfile, lefthook.yml, bin/lefthook, scripts/instance-env.sh, ci.yml), ~5 deployment (Dockerfile, docker.yml, deploy/compose/*), and 9 product code (crates/buzz-cli/src/commands/pack.rs, crates/buzz-persona/src/resolve.rs, 6× desktop/src-tauri/**).

  • A reason is recorded for 7 of those 42. ADR-0005 documents five deployment files; ADR-0017 documents the two lefthook pins. The other ~35, including all nine product-code files, have no recorded statement of why they diverge or which side should win a conflict.

  • git rerere is not enabled. Every recurring conflict is re-resolved from scratch, every time.

  • .gitattributes sets only * text=auto eol=lf. No merge drivers, so files the fork permanently owns still conflict on every sync.

  • launchpad-26/main is a clean, unmodified ancestor of upstream/main — 0 ahead, 221 behind. Confirmed intentional: it is the mirror through which updates arrive before being worked on locally.

  • The 60-commit gap test-merges with exactly three conflicts. git merge-tree launchpad upstream/main auto-merges AGENTS.md, Justfile, crates/buzz-cli/src/lib.rs and desktop/src-tauri/src/managed_agents/restore.rs cleanly, and conflicts on only:

    • lefthook.yml — divergence documented (ADR-0017), so the winner is already known
    • .github/workflows/ci.yml — divergence undocumented, config
    • desktop/src-tauri/src/managed_agents/runtime.rs — divergence undocumented, product code

    One conflict in each of the three resolution classes this PRD proposes: register-driven, mechanical, and semantic. The backlog is small today and the mechanism can be proven against a real case immediately.

  • The only sync automation that exists today runs on a contributor's personal fork and merges launchpad-26/main, which is itself 416 commits behind launchpad. It syncs from a stale mirror.

Success criteria

  1. The mirror is never stale by more than one cadence period. launchpad-26/main fast-forwards from upstream/main unattended; a failure to do so is visible, not silent.
  2. A clean upstream merge reaches a reviewable PR with no human involvement — no model invoked, no contributor prompted.
  3. Every one of the 42 diverged upstream files has a recorded reason and a stated conflict winner, in a register a resolver can consult. New divergence is added to it in the PR that creates the divergence.
  4. A conflict already resolved once does not require resolving again, by way of rerere and/or merge drivers. Demonstrated by a repeat sync over the same file pair.
  5. A semantic conflict escalates with context: which files, which register entries apply, what upstream changed, and a one-command local entry point that reproduces the merge with the full toolchain available.
  6. just ci gates every sync PR before it is mergeable. A sync that breaks the build is a failed sync, not a merged one.
  7. A contributor mid-feature is never the first to discover an upstream conflict in files they did not touch.
  8. The agent never merges to launchpad itself — see non-goals.

Non-goals

  • No unilateral merging. The agent opens PRs; a human with write access merges them. This is a hard constraint, not a default: the cohort has already lost a repository to an agent taking an irreversible action with legitimately granted privilege.
  • No unattended resolution of semantic conflicts in CI. Resolving a Rust or TSX conflict without being able to build and test it produces confidently broken merges. Mechanical resolution (register-driven, rerere, merge drivers) is in scope; judgement is escalated.
  • No PRs sent back to block/buzz. ADR-0017 records that the cohort is not currently sending changes upstream. If that changes it is a separate decision.
  • No rebasing of shared branches. launchpad has eleven people working off it, and rebasing would defeat rerere. Merge only.
  • Not an upstream-awareness product. prd-01 — upstream intelligence: Buzz keeps the cohort aware of upstream #3 owns reporting on upstream releases and activity. This PRD owns keeping the fork current. Where they touch — where records persist, how failures are surfaced out-of-band — the ADRs under prd-01 — upstream intelligence: Buzz keeps the cohort aware of upstream #3 (adr: where generated upstream reports persist #51, adr: the minimum Discord fallback for upstream notifications #52) apply rather than being re-decided here.
  • Not a reduction in deliberate divergence. The fork's product-code changes are intentional and this PRD does not propose reverting them.

Impacted components

.gitattributes                                  merge drivers for fork-owned files
.github/workflows/launchpad-upstream-sync.yml   new — scheduled mirror + merge attempt
launchpad/upstream-sync/DIVERGENCE-REGISTER.md  new — the 42 files, reasons, conflict winners
launchpad/upstream-sync/                        new — resolution scripts and skill
launchpad/decisions/                            ADRs this PRD raises (below)
Justfile                                        local entry point for the escalation path

Security implications

The agent holds write access to shared branches on a public repository and takes actions on them. That is the same risk class as buzz-infrastructure #103, and the mitigations are the ones ADR-0015 already established for host access: the agent never holds a credential of its own beyond the workflow's scoped GITHUB_TOKEN, destructive or irreversible steps are proposed rather than taken, and every action is attributable.

Three specifics:

  • Token scope. The workflow needs contents: write and pull-requests: write and nothing else. It must not carry the ability to delete branches, delete the repository, or alter settings.
  • Branch protection is the backstop, and it is currently thin. launchpad requires one approval and has no required status checks, so success criterion 6 (just ci gates the merge) needs the check to be required, not merely present — otherwise a red sync PR is one click from landing.
  • Upstream content is untrusted input. The agent reads and merges code authored outside the cohort, and a resolution prompt containing upstream diff text is attacker-influenceable in the same way launchpad/review-agent/CONTAINMENT.md describes for PR-authored text. That containment contract should be reused, not reinvented.
  • The escalation path runs on a contributor machine, which is in scope for buzz-infrastructure group_vars must sit beside the inventory, and role defaults are not cross-role scope #103. It is the favourable case for that ADR — human present, explicit per-action instruction — but it should be decided there, and the workflow half ships independently of it.

Decisions this PRD raises

To be filed as child ADRs, not decided here:

  1. Conflict-winner policy for the ~35 undocumented divergences — per-file, or per-category with named exceptions.
  2. Cadence — daily is assumed (small deltas conflict far less than large ones); the alternative is upstream-tag-triggered.
  3. How far mechanical resolution may go before escalating — rerere replay and merge=ours are clearly mechanical; a three-way merge the agent believes is unambiguous is the boundary case.
  4. Where the escalation runs — contributor machine with full toolchain, versus a provisioned environment. Interacts with buzz-infrastructure group_vars must sit beside the inventory, and role defaults are not cross-role scope #103.

Filed by an AI agent (Claude Opus 5) on behalf of @tucktuck101, from direction given in session on 2026-08-21. Verified today against the GitHub API and the local clone: all branch divergence counts, the 324/282/42/9 file breakdown and its categories, commit authorship of the 255, the absence of rerere configuration, the contents of .gitattributes, that launchpad-26/main is an unmodified ancestor of upstream/main, and that ADR-0005 and ADR-0017 between them document 7 of the 42 files. Not verified: whether the three conflicts resolve to a correct merge — merge-tree reports textual conflicts, not semantic ones, and the four files that auto-merged cleanly could still be wrong in behaviour. just ci on a real merge branch is what would establish that, and it has not been run.

Activity

  1. self-assigned this
    on Aug 21, 2026
  2. added
    type:prdProblem, evidence and success criteria — delivered through child features and tasks
    area:processHow the cohort works: templates, labels, conventions
    by:agentFiled or authored by an AI agent, not a human
    area:agents-and-automationAgentic workflows and automation — proposals and delivery (see #40)
    on Aug 21, 2026
  3. tucktuck101 commented on Aug 21, 2026

    @tucktuck101
    CollaboratorAuthor

    Proposal — completing PRD #273 (the change agent)

    Nothing was written. All work below is read-only: gh issue view, gh api, git fetch, git diff, git merge-tree, and reading launchpad/AGENTS.md, ADR-0005, ADR-0017, launchpad/AGENT_PR_TEMPLATE.md.


    0. Re-measured facts, and four places the PRD is wrong

    I re-derived everything I rely on. The tip moved; three of the changes matter.

    PRD says Measured today (after git fetch upstream main)
    255 ahead / 60 behind 259 ahead / 67 behind
    324 files / 282 in launchpad/ / 42 upstream 327 / 279 / 48
    3 conflicts 4 — Cargo.lock has joined
    merge-base 2026-08-17 unchanged (f8692fa9b)
    $ git rev-list --left-right --count launchpad/launchpad...upstream/main
    259	67
    $ git merge-tree --write-tree --name-only launchpad/launchpad upstream/main
    7f3833a261c463db0861f36d6d8dad9cac9d07cc
    .github/workflows/ci.yml
    Cargo.lock
    desktop/src-tauri/src/managed_agents/runtime.rs
    lefthook.yml
    

    0.1 The "42 diverged upstream files" is not a 42-file conflict surface

    Classifying all 48 by status against the merge-base and against upstream/main:

    • 21 are pure fork additions with no upstream counterpart — the six .claude/skills/*, the six .github/ISSUE_TEMPLATE/0*.yml, the five launchpad-*.yml workflows, LAUNCHPAD.md, bin/.lefthook-2.1.10.pkg, desktop/src-tauri/src/managed_agents/runtime/summary.rs, scripts/test-ci-changed-paths-filter.sh. These cannot conflict unless upstream one day creates a file at the same path.
    • 2 are deletions (bug-report.md, feature-request.md) — these conflict only as modify/delete.
    • 25 are true modifications of files upstream still owns.
    • Of those 25, upstream has touched only 8 since the merge-base. Four of the eight conflict.

    So the register has ~27 rows that can ever matter and 8 that matter now. That is good news for scope and it changes sequencing: the register is insurance against future syncs, not the thing blocking this one.

    0.2 ADR-0017 does not document lefthook.yml

    The PRD says lefthook.yml's divergence is "documented (ADR-0017), so the winner is already known." It is not. ADR-0017 is scoped to "exactly bin/lefthook and bin/.lefthook-*.pkg." lefthook.yml's divergence is a one-line branch-skew redirect, documented only in an in-file comment citing #15. It is an undocumented divergence for register purposes, and its conflict is in the semantic class, not the register-driven one. That moves the PRD's "one conflict in each of the three classes" claim: today it is two mechanical-ish, two semantic, not one of each.

    0.3 merge=ours drivers are wrong for almost every candidate the PRD names

    This is the largest correction. Three of the four candidate groups fail on inspection:

    lefthook.yml — actively harmful. Our divergence is one line. Upstream's change since the merge-base is a near-rewrite: it adds rc: bin/.lefthookrc, adds files: git diff --name-only origin/main...HEAD scoping to six lanes, adds push-head-scope and file-size-check lanes, and renames mobile-fix→mobile-fmt and mobile-test→mobile-checks. merge=ours would silently discard all of it to preserve one line. The correct resolution is theirs, then re-apply our line.

    The five ADR-0005 deployment files — contradicts the ADR. ADR-0005 explicitly rejects a fork-local copy of docker.yml and states the reasoning: "A conflict you must resolve is better than a copy you forget to." merge=ours reintroduces exactly the silent-drift failure that ADR rejected. Adding those drivers would be reversing a decided ADR inside a plumbing PR.

    bin/lefthook and bin/.lefthook-*.pkg — the ADR states a different rule. ADR-0017: "resolved by taking whichever version is newer." That is neither ours nor theirs; it is a comparison. merge=ours would pin us to 2.1.10 forever and block an upstream bump to 2.2.x.

    Only .github/ISSUE_TEMPLATE/* survives, and mostly it does not need a driver: six of the nine files are fork-only additions, two are deletions, and config.yml is the single genuine ours-wins case.

    0.4 A concrete hazard already sitting in the 67-commit backlog

    Upstream's new bin/.lefthookrc sets LEFTHOOK_BIN to the Hermit-pinned bin/lefthook at 2.1.3 — the exact version ADR-0017 records as crashing every first push in this fork, because the branch name launchpad collides with the launchpad/ directory. lefthook.yml and bin/.lefthookrc auto-merge or arrive clean; the interaction with our 2.1.10 pin does not. A textually clean merge here reintroduces a known, filed bug (#196). This is the best available argument for the PRD's own "no unattended semantic resolution" non-goal, and it should be the worked example in the escalation contract.


    1. The eight success criteria

    SC1 — mirror never stale by more than one cadence period

    Blocked by a permission I cannot grant, and the PRD does not know it.

    $ gh api repos/launchpad-26/buzz/branches/main/protection --jq '.restrictions.users[].login'
    joshuavial
    $ gh api repos/launchpad-26/buzz --jq '.default_branch'
    launchpad
    

    Push to main is restricted to one named user. restrictions.apps is empty, so the Actions GITHUB_TOKEN cannot fast-forward it. allow_fork_syncing is false.

    Three ways out, in preference order: (a) an admin adds github-actions to restrictions.apps — one API call, keeps the design intact; (b) the mirror moves to an unprotected upstream-mirror branch and main stays a human-maintained artifact; (c) a PAT, which I would argue against on ADR-0015 grounds.

    How I'd satisfy it: scheduled launchpad-upstream-sync.yml, contents: write + pull-requests: write only, fetching block/buzz and fast-forwarding. Evidence: a run log showing the FF, plus a deliberate failure injection (point it at a non-fast-forwardable ref) showing the job goes red rather than silent. Not achievable without (a) or (b) being decided by a human with admin.

    SC2 — clean upstream merge reaches a reviewable PR with no human involvement

    Achievable and cheap. Pure shell in the same workflow: git merge --no-ff, and on success push a branch and gh pr create with the by:agent label and an AGENT_PR_TEMPLATE-shaped body. No model in the loop.

    Evidence: a run where merge exits 0, the PR exists, and the workflow log shows no model invocation. The honest caveat is that this path is currently unexercised — the backlog conflicts, so the clean-merge branch will not run for real until the four conflicts are cleared. I would prove it against a synthetic ancestor pair rather than claim it works.

    SC3 — every diverged upstream file has a recorded reason and a stated conflict winner

    Achievable, and the most valuable single deliverable. launchpad/upstream-sync/DIVERGENCE-REGISTER.md, one row per file: path, category, status vs merge-base, why it diverges, conflict winner, authority (ADR / issue / in-file comment / unrecorded), and who to ask.

    Two things I would insist on. First, the honest rows: the eight modified product-code files trace to four commits (f36d10f9c pack JSON output, 35cab546a cfg(unix) gating, 975e6d444 configured-relay dial, 43366affa file-size ratchet split) but none of those has a recorded statement of upstream-conflict intent. I would record the commit as provenance and mark the winner UNDECIDED — see ADR-0018, not invent one. Second, "add to the register in the PR that creates the divergence" needs a check to be real; a convention nobody enforces decays. I would extend launchpad-pr-check.yml to fail when a PR modifies an upstream-owned file with no matching register row.

    Evidence: row count equals the generator's file count; a script that regenerates the file list and diffs it against the register.

    SC4 — a conflict resolved once is not resolved again

    Achievable in weaker form than the PRD assumes. Two structural facts the PRD does not account for:

    • rerere state lives in .git/rr-cache/, which is per-clone and never committed. A GitHub Actions runner is ephemeral, so rerere gives the sync agent nothing unless rr-cache is persisted — via actions/cache, or committed to a dedicated branch. Contributor machines each get their own, independently.
    • Custom merge drivers are defined in git config, not in .gitattributes — deliberately, for security. merge=ours in .gitattributes is inert until every clone runs git config merge.ours.driver true. union is built in; ours is not.

    So both halves of the PRD's mechanism need a bootstrap that the PRD does not list. I would add a just upstream-sync-setup recipe (enable rerere, define the drivers) wired into just setup, plus a documented rr-cache persistence strategy for CI.

    Evidence: the PRD's own test — resolve lefthook.yml, discard the merge, re-merge, and paste git rerere status showing the replay. Run it twice on the same machine, and once on a second machine to demonstrate the sharing gap honestly.

    SC5 — semantic conflicts escalate with context

    Achievable. On non-zero merge exit: emit conflicted paths, the matching register rows, git log --oneline merge-base..upstream/main -- <path> per file, and a one-command local entry point (just upstream-sync-resume) that recreates the merge with the toolchain live. The escalation should be a GitHub issue or a draft PR with the conflict markers committed, not a Discord ping alone.

    Containment: upstream diff text is attacker-influenceable. launchpad/review-agent/CONTAINMENT.md and contain.py already exist for PR-authored text and should be reused verbatim rather than reinvented — the PRD says this and it is right.

    Evidence: the escalation artifact for today's real runtime.rs conflict, showing it names the code-motion cause.

    SC6 — just ci gates every sync PR

    Cannot be fully satisfied, and it is broken twice, not once.

    The PRD identifies one break: no required status checks (gh api .../branches/launchpad/protection returns "checks": null), and making one required is out of scope for me.

    The second break is not in the PRD. A PR opened by the Actions GITHUB_TOKEN does not trigger pull_request workflows. ci.yml's triggers are push: branches: [main, release] and pull_request: — a sync branch matches neither. So CI would not merely be un-required on the sync PR; it would not run at all. Fixing that needs either a GitHub App / PAT to author the PR, or an explicit push/workflow_dispatch trigger for sync branches.

    I can make CI run. I cannot make it required. I would state that gap in the register and the ADR rather than paper over it.

    SC7 — a contributor mid-feature is never first to discover an upstream conflict

    Satisfiable in practice, unfalsifiable as written. Contributors branch from and merge to launchpad; they never merge upstream. The real content is "the sync agent gets there first," which follows from cadence plus SC2/SC5. Evidence: a log of sync runs with dates and conflicted paths, so a contributor who does hit one can be traced to a specific gap. I would rewrite the criterion as a negative-observation record rather than pretend it is testable.

    SC8 — the agent never merges to launchpad

    Achievable, and enforced by the platform rather than by the agent's good behaviour: launchpad requires one approving review, and can_approve_pull_request_reviews is false for the Actions token. Evidence: the workflow's permissions: block, plus that API output. Belt and braces — a plan that relies only on the agent choosing not to merge is not a plan, given what the cohort already lost.


    2. Work items

    Each is one branch, one PR, against launchpad.

    # Work item Size Depends on
    W1 Divergence register — launchpad/upstream-sync/DIVERGENCE-REGISTER.md, ~48 rows with a generator script for the file list. Winners recorded only where an authority exists; the rest marked UNDECIDED. M —
    W2 rerere + bootstrap — just upstream-sync-setup, wired into just setup; contributor docs. No .gitattributes change. S —
    W3 .gitattributes drivers, narrow — .github/ISSUE_TEMPLATE/config.yml only, plus the driver definition in W2's recipe. Explicitly not the ADR-0005 five, not bin/lefthook*, not lefthook.yml, with the reasoning in the PR body. S W1, W2
    W4 Clear the four conflicts — the first real sync, hand-resolved, with rerere recording. Four PRs or one, per §3. L W1, W2
    W5 Mirror workflow — scheduled FF of launchpad-26/main from upstream/main, failing loudly. S admin decision on main push restriction
    W6 Merge + PR workflow — attempt merge, open PR on success. M W5
    W7 Escalation path — conflict context bundle, just upstream-sync-resume, containment reuse. M W6, ADR-0021
    W8 Register enforcement — extend launchpad-pr-check.yml to require a register row for upstream-file changes. S W1
    W9 Sync-PR CI trigger — make ci.yml actually run on sync branches. S W6

    Four ADR issues (§4) are filed alongside, not counted as work items — per launchpad/AGENTS.md §4, an ADR is not a work item.


    3. Sequencing, and where the PRD's ordering is wrong

    W1 register ──┬─► W3 gitattributes ──┐
    W2 rerere  ───┴─► W4 clear conflicts ─┴─► W6 merge/PR ─► W7 escalate
                                          ▲                   W9 CI trigger
    W8 enforcement (after W1)             │
    W5 mirror ────────────────────────────┘   [gated on admin]
    

    Three departures from the PRD's implied order.

    (a) rerere must precede the first hand-resolution, not follow it. The PRD lists plumbing and register as parallel setup. But rerere only records resolutions performed while it is enabled. Resolving the four conflicts first and enabling rerere afterwards throws away the single most valuable training set the fork will ever produce. W2 is small and blocks nothing — it should land first, before anyone touches a conflict.

    (b) The register must precede the merge drivers, and it did the work of shrinking them. The brief I was originally given assumed the ADR-0005 five, bin/lefthook*, lefthook.yml, and the issue templates were all merge-driver candidates. Writing the register is what shows that all but one are wrong (§0.3). Any ordering that lets the drivers land first ships a change that reverses ADR-0005 by side effect.

    (c) Clearing the four conflicts should come before the automation, not after. The PRD treats the current backlog as the thing automation will handle. It is not — it is the thing that proves the automation is needed and supplies its test fixtures. A sync workflow built while the branch is 67 behind has no clean-merge path to exercise; every run escalates, and you learn nothing about SC2. Clear the backlog by hand with rerere on, then automate the steady state.

    On W4's shape: I would split it. Cargo.lock (regenerate) and .github/workflows/ci.yml (small — upstream replaced two of our steps with just file-size-check) are one PR. lefthook.yml is its own PR, because resolving it correctly means noticing the .lefthookrc/2.1.3 hazard in §0.4 and that is a reviewable judgement in itself. runtime.rs is its own PR: it is a code-motion-versus-edit conflict — we extracted persona_drift_state, workspace_pair_key and build_managed_agent_summary into runtime/summary.rs for the file-size ratchet, and upstream edited that block in place. Resolving it means porting upstream's edit into our extracted file and building it. No mechanism helps here; this is what escalation is for, and it is the best evidence for ADR-0020's boundary.


    4. The four ADRs

    ADR Question Blocks Can proceed without it
    0018 Conflict-winner policy for the undecided divergences — per-file or per-category W3 (which drivers), the winner column of W1 W1's reason/provenance columns; W2; W4's four resolutions (each is a specific technical call, not a policy)
    0019 Cadence — daily vs upstream-tag-triggered The schedule: line in W5 Everything. Ship with daily and amend one cron line. Genuinely low-stakes; I would not let it block.
    0020 How far mechanical resolution may go before escalating W6/W7's decision boundary W1–W5, W8, W9
    0021 Where escalation runs — contributor machine vs provisioned environment; interacts with buzz-infrastructure #103 The runner half of W7 W7's context-bundle half. Emitting the bundle is independent of where the resume happens.

    0018 is the real gate and the one most likely to stall, because answering it means eight product-code files whose authors may not have thought about upstream conflict at all. I would file it with the register attached as evidence and a recommended default — upstream wins on product code unless a row says otherwise, fork wins on process and deployment files — so the decision is a yes/no on a concrete proposal rather than an open design question. 0019 should be decided by fiat in the PRD, not as an ADR; it is a cron expression, and giving it ADR weight adds a week of latency to a one-line change.


    5. What I would do first

    W2 then W1, in that order, and they are cheap.

    W2 is roughly an hour: a just upstream-sync-setup recipe running git config rerere.enabled true, git config rerere.autoUpdate true, and the merge-driver definition; a hook into just setup; a paragraph in launchpad/AGENTS.md §3 or a new launchpad/upstream-sync/README.md. It blocks nothing, it is reversible, and every hour it is not landed is an hour in which someone might resolve a conflict that is then lost. Evidence would be git config --get rerere.enabled before and after, pasted raw.

    W1 is most of a day. I have already derived the classification (48 files, 21/2/25 split, upstream-touched-since-merge-base per file) with a loop over git diff --name-status against both sides, so the mechanical part is done. The expensive part is the ~35 unrecorded reasons, which means reading four product-code commits and roughly a dozen process-file commits and writing down what they were actually for. Where I cannot determine intent I would write unrecorded — see #<commit>, not guess.

    What it would take beyond my own time: one admin decision before W5 can start — whether github-actions joins restrictions.apps on main, or the mirror moves to an unprotected branch. And one human to name owners for the product-code rows in the register; the "who to ask" column is worthless if I fill it in from commit authorship alone.


    6. What cannot be done

    Cannot be done at all, by me:

    • SC6 in full. Making a check required needs admin and is explicitly out of scope. I can make CI run on sync PRs (W9); I cannot make it block. Until someone does, a red sync PR is one approval away from landing, and the PRD's own security section is right to flag it.
    • The main fast-forward (SC1) until the push restriction is resolved. I have no path around it and would not want one.
    • Deciding any of the four ADRs. launchpad/AGENTS.md §5.1: draft everything, approve nothing.

    Cannot be done well in 27 days:

    • A register that is genuinely trustworthy on all 48 rows. I can produce all 48 rows with accurate mechanics and honest provenance. I cannot produce 48 rows with confident, owner-endorsed conflict winners without the ADR-0018 decision and several people's attention. A register with fabricated confidence is worse than one with UNDECIDED in it, so I would ship the honest version and let the winners fill in.
    • A proven steady state. SC4's real test is a repeat sync over the same file pair, and SC1's is a cadence sustained across periods. With 27 days and an unclear start on W5, there is time for perhaps two or three real sync cycles. That is enough to demonstrate the mechanism and not enough to demonstrate it is reliable. I would say so rather than let three green runs read as proof.

    Should not be done, though it was asked for:

    • merge=ours on the ADR-0005 five, bin/lefthook*, or lefthook.yml. §0.3. Each contradicts a written decision or discards substantial upstream work. If the intent behind that instruction was "make these stop conflicting," the honest answer is that they should keep conflicting, and the register's job is to make each conflict cheap to resolve rather than to make it disappear.

    Not verified: I have not run just ci, have not attempted a real merge in a working tree (I used git merge-tree --write-tree, which reports textual conflicts only), have not confirmed the four resolutions produce a building tree, have not tested rerere replay end to end, have not confirmed that adding github-actions to restrictions.apps actually permits the FF, and have not read the ~12 process-file commits behind the unrecorded divergences — only the four product-code ones. No VPS access and none needed here.


    Written by an AI agent (Claude Opus 5) on behalf of @tucktuck101, from direction given in session on 2026-08-21. Read-only investigation: gh issue view, gh api, git fetch, git diff, git merge-tree, and reading launchpad/AGENTS.md, ADR-0005, ADR-0017, launchpad/AGENT_PR_TEMPLATE.md. No repository files were changed, no commits, no pushes, no pull requests. This is a proposal, not a decision — nothing here is approved.

  4. 36 remaining items

  5. added a commit that references this issue on Aug 31, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

area:agents-and-automationAgentic workflows and automation — proposals and delivery (see #40)area:processHow the cohort works: templates, labels, conventionsby:agentFiled or authored by an AI agent, not a humantype:prdProblem, evidence and success criteria — delivered through child features and tasks

Type

No type

Projects

No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions