feat(tools): add tbd_ship — CI-gated trunk-based ship (#40)
An intent verb for the trunk-based loop: branch from base → write the file → open a PR → auto-merge (squash) → delete the branch. One call instead of orchestrating file_write_branch + pr_create + workflow_run_status + pr_merge + branch_delete and remembering the conventions each time. The load-bearing safety is a pure, fail-closed CI gate (evaluateShipGate): merge=true ONLY when every workflow run for the PR head commit is completed+success AND the base branch is not review-protected. Every other state — CI pending / red / absent, review-required base, or an unclean merge — fails closed to PR-only and returns the PR with a reason. A change with no CI gate is never auto-merged to trunk (cf. agentsquad#36: non-compiling code reviewer-approved straight to main with no CI wall). - ci_timeout_seconds polls the head commit's runs to completion (default 0 = snapshot, returns pending right after opening the PR). - Derives a deterministic short-lived branch (tbd/<slug>-<hash>); handles new and existing files (fetches the blob sha for updates). - Adds head.sha + mergeable to the PR struct. - Tests: full gate matrix (green/pending/red/cancelled/none/mixed/protected) + Call happy-merge, no-CI fail-closed, red fail-closed, allowlist. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -33,6 +33,7 @@ func RegisterAll(
|
||||
reg.Register(NewPRGet(c, a))
|
||||
reg.Register(NewPRList(c, a))
|
||||
reg.Register(NewPRMerge(c, a))
|
||||
reg.Register(NewTBDShip(c, a))
|
||||
reg.Register(NewPRComment(c, a))
|
||||
reg.Register(NewPRFilesDiff(c, a))
|
||||
reg.Register(NewWorkflowRunTrigger(c, a, giteaBaseURL))
|
||||
|
||||
Reference in New Issue
Block a user