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
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:
co-authored by
Claude Opus 4.8
parent
84467f6dfd
commit
e9df9d6bdd
@@ -44,8 +44,14 @@ trig() { if [ -z "$TTOK" ]; then echo "no trigger token — cannot fire on #$1";
|
||||
# Origin issue for this run (route.sh resolves it from the branch on PR threads), and a resolver for
|
||||
# the open PR built from its branch (ai/issue-<issue>). Lets @pm/@qa cross between the issue and PR.
|
||||
ISSN="${ISSNUM:-$NUM}"
|
||||
resolve_pr() { curl -sS "${hdr[@]}" "$API/pulls?state=open&limit=50" \
|
||||
| jq -r --arg br "ai/issue-$ISSN" 'if type=="array" then (map(select(.head.ref==$br))|.[0].number // empty) else empty end' 2>/dev/null; }
|
||||
# All OPEN PRs belonging to this issue, oldest→newest. Matches ai/issue-N AND the ai/issue-N-<slug>
|
||||
# split branches AGENTS.md tells devs to use — an exact-only match silently stalled the flow on
|
||||
# slugged branches (DELEGATE:@qa found "no open PR"; autopilot MERGE_PR couldn't merge).
|
||||
resolve_prs() { curl -sS "${hdr[@]}" "$API/pulls?state=open&limit=50" \
|
||||
| jq -r --arg br "ai/issue-$ISSN" 'if type=="array" then
|
||||
([ .[] | select(.head.ref==$br or (.head.ref|startswith($br+"-"))) | .number ] | sort | join(" "))
|
||||
else "" end' 2>/dev/null; }
|
||||
resolve_pr() { resolve_prs | awk '{print $NF}'; } # newest open PR (empty if none)
|
||||
# Remove the 'autopilot' label from an issue by resolving its ID first (Gitea's DELETE label
|
||||
# endpoint is by ID, not name). Arg $1 = issue number. Used as the autopilot kill switch.
|
||||
del_autopilot_label() {
|
||||
@@ -194,9 +200,13 @@ if [ "$MODE" != "pr" ]; then
|
||||
# (@qa never merges — it approves and hands back here.) Merge with the PAT (TTOK), not the built-in
|
||||
# token, so the push to main fires the deploy. TOKEN_PM must carry write:repository.
|
||||
if [ "$NAME" = "pm" ] && [ "$AUTOPILOT" = "true" ] && grep -qiE '^[[:space:]]*MERGE_PR[[:space:]]*$' /tmp/agent_out.md; then
|
||||
PRN=$(resolve_pr)
|
||||
PRS=$(resolve_prs); PRN=${PRS##* }; CNT=$(echo "$PRS" | wc -w)
|
||||
if [ -z "$PRN" ]; then
|
||||
echo "MERGE_PR but no open PR found for issue #$ISSN"
|
||||
elif [ "$CNT" -gt 1 ]; then
|
||||
# Split-PR work: auto-merging just one of several open PRs is half a change deployed.
|
||||
del_autopilot_label "$ISSN"
|
||||
post_to "$ISSN" "⚠️ This issue has $CNT open PRs (#${PRS// /, #}) — autopilot only merges single-PR work. Removed the autopilot label; @ffaerber please review and merge them in order."
|
||||
else
|
||||
echo "@pm autopilot: merging PR #$PRN (issue #$ISSN)"
|
||||
mc=$(curl -sS -o /tmp/merge_resp.txt -w '%{http_code}' -X POST \
|
||||
@@ -221,7 +231,7 @@ if [ "$MODE" != "pr" ]; then
|
||||
# pm → qa → merge), and run-agent.sh injects LEARNINGS.md into every future prompt — closing the loop.
|
||||
if [ "$NAME" = "pm" ] && grep -qiE '^[[:space:]]*RETRO[[:space:]]*$' /tmp/agent_out.md; then
|
||||
PRN=$(curl -sS "${hdr[@]}" "$API/pulls?state=all&limit=50" \
|
||||
| jq -r --arg br "ai/issue-$ISSN" 'if type=="array" then ([.[]|select(.head.ref==$br)] | sort_by(.number) | last | .number // empty) else empty end' 2>/dev/null)
|
||||
| jq -r --arg br "ai/issue-$ISSN" 'if type=="array" then ([.[]|select(.head.ref==$br or (.head.ref|startswith($br+"-")))] | sort_by(.number) | last | .number // empty) else empty end' 2>/dev/null)
|
||||
rbody=$(printf 'Retrospective for issue #%s%s.\n\nRead the FULL issue thread%s using the gitea-api skill (issue comments%s and the PR diff). Identify what went wrong, slow, or needed human correction — missed wiring, review misses, bounced rounds, unclear delegation, missing context.\n\nThen APPEND the distilled learnings to `LEARNINGS.md` at the repo root (create it with a short header if missing). Rules for entries:\n- 3 to 6 bullets max, each ONE line: `symptom -> rule for next time`.\n- Concrete and checkable (name the file/step/marker), not generic advice.\n- Do not repeat an existing bullet; refine it instead.\n- Do not rewrite unrelated parts of the file.\n\nThese learnings are injected into every future agent prompt, so quality over quantity.' \
|
||||
"$ISSN" "${PRN:+ / PR #$PRN}" "${PRN:+ and PR #$PRN thread}" "${PRN:+, PR comments}")
|
||||
rnum=$(curl -sS -X POST "${hdr[@]}" "$API/issues" \
|
||||
@@ -242,8 +252,10 @@ if [ "$MODE" != "pr" ]; then
|
||||
# the PR. Chain terminates: normal → @pm tells the creator (no marker); autopilot → @pm merges above.
|
||||
if [ -n "$target" ] && [ "$target" != "$NAME" ]; then
|
||||
if [ "$target" = "qa" ]; then
|
||||
PRN=$(resolve_pr)
|
||||
if [ -n "$PRN" ]; then
|
||||
PRS=$(resolve_prs); PRN=${PRS##* }; CNT=$(echo "$PRS" | wc -w)
|
||||
if [ -n "$PRN" ] && [ "$CNT" -gt 1 ]; then
|
||||
trig "$ISSN" "@qa please review the $CNT open PRs for issue #$ISSN (#${PRS// /, #}) — put your recommendations on each PR; approve only when ALL are good."
|
||||
elif [ -n "$PRN" ]; then
|
||||
trig "$ISSN" "@qa please review PR #$PRN for issue #$ISSN — put your recommendations on the PR, or approve."
|
||||
else
|
||||
echo "DELEGATE:@qa but no open PR yet for issue #$ISSN — not firing"
|
||||
|
||||
Reference in New Issue
Block a user