# list_prs_no_active_review_ci_passing — Open PRs With Passing CI, No Approvals, and No Active REQUEST_CHANGES Reviews

**Script name:** `list_prs_no_active_review_ci_passing`

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

**Invoke:**
```bash
npx --yes tsx .opencode/skills/auto-agents-system/scripts/list_prs_no_active_review_ci_passing.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_no_active_review_ci_passing.ts --url URL --pat TOKEN --owner OWNER --repo REPO
```

Returns all **open** pull requests that have **passing CI**, **zero active
approvals**, and **no active `REQUEST_CHANGES` reviews**. This captures PRs
waiting for a fresh review with no outstanding reviewer feedback. Includes:
PRs never reviewed, PRs with only `COMMENT` reviews, and PRs with dismissed
`REQUEST_CHANGES`.

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: false
```


## 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 script.

### Invalid Argument Combinations

There are no valid filter-combination errors since no optional filters exist.
However, passing any filter-style flag (e.g. `--min-approvals`, `--stale`, etc.)
will cause an 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` | `false` | No 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.

**"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.

**"No request changes"** means no reviewer's latest non-dismissed review has
state `REQUEST_CHANGES`. This includes PRs that have never been reviewed, PRs
with only `COMMENT` reviews, and PRs where all previous `REQUEST_CHANGES`
reviews have been dismissed.


## 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 no active REQUEST_CHANGES reviews.

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: 5/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_no_active_review_ci_passing` when you need to identify PRs that
are **ready for a first review with green CI**. No reviewer has submitted a
`REQUEST_CHANGES` review, and all CI checks are passing — a reviewer can
perform a full code review without blockers. Typical use cases:

- **`pr-review-supervisor`** uses this as its **second-priority** review
  bucket (after re-reviews): fresh PRs with green CI are the next best
  candidates after re-reviews of addressed feedback.
- A **review dispatcher** agent can assign these to available reviewers
  since no prior feedback needs to be considered first.
- A **monitoring agent** can track this bucket to detect growing backlogs
  of unreviewed PRs with healthy CI.

### Position in the Review Pipeline

```
The review pipeline defines five non-overlapping buckets for open PRs
with zero approvals (excluding unaddressed REQUEST_CHANGES and CI pending):

  Bucket 1 — list_prs_addressed_changes_ci_passing    (addressed + CI passing)
  Bucket 2 — list_prs_no_active_review_ci_passing      (no review + CI passing)     ← THIS SCRIPT
  Bucket 3 — list_prs_addressed_changes_ci_failing     (addressed + CI failing)
  Bucket 4 — list_prs_no_active_review_ci_failing      (no review + CI failing)
  Bucket 5 — list_prs_missing_ci_checks                (no CI checks reported)
```

Workflow for a PR in this bucket once review passes:
```
Reviewer approves  →  PR moves to list_prs_ready_to_merge  →  merge_pr
```


## Usage Examples

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

# Count how many PRs are waiting for first review
npx --yes tsx /app/.opencode/skills/auto-agents-system/scripts/list_prs_no_active_review_ci_passing.ts \
  --url https://git.example.com \
  --pat ghp_XXXX \
  --owner my-org \
  --repo my-repo \
  | jq 'length'

# Get just the PR numbers and titles
npx --yes tsx /app/.opencode/skills/auto-agents-system/scripts/list_prs_no_active_review_ci_passing.ts \
  --url https://git.example.com \
  --pat ghp_XXXX \
  --owner my-org \
  --repo my-repo \
  | jq '[.[] | {number, title}]'
```


## Agent Usage Examples

### pr-review-supervisor

The supervisor calls this script as the fetch algorithm for its second-priority
work group (`no_active_review_ci_passing`). Each result is dispatched to a
`pr-review-worker` for a full first review.

```bash
npx --yes tsx /app/.opencode/skills/auto-agents-system/scripts/list_prs_no_active_review_ci_passing.ts \
  --url $FORGEJO_URL \
  --pat $FORGEJO_PAT \
  --owner $REPO_OWNER \
  --repo $REPO_NAME
```


## Dependencies

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