From ffebeb3e24c76489d259540e2ae8ea315649e94c Mon Sep 17 00:00:00 2001 From: Arjun Mehta Date: Wed, 5 Aug 2026 23:02:43 -0500 Subject: [PATCH] [skills] iterate-pr 2.4.0: never report an unfetched PR as a clean one The feedback fetcher could report `needs_attention: 0` and exit 0 while the PR held real, unaddressed review feedback. A run that trusted that output merged unreviewed code, and nothing in the output said so. Root cause: an empty response and an undelivered one were treated the same. `get_review_threads` did `if not isinstance(result, dict): break`, so any non-dict payload - including `gh` exiting 0 with empty stdout - silently yielded zero threads and a clean-looking summary. The REST channels had the identical inversion via `flatten_pages`, which returned `[]` for any non-list. Fixed at the transport layer rather than the call sites: each of the three feedback channels (inline review threads, PR conversation comments, review bodies) must now *deliver*. A non-zero exit, an exit-0-with-no-output, or an unexpected shape is an error, never an absence. On error the script exits non-zero and emits `status: "error"` with `summary` and `feedback` explicitly null, so a caller reading only stdout cannot mistake a failed lookup for a clean PR. Because a future silent-empty path would look exactly like a clean PR again, a count probe backstops it: when a channel comes back empty, the script asks GitHub how many records that channel holds and fails with the channel named and both numbers shown if the server disagrees. It runs only when something is already empty, so a genuinely quiet PR costs nothing extra and still reports `status: "ok"`. Also converged the two skill lineages into one copy at 2.4.0: - Script paths corrected from `.claude/skills/...` to `.agents/skills/...` (11 references). `.claude/skills` is a symlink in some repos but is absent on a Windows checkout with `core.symlinks=false`, so `.agents/` is canonical. - Release steps are repo-neutral - the repo is resolved from the checkout, and a repository's own release skill takes precedence when it ships one. - `full` / `full-release` are documented and honored as synonyms for `--merge` / `--merge --release`. `full` previously matched no rule in the mode-hint precedence and silently fell through to non-merging default mode. Validated against six meshery/meshery PRs holding 20 review threads (#21146=10, #21145=3, #21168=2, #21144=2, #21140=2, #21147=1): 20/20 found, per-PR counts exact. Both silent-empty paths now exit non-zero, and eight genuinely quiet PRs still report `status: "ok"` with no false alarm. Also removes committed __pycache__ bytecode from this repo's copy of the skill. It is compiled from the very scripts replaced here, so it is stale on arrival, and it left the skill directory differing between repos: .agents/skills/iterate-pr/scripts/__pycache__/fetch_pr_checks.cpython-314.pyc .agents/skills/iterate-pr/scripts/__pycache__/fetch_pr_feedback.cpython-314.pyc Signed-off-by: Arjun Mehta --- .agents/skills/iterate-pr/SKILL.md | 167 +++++- .../fetch_pr_checks.cpython-314.pyc | Bin 10826 -> 0 bytes .../fetch_pr_feedback.cpython-314.pyc | Bin 20211 -> 0 bytes .../iterate-pr/scripts/fetch_pr_checks.py | 66 ++- .../iterate-pr/scripts/fetch_pr_feedback.py | 492 ++++++++++++++---- 5 files changed, 591 insertions(+), 134 deletions(-) delete mode 100644 .agents/skills/iterate-pr/scripts/__pycache__/fetch_pr_checks.cpython-314.pyc delete mode 100644 .agents/skills/iterate-pr/scripts/__pycache__/fetch_pr_feedback.cpython-314.pyc diff --git a/.agents/skills/iterate-pr/SKILL.md b/.agents/skills/iterate-pr/SKILL.md index 1c7151f11..55183aafb 100644 --- a/.agents/skills/iterate-pr/SKILL.md +++ b/.agents/skills/iterate-pr/SKILL.md @@ -4,11 +4,16 @@ description: Iterate on a PR until CI passes. Optionally merge or merge and publ argument-hint: "[--merge] [--release]" metadata: author: leecalcote - version: "2.3.0" + version: "2.4.0" --- # Iterate on PR Until CI Passes +> **2.4.0** - `fetch_pr_feedback.py` no longer reports an empty result as a successful +> fetch. Every path where a feedback channel could come back empty because the request +> did not actually deliver now fails loudly, and a server-side count probe backstops any +> path not yet known. See [Fetch Integrity](#fetch-integrity). + Continuously iterate on the current branch until all CI checks pass and review feedback is addressed. **Requires**: GitHub CLI (`gh`) authenticated. @@ -19,6 +24,11 @@ Continuously iterate on the current branch until all CI checks pass and review f ### Running the Bundled Scripts +Skills live in `.agents/skills/` - that is the canonical path, and the only one used in +this document. Some repos also expose `.claude/skills` as a symlink to it, but that +symlink is not guaranteed: it does not survive a Windows checkout with +`core.symlinks=false`, and not every repo carries it. Always invoke via `.agents/`. + Every script below accepts either runner - they only use the standard library, so no dependency installation is needed either way: @@ -39,23 +49,66 @@ fi The rest of this document shows invocations in the shorter `python3