# list_prs_ci_failing — Open PRs With Failing CI, Any Review Status

**Script name:** `list_prs_ci_failing`

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

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

Returns all **open** pull requests whose CI is **failing** — i.e. at least one
commit status check has reported `failure`, `error`, or `warning` for the PR's
head SHA. No review-status filter is applied: the result spans PRs with zero
approvals, PRs currently under review, and already-approved PRs alike.

PRs with `pending` CI (still running), `passing` CI (all checks succeeded), or
`unknown` CI (no checks reported yet) are excluded. Only `ci_status == 'failing'`
is returned.

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: ['failing']
(no approval filter — all review states are included)
```


## 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` | `['failing']` | At least one CI check reported failure, error, or warning |

**"CI failing"** means the Forgejo combined commit-status for the PR's head SHA
returned `state` of `failure`, `error`, or `warning`. This covers any situation
where at least one check has not succeeded:

- `failure` — a check explicitly reported a failed result
- `error`   — a check reported an error (e.g. infrastructure problem)
- `warning` — a check reported a warning state

PRs with `pending` CI are **not** included — those are still running and have
not yet failed. PRs with `unknown` CI (no checks registered at all) are also
**not** included. Only confirmed failures are returned.

**No approval filter** is applied. A PR appears in this list regardless of
whether it has zero approvals, is under review, or is already approved. A
CI failure is actionable at any point in the review pipeline.


## 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 | Any value — **not filtered** by this script |
| `stale_state` | string | Any value — **not filtered** by this script |
| `ci_status` | string | Will always be `failing` 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 failing CI — the
repository's CI is fully green.

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: 4/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_ci_failing` when you need a complete picture of all open PRs
currently blocked by CI failures, irrespective of their review status. Typical
use cases:

- **`ci-blocker-pool-supervisor`** calls this to get the full set of PRs that
  need CI investigation. Sorting by `priority_rank` ensures that
  `Priority/CI Blocker`-labelled PRs are addressed first.
- A **triage agent** can cross-reference this list with recently-merged commits
  to identify which base-branch changes broke CI for PRs that were previously
  green.
- A **monitoring agent** can track the size of this bucket over time as a
  repository health metric — a growing list indicates accumulating CI debt.
- A **notification agent** can alert PR authors when their PR enters this bucket,
  prompting them to investigate their CI failures.

### Relationship to the Six-Bucket Pipeline

The six-bucket pipeline scripts (`list_prs_ready_to_merge`, `list_prs_stale_*`,
`list_prs_needs_review_*`) do not filter on CI status — they classify PRs by
approval state and staleness. `list_prs_ci_failing` cuts across all buckets:

```
A PR in any of the six buckets may simultaneously appear in list_prs_ci_failing.

list_prs_ready_to_merge  explicitly requires CI passing — its results never
                          overlap with list_prs_ci_failing.

All other five buckets (stale/needs-review) accept any CI status, so their
results may partially overlap with list_prs_ci_failing.
```

This cross-cutting view is intentional: CI failures are urgent regardless of
where a PR sits in the approval/staleness pipeline.


## Usage Examples

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

# Count open PRs with failing CI
npx --yes tsx /app/.opencode/skills/auto-agents-system/scripts/list_prs_ci_failing.ts \
  --url https://git.example.com \
  --pat ghp_XXXX \
  --owner my-org \
  --repo my-repo \
  | jq 'length'

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

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


## Agent Usage Examples

### ci-blocker-pool-supervisor

The supervisor calls this script to discover all PRs with broken CI. It then
dispatches workers to investigate and repair each failing PR, sorted by
priority so `Priority/CI Blocker` PRs are handled first.

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

### system-watchdog-pool-supervisor

The watchdog can call this periodically to ensure CI failures are not
accumulating. If the result grows across consecutive cycles without being
addressed, the watchdog may escalate or alert human operators.

### human-liaison-pool-supervisor

The human liaison can filter results by `created_at` or `updated_at` to
identify PRs that have had failing CI for an extended period, then post
comments or ping PR authors to take action.


## Dependencies

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