Skip to content

GitHub Way macro is PR-blind: surface open non-bot PRs + maintainerCanModify #291

Description

@aaronsb

Summary

The GitHub Way's dynamic macro (hooks/ways/softwaredev/delivery/github/macro.sh) is PR-blind. It classifies the repo (solo/pair vs team), scores repo health, and surfaces the session-link/attribution control — but it never looks at open pull requests. So when the GitHub Way fires, Claude has no ambient awareness that a human PR is sitting open, and — critically — no awareness of whether it has the standing to push fixes to that PR's branch (maintainerCanModify).

Proposal: add a fourth, tiered section to the macro that surfaces open non-bot PRs and, for each cross-repo (fork) PR, whether maintainerCanModify is true; and add a matching convention to the GitHub Way prose (github.md) for how to act on that signal.

Motivating example (a real session)

A maintainer sat down to triage PRs on a plugin repo. Seven were open: one substantive human fix and six dependabot bumps. The human had to manually run gh pr list, eyeball authors to separate the real PR from the bots, then separately run gh pr view --json maintainerCanModify to discover the fork PR allowed maintainer edits — which unlocked the whole workflow of fixing review findings directly on the contributor's branch, merging, then using the PR as the communication record.

Every one of those discovery steps is something the macro already has the shape to do proactively. When the GitHub Way triggered on "let's look at pull requests," the ideal ambient context would have been:

**Open PRs**: 1 from contributors, 6 from bots (dependabot)
- #249 fix(dataview): render list/metadata… — @laplaque (fork, maintainerCanModify: ✓ — you can push fixes to their branch)

That single line front-loads two decisions the human/agent otherwise has to excavate by hand.

Why this fits the macro's existing design

The macro is already a tiered, mostly-silent reporter — it fans out parallel gh api calls, then prints nothing when healthy, a brief line when there's a little to say, and a full table only when there's a lot (see the FAIL_COUNT tiering in Section 2). A PR-awareness section should follow the same discipline:

  • Silent when there are no open non-bot PRs (the common case).
  • Brief line(s) when there are a handful — number, title, author, and the fork/maintainerCanModify flag.
  • Cap the list (e.g. first 5) with an "…and N more" tail, matching the macro's other caps.

It also already separates bots from humans conceptually (the solo/team classification), so "filter out bots" is idiomatic here.

Proposed change 1 — macro (macro.sh)

Add an open-PR fan-out alongside the existing parallel gh api batch. A single GraphQL-backed call gets everything needed:

timeout 3 gh pr list --state open --limit 30 \
  --json number,title,author,isCrossRepository,maintainerCanModify,createdAt \
  >"$WORK_DIR/prs.json" 2>/dev/null &

Then, after wait, partition on author.is_bot (this catches dependabot, renovate, pre-commit-ci, github-actions, etc. generically — no hardcoded bot names) and render tiered:

  • Count human PRs vs bot PRs (bots collapsed to a single tally — they have their own hold/triage discipline).
  • For each human PR: #<n> <title> — @<author>, and when isCrossRepository is true, append the maintainerCanModify verdict as an actionable flag: ✓ you can push fixes to their branch / ✗ no push access — merge-then-fix or request changes.

Notes / open questions for implementation:

  • maintainerCanModify is only meaningful for cross-repo PRs; for same-repo branches the mainline push permission (CAN_PUSH, already computed) governs. Report accordingly rather than showing a confusing flag on same-repo PRs.
  • Consider whether to also surface CI/review state (gh pr checks, reviewDecision) — probably out of scope for the ambient line to keep it cheap and quiet; the agent can drill in once it knows the PR exists.
  • Keep the 3s timeout guard and the silent-on-failure pattern the rest of the macro uses.

Proposed change 2 — the GitHub Way (github.md)

The prose covers PRs, review-before-merge, merge strategy, and post-merge cleanup, but has no convention for external-contributor (fork) PRs. Add one, because the right default there is non-obvious and differs from the solo/team default:

External-contributor PRs. When a PR comes from a fork, check maintainerCanModify. If it's true and the review turns up small, well-understood fixes, prefer pushing the fix commits directly to the contributor's branch (gh pr checkout, commit, push) over round-tripping "please change X" review comments — it's faster and keeps the contributor's authorship intact. Then use the PR itself as the communication record: a comment documenting exactly what you changed and why, so the contributor learns what happened. If you lack push access, merge first and fix in a follow-up, but still post to the (now-closed) PR describing the follow-up — the PR remains the durable communication vehicle even after it's closed. Prefer a regular merge (not squash) so the contributor's distinct commits and attribution survive in history.

This is the convention the motivating session arrived at organically; encoding it means the next session reaches for it by default instead of defaulting to "leave review comments and wait."

Scope / effort

  • macro.sh: one added parallel call + a tiered render block (~30-40 lines, mirrors Section 2's structure).
  • github.md: one prose subsection.
  • No new dependencies; gh already required. Suggest area:ways, enhancement, effort:small.

Filed from a downstream project (obsidian-mcp-plugin) after the workflow above played out in practice.

Metadata

Metadata

Assignees

No one assigned

    Labels

    area:waysWays CLI, matching, steering layerenhancementNew feature or request

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions