Trials P-28 and P-29: the last pusher and the identity of the content are readable (pass)

Merged
DO
4d ago
+8798-20

Closes #11.

Trials P-28 and P-29: are the last pusher and the identity of the content readable? (design ยง6, batch 1; ADR-0013, decision 7)

TrialPass condition, written firstVerdict
P-28The actor who last pushed a pull request's head, pushed by a person, can be read as a fact, and the field is namedPass
P-29, baseThe hash of a pull request's own diff is unchanged when only the base movesPass
P-29, truncatedA truncated diff is detectable, and how it presents is recordedPass, with a gap

P-28: GET /repos/{repo}/activity?ref=refs/heads/{head}. Each entry carries actor.login, actor.type, activity_type (push, force_push or branch_creation), before, after and timestamp. The entry whose after equals the pull request's head.sha names the pusher, for plain and force pushes alike.

  • The timeline's head_ref_force_pushed (REST) and HeadRefForcePushedEvent (GraphQL) name an actor only for a force push.
  • committed and PullRequestCommit carry only git's author and committer; an amend kept the old author date.
  • The events API showed no push after five minutes.

P-29, base: the SHA-256 of the pull request's diff (Accept: application/vnd.github.diff) was byte-identical before and after main moved, and changed at each push to the head.

  • Unexpected: the pull request's base.sha did not follow main. It moved only when the head was pushed, and merge_commit_sha was rebuilt only then. Filed against the design as #163.

P-29, truncated:

  • A pull request of 3,001 files gets a 406 with errors[0].code: too_large and field: diff, naming the 300-file limit. The .patch form is the same.
  • The files list stops at 3,000 entries with a 200, detectable only against changed_files.
  • Large files lose their patch field.
  • No refusal by line count was seen: 225,000 lines (1.65 MB) came back whole.

What changes

  • trials/P-28.json, trials/P-29.base.json and trials/P-29.truncated.json.
  • Grounding in sim/grounding.py: the_pusher_is_the_last_pusher, a_push_is_new_content and a_short_diff_says_so. an_approval_survives_a_push stays unverified, since no approval was made.
  • One test fix, in a commit of its own: the same change as in #162, so the two merge cleanly, plus moving one test's scratch rule from P-28's rule to P-18's.

Redaction removed the authorization header on every request, and 11โ€“12 response headers a fixture may not keep. Nothing shaped like a credential was found.

Step 8 undid: the canary's PRs #26โ€“28 (closed), their three branches (deleted), and seven CodeQL runs (deleted).

Staying in the canary:

  • the commit a260bd6 that moved main;
  • the closed PRs;
  • seven code-scanning analyses.

The commits were made under the Maintainer's identity, through their gh login. The environment main-only and its secret were never named or touched.

Verified: python3 -m tools.check_trials passes, and make verify passes on a git archive export. The mutation run is CI's.

๐Ÿค– Generated with Claude Code