Repository navigation
fix(OMN-17875): omnibase_core auto-merge arms with the org PAT so dev push workflows fire - #1646
Conversation
…push workflows fire auto-merge.yml armed 'gh pr merge --auto' with the default workflow token. GitHub completes an armed auto-merge as the identity that armed it, and fires no push event for commits authored by that default token, so every push-on-dev workflow was skipped on every PR that landed through this job. Measured 2026-09-04T15:20-15:25Z over the 30 most recently merged dev PRs (#1613-#1645), via gh api "repos/OmniNode-ai/omnibase_core/actions/runs?head_sha=<full-oid>&event=push" --jq .total_count all 20 bot merges had 0 dev-branch push runs; all 10 jonahgabriel merges had 12-14. The human counts are the positive control that makes those zeros evidence of absence rather than a broken query. Swap the two merge-state-mutating steps to secrets.CROSS_REPO_PAT (existing org secret, visibility=all, already consumed by seven workflows in this repo). The read-only pre-check resolve step stays on the default token: it creates no commit. No fallback expression, which would restore the defect silently. Port of omnibase_infra#3178.
|
Measured note for whoever verifies this after it lands — one field behaves differently here than the doctrine text predicts, and it is not a contradiction of the fix. This PR was armed by the current, unfixed job on But So verify on Expected on this PR’s own merge commit, unchanged: Current state: 129 checks pass. The two still pending are |
…#8211) * evidence: OCC companion pass 1 for OmniNode-ai/omnibase_core#1646 * evidence: OCC companion self-bind for #8211 --------- Co-authored-by: node-occ-companion-effect <occ-companion-effect@omninode.ai>
Closes OMN-17875 (AC4 — the
omnibase_coresibling port).Port of omnibase_infra#3178 (merged 2026-09-04T12:32:53Z,
b71159f3e0b1fb59a26c593fa4be2f78118ff51c), which root-caused this defect on the sibling repo. Same change, same rationale, re-measured against this repo's own live data.Finding — measured here, 2026-09-04T15:20–15:25Z
auto-merge.ymlarmedgh pr merge --autowith the default workflow token. GitHub completes an armed auto-merge as the identity that armed it, and fires nopushevent for commits authored by that default token (documented Actions-recursion prevention). Every push-on-devworkflow was therefore skipped on every PR that landed through this job.Query, over the 30 most recently merged
devPRs (#1613–#1645):1bd884e575d6da6f50dbdb93a2c38d4ba830f338525bffc20d0869d191ffb22a3c3184e04edb9e596cccbdbbfeTotals over that window: 20 bot merges, all 20 with zero dev-branch push runs; 10
jonahgabrielmerges, all 12–14.Two of the bot merges (
31e44e9db#1621,9b8b5704b#1615) reporttotal_count: 2, but those two runs areRelease+Propagate config across downstream reposonhead_branchv0.47.1/v0.47.0with actorjonahgabriel— tag pushes that happen to share the commit, not dev-branch pushes. Dev-branch suppression is 20 of 20.Measurement gotcha worth recording:
head_shamust be the full 40-char oid. An abbreviated SHA matches nothing and returns a falsetotal_count: 0— that false zero initially made those two look like clean bot merges. The 12–14 counts on the human merges are the positive control that makes the real zeros evidence of absence rather than a broken query (CLAUDE.md rule 16).What was skipped
Push-on-
devworkflows in this repo:ci.yml,security-scan.yml,cross-repo-validation.yml,precommit-parity-gate.yml,receipt-honesty.yml,omni-standards-compliance.yml,check-db-ownership.yml,check-handshake.yml,check-llm-refs-drift.yml,validator-fsm-handler-drift.yml,validator-no-plugin-daemon-classes.yml,validator-runtime-profiles.yml, pluspropagate-config.yml(push, path-filtered, no branch filter).release.ymlis not in the skipped set here: its only push trigger istags: ['v[0-9]*.[0-9]*.[0-9]*']with nobranches:key, so a dev merge never fires it regardless of merger identity. (This corrects the ticket body's "check its trigger" note for this repo, matching the same correction #3178 made for infra.)Mechanism, and why not an App token
A GitHub App installation token is not a substitute. The OMN-16373 controlled probe (2026-08-22, branch
test/omn16373-suppression-probe-1, since deleted) isolated the identities against a push-triggered marker workflow:jonahgabrielauth: commitfd534b2a→ marker workflow FIRED (run32562988366,event=push,conclusion=success).onexbot-occ-writer[bot]: commit38ffe1f4on the same branch → marker workflow did NOT fire; zeroevent=pushruns at that head SHA.omninode_infra/.github/workflows/auto-merge.ymlis the precedent — it kept the org PAT for exactly this property (OMN-15769, re-affirmed by OMN-16373) and its dev merges have never suffered this suppression.Exact changes
.github/workflows/auto-merge.yml(+109/−2):Resolve PR number and author without checkoutpre-checkgh pr view/gh apireads), creates no commit, so the suppression mechanism cannot applyEnable auto-mergeauto-mergesecrets.CROSS_REPO_PAT— this is the step that arms the mergeEnqueue armed PR and verify it entered the queueauto-mergesecrets.CROSS_REPO_PAT— mutates merge state twice:gh pr update-branchpushes a merge commit onto the PR head branch, andenqueuePullRequesthands the merge to a queuePlus a header comment block carrying the measurements above, the OMN-16373 probe result, and an explicit "do not modernise this back to the default token or an App token" instruction, citing OMN-17875 / OMN-16373.
No new credential is minted.
CROSS_REPO_PATis an existing org secret withvisibility: all— readback 2026-09-04T15:19Z,gh api orgs/OmniNode-ai/actions/secrets/CROSS_REPO_PAT→{"name":"CROSS_REPO_PAT","created_at":"2026-03-03T19:03:03Z","visibility":"all"}. This repo already consumes it inci.yml,release.yml,propagate-config.yml,publish-downstream-pin-bump.yml,cr-thread-gate.yml,cr-thread-gate-caller.ymlanddependency-cascade.yml.No fallback expression was added. A fallback to the default token would restore the defect silently on any run where the PAT is unavailable — precisely the invisible-failure shape this ticket exists to remove.
Precondition verified before porting:
gh api repos/OmniNode-ai/omnibase_core --jq .allow_auto_merge→true,squashonly,default_branch: dev. So the arming step is live here (not the known-red unconditional---autodefect that affects the repos where auto-merge is disabled).Enforcement (CLAUDE.md rule 5)
This repo already had a policy test pinning this workflow —
tests/unit/validation/test_auto_merge_workflow_shape.py— so rather than adding a second file that could drift from it (infra had none and needed a new one), the 7 new assertions are appended there, keeping one home forauto-merge.ymlshape:secrets.CROSS_REPO_PAT(parametrized, 2 cases);pre-checkresolve step stays on the default token and performs no mutating verb;Negative control (rule 16 — a passing test is not evidence until it is shown to bite): reverting both tokens produces
4 failed, 13 passed; the fix in place produces17 passed.Local verification
uv run pytest tests/unit/validation/test_auto_merge_workflow_shape.py -q→17 passed(10 pre-existing + 7 new)tests/unit/validation/test_validator_github_token_env_reads.py+tests/ci/test_workflow_uses_refs_resolve.py→31 passeduv run ruff format/uv run ruff check→ cleanpre-commitfull hook set on commit → all passed1901 passed in 293.63s,[prepush-smart-tests] impacted tests passed; allowing push.mypy --strictreports 9 errors in the test file, all of them pre-existing onorigin/dev(identical count and lines against the unmodified file) and all in the pre-existing helpers, none in the appended block.tests/is explicitly outside this repo's gated mypy scope — themypy-type-checkhook isfiles: ^src/omnibase_core/.*\.py$withexclude: ^(tests/|...). Nothing was suppressed to achieve that.Expected: this PR's own merge will still fire no push workflows
This PR will be armed and merged by the current, unfixed job — a workflow's
pull_request/check_suiterun uses the base-branch definition, not the PR's, so the version ofauto-merge.ymldoing the arming is the one ondev. This merge commit will therefore show0push-event runs, exactly like the 20 bot merges tabulated above. That is expected, it is the defect being fixed, and it is not a regression introduced here. Record it as the last suppressed merge on this repo; every merge after it should be non-zero.First post-merge verification
gh api "repos/OmniNode-ai/omnibase_core/actions/runs?head_sha=<next-merge-sha>&event=push" --jq .total_count→ expected non-zero (12–14, matching the human-merge baseline), where the same query on every bot merge before this PR returned 0.gh api repos/OmniNode-ai/omnibase_core/pulls/<next-pr> --jq .merged_by.loginshould readjonahgabriel(the PAT owner, aUser) rather thangithub-actions[bot].Scope
omnibase_coreonly. Nosrc/code is touched — this changes CI workflow arming credentials and their policy test. The remaining AC4 siblings (omniclaude— claimed by a peer lane,omnimarket,omnimemory,onex_change_control,omnidash) stay on the ticket. No boot code is touched, so the codex-owned staging boot tickets are unaffected.Evidence-Ticket: OMN-17875
Evidence-Source: OCC#8211