Skip to content

v2.1.0

Choose a tag to compare

@github-actions github-actions released this 14 Jul 10:37
dcd058a

v2.1.0 adds one new MCP tool (branch_guard) and hardens several existing ones against silent false-positive gate results — the dominant theme this cycle is "a compliance/trust check returned a confident ok:true/success when it shouldn't have." ci_wait_run gains a merge-result anchor to stop grading the wrong pipeline; ibm and branch_guard stop guessing repo/branch pairings; work_item stops leaking type::epic onto Plans. Also: three wave-engine handlers stop hardcoding main as the mainline, a deploy-freshness startup check was added, and two HIGH CVEs were patched. CHANGELOG.md was retired in this range (#459) — GitHub Releases notes (this document) are now the authoritative changelog; there is no in-repo file to check.

New tools

  • branch_guard (#469, refined #471, #485) — Guards against basing on / merging into the wrong mainline. Input: role ('base'|'target'), optional branch, optional repo. Resolves the git host's live default branch and verdicts whether the checked branch is "protected" by name (main or release/* — a shared pattern with ibm, not a live host protection query as originally shipped in #469 and reworked in #471). Returns {verdict: 'pass'|'warn', reason, default_branch, checked_branch, is_protected, is_sandbox}; kahuna/* sandboxes always pass. Warns when a protected-by-name branch is neither the live default nor a sandbox (e.g. a stale release/0.0.1 after the default moved to release/1.0.0). Call it before basing/merging to catch drift against a moved default branch. As of #485, role:'base' with an explicit repo but no branch is refused rather than pairing the server cwd's current branch with a possibly-unrelated foreign repo.

Changed

  • ci_wait_run (#478, #484) — New optional params require_merge_result: boolean and pr_number: number (required together via a zod .refine). Set require_merge_result: true to accept only a run that validated the actual merge result for the PR/MR's current head — GitHub: a pull_request run whose head_sha matches the PR head; GitLab: the pipeline GitLab reports as the MR's head_pipeline (a detached /head or merge-train /train pipeline no longer counts). A non-qualifying run now yields final_status: "not_merge_result" instead of a misleading success. Also: the "no run has appeared yet" grace window is now decoupled by call shape — require_merge_result still gets the full timeout_sec (merged-results pipelines are slow to appear), but a plain expected_sha wait is now bounded to min(timeout_sec, 180s) instead of silently consuming the entire timeout on a transient first-poll miss. Phase-2 (polling a run once it has appeared) is unaffected either way.
  • ibm (#481) — New optional repo param, threaded through both the issue lookup and the PR/MR lookup. Pass it whenever the branch being checked is not the one checked out in the server's cwd. Behavior change: an unrecognized branch with no repo given is now refused (ok:false) rather than silently resolved against the cwd's repo — previously this could match a same-numbered but unrelated issue in the wrong repository and return a false ok:true compliance pass. The response envelope now echoes the repo actually checked.
  • work_item (#479) — type enum gains 'plan' (applies type::plan); previously /issue plan was documented but not creatable. Behavior change: the auto type::<type> label is now suppressed whenever the caller already supplies any type::* label (both platforms) — previously it was always prepended, which was only safe on GitLab by accident (scoped-label eviction); on GitHub the same call could produce an issue tagged with both type::epic and type::plan. Caller-supplied labels are also now trimmed/normalized once before both the suppression check and the platform argv, and a GitHub --label failure on a non-existent label now names the remedy (label_create) in the error message.
  • wave_init — the kahuna bootstrap's implicit base_branch no longer defaults to the literal 'main'; when the plan omits base_branch it now resolves the repo's live default branch via the adapter (#473).
  • wave_finalizetarget_branch changed from z.string().min(1).default('main') to z.string().min(1).optional(). An explicit value still wins; when omitted, it now resolves the repo's live default branch instead of silently targeting main (#473). Matters for any repo whose default branch isn't main (e.g. release/1.0.0).
  • Internal-only, no signature/output change: fetch-ci-trust-signal-github's branch-protection probe (backs wave_ci_trust_level) now probes the live default branch instead of a hardcoded main (#473). FlightDeck event emission was wired into commutativity_verify, drift_check_path_exists, drift_check_symbol_exists, drift_files_changed, ci_wait_run, pr_wait_ci, wave_ci_trust_level, pr_merge, and wave_finalize (#464) — fire-and-forget telemetry to ~/.claude/status/events.jsonl/FlightDeck ingest; every emit runs after the handler's normal work and never alters the response or control flow.
  • Server startupSERVER_VERSION now derives from the injected build tag (git describe, e.g. 2.1.0) instead of a hardcoded '1.0.0'; uncompiled dev runs report 0.0.0-dev. A new one-time, non-blocking deploy_freshness check compares the running binary's embedded build SHA against the server's own latest GitHub release and emits a single warn-level log line if the binary is stale (#482, closes #447) — network-optional, degrades silently if gh/network/releases are unavailable, and answers initialize in ~150ms even while the freshness check is in flight.

Fixed

  • ci_wait_run / wave trust gate (#478) — Fixed a live false-pass: GitLab skips the branch pipeline on a merge commit, and the status mapping treated skipped as success, so a kahuna merge commit's gate could report final_status: "success" for a pipeline that never ran. Also closed a "freshness by absence" gap where a green merge-result run for a previous commit could satisfy the gate for a PR/MR whose head had since moved — the run is now re-validated against the anchor before grading.
  • ci_wait_run (#484) — Fixed a silent full-timeout_sec hang: with expected_sha set, a transient miss on the first CI-run poll used to consume the entire (typically 1800s) timeout with zero partial output before failing; now bounded to ~180s with an actionable error.
  • ibm (#481) — Fixed a false compliance pass where a branch not checked out in the server's cwd got its issue number looked up against the cwd's repo, matching an unrelated same-numbered issue in the wrong repository.
  • work_item (#479) — Fixed a GitHub-only taxonomy leak where an issue created with type: 'epic' plus a caller-supplied type::plan label ended up carrying both labels (GitHub has no scoped-label mutual exclusion, unlike GitLab).
  • branch_guard (#480, shipped in #485) — Fixed the same cwd-branch/foreign-repo pairing trap as the ibm fix, scoped to role:'base': a repo given without a branch no longer infers the cwd's current branch and resolves it against a repository it may not belong to.
  • Security (#468, #450, shipped in #485) — fast-uri bumped to ^3.1.2 (resolves 3.1.3) and hono to ^4.12.25 (resolves 4.12.30), patching CVE-2026-6321, CVE-2026-6322, and CVE-2026-54290. trivy fs --severity HIGH,CRITICAL: 0 findings.