agents: review round 2 — split-PR flow, thread recency, mention boundaries, learnings cap, pm model
ci / lint (push) Skipped
ci / lint (pull_request) Successful in 11s

- publish.sh: resolve_prs matches ai/issue-N AND ai/issue-N-<slug> split branches
  (exact-only silently stalled DELEGATE:@qa and autopilot MERGE_PR on slugged
  work); qa hand-off lists all open PRs; autopilot refuses to merge multi-PR
  issues (drops the label, hands to the human) — merging one of several open
  PRs is half a change deployed. Retro's state=all resolve matches slugs too.
- fetch-thread.sh: paginate and keep the NEWEST 100 comments — a bare limit=100
  kept the OLDEST page and dropped recent decisions on long threads.
- route.sh: word-boundary mention matching ("@internal" no longer routes to
  @intern); a comment with no real agent mention now SKIPS gracefully
  (mode=skip outputs + step guards in agent.yml) instead of a red run.
- run-agent.sh: LEARNINGS.md cap is line-aware and keeps the NEWEST entries
  (retros append at the bottom; the old head -c cut the latest lessons first).
- agents.json/README: @pm gemma4 -> minimax-m3 — the retro rule demands an
  investigating PM, and gemma4 posted 0 tool calls on every run; minimax is the
  model @qa demonstrably uses tools with.
- agent.yml: document the PR-thread concurrency-group caveat.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Felix Faerber
2026-07-06 20:11:45 +03:00
co-authored by Claude Opus 4.8
parent 84467f6dfd
commit e9df9d6bdd
7 changed files with 76 additions and 19 deletions
+14 -1
View File
@@ -11,6 +11,10 @@ jobs:
# One run at a time PER ISSUE: two quick comments on the same issue would otherwise race —
# both checking out ai/issue-N, pushing (non-fast-forward loss) and double-posting. Queued
# runs wait (no cancel) so every trigger is still processed, just serially.
# KNOWN CAVEAT: a run triggered on the PR thread groups under the PR number, not the origin
# issue (that mapping is only resolved later, in route.sh) — so an issue-thread run and a
# PR-thread run for the SAME work item can overlap. Accepted: they post to different threads,
# and the branch is only mutated by dev runs, which resume serially per thread.
concurrency:
group: ai-agent-${{ github.repository }}-${{ github.event.issue.number }}
cancel-in-progress: false
@@ -116,6 +120,7 @@ jobs:
run: bash "$SCRIPTS/route.sh"
- name: Install opencode + provider config (+ Playwright MCP for browser agents)
if: steps.prep.outputs.mode != 'skip'
env:
SCRIPTS: ${{ runner.temp }}/agents-scripts
OLLAMA_URL: ${{ secrets.OLLAMA_URL }}
@@ -125,6 +130,7 @@ jobs:
run: bash "$SCRIPTS/install-opencode.sh"
- name: Install caller-provided skills (from the caller repo's .gitea/agent-skills/)
if: steps.prep.outputs.mode != 'skip'
# Framework skill-plugin hook. A consuming repo can ship its OWN opencode skills under
# `.gitea/agent-skills/<name>/` (SKILL.md + skill.json + optional setup.sh) — e.g. homelab's
# "ssh into the deploy host" skill. This installs the ones allowed for the running agent, so
@@ -139,6 +145,7 @@ jobs:
run: bash "$SCRIPTS/install-caller-skills.sh"
- name: Set up `gitea-api` skill (let agents read/write issues, PRs, Actions across repos)
if: steps.prep.outputs.mode != 'skip'
# Emits an opencode Skill file. The skill uses SELF_TOKEN — the running agent's OWN token
# (e.g. TOKEN_PM for @pm), injected into the Run-agent step below — so each agent talks to
# Gitea as itself. This step only writes the doc; permission.skill scopes who may load it.
@@ -147,6 +154,7 @@ jobs:
run: bash "$SCRIPTS/skill-gitea-api.sh"
- name: Set up `gitea-admin` skill (@ops only — administer the Gitea instance)
if: steps.prep.outputs.mode != 'skip'
# Instance administration (orgs/users/repos/labels/secrets/scoped tokens). The SKILL.md is
# written ONLY for @ops (skill-gitea-admin.sh gates on NAME) and permission.skill also denies
# it to every other agent. It uses SELF_TOKEN (which for @ops is TOKEN_OPS), injected into the
@@ -157,6 +165,7 @@ jobs:
run: bash "$SCRIPTS/skill-gitea-admin.sh"
- name: Inspect / fetch image attachments (download only for vision agents)
if: steps.prep.outputs.mode != 'skip'
id: imgs
env:
SCRIPTS: ${{ runner.temp }}/agents-scripts
@@ -166,6 +175,7 @@ jobs:
run: bash "$SCRIPTS/fetch-images.sh"
- name: Fetch the full issue thread (shared memory)
if: steps.prep.outputs.mode != 'skip'
env:
SCRIPTS: ${{ runner.temp }}/agents-scripts
GT: ${{ secrets.GITEA_TOKEN }}
@@ -173,6 +183,7 @@ jobs:
run: bash "$SCRIPTS/fetch-thread.sh"
- name: Run agent
if: steps.prep.outputs.mode != 'skip'
id: run
env:
SCRIPTS: ${{ runner.temp }}/agents-scripts
@@ -198,6 +209,7 @@ jobs:
run: bash "$SCRIPTS/run-agent.sh"
- name: Build run report (tool calls + input/output tokens + $ cost) from the event stream
if: steps.prep.outputs.mode != 'skip'
id: log
env:
SCRIPTS: ${{ runner.temp }}/agents-scripts
@@ -206,6 +218,7 @@ jobs:
run: bash "$SCRIPTS/build-activity-log.sh"
- name: Publish — PR (dev agents) or comment (pm), always reply in the issue
if: steps.prep.outputs.mode != 'skip'
env:
SCRIPTS: ${{ runner.temp }}/agents-scripts
GT: ${{ secrets.GITEA_TOKEN }}
@@ -232,7 +245,7 @@ jobs:
# This best-effort step opens a PR for the pushed branch so nothing is silently lost. Runs from
# $SCRIPTS (outside the workspace) so it works even if the tree was mangled by the agent.
- name: Rescue — open a PR for pushed work if the run failed
if: failure()
if: failure() && steps.prep.outputs.mode != 'skip'
env:
SCRIPTS: ${{ runner.temp }}/agents-scripts
GT: ${{ secrets.GITEA_TOKEN }}