Compare commits

..

3 Commits

Author SHA1 Message Date
HAL9000 8077d027e9 Merge master into PR #9247 - keep PR branch CHANGELOG with #9060 entry 2026-04-17 07:34:27 +00:00
HAL9000 06d5474957 docs(changelog): Add entry for #9060 error suppression fix
CI / lint (pull_request) Successful in 27s
CI / typecheck (pull_request) Successful in 52s
CI / quality (pull_request) Successful in 46s
CI / security (pull_request) Successful in 53s
CI / build (pull_request) Successful in 23s
CI / helm (pull_request) Successful in 29s
CI / push-validation (pull_request) Successful in 19s
CI / e2e_tests (pull_request) Successful in 3m45s
CI / integration_tests (pull_request) Successful in 6m45s
CI / unit_tests (pull_request) Successful in 7m50s
CI / docker (pull_request) Successful in 1m43s
CI / coverage (pull_request) Successful in 8m4s
CI / status-check (pull_request) Successful in 1s
2026-04-15 15:50:56 +00:00
HAL9000 55455304be fix(application): Remove error suppression in reactive_registry_adapter.py
Remove two try...except Exception: blocks that were silently suppressing
errors in register_registry_agents(), violating CONTRIBUTING.md fail-fast
policy.

Changes:
- Remove try/except around actor_registry.list_actors() call; exceptions
  now propagate to the caller instead of silently returning
- Remove try/except around route_bridge.agents refresh; exceptions now
  propagate instead of silently resetting to empty dict
- Update docstring to document the fail-fast propagation behaviour
- Update Behave scenarios to verify exceptions propagate correctly:
  * RuntimeError from list_actors() propagates
  * AttributeError from actors without .name attribute propagates
  * TypeError from None actors list propagates

Closes #9060
2026-04-15 15:40:58 +00:00
219 changed files with 7503 additions and 9838 deletions
@@ -6,8 +6,7 @@ description: >
mode: subagent
hidden: true
temperature: 0.2
model: anthropic/claude-haiku-4-5
reasoningEffort: "max"
model: anthropic/claude-sonnet-4-6
color: "#E74C3C"
permission:
"*": deny
+1 -2
View File
@@ -6,8 +6,7 @@ description: >
mode: subagent
hidden: true
temperature: 0.2
model: anthropic/claude-haiku-4-5
reasoningEffort: "max"
model: anthropic/claude-sonnet-4-6
permission:
"*": deny
"doom_loop": deny
-1
View File
@@ -10,7 +10,6 @@ mode: subagent
hidden: true
temperature: 0.1
model: anthropic/claude-haiku-4-5
reasoningEffort: "max"
permission:
"*": deny
"doom_loop": deny
@@ -7,8 +7,7 @@ description: >
mode: subagent
hidden: true
temperature: 0.1
model: anthropic/claude-haiku-4-5
reasoningEffort: "max"
model: anthropic/claude-sonnet-4-6
color: warning
permission:
"*": deny
@@ -6,8 +6,7 @@ description: >
mode: subagent
hidden: true
temperature: 0.1
model: anthropic/claude-haiku-4-5
reasoningEffort: "max"
model: anthropic/claude-sonnet-4-6
permission:
"*": deny
"doom_loop": deny
@@ -7,8 +7,7 @@ description: >
mode: subagent
hidden: true
temperature: 0.3
model: anthropic/claude-haiku-4-5
reasoningEffort: "max"
model: anthropic/claude-sonnet-4-6
color: primary
permission:
"*": deny
+1 -2
View File
@@ -6,8 +6,7 @@ description: >
mode: subagent
hidden: true
temperature: 0.3
model: anthropic/claude-haiku-4-5
reasoningEffort: "max"
model: anthropic/claude-sonnet-4-6
permission:
"*": deny
"doom_loop": deny
+1 -2
View File
@@ -5,8 +5,7 @@ description: >
mode: subagent
hidden: true
temperature: 0.2
model: anthropic/claude-haiku-4-5
reasoningEffort: "max"
model: anthropic/claude-sonnet-4-6
color: success
permission:
"*": deny
@@ -6,7 +6,6 @@ mode: subagent
hidden: true
temperature: 0.1
model: anthropic/claude-haiku-4-5
reasoningEffort: "max"
color: "#DC2626"
permission:
"*": deny
-1
View File
@@ -6,7 +6,6 @@ mode: subagent
hidden: true
temperature: 0.1
model: anthropic/claude-haiku-4-5
reasoningEffort: "max"
color: "#DC2626"
permission:
"*": deny
-1
View File
@@ -8,7 +8,6 @@ mode: subagent
hidden: true
temperature: 0.1
model: anthropic/claude-haiku-4-5
reasoningEffort: "max"
color: "#DC2626"
permission:
"*": deny
-1
View File
@@ -7,7 +7,6 @@ mode: subagent
hidden: true
temperature: 0.1
model: anthropic/claude-haiku-4-5
reasoningEffort: "max"
color: "#DC2626"
permission:
"*": deny
+1 -2
View File
@@ -5,8 +5,7 @@ description: >
mode: subagent
hidden: true
temperature: 0.1
model: anthropic/claude-haiku-4-5
reasoningEffort: "max"
model: anthropic/claude-sonnet-4-6
color: error
permission:
"*": deny
+1 -2
View File
@@ -6,8 +6,7 @@ description: >
mode: subagent
hidden: true
temperature: 0.1
model: anthropic/claude-haiku-4-5
reasoningEffort: "max"
model: anthropic/claude-sonnet-4-6
permission:
"*": deny
"doom_loop": deny
-1
View File
@@ -7,7 +7,6 @@ mode: subagent
hidden: true
temperature: 0.1
model: anthropic/claude-haiku-4-5
reasoningEffort: "max"
color: "#6B7280"
permission:
"*": deny
-1
View File
@@ -7,7 +7,6 @@ mode: subagent
hidden: true
temperature: 0.1
model: anthropic/claude-haiku-4-5
reasoningEffort: "max"
color: info
permission:
"*": deny
@@ -6,8 +6,7 @@ description: >
mode: subagent
hidden: true
temperature: 0.3
model: anthropic/claude-haiku-4-5
reasoningEffort: "max"
model: anthropic/claude-sonnet-4-6
color: "#9B59B6"
permission:
"*": deny
+1 -2
View File
@@ -5,8 +5,7 @@ description: >
mode: subagent
hidden: true
temperature: 0.3
model: anthropic/claude-haiku-4-5
reasoningEffort: "max"
model: anthropic/claude-sonnet-4-6
permission:
"*": deny
"doom_loop": deny
@@ -6,8 +6,7 @@ description: >
mode: subagent
hidden: true
temperature: 0.2
model: anthropic/claude-haiku-4-5
reasoningEffort: "max"
model: anthropic/claude-sonnet-4-6
color: accent
permission:
"*": deny
+1 -2
View File
@@ -6,8 +6,7 @@ description: >
mode: subagent
hidden: true
temperature: 0.2
model: anthropic/claude-haiku-4-5
reasoningEffort: "max"
model: anthropic/claude-sonnet-4-6
permission:
"*": deny
"doom_loop": deny
+1 -2
View File
@@ -5,8 +5,7 @@ description: >
mode: subagent
hidden: true
temperature: 0.2
model: anthropic/claude-haiku-4-5
reasoningEffort: "max"
model: anthropic/claude-sonnet-4-6
color: info
permission:
"*": deny
+1 -2
View File
@@ -4,8 +4,7 @@ description: >
CI failure resolution and review feedback handling. User-facing.
mode: primary
temperature: 0.2
model: anthropic/claude-haiku-4-5
reasoningEffort: "max"
model: anthropic/claude-sonnet-4-6
color: "#059669"
permission:
"*": deny
+1 -2
View File
@@ -7,8 +7,7 @@ description: >
mode: subagent
hidden: true
temperature: 0.1
model: anthropic/claude-haiku-4-5
reasoningEffort: "max"
model: anthropic/claude-sonnet-4-6
color: "#9B59B6"
permission:
"*": deny
@@ -7,7 +7,6 @@ mode: subagent
hidden: true
temperature: 0.1
model: anthropic/claude-haiku-4-5
reasoningEffort: "max"
color: "#6B7280"
permission:
"*": deny
-1
View File
@@ -7,7 +7,6 @@ mode: subagent
hidden: true
temperature: 0.1
model: anthropic/claude-haiku-4-5
reasoningEffort: "max"
color: "#10B981"
permission:
"*": deny
-188
View File
@@ -1,188 +0,0 @@
---
description: >
Git rebase helper. Rebases a branch onto a target branch (usually master)
and resolves any merge conflicts that arise. Ensures the rebase completes
fully by running git rebase --continue for every conflicting commit. Does
NOT push — the caller is responsible for pushing after this agent exits.
mode: subagent
hidden: true
temperature: 0.1
model: anthropic/claude-haiku-4-5
reasoningEffort: "max"
color: "#F59E0B"
permission:
"*": deny
"doom_loop": deny
question: deny
"sequential-thinking*": allow
read: "allow"
grep: "allow"
glob: "allow"
edit:
"*": deny
"/tmp/**": allow
external_directory:
"/tmp/**": allow
webfetch: allow
websearch: allow
codesearch: allow
bash:
"*": deny
"git *": allow
"git push *": deny
"git * --force *": deny
"ls *": allow
"cat *": allow
"find *": allow
"grep *": allow
# Block ALL commands that could hit the label creation endpoints
"*api/v1/orgs/*/labels*": deny
"*api/v1/repos/*/labels*": deny
"*https://git.cleverthis.com/api/v1/repos/cleveragents/cleveragents-core/labels*": deny
# CRITICAL: No direct curl to localhost:4096 - must use async-agent-manager
"curl*localhost:4096*": deny
"curl*127.0.0.1:4096*": deny
task:
"*": deny
---
# Git Rebase Helper
You rebase a branch onto a target branch and resolve any merge conflicts that arise. You do not push — your caller handles that after you exit.
## What You Receive
Your prompt includes:
- **working_directory** — absolute path to the git clone
- **branch** — the feature branch to rebase (the branch whose history is rewritten)
- **base_branch** — the branch to rebase onto (usually `master` or `origin/master`)
- **git email** and **git name** — git author identity (optional; configure if provided)
## Rebase Procedure
Follow these steps exactly:
### 1. Prepare
```bash
# Optionally configure identity if provided
git -C "$WORK_DIR" config user.name "$GIT_USER_NAME"
git -C "$WORK_DIR" config user.email "$GIT_USER_EMAIL"
# Fetch the latest state of all branches
git -C "$WORK_DIR" fetch origin
# Switch to the feature branch
git -C "$WORK_DIR" checkout "$BRANCH"
# Confirm current state before starting
git -C "$WORK_DIR" log --oneline -5
git -C "$WORK_DIR" status
```
### 2. Start the rebase
```bash
git -C "$WORK_DIR" rebase "origin/$BASE_BRANCH"
```
If the rebase exits cleanly with no conflicts, skip to step 5 (Verify).
### 3. Resolve conflicts (repeat for every conflicting commit)
When the rebase pauses due to conflicts:
**a. Identify all conflicted files:**
```bash
git -C "$WORK_DIR" diff --name-only --diff-filter=U
```
**b. For each conflicted file:**
Read the file to understand what both sides changed:
```bash
cat "$WORK_DIR/$FILE"
```
The conflict markers look like:
```
<<<<<<< HEAD
(incoming from base_branch)
=======
(original from the rebased commit)
>>>>>>> <commit-sha> (<commit message>)
```
Study the recent git history on both sides to understand the intent:
```bash
# What changed on the base branch around this file
git -C "$WORK_DIR" log --oneline "HEAD..origin/$BASE_BRANCH" -- "$FILE"
git -C "$WORK_DIR" show "origin/$BASE_BRANCH" -- "$FILE"
# What this rebased commit intended to change
git -C "$WORK_DIR" show ORIG_HEAD -- "$FILE"
```
Use the `edit` tool to resolve the conflict. Remove all `<<<<<<<`, `=======`, and `>>>>>>>` markers. Produce a result that correctly incorporates both sets of changes, preserving the intent of the rebased commit against the current state of `base_branch`.
**c. Stage the resolved file:**
```bash
git -C "$WORK_DIR" add "$WORK_DIR/$FILE"
```
Repeat (b)(c) for every conflicted file in this commit.
**d. Continue the rebase:**
```bash
GIT_EDITOR=true git -C "$WORK_DIR" rebase --continue
```
`GIT_EDITOR=true` prevents git from opening an interactive editor for the commit message — the original commit message is preserved as-is.
**e. Check if more conflicts remain:**
If the rebase pauses again, return to step (a). Repeat until `git rebase --continue` completes without error.
**CRITICAL:** If a conflict cannot be resolved safely (e.g. a file was deleted on one side and heavily modified on the other, and the correct resolution is ambiguous), never abort the rebase, make a best effort and report accordingly when done.
### 4. Verify completion
After the rebase finishes cleanly:
```bash
# Confirm clean working tree (no conflict markers, nothing unstaged)
git -C "$WORK_DIR" status
# Show the rebased commits relative to base
git -C "$WORK_DIR" log --oneline "origin/$BASE_BRANCH..HEAD"
# Confirm no conflict markers remain in any file
git -C "$WORK_DIR" diff --check
```
If `git diff --check` reports any remaining conflict markers, find and fix them before returning.
## Return Value
Always return a structured summary to your caller:
- Final status of `git status`
- Short log of commits that were rebased (`git log --oneline origin/$BASE_BRANCH..HEAD`)
- List of files where conflicts were resolved (and a brief description of how each was resolved)
- Confirmation that the branch is ready to push
## **CRITICAL** Rules
1. **Never push.** Your job ends when the rebase is complete and verified. Pushing is the caller's responsibility.
2. **Never use `git rebase --skip`.** Skipping a commit silently discards its changes. If a commit cannot be applied, make a best effort.
3. **Never use `--force` git operations.** You are not pushing, so this does not apply, but do not run any destructive git commands not required by the rebase procedure.
4. **Always remove all conflict markers.** A file containing `<<<<<<<`, `=======`, or `>>>>>>>` that was staged would corrupt the commit. Run `git diff --check` to confirm all markers are gone.
5. **Preserve the intent of both sides.** When resolving a conflict, do not silently drop either side's changes without justification. If you cannot safely combine them, abort.
6. **Never work in `/app`.** The working directory provided by your caller must be inside `/tmp/`. Refuse and report an error if it is not.
7. **One task, then exit.** Do not look for more work, do not loop, do not sleep.
8. **Apply labels via `forgejo-label-manager`.** Never apply labels directly or using the Forgejo MCP/task. All label operations must go through `forgejo-label-manager`.
9. **Exhaustive pagination for all list results.** Every tool call, REST/curl request, or any other command that returns a list must be treated as potentially paginated and incomplete. Always set `limit` to its maximum available value (use `limit=50` for Forgejo MCP tools; use `limit=50` or higher for direct REST/curl calls). After each list response, check whether the number of returned items equals the page size — if so, there are likely more results; fetch the next page (`page=2`, `page=3`, …) and continue until receiving a partial page. Never assume the first response is the complete result. This rule applies to every list-returning call without exception. *Examples specific to this agent (not exhaustive):* `git diff --name-only --diff-filter=U` listing conflicted files must be fully processed — do not stop at an assumed cutoff; `git log` output during history inspection may be long — use `--no-pager` or explicit `--max-count` limits and be aware the output may be truncated; any future REST/curl calls returning JSON arrays must be paginated.
+1 -2
View File
@@ -7,8 +7,7 @@ description: >
mode: subagent
hidden: true
temperature: 0.1
model: anthropic/claude-haiku-4-5
reasoningEffort: "max"
model: anthropic/claude-sonnet-4-6
color: "#95A5A6"
permission:
"*": deny
+1 -2
View File
@@ -6,8 +6,7 @@ description: >
mode: subagent
hidden: true
temperature: 0.1
model: anthropic/claude-haiku-4-5
reasoningEffort: "max"
model: anthropic/claude-sonnet-4-6
permission:
"*": deny
"doom_loop": deny
@@ -6,8 +6,7 @@ description: >
mode: subagent
hidden: true
temperature: 0.3
model: anthropic/claude-haiku-4-5
reasoningEffort: "max"
model: anthropic/claude-sonnet-4-6
color: "#3498DB"
permission:
"*": deny
+1 -2
View File
@@ -6,8 +6,7 @@ description: >
mode: subagent
hidden: true
temperature: 0.3
model: anthropic/claude-haiku-4-5
reasoningEffort: "max"
model: anthropic/claude-sonnet-4-6
permission:
"*": deny
"doom_loop": deny
+1 -2
View File
@@ -6,8 +6,7 @@ description: >
mode: subagent
hidden: true
temperature: 0.1
model: anthropic/claude-haiku-4-5
reasoningEffort: "max"
model: anthropic/claude-sonnet-4-6
color: info
permission:
"*": deny
-1
View File
@@ -7,7 +7,6 @@ mode: subagent
hidden: true
temperature: 0.0
model: anthropic/claude-haiku-4-5
reasoningEffort: "max"
color: info
permission:
"*": deny
@@ -6,7 +6,6 @@ mode: subagent
hidden: true
temperature: 0.1
model: anthropic/claude-haiku-4-5
reasoningEffort: "max"
color: "#8B5CF6"
permission:
"*": deny
-1
View File
@@ -6,7 +6,6 @@ mode: subagent
hidden: true
temperature: 0.3
model: anthropic/claude-haiku-4-5
reasoningEffort: "max"
color: info
permission:
"*": deny
+1 -2
View File
@@ -6,8 +6,7 @@ description: >
mode: subagent
hidden: true
temperature: 0.2
model: anthropic/claude-haiku-4-5
reasoningEffort: "max"
model: anthropic/claude-sonnet-4-6
color: warning
permission:
"*": deny
+1 -2
View File
@@ -6,8 +6,7 @@ description: >
mode: subagent
hidden: true
temperature: 0.2
model: anthropic/claude-haiku-4-5
reasoningEffort: "max"
model: anthropic/claude-sonnet-4-6
color: "#9B59B6"
permission:
"*": deny
+1 -2
View File
@@ -6,8 +6,7 @@ description: >
mode: subagent
hidden: true
temperature: 0.1
model: anthropic/claude-haiku-4-5
reasoningEffort: "max"
model: anthropic/claude-sonnet-4-6
color: warning
permission:
"*": deny
+1 -2
View File
@@ -6,8 +6,7 @@ description: >
mode: subagent
hidden: true
temperature: 0.0
model: anthropic/claude-haiku-4-5
reasoningEffort: "max"
model: anthropic/claude-sonnet-4-6
color: "#9B59B6"
permission:
"*": deny
@@ -6,7 +6,6 @@ mode: subagent
hidden: true
temperature: 0.3
model: anthropic/claude-haiku-4-5
reasoningEffort: "max"
color: secondary
permission:
"*": deny
+1 -2
View File
@@ -6,8 +6,7 @@ description: >
mode: subagent
hidden: true
temperature: 0.1
model: anthropic/claude-haiku-4-5
reasoningEffort: "max"
model: anthropic/claude-sonnet-4-6
color: "#10B981"
permission:
"*": deny
+1 -2
View File
@@ -5,8 +5,7 @@ description: >
agents for specific operations. User-facing.
mode: all
temperature: 0.2
model: anthropic/claude-haiku-4-5
reasoningEffort: "max"
model: anthropic/claude-sonnet-4-6
color: "#6366F1"
permission:
"*": deny
+9 -22
View File
@@ -7,8 +7,7 @@ description: >
mode: subagent
hidden: true
temperature: 0.1
model: openai/gpt-5-nano
reasoningEffort: "high"
model: anthropic/claude-sonnet-4-6
color: "#059669"
permission:
"*": deny
@@ -21,13 +20,11 @@ permission:
external_directory:
"/tmp/**": allow
webfetch: deny
websearch: deny
codesearch: deny
bash:
"*": deny
"sleep *": allow
"jq *": allow
"npx --yes tsx *.opencode/skills/auto-agents-system/scripts/*": allow
"npx --yes tsx /app/.opencode/skills/auto-agents-system/scripts/*": allow
# Block ALL commands that could hit the label creation endpoints
"*api/v1/orgs/*/labels*": deny
"*api/v1/repos/*/labels*": deny
@@ -51,12 +48,6 @@ permission:
You are a supervisor that monitors open PRs for merge readiness, verifies all criteria are met, rebases stale PRs, resolves conflicts, and merges them. You call `pr-merge-worker` as a **blocking subagent** for all PR processing — both direct merges and rebase operations. Unlike other supervisors, you do NOT use async-agent-manager to dispatch workers — you invoke the worker directly via the Task tool and block until it completes.
## Do first
**Always** do the following things first before anything else:
- Load the `auto-agents-system` skill and from it learn how to use the scripts with the following names: `list_prs_ready_to_merge`, `list_prs_stale_clean`, `list_prs_stale_conflicts`, `list_prs_needs_review_stale_clean`, and `list_prs_needs_review_stale_conflicts`. Once you have queried the skill to fully understand these scripts you should understand what arguments it takes, what arguments are valid, how to call it, and what output you expect in return.
## What You Receive
Your prompt will include:
@@ -76,23 +67,21 @@ Every worker prompt must include:
- Whether the PR is stale (merge_base != base.sha)
- Current review status (any approvals? any unresolved REQUEST_CHANGES?)
- Current CI status if known
- If the PR has conflicts.
- Repository info, Forgejo PAT, git identity
- Credentials: PAT, username, password, git name, git email
## Main Loop
Before starting the main loop below be sure to create your status tracking ticket (see the tracking section below). Also, before starting the below main loop ensure you have loaded the `auto-agents-system` skill.
Before starting the main loop below be sure to create your status tracking ticket (see the tracking section below). Also, before starting the below main loop ensure you have enabled the `auto-agents-system` skill.
In an infinite loop do the following each cycle:
1. If at least 10 minutes has passed since the last time you updated your automation tracking status ticket, or if you never created/updated one, (see tracking section below) then update your tracking ticket using the `automation-tracking-manager` subagent according to the details provided in the section labeled "tracking" below.
2. Run via bash tool the script named `list_prs_ready_to_merge` from the `auto-agents-system` skill which you must load and query how to use the mentioned skill, if the list is empty skip to the next step, however, if it has one or more PR in it then sequentially dispatch a single `pr-merge-worker` subagent for each PR in the group and then start the cycle over at #1 (skipping the rest of the steps in this cycle)
3. Run via bash tool the script named `list_prs_stale_clean` from the `auto-agents-system` skill which you must load and query how to use the mentioned skill, if the list is empty skip to the next step, however, if it has one or more PR in it then sequentially dispatch a single `pr-merge-worker` subagent for each PR in the group and then start the cycle over at #1 (skipping the rest of the steps in this cycle)
4. Run via bash tool the script named `list_prs_stale_conflicts` from the `auto-agents-system` skill which you must load and query how to use the mentioned skill, if the list is empty skip to the next step, however, if it has one or more PR in it then sequentially dispatch a single `pr-merge-worker` subagent for each PR in the group and then start the cycle over at #1 (skipping the rest of the steps in this cycle)
5. Run via bash tool the script named `list_prs_needs_review_stale_clean` from the `auto-agents-system` skill which you must load and query how to use the mentioned skill, if the list is empty skip to the next step, however, if it has one or more PR in it then sequentially dispatch a single `pr-merge-worker` subagent for each PR in the group and then start the cycle over at #1 (skipping the rest of the steps in this cycle)
6. Run via bash tool the script named `list_prs_needs_review_stale_conflicts` from the `auto-agents-system` skill which you must load and query how to use the mentioned skill, if the list is empty skip to the next step, however, if it has one or more PR in it then sequentially dispatch a single `pr-merge-worker` subagent for each PR in the group and then start the cycle over at #1 (skipping the rest of the steps in this cycle)
7. Sleep for 5 minutes using `bash("sleep 300", timeout=360000)`.
8. Loop through the cycle indefinately by starting at step 1 above again.
2. Use the script `list_prs_ready_to_merge` from the `auto-agents-system` skill, if the list is empty skip to the next step, however, if it has one or more PR in it then sequentially dispatch a single `pr-merge-worker` subagent for each PR in the group and then start the cycle over at #1 (skipping the rest of the steps in this cycle)
3. Use the script `list_prs_stale_clean` from the `auto-agents-system` skill, if the list is empty skip to the next step, however, if it has one or more PR in it then sequentially dispatch a single `pr-merge-worker` subagent for each PR in the group and then start the cycle over at #1 (skipping the rest of the steps in this cycle)
4. Use the script `list_prs_stale_conflicts` from the `auto-agents-system` skill, if the list is empty skip to the next step, however, if it has one or more PR in it then sequentially dispatch a single `pr-merge-worker` subagent for each PR in the group and then start the cycle over at #1 (skipping the rest of the steps in this cycle)
5. Use the script `list_prs_needs_review` from the `auto-agents-system` skill, if the list is empty skip to the next step, however, if it has one or more PR in it then sequentially dispatch a single `pr-merge-worker` subagent for each PR in the group and then start the cycle over at #1 (skipping the rest of the steps in this cycle)
6. Sleep for 5 minutes using `bash("sleep 300", timeout=360000)`.
7. Loop through the cycle indefinately by starting at step 1 above again.
## Tracking
@@ -117,5 +106,3 @@ Supervisor: PR Merge Pool | Agent: pr-merge-pool-supervisor
3. **Apply labels via `forgejo-label-manager`.** Never apply labels directly or using the Forgejo MCP/task. All label operations must go through `forgejo-label-manager`.
4. **Exhaustive pagination for all list results.** Every tool call that returns a list must be treated as potentially paginated. Always set `limit=50` for Forgejo MCP tools. After each list response, check whether the number of returned items equals the page size — if so, fetch the next page. Never assume the first response is the complete result. This applies to: `forgejo_list_repo_pull_requests` (must paginate ALL pages — missing a page means a ready PR never gets merged), `forgejo_list_pull_reviews` (paginate to see all review rounds), `forgejo_list_issue_comments` (paginate when updating linked issues post-merge).
5. **Never close or change the label of a PR's issue** The issue for a PR will automatically be closed and the grooming agent will update its labels. Never close the originating issue directly or change its state.
6. **Never try to access Forgejo directly** All access to forgejo will occur through the scripts provided by the `auto-agents-system` skill and provide all the access to Forgejo you need, **never** try to call the Forgejo API directly.
7. **Never ask questions or give up** Under no circumstances should you ask questions for clarification, you must operate fully autonomously. You have all the resources you need to succeed at your task, do not give up and give it your best possible effort, any questions you may have just use your best judgement.
+16 -25
View File
@@ -6,7 +6,7 @@ description: >
mode: subagent
hidden: true
temperature: 0.1
model: openai/gpt-5-nano
model: anthropic/claude-sonnet-4-6
permission:
"*": deny
"doom_loop": deny
@@ -18,11 +18,9 @@ permission:
"external_directory":
"/tmp/**": allow
webfetch: deny
websearch: deny
codesearch: deny
bash:
"*": deny
"git status *": allow
"git *": allow
"mkdir *": allow
"rm -rf *": allow
"sleep *": allow
@@ -38,7 +36,7 @@ permission:
"*": deny
"repo-isolator": allow
"git-commit-helper": allow
"git-rebase-helped": allow
"forgejo-label-manager": allow
skill:
"*": deny
"auto-agents-system": allow
@@ -48,35 +46,30 @@ permission:
You perform a single rebase operation on a PR branch, resolve any conflicts, and then exit. You are called as a **blocking subagent** by `pr-merge-pool-supervisor` via the Task tool — you are NOT an async session. The supervisor blocks until you finish and return your results.
## Do First
## **CRITICAL** Running scripts from skills
**Always** do the following things first before anything else:
- Load the `auto-agents-system` skill and from it learn how to use the scripts with the following names: `merge_pr`, and `rebase_pr`.
When running any scripts from skills use `npx --yes tsx <script_path> <args>` for example `npx --yes tsx /app/.opencode/skills/auto-agents-system/scripts/foo.ts --arg value`.
## Procedure
**CRITICAL**: Always follow this procedure exactly unless explicitly stated otherwise. You need to strictly adhere to these steps exactly as laid out whenever called except when clearly and explicitly stated in your prompt to deviate.
Before starting the below main loop ensure you have loaded the `auto-agents-system` skill.
Your prompt tells you which PR to rebase. Your prompt will tell you all the information you need, no need to investigate the PR for more information.
Your prompt tells you which PR to rebase. First you must determine if the PR has conflicts.
If the PR is stale and has conflicts then do the following:
1. Create an isolated clone using the `repo-isolator` subagent ensuring you pass it the branch used by the PR. Make sure all work is done within this clone's directory.
2. Call the `git-rebase-helper` subagent and pass it the directory of the isolated and cloned repo, the base branch as master, and the name of the branch to be rebased, instruct it to conduct the rebase and conflict resolution, and finish any rebase operation, but not to push.
3. Pass the correct branch, and repo directory in the prompt, and instruct `git-commit-helper` subagent to force-push the branch with lease
4. Clean up the clone.
5. load the skill `auto-agents-system` and run, via the bash tool, the script named `merge_pr` from the skill to initiate the merge (or at least auto-schedule it).
6. Report back with any relevant details.
2. Rebase it onto the base branch (usually `master`).
3. Resolve any conflicts that arise by reviewing the recent git history and using that to fix the conflicts
4. Force-push with lease using `git-commit-helper`
5. Clean up the clone.
6. load the skill `auto-agents-system` and run the script `merge_pr` to initiate the merge (or at least auto-schedule it).
7. Report back with any relevant details.
If the PR does **not** have any conflicts but is stale:
1. Load the skill `auto-agents-system` and run, via the bash tool, the script named `rebase_pr` from the skill to initiate an on-server rebase.
2. load the skill `auto-agents-system` and run, via the bash tool, the script named `merge_pr` from the skill to initiate the merge (or at least auto-schedule it).
1. Load the skill `auto-agents-system` and run the script `rebase_pr` to initiate an on-server rebase.
2. load the skill `auto-agents-system` and run the script `merge_pr` to initiate the merge (or at least auto-schedule it).
3. Report back with any relevant details.
If the PR is **not** stale (and therefore wouldnt have any conflicts either):
1. load the skill `auto-agents-system` and run, via the bash tool, the script named `merge_pr` to initiate the merge (or at least auto-schedule it).
1. load the skill `auto-agents-system` and run the script `merge_pr` to initiate the merge (or at least auto-schedule it).
2. Report back with any relevant details.
## **CRITICAL** Rules
@@ -87,6 +80,4 @@ If the PR is **not** stale (and therefore wouldnt have any conflicts either):
4. **Apply labels via `forgejo-label-manager`.** Never apply labels directly or using the Forgejo MCP/task. All label operations must go through `forgejo-label-manager`.
5. **Exhaustive pagination for all list results.** Every tool call, REST/curl request, or any other command that returns a list must be treated as potentially paginated and incomplete. Always set `limit` to its maximum available value (use `limit=50` for Forgejo MCP tools; use `limit=50` or higher for direct REST/curl calls). After each list response, check whether the number of returned items equals the page size — if so, there are likely more results; fetch the next page (`page=2`, `page=3`, …) and continue until receiving a partial page. Never assume the first response is the complete result. This rule applies to every list-returning call without exception. *Examples specific to this agent (not exhaustive):* `git log` listing commits during conflict resolution must be fully read; any future REST/curl calls returning JSON arrays must be paginated.
6. **Never close or change the label of a PR's issue** The issue for a PR will automatically be closed and the grooming agent will update its labels. Never close the originating issue directly or change its state.
7. **CRITICAL** Never wait for CI quality gates or merges to finish, merge, when set, will be scheduled to occur automatically when tests complete.
8. **Never try to access Forgejo directly** All access to forgejo will occur through the scripts provided by the `auto-agents-system` skill and provide all the access to Forgejo you need, **never** try to call the Forgejo API directly.
9. **Never ask questions or give up** Under no circumstances should you ask questions for clarification, you must operate fully autonomously. You have all the resources you need to succeed at your task, do not give up and give it your best possible effort, any questions you may have just use your best judgement.
7. **CRITICAL** Never wait for CI quality gates or merges to finish, merge, when set, will be scheduled to occur automatically when tests complete.
@@ -7,8 +7,7 @@ description: >
mode: subagent
hidden: true
temperature: 0.1
model: anthropic/claude-haiku-4-5
reasoningEffort: "max"
model: anthropic/claude-sonnet-4-6
color: info
permission:
edit: deny
+1 -2
View File
@@ -7,8 +7,7 @@ description: >
mode: subagent
hidden: true
temperature: 0.2
model: anthropic/claude-haiku-4-5
reasoningEffort: "max"
model: anthropic/claude-sonnet-4-6
color: warning
permission:
"*": deny
-1
View File
@@ -6,7 +6,6 @@ mode: subagent
hidden: true
temperature: 0.1
model: anthropic/claude-haiku-4-5
reasoningEffort: "max"
color: "#3B82F6"
permission:
"*": deny
+1 -4
View File
@@ -5,8 +5,7 @@ description: >
and reports status. Never does implementation work itself.
mode: primary
temperature: 0.1
model: anthropic/claude-haiku-4-5
reasoningEffort: "max"
model: anthropic/claude-sonnet-4-6
color: primary
permission:
"*": deny
@@ -15,8 +14,6 @@ permission:
"sequential-thinking*": allow
edit: deny
webfetch: deny
websearch: deny
codesearch: deny
bash:
"*": deny
"echo $*": allow
+1 -2
View File
@@ -6,8 +6,7 @@ description: >
mode: subagent
hidden: true
temperature: 0.1
model: anthropic/claude-haiku-4-5
reasoningEffort: "max"
model: anthropic/claude-sonnet-4-6
color: info
permission:
"*": deny
+1 -2
View File
@@ -6,8 +6,7 @@ description: >
mode: subagent
hidden: true
temperature: 0.2
model: anthropic/claude-haiku-4-5
reasoningEffort: "max"
model: anthropic/claude-sonnet-4-6
color: primary
permission:
"*": deny
@@ -6,8 +6,7 @@ description: >
mode: subagent
hidden: true
temperature: 0.3
model: anthropic/claude-haiku-4-5
reasoningEffort: "max"
model: anthropic/claude-sonnet-4-6
color: "#8E44AD"
permission:
"*": deny
+1 -2
View File
@@ -6,8 +6,7 @@ description: >
mode: subagent
hidden: true
temperature: 0.3
model: anthropic/claude-haiku-4-5
reasoningEffort: "max"
model: anthropic/claude-sonnet-4-6
permission:
"*": deny
"doom_loop": deny
+1 -2
View File
@@ -6,8 +6,7 @@ description: >
mode: subagent
hidden: true
temperature: 0.0
model: anthropic/claude-haiku-4-5
reasoningEffort: "max"
model: anthropic/claude-sonnet-4-6
color: error
permission:
"*": deny
-1
View File
@@ -7,7 +7,6 @@ mode: subagent
hidden: true
temperature: 0.1
model: anthropic/claude-haiku-4-5
reasoningEffort: "max"
color: "#6B7280"
permission:
"*": deny
+1 -2
View File
@@ -6,8 +6,7 @@ description: >
mode: subagent
hidden: true
temperature: 0.0
model: anthropic/claude-haiku-4-5
reasoningEffort: "max"
model: anthropic/claude-sonnet-4-6
color: info
permission:
"*": deny
-1
View File
@@ -7,7 +7,6 @@ mode: subagent
hidden: true
temperature: 0.1
model: anthropic/claude-haiku-4-5
reasoningEffort: "max"
color: "#6B7280"
permission:
"*": deny
+1 -2
View File
@@ -5,8 +5,7 @@ description: >
mode: subagent
hidden: true
temperature: 0.0
model: anthropic/claude-haiku-4-5
reasoningEffort: "max"
model: anthropic/claude-sonnet-4-6
color: info
permission:
"*": deny
@@ -7,8 +7,7 @@ description: >
mode: subagent
hidden: true
temperature: 0.2
model: anthropic/claude-haiku-4-5
reasoningEffort: "max"
model: anthropic/claude-sonnet-4-6
color: "#9B59B6"
permission:
"*": deny
+1 -2
View File
@@ -6,8 +6,7 @@ description: >
mode: subagent
hidden: true
temperature: 0.2
model: anthropic/claude-haiku-4-5
reasoningEffort: "max"
model: anthropic/claude-sonnet-4-6
permission:
"*": deny
"doom_loop": deny
+1 -2
View File
@@ -5,8 +5,7 @@ description: >
mode: subagent
hidden: true
temperature: 0.0
model: anthropic/claude-haiku-4-5
reasoningEffort: "max"
model: anthropic/claude-sonnet-4-6
color: warning
permission:
"*": deny
-1
View File
@@ -9,7 +9,6 @@ mode: subagent
hidden: true
temperature: 0.1
model: anthropic/claude-haiku-4-5
reasoningEffort: "max"
color: accent
permission:
"*": deny
@@ -7,8 +7,7 @@ description: >
mode: subagent
hidden: true
temperature: 0.1
model: anthropic/claude-haiku-4-5
reasoningEffort: "max"
model: anthropic/claude-sonnet-4-6
color: "#E74C3C"
permission:
"*": deny
+1 -2
View File
@@ -6,8 +6,7 @@ description: >
mode: subagent
hidden: true
temperature: 0.1
model: anthropic/claude-haiku-4-5
reasoningEffort: "max"
model: anthropic/claude-sonnet-4-6
permission:
"*": deny
"doom_loop": deny
@@ -7,8 +7,7 @@ description: >
mode: subagent
hidden: true
temperature: 0.2
model: anthropic/claude-haiku-4-5
reasoningEffort: "max"
model: anthropic/claude-sonnet-4-6
color: "#2ECC71"
permission:
"*": deny
+1 -2
View File
@@ -6,8 +6,7 @@ description: >
mode: subagent
hidden: true
temperature: 0.2
model: anthropic/claude-haiku-4-5
reasoningEffort: "max"
model: anthropic/claude-sonnet-4-6
permission:
"*": deny
"doom_loop": deny
-1
View File
@@ -6,7 +6,6 @@ mode: subagent
hidden: true
temperature: 0.0
model: anthropic/claude-haiku-4-5
reasoningEffort: "max"
permission:
"*": deny
"doom_loop": deny
@@ -6,8 +6,7 @@ description: >
mode: subagent
hidden: true
temperature: 0.1
model: anthropic/claude-haiku-4-5
reasoningEffort: "max"
model: anthropic/claude-sonnet-4-6
color: "#2ECC71"
permission:
"*": deny
+1 -2
View File
@@ -6,8 +6,7 @@ description: >
mode: subagent
hidden: true
temperature: 0.1
model: anthropic/claude-haiku-4-5
reasoningEffort: "max"
model: anthropic/claude-sonnet-4-6
permission:
"*": deny
"doom_loop": deny
+1 -2
View File
@@ -7,8 +7,7 @@ description: >
mode: subagent
hidden: true
temperature: 0.3
model: anthropic/claude-haiku-4-5
reasoningEffort: "max"
model: anthropic/claude-sonnet-4-6
color: success
permission:
"*": deny
+1 -2
View File
@@ -6,8 +6,7 @@ description: >
mode: subagent
hidden: true
temperature: 0.3
model: anthropic/claude-haiku-4-5
reasoningEffort: "max"
model: anthropic/claude-sonnet-4-6
permission:
"*": deny
"doom_loop": deny
@@ -0,0 +1,70 @@
# Async Agent Manager Migration Summary
## Problem Identified
The `async-agent-starter` subagent was failing because it tried to use bash with curl commands, but the environment was restricting these operations. The error message showed:
> "I don't currently have the ability to run the required shell or HTTP commands from this environment"
## Solution Implemented
### 1. Created New `async-agent-manager.md`
- Renamed from `async-agent-starter` to better reflect its expanded responsibilities
- Enhanced to handle all async agent operations:
- Starting async agents
- Getting session status
- Retrieving session messages
- Searching sessions by tag
- Closing/cleanup sessions
- Monitoring session health
- Properly configured with explicit curl permissions to localhost:4096
- Includes detailed curl command examples that have been tested and verified to work
### 2. Updated All Agents Using Async Operations
#### Primary Agent Updated:
- **product-builder.md**:
- Removed direct curl permissions to localhost:4096
- Added permission to use `async-agent-manager` subagent
- Updated `launch_supervisor` function to use async-agent-manager instead of direct curl
- Updated all session status queries to use async-agent-manager
- Updated session conversation retrieval to use async-agent-manager
#### Pool Supervisors Updated:
- **implementation-orchestrator.md**: Updated all references from async-agent-starter to async-agent-manager
- **uat-tester.md**: Added async-agent-manager permission and updated worker launch code
- **test-infra-improver.md**: Added async-agent-manager permission and updated worker launch code
- **continuous-pr-reviewer.md**: Added async-agent-manager permission and updated reviewer dispatch code
- **bug-hunter.md**: Added async-agent-manager permission (already structured for worker dispatch)
#### Other Agents Updated:
- **subtask-loop.md**: Updated all references from async-agent-starter to async-agent-manager
- **async-agent-monitor.md**: Updated to use async-agent-manager for restart operations
- **system-watchdog.md**: Added async-agent-manager permission and updated dispatch_one_off function
- **async-agent-cleanup.md**: Removed direct curl permissions, added async-agent-manager permission
- **async-agent-cleanup-all.md**: Removed direct curl permissions, added async-agent-manager permission
### 3. Key Design Principles
1. **Single Point of Control**: Only `async-agent-manager` has permission to curl to localhost:4096
2. **Consistent Interface**: All agents use the same Task tool interface to interact with async operations
3. **Proper Error Handling**: The manager returns structured JSON responses for all operations
4. **Security**: Properly escapes all inputs to prevent injection attacks
5. **Comprehensive Operations**: Handles the full lifecycle of async sessions
### 4. Testing
Created and ran a test script that verified:
- Session listing works correctly
- Session status retrieval works correctly
- Session creation returns proper session IDs
- Async agent launch returns HTTP 204 (success)
- Session deletion works correctly
## Benefits
1. **Centralized Management**: All async operations go through a single, well-tested agent
2. **Better Error Handling**: Structured responses make it easier to handle failures
3. **Improved Security**: Only one agent needs curl permissions to the API
4. **Easier Maintenance**: Changes to the API only need to be updated in one place
5. **Consistent Patterns**: All agents use the same interface for async operations
## Migration Complete
All agents that previously used direct curl commands or async-agent-starter have been updated to use the new async-agent-manager. The old async-agent-starter.md file has been removed.
+10 -283
View File
@@ -5,100 +5,21 @@
"packages": {
"": {
"dependencies": {
"@opencode-ai/plugin": "1.4.8"
"@opencode-ai/plugin": "1.3.17"
}
},
"node_modules/@msgpackr-extract/msgpackr-extract-darwin-arm64": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-darwin-arm64/-/msgpackr-extract-darwin-arm64-3.0.3.tgz",
"integrity": "sha512-QZHtlVgbAdy2zAqNA9Gu1UpIuI8Xvsd1v8ic6B2pZmeFnFcMWiPLfWXh7TVw4eGEZ/C9TH281KwhVoeQUKbyjw==",
"cpu": [
"arm64"
],
"license": "MIT",
"optional": true,
"os": [
"darwin"
]
},
"node_modules/@msgpackr-extract/msgpackr-extract-darwin-x64": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-darwin-x64/-/msgpackr-extract-darwin-x64-3.0.3.tgz",
"integrity": "sha512-mdzd3AVzYKuUmiWOQ8GNhl64/IoFGol569zNRdkLReh6LRLHOXxU4U8eq0JwaD8iFHdVGqSy4IjFL4reoWCDFw==",
"cpu": [
"x64"
],
"license": "MIT",
"optional": true,
"os": [
"darwin"
]
},
"node_modules/@msgpackr-extract/msgpackr-extract-linux-arm": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-linux-arm/-/msgpackr-extract-linux-arm-3.0.3.tgz",
"integrity": "sha512-fg0uy/dG/nZEXfYilKoRe7yALaNmHoYeIoJuJ7KJ+YyU2bvY8vPv27f7UKhGRpY6euFYqEVhxCFZgAUNQBM3nw==",
"cpu": [
"arm"
],
"license": "MIT",
"optional": true,
"os": [
"linux"
]
},
"node_modules/@msgpackr-extract/msgpackr-extract-linux-arm64": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-linux-arm64/-/msgpackr-extract-linux-arm64-3.0.3.tgz",
"integrity": "sha512-YxQL+ax0XqBJDZiKimS2XQaf+2wDGVa1enVRGzEvLLVFeqa5kx2bWbtcSXgsxjQB7nRqqIGFIcLteF/sHeVtQg==",
"cpu": [
"arm64"
],
"license": "MIT",
"optional": true,
"os": [
"linux"
]
},
"node_modules/@msgpackr-extract/msgpackr-extract-linux-x64": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-linux-x64/-/msgpackr-extract-linux-x64-3.0.3.tgz",
"integrity": "sha512-cvwNfbP07pKUfq1uH+S6KJ7dT9K8WOE4ZiAcsrSes+UY55E/0jLYc+vq+DO7jlmqRb5zAggExKm0H7O/CBaesg==",
"cpu": [
"x64"
],
"license": "MIT",
"optional": true,
"os": [
"linux"
]
},
"node_modules/@msgpackr-extract/msgpackr-extract-win32-x64": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-win32-x64/-/msgpackr-extract-win32-x64-3.0.3.tgz",
"integrity": "sha512-x0fWaQtYp4E6sktbsdAqnehxDgEc/VwM7uLsRCYWaiGu0ykYdZPiS8zCWdnjHwyiumousxfBm4SO31eXqwEZhQ==",
"cpu": [
"x64"
],
"license": "MIT",
"optional": true,
"os": [
"win32"
]
},
"node_modules/@opencode-ai/plugin": {
"version": "1.4.8",
"resolved": "https://registry.npmjs.org/@opencode-ai/plugin/-/plugin-1.4.8.tgz",
"integrity": "sha512-arbggGAwR7vE6d5a/Ra8A7yECXYcOAPyRbJHzkofLLiVzyclsThFaL2SSCZw/UNJJTtt3L7JGl95phFodJq8tQ==",
"version": "1.3.17",
"resolved": "https://registry.npmjs.org/@opencode-ai/plugin/-/plugin-1.3.17.tgz",
"integrity": "sha512-N5lckFtYvEu2R8K1um//MIOTHsJHniF2kHoPIWPCrxKG5Jpismt1ISGzIiU3aKI2ht/9VgcqKPC5oZFLdmpxPw==",
"license": "MIT",
"dependencies": {
"@opencode-ai/sdk": "1.4.8",
"effect": "4.0.0-beta.48",
"@opencode-ai/sdk": "1.3.17",
"zod": "4.1.8"
},
"peerDependencies": {
"@opentui/core": ">=0.1.100",
"@opentui/solid": ">=0.1.100"
"@opentui/core": ">=0.1.96",
"@opentui/solid": ">=0.1.96"
},
"peerDependenciesMeta": {
"@opentui/core": {
@@ -110,24 +31,16 @@
}
},
"node_modules/@opencode-ai/sdk": {
"version": "1.4.8",
"resolved": "https://registry.npmjs.org/@opencode-ai/sdk/-/sdk-1.4.8.tgz",
"integrity": "sha512-DTN0TwRxuBxdm2JvJO3Dg7Vp9/j8PFpTS/26qD6Mzi6UPI5+NBxgcDVkozKygi55Goj3AAQGJPp63qzbdc+8ag==",
"version": "1.3.17",
"resolved": "https://registry.npmjs.org/@opencode-ai/sdk/-/sdk-1.3.17.tgz",
"integrity": "sha512-2+MGgu7wynqTBwxezR01VAGhILXlpcHDY/pF7SWB87WOgLt3kD55HjKHNj6PWxyY8n575AZolR95VUC3gtwfmA==",
"license": "MIT",
"dependencies": {
"cross-spawn": "7.0.6"
}
},
"node_modules/@standard-schema/spec": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/@standard-schema/spec/-/spec-1.1.0.tgz",
"integrity": "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==",
"license": "MIT"
},
"node_modules/cross-spawn": {
"version": "7.0.6",
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
"integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==",
"license": "MIT",
"dependencies": {
"path-key": "^3.1.0",
@@ -138,164 +51,19 @@
"node": ">= 8"
}
},
"node_modules/detect-libc": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz",
"integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==",
"license": "Apache-2.0",
"optional": true,
"engines": {
"node": ">=8"
}
},
"node_modules/effect": {
"version": "4.0.0-beta.48",
"resolved": "https://registry.npmjs.org/effect/-/effect-4.0.0-beta.48.tgz",
"integrity": "sha512-MMAM/ZabuNdNmgXiin+BAanQXK7qM8mlt7nfXDoJ/Gn9V8i89JlCq+2N0AiWmqFLXjGLA0u3FjiOjSOYQk5uMw==",
"license": "MIT",
"dependencies": {
"@standard-schema/spec": "^1.1.0",
"fast-check": "^4.6.0",
"find-my-way-ts": "^0.1.6",
"ini": "^6.0.0",
"kubernetes-types": "^1.30.0",
"msgpackr": "^1.11.9",
"multipasta": "^0.2.7",
"toml": "^4.1.1",
"uuid": "^13.0.0",
"yaml": "^2.8.3"
}
},
"node_modules/fast-check": {
"version": "4.6.0",
"resolved": "https://registry.npmjs.org/fast-check/-/fast-check-4.6.0.tgz",
"integrity": "sha512-h7H6Dm0Fy+H4ciQYFxFjXnXkzR2kr9Fb22c0UBpHnm59K2zpr2t13aPTHlltFiNT6zuxp6HMPAVVvgur4BLdpA==",
"funding": [
{
"type": "individual",
"url": "https://github.com/sponsors/dubzzz"
},
{
"type": "opencollective",
"url": "https://opencollective.com/fast-check"
}
],
"license": "MIT",
"dependencies": {
"pure-rand": "^8.0.0"
},
"engines": {
"node": ">=12.17.0"
}
},
"node_modules/find-my-way-ts": {
"version": "0.1.6",
"resolved": "https://registry.npmjs.org/find-my-way-ts/-/find-my-way-ts-0.1.6.tgz",
"integrity": "sha512-a85L9ZoXtNAey3Y6Z+eBWW658kO/MwR7zIafkIUPUMf3isZG0NCs2pjW2wtjxAKuJPxMAsHUIP4ZPGv0o5gyTA==",
"license": "MIT"
},
"node_modules/ini": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/ini/-/ini-6.0.0.tgz",
"integrity": "sha512-IBTdIkzZNOpqm7q3dRqJvMaldXjDHWkEDfrwGEQTs5eaQMWV+djAhR+wahyNNMAa+qpbDUhBMVt4ZKNwpPm7xQ==",
"license": "ISC",
"engines": {
"node": "^20.17.0 || >=22.9.0"
}
},
"node_modules/isexe": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
"integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
"license": "ISC"
},
"node_modules/kubernetes-types": {
"version": "1.30.0",
"resolved": "https://registry.npmjs.org/kubernetes-types/-/kubernetes-types-1.30.0.tgz",
"integrity": "sha512-Dew1okvhM/SQcIa2rcgujNndZwU8VnSapDgdxlYoB84ZlpAD43U6KLAFqYo17ykSFGHNPrg0qry0bP+GJd9v7Q==",
"license": "Apache-2.0"
},
"node_modules/msgpackr": {
"version": "1.11.9",
"resolved": "https://registry.npmjs.org/msgpackr/-/msgpackr-1.11.9.tgz",
"integrity": "sha512-FkoAAyyA6HM8wL882EcEyFZ9s7hVADSwG9xrVx3dxxNQAtgADTrJoEWivID82Iv1zWDsv/OtbrrcZAzGzOMdNw==",
"license": "MIT",
"optionalDependencies": {
"msgpackr-extract": "^3.0.2"
}
},
"node_modules/msgpackr-extract": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/msgpackr-extract/-/msgpackr-extract-3.0.3.tgz",
"integrity": "sha512-P0efT1C9jIdVRefqjzOQ9Xml57zpOXnIuS+csaB4MdZbTdmGDLo8XhzBG1N7aO11gKDDkJvBLULeFTo46wwreA==",
"hasInstallScript": true,
"license": "MIT",
"optional": true,
"dependencies": {
"node-gyp-build-optional-packages": "5.2.2"
},
"bin": {
"download-msgpackr-prebuilds": "bin/download-prebuilds.js"
},
"optionalDependencies": {
"@msgpackr-extract/msgpackr-extract-darwin-arm64": "3.0.3",
"@msgpackr-extract/msgpackr-extract-darwin-x64": "3.0.3",
"@msgpackr-extract/msgpackr-extract-linux-arm": "3.0.3",
"@msgpackr-extract/msgpackr-extract-linux-arm64": "3.0.3",
"@msgpackr-extract/msgpackr-extract-linux-x64": "3.0.3",
"@msgpackr-extract/msgpackr-extract-win32-x64": "3.0.3"
}
},
"node_modules/multipasta": {
"version": "0.2.7",
"resolved": "https://registry.npmjs.org/multipasta/-/multipasta-0.2.7.tgz",
"integrity": "sha512-KPA58d68KgGil15oDqXjkUBEBYc00XvbPj5/X+dyzeo/lWm9Nc25pQRlf1D+gv4OpK7NM0J1odrbu9JNNGvynA==",
"license": "MIT"
},
"node_modules/node-gyp-build-optional-packages": {
"version": "5.2.2",
"resolved": "https://registry.npmjs.org/node-gyp-build-optional-packages/-/node-gyp-build-optional-packages-5.2.2.tgz",
"integrity": "sha512-s+w+rBWnpTMwSFbaE0UXsRlg7hU4FjekKU4eyAih5T8nJuNZT1nNsskXpxmeqSK9UzkBl6UgRlnKc8hz8IEqOw==",
"license": "MIT",
"optional": true,
"dependencies": {
"detect-libc": "^2.0.1"
},
"bin": {
"node-gyp-build-optional-packages": "bin.js",
"node-gyp-build-optional-packages-optional": "optional.js",
"node-gyp-build-optional-packages-test": "build-test.js"
}
},
"node_modules/path-key": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
"integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
"license": "MIT",
"engines": {
"node": ">=8"
}
},
"node_modules/pure-rand": {
"version": "8.4.0",
"resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-8.4.0.tgz",
"integrity": "sha512-IoM8YF/jY0hiugFo/wOWqfmarlE6J0wc6fDK1PhftMk7MGhVZl88sZimmqBBFomLOCSmcCCpsfj7wXASCpvK9A==",
"funding": [
{
"type": "individual",
"url": "https://github.com/sponsors/dubzzz"
},
{
"type": "opencollective",
"url": "https://opencollective.com/fast-check"
}
],
"license": "MIT"
},
"node_modules/shebang-command": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
"integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
"license": "MIT",
"dependencies": {
"shebang-regex": "^3.0.0"
@@ -306,39 +74,13 @@
},
"node_modules/shebang-regex": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
"integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
"license": "MIT",
"engines": {
"node": ">=8"
}
},
"node_modules/toml": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/toml/-/toml-4.1.1.tgz",
"integrity": "sha512-EBJnVBr3dTXdA89WVFoAIPUqkBjxPMwRqsfuo1r240tKFHXv3zgca4+NJib/h6TyvGF7vOawz0jGuryJCdNHrw==",
"license": "MIT",
"engines": {
"node": ">=20"
}
},
"node_modules/uuid": {
"version": "13.0.0",
"resolved": "https://registry.npmjs.org/uuid/-/uuid-13.0.0.tgz",
"integrity": "sha512-XQegIaBTVUjSHliKqcnFqYypAd4S+WCYt5NIeRs6w/UAry7z8Y9j5ZwRRL4kzq9U3sD6v+85er9FvkEaBpji2w==",
"funding": [
"https://github.com/sponsors/broofa",
"https://github.com/sponsors/ctavan"
],
"license": "MIT",
"bin": {
"uuid": "dist-node/bin/uuid"
}
},
"node_modules/which": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
"integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
"license": "ISC",
"dependencies": {
"isexe": "^2.0.0"
@@ -350,21 +92,6 @@
"node": ">= 8"
}
},
"node_modules/yaml": {
"version": "2.8.3",
"resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.3.tgz",
"integrity": "sha512-AvbaCLOO2Otw/lW5bmh9d/WEdcDFdQp2Z2ZUH3pX9U2ihyUY0nvLv7J6TrWowklRGPYbB/IuIMfYgxaCPg5Bpg==",
"license": "ISC",
"bin": {
"yaml": "bin.mjs"
},
"engines": {
"node": ">= 14.6"
},
"funding": {
"url": "https://github.com/sponsors/eemeli"
}
},
"node_modules/zod": {
"version": "4.1.8",
"license": "MIT",
File diff suppressed because it is too large Load Diff
@@ -44,6 +44,7 @@ product-builder (AUTO-PROD-BLDR) ← process supervisor (like systemd)
└── system-watchdog-worker ← dispatched by AUTO-WDOG
```
---
## Pool Supervisor Detailed Reference
@@ -65,6 +66,7 @@ product-builder (AUTO-PROD-BLDR) ← process supervisor (like systemd)
**Never dispatches to**: PRs that are already in mergeable state (passing CI + approval)
---
### 2. PR Review Pool (`AUTO-REV-SUP`)
@@ -78,6 +80,7 @@ product-builder (AUTO-PROD-BLDR) ← process supervisor (like systemd)
**Special**: Receives `FORGEJO_REVIEWER_PAT/USERNAME/PASSWORD` instead of primary credentials.
---
### 3. PR Merge Pool (`AUTO-PRMRG-SUP`)
@@ -87,10 +90,11 @@ product-builder (AUTO-PROD-BLDR) ← process supervisor (like systemd)
**Workers**: `pr-merge-worker` via **blocking Task tool call** (not async)
**Worker tag pattern**: NONE — no `[AUTO-PRMRG-N]` sessions ever exist
**Role**: Merges approved PRs. Verifies merge criteria. Handles pre-merge rebasing.
**Role**: Merges approved PRs. Verifies seven merge criteria. Handles pre-merge rebasing.
**⚠️ Special**: Does NOT use async-agent-manager. Calls `pr-merge-worker` directly as a Task subagent and blocks until it completes. When the supervisor is busy executing its worker, it appears as a normal busy session — this is correct behavior. Product-builder and system-watchdog must NOT flag the absence of `[AUTO-PRMRG-N]` sessions as a problem.
---
### 4. UAT Test Pool (`AUTO-UAT-SUP`)
@@ -102,28 +106,31 @@ product-builder (AUTO-PROD-BLDR) ← process supervisor (like systemd)
**Role**: Specification-driven user acceptance testing. Discovers testable feature areas from the spec, dispatches workers to test each area, files bug issues for gaps. Only assigns Priority/Critical bugs to the active milestone (scope guard).
---
### 5. Bug Hunt Pool (`AUTO-BUG-SUP`)
**Definition**: `bug-hunt-pool-supervisor`
**Worker count**: N_QUARTER
**Sleep**: 900 seconds (15 minutes)
**Workers**: `bug-hunt-worker` (async sessions)
**Workers**: `bug-hunt-worker` (async sessions, use Gemini 2.5 Pro for large context)
**Worker tag pattern**: `[AUTO-BUG-N]`
**Role**: Proactive bug detection. Maps source modules, dispatches workers for deep code analysis combined with specification comparison.
---
### 6. Test Infrastructure Pool (`AUTO-INF-SUP`)
**Definition**: `test-infra-pool-supervisor`
**Worker count**: N_QUARTER
**Sleep**: 900 seconds (15 minutes)
**Workers**: `test-infra-worker` (async sessions)
**Workers**: `test-infra-worker` (async sessions, use Gemini 2.5 Pro)
**Worker tag pattern**: `[AUTO-INF-N]`
**Role**: Testing infrastructure improvement. Analyzes CI timing, coverage gaps, test architecture. Never disables or weakens existing checks — only proposes additions and optimizations.
---
### 7. Architecture (`AUTO-ARCH`)
@@ -135,6 +142,7 @@ product-builder (AUTO-PROD-BLDR) ← process supervisor (like systemd)
**Role**: Specification authoring and module boundary definition. **The most consequential agent** — bad architecture cascades everywhere. Major changes go through PRs with `needs feedback` label for human approval.
---
### 8. Epic Planning (`AUTO-EPIC`)
@@ -146,6 +154,7 @@ product-builder (AUTO-PROD-BLDR) ← process supervisor (like systemd)
**Role**: Decomposes architecture into Forgejo Epics and Issues. Monitors for milestones without issues, epics without children. Creates dependency chains and metadata.
---
### 9. Human Liaison (`AUTO-HUMAN`)
@@ -157,6 +166,7 @@ product-builder (AUTO-PROD-BLDR) ← process supervisor (like systemd)
**Role**: Bridge to humans. Monitors all human activity on Forgejo. Has full triage authority. Responds to new issues, comments, PR reviews, and label changes.
---
### 10. Agent Evolution (`AUTO-EVLV`)
@@ -168,6 +178,7 @@ product-builder (AUTO-PROD-BLDR) ← process supervisor (like systemd)
**Role**: Monitors agent effectiveness. Identifies failure patterns. Proposes agent definition modifications in `.opencode/agents/`. All changes require human-approved PRs with `needs feedback` label.
---
### 11. Architecture Guard (`AUTO-GUARD`)
@@ -179,6 +190,7 @@ product-builder (AUTO-PROD-BLDR) ← process supervisor (like systemd)
**Role**: Aggressive codebase coherence checking. Scans for pattern drift, duplicate code, module coupling, API inconsistencies, and technical debt.
---
### 12. Spec Update (`AUTO-SPEC`)
@@ -190,6 +202,7 @@ product-builder (AUTO-PROD-BLDR) ← process supervisor (like systemd)
**Role**: Compares implementation against spec after merges. Updates spec where implementation found a better approach. Creates issues where implementation deviates incorrectly.
---
### 13. Backlog Grooming (`AUTO-GROOM`)
@@ -201,6 +214,7 @@ product-builder (AUTO-PROD-BLDR) ← process supervisor (like systemd)
**Role**: Continuously scans all open Forgejo issues and PRs for quality problems. Detects duplicates, orphans, stale issues, missing labels, priority mismatches. Works entirely via Forgejo API — no clone needed.
---
### 14. Documentation (`AUTO-DOCS`)
@@ -212,6 +226,7 @@ product-builder (AUTO-PROD-BLDR) ← process supervisor (like systemd)
**Role**: Documentation generation at milestone boundaries. Generates API docs, architecture overviews, README updates, changelogs.
---
### 15. Timeline Update (`AUTO-TIME`)
@@ -223,6 +238,7 @@ product-builder (AUTO-PROD-BLDR) ← process supervisor (like systemd)
**Role**: Monitors project progress and updates `docs/timeline.md` with milestone status, schedule adherence, and PlantUML gantt chart entries.
---
### 16. Project Owner (`AUTO-OWNR`)
@@ -234,6 +250,7 @@ product-builder (AUTO-PROD-BLDR) ← process supervisor (like systemd)
**Role**: Autonomous strategic decision-maker. Triages unverified issues, assigns priority and scope labels, makes strategic decisions, and engages with developers. For the label system and ticket lifecycle this agent uses, see `cleveragents-contributing` and `cleverthis-guidelines` skills.
---
### 17. System Watchdog (`AUTO-WDOG`)
@@ -248,6 +265,7 @@ product-builder (AUTO-PROD-BLDR) ← process supervisor (like systemd)
**Special**: Has the broadest view — monitors ALL other agents and their tracking issues.
---
## Utility Subagents (No Session Tags)
@@ -6,6 +6,7 @@ The CleverAgents system runs as an OpenCode session (using `@opencode-ai/plugin`
**Critical rule**: Only `async-agent-manager` is permitted to make HTTP calls to `localhost:4096`. All other agents have this explicitly denied in their permissions. This centralises all async operations through a single, well-tested gateway.
---
## Why prompt_async Exists
@@ -24,6 +25,7 @@ Pool supervisors cannot use synchronous calls for workers because:
`prompt_async` solves this: the supervisor dispatches a worker, gets a 204 response immediately, and continues its main loop. Workers signal completion through Forgejo activity (comments, PRs, issue state changes) — the supervisor detects this by checking session status and Forgejo state on subsequent cycles.
---
## OpenCode Server API Reference
@@ -137,6 +139,7 @@ curl -s -X DELETE "http://localhost:4096/session/${SESSION_ID}"
Returns `true` with HTTP 200 on success.
---
## Session Naming Convention
@@ -191,6 +194,7 @@ All sessions follow the format: `[TAG] display-name`
| `AUTO-OWNR` | `[AUTO-OWNR-N]` | `[AUTO-OWNR-8]` |
| `AUTO-WDOG` | `[AUTO-WDOG-N]` | `[AUTO-WDOG-2]` |
---
## Common Operations (via async-agent-manager)
@@ -225,6 +229,7 @@ Workers completing normally is expected — they do their task and exit. The sup
Supervisors periodically prune completed worker sessions using async-agent-cleanup.
---
## Error Handling
@@ -4,6 +4,7 @@
Multiple agents may discover the same work item simultaneously. Without coordination, two agents might work on the same issue/PR concurrently, leading to conflicts. The system uses a **comment-based claiming protocol** on Forgejo issues and PRs to prevent this.
---
## Claim Protocol
@@ -84,6 +85,7 @@ Reason: completed | failed | timeout | error
**Automated by CleverAgents Bot**
```
---
## PR Work Coordination
@@ -100,6 +102,7 @@ When multiple agents may work on the same PR (e.g., implementation pool fixes a
**Wait policy**: If another agent has been working < 15 minutes → wait 5 minutes and retry. If > 15 minutes → they may be stuck; proceed anyway.
---
## Session-Level Deduplication (Supervisor Responsibility)
@@ -111,6 +114,7 @@ Beyond claim-level coordination, supervisors prevent duplicate dispatch by check
This tag-based deduplication is the PRIMARY mechanism. The claim protocol is a secondary safeguard for cases where the tag search might miss something.
---
## System Watchdog Monitoring of Coordination
@@ -123,6 +127,7 @@ The system-watchdog monitors for coordination violations:
When violations are detected, the watchdog dispatches a `system-watchdog-worker` to clean up and may create an announcement.
---
## Startup Deduplication
@@ -133,6 +138,7 @@ Product-builder prevents duplicate supervisors:
This prevents supervisor accumulation across restarts. Supervisors recover their state from Forgejo tracking issues, so stopping them causes no data loss.
---
## Bot Signatures
@@ -153,12 +159,13 @@ Agent: implementation-worker
This identifies automated content, helps humans understand which agent made a change, and is used by the coordination protocols to distinguish automated from human comments.
---
## Announcement Relevancy Matrix
The full canonical cross-agent attention table lives in
[`../tracking-system/announcement-matrix/`](../tracking-system/announcement-matrix/).
It lists every supervisor prefix with its complete source-and-minimum-priority matrix.
The full canonical cross-agent attention table is in **SKILL.md** under the
"Which announcements should I consume?" decision tree. It lists every supervisor
prefix with its complete source-and-minimum-priority matrix.
For dynamic lookup: use `agent-prefix-info` with `GET_RELEVANCY_MATRIX` to get
the table for any specific prefix programmatically.
@@ -31,6 +31,7 @@ git remote get-url origin
# → FORGEJO_REPO = cleveragents-core
```
---
## Credential Hierarchy
@@ -48,6 +49,7 @@ git commits, Forgejo API calls, etc.
**Key principle**: Every level explicitly passes ALL needed credentials to the next level. Nothing is inferred from environment variables after product-builder's initial read.
---
## The Two Bot Accounts
@@ -71,6 +73,7 @@ Credentials: `FORGEJO_REVIEWER_PAT`, `FORGEJO_REVIEWER_USERNAME`, `FORGEJO_REVIE
**Note**: product-builder detects this special case and passes reviewer credentials to `pr-review-pool-supervisor` instead of the primary credentials.
---
## Worker Credential Rules
@@ -98,6 +101,7 @@ The supervisor's prompt to the worker must include:
If a supervisor omits any of these, the worker cannot proceed. Supervisors are responsible for passing everything explicitly.
---
## Worker Count Configuration
@@ -117,6 +121,7 @@ Product-builder computes these values at startup and passes the appropriate coun
| If N = 16: | N_FULL=16, N_HALF=8, N_QUARTER=4 |
| If N = 1: | N_FULL=1, N_HALF=1, N_QUARTER=1 (minimums enforced) |
---
## Security Notes
@@ -1,97 +0,0 @@
# Operational Parameters — Key Numbers and Thresholds
All timing, sizing, and threshold values used across the autonomous agent system.
For the *complete* supervisor details (role descriptions, worker types, worker tag
patterns) see [`../agent-registry/`](../agent-registry/).
## Supervisor Registry — Quick Lookup Table
| # | Prefix | Agent Definition | Workers | Sleep | Tracking Prefix |
|---|--------|-----------------|---------|-------|-----------------|
| 0 | `AUTO-PROD-BLDR` | product-builder | N/A (monitors, not a pool) | 60 s | `AUTO-PROD-BLDR` |
| 1 | `AUTO-IMP-SUP` | implementation-pool-supervisor | N_FULL | 120 s | `AUTO-IMP-POOL` |
| 2 | `AUTO-REV-SUP` | pr-review-pool-supervisor | N_HALF | 30 s | `AUTO-REV-SUP` |
| 3 | `AUTO-PRMRG-SUP` | pr-merge-pool-supervisor | 0 (blocking subagent) | 300 s | `AUTO-PRMRG-SUP` |
| 4 | `AUTO-UAT-SUP` | uat-test-pool-supervisor | N_QUARTER | 600 s | `AUTO-UAT-SUP` |
| 5 | `AUTO-BUG-SUP` | bug-hunt-pool-supervisor | N_QUARTER | 900 s | `AUTO-BUG-SUP` |
| 6 | `AUTO-INF-SUP` | test-infra-pool-supervisor | N_QUARTER | 900 s | `AUTO-INF-SUP` |
| 7 | `AUTO-ARCH` | architecture-pool-supervisor | 1 | 1800 s | `AUTO-ARCH` |
| 8 | `AUTO-EPIC` | epic-planning-pool-supervisor | 1 | 600 s | `AUTO-EPIC` |
| 9 | `AUTO-HUMAN` | human-liaison-pool-supervisor | 1 | 120 s | `AUTO-HUMAN` |
| 10 | `AUTO-EVLV` | agent-evolution-pool-supervisor | 1 | 1800 s | `AUTO-EVLV` |
| 11 | `AUTO-GUARD` | architecture-guard-pool-supervisor | 1 | 600 s | `AUTO-GUARD` |
| 12 | `AUTO-SPEC` | spec-update-pool-supervisor | 1 | 900 s | `AUTO-SPEC` |
| 13 | `AUTO-GROOM` | grooming-pool-supervisor | 1 | 300 s | `AUTO-GROOM` |
| 14 | `AUTO-DOCS` | documentation-pool-supervisor | 1 | 1800 s | `AUTO-DOCS` |
| 15 | `AUTO-TIME` | timeline-update-pool-supervisor | 1 | 3600 s | `AUTO-TIME` |
| 16 | `AUTO-OWNR` | project-owner-pool-supervisor | 1 | 300 s | `AUTO-OWNR` |
| 17 | `AUTO-WDOG` | system-watchdog-pool-supervisor | 1 | 300 s | `AUTO-WATCHDOG` |
> **⚠️ `AUTO-WDOG` tracking prefix exception:** The session tag is `[AUTO-WDOG]` but
> the tracking issue prefix is `AUTO-WATCHDOG`. Don't confuse the two.
> **⚠️ `AUTO-PRMRG-SUP` worker count exception:** This supervisor calls
> `pr-merge-worker` as a **blocking Task subagent** — there are no `[AUTO-PRMRG-N]`
> async sessions. Worker count = 0 means "no async worker sessions", not "no work".
### Sleep Timeout Rule
Always set bash timeout to `sleep_duration × 1.5` minimum:
```bash
bash("sleep 300", timeout=450000) # 5 min sleep → 7.5 min timeout
bash("sleep 120", timeout=180000) # 2 min sleep → 3 min timeout
```
Never let the bash timeout be less than the sleep duration — the call will be
killed before the sleep completes.
## Worker Count Formula
Controlled by the `CA_MAX_PARALLEL_WORKERS` environment variable (default: 4).
Product-builder reads this at startup and passes the computed values to each supervisor.
```
N = CA_MAX_PARALLEL_WORKERS
N_FULL = N
N_HALF = max(1, N ÷ 2) # integer division; minimum 1
N_QUARTER = max(1, N ÷ 4) # integer division; minimum 1
```
| If N = 1 | N_FULL=1, N_HALF=1, N_QUARTER=1 | (minimums enforced) |
|----------|----------------------------------|---------------------|
| If N = 4 | N_FULL=4, N_HALF=2, N_QUARTER=1 | |
| If N = 8 | N_FULL=8, N_HALF=4, N_QUARTER=2 | |
| If N = 16 | N_FULL=16, N_HALF=8, N_QUARTER=4 | |
## Key Numbers — All Thresholds and Timings
| Parameter | Value | Context |
|-----------|-------|---------|
| `CA_MAX_PARALLEL_WORKERS` default | 4 | Set via environment variable |
| N_FULL | N | Implementation pool only |
| N_HALF | max(1, N ÷ 2) | PR review pool only |
| N_QUARTER | max(1, N ÷ 4) | UAT, Bug Hunt, Test Infra |
| Work claim expiry | 2 hours | Without heartbeat — see `references/coordination/` |
| Heartbeat interval | 10 minutes | Must send to maintain a claim |
| Rolling average formula | 0.90 × old + 0.10 × actual | Cycle interval smoothing |
| Status issue limit | 1 per prefix at a time | Older ones closed when new one created |
| Human escalation trigger | Opus tier × 3 same-problem failures | Apply `needs feedback` label |
| Forgejo API timeout | 30 seconds | Per individual HTTP request |
| Git operation timeout | 5 minutes | Local git commands |
| Test execution timeout | 15 minutes | Full test suite runs |
| Worker stuck threshold | 15 minutes idle | No new messages → classified as `stuck` |
| Product-builder fast cycle | 60 seconds | Liveness check + question-answering |
| Product-builder deep inspection | Every 5 fast cycles (~5 min) | Message reading, anti-pattern detection |
| Product-builder worker health check | Every 5 fast cycles (~5 min) | Pool count vs expected |
| Product-builder hourly cycle | Every ~60 fast cycles | Full verification + status ticket |
| Watchdog staleness threshold | 2 × estimated_cycle_interval | If tracking issue older → supervisor frozen |
| Supervisor max downtime | ≤ 60 seconds | product-builder fast cycle detects crash |
| Worker max downtime before re-dispatch | Supervisor's sleep interval | 2 min (IMP) to 60 min (TIME) |
| Max temp dir age | 24 hours | Cleaned automatically by repo-isolator |
| Forgejo MCP page limit | 50 per page | Always paginate exhaustively |
| Supervisor crash offline thresholds | < 30 min → light recovery | Resume from state |
| | 30120 min → moderate recovery | Re-verify key Forgejo state |
| | > 120 min → full re-scan | Treat as fresh start with hints |
@@ -12,6 +12,7 @@ Layer 3 — each supervisor monitors its own workers (every cycle)
No layer depends on another to detect problems — if product-builder is distracted or slow, system-watchdog independently detects frozen supervisors via Forgejo. If a supervisor's pool drains, product-builder notices the undercount before system-watchdog checks in.
---
## Layer 1: Product-Builder Monitoring
@@ -72,6 +73,7 @@ Product-builder manages its own context window explicitly:
**Critical limit**: product-builder itself has no external watcher. If it crashes or exhausts its context, a human must restart it. This is the only single point of failure in the system. All supervisor-level crashes self-heal; product-builder-level crashes require human intervention.
---
## Layer 2: System Watchdog
@@ -117,6 +119,7 @@ System-watchdog monitors supervisors but does NOT restart them. It creates:
Product-builder is responsible for actually relaunching failed supervisors.
---
## Layer 3: Supervisor Self-Monitoring of Workers
@@ -162,6 +165,7 @@ Each pool supervisor maintains a sliding window of active workers:
- The pool is continuously filled, not batch-dispatched
- A supervisor that stops filling its pool triggers product-builder's worker health check and gets relaunched
---
## State Persistence: The Foundation of Self-Healing
@@ -215,6 +219,7 @@ Self-healing only works because all state is externalized to Forgejo. No state l
8. New worker starts from the appropriate resumption point
```
---
## The Two Independent Health Signals
@@ -227,6 +232,7 @@ Understanding which signal catches which failure:
Together they provide complete coverage. A session can appear `busy` in OpenCode while being completely stuck (no Forgejo output) — only the staleness check catches this. A session can stop posting to Forgejo because it crashed — only the OpenCode check catches this.
---
## Detecting Specific Failure Modes
@@ -243,6 +249,7 @@ Together they provide complete coverage. A session can appear `busy` in OpenCode
| Multiple supervisors down | product-builder: repeated relaunch failures; system-watchdog: multiple stale tracking issues | product-builder: Priority/Critical announcement; human intervention |
| product-builder itself crashed | No automatic detection | Human must restart |
---
## The async-agent-monitor Subagent
@@ -260,6 +267,7 @@ Classifies sessions as:
The 15-minute threshold is configurable by the caller via `idle_threshold_minutes`. For short-cycle supervisors (120s sleep) this may be set lower; for long-cycle supervisors (1800s sleep) the default may be appropriate.
---
## Redundancy Gaps and Limitations
@@ -1,103 +0,0 @@
# Scripts Reference
Helper scripts for interacting with the Forgejo API. All scripts are written
in TypeScript and executed via `npx --yes tsx`. They require Node.js ≥ 18 and
zero external npm dependencies.
**Scripts directory:** [`scripts/`](../../scripts/)
## Available Scripts
### PR Listing Scripts
Six scripts that classify every open PR into one of six mutually exclusive
buckets. Together they cover the complete PR pipeline used by
`pr-merge-pool-supervisor` and `pr-review-pool-supervisor`.
| Script | One-liner |
|--------|-----------|
| [`list_prs`](./list_prs/) | General-purpose PR lister — all filter options (`--stale`, `--ci-status`, `--min-approvals`, …), importable as a module by the six wrappers below |
| [`list_prs_ready_to_merge`](./list_prs_ready_to_merge/) | Open PRs with ≥ 1 approval, already current with their base branch, **and CI passing** — merge immediately |
| [`list_prs_stale_clean`](./list_prs_stale_clean/) | Open PRs with ≥ 1 approval, behind their base branch, no conflicts, any CI status — server-side rebase then merge |
| [`list_prs_stale_conflicts`](./list_prs_stale_conflicts/) | Open PRs with ≥ 1 approval, behind their base branch, merge conflicts present, any CI status — local clone, resolve, force-push, then merge |
| [`list_prs_needs_review_not_stale`](./list_prs_needs_review_not_stale/) | Open PRs with zero approvals, current with their base branch, any CI status — review only needed |
| [`list_prs_needs_review_stale_clean`](./list_prs_needs_review_stale_clean/) | Open PRs with zero approvals, stale but conflict-free, any CI status — review + server-side rebase needed |
| [`list_prs_needs_review_stale_conflicts`](./list_prs_needs_review_stale_conflicts/) | Open PRs with zero approvals, stale with conflicts, any CI status — review + local conflict resolution needed |
### PR Action Scripts
| Script | One-liner |
|--------|-----------|
| [`rebase_pr`](./rebase_pr/) | Triggers a Forgejo server-side rebase on a single stale, conflict-free PR — no local clone required |
| [`merge_pr`](./merge_pr/) | Initiates a rebase-style merge (with automerge scheduling) on a single PR, handling open issue dependencies before calling the merge endpoint |
## The Six-Bucket Pipeline
The six listing scripts define a complete, non-overlapping classification of
open PRs. The two approval states (approved vs needs review) are each split
by three staleness states, giving six buckets in total. **Bucket 1 additionally
requires CI to be passing**; approved + not-stale PRs with failing or pending CI
are held out of all buckets until their CI resolves.
```
Every open PR belongs to exactly one bucket at any moment
(or is temporarily absent if CI is blocking it from Bucket 1):
── Approved (≥ 1 non-dismissed approval) ──────────────────────────────────
Bucket 1 — list_prs_ready_to_merge (approved + not stale + CI passing)
Bucket 2 — list_prs_stale_clean (approved + stale, no conflicts, any CI)
Bucket 3 — list_prs_stale_conflicts (approved + stale, has conflicts, any CI)
── Needs Review (0 approvals) ─────────────────────────────────────────────
Bucket 4 — list_prs_needs_review_not_stale (no approvals + not stale, any CI)
Bucket 5 — list_prs_needs_review_stale_clean (no approvals + stale, no conflicts, any CI)
Bucket 6 — list_prs_needs_review_stale_conflicts (no approvals + stale, has conflicts, any CI)
── Temporarily absent (not in any bucket) ─────────────────────────────────
• stale_state == stale_unknown → Forgejo still computing conflict status; appears shortly
• approved + not stale + CI failing/pending/unknown → held out of Bucket 1 until CI passes
```
Typical action sequence per bucket:
```
Bucket 1: merge_pr (CI already green — safe to merge immediately)
Bucket 2: rebase_pr → merge_pr
Bucket 3: clone → rebase locally → resolve conflicts → force-push → merge_pr
Bucket 4: (dispatch reviewer → on approval, moves to Bucket 1 if CI passes)
Bucket 5: (dispatch reviewer → on approval, moves to Bucket 2)
Bucket 6: (dispatch reviewer → on approval, moves to Bucket 3)
```
## Quick Invocation Reference
All scripts share the same four connection flags:
```bash
npx --yes tsx /app/.opencode/skills/auto-agents-system/scripts/<script>.ts \
--url <forgejo-base-url> \ # e.g. https://git.example.com
--pat <personal-access-token> \
--owner <repo-owner-or-org> \
--repo <repo-name>
```
`merge_pr` and `rebase_pr` additionally require `--pr <number>`.
`merge_pr` has an optional `--dep error|delete|reverse` flag.
The six `list_prs_*` wrappers accept **only** the four connection flags —
their filter parameters are hard-coded and cannot be overridden on the CLI.
`list_prs` itself accepts optional filter flags: `--state`, `--min-approvals`,
`--max-approvals`, `--mergeable`, `--stale`, and `--ci-status`.
**`--ci-status`** accepts a comma-separated whitelist of CI states to include:
`passing`, `failing`, `pending`, `unknown` (any combination). Omit to include
all CI states. Example: `--ci-status passing,pending`
Each PR object in all outputs now includes a `ci_status` field
(`passing` | `failing` | `pending` | `unknown`) derived from the Forgejo
combined commit-status endpoint for the PR's head SHA.
All scripts write JSON to **stdout** and progress/diagnostics to **stderr**.
Exit code `0` = success, `1` = error.
@@ -1,310 +0,0 @@
# list_prs — General Forgejo PR Listing Script
**Script name:** `list_prs`
**Script location:** [`scripts/list_prs.ts`](../../../scripts/list_prs.ts)
**Invoke:**
```bash
npx --yes tsx .opencode/skills/auto-agents-system/scripts/list_prs.ts \
--url URL --pat TOKEN --owner OWNER --repo REPO \
[--state open|closed|all] [--min-approvals N] [--max-approvals N] \
[--mergeable true|false] [--stale not_stale|stale_no_conflicts|stale_with_conflicts|stale_unknown] \
[--ci-status passing|failing|pending|unknown[,...]]
```
**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.ts --url URL --pat TOKEN --owner OWNER --repo REPO [OPTIONS]
```
Fetches all pull requests from a Forgejo repository, enriches each one with a
computed approval count, a staleness classification, and a priority rank, then
filters and sorts the results before writing a JSON array to stdout.
`list_prs.ts` is both a standalone CLI tool and the **importable core module**
used by the four thin wrapper scripts
(`list_prs_needs_review`, `list_prs_ready_to_merge`, `list_prs_stale_clean`,
`list_prs_stale_conflicts`). When imported, it exports `listPRs` and
`parseConnectionArgs` for use by those wrappers.
## Arguments
### Required
| 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 |
All four required flags must be present. Any missing flag causes an immediate
exit with code 1 and an error message to stderr.
### Optional Filters
All filter flags default to "no filter" (i.e. all values pass) when omitted.
| Flag | Type | Default | Description |
|------|------|---------|-------------|
| `--state open\|closed\|all` | string | `open` | Filter by PR state |
| `--min-approvals N` | integer ≥ 0 | (none) | Include only PRs with **≥ N** non-dismissed approvals |
| `--max-approvals N` | integer ≥ 0 | (none) | Include only PRs with **≤ N** non-dismissed approvals |
| `--mergeable true\|false` | boolean | (none) | Filter by Forgejo's raw `PR.mergeable` field |
| `--stale VALUE` | string | (none) | Filter by computed `stale_state` (see Stale States below) |
| `--ci-status VALUE[,...]` | string | (none) | Comma-separated whitelist of CI statuses to include (see CI Status below). Omit to include all CI statuses. |
| `-h`, `--help` | — | — | Print usage to stderr and exit 0 |
### Argument Validity Rules
- `--min-approvals` and `--max-approvals` may be used together; both constraints apply simultaneously (logical AND).
- `--min-approvals 1 --max-approvals 0` is logically impossible and will return an empty result set — the script does not reject it, it simply matches nothing.
- `--mergeable` filters on the raw API field, not on the computed `stale_state`. Use `--stale` for the semantically richer classification.
- `--ci-status` accepts a comma-separated list of values from `passing`, `failing`, `pending`, `unknown`. A PR must match **any one** of the listed values (logical OR within the list). Multiple `--ci-status` flags are not supported — put all desired values in one comma-separated argument.
- Any unknown flag causes exit code 1 and a usage message.
- `--state` only accepts the three literal values `open`, `closed`, `all`; any other value is passed to the API which may behave unexpectedly (this is not validated client-side).
## Output
Written to **stdout** as a pretty-printed JSON array. Each element is the full
Forgejo PR object as returned by the API, augmented with four additional fields:
| Field | Type | Description |
|-------|------|-------------|
| `approvals_count` | integer | Count of distinct non-dismissed `APPROVED` reviews. Per-reviewer: only the reviewer's most recent review is counted; if they later submitted `REQUEST_CHANGES`, that supersedes the approval and it is not counted. |
| `stale_state` | string | One of five stale states (see below) |
| `ci_status` | string | One of four CI status values (see CI Status below) |
| `priority_rank` | integer | 0 = `Priority/CI Blocker` (highest), …, 5 = `Priority/Backlog`, 6 = unlabelled |
| `priority_label` | string \| null | The matched `Priority/*` label name, or `null` if none present |
The array is **sorted ascending by `priority_rank`** so the most urgent PRs appear
first within the result set.
### Stale States
| `stale_state` value | Meaning |
|---------------------|---------|
| `not_stale` | `PR.merge_base == base branch HEAD` — PR is fully up-to-date |
| `stale_no_conflicts` | Base has advanced AND `PR.mergeable == true` — clean auto-rebase possible |
| `stale_with_conflicts` | Base has advanced AND `PR.mergeable == false` — manual resolution required |
| `stale_unknown` | Base has advanced AND `PR.mergeable == null` — Forgejo is still computing |
| `compute_error` | `PR.merge_base` or base HEAD SHA is missing; classification impossible |
### CI Status
Derived from `GET /api/v1/repos/{owner}/{repo}/commits/{head_sha}/status` — the Forgejo combined commit-status endpoint. The `state` field of that response is mapped as follows:
| `ci_status` value | Forgejo combined state | Meaning |
|-------------------|----------------------|---------|
| `passing` | `success` | All status checks have reported success |
| `failing` | `failure` \| `error` \| `warning` | At least one check has failed or errored |
| `pending` | `pending` | Checks are queued or still running |
| `unknown` | `""` \| `unknown` | No status checks have been reported for this commit |
Use `--ci-status passing` to restrict to PRs where all CI has passed. Use `--ci-status passing,pending` to include both passing and still-running PRs. Omit `--ci-status` entirely to return PRs regardless of their CI state.
### Priority Rank Table
| `priority_rank` | Label |
|----------------|-------|
| 0 | `Priority/CI Blocker` |
| 1 | `Priority/Critical` |
| 2 | `Priority/High` |
| 3 | `Priority/Medium` |
| 4 | `Priority/Low` |
| 5 | `Priority/Backlog` |
| 6 | (no `Priority/*` label present) |
## Diagnostics / stderr
Progress messages are written to stderr during execution (not to stdout, so
they do not contaminate 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: 12/42 PR(s) matched the filter criteria.
```
Warnings about individual failures (e.g. a branch API error for one PR) are
also written to stderr. The script continues processing the remaining PRs
rather than aborting.
## Exit Codes
| Code | Meaning |
|------|---------|
| 0 | Success — JSON array written to stdout (may be empty `[]`) |
| 1 | Fatal error — message written to stderr |
## Errors the Script May Throw
| Condition | Behaviour |
|-----------|-----------|
| Missing required `--url`, `--pat`, `--owner`, or `--repo` | Exit 1 with descriptive message |
| Unknown CLI flag | Exit 1 with usage message |
| API returns non-2xx for the PR list | Throws; script exits 1 with the HTTP status and body |
| API returns non-2xx for a base branch HEAD | Logs a warning to stderr; marks affected PRs as `compute_error`; continues |
| API returns non-2xx for a PR's reviews | Logs a warning; treats that PR as having 0 approvals; continues |
| Network timeout (30 s per request) | Throws; script exits 1 |
## Performance Notes
The script uses concurrent fetch chains to minimise wall-clock time:
- **PR pages** are fetched in parallel batches of 6 pages at a time.
- **Base-branch HEAD SHAs** are fetched simultaneously for all unique branches (cached: one call per unique branch regardless of how many PRs share it).
- **Reviews** are fetched with up to 20 concurrent in-flight requests at once.
For a repository with ~326 PRs, this reduces review-fetching from ~230 s
(sequential) to ~1.7 s.
## When to Use This Script
Use `list_prs.ts` directly when you need **custom filter combinations** not
served by one of the four wrapper scripts:
- List all closed PRs: `--state closed`
- Find PRs with exactly 2 approvals: `--min-approvals 2 --max-approvals 2`
- Find approved PRs that are still pending Forgejo's conflict check: `--min-approvals 1 --stale stale_unknown`
- List all PRs regardless of state: `--state all`
- Find open PRs ready to merge (approved, not stale, CI passing): `--min-approvals 1 --stale not_stale --ci-status passing`
- Find PRs with broken CI: `--ci-status failing`
- Find PRs with passing or pending CI: `--ci-status passing,pending`
For the four standard operating buckets used by `pr-merge-pool-supervisor`,
prefer the thin wrappers — they are self-documenting and require fewer flags.
## Usage Examples
```bash
# List all open PRs (no filters — returns everything)
npx --yes tsx /app/.opencode/skills/auto-agents-system/scripts/list_prs.ts \
--url https://git.example.com \
--pat ghp_XXXX \
--owner my-org \
--repo my-repo
# List open PRs with at least 1 approval that are not stale
npx --yes tsx /app/.opencode/skills/auto-agents-system/scripts/list_prs.ts \
--url https://git.example.com \
--pat ghp_XXXX \
--owner my-org \
--repo my-repo \
--min-approvals 1 \
--stale not_stale
# List open PRs awaiting a first review (0 approvals)
npx --yes tsx /app/.opencode/skills/auto-agents-system/scripts/list_prs.ts \
--url https://git.example.com \
--pat ghp_XXXX \
--owner my-org \
--repo my-repo \
--max-approvals 0
# List all closed PRs (for audit/history purposes)
npx --yes tsx /app/.opencode/skills/auto-agents-system/scripts/list_prs.ts \
--url https://git.example.com \
--pat ghp_XXXX \
--owner my-org \
--repo my-repo \
--state closed
# Extract just PR numbers from the result using jq
npx --yes tsx /app/.opencode/skills/auto-agents-system/scripts/list_prs.ts \
--url https://git.example.com --pat ghp_XXXX \
--owner my-org --repo my-repo --min-approvals 1 \
| jq '[.[].number]'
```
## Agent Usage Examples
### pr-merge-pool-supervisor
The supervisor does **not** call `list_prs.ts` directly. It calls the four
purpose-built wrapper scripts to populate its four work queues each cycle.
It would only call `list_prs.ts` directly if it needed a custom filter
combination not covered by those wrappers (e.g. investigating `stale_unknown`
PRs to determine if Forgejo is lagging).
### pr-merge-worker
The worker does **not** call `list_prs.ts`. It receives a specific PR number
from the supervisor and operates on that single PR. However, a worker
implementing complex decision logic could import `listPRs` programmatically
to inspect the state of all PRs before deciding how to proceed.
### system-watchdog-pool-supervisor
The watchdog could use `list_prs.ts` with `--state all` or custom filter
combinations to audit the full PR pipeline — for example, to detect PRs
that have been open for an unusually long time, or to count approved PRs
that are not progressing through the merge pipeline.
### implementation-pool-supervisor
The implementation supervisor might use `list_prs.ts` with
`--min-approvals 0 --max-approvals 0` (or equivalently `list_prs_needs_review`)
to check whether any of its submitted PRs are awaiting a first review, so it
can decide whether to dispatch more implementation workers or wait for review
capacity to clear.
## Module API (when imported)
```typescript
import { listPRs, parseConnectionArgs } from './list_prs.ts';
// Config object
const config: Config = {
url: 'https://git.example.com',
pat: 'ghp_XXXX',
owner: 'my-org',
repo: 'my-repo',
};
// Filters object (all fields optional)
const filters: Filters = {
state: 'open',
minApprovals: 1,
stale: 'not_stale',
ciStatus: ['passing'], // only PRs with all CI checks passing
};
// ciStatus accepts any combination:
// ciStatus: ['passing'] — CI must have passed
// ciStatus: ['pending'] — CI still running
// ciStatus: ['failing'] — CI has failed
// ciStatus: ['passing', 'pending'] — CI passed or still running
// (omit ciStatus entirely) — any CI state passes through
const prs: AugmentedPR[] = await listPRs(config, filters);
```
The exported `parseConnectionArgs(argv)` function parses only the four
connection flags (`--url`, `--pat`, `--owner`, `--repo`) and is used by the
four wrapper scripts. It rejects any unknown flag with an informative error.
## Dependencies
- Node.js ≥ 18 (native `fetch` API, stable since v21; available unflagged since v18)
- `npx tsx` for TypeScript execution (auto-installed by `npx --yes tsx`)
- Zero external npm packages — uses only Node.js built-ins
@@ -1,242 +0,0 @@
# list_prs_needs_review_not_stale — Open PRs With No Approvals, Up-to-Date
**Script name:** `list_prs_needs_review_not_stale`
**Script location:** [`scripts/list_prs_needs_review_not_stale.ts`](../../../scripts/list_prs_needs_review_not_stale.ts)
**Invoke:**
```bash
npx --yes tsx .opencode/skills/auto-agents-system/scripts/list_prs_needs_review_not_stale.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_needs_review_not_stale.ts --url URL --pat TOKEN --owner OWNER --repo REPO
```
Returns all **open** pull requests that have **zero non-dismissed approvals**
and are **not stale** — i.e. the PR's `merge_base` already matches the current
HEAD of its base branch. The PR is fully up-to-date and requires no rebase
before merging.
These are the simplest PRs in the "needs review" set: once a reviewer approves
them, they can be merged immediately without any additional rebase or conflict
resolution step.
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'
maxApprovals: 0
stale: 'not_stale'
(no ciStatus filter — all CI 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 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 |
| `maxApprovals` | `0` | PRs with zero non-dismissed `APPROVED` reviews |
| `stale` | `not_stale` | `PR.merge_base` equals the current base branch HEAD |
**"Not stale"** means `PR.merge_base == current base branch HEAD`: the base
branch has not advanced since the PR's head was last reconciled, so no rebase
is needed.
**"Zero approvals"** means: no reviewer has an active (non-dismissed) `APPROVED`
review as their most recent review. A reviewer who approved and then later
submitted `REQUEST_CHANGES` is not counted as an approver.
## 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 | Will always be `not_stale` for results of this script |
| `ci_status` | string | `passing`, `failing`, `pending`, or `unknown`**not filtered**; any CI state is included |
| `priority_rank` | integer | 0 (highest) through 6 (unlabelled) |
| `priority_label` | string \| null | Matched `Priority/*` label name, or `null` |
An **empty array** `[]` is a valid and common result — it means all open
up-to-date PRs already have at least one approval.
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: 8/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_needs_review_not_stale` when you want to identify PRs that are
**waiting for a first review and are already current with their base branch**.
Typical use cases:
- **`pr-review-pool-supervisor`** uses this as its highest-priority review
bucket: once approved, these PRs merge cleanly with no further action.
- A **review dispatcher** agent can prioritise these over stale PRs since
reviewing them provides immediate merge readiness.
- A **monitoring agent** can track this bucket to detect a backlog of fresh
PRs waiting for review.
### Position in the Six-Bucket System
```
Every open PR belongs to exactly one bucket at any moment:
Bucket 1 — list_prs_ready_to_merge (approved + not stale)
Bucket 2 — list_prs_stale_clean (approved + stale, no conflicts)
Bucket 3 — list_prs_stale_conflicts (approved + stale, has conflicts)
Bucket 4 — list_prs_needs_review_not_stale (no approvals + not stale) ← THIS SCRIPT
Bucket 5 — list_prs_needs_review_stale_clean (no approvals + stale, no conflicts)
Bucket 6 — list_prs_needs_review_stale_conflicts (no approvals + stale, has conflicts)
Exception: PRs with stale_state == stale_unknown are transiently absent from
all buckets while Forgejo computes conflict status. They appear shortly.
```
Workflow for a PR in this bucket once approved:
```
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_needs_review_not_stale.ts \
--url https://git.example.com \
--pat ghp_XXXX \
--owner my-org \
--repo my-repo
# Count how many fresh PRs are waiting for a first review
npx --yes tsx /app/.opencode/skills/auto-agents-system/scripts/list_prs_needs_review_not_stale.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_needs_review_not_stale.ts \
--url https://git.example.com \
--pat ghp_XXXX \
--owner my-org \
--repo my-repo \
| jq '[.[] | {number, title}]'
# Get only the highest-priority PR needing review
npx --yes tsx /app/.opencode/skills/auto-agents-system/scripts/list_prs_needs_review_not_stale.ts \
--url https://git.example.com \
--pat ghp_XXXX \
--owner my-org \
--repo my-repo \
| jq 'first'
```
## Agent Usage Examples
### pr-review-pool-supervisor
The supervisor can call this script to find its highest-priority review
targets — PRs that will merge immediately after approval. It dispatches
`pr-reviewer` workers for each result.
```bash
npx --yes tsx /app/.opencode/skills/auto-agents-system/scripts/list_prs_needs_review_not_stale.ts \
--url $FORGEJO_URL \
--pat $FORGEJO_PAT \
--owner $REPO_OWNER \
--repo $REPO_NAME
```
### pr-merge-pool-supervisor
The merge supervisor uses this to surface PRs waiting for review that will
have the simplest post-approval workflow. An empty result here (combined with
non-empty stale buckets) suggests review bandwidth is being absorbed by PRs
that still have pending rebase work.
### human-liaison-pool-supervisor
The human liaison can filter by `created_at` to identify PRs that have been
waiting for a first review for too long, then post reminder comments or alert
human reviewers.
## Dependencies
- Node.js ≥ 18 (native `fetch` API)
- `npx tsx` for TypeScript execution
- Zero external npm packages
@@ -1,238 +0,0 @@
# list_prs_needs_review_stale_clean — Open PRs With No Approvals, Stale, No Conflicts
**Script name:** `list_prs_needs_review_stale_clean`
**Script location:** [`scripts/list_prs_needs_review_stale_clean.ts`](../../../scripts/list_prs_needs_review_stale_clean.ts)
**Invoke:**
```bash
npx --yes tsx .opencode/skills/auto-agents-system/scripts/list_prs_needs_review_stale_clean.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_needs_review_stale_clean.ts --url URL --pat TOKEN --owner OWNER --repo REPO
```
Returns all **open** pull requests that have **zero non-dismissed approvals**,
are **stale** (the base branch has advanced since the PR was last synced), and
have **no merge conflicts** (`PR.mergeable == true`). These PRs need a first
review AND will require a server-side rebase before or after approval — but no
conflict resolution will be required.
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'
maxApprovals: 0
stale: 'stale_no_conflicts'
(no ciStatus filter — all CI 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 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 |
| `maxApprovals` | `0` | PRs with zero non-dismissed `APPROVED` reviews |
| `stale` | `stale_no_conflicts` | Base has advanced AND `PR.mergeable == true` |
**"Stale no conflicts"** means two things are simultaneously true:
1. `PR.merge_base != current base branch HEAD` — the base branch has been pushed to since the PR was last synced.
2. `PR.mergeable == true` — Forgejo has determined that rebasing the PR's commits onto the new base would succeed without any merge conflicts.
**"Zero approvals"** means: no reviewer has an active (non-dismissed) `APPROVED`
review as their most recent review.
## 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 | Will always be `stale_no_conflicts` for results of this script |
| `ci_status` | string | `passing`, `failing`, `pending`, or `unknown`**not filtered**; any CI state is included |
| `priority_rank` | integer | 0 (highest) through 6 (unlabelled) |
| `priority_label` | string \| null | Matched `Priority/*` label name, or `null` |
An **empty array** `[]` is a valid and common result — it means no open
stale-but-clean PRs are currently awaiting a first review.
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_needs_review_stale_clean` when you want to identify PRs that are
**waiting for a first review and will need a server-side rebase before
merging** (but no conflict resolution). Typical use cases:
- **`pr-review-pool-supervisor`** uses this as a medium-priority review
bucket. After approving one of these PRs, the merge workflow is:
`rebase_pr` then `merge_pr` — no local clone required.
- A **review dispatcher** can distinguish these from `not_stale` PRs to
inform the review prioritisation strategy.
- A **monitoring agent** can track a growing bucket here as a signal that
the base branch is advancing faster than reviewers are approving PRs.
### Position in the Six-Bucket System
```
Every open PR belongs to exactly one bucket at any moment:
Bucket 1 — list_prs_ready_to_merge (approved + not stale)
Bucket 2 — list_prs_stale_clean (approved + stale, no conflicts)
Bucket 3 — list_prs_stale_conflicts (approved + stale, has conflicts)
Bucket 4 — list_prs_needs_review_not_stale (no approvals + not stale)
Bucket 5 — list_prs_needs_review_stale_clean (no approvals + stale, no conflicts) ← THIS SCRIPT
Bucket 6 — list_prs_needs_review_stale_conflicts (no approvals + stale, has conflicts)
Exception: PRs with stale_state == stale_unknown are transiently absent from
all buckets while Forgejo computes conflict status. They appear shortly.
```
Workflow for a PR in this bucket once approved:
```
Reviewer approves → PR moves to list_prs_stale_clean → rebase_pr → merge_pr
```
## Usage Examples
```bash
# Standard usage
npx --yes tsx /app/.opencode/skills/auto-agents-system/scripts/list_prs_needs_review_stale_clean.ts \
--url https://git.example.com \
--pat ghp_XXXX \
--owner my-org \
--repo my-repo
# Count stale-clean PRs awaiting first review
npx --yes tsx /app/.opencode/skills/auto-agents-system/scripts/list_prs_needs_review_stale_clean.ts \
--url https://git.example.com \
--pat ghp_XXXX \
--owner my-org \
--repo my-repo \
| jq 'length'
# Get PR numbers, titles, and their base branches
npx --yes tsx /app/.opencode/skills/auto-agents-system/scripts/list_prs_needs_review_stale_clean.ts \
--url https://git.example.com \
--pat ghp_XXXX \
--owner my-org \
--repo my-repo \
| jq '[.[] | {number, title, base: .base.ref}]'
# Get the highest-priority stale-clean PR awaiting review
npx --yes tsx /app/.opencode/skills/auto-agents-system/scripts/list_prs_needs_review_stale_clean.ts \
--url https://git.example.com \
--pat ghp_XXXX \
--owner my-org \
--repo my-repo \
| jq 'first'
```
## Agent Usage Examples
### pr-review-pool-supervisor
The supervisor dispatches `pr-reviewer` workers for PRs found in this bucket.
After approval, the merge supervisor's `list_prs_stale_clean` script will pick
them up for server-side rebase and merge.
```bash
result=$(npx --yes tsx /app/.opencode/skills/auto-agents-system/scripts/list_prs_needs_review_stale_clean.ts \
--url $FORGEJO_URL --pat $FORGEJO_PAT --owner $REPO_OWNER --repo $REPO_NAME)
# If non-empty → dispatch pr-reviewer for each PR
```
### pr-merge-pool-supervisor
The merge supervisor can use the combined sizes of this bucket and
`list_prs_needs_review_not_stale` to understand total review demand. A large
combined backlog relative to approved buckets signals under-capacity in the
review pool.
### system-watchdog-pool-supervisor
A growing `list_prs_needs_review_stale_clean` bucket over consecutive watchdog
cycles — while PRs in `list_prs_stale_clean` (approved) are being processed
normally — suggests that review capacity is insufficient to keep pace with
incoming PRs.
## Dependencies
- Node.js ≥ 18 (native `fetch` API)
- `npx tsx` for TypeScript execution
- Zero external npm packages
@@ -1,244 +0,0 @@
# list_prs_needs_review_stale_conflicts — Open PRs With No Approvals, Stale, With Conflicts
**Script name:** `list_prs_needs_review_stale_conflicts`
**Script location:** [`scripts/list_prs_needs_review_stale_conflicts.ts`](../../../scripts/list_prs_needs_review_stale_conflicts.ts)
**Invoke:**
```bash
npx --yes tsx .opencode/skills/auto-agents-system/scripts/list_prs_needs_review_stale_conflicts.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_needs_review_stale_conflicts.ts --url URL --pat TOKEN --owner OWNER --repo REPO
```
Returns all **open** pull requests that have **zero non-dismissed approvals**,
are **stale** (the base branch has advanced since the PR was last synced), and
**have merge conflicts** (`PR.mergeable == false`). These PRs need a first
review AND require manual conflict resolution — they have the most complex
path to merge of any PR awaiting review.
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'
maxApprovals: 0
stale: 'stale_with_conflicts'
(no ciStatus filter — all CI 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 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 |
| `maxApprovals` | `0` | PRs with zero non-dismissed `APPROVED` reviews |
| `stale` | `stale_with_conflicts` | Base has advanced AND `PR.mergeable == false` |
**"Stale with conflicts"** means two things are simultaneously true:
1. `PR.merge_base != current base branch HEAD` — the base branch has been pushed to since the PR was last synced.
2. `PR.mergeable == false` — Forgejo has determined that rebasing the PR's commits onto the new base would produce merge conflicts that cannot be resolved automatically.
**"Zero approvals"** means: no reviewer has an active (non-dismissed) `APPROVED`
review as their most recent review.
## 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 | Will always be `stale_with_conflicts` for results of this script |
| `ci_status` | string | `passing`, `failing`, `pending`, or `unknown`**not filtered**; any CI state is included |
| `priority_rank` | integer | 0 (highest) through 6 (unlabelled) |
| `priority_label` | string \| null | Matched `Priority/*` label name, or `null` |
An **empty array** `[]` is a valid and common result — it means no open
conflicted PRs are currently awaiting a first review.
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: 2/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_needs_review_stale_conflicts` when you want to identify the
**highest-complexity PRs awaiting review** — those that need both a reviewer
AND conflict resolution before they can merge. Typical use cases:
- **`pr-review-pool-supervisor`** uses this as its lowest-priority review
bucket (these PRs have the most work remaining after review).
- A **human-liaison agent** can use this to surface a conflict-backlog report:
"These N PRs are not yet reviewed AND already have conflicts — they need
author attention to resolve the conflicts first."
- A **monitoring agent** can track a growing bucket here as a compound health
signal: both review bandwidth AND code divergence are problems.
### Position in the Six-Bucket System
```
Every open PR belongs to exactly one bucket at any moment:
Bucket 1 — list_prs_ready_to_merge (approved + not stale)
Bucket 2 — list_prs_stale_clean (approved + stale, no conflicts)
Bucket 3 — list_prs_stale_conflicts (approved + stale, has conflicts)
Bucket 4 — list_prs_needs_review_not_stale (no approvals + not stale)
Bucket 5 — list_prs_needs_review_stale_clean (no approvals + stale, no conflicts)
Bucket 6 — list_prs_needs_review_stale_conflicts (no approvals + stale, has conflicts) ← THIS SCRIPT
Exception: PRs with stale_state == stale_unknown are transiently absent from
all buckets while Forgejo computes conflict status. They appear shortly.
```
Workflow for a PR in this bucket once approved:
```
Reviewer approves → PR moves to list_prs_stale_conflicts
→ clone repo → rebase locally → resolve conflicts → force-push → merge_pr
```
Note: Conflict resolution may need to happen **before** review if the PR
author is asked to fix their branch first. Whether review comes before or after
conflict resolution is a project workflow decision — this script surfaces the
set of PRs where both are pending.
## Usage Examples
```bash
# Standard usage
npx --yes tsx /app/.opencode/skills/auto-agents-system/scripts/list_prs_needs_review_stale_conflicts.ts \
--url https://git.example.com \
--pat ghp_XXXX \
--owner my-org \
--repo my-repo
# Count conflicted PRs awaiting first review
npx --yes tsx /app/.opencode/skills/auto-agents-system/scripts/list_prs_needs_review_stale_conflicts.ts \
--url https://git.example.com \
--pat ghp_XXXX \
--owner my-org \
--repo my-repo \
| jq 'length'
# Get PR numbers, titles, and head/base branches (useful for conflict resolution planning)
npx --yes tsx /app/.opencode/skills/auto-agents-system/scripts/list_prs_needs_review_stale_conflicts.ts \
--url https://git.example.com \
--pat ghp_XXXX \
--owner my-org \
--repo my-repo \
| jq '[.[] | {number, title, head_branch: .head.ref, base_branch: .base.ref}]'
# Get the highest-priority conflicted PR awaiting review
npx --yes tsx /app/.opencode/skills/auto-agents-system/scripts/list_prs_needs_review_stale_conflicts.ts \
--url https://git.example.com \
--pat ghp_XXXX \
--owner my-org \
--repo my-repo \
| jq 'first'
```
## Agent Usage Examples
### pr-review-pool-supervisor
The supervisor dispatches `pr-reviewer` workers for PRs in this bucket as
lowest priority. The reviewer is informed that conflicts also exist and may
note this in their review feedback.
```bash
result=$(npx --yes tsx /app/.opencode/skills/auto-agents-system/scripts/list_prs_needs_review_stale_conflicts.ts \
--url $FORGEJO_URL --pat $FORGEJO_PAT --owner $REPO_OWNER --repo $REPO_NAME)
# If non-empty → dispatch pr-reviewer for each PR (note conflict state in prompt)
```
### human-liaison-pool-supervisor
The liaison can filter results by `created_at` to identify PRs stuck in this
worst-case state for an extended period — no review AND conflicts — and post
a comment pinging the PR author to fix the conflicts first, making the PR
easier to review.
### system-watchdog-pool-supervisor
A growing `list_prs_needs_review_stale_conflicts` bucket is a compound health
signal: it indicates that neither the review pipeline nor the conflict
resolution pipeline is keeping pace with incoming work. The watchdog should
create a `Priority/High` announcement if this bucket exceeds a threshold.
## Dependencies
- Node.js ≥ 18 (native `fetch` API)
- `npx tsx` for TypeScript execution
- Zero external npm packages
@@ -1,242 +0,0 @@
# list_prs_ready_to_merge — Open PRs Approved, Up-to-Date, and CI Passing
**Script name:** `list_prs_ready_to_merge`
**Script location:** [`scripts/list_prs_ready_to_merge.ts`](../../../scripts/list_prs_ready_to_merge.ts)
**Invoke:**
```bash
npx --yes tsx .opencode/skills/auto-agents-system/scripts/list_prs_ready_to_merge.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_ready_to_merge.ts --url URL --pat TOKEN --owner OWNER --repo REPO
```
Returns all **open** pull requests that have **at least 1 non-dismissed
approval**, are **not stale** (the PR's head branch is already current with
its base branch), and have **passing CI** (all commit status checks have
succeeded). These PRs are ready to be merged immediately — no rebase,
conflict resolution, or CI wait is required.
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'
minApprovals: 1
stale: 'not_stale'
ciStatus: ['passing']
```
## 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 |
| `minApprovals` | `1` | At least one non-dismissed `APPROVED` review required |
| `stale` | `not_stale` | `PR.merge_base == current base branch HEAD` |
| `ciStatus` | `['passing']` | All CI checks must have succeeded (`ci_status == 'passing'`) |
**"Not stale"** means `PR.merge_base` (the common ancestor SHA between the PR
head and the base) equals the current HEAD of the base branch. In other words,
the base branch has not advanced since the PR was last synced — the PR can be
merged into the base branch without a rebase.
**"At least 1 approval"** means at least one reviewer has their most recent
review in `APPROVED` state (non-dismissed). A reviewer who approved then later
submitted `REQUEST_CHANGES` is not counted.
**"CI passing"** means the Forgejo combined commit-status for the PR's head
SHA returned `state == 'success'`. PRs with `pending` CI (still running),
`failing` CI (at least one check failed), or `unknown` CI (no checks reported)
are excluded. This prevents merging code before the full test suite has
confirmed it is safe.
## 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 ≥ 1 for results of this script |
| `stale_state` | string | Will always be `not_stale` for results of 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 satisfies both conditions.
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_ready_to_merge` when you need a list of PRs that can be merged
**right now** without any intermediate steps. Typical use cases:
- **`pr-merge-pool-supervisor`** calls this as the **first and highest-priority
step** in its cycle. Processing these PRs first ensures that already-approved,
current PRs are never delayed while rebase or review work is happening.
- A **monitoring agent** can use this as a health indicator: a consistently
non-empty result that never shrinks suggests the merge process is blocked.
- A **deployment pipeline** trigger could use this to determine whether any
code is ready for release.
### Priority in the Four-Bucket System
```
pr-merge-pool-supervisor processes buckets in this order:
1. list_prs_ready_to_merge ← THIS SCRIPT (highest priority)
2. list_prs_stale_clean
3. list_prs_stale_conflicts
4. list_prs_needs_review
When this bucket is non-empty, the supervisor dispatches workers for
ALL PRs in it and then restarts the cycle at step 1.
```
## Usage Examples
```bash
# Standard usage
npx --yes tsx /app/.opencode/skills/auto-agents-system/scripts/list_prs_ready_to_merge.ts \
--url https://git.example.com \
--pat ghp_XXXX \
--owner my-org \
--repo my-repo
# Count ready-to-merge PRs
npx --yes tsx /app/.opencode/skills/auto-agents-system/scripts/list_prs_ready_to_merge.ts \
--url https://git.example.com \
--pat ghp_XXXX \
--owner my-org \
--repo my-repo \
| jq 'length'
# Extract PR numbers for iteration
READY_PRS=$(npx --yes tsx /app/.opencode/skills/auto-agents-system/scripts/list_prs_ready_to_merge.ts \
--url https://git.example.com \
--pat ghp_XXXX \
--owner my-org \
--repo my-repo \
| jq '[.[].number]')
# Get only the top-priority ready PR
npx --yes tsx /app/.opencode/skills/auto-agents-system/scripts/list_prs_ready_to_merge.ts \
--url https://git.example.com \
--pat ghp_XXXX \
--owner my-org \
--repo my-repo \
| jq 'first'
```
## Agent Usage Examples
### pr-merge-pool-supervisor
The supervisor calls this script as **step 2** (the first work step) of its
main cycle. If the list is non-empty, it dispatches `pr-merge-worker`
sequentially for each PR and then restarts the cycle from step 1.
```bash
result=$(npx --yes tsx /app/.opencode/skills/auto-agents-system/scripts/list_prs_ready_to_merge.ts \
--url $FORGEJO_URL --pat $FORGEJO_PAT --owner $REPO_OWNER --repo $REPO_NAME)
# If non-empty → iterate and dispatch pr-merge-worker for each PR number
```
The supervisor passes each PR's full JSON object (number, title, head SHA,
base branch, staleness, approval count, etc.) in the `pr-merge-worker` prompt.
Since results come from this script, the worker knows the PR is already
approved and not stale — it calls [`merge_pr`](../merge_pr/) directly without
needing to rebase first.
### pr-merge-worker
When dispatched for a PR found by `list_prs_ready_to_merge`, the worker's
decision tree is simple: the PR is approved and current, so it calls
[`merge_pr`](../merge_pr/) immediately without checking for staleness or
conflicts.
### system-watchdog-pool-supervisor
The watchdog could call this periodically to verify that the merge pipeline
is healthy. A PR that appears in `list_prs_ready_to_merge` for many
consecutive watchdog cycles without being merged indicates the
`pr-merge-pool-supervisor` may be stuck or absent.
## Dependencies
- Node.js ≥ 18 (native `fetch` API)
- `npx tsx` for TypeScript execution
- Zero external npm packages
@@ -1,237 +0,0 @@
# list_prs_stale_clean — Open PRs Approved, Behind Base, No Conflicts
**Script name:** `list_prs_stale_clean`
**Script location:** [`scripts/list_prs_stale_clean.ts`](../../../scripts/list_prs_stale_clean.ts)
**Invoke:**
```bash
npx --yes tsx .opencode/skills/auto-agents-system/scripts/list_prs_stale_clean.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_stale_clean.ts --url URL --pat TOKEN --owner OWNER --repo REPO
```
Returns all **open** pull requests that have **at least 1 non-dismissed
approval**, are **stale** (the base branch has advanced since the PR was last
synced), and have **no merge conflicts** (`PR.mergeable == true`). These PRs
are approved and almost ready — they just need a server-side rebase to bring
them current before merging.
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'
minApprovals: 1
stale: 'stale_no_conflicts'
(no ciStatus filter — all CI 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:
`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. Passing any filter-style flag
(e.g. `--min-approvals`, `--stale`, `--state`) causes immediate exit 1.
## Hard-Coded Filters
| Filter | Value | Meaning |
|--------|-------|---------|
| `state` | `open` | Only open PRs are returned |
| `minApprovals` | `1` | At least one non-dismissed `APPROVED` review required |
| `stale` | `stale_no_conflicts` | Base has advanced AND `PR.mergeable == true` |
**"Stale no conflicts"** means two things are simultaneously true:
1. `PR.merge_base != current base branch HEAD` — the base branch has been pushed to since the PR was last synced.
2. `PR.mergeable == true` — Forgejo has determined the PR's commits can be rebased/merged on top of the new base without producing conflicts.
This combination means the rebase can be triggered automatically via the
Forgejo server-side rebase API (`POST /pulls/{index}/update?style=rebase`)
without any manual intervention. See [`rebase_pr`](../rebase_pr/).
## 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 ≥ 1 for results of this script |
| `stale_state` | string | Will always be `stale_no_conflicts` for results of this script |
| `ci_status` | string | `passing`, `failing`, `pending`, or `unknown`**not filtered**; any CI state is included |
| `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 matches all three conditions.
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_stale_clean` when you need to identify approved PRs that can be
**brought up-to-date automatically** (no human conflict resolution needed).
Typical use cases:
- **`pr-merge-pool-supervisor`** calls this as **step 3** of its cycle (after
processing ready-to-merge PRs). For each result it dispatches a
`pr-merge-worker` to trigger a server-side rebase, then re-checks step 2
before continuing — because a successful rebase moves the PR from this
bucket into `list_prs_ready_to_merge`.
- A **rebase automation** script could use this as its sole input to keep all
approved PRs current without any merge logic.
- A **monitoring agent** could track this bucket's size over time as a
measure of base-branch churn.
### Position in the Four-Bucket System
```
pr-merge-pool-supervisor processes buckets in this order:
1. list_prs_ready_to_merge
2. list_prs_stale_clean ← THIS SCRIPT (second priority)
3. list_prs_stale_conflicts
4. list_prs_needs_review
Workflow for a PR in this bucket:
rebase_pr → moves PR 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_stale_clean.ts \
--url https://git.example.com \
--pat ghp_XXXX \
--owner my-org \
--repo my-repo
# Count stale-but-clean PRs awaiting rebase
npx --yes tsx /app/.opencode/skills/auto-agents-system/scripts/list_prs_stale_clean.ts \
--url https://git.example.com \
--pat ghp_XXXX \
--owner my-org \
--repo my-repo \
| jq 'length'
# Get PR numbers and their base branches (useful for batch rebase planning)
npx --yes tsx /app/.opencode/skills/auto-agents-system/scripts/list_prs_stale_clean.ts \
--url https://git.example.com \
--pat ghp_XXXX \
--owner my-org \
--repo my-repo \
| jq '[.[] | {number, title, base: .base.ref}]'
# Get the top-priority stale-clean PR
npx --yes tsx /app/.opencode/skills/auto-agents-system/scripts/list_prs_stale_clean.ts \
--url https://git.example.com \
--pat ghp_XXXX \
--owner my-org \
--repo my-repo \
| jq 'first'
```
## Agent Usage Examples
### pr-merge-pool-supervisor
The supervisor calls this script as **step 3** of its main cycle. If the
list is non-empty, it dispatches `pr-merge-worker` sequentially for each PR
and then restarts the cycle at step 1.
```bash
result=$(npx --yes tsx /app/.opencode/skills/auto-agents-system/scripts/list_prs_stale_clean.ts \
--url $FORGEJO_URL --pat $FORGEJO_PAT --owner $REPO_OWNER --repo $REPO_NAME)
# If non-empty → dispatch pr-merge-worker for each PR
```
The worker receives the PR's `stale_state == stale_no_conflicts` in its
prompt and follows the "stale, no conflicts" path: call
[`rebase_pr`](../rebase_pr/) first, then call [`merge_pr`](../merge_pr/).
### pr-merge-worker
When dispatched for a PR from this bucket, the worker:
1. Calls [`rebase_pr`](../rebase_pr/) — triggers server-side rebase
2. Calls [`merge_pr`](../merge_pr/) — schedules the merge
The worker does **not** need to clone the repo or resolve conflicts — the
`stale_no_conflicts` state guarantees the server can do it automatically.
### system-watchdog-pool-supervisor
The watchdog can compare the sizes of the `list_prs_stale_clean` and
`list_prs_stale_conflicts` buckets over time. A growing `stale_clean`
bucket paired with a shrinking `list_prs_ready_to_merge` bucket suggests
the merge supervisor is running but rebases are not completing successfully.
## Dependencies
- Node.js ≥ 18 (native `fetch` API)
- `npx tsx` for TypeScript execution
- Zero external npm packages
@@ -1,253 +0,0 @@
# list_prs_stale_conflicts — Open PRs Approved, Stale, and Conflicted
**Script name:** `list_prs_stale_conflicts`
**Script location:** [`scripts/list_prs_stale_conflicts.ts`](../../../scripts/list_prs_stale_conflicts.ts)
**Invoke:**
```bash
npx --yes tsx .opencode/skills/auto-agents-system/scripts/list_prs_stale_conflicts.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_stale_conflicts.ts --url URL --pat TOKEN --owner OWNER --repo REPO
```
Returns all **open** pull requests that have **at least 1 non-dismissed
approval**, are **stale** (the base branch has advanced since the PR was last
synced), and **have merge conflicts** (`PR.mergeable == false`). These PRs have
been reviewed and approved but cannot progress without manual conflict
resolution by the PR author or an agent with a local clone.
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'
minApprovals: 1
stale: 'stale_with_conflicts'
(no ciStatus filter — all CI 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:
`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. Passing any filter-style flag
(e.g. `--min-approvals`, `--stale`, `--state`) causes immediate exit 1.
## Hard-Coded Filters
| Filter | Value | Meaning |
|--------|-------|---------|
| `state` | `open` | Only open PRs are returned |
| `minApprovals` | `1` | At least one non-dismissed `APPROVED` review required |
| `stale` | `stale_with_conflicts` | Base has advanced AND `PR.mergeable == false` |
**"Stale with conflicts"** means two things are simultaneously true:
1. `PR.merge_base != current base branch HEAD` — the base branch has been pushed to since the PR was last synced.
2. `PR.mergeable == false` — Forgejo has determined that rebasing the PR's commits onto the new base would produce conflicts that cannot be resolved automatically.
This combination requires manual intervention. The resolution path is:
1. Clone the repository locally (or use `repo-isolator`).
2. Rebase the head branch against the latest base branch.
3. Resolve all merge conflicts.
4. Force-push with lease (`--force-with-lease`).
5. Request re-review if the original approvals are now considered stale.
6. Call [`merge_pr`](../merge_pr/) to initiate the merge.
The server-side rebase endpoint (`POST /pulls/{index}/update?style=rebase`,
used by [`rebase_pr`](../rebase_pr/)) **cannot** be used for these PRs — it
requires `mergeable == true`.
## 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 ≥ 1 for results of this script |
| `stale_state` | string | Will always be `stale_with_conflicts` for results of this script |
| `ci_status` | string | `passing`, `failing`, `pending`, or `unknown`**not filtered**; any CI state is included |
| `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 matches all three conditions.
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: 2/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_stale_conflicts` to identify approved PRs that are **blocked by
conflicts** and need manual or agent-driven resolution. Typical use cases:
- **`pr-merge-pool-supervisor`** calls this as **step 4** of its cycle, after
processing ready-to-merge and stale-clean PRs. For each result it dispatches
a `pr-merge-worker` to perform a local clone, resolve conflicts, force-push,
and then trigger the merge.
- A **human-liaison agent** could use this to generate a "conflict backlog"
report, listing PRs that require author attention.
- A **monitoring alert** could trigger when this bucket grows beyond a
threshold, signalling that the codebase is accumulating merge debt.
### Position in the Four-Bucket System
```
pr-merge-pool-supervisor processes buckets in this order:
1. list_prs_ready_to_merge
2. list_prs_stale_clean
3. list_prs_stale_conflicts ← THIS SCRIPT (third priority)
4. list_prs_needs_review
Workflow for a PR in this bucket (requires local clone):
clone repo → rebase locally → resolve conflicts → force-push
→ merge_pr
```
## Usage Examples
```bash
# Standard usage
npx --yes tsx /app/.opencode/skills/auto-agents-system/scripts/list_prs_stale_conflicts.ts \
--url https://git.example.com \
--pat ghp_XXXX \
--owner my-org \
--repo my-repo
# Count conflicted approved PRs
npx --yes tsx /app/.opencode/skills/auto-agents-system/scripts/list_prs_stale_conflicts.ts \
--url https://git.example.com \
--pat ghp_XXXX \
--owner my-org \
--repo my-repo \
| jq 'length'
# Get PR numbers, titles, and head branches (for conflict resolution planning)
npx --yes tsx /app/.opencode/skills/auto-agents-system/scripts/list_prs_stale_conflicts.ts \
--url https://git.example.com \
--pat ghp_XXXX \
--owner my-org \
--repo my-repo \
| jq '[.[] | {number, title, head_branch: .head.ref, base_branch: .base.ref}]'
# Get the highest-priority conflicted PR
npx --yes tsx /app/.opencode/skills/auto-agents-system/scripts/list_prs_stale_conflicts.ts \
--url https://git.example.com \
--pat ghp_XXXX \
--owner my-org \
--repo my-repo \
| jq 'first'
```
## Agent Usage Examples
### pr-merge-pool-supervisor
The supervisor calls this script as **step 4** of its main cycle. If the
list is non-empty, it dispatches `pr-merge-worker` sequentially for each PR
and then restarts the cycle at step 1.
```bash
result=$(npx --yes tsx /app/.opencode/skills/auto-agents-system/scripts/list_prs_stale_conflicts.ts \
--url $FORGEJO_URL --pat $FORGEJO_PAT --owner $REPO_OWNER --repo $REPO_NAME)
# If non-empty → dispatch pr-merge-worker for each PR (conflict resolution path)
```
The worker receives `stale_state == stale_with_conflicts` in its prompt and
follows the conflict-resolution path: clone via `repo-isolator`, rebase
locally, resolve conflicts, force-push via `git-commit-helper`, then call
[`merge_pr`](../merge_pr/).
### pr-merge-worker
When dispatched for a PR from this bucket, the worker cannot use the server-
side rebase shortcut. Instead it must:
1. Use `repo-isolator` to create a local clone with the PR branch.
2. Run `git rebase <base>` locally.
3. Inspect conflict markers; use recent git history to inform resolutions.
4. Stage resolved files and continue the rebase.
5. Use `git-commit-helper` to force-push with lease.
6. Call [`merge_pr`](../merge_pr/) to schedule the merge.
### human-liaison-pool-supervisor
The liaison could filter this script's output by `created_at` to identify
PRs that have been stuck in conflict state for more than N days, then post
a comment pinging the PR author to resolve the conflict.
### system-watchdog-pool-supervisor
A growing `list_prs_stale_conflicts` bucket over consecutive watchdog cycles
(while the merge supervisor is running) indicates that conflict resolution
is failing — possibly because the automated resolver is not capable of
handling the specific type of conflict. The watchdog should create a
`Priority/High` announcement.
## Dependencies
- Node.js ≥ 18 (native `fetch` API)
- `npx tsx` for TypeScript execution
- Zero external npm packages
@@ -1,322 +0,0 @@
# merge_pr — Initiate a Rebase-Style Merge (with Automerge) on a PR
**Script name:** `merge_pr`
**Script location:** [`scripts/merge_pr.ts`](../../../scripts/merge_pr.ts)
**Invoke:**
```bash
npx --yes tsx .opencode/skills/auto-agents-system/scripts/merge_pr.ts \
--url URL --pat TOKEN --owner OWNER --repo REPO --pr NUMBER \
[--dep error|delete|reverse]
```
**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:".
**CRITICAL:** All attempts to merge pull requests **must** use this script.
## Synopsis
```
merge_pr.ts --url URL --pat TOKEN --owner OWNER --repo REPO --pr NUMBER
[--dep error|delete|reverse]
```
Calls the Forgejo REST API to merge a pull request using the `rebase` merge
style with `merge_when_checks_succeed=true`. If all CI checks and review
requirements are already satisfied, the PR merges immediately. Otherwise,
Forgejo queues it for automatic merging once those conditions are met — the
script does not wait; it returns as soon as the merge request is accepted.
The script also detects and handles **open blocking issue dependencies** before
calling the merge endpoint, since Forgejo silently ignores merge requests when
a PR has open dependencies (returns HTTP 200 but does nothing).
## Arguments
### Required
| 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 **merge permission** on the repository |
| `--owner OWNER` | string | Repository owner or organisation name |
| `--repo REPO` | string | Repository name |
| `--pr NUMBER` | positive integer | Pull request number to merge |
### Optional
| Flag | Type | Default | Description |
|------|------|---------|-------------|
| `--dep STRATEGY` | string | `error` | How to handle open blocking issue dependencies (see below) |
| `-h`, `--help` | — | — | Print usage to stderr and exit 0 |
### Dependency Strategy (`--dep`)
Forgejo PRs can declare issue dependencies. When a PR has **open** (unresolved)
dependencies, Forgejo silently ignores merge requests — it returns HTTP 200 but
the PR is never actually merged. This script detects open dependencies first
and handles them according to `--dep`:
| Value | Behaviour |
|-------|-----------|
| `error` | **(default)** Abort with exit code 1 and list all open blocking dependencies. State is never modified. Safe for read-before-write workflows. |
| `delete` | Delete each open dependency link from the PR, then proceed with the merge. The dependent issues are unaffected; only the link is removed. |
| `reverse` | Delete each open dependency link, then create a new reversed link (the formerly-blocking issue now depends on the PR instead of the other way around). Useful when the intent is "merge this PR, then finish the related issue". |
### Argument Validity Rules
- `--pr` must be a positive integer. Floats, zero, and negatives are rejected
with exit code 1.
- `--dep` must be exactly `error`, `delete`, or `reverse`. Any other value
causes exit code 1.
- All five named arguments are required (except `--dep` which defaults to
`error`). Any missing required argument causes exit code 1.
- Unknown flags cause exit code 1.
## What the Script Does
The script executes these steps in order:
1. **Fetch the PR** — verifies it is open and not already merged.
2. **Fetch all dependencies** (exhaustively paginated) — filters to open ones.
3. **Handle open dependencies** per `--dep` strategy (error / delete / reverse).
4. **POST to the merge endpoint**:
```
POST /api/v1/repos/{owner}/{repo}/pulls/{index}/merge
{
"Do": "rebase",
"merge_when_checks_succeed": true,
"head_commit_id": "<current HEAD SHA>"
}
```
The `head_commit_id` acts as an **optimistic lock** — if someone pushed to
the branch between the script reading the PR and calling merge, Forgejo
returns HTTP 409, preventing a stale-read merge.
5. **Re-fetch the PR** — inspects `merged` flag to determine the outcome.
6. **Return JSON result** with `status: "merged"` or `status: "auto_merge_scheduled"`.
## Output
Written to **stdout** on success as a pretty-printed JSON object:
```json
{
"status": "merged" | "auto_merge_scheduled",
"pr_number": 42,
"pr_title": "feat: add new feature",
"head_sha": "abc123...",
"merge_commit_sha": "<sha>" | null,
"merged_at": "2026-04-17T12:00:00Z" | null,
"deps_handled": [
{
"action": "deleted" | "reversed",
"dep_number": 10,
"dep_title": "Related issue title",
"dep_repo": "owner/repo"
}
],
"message": "PR #42 merged immediately using rebase style."
}
```
| Field | Type | Description |
|-------|------|-------------|
| `status` | string | `merged` — PR merged immediately; `auto_merge_scheduled` — Forgejo accepted the request and will merge when checks pass |
| `pr_number` | integer | The PR number that was processed |
| `pr_title` | string | The PR title at the time of the call |
| `head_sha` | string | The head commit SHA that was submitted for merge |
| `merge_commit_sha` | string \| null | Non-null only when `status == "merged"` |
| `merged_at` | string \| null | ISO 8601 timestamp, non-null only when `status == "merged"` |
| `deps_handled` | array | Zero or more dependency actions taken (empty if no open deps existed) |
| `message` | string | Human-readable summary of the outcome |
## Diagnostics / stderr
All progress information is written to stderr:
```
Fetching PR #42 from https://git.example.com/org/repo...
PR #42: "feat: add new feature"
State: open
Head SHA: abc123def456...
Mergeable: true
Fetching dependencies for PR #42...
Total dependencies: 2 (1 open / blocking)
BLOCKING: #10 [owner/repo] "Related issue"
Handling 1 open dependency(ies) with strategy 'delete'...
DELETE dependency: PR #42#10 (owner/repo)
Deleted OK (HTTP 200)
POST https://git.example.com/api/v1/repos/owner/repo/pulls/42/merge
Do=rebase merge_when_checks_succeed=true head_commit_id=abc123def456…
Response: HTTP 200
Merge request accepted. Re-fetching PR to determine state...
merged=false state=open
PR #42 not yet merged — auto-merge is pending checks/approvals.
```
## Exit Codes
| Code | Meaning |
|------|---------|
| 0 | Merge initiated — `status` is `merged` or `auto_merge_scheduled` |
| 1 | Any failure — descriptive error on stderr with machine-readable error code |
## Errors the Script May Throw
| Error Code | HTTP Status | Condition |
|------------|-------------|-----------|
| `PR_MERGED` | — | PR is already merged; nothing to do |
| `PR_NOT_OPEN` | — | PR is closed (not open) |
| `OPEN_DEPENDENCIES` | — | Open deps found and `--dep=error` (default); lists all blockers |
| `DEP_DELETE_FAILED` | varies | DELETE of a dependency link returned non-200 |
| `DEP_REVERSE_FAILED` | varies | POST of the reversed dependency returned non-201 |
| `MERGE_FORBIDDEN` | 403 | The PAT lacks merge access to the repository |
| `MERGE_NOT_ALLOWED` | 405 | Branch protection disallows the `rebase` merge style, or automerge is disabled |
| `MERGE_CONFLICT` | 409 | Merge conflicts present, or `head_commit_id` mismatch (concurrent push between read and merge call); re-run to retry with fresh HEAD |
| `MERGE_UNPROCESSABLE` | 422 | PR is a draft, already merged, or otherwise not mergeable |
| `HTTP_NNN` | NNN | Any other unexpected HTTP response from the merge endpoint |
A special case: HTTP 409 with the message `"already scheduled to auto merge"`
is treated as **success** (not an error). This happens when the script is run
twice on the same PR; the second run detects the already-scheduled automerge
and returns `status: "auto_merge_scheduled"`.
## Important Behaviours and Caveats
### Automerge State Is Not Directly Readable
Forgejo provides no read-only endpoint to confirm automerge is scheduled. The
script infers `status: "auto_merge_scheduled"` from the combination of a 200
response from the merge endpoint plus `merged=false` on the re-fetched PR.
This is the authoritative signal — it means Forgejo has accepted the request.
### Optimistic Locking
The `head_commit_id` field in the merge request body is an optimistic lock. If
someone pushes to the PR branch between when the script fetches the PR (step 1)
and when it calls the merge endpoint (step 4), Forgejo returns HTTP 409
(`MERGE_CONFLICT`). Simply re-running the script resolves this.
### No Waiting for CI
The script returns immediately after Forgejo accepts the merge request. It does
**not** poll for the merge to complete. When `status: "auto_merge_scheduled"`,
the caller should expect the PR to eventually close on its own once CI passes.
This is intentional — agents should never block waiting for CI.
### Rebase Merge Style
The `Do: "rebase"` merge style rewrites the PR's commits linearly on top of
the base branch HEAD. No merge commit is created. This produces a clean,
linear history. Other merge styles (`merge`, `squash`, `rebase-merge`) are
not used by this script.
## When to Use This Script
Use `merge_pr` whenever you want to **initiate a merge on a specific PR**:
- After [`rebase_pr`](../rebase_pr/) has brought a stale PR current.
- After manual conflict resolution and force-push on a conflicted PR.
- Directly on a PR returned by [`list_prs_ready_to_merge`](../list_prs_ready_to_merge/).
- Any time you need to queue a PR for automerge once its CI finishes.
Do **not** use this script if the PR is still stale — call
[`rebase_pr`](../rebase_pr/) first (if `stale_no_conflicts`) or resolve
conflicts locally (if `stale_with_conflicts`).
## Usage Examples
```bash
# Merge PR #42 (default: abort if open dependencies exist)
npx --yes tsx /app/.opencode/skills/auto-agents-system/scripts/merge_pr.ts \
--url https://git.example.com \
--pat ghp_XXXX \
--owner my-org \
--repo my-repo \
--pr 42
# Merge PR #42, deleting any open dependency links first
npx --yes tsx /app/.opencode/skills/auto-agents-system/scripts/merge_pr.ts \
--url https://git.example.com \
--pat ghp_XXXX \
--owner my-org \
--repo my-repo \
--pr 42 \
--dep delete
# Merge PR #42, reversing dependency links (issue now depends on PR)
npx --yes tsx /app/.opencode/skills/auto-agents-system/scripts/merge_pr.ts \
--url https://git.example.com \
--pat ghp_XXXX \
--owner my-org \
--repo my-repo \
--pr 42 \
--dep reverse
# Parse just the status from the output
npx --yes tsx /app/.opencode/skills/auto-agents-system/scripts/merge_pr.ts \
--url https://git.example.com --pat ghp_XXXX \
--owner my-org --repo my-repo --pr 42 \
| jq -r '.status'
# Check if the merge was immediate or scheduled
result=$(npx --yes tsx /app/.opencode/skills/auto-agents-system/scripts/merge_pr.ts \
--url https://git.example.com --pat ghp_XXXX \
--owner my-org --repo my-repo --pr 42)
status=$(echo "$result" | jq -r '.status')
if [ "$status" = "merged" ]; then
echo "Merged immediately"
else
echo "Queued for automerge"
fi
```
## Agent Usage Examples
### pr-merge-worker
The worker is the **primary caller** of this script. It always calls
`merge_pr` as the final step after any necessary rebase or conflict resolution:
```
# After rebase_pr (stale_no_conflicts path):
npx --yes tsx /app/.opencode/skills/auto-agents-system/scripts/merge_pr.ts \
--url $FORGEJO_URL --pat $FORGEJO_PAT \
--owner $REPO_OWNER --repo $REPO_NAME \
--pr $PR_NUMBER --dep delete
# After local conflict resolution (stale_with_conflicts path):
npx --yes tsx /app/.opencode/skills/auto-agents-system/scripts/merge_pr.ts \
--url $FORGEJO_URL --pat $FORGEJO_PAT \
--owner $REPO_OWNER --repo $REPO_NAME \
--pr $PR_NUMBER --dep delete
# For a ready-to-merge PR (not stale, already approved):
npx --yes tsx /app/.opencode/skills/auto-agents-system/scripts/merge_pr.ts \
--url $FORGEJO_URL --pat $FORGEJO_PAT \
--owner $REPO_OWNER --repo $REPO_NAME \
--pr $PR_NUMBER
```
The worker uses `--dep delete` by default for the stale buckets because those
PRs have already been verified to meet all quality gates; open dependency links
at that point are likely stale metadata rather than genuine blockers.
### pr-merge-pool-supervisor
The supervisor does **not** call this script directly. It dispatches
`pr-merge-worker` subagents, which call this script as part of their procedure.
### implementation-worker
An implementation worker creating a PR would never call this script — that
would be outside its responsibility. However, it might call it after creating
a PR if the project's workflow involves self-merging after CI passes (unusual
but possible with `--dep error` for safety).
## Dependencies
- Node.js ≥ 18 (native `fetch` API)
- `npx tsx` for TypeScript execution
- Zero external npm packages
@@ -1,322 +0,0 @@
# rebase_pr — Trigger a Server-Side Rebase on a Stale, Conflict-Free PR
**Script name:** `rebase_pr`
**Script location:** [`scripts/rebase_pr.ts`](../../../scripts/rebase_pr.ts)
**Invoke:**
```bash
npx --yes tsx .opencode/skills/auto-agents-system/scripts/rebase_pr.ts \
--url URL --pat TOKEN --owner OWNER --repo REPO --pr NUMBER
```
**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
```
rebase_pr.ts --url URL --pat TOKEN --owner OWNER --repo REPO --pr NUMBER
```
Calls the Forgejo REST API to rebase a pull request's head branch onto the
latest commit of its base branch — **entirely server-side, without a local
git clone**. The PR's commits are rewritten on top of the current base branch
HEAD, bringing the PR fully up-to-date.
The script enforces three strict pre-flight conditions before calling the
rebase endpoint. If any condition fails, the script exits with code 1 and a
descriptive error; it **never proceeds blindly**.
## Arguments
All five arguments are **required**. There are no optional arguments beyond
`--help`.
| 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 **write access** to the repository |
| `--owner OWNER` | string | Repository owner or organisation name |
| `--repo REPO` | string | Repository name |
| `--pr NUMBER` | positive integer | Pull request number to rebase |
| `-h`, `--help` | — | Print usage to stderr and exit 0 |
### Argument Validity Rules
- `--pr` must be a **positive integer**. Floats, zero, and negatives are
rejected with exit code 1: `ERROR: --pr must be a positive integer`.
- All five arguments are required. Any missing argument causes exit code 1.
- Unknown flags cause exit code 1.
### Invalid Argument Combinations
There are no multi-flag combinations to validate — the five arguments are
independent. However the following are logically invalid and will be caught
by the pre-flight checks (not by argument parsing):
- Passing the number of an already-merged PR → `PR_MERGED` error
- Passing a PR that is not stale → `PR_NOT_STALE` error (informational, not a bug)
- Passing a PR with conflicts → `PR_HAS_CONFLICTS` error
## Pre-Flight Conditions
The script enforces **all three** of the following before calling the Forgejo
rebase endpoint. Failing any one causes an immediate exit 1:
| Condition | Check | Error Code if Failed |
|-----------|-------|---------------------|
| PR must be open | `PR.state == "open"` AND `PR.merged == false` | `PR_MERGED` / `PR_NOT_OPEN` |
| PR must be stale | `PR.merge_base != current base-branch HEAD SHA` | `PR_NOT_STALE` (informational — no rebase needed) |
| PR must have no conflicts | `PR.mergeable == true` | `MERGEABLE_UNKNOWN` (null) or `PR_HAS_CONFLICTS` (false) |
The staleness check requires one additional API call to fetch the current HEAD
SHA of the base branch. This is cached internally but requires the PAT to have
read access to branches.
## What the Script Does
1. **Fetch the PR** — reads `state`, `merged`, `mergeable`, `merge_base`,
`base.ref`, `head.sha`.
2. **Guard: PR must be open and not merged.**
3. **Fetch the current base-branch HEAD SHA** via
`GET /api/v1/repos/{owner}/{repo}/branches/{branch}`.
4. **Guard: PR must be stale** (`merge_base != base HEAD`).
5. **Guard: PR must have no conflicts** (`mergeable == true`; rejects `null` and `false`).
6. **POST to the rebase endpoint**:
```
POST /api/v1/repos/{owner}/{repo}/pulls/{index}/update?style=rebase
```
No request body; the `style=rebase` query parameter selects the rebase
strategy (as opposed to `style=merge` which creates a merge commit).
7. **Re-fetch the PR** — captures the new head SHA to confirm the rebase applied.
8. **Return JSON result** with the old and new SHAs.
## Output
Written to **stdout** on success as a pretty-printed JSON object:
```json
{
"success": true,
"message": "PR #42 successfully rebased onto 'master'.",
"pr_number": 42,
"base_branch": "master",
"old_merge_base": "abc123def456...",
"new_head_sha": "xyz789abc012..."
}
```
| Field | Type | Description |
|-------|------|-------------|
| `success` | boolean | Always `true` on a successful exit |
| `message` | string | Human-readable summary |
| `pr_number` | integer | The PR number that was rebased |
| `base_branch` | string | The base branch the PR was rebased onto |
| `old_merge_base` | string | The `merge_base` SHA before the rebase (documents what changed) |
| `new_head_sha` | string | The PR's new head SHA after the rebase |
## Diagnostics / stderr
All progress information is written to stderr:
```
Fetching PR #42 from https://git.example.com/org/repo...
PR #42: "feat: add new feature"
State: open
Base: master
Head: feature/my-feature
Merge base: abc123def456...
Mergeable: true
Fetching current HEAD of base branch 'master'...
Base HEAD: def789abc123...
PR is stale: merge_base (abc123def4…) != base HEAD (def789abc1…).
No conflicts detected (mergeable=true). Triggering server-side rebase...
POST https://git.example.com/api/v1/repos/org/repo/pulls/42/update?style=rebase
Response: HTTP 200
Rebase triggered. Fetching updated PR details...
New head SHA: xyz789abc012...
New merge_base: (pending — Forgejo will compute shortly)
```
## Exit Codes
| Code | Meaning |
|------|---------|
| 0 | Rebase triggered successfully — JSON result written to stdout |
| 1 | Any failure — descriptive error on stderr with machine-readable error code |
## Errors the Script May Throw
| Error Code | Condition |
|------------|-----------|
| `PR_MERGED` | The PR is already merged; nothing to rebase |
| `PR_NOT_OPEN` | The PR is closed (not open) |
| `MERGE_BASE_MISSING` | `PR.merge_base` is null — Forgejo hasn't set it yet; retry shortly |
| `PR_NOT_STALE` | `PR.merge_base == base HEAD` — PR is already up-to-date; no rebase needed (informational, not a bug) |
| `MERGEABLE_UNKNOWN` | `PR.mergeable == null` — Forgejo hasn't finished computing the conflict status; retry in a few seconds |
| `PR_HAS_CONFLICTS` | `PR.mergeable == false` — PR has merge conflicts; server-side rebase cannot proceed; manual resolution required |
| `BASE_HEAD_UNKNOWN` | The branch API did not return a commit id for the base branch |
| `FORBIDDEN` | HTTP 403 — the PAT lacks write access to the head repository |
| `NOT_FOUND` | HTTP 404 — the PR or repository was not found |
| `REBASE_CONFLICT` | HTTP 409 — conflicts were detected during the rebase itself despite `mergeable=true` pre-flight check (race condition: concurrent push between pre-flight and rebase call); re-run |
| `ALREADY_UP_TO_DATE` | HTTP 422 — PR was already current by the time the rebase was called (race condition: another process rebased it first); treat as success and proceed |
| `HTTP_NNN` | Any other unexpected HTTP response from the update endpoint |
### Race Condition Notes
Two race conditions are possible between the pre-flight check and the rebase call:
1. **`REBASE_CONFLICT` (HTTP 409)**: Another agent pushed to the base branch
between your staleness check (step 3) and the rebase call (step 6), causing
newly introduced conflicts. Resolution: re-run the script; if conflicts
persist, the PR needs manual resolution.
2. **`ALREADY_UP_TO_DATE` (HTTP 422)**: Another process rebased the PR first.
This should be treated as a success — proceed to call
[`merge_pr`](../merge_pr/).
## Important Behaviours and Caveats
### Server-Side Only
This script uses Forgejo's built-in rebase capability. It does **not**
clone the repository, run `git` locally, or require git to be installed.
This is only possible because `PR.mergeable == true` guarantees there are
no conflicts for the server to stumble on.
### `mergeable == null` Is Not Processed
Forgejo computes `PR.mergeable` asynchronously after a PR is created or
updated. If the value is `null`, the script exits with `MERGEABLE_UNKNOWN`
rather than guessing. Retry after a few seconds.
### After the Rebase
The re-fetched PR may show `merge_base` as still `null` or a stale value —
Forgejo computes the new `merge_base` asynchronously after the rebase. The
`new_head_sha` field in the output is the reliable indicator that the rebase
applied. The next call to a `list_prs_*` script will see the updated state
once Forgejo catches up (typically within seconds).
### This Script Does Not Merge
`rebase_pr` only brings the PR up-to-date. To actually merge it after rebasing,
call [`merge_pr`](../merge_pr/).
## When to Use This Script
Use `rebase_pr` when you have a PR whose `stale_state` is `stale_no_conflicts`
(i.e. [`list_prs_stale_clean`](../list_prs_stale_clean/) returns it). This is
the correct and only safe use of this script.
Do **not** use this script for:
- PRs with `stale_state == stale_with_conflicts` — use a local clone instead.
- PRs with `stale_state == stale_unknown` — wait for Forgejo to compute the
conflict status, then retry.
- PRs with `stale_state == not_stale` — they are already current; call
[`merge_pr`](../merge_pr/) directly.
## Usage Examples
```bash
# Rebase PR #42 onto its base branch
npx --yes tsx /app/.opencode/skills/auto-agents-system/scripts/rebase_pr.ts \
--url https://git.example.com \
--pat ghp_XXXX \
--owner my-org \
--repo my-repo \
--pr 42
# Check the new head SHA after a successful rebase
npx --yes tsx /app/.opencode/skills/auto-agents-system/scripts/rebase_pr.ts \
--url https://git.example.com \
--pat ghp_XXXX \
--owner my-org \
--repo my-repo \
--pr 42 \
| jq -r '.new_head_sha'
# Rebase then immediately queue for merge (full pipeline for stale-clean PRs)
npx --yes tsx /app/.opencode/skills/auto-agents-system/scripts/rebase_pr.ts \
--url https://git.example.com --pat ghp_XXXX \
--owner my-org --repo my-repo --pr 42 \
&& \
npx --yes tsx /app/.opencode/skills/auto-agents-system/scripts/merge_pr.ts \
--url https://git.example.com --pat ghp_XXXX \
--owner my-org --repo my-repo --pr 42
# Handle PR_NOT_STALE gracefully in a shell script
output=$(npx --yes tsx /app/.opencode/skills/auto-agents-system/scripts/rebase_pr.ts \
--url https://git.example.com --pat ghp_XXXX \
--owner my-org --repo my-repo --pr 42 2>&1)
exit_code=$?
if [ $exit_code -ne 0 ]; then
if echo "$output" | grep -q "PR_NOT_STALE"; then
echo "PR is already current — proceeding to merge"
# call merge_pr
else
echo "Rebase failed: $output"
exit 1
fi
fi
```
## Agent Usage Examples
### pr-merge-worker
The worker is the **primary caller** of this script, specifically on the
`stale_no_conflicts` path:
```
# Step 1: Server-side rebase (stale_no_conflicts path)
npx --yes tsx /app/.opencode/skills/auto-agents-system/scripts/rebase_pr.ts \
--url $FORGEJO_URL --pat $FORGEJO_PAT \
--owner $REPO_OWNER --repo $REPO_NAME \
--pr $PR_NUMBER
# Step 2: Immediately schedule the merge
npx --yes tsx /app/.opencode/skills/auto-agents-system/scripts/merge_pr.ts \
--url $FORGEJO_URL --pat $FORGEJO_PAT \
--owner $REPO_OWNER --repo $REPO_NAME \
--pr $PR_NUMBER --dep delete
```
The worker does **not** call `rebase_pr` for the `stale_with_conflicts` path —
that path requires a local clone with manual conflict resolution.
### pr-merge-pool-supervisor
The supervisor never calls this script directly. It dispatches `pr-merge-worker`
subagents (via the Task tool, blocking), which call this script as part of
the stale-clean processing path.
### system-watchdog-pool-supervisor
The watchdog would not normally call `rebase_pr`. However, it could be
used in an emergency intervention workflow to manually rebase a PR that the
merge supervisor has been unable to process.
### grooming-pool-supervisor
The grooming supervisor focuses on issue/PR metadata and would not normally
call `rebase_pr`. However, it might verify that `rebase_pr` is available
and runnable as part of a pipeline health check.
## Dependencies
- Node.js ≥ 18 (native `fetch` API)
- `npx tsx` for TypeScript execution
- Zero external npm packages
@@ -13,6 +13,7 @@ The system uses four model tiers for implementation work, ordered by cost and ca
All tiers have `max_tokens: 200000`.
---
## How Tier Selectors Work
@@ -40,6 +41,7 @@ This applies to any agent that uses tier-based execution. The same `tier-*` sele
- `typecheck-fixer`, `lint-fixer`, `test-fixer`
- `coverage-improver`
---
## Progressive Escalation
@@ -82,6 +84,7 @@ Steps:
3. **Stop dispatching workers** for this item until `needs feedback` is removed
4. Create announcement: `[{prefix}] Announce: Human escalation needed for issue/PR #N` at Priority/High
---
## Default Model Assignments
@@ -144,6 +147,7 @@ Several agents switch to **Gemini 2.5 Pro** at runtime for large context windows
- `test-infra-worker` → Gemini 2.5 Pro
- `architecture-guard-worker` → Gemini 2.5 Pro
---
## Escalation Path Reference
@@ -9,6 +9,7 @@ The CleverAgents system has no shared memory between agents. All coordination ha
| **Status issue** | Current agent state — what it's doing, health, progress | Replaced each cycle (old one closed) | `[{PREFIX}] Status: {Type} (Cycle N)` |
| **Announcement issue** | Persistent signals to other agents | Persists until explicitly closed | `[{PREFIX}] Announce: {Message}` |
---
## Status Tracking Issues
@@ -64,6 +65,7 @@ Any agent that wants to find another agent's current status can:
2. The most recent open issue is the current cycle
3. Read its body and comments for detailed state
---
## Announcement Issues
@@ -114,6 +116,7 @@ Agents read others' announcements via `READ_ANNOUNCEMENTS`:
- High: process before starting next work cycle
- Medium/Low: opportunistically when convenient
---
## System-Specific Labels
@@ -147,6 +150,7 @@ For complete label rules — forbidden operations (`forgejo_create_label` etc.),
- **`cleverthis-guidelines` skill** — company-wide label and priority hierarchy definitions
- **`forgejo-api` skill** — curl patterns for all Forgejo API operations including label endpoints (`forgejo-label-manager` loads this skill automatically)
---
## automation-tracking-manager Operations Summary
@@ -1,228 +0,0 @@
# Announcement Relevancy Matrix
Which agents consume announcements from which other agents, and at what
minimum priority threshold.
For context on the announcement system itself (how to create, read, and close
announcements) see [`../`](../) (the tracking-system reference).
For dynamic programmatic lookup use the `agent-prefix-info` subagent with
operation `GET_RELEVANCY_MATRIX`.
## Universal Baseline — Applies to ALL Agents Without Exception
```
Priority/CI-Blocker from ANY agent → consume immediately, always
```
No agent is exempt from this rule. CI-Blocker signals block all other work.
## Per-Agent Relevancy Table
### `AUTO-PROD-BLDR` — product-builder (process supervisor)
| Source | Min Priority | Rationale |
|--------|-------------|-----------|
| ALL agents | Priority/Low+ | Monitors everything; must see all signals |
### `AUTO-WDOG` — system-watchdog
| Source | Min Priority | Rationale |
|--------|-------------|-----------|
| ALL agents | Priority/Low+ | Must observe the full system to audit it |
### `AUTO-HUMAN` — human-liaison
| Source | Min Priority | Rationale |
|--------|-------------|-----------|
| ALL agents | Priority/High+ | Relays important events to humans |
### `AUTO-EVLV` — agent-evolution
| Source | Min Priority | Rationale |
|--------|-------------|-----------|
| ALL agents | Priority/Medium+ | Needs broad pattern detection across all pools |
### `AUTO-IMP-SUP` — implementation pool (primary code producer)
| Source | Min Priority | Rationale |
|--------|-------------|-----------|
| `AUTO-WDOG` | Priority/Critical+ | System alerts that may block implementation work |
| `AUTO-EPIC` | Priority/High+ | New issues created and ready to implement |
| `AUTO-REV-SUP` | Priority/High+ | Review feedback requiring code fixes |
| `AUTO-PRMRG-SUP` | Priority/High+ | Merge status, rebase failures affecting PR work |
| `AUTO-ARCH` | Priority/High+ | Architectural decisions affecting implementation approach |
| `AUTO-OWNR` | Priority/High+ | Priority and scope changes |
| `AUTO-HUMAN` | Priority/High+ | Human requests relayed by liaison |
| `AUTO-GROOM` | Priority/Medium+ | Issue quality corrections affecting work items |
| `AUTO-GUARD` | Priority/Medium+ | Pattern drift warnings to apply to new code |
| `AUTO-SPEC` | Priority/Medium+ | Spec changes affecting implementation approach |
| All others | Priority/Critical+ | Universal baseline |
### `AUTO-REV-SUP` — PR review pool
| Source | Min Priority | Rationale |
|--------|-------------|-----------|
| `AUTO-WDOG` | Priority/Critical+ | System alerts |
| `AUTO-IMP-SUP` | Priority/High+ | New PRs available for review |
| `AUTO-ARCH` | Priority/High+ | Architecture decisions affecting review criteria |
| `AUTO-PRMRG-SUP` | Priority/High+ | Merge status of previously reviewed PRs |
| `AUTO-GUARD` | Priority/Medium+ | Pattern standards to check for in reviews |
| `AUTO-SPEC` | Priority/Medium+ | Spec alignment criteria updates |
| All others | Priority/Critical+ | Universal baseline |
### `AUTO-PRMRG-SUP` — PR merge pool
| Source | Min Priority | Rationale |
|--------|-------------|-----------|
| `AUTO-WDOG` | Priority/Critical+ | CI-Blocker alerts, system health |
| `AUTO-REV-SUP` | Priority/High+ | Review approvals that enable merging |
| `AUTO-IMP-SUP` | Priority/High+ | New PRs entering the merge pipeline |
| `AUTO-GROOM` | Priority/Medium+ | PR quality corrections before merge |
| All others | Priority/Critical+ | Universal baseline |
### `AUTO-UAT-SUP` — UAT test pool
| Source | Min Priority | Rationale |
|--------|-------------|-----------|
| `AUTO-WDOG` | Priority/Critical+ | System alerts |
| `AUTO-IMP-SUP` | Priority/High+ | New code merged and ready for UAT |
| `AUTO-SPEC` | Priority/High+ | Spec changes requiring retesting |
| `AUTO-ARCH` | Priority/High+ | Behavioral changes affecting test scope |
| `AUTO-PRMRG-SUP` | Priority/Medium+ | Merged PRs triggering retest cycles |
| All others | Priority/Critical+ | Universal baseline |
### `AUTO-BUG-SUP` — bug hunt pool
| Source | Min Priority | Rationale |
|--------|-------------|-----------|
| `AUTO-WDOG` | Priority/Critical+ | System alerts |
| `AUTO-IMP-SUP` | Priority/High+ | New code to analyze for bugs |
| `AUTO-UAT-SUP` | Priority/Medium+ | Test failures that may reveal underlying bugs |
| `AUTO-SPEC` | Priority/Medium+ | Spec changes affecting analysis scope |
| All others | Priority/Critical+ | Universal baseline |
### `AUTO-INF-SUP` — test infrastructure pool
| Source | Min Priority | Rationale |
|--------|-------------|-----------|
| `AUTO-WDOG` | Priority/Critical+ | CI pipeline failures |
| `AUTO-IMP-SUP` | Priority/High+ | CI changes, test additions requiring infra update |
| `AUTO-BUG-SUP` | Priority/Medium+ | Test reliability issues affecting infrastructure |
| `AUTO-UAT-SUP` | Priority/Medium+ | Test infrastructure problems discovered during UAT |
| All others | Priority/Critical+ | Universal baseline |
### `AUTO-ARCH` — architecture
| Source | Min Priority | Rationale |
|--------|-------------|-----------|
| `AUTO-WDOG` | Priority/Critical+ | System alerts |
| `AUTO-IMP-SUP` | Priority/High+ | Implementation discoveries affecting spec |
| `AUTO-SPEC` | Priority/High+ | Spec evolution feedback requiring arch input |
| `AUTO-GUARD` | Priority/High+ | Pattern drift requiring architectural response |
| `AUTO-HUMAN` | Priority/High+ | Human architectural feedback |
| `AUTO-EPIC` | Priority/Medium+ | Planning gaps needing spec coverage |
| All others | Priority/Critical+ | Universal baseline |
### `AUTO-EPIC` — epic planning
| Source | Min Priority | Rationale |
|--------|-------------|-----------|
| `AUTO-WDOG` | Priority/Critical+ | System alerts |
| `AUTO-ARCH` | Priority/High+ | Architecture to decompose into epics/issues |
| `AUTO-OWNR` | Priority/High+ | Priority and scope decisions affecting planning |
| `AUTO-HUMAN` | Priority/High+ | Human requests for work breakdown |
| `AUTO-SPEC` | Priority/Medium+ | Spec changes affecting issue planning |
| `AUTO-IMP-SUP` | Priority/Medium+ | Implementation progress affecting future plans |
| All others | Priority/Critical+ | Universal baseline |
### `AUTO-GUARD` — architecture guard
| Source | Min Priority | Rationale |
|--------|-------------|-----------|
| `AUTO-WDOG` | Priority/Critical+ | System alerts |
| `AUTO-ARCH` | Priority/High+ | Architecture pattern standards to enforce |
| `AUTO-IMP-SUP` | Priority/High+ | New code merges that may introduce pattern drift |
| `AUTO-SPEC` | Priority/Medium+ | Spec changes affecting acceptable patterns |
| All others | Priority/Critical+ | Universal baseline |
### `AUTO-SPEC` — spec update
| Source | Min Priority | Rationale |
|--------|-------------|-----------|
| `AUTO-WDOG` | Priority/Critical+ | System alerts |
| `AUTO-ARCH` | Priority/High+ | Architecture changes to reflect in spec |
| `AUTO-IMP-SUP` | Priority/High+ | Implementation divergences from spec |
| `AUTO-HUMAN` | Priority/High+ | Human feedback on spec content |
| `AUTO-PRMRG-SUP` | Priority/Medium+ | Merges triggering spec-vs-implementation comparison |
| All others | Priority/Critical+ | Universal baseline |
### `AUTO-GROOM` — backlog grooming
| Source | Min Priority | Rationale |
|--------|-------------|-----------|
| `AUTO-WDOG` | Priority/Critical+ | System alerts |
| `AUTO-OWNR` | Priority/High+ | Priority corrections from project owner |
| `AUTO-IMP-SUP` | Priority/High+ | PR quality issues surfaced during implementation |
| `AUTO-HUMAN` | Priority/High+ | Human requests about specific issues |
| `AUTO-EPIC` | Priority/Medium+ | New epics with children needing grooming |
| All others | Priority/Critical+ | Universal baseline |
### `AUTO-DOCS` — documentation
| Source | Min Priority | Rationale |
|--------|-------------|-----------|
| `AUTO-WDOG` | Priority/Critical+ | System alerts |
| `AUTO-ARCH` | Priority/High+ | Architecture changes to document |
| `AUTO-SPEC` | Priority/High+ | Spec changes requiring documentation updates |
| `AUTO-IMP-SUP` | Priority/Medium+ | New features completed and ready to document |
| `AUTO-UAT-SUP` | Priority/Medium+ | Test examples suitable for documentation |
| `AUTO-PRMRG-SUP` | Priority/Medium+ | Milestone completions triggering doc cycle |
| All others | Priority/Critical+ | Universal baseline |
### `AUTO-TIME` — timeline update
| Source | Min Priority | Rationale |
|--------|-------------|-----------|
| `AUTO-WDOG` | Priority/Critical+ | System alerts |
| `AUTO-IMP-SUP` | Priority/Medium+ | Progress data for timeline entries |
| `AUTO-PRMRG-SUP` | Priority/Medium+ | Merged PRs to record in timeline |
| `AUTO-PROD-BLDR` | Priority/Medium+ | Milestone status updates |
| All others | Priority/Critical+ | Universal baseline |
### `AUTO-OWNR` — project owner
| Source | Min Priority | Rationale |
|--------|-------------|-----------|
| `AUTO-WDOG` | Priority/Critical+ | System alerts |
| `AUTO-HUMAN` | Priority/High+ | Human requests and feedback |
| `AUTO-EPIC` | Priority/High+ | New epics and scope changes |
| `AUTO-IMP-SUP` | Priority/High+ | Implementation progress affecting priority decisions |
| `AUTO-GROOM` | Priority/Medium+ | Issue quality reports requiring owner action |
| `AUTO-UAT-SUP` | Priority/Medium+ | Test results affecting priority decisions |
| All others | Priority/Critical+ | Universal baseline |
## Rule of Thumb
When in doubt, **lower the threshold** (consume more). Missing an important
announcement is always worse than reading a slightly irrelevant one.
@@ -3,6 +3,7 @@
These rules apply to **every** agent in the CleverAgents system without exception.
No agent, at any tier or role, is exempt from any of these rules.
---
## Rule 1 — Exhaustive Pagination
@@ -50,6 +51,7 @@ causing incorrect escalation decisions, duplicate filings, or incomplete
audits. The cost of an extra API call is always less than the cost of
a missed item.
---
## Rule 2 — Label Management via `forgejo-label-manager`
@@ -88,6 +90,7 @@ All labels applied by agents must exist at the **organization level**. Labels
are defined once at the org level and inherited by all repos. Repo-level labels
are not used by the autonomous agent system.
---
## Rule 3 — Bot Signature on All Forgejo Content
@@ -116,6 +119,7 @@ after code blocks, after any closing notes. Never buried in the middle.
**Values:** Use the values given in your system prompt. Do not invent or guess
the pool name or agent name — they are always provided in context.
---
## Rule 4 — Credential Flow: Workers Never Read Environment Variables
@@ -156,6 +160,7 @@ workers use credentials
**If a supervisor omits any of these, the worker cannot proceed.** Supervisors
bear full responsibility for including complete credentials in every worker prompt.
---
## Rule 5 — localhost:4096 Restriction
@@ -19,10 +19,6 @@
// USAGE (as CLI):
// list_prs.ts --url URL --pat TOKEN --owner OWNER --repo REPO [OPTIONS]
//
// Notable filter options:
// --stale not_stale|stale_no_conflicts|stale_with_conflicts|stale_unknown
// --ci-status passing|failing|pending|unknown (comma-separated, any combination)
//
// USAGE (as module, imported by the four wrapper scripts):
// import { listPRs, parseConnectionArgs } from './list_prs.ts';
// =============================================================================
@@ -39,13 +35,6 @@ export type StaleState =
| 'stale_unknown' // base advanced; mergeable=null (Forgejo pending)
| 'compute_error'; // missing data or branch API failure
// CIStatus — combined commit-status result for the PR head SHA
// 'passing' — all checks reported success (Forgejo combined state == 'success')
// 'failing' — at least one check failed/errored (state == 'failure'|'error'|'warning')
// 'pending' — checks are queued or still running (state == 'pending')
// 'unknown' — no checks have been reported yet (state == ''|'unknown')
export type CIStatus = 'passing' | 'failing' | 'pending' | 'unknown';
export interface Config {
url: string; // Forgejo base URL, no trailing slash
pat: string; // Personal Access Token
@@ -59,7 +48,6 @@ export interface Filters {
maxApprovals?: number; // approvals_count <= N
mergeable?: boolean; // filter on PR.mergeable directly
stale?: StaleState; // filter on computed stale_state
ciStatus?: CIStatus[]; // whitelist: PR's ci_status must be one of these values
}
// Raw shape of a Forgejo pull request object (only the fields we use).
@@ -67,7 +55,6 @@ export interface Filters {
interface RawPR {
number: number;
title: string;
head: { sha: string };
base: { ref: string };
merge_base?: string | null;
mergeable: boolean | null;
@@ -78,7 +65,6 @@ interface RawPR {
export interface AugmentedPR extends RawPR {
approvals_count: number;
stale_state: StaleState;
ci_status: CIStatus;
priority_rank: number; // 0 = CI Blocker (highest), higher = lower; PRIORITY_NONE if unlabelled
priority_label: string | null; // matched Priority/* label name, or null if none
}
@@ -94,10 +80,6 @@ interface BranchInfo {
commit: { id: string };
}
interface CombinedStatus {
state: string; // 'success' | 'pending' | 'failure' | 'error' | 'warning' | '' | 'unknown'
}
// ─────────────────────────────────────────────────────────────────────────────
// CONSTANTS
// ─────────────────────────────────────────────────────────────────────────────
@@ -289,17 +271,6 @@ function computeStaleState(
return 'stale_unknown';
}
// ─────────────────────────────────────────────────────────────────────────────
// mapCIState — translate Forgejo's combined commit-status state string into
// our canonical CIStatus enum value
// ─────────────────────────────────────────────────────────────────────────────
function mapCIState(state: string): CIStatus {
if (state === 'success') return 'passing';
if (state === 'pending') return 'pending';
if (state === 'failure' || state === 'error' || state === 'warning') return 'failing';
return 'unknown'; // '' | 'unknown' | anything else → no checks reported
}
// ─────────────────────────────────────────────────────────────────────────────
// listPRs — fetch, enrich, filter, and return matching PRs
//
@@ -376,34 +347,12 @@ export async function listPRs(
REVIEW_CONCURRENCY,
);
// ── Step 4: Fetch CI (combined commit-status) for every PR concurrently ───
// Uses GET /api/v1/repos/{owner}/{repo}/commits/{sha}/status which returns
// the aggregated combined state for all status checks on the head commit.
log(`Fetching CI status for ${rawPRs.length} PR(s) concurrently (limit=${REVIEW_CONCURRENCY})...`);
const allCIStatuses = await pLimit<CIStatus>(
rawPRs.map(pr => async () => {
try {
const combined = await apiGet<CombinedStatus>(
`${repoBase}/commits/${encodeURIComponent(pr.head.sha)}/status`,
config.pat,
);
return mapCIState(combined.state ?? '');
} catch {
log(`WARNING: Could not fetch CI status for PR #${pr.number}; treating as 'unknown'`);
return 'unknown' as CIStatus;
}
}),
REVIEW_CONCURRENCY,
);
// ── Step 5: Compute fields, apply filters, collect results ────────────────
// ── Step 4: Compute fields, apply filters, collect results ────────────────
const results: AugmentedPR[] = [];
for (let i = 0; i < rawPRs.length; i++) {
const pr = rawPRs[i];
const approvalsCount = countApprovals(allReviews[i]);
const ciStatus = allCIStatuses[i];
const baseHead = branchCache.get(pr.base?.ref ?? '') ?? null;
const staleState = computeStaleState(
pr.merge_base ?? null,
@@ -416,14 +365,12 @@ export async function listPRs(
if (filters.maxApprovals !== undefined && approvalsCount > filters.maxApprovals) continue;
if (filters.mergeable !== undefined && pr.mergeable !== filters.mergeable) continue;
if (filters.stale !== undefined && staleState !== filters.stale) continue;
if (filters.ciStatus !== undefined && !filters.ciStatus.includes(ciStatus)) continue;
const { rank: priorityRank, label: priorityLabel } = prPriority(pr);
results.push({
...pr,
approvals_count: approvalsCount,
stale_state: staleState,
ci_status: ciStatus,
priority_rank: priorityRank,
priority_label: priorityLabel,
});
@@ -497,12 +444,11 @@ function parseFullArgs(argv: string[]): { config: Config; filters: Filters } {
case '--pat': config.pat = val; i++; break;
case '--owner': config.owner = val; i++; break;
case '--repo': config.repo = val; i++; break;
case '--state': filters.state = val as Filters['state']; i++; break;
case '--min-approvals': filters.minApprovals = Number(val); i++; break;
case '--max-approvals': filters.maxApprovals = Number(val); i++; break;
case '--mergeable': filters.mergeable = val === 'true'; i++; break;
case '--stale': filters.stale = val as StaleState; i++; break;
case '--ci-status': filters.ciStatus = val.split(',').map(s => s.trim()) as CIStatus[]; i++; break;
case '--state': filters.state = val as Filters['state']; i++; break;
case '--min-approvals': filters.minApprovals = Number(val); i++; break;
case '--max-approvals': filters.maxApprovals = Number(val); i++; break;
case '--mergeable': filters.mergeable = val === 'true'; i++; break;
case '--stale': filters.stale = val as StaleState; i++; break;
case '-h':
case '--help':
printUsage();
@@ -527,7 +473,6 @@ function printUsage(): void {
process.stderr.write(`\
Usage:
list_prs.ts --url URL --pat TOKEN --owner OWNER --repo REPO [OPTIONS]
[--ci-status passing|failing|pending|unknown[,...]]
REQUIRED:
--url URL Forgejo base URL, no trailing slash (e.g. https://git.example.com)
@@ -542,20 +487,11 @@ OPTIONAL FILTERS (all default to no filter):
--mergeable true|false Filter on PR.mergeable field
--stale not_stale|stale_no_conflicts|stale_with_conflicts|stale_unknown
Filter on computed staleness state
--ci-status passing|failing|pending|unknown[,...]
Comma-separated whitelist of CI statuses to include.
passing = all checks succeeded (Forgejo state: success)
failing = at least one check failed/errored (failure|error|warning)
pending = checks are queued or running (state: pending)
unknown = no checks reported yet (state: ''|unknown)
Multiple values: --ci-status passing,pending
Omit flag entirely to include all CI statuses.
OUTPUT (stdout): JSON array sorted by priority (highest first); each object is
the full Forgejo PR plus:
.approvals_count integer distinct non-dismissed APPROVED review count
.stale_state string one of the stale states listed above
.ci_status string passing|failing|pending|unknown (see --ci-status above)
.priority_rank integer 0=CI Blocker, 1=Critical, 2=High, 3=Medium,
4=Low, 5=Backlog, 6=none (unlabelled)
.priority_label string|null matched Priority/* label name, or null
@@ -0,0 +1,54 @@
#!/usr/bin/env -S npx --yes tsx
// =============================================================================
// list_prs_needs_review.ts — Open PRs with no approvals yet ("everything else")
//
// Part of: .opencode/skills/auto-agents-system/scripts/
//
// Delegates to list_prs.ts with hard-coded filters.
//
// Returns all OPEN pull requests that:
// • have zero review approvals (approvals_count == 0)
//
// These are the "everything else" bucket — PRs that have not received any
// approvals from any reviewer yet, regardless of their staleness state.
// They need a first review before any merge decision can be made.
//
// Why this is "everything else":
// The three complementary scripts together cover every open PR that has at
// least one approval, split by staleness state:
// list_prs_ready_to_merge → approved + not stale
// list_prs_stale_clean → approved + stale (no conflicts)
// list_prs_stale_conflicts → approved + stale (with conflicts)
// This script covers the remaining bucket: PRs awaiting a first review.
//
// Note: PRs with approvals but stale_state == stale_unknown (Forgejo has not
// yet finished computing the conflict status) are a brief transient state that
// will resolve shortly. They are intentionally absent from all four scripts
// during that window and will appear in one of the approved scripts once
// Forgejo finishes.
//
// Hard-coded filters (not configurable):
// state: 'open' only open PRs are considered
// maxApprovals: 0 PRs with no approvals whatsoever
//
// USAGE:
// list_prs_needs_review.ts --url URL --pat TOKEN --owner OWNER --repo REPO
//
// OUTPUT (stdout): JSON array — same schema as list_prs.ts
// DEPENDENCIES: Node.js >= 18 (native fetch), npx tsx (for TypeScript execution)
// =============================================================================
import { listPRs, parseConnectionArgs } from './list_prs.ts';
async function main(): Promise<void> {
const config = parseConnectionArgs(process.argv);
const prs = await listPRs(config, {
state: 'open',
maxApprovals: 0,
});
process.stdout.write(JSON.stringify(prs, null, 2) + '\n');
}
main().catch((err: unknown) => {
process.stderr.write(`ERROR: ${err instanceof Error ? err.message : String(err)}\n`);
process.exit(1);
});
@@ -1,57 +0,0 @@
#!/usr/bin/env -S npx --yes tsx
// =============================================================================
// list_prs_needs_review_not_stale.ts — Open PRs with no approvals, up-to-date
//
// Part of: .opencode/skills/auto-agents-system/scripts/
//
// Delegates to list_prs.ts with hard-coded filters.
//
// Returns all OPEN pull requests that:
// • have zero review approvals (approvals_count == 0)
// • are NOT stale (stale_state == not_stale)
// i.e. the PR's merge_base matches the current HEAD of its base branch —
// the PR is fully up-to-date and requires no rebase before merging.
//
// These are PRs that need only a first review — no rebase or conflict
// resolution will be required when they are eventually approved.
//
// Why this bucket exists:
// Together with list_prs_needs_review_stale_clean and
// list_prs_needs_review_stale_conflicts, these three scripts partition every
// open PR with zero approvals into three actionable sub-buckets based on
// what additional work will be required after a reviewer approves:
// list_prs_needs_review_not_stale → review only; merge immediately on approval
// list_prs_needs_review_stale_clean → review + server-side rebase; no conflicts
// list_prs_needs_review_stale_conflicts → review + local rebase; conflicts present
//
// Note: PRs with zero approvals and stale_state == stale_unknown are
// transiently absent while Forgejo computes conflict status; they will appear
// in stale_clean or stale_conflicts once Forgejo finishes.
//
// Hard-coded filters (not configurable):
// state: 'open' only open PRs are considered
// maxApprovals: 0 PRs with no approvals whatsoever
// stale: 'not_stale' PR is current with its base branch
//
// USAGE:
// list_prs_needs_review_not_stale.ts --url URL --pat TOKEN --owner OWNER --repo REPO
//
// OUTPUT (stdout): JSON array — same schema as list_prs.ts
// DEPENDENCIES: Node.js >= 18 (native fetch), npx tsx (for TypeScript execution)
// =============================================================================
import { listPRs, parseConnectionArgs } from './list_prs.ts';
async function main(): Promise<void> {
const config = parseConnectionArgs(process.argv);
const prs = await listPRs(config, {
state: 'open',
maxApprovals: 0,
stale: 'not_stale',
});
process.stdout.write(JSON.stringify(prs, null, 2) + '\n');
}
main().catch((err: unknown) => {
process.stderr.write(`ERROR: ${err instanceof Error ? err.message : String(err)}\n`);
process.exit(1);
});
@@ -1,60 +0,0 @@
#!/usr/bin/env -S npx --yes tsx
// =============================================================================
// list_prs_needs_review_stale_clean.ts — Open PRs with no approvals, stale, no conflicts
//
// Part of: .opencode/skills/auto-agents-system/scripts/
//
// Delegates to list_prs.ts with hard-coded filters.
//
// Returns all OPEN pull requests that:
// • have zero review approvals (approvals_count == 0)
// • are stale but have NO merge conflicts (stale_state == stale_no_conflicts)
// i.e. the base branch has advanced since the PR was last synced,
// but rebasing/merging would succeed without any conflict resolution.
//
// These are PRs that need a first review AND will also need a server-side
// rebase before they can be merged — but no conflict resolution will be
// required. Once approved, the workflow is:
//
// rebase_pr → (wait for approval if not yet given) → merge_pr
//
// Why this bucket exists:
// Together with list_prs_needs_review_not_stale and
// list_prs_needs_review_stale_conflicts, these three scripts partition every
// open PR with zero approvals into three actionable sub-buckets based on
// what additional work will be required after a reviewer approves:
// list_prs_needs_review_not_stale → review only; merge immediately on approval
// list_prs_needs_review_stale_clean → review + server-side rebase; no conflicts
// list_prs_needs_review_stale_conflicts → review + local rebase; conflicts present
//
// Note: PRs with zero approvals and stale_state == stale_unknown are
// transiently absent while Forgejo computes conflict status; they will appear
// here or in stale_conflicts once Forgejo finishes.
//
// Hard-coded filters (not configurable):
// state: 'open' only open PRs are considered
// maxApprovals: 0 PRs with no approvals whatsoever
// stale: 'stale_no_conflicts' PR is behind base but conflict-free
//
// USAGE:
// list_prs_needs_review_stale_clean.ts --url URL --pat TOKEN --owner OWNER --repo REPO
//
// OUTPUT (stdout): JSON array — same schema as list_prs.ts
// DEPENDENCIES: Node.js >= 18 (native fetch), npx tsx (for TypeScript execution)
// =============================================================================
import { listPRs, parseConnectionArgs } from './list_prs.ts';
async function main(): Promise<void> {
const config = parseConnectionArgs(process.argv);
const prs = await listPRs(config, {
state: 'open',
maxApprovals: 0,
stale: 'stale_no_conflicts',
});
process.stdout.write(JSON.stringify(prs, null, 2) + '\n');
}
main().catch((err: unknown) => {
process.stderr.write(`ERROR: ${err instanceof Error ? err.message : String(err)}\n`);
process.exit(1);
});
@@ -1,60 +0,0 @@
#!/usr/bin/env -S npx --yes tsx
// =============================================================================
// list_prs_needs_review_stale_conflicts.ts — Open PRs with no approvals, stale, with conflicts
//
// Part of: .opencode/skills/auto-agents-system/scripts/
//
// Delegates to list_prs.ts with hard-coded filters.
//
// Returns all OPEN pull requests that:
// • have zero review approvals (approvals_count == 0)
// • are stale AND have merge conflicts (stale_state == stale_with_conflicts)
// i.e. the base branch has advanced since the PR was last synced,
// and rebasing/merging would produce conflicts that cannot be resolved
// automatically (PR.mergeable == false).
//
// These are PRs that need BOTH a first review AND manual conflict resolution
// before they can be merged. The conflict resolution path requires a local
// clone or repo-isolator since the Forgejo server-side rebase endpoint
// (POST .../update?style=rebase) cannot handle conflicted PRs.
//
// Why this bucket exists:
// Together with list_prs_needs_review_not_stale and
// list_prs_needs_review_stale_clean, these three scripts partition every
// open PR with zero approvals into three actionable sub-buckets based on
// what additional work will be required after a reviewer approves:
// list_prs_needs_review_not_stale → review only; merge immediately on approval
// list_prs_needs_review_stale_clean → review + server-side rebase; no conflicts
// list_prs_needs_review_stale_conflicts → review + local rebase; conflicts present
//
// Note: PRs with zero approvals and stale_state == stale_unknown are
// transiently absent while Forgejo computes conflict status; they will appear
// in stale_clean or here once Forgejo finishes.
//
// Hard-coded filters (not configurable):
// state: 'open' only open PRs are considered
// maxApprovals: 0 PRs with no approvals whatsoever
// stale: 'stale_with_conflicts' PR is behind base AND has conflicts
//
// USAGE:
// list_prs_needs_review_stale_conflicts.ts --url URL --pat TOKEN --owner OWNER --repo REPO
//
// OUTPUT (stdout): JSON array — same schema as list_prs.ts
// DEPENDENCIES: Node.js >= 18 (native fetch), npx tsx (for TypeScript execution)
// =============================================================================
import { listPRs, parseConnectionArgs } from './list_prs.ts';
async function main(): Promise<void> {
const config = parseConnectionArgs(process.argv);
const prs = await listPRs(config, {
state: 'open',
maxApprovals: 0,
stale: 'stale_with_conflicts',
});
process.stdout.write(JSON.stringify(prs, null, 2) + '\n');
}
main().catch((err: unknown) => {
process.stderr.write(`ERROR: ${err instanceof Error ? err.message : String(err)}\n`);
process.exit(1);
});
@@ -1,6 +1,6 @@
#!/usr/bin/env -S npx --yes tsx
// =============================================================================
// list_prs_ready_to_merge.ts — Open PRs approved, up-to-date, and CI passing
// list_prs_ready_to_merge.ts — Open PRs approved and up-to-date with base
//
// Part of: .opencode/skills/auto-agents-system/scripts/
//
@@ -9,22 +9,15 @@
// Returns all OPEN pull requests that:
// • have at least 1 review approval (approvals_count >= 1)
// • are NOT stale (stale_state == not_stale)
// • have passing CI (ci_status == 'passing')
//
// These PRs are ready to be merged immediately — they are approved, their
// branch is already up-to-date with the base branch, and all CI checks have
// passed. No rebase, conflict resolution, or CI wait is required.
//
// CI filter rationale: merging a PR with failing or pending CI would push
// broken code to the base branch. Only 'passing' is accepted here. PRs
// with 'pending' or 'failing' CI appear in none of the approved buckets
// until their CI resolves, preventing premature merges.
// These PRs are ready to be merged immediately — they are approved and their
// branch is already up-to-date with the base branch, so no rebase or conflict
// resolution is required before merging.
//
// Hard-coded filters (not configurable):
// state: 'open' only open PRs are considered
// minApprovals: 1 at least one non-dismissed approval required
// stale: 'not_stale' PR head must be current with its base branch
// ciStatus: ['passing'] all CI checks must have succeeded
// state: 'open' only open PRs are considered
// minApprovals: 1 at least one non-dismissed approval required
// stale: 'not_stale' PR head must be current with its base branch
//
// USAGE:
// list_prs_ready_to_merge.ts --url URL --pat TOKEN --owner OWNER --repo REPO
@@ -40,7 +33,6 @@ async function main(): Promise<void> {
state: 'open',
minApprovals: 1,
stale: 'not_stale',
ciStatus: ['passing'],
});
process.stdout.write(JSON.stringify(prs, null, 2) + '\n');
}
+69 -211
View File
@@ -7,35 +7,7 @@ The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
### Fixed
- **Actor v3 YAML Schema Validation in CLI** (#5869): The `agents actor add --config`
command now validates v3 YAML files using `ActorConfigSchema`, ensuring proper
schema compliance including cycle detection for GRAPH actors, required field
validation, and enum validation. v3 YAML is detected by the presence of ANY
`type` field (any value — invalid type values are then rejected by schema
validation) or a `version` field whose string value starts with `"3"` (e.g.
`"3"`, `"3.0"`, `"3.0.0"`). Configs with `type: null` are not treated as v3.
Invalid v3 actors are rejected with clear error messages before registration.
- **Alembic Files Missing from Wheel Distribution** (#4180): Alembic configuration
(`alembic.ini`) and migration files are now part of the Python package structure
at `src/cleveragents/infrastructure/database/migrations/`. Previously, when
`agents init` was run in Docker containers or any wheel-based installation,
`FileNotFoundError` was raised because alembic files were stored at the
repository root and excluded from the wheel distribution. Now alembic files
follow standard Python packaging conventions and are automatically included.
`MigrationRunner._find_alembic_ini()` has been updated to search the new package
location as the primary anchor point. This fix enables `agents init` to work
correctly in all deployment modes: Docker containers, local pip installs
(wheel or editable), and development environments.
- **TDD Non-AssertionError Guard Visibility** (#8294): `apply_tdd_inversion` in
- **bug-hunt-pool-supervisor Non-Blocking Tracking** (#8835): The automation-tracking-manager
call in step 5 was blocking the main loop indefinitely, causing 3+ consecutive initialization
failures. Step 5 now explicitly marks tracking as best-effort -- if the call does not complete
within a reasonable time or fails, it is skipped and the supervisor continues to the next
cycle. A new Rule 9 reinforces that tracking must never block the main loop; core
functionality (module mapping, worker dispatch, monitoring) takes priority over status
reporting.
`features/environment.py` now emits its non-assertion exception guard warning to
both the structured logger and `stderr` via a new `_warning_with_stderr` helper.
This makes the guard firing visible in standard Behave console output and CI log
@@ -54,6 +26,12 @@ The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
crash (unhandled exception) is detected via an all-zero summary and the
captured traceback is always surfaced.
- **Error Suppression in Reactive Registry Adapter** (#9060): Removed two
`try...except Exception:` blocks in `register_registry_agents()` that were
silently suppressing errors. Exceptions from `actor_registry.list_actors()`
and the route bridge refresh now propagate to the caller per the fail-fast
policy.
- **Automation Profile Silent Fallback** (#8232): `_resolve_profile_for_plan` in
`PlanLifecycleService` now raises a clear `ValidationError` when a plan's
automation profile name is not a known built-in profile, instead of silently
@@ -62,16 +40,21 @@ The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
message listing available built-in profiles. The resolved profile name is also
logged at debug level for observability.
- **CheckpointManager rollback_to always returned False** (#7488): Fixed a data
integrity bug in `CheckpointManager.create_checkpoint()` where `sandbox_path`
was computed from `sandbox.context.sandbox_path` but never stored in the
checkpoint metadata. As a result, `rollback_to()` always found
`checkpoint.metadata.get("sandbox_path")` returning `None` and silently
skipped the rollback, returning `False`. The fix adds `sandbox_path` to the
metadata dict before constructing the `SandboxCheckpoint`, enabling
`rollback_to()` to correctly restore the sandbox filesystem state.
### Added
- Wired `StrategyActor` into the real plan execution path: `_get_plan_executor`
in `plan.py` now resolves the strategy actor via `resolve_strategy_actor()`
(reading the `actor.default.strategy` config key) instead of always
constructing `LLMStrategizeActor`. `run_strategize` in `PlanExecutor` now
passes `resources` (derived from `plan.project_links`) and `project_context`
to the actor so the LLM prompt receives full project context. Strategy
decisions are serialised as JSON in `plan.error_details["strategy_decisions_json"]`
so `_build_decisions` can reconstruct the full hierarchy (dependency ordering,
parent/child structure) during Execute instead of rebuilding from
`definition_of_done`. `StrategizeStubActor.execute` accepts `**kwargs` for
forward-compatibility. Added BDD coverage for the stored-JSON path,
corrupt-JSON fallback, resource-passing, and stub extra-kwargs scenarios.
(#828)
- **TDD Issue-Capture Test Activation** (#7025): Replaced 234 bare `@skip` tags
across 82 Behave feature files with the correct `@tdd_expected_fail @tdd_issue
@@ -166,6 +149,13 @@ The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
`docs/development/automation-tracking.md` and the new
`docs/development/docs-writer.md` reference.
- **ACMS / UKO API Documentation** (`docs/api/acms.md`): Added comprehensive API
reference for the `cleveragents.acms` package covering the four-layer UKO ontology
hierarchy, `VocabularyRegistry`, `ProvenanceInfo`, `UKOClass`, `UKOProperty`,
`UKOVocabulary`, `Layer2Dependency`, `ParadigmVocabulary`, `DetailLevelMapBuilder`,
and all Layer 3 language vocabulary types (Python, TypeScript, Rust, Java).
The new page is linked from the API Reference index and the MkDocs navigation.
### Changed
- **Decision Tree Full ULID Display** (#5825): The `agents plan tree` command now
@@ -199,13 +189,33 @@ The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
### Fixed
- **Path Traversal Sandbox Escape via Prefix Collision** (#7558): Fixed
`validate_path()` in `file_tools.py` using `str.startswith()` for sandbox
containment, which allowed sibling directories with a matching name prefix
(e.g. `/tmp/sandbox-escape/` bypassing `/tmp/sandbox/`) to escape the
sandbox. Replaced with `Path.relative_to()` which performs a proper path
prefix check using OS path separators. Added regression test tagged
`@tdd_issue_7558`.
- **Plan Concurrency Race Condition** (#7989): Fixed critical race condition in `execute_plan()` and
`apply_plan()` where concurrent CLI/worker sessions could simultaneously modify the same plan,
corrupting plan state. `LockService` is now wired into the plan lifecycle with plan-level advisory
locking. Each invocation generates a unique caller identity (UUID) to prevent re-entrant lock
acquisition by concurrent sessions on the same plan. Concurrent attempts now raise `LockConflictError`
instead of silently racing. Lock is acquired before phase transition and released in a `finally`
block to ensure cleanup even on error.
- **`--format color` ANSI Output** (#7910): Fixed `format_output` routing the `color` format
option to `_format_plain`, which produced plain uncoloured text instead of ANSI escape
sequences. The `color` format is now routed to `format_output_session` which uses the
`ColorMaterializer` to emit proper ANSI-coloured output. `--format plain` and all other
formats remain unaffected.
- **ContextTierService Thread Safety** (#7547): Added `threading.RLock` to
`ContextTierService` to prevent `RuntimeError: dictionary changed size during
iteration` and data corruption under concurrent plan execution. All public
methods (`store`, `get`, `promote`, `demote`, `evict_lru`, `enforce_staleness`,
`get_metrics`, `get_all_fragments`, `get_hot_fragments`, `get_for_actor`,
`get_scoped_view`, `get_scoped_by_resource`, `get_scoped_metrics`) now acquire
the reentrant lock before accessing the hot/warm/cold tier dicts. The service
was previously documented as single-threaded but registered as a DI Singleton,
causing potential data corruption when parallel subplans shared the same
instance. The `TierRuntimeMixin.enforce_staleness()` and
`ScopedTierMixin.get_scoped_by_resource()` / `get_scoped_metrics()` methods
are also protected. The DI container registration as `providers.Singleton`
is now correct and safe.
- **Validation Gate Empty-Run Guard** (#7508): Fixed `ApplyValidationSummary.all_required_passed`
returning `True` when zero validations were run, silently bypassing the apply gate. The property
@@ -227,6 +237,16 @@ The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
`sandbox_root=.cleveragents/sandbox/`, so LLM file output (`FILE:` blocks)
is written to disk during the execute phase. (#4222)
- **SubplanExecutionService fail_fast cancellation** (#7582): Fixed a race condition where
already-running parallel subplans were not cancelled when `fail_fast` fired. Previously,
`Future.cancel()` only prevented queued futures from starting but had no effect on
in-flight futures that completed after `stop_flag` was set — their `COMPLETE` results
were incorrectly included in the merge output. The fix adds a post-completion guard that
overrides any non-`ERRORED`/non-`CANCELLED` result to `CANCELLED` when `stop_flag` is
active, and clears the associated output to prevent it from entering the merge. Also
replaces the O(n) linear `status` lookup in the `as_completed()` loop with an O(1)
`status_map` dict pre-computed before the executor block.
- **Robot Framework TDD Listener Guards** (#5436): Added three guard conditions to the
`tdd_expected_fail_listener` `end_test()` function to prevent blindly inverting ALL test
failures to passes, which was masking infrastructure errors and causing flaky CI behavior.
@@ -235,6 +255,11 @@ The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
e2e test files and removed `tdd_expected_fail` from 4 context assembly e2e tests where
bugs were already fixed.
- **PluginLoader entry point prefix validation** (#7476): Parse entry point targets before
import, enforce the module allowlist ahead of loading, and add Behave plus Robot Framework
regression coverage to ensure disallowed prefixes never execute untrusted module-level code
in either unit or integration flows.
- **`issue-state-updater` Bash Script Errors**: Removed problematic bash script examples
that tried to invoke `task forgejo-label-manager` as a bash command (the Task tool cannot
be invoked from bash). Replaced with clear step-by-step operational instructions and
@@ -254,15 +279,6 @@ The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
a `sqlite3.IntegrityError: UNIQUE constraint failed` crash when `agents plan use` was
called on an action that already had arguments registered via `action create`. (#4197)
- Fixed CheckpointManager not wired into PlanExecutor — checkpoints were
never created during plan execution because `_get_plan_executor()` in
the CLI constructed PlanExecutor without a CheckpointManager (defaulted
to None, silently skipping all checkpoint hooks). `_get_plan_executor()`
now resolves the container singleton so CLI `plan execute` and `plan
rollback` share the same registry, and `_try_create_checkpoint()` raises
`PlanError` if checkpoint metadata cannot be persisted. Writable sandboxable
resources and write-capable tools now default to `checkpointable=True`, and
new Behave scenarios cover DI wiring, rollback, and capability defaults. (#1253)
---
## [3.8.0] — 2026-04-05
@@ -286,161 +302,3 @@ The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
renders permission requests directly in the conversation stream for single-file
operations. Users can allow/reject with single-key shortcuts (`a`/`A`/`r`/`R`),
navigate with arrow keys, confirm with `Enter`, or press `v` to open the full
permissions screen. (#1004)
- **TUI — Actor thought blocks**: Expandable reasoning trace widgets rendered
inline in the conversation stream with muted styling. Collapsed by default;
expand with `Space` or click. (#1005)
- **UKO provenance tracking**: Every typed triple now carries `sourceResource`,
`validFrom`, and `isCurrent` metadata. A revision chain enables temporal
queries and point-in-time ontology state reconstruction.
- **JSON-RPC 2.0 A2A wire format**: `A2aRequest`/`A2aResponse` fields renamed to
standard JSON-RPC 2.0 names (`method`, `id`, `result`, `error`). The
`A2aVersionNegotiator` handles backward compatibility.
- **Database resource handler**: Full CRUD and checkpoint/rollback support for
SQLite, PostgreSQL, MySQL, and DuckDB resources via the resource DAG.
- **Estimation lifecycle hook**: `actor.default.estimation` config key wires an
estimation actor into the Strategize-to-Estimate lifecycle hook.
- **Persona system**: YAML-backed personas bind actors, argument presets, and scope
references to named identities; persisted in `~/.config/cleveragents/personas/`.
- **Session management**: Create, list, export, and import conversation sessions;
full JSON export/import for portability; Markdown transcript export
(`--format md`) for human-readable sharing.
- **First-run experience**: `ActorSelectionOverlay` guides new users to pick an
actor on first TUI launch; creates a `"default"` persona automatically.
- **Server mode**: `agents server connect` configures a remote CleverAgents server;
Kubernetes Helm chart in `k8s/` for production deployment.
- **A2A integration**: Agent-to-Agent protocol facade wires CLI and TUI to live
application services (session, plan, registry, event).
- **Permissions screen**: TUI overlay for reviewing tool permission requests with
unified, side-by-side, and context diff views; session-scoped allow/reject decisions.
- **Inline permission questions**: `PermissionQuestionWidget` renders single-file
permission requests directly in the conversation stream with single-key shortcuts.
- **Invariant reconciliation**: `InvariantReconciliationActor` runs automatically at
every plan phase transition; failures block the transition and emit `INVARIANT_VIOLATED`.
- **UKO runtime**: Universal Knowledge Ontology query interface, inference engine, and
graph persistence for ACMS context strategies.
### Fixed
- `LangChainChatProvider.name` and `model_id` are now mutable properties with setters,
fixing an `AttributeError` when `PlanService` attempted to resolve provider names after
instantiation. (#1553)
---
## [3.7.0] — 2026-03-15
### Added
- **Interactive TUI** (`agents tui`) — full-screen Textual app with multi-session tabs,
persona switching, slash commands (67 commands across 14 groups), reference picker
(`@`), shell mode (`!`), context-sensitive F1 help, and `Ctrl+T` argument preset cycling.
- **Slash command system** — 67 commands across 14 groups accessible via `/` overlay.
- **Reference picker**`@` key opens a file/resource reference picker that inserts
references into the input field.
- **TUI persona system** — YAML-backed personas bind actors, argument presets, and scope
references; persisted in `~/.config/cleveragents/personas/`.
- **TUI session export/import** — full JSON round-trip and Markdown transcript export
(`--format md`).
---
## [3.6.0] — 2026-02-28
### Added
- Advanced Context Management System (ACMS) with three-tier context strategy.
- UKO Runtime (Universal Knowledge Ontology) with graph persistence and inference engine.
- Implicit inference engine producing `uko:implicitSiblingOf`, `uko:implicitContains`,
and `uko:implicitDependsOn` triples with confidence 0.7.
---
## [3.5.0] — 2026-02-14
### Added
- Autonomy hardening: advisory locking, validation pipeline, definition-of-done gating.
- Resource DAG with dependency tracking and type hierarchy with multiple inheritance.
- Container resource types (`container.docker`, `container.podman`).
- LSP resource types (`lsp.*`).
---
## [3.4.0] — 2026-01-31
### Added
- ACMS v1 with context scaling strategies.
- Resource type inheritance system (ADR-042).
- Safety profile extraction (ADR-041).
---
## [3.3.0] — 2026-01-17
### Added
- Corrections and subplans support in plan lifecycle.
- Checkpoint and rollback for all resource writes.
- Decision tree versioning and history (ADR-034).
- Decision tree rollback and replay (ADR-035).
---
## [3.2.0] — 2026-01-03
### Added
- Decisions, validations, and invariants in plan lifecycle.
- Validation abstraction layer (ADR-013).
- Invariant system (ADR-016).
- Automation profiles (ADR-017).
- Semantic error prevention (ADR-018).
---
## [3.1.0] — 2025-12-20
### Added
- MCP (Model Context Protocol) adapter and client (ADR-029).
- LSP (Language Server Protocol) client integration (ADR-027).
- Agent Skills Standard (AgentSkills.io) support (ADR-028).
- Skill abstraction definition (ADR-030).
---
## [3.0.0] — 2025-12-06
### Added
- Initial public release of CleverAgents Core.
- Unified `agents` / `cleveragents` CLI entry points.
- Layered architecture: Entry Points → Application → Domain → Infrastructure → Integration → Core.
- Actor system with YAML-defined LangGraph node graphs.
- Tool system with four-stage lifecycle (activate → validate → execute → deactivate).
- Skill system with three-tier progressive disclosure.
- Resource system with DAG and type hierarchy.
- A2A (Agent-to-Agent) protocol facade.
- DI container (`cleveragents.application.container`).
- LangChain/LangGraph integration (ADR-022).
- Provider registry with fallback chain (OpenAI → Anthropic → Google → Azure → OpenRouter → Groq → Together → Cohere).
- Observability: structured logging, metrics, audit trail, token/cost tracking.
- BDD test suite (Behave + Robot Framework).
- Nox automation for lint, typecheck, tests, docs, benchmarks.
- MkDocs-powered documentation with CleverAgents branding.
-2
View File
@@ -19,7 +19,5 @@ Below are some of the specific details of various contributions.
* HAL 9000 has contributed concurrency safety improvements, including thread-safe context tier management (issue #7547) for parallel plan execution.
* HAL 9000 has contributed the plan concurrency race-condition fix (#7989): wired `LockService` into the plan lifecycle, guarding `execute_plan()` and `apply_plan()` with plan-level advisory locks and unique per-invocation owner identities to prevent silent concurrent state corruption.
* HAL 9000 has contributed the plugin entry point security hardening fix (#7476): enforced entry point allowlist validation before importing plugin modules to prevent malicious plugin loading.
* Rui Hu has contributed the v3 actor YAML schema validation fix (#5869): added `ActorConfigSchema` validation to the `agents actor add --config` CLI command, covering cycle detection, required field validation, and enum validation for v3 YAML actor definitions.
* HAL 9000 has contributed automated bug fixes, including fix #7488 (store sandbox_path in checkpoint metadata to enable rollback).
* This project was made possible thanks to considerable donation of time, money, and resources by CleverThis, Inc.
* HAL 9000 has contributed automated bug fixes, CLI output formatting improvements, and ongoing maintenance as part of the CleverAgents automation system.

Some files were not shown because too many files have changed in this diff Show More