11 KiB
Pydantic AI Stale Issues Finder
Objective
Review the entire open-issues corpus every run and identify issues that are very likely already resolved, no longer relevant, duplicates, or tied to deprecated/removed features. Then file one triage-report issue listing the close candidates with concrete evidence. The report is human-in-the-loop only; it does not close anything automatically.
For completed recommendations, the issue must be fully resolved, not
partially resolved. If any substantive work from the original issue still
remains open — including follow-up implementation, required docs work,
remaining edge cases, or maintainer-requested cleanup — skip the issue.
Do NOT add labels, comment on issues, or close issues. Only
mcp__safeoutputs__create_issue and mcp__safeoutputs__noop are permitted.
The bar is high: only include issues where you are confident. False positives waste maintainer time and erode trust. If you are unsure about an issue, or if it looks only partially fixed, skip it.
Data Gathering
-
Load the full local issue corpus (already prefetched)
A prescan step has already fetched open issues into local files before the AWF firewall blocks gh CLI access.
Available local inputs:
/tmp/gh-aw/agent/open-issues.tsv- Columns:
number,title,updated_at,created_at,label_names
- Columns:
/tmp/gh-aw/agent/issues/all/{issue_number}.json- One JSON file per open issue (full body + metadata)
/tmp/gh-aw/agent/issues/batch-manifest.tsv- Maps issue numbers to batch folders
/tmp/gh-aw/agent/issues/batches/batch-XXX/*.json- Pre-batched issue files for subagent fan-out
Start by reading
open-issues.tsvandbatch-manifest.tsv. -
Review all open issues every run
You must process the entire open issue set from disk each run (not just oldest issues, not a fixed sample, not top 10). Age is a prioritization hint, not a scope limiter.
-
Subagent fan-out over local batch folders
Launch parallel
Tasksubagents, one subagent per batch folder (or combine 2 small folders if needed). Use local files only for first-pass triage.Subagents must NOT call GitHub search/list/read APIs for this first pass; they should operate from
/tmp/gh-aw/agent/issues/batches/*files and the local repository code.Each subagent should, for each issue file in its batch:
a) Read local issue JSON
- Number, title, body, labels, timestamps
b) Triaging checks from local data and repository code
- Does issue text reference behavior that is clearly gone/renamed/removed?
- Does issue describe behavior that is now implemented in current code?
- Is there explicit local evidence in issue body text (for example, mention of a merged PR number or closure language) that merits escalation?
- Is the issue obviously meta/tracking/umbrella and therefore out of scope?
c) Return structured JSON for the whole batch
- Do not write files.
Tasksubagents are read-only. - Return one compact JSON object for the batch using this schema:
{ "batch_name": "batch-001", "summary": { "candidate_count": 3, "skip_count": 21, "needs_comment_check_count": 1 }, "verdicts": [ { "issue": 1234, "verdict": "CANDIDATE", "confidence": "high", "reason": "short reason", "evidence": ["bullet 1", "bullet 2"], "recommended_close_reason": "completed", "linked_pr_numbers": [1111, 2222] } ] }
d) Keep the response compact
- Include all non-
SKIPverdicts in full - For
SKIPissues, include only enough entries for accurate coverage accounting and dedupe-free processing - Output valid JSON only; no prose before or after
-
Supervisor second pass (targeted comment checks only)
After all subagents complete:
- Aggregate all subagent JSON responses
- Build shortlist = all
CANDIDATE+NEEDS_COMMENT_CHECK - For shortlist only, fetch comments live to confirm or reject closure
confidence — comments are NOT in the prefetched corpus. Use the proxied
ghCLI:gh api repos/pydantic/pydantic-ai/issues/<n>/comments(a per-issue read; nomcp__github__*tools exist, and only/searchis firewall-blocked). If that call is unavailable, leave the item asNEEDS_COMMENT_CHECKrather than asserting staleness. - If comment evidence weakens confidence, downgrade to
SKIP
-
Build final close-candidate set
Include only issues with high-confidence evidence after second-pass checks. Track coverage stats:
total_opentotal_processed(must equaltotal_openunless a file is corrupt)candidate_countcomment_checks_performed
Key areas of the codebase to know:
pydantic_ai_slim/pydantic_ai/models/— model provider integrations (one file per provider)pydantic_ai_slim/pydantic_ai/— core agent, tools, output, dependencies, message historypydantic_ai_slim/pydantic_ai/providers/— provider credential helperspydantic_graph/— graph/node executionpydantic_evals/— evaluation frameworkclai/— CLI and web UItests/— integration tests (also useful for confirming fix presence)
What Qualifies as "Very Likely Resolved or Closeable"
Only flag an issue if you have strong evidence from at least one of these categories:
-
Merged PR with explicit link — A merged PR contains
fixes #N,closes #N, orresolves #Nin its body or commit messages, but the issue was not auto-closed (e.g., PR targeted a non-default branch) -
Code evidence — The specific bug, missing feature, or requested change described in the issue is verifiably addressed in the current codebase. You must confirm this by reading the relevant code — not just by finding a likely-looking PR. Do not use this category if any meaningful part of the original issue remains outstanding.
-
Conversation consensus — The issue thread contains clear agreement that the issue is resolved (e.g., the reporter confirmed the fix, a maintainer said "this is done"), and there is no remaining follow-up work called out, but nobody closed it.
-
Deprecated or removed feature — The issue references a public API, class, parameter, or integration that no longer exists in
main(e.g., a provider that was renamed or dropped, a kwarg that was removed). Confirm by reading the codebase or changelog. -
Answered question with no follow-up — The issue is a question where the original reporter's question was answered in the comments, with no follow-up activity for 90+ days.
What to Skip
- Issues with activity in the last 14 days — someone is actively working on them
- Issues labeled
epic,tracking,umbrella, orgood first issue - Issues where the resolution is ambiguous or you aren't confident
- Issues that are only partially resolved, even if the main bug was fixed
- Issues where code landed but docs, follow-up implementation, or other maintainer-requested work still remains
- Feature requests where you can't definitively confirm implementation
- Issues with open/unmerged PRs linked — work may still be in progress
- Issues that reference ongoing design discussions or open PRs
- Performance or UX issues where "resolved" is subjective
- Any issue not processed through the local file corpus in this run
When in doubt, skip the issue. A short report with high-confidence candidates is far more valuable than a long report full of maybes.
Deduplication — mandatory BEFORE filing
Search the prefetched local corpus for existing stale-finder reports that might
overlap this run — grep the on-disk issue list for the [stale-finder] title
prefix (no live GitHub call needed):
grep -F '[stale-finder]' /tmp/gh-aw/agent/open-issues.tsv
Do not skip this run just because a previous report exists. You are reviewing
the full corpus every run. If no candidates qualify this run, call
mcp__safeoutputs__noop with coverage stats.
Sandbox notes
- Read files in large ranges (500+ lines per call). Do NOT read 30–80 lines at a time.
- Use the native
GrepandGlobtools for codebase search. - There are no
mcp__github__*tools, and live GitHub search is blocked by the firewall proxy. Do first-pass triage entirely from the prefetched local corpus (/tmp/gh-aw/agent/open-issues.tsvandissues/all/{number}.json) — it holds the full open-issue set with titles, labels, and timestamps, so first-pass needs no live call. - The corpus does NOT include comments. For the second-pass shortlist only,
fetch them with the proxied
ghCLI (gh api repos/pydantic/pydantic-ai/issues/<n>/comments) — a per-issue read, not search.
Issue Format
Issue title: Stale issues report — [N] issues likely resolved or obsolete
Issue body:
Stale Issues Report
The following open issues appear to already be resolved, no longer relevant, or related to deprecated/removed features. Each entry includes the evidence supporting closure.
Reviewed {total_processed} of {total_open} open issues this run. Performed {comment_checks_performed} targeted comment checks. ({total_open} total open issues).
1. #{number} — {issue title}
Evidence: {What makes you confident this is resolved or obsolete} Resolving PR: #{PR number} (if applicable) Recommendation: Close as {completed / not planned / duplicate}
2. #{number} — {issue title}
...
Suggested Actions
- Review and close #{number} — {one-line reason}
- Review and close #{number} — {one-line reason}
Guidelines:
- Do not place the issue body in a block quote in the actual output — write it directly.
- Do not cap to 10. Include every high-confidence close candidate found in this full-corpus run.
- Always include the specific evidence — don't just say "this looks resolved."
- Link to the resolving PR, commit, or code line when possible.
- If no issues qualify, call
mcp__safeoutputs__noopwith message: "No stale issues found — reviewed {total_processed}/{total_open} open issues with {comment_checks_performed} targeted comment checks."