workflows: sign-branch and branch-sweep — the two ref writes sessions cannot do - #142
Merged
Merged
Conversation
… cannot do Both are the merge-claude-harness doctrine — build the window rather than declare the capability missing — applied to the two gaps measured 2026-08-08 while landing #140 and .github-private#384/#391: sign-branch: every default branch requires verified signatures, and a session can produce one by exactly zero of its lanes (local key absent and unregistrable, GraphQL createCommitOnBranch not served to sessions, REST commits unsigned AND mode-corrupting). So every session-authored PR ended in a human amend from a laptop, on every PR, forever. This lane re-creates a branch as one API commit — signed by GitHub as the token's identity, the same mechanism org-defaults' pin and registry-graph's sync already rely on — then verifies the tree byte- and MODE-identical to the old tip before succeeding, restoring the ref on any mismatch. The mode check is the REST probe's lesson: a signed commit that dropped 100755 on check-session-scope.sh would satisfy the ruleset by unmaking the hook. branch-sweep: delete_branch_on_merge covers merged branches only; the 36 non-default branches on .github-private are all closed-unmerged, never-PR'd, or probe branches, which nothing cleans — and a session cannot clean up even its own probe (ref deletion refused on both session lanes, git protocol and REST, measured against tmp/api-mode-probe). Dry-run by default; open PRs are the hard exclusion; age waived only under an explicit prefix. Both mint cross-repo via the existing front-desk broker door (require: contents) and fall back to the workflow's own token same-repo. The ratchet in workflows.test.mjs holds for both: every write goes through the API, no git commit or push in a runner. 195/195 tests pass. Chicken and egg, named rather than hidden: sign-branch cannot sign its own first landing — workflow_dispatch needs the file on main, and the broker pins job_workflow_ref to refs/heads/main. This PR's commit therefore needs one human signature or a bypass. It is the last one that does. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
bdelanghe
force-pushed
the
claude/session-root-dispatcher-export-emrnqk
branch
from
August 8, 2026 01:33
a24d039 to
8540238
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Two
workflow_dispatchlanes, both themerge-claude-harnessdoctrine — build the window rather than declare the capability missing — applied to the two gaps measured today while landing #140 / .github-private#384 / #391.sign-branch
Re-creates a named repo+branch's commits as one GitHub-signed commit via
createCommitOnBranch— the mechanismorg-defaults' pin andregistry-graph's sync already rely on — so a session-authored branch clearsrequired_signatureswithout a laptop amend.Why a workflow and not the session: all three session lanes are measured closed (local key absent and unregistrable; GraphQL not served to sessions; REST commits unsigned and mode-corrupting). Every session PR today ends with a human
git commit --amend -S, after all checks are green, on every PR, forever.Guarantees before it reports success, with the ref restored on any failure:
100755oncheck-session-scope.shwould satisfy the ruleset by silently unmaking the hookverified=trueN commits become one; original messages are preserved in the body and the replaced SHA is named. Refuses the default branch and already-verified tips.
branch-sweep
delete_branch_on_mergeis on org-wide, so merged branches already clean up — but the 36 non-default branches on.github-privateare all closed-unmerged, never-PR'd, or probe branches, which nothing touches. And a session can't clean up even its own mess: ref deletion is refused on both session lanes (git protocol and REST), measured against this very repo pair'stmp/api-mode-probe.Dry-run by default (a real run must be asked for twice). Open PRs are the hard exclusion — never touched at any age. Age (
stale_days, default 30) gates everything else, waived only under an explicitprefixliketmp/.Shared shape
require: contents),job_workflow_refpinned to main as prx-26bq designed. Same-repo: the workflow's own token.workflows.test.mjsratchet holds: every write goes through the API, nogit commit/git pushin a runner. 195/195 tests pass (the suite auto-adopted both files — column-0, brokerrequire:, API-not-git checks all green).Chicken and egg, named
sign-branchcannot sign its own first landing:workflow_dispatchneeds the file onmain, and the broker pins tomain. This PR's commit needs one human signature (or bypass). It's the last one that does.After landing, the two immediate uses:
branch-sweepon.github-privatewithprefix: tmp/— finally deletestmp/api-mode-probe; dry-run first shows the full candidate table for the other 35.sign-branchon the next session-authored PR instead of the laptop amend.Generated by Claude Code