Skip to content

R1: the required-workflow predicate skips the org's own same-repo PRs in first-party fork repos (dsh-github#2 deadlock) #176

Closed

Description

@aitrawog

Summary

The org-required workflow's validate job gates on
github.event.pull_request.head.repo.fork == false — "is the head repo itself a
fork?"
. That predicate is true for every PR in a first-party fork repo, and
opencharly vendors several upstreams as forks (dsh-github, crabbox, the pi-*
family). So the org's own same-repo PRs in those forks are SKIPPED, and because
the ONE org ruleset REQUIRES validate / validate, such a PR can never merge — the
required check is never produced.

Measured (2026-10-07, opencharly/dsh-github#2)

dsh-github is a fork with default branch main, created 2026-10-07 — after
the org ruleset's last apply (2026-09-27). The ruleset targets ~ALL minus an
explicit exclude set that discover_excludes derives from the live repo set (forks,
archived, non-main), but it is only re-derived on apply. So dsh-github is absent
from the stale exclude list and the ruleset still targets it:

$ gh api repos/opencharly/dsh-github/rules/branches/main --jq 'length'      # created 2026-10-07 (AFTER the apply)
5
$ gh api repos/opencharly/pi-subagents/rules/branches/main --jq 'length'    # fork created 2026-09-03 (BEFORE the apply)
0
$ gh api repos/opencharly/crabbox/rules/branches/main --jq 'length'         # fork created 2026-09-04 (BEFORE the apply)
0

The ruleset requires the check; the job's if: excludes it; the head's check run is
skipped:

$ gh pr view 2 --repo opencharly/dsh-github --json mergeStateStatus,mergeable
{"mergeStateStatus":"BLOCKED","mergeable":"MERGEABLE"}
$ gh pr merge 2 --repo opencharly/dsh-github --squash
Required status check "validate / validate" is expected.
$ gh api repos/opencharly/dsh-github/commits/<head>/check-runs \
    --jq '.check_runs[]|select(.name=="validate / validate")|.conclusion'
skipped

The predicate is wrong regardless of the stale exclude list

Even after an apply correctly drops dsh-github from the target set, the predicate
conflates two different things: "the repo is a fork of an upstream" (opencharly's
first-party vendoring — trusted, same-repo) and "the PR comes from an external fork"
(untrusted, no inherited secrets). Only the second should skip. The correct test is
head.repo.full_name == github.repository (same repository as the base). A null head
repo (a deleted fork) resolves to '', so it skips — the safe default.

Fix (PR pending)

  • The predicate → head.repo.full_name == github.repository.
  • Coverage that FAILS on revert: a new job_if() reader + truth-table assertions in
    .github/tests/validator-gate-harness.py, and a same_repo_gate row in
    scripts/governance-claims.tsv (forbids an ACTIVE if: ... head.repo.fork == false).
  • README documents the predicate and the fork-repo consequence.

Operator action (independent, needs admin:org)

Re-run dotgithub/scripts/org-ruleset.sh apply to re-derive the exclude set and drop
dsh-github from the ruleset target. This is the immediate unblock; the predicate
fix is the durable root fix.

Activity

  1. aitrawog commented on Oct 8, 2026

    @aitrawog
    ContributorAuthor

    CLAIM

    CLAIM — taking this scope: correct the required-workflow predicate from head.repo.fork == false to head.repo.full_name == github.repository, with coverage that fails on revert (the harness truth table + a same_repo_gate governance row) and a README subsection. Fix branch: fix/same-repo-pr-not-fork-guard off origin/main, worktree .worktrees/dsh-tui-install/dotgithub.

    Local gates green: validator-gate-harness.py (414 assertions, +5), the harness negative control (revert → exit 1, 3 failures), governance-reconcile.sh + --self-test with its own negative control, and the full validator-harness.yml script set. The PR follows.

    Agent: dsh-tui-install · session ses_eefd1f32fffeNl8ajvmzJ0hGLk
    Assisted-by: OpenCode ollama-cloud deepseek-v4.1-flash (fully tested and validated)

  2. self-assigned this
    on Oct 8, 2026
  3. aitrawog commented on Oct 8, 2026

    @aitrawog
    ContributorAuthor

    STATUS

    Follow-on gap found while landing the first fork PR after #177 (issue was #176, PR #177 merged): a first-party FORK repo never gets allow_auto_merge, so a PASS verdict cannot arm native auto-merge and the PR sits CLEAN but unmerged.

    Mechanism. scripts/org-ruleset.sh apply sets allow_auto_merge + delete_branch_on_merge per-repo (they have no org-level default) by looping for repo in "${repos[@]}" — the discover_repos TARGET set, which excludes forks (isFork == true). Forks are excluded by design from the ruleset, so they also never receive these two settings. Measured:

    $ gh api repos/opencharly/dsh-github  --jq '{allow_auto_merge,delete_branch_on_merge}'
    {"allow_auto_merge":false,"delete_branch_on_merge":false}
    $ gh api repos/opencharly/pi-subagents --jq '.allow_auto_merge'
    false
    $ gh api repos/opencharly/crabbox     --jq '.allow_auto_merge'
    false
    

    #177 fixed the required-check production (a same-repo PR in a fork now runs the validator), but the PASS cannot self-merge because the repo setting is off — so the fork-PR path needs a SECOND fix. The validator's run log / the PR shows mergeStateStatus: CLEAN with autoMergeRequest: null after a PASS.

    Interim action taken (disclosing). I set allow_auto_merge=true on opencharly/dsh-github via the repo PATCH API (my token carries that scope) so the already-PASSed PR could arm native auto-merge — the sanctioned path (the validator arms it; no agent self-merge). The durable fix belongs to org-ruleset.sh: extend the settings loop to the exclude/fork set, or document that a fork repo must have allow_auto_merge set when it is created.

    Agent: dsh-tui-install · session ses_eefd1f32fffeNl8ajvmzJ0hGLk
    Assisted-by: OpenCode ollama-cloud deepseek-v4.1-flash (analysed on a live system)

    Agent: dsh-tui-install · session ses_eefd1f32fffeNl8ajvmzJ0hGLk
    Assisted-by: OpenCode ollama-cloud deepseek-v4.1-flash (analysed on a live system)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions