# list_prs_changes_requested — Open PRs With Passing CI, No Approvals, and Active Changes-Requested Reviews

**Script name:** `list_prs_changes_requested`

**Script location:** [`scripts/list_prs_changes_requested.ts`](../../../scripts/list_prs_changes_requested.ts)

**Invoke:**
```bash
npx --yes tsx .opencode/skills/auto-agents-system/scripts/list_prs_changes_requested.ts \
  --url URL --pat TOKEN --owner OWNER --repo REPO
```

**CRITICAL:** Always invoke the script using bash and the format noted above. **Never** try to use the skill as a task, or invoke it through any other method than by directly calling bash with a command of the form listed above under "Invoke:".


## Synopsis

```
list_prs_changes_requested.ts --url URL --pat TOKEN --owner OWNER --repo REPO
```

Returns all **open** pull requests that have **passing CI**, **zero active
approvals**, and **at least one active `REQUEST_CHANGES` review**. These PRs
have been explicitly reviewed and a reviewer has requested code changes — the
CI is green so the code runs correctly, but the implementation does not yet
satisfy the reviewer's requirements.

This script is a thin wrapper around [`list_prs`](../list_prs/). It
hard-codes the following filters and delegates all logic to that script:

```
state:             'open'
ciStatus:          ['passing']
maxApprovals:      0
hasRequestChanges: true
```


## Arguments

All four arguments are **required**. No optional filter arguments exist — the
filters are baked in and cannot be changed.

| Flag | Type | Description |
|------|------|-------------|
| `--url URL` | string | Forgejo base URL, **no trailing slash** (e.g. `https://git.example.com`) |
| `--pat TOKEN` | string | Personal Access Token with read access to the repository |
| `--owner OWNER` | string | Repository owner or organisation name |
| `--repo REPO` | string | Repository name |
| `-h`, `--help` | — | Print usage to stderr and exit 0 |

Any flag other than these five is **rejected** with exit code 1 and an error
message: `ERROR: Unknown argument: <flag>`. Filter parameters are hard-coded
and cannot be overridden via CLI flags on this wrapper.

### Invalid Argument Combinations

No optional filter arguments are accepted on this script. Passing any
filter-style flag (e.g. `--min-approvals`, `--stale`, `--state`, etc.) causes
immediate exit 1 — those flags are not accepted by this wrapper.


## Hard-Coded Filters

| Filter | Value | Meaning |
|--------|-------|---------|
| `state` | `open` | Only open PRs are returned |
| `ciStatus` | `['passing']` | All CI checks must have succeeded (`ci_status == 'passing'`) |
| `maxApprovals` | `0` | No reviewer has an active non-dismissed `APPROVED` review |
| `hasRequestChanges` | `true` | At least one reviewer's latest non-dismissed review is `REQUEST_CHANGES` |

**"CI passing"** means the Forgejo combined commit-status for the PR's head SHA
returned `state == 'success'`. PRs with `pending`, `failing`, or `unknown` CI
are excluded. This ensures only PRs where the code is functionally correct are
returned — the problem is design/implementation feedback, not broken tests.

**"Zero approvals"** means no reviewer has an active (non-dismissed) `APPROVED`
review as their most recent submission. The per-reviewer deduplication rule
applies: only the reviewer's highest-ID non-dismissed review counts per user.
A reviewer who previously approved but subsequently submitted `REQUEST_CHANGES`
is counted as requesting changes (not approving).

**"Has request changes"** means at least one reviewer's latest non-dismissed
review has state `REQUEST_CHANGES`. The same per-reviewer deduplication applies:
a reviewer who requested changes but later approved is counted as approving
(not requesting changes). Only the most recent non-dismissed review per user
determines their current stance.

The combination of `maxApprovals: 0` and `hasRequestChanges: true` selects PRs
where the reviewer feedback is net-negative: nobody has approved, and at least
one person has actively requested changes.


## Output

Written to **stdout** as a pretty-printed JSON array sorted by `priority_rank`
(highest priority first). Each element is the full Forgejo PR object augmented
with four fields:

| Field | Type | Description |
|-------|------|-------------|
| `approvals_count` | integer | Will always be `0` for results of this script |
| `stale_state` | string | Any value — **not filtered** by this script |
| `ci_status` | string | Will always be `passing` for results of this script |
| `priority_rank` | integer | 0 (highest) through 6 (unlabelled) |
| `priority_label` | string \| null | Matched `Priority/*` label name, or `null` |

An **empty array** `[]` means no open PR currently has passing CI, zero
approvals, and an active changes-requested review — either all such PRs have
been approved, their CI has broken since the review, or the authors have
addressed the feedback.

See [`list_prs`](../list_prs/) for the full output schema documentation.


## Diagnostics / stderr

Progress messages are written to stderr and do not affect the JSON output:

```
Fetching PRs from https://git.example.com/org/repo (state=open)...
Fetched 42 PR(s).  Enriching and filtering...
Fetching HEAD SHAs for 3 unique base branch(es)...
Fetching reviews for 42 PR(s) concurrently (limit=20)...
Fetching CI status for 42 PR(s) concurrently (limit=20)...

Result: 3/42 PR(s) matched the filter criteria.
```


## Exit Codes

| Code | Meaning |
|------|---------|
| 0 | Success — JSON array written to stdout (may be `[]`) |
| 1 | Fatal error — message written to stderr |


## Errors the Script May Throw

| Condition | Behaviour |
|-----------|-----------|
| Missing `--url`, `--pat`, `--owner`, or `--repo` | Exit 1: `ERROR: --<flag> is required` |
| Any unknown flag passed | Exit 1: `ERROR: Unknown argument: <flag>` |
| Forgejo API non-2xx on PR list | Exit 1 with HTTP status and body detail |
| Forgejo API failure for a single branch or review | Warning to stderr; processing continues |
| Network timeout (30 s per request) | Exit 1 with error message |


## When to Use This Script

Use `list_prs_changes_requested` when you need to identify PRs that are
**blocked by reviewer feedback** and are ready to be iterated on. The CI is
passing so the author can focus solely on addressing the review comments rather
than fixing broken tests. Typical use cases:

- **`pr-author-notification-supervisor`** calls this to find PRs where the ball
  is in the author's court — a reviewer has asked for changes and the author
  needs to push new commits. The passing CI signal confirms the PR is otherwise
  healthy.
- A **review-feedback agent** can parse the review comments from each result and
  suggest specific code changes to address the reviewer's concerns, then push
  commits on the author's behalf.
- A **triage agent** can cross-reference this with `updated_at` to find PRs
  where changes were requested long ago and no response has been made, flagging
  them for human follow-up.
- A **monitoring agent** can track the size of this bucket as a measure of
  review-response latency — a growing list suggests authors are not addressing
  review feedback promptly.

### Relationship to the Six-Bucket Pipeline

This script does not correspond to one of the six standard pipeline buckets.
It is an orthogonal view that identifies a specific sub-state within the
"needs review" tier: PRs that have already received review feedback but have
not yet been approved.

```
A PR in list_prs_changes_requested overlaps with buckets 4, 5, and 6
(the three needs-review buckets), filtered to those with passing CI and
an active REQUEST_CHANGES review:

  Bucket 4 — list_prs_needs_review_not_stale        ← may contain PRs from this script (not stale, passing CI)
  Bucket 5 — list_prs_needs_review_stale_clean      ← may contain PRs from this script (stale/clean, passing CI)
  Bucket 6 — list_prs_needs_review_stale_conflicts  ← may contain PRs from this script (stale/conflicts, passing CI)

PRs from list_prs_ready_to_merge (bucket 1) and the approved-stale buckets
(2, 3) cannot appear here because they require approvals_count >= 1.
```


## Usage Examples

```bash
# Standard usage
npx --yes tsx /app/.opencode/skills/auto-agents-system/scripts/list_prs_changes_requested.ts \
  --url https://git.example.com \
  --pat ghp_XXXX \
  --owner my-org \
  --repo my-repo

# Count PRs awaiting author response to review feedback
npx --yes tsx /app/.opencode/skills/auto-agents-system/scripts/list_prs_changes_requested.ts \
  --url https://git.example.com \
  --pat ghp_XXXX \
  --owner my-org \
  --repo my-repo \
  | jq 'length'

# Get PR numbers, titles, and staleness for all changes-requested PRs
npx --yes tsx /app/.opencode/skills/auto-agents-system/scripts/list_prs_changes_requested.ts \
  --url https://git.example.com \
  --pat ghp_XXXX \
  --owner my-org \
  --repo my-repo \
  | jq '[.[] | {number, title, stale_state, ci_status}]'

# Get the highest-priority changes-requested PR
npx --yes tsx /app/.opencode/skills/auto-agents-system/scripts/list_prs_changes_requested.ts \
  --url https://git.example.com \
  --pat ghp_XXXX \
  --owner my-org \
  --repo my-repo \
  | jq 'first'
```


## Agent Usage Examples

### pr-author-notification-supervisor

The supervisor calls this script to find PRs whose authors need to act on
reviewer feedback. It dispatches workers to notify authors or to attempt
automated remediation of the requested changes.

```bash
result=$(npx --yes tsx /app/.opencode/skills/auto-agents-system/scripts/list_prs_changes_requested.ts \
  --url $FORGEJO_URL --pat $FORGEJO_PAT --owner $REPO_OWNER --repo $REPO_NAME)
# If non-empty → iterate and dispatch pr-author-nudge-worker for each PR
```

### human-liaison-pool-supervisor

The human liaison can filter by `updated_at` to surface PRs where review
feedback has gone unaddressed for more than a configured threshold (e.g. 3
days), then post reminder comments or ping the PR author in a team channel.

### review-feedback-agent

An agent tasked with automated code improvement can use this list as its work
queue: for each PR, fetch the review comments, analyse the requested changes,
generate patch commits to address the feedback, and push them to the PR branch.


## Dependencies

- Node.js ≥ 18 (native `fetch` API)
- `npx tsx` for TypeScript execution
- Zero external npm packages
