Skip to content

workflows: sign-branch and branch-sweep — the two ref writes sessions cannot do - #142

Merged
bdelanghe merged 1 commit into
mainfrom
claude/session-root-dispatcher-export-emrnqk
Aug 8, 2026
Merged

workflows: sign-branch and branch-sweep — the two ref writes sessions cannot do#142
bdelanghe merged 1 commit into
mainfrom
claude/session-root-dispatcher-export-emrnqk

Conversation

@bdelanghe

Copy link
Copy Markdown
Contributor

Two workflow_dispatch lanes, both the merge-claude-harness doctrine — 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 mechanism org-defaults' pin and registry-graph's sync already rely on — so a session-authored branch clears required_signatures without 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:

  • tree byte-identical to the replaced tip
  • file modes identical — the REST probe's lesson: a signed commit that dropped 100755 on check-session-scope.sh would satisfy the ruleset by silently unmaking the hook
  • new tip actually reports verified=true

N 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_merge is on org-wide, so merged branches already clean up — but the 36 non-default branches on .github-private are 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's tmp/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 explicit prefix like tmp/.

Shared shape

  • Cross-repo: mint via the existing front-desk broker door (require: contents), job_workflow_ref pinned to main as prx-26bq designed. Same-repo: the workflow's own token.
  • The workflows.test.mjs ratchet holds: every write goes through the API, no git commit/git push in a runner. 195/195 tests pass (the suite auto-adopted both files — column-0, broker require:, API-not-git checks all green).

Chicken and egg, named

sign-branch cannot sign its own first landing: workflow_dispatch needs the file on main, and the broker pins to main. This PR's commit needs one human signature (or bypass). It's the last one that does.

After landing, the two immediate uses:

  1. branch-sweep on .github-private with prefix: tmp/ — finally deletes tmp/api-mode-probe; dry-run first shows the full candidate table for the other 35.
  2. sign-branch on the next session-authored PR instead of the laptop amend.

Generated by Claude Code

@bdelanghe
bdelanghe marked this pull request as ready for review August 8, 2026 01:32
@bdelanghe
bdelanghe requested a review from a team as a code owner August 8, 2026 01:32
… 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
bdelanghe force-pushed the claude/session-root-dispatcher-export-emrnqk branch from a24d039 to 8540238 Compare August 8, 2026 01:33
@bdelanghe
bdelanghe merged commit 46f69af into main Aug 8, 2026
8 checks passed
@bdelanghe
bdelanghe deleted the claude/session-root-dispatcher-export-emrnqk branch August 8, 2026 01:35
@github-project-automation github-project-automation Bot moved this from Todo to Done in Front Desk Aug 8, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

2 participants