Why
Additive to #354 (the adoption plane, delivered in modules/update-adopt.nix on 2026-09-13). The issue-zero design (/home/tom/today/review/2026-09-19/ISSUE-ZERO-DISTILLATION.md section 7) uses the adoption receipt as the strongest promotion signal a protocol card can earn: the card's PR was merged, built by the NAS at 01:30, adopted by the worker and probed known-good. Today the receipt names the candidate rev and store path; it does not say which PRs the rev carries, so the promotion counter would have to walk git itself on every host.
Outcome
- hosts/nas/update-center.sh: after the build and Attic push succeed, compute
merged_prs for each host as the PR numbers of merge commits between the previous published candidate rev for that host and the new rev (git log --merges --format=%s <prev>..<new> on the public checkout the build already fetched, parsing "Merge pull request #N"), and write it into the manifest beside rev and store_path. Empty list when there is no previous candidate. No change to signing: the field is inside the signed manifest.
- modules/update-adopt.py: copy merged_prs from the manifest into every receipt written for that candidate (stage, activate, known-good, rolled-back, superseded) and into
update-adopt status --json.
- tests/update-center: one case with two candidate revs and a fake git log; the manifest carries the expected numbers.
- Docs: one paragraph in the update-adopt.nix header naming the field and its consumer (protocols/tools/promote.py, dotfiles issue on the distiller).
Acceptance
Refs #354, #322, the distiller issue.
Why
Additive to #354 (the adoption plane, delivered in modules/update-adopt.nix on 2026-09-13). The issue-zero design (/home/tom/today/review/2026-09-19/ISSUE-ZERO-DISTILLATION.md section 7) uses the adoption receipt as the strongest promotion signal a protocol card can earn: the card's PR was merged, built by the NAS at 01:30, adopted by the worker and probed known-good. Today the receipt names the candidate rev and store path; it does not say which PRs the rev carries, so the promotion counter would have to walk git itself on every host.
Outcome
merged_prsfor each host as the PR numbers of merge commits between the previous published candidate rev for that host and the new rev (git log --merges --format=%s <prev>..<new>on the public checkout the build already fetched, parsing "Merge pull request #N"), and write it into the manifest beside rev and store_path. Empty list when there is no previous candidate. No change to signing: the field is inside the signed manifest.update-adopt status --json.Acceptance
update-adopt stageon a host carries the list;update-adopt status --jsonshows it.Refs #354, #322, the distiller issue.