-
Notifications
You must be signed in to change notification settings - Fork 12
feat(retro): add flapping detection to retro analysis skill #540
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
de40314
ca31c01
6495895
30c8f64
b11fab1
f581d10
ca4b912
bd3fb8d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -121,6 +121,50 @@ After subagents return their findings, use your main context to: | |
| 3. Form hypotheses about root causes | ||
| 4. Decide what changes to propose and where | ||
|
|
||
| ## Flapping detection | ||
|
|
||
| Check whether the workflow exhibits fix-break oscillation. Flapping wastes agent cycles and often indicates a deeper problem (conflicting instructions, flaky tests, or an approach the agent cannot converge on). | ||
|
|
||
| ### Signals to check | ||
|
|
||
| Flapping detection applies to PR-based workflows with code/fix cycles. Derive the PR number from the originating URL, branching on its shape: | ||
|
|
||
| - If `$ORIGINATING_URL` matches `/pull/`, extract directly: `PR_NUMBER="${ORIGINATING_URL##*/}"` and set `REPO="$REPO_FULL_NAME"`. | ||
| - If it matches `/issues/`, check for a linked PR before skipping (issue-triggered retros routinely have downstream code dispatches once the issue reaches `ready-to-code`). Query `gh issue view "$ORIGINATING_URL" --json closedByPullRequestsReferences`. If multiple PRs are linked, prefer the one in `$REPO_FULL_NAME`; otherwise use the most recently updated entry and note the ambiguity in the retro summary. Set `REPO` to the matching entry's `repository.owner.login/repository.name` and `PR_NUMBER` to its `number`. If no linked PR is found, skip flapping detection for this retro. | ||
|
|
||
| Derive `ISSUE_REF` from the PR branch name using the `agent/{issue}-{slug}` convention documented in "From a PR" above (e.g. branch `agent/5512-flapping` yields `ISSUE_REF="5512"`). | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. MEDIUM — ISSUE_REF derivation has no fallback and is used as an unconstrained grep substring
Suggestion: Constrain |
||
|
|
||
| Dispatch subagents to gather the data. Substitute `<DISPATCH_REPO>` (from Setup), `<REPO>`, `<PR_NUMBER>`, and `<ISSUE_REF>` with the concrete values derived above before dispatching. | ||
|
|
||
| Dispatch Run discovery and Review history in parallel. CI results depends on Run discovery's output (the correlated commit SHAs), so dispatch it after Run discovery returns. | ||
|
|
||
| - **Run discovery:** "List all code, fix, and review workflow runs via `gh run list --workflow=code.yml --repo <DISPATCH_REPO> --limit 100`, `gh run list --workflow=fix.yml --repo <DISPATCH_REPO> --limit 100`, and `gh run list --workflow=review.yml --repo <DISPATCH_REPO> --limit 100`. Filter to runs belonging to PR #<PR_NUMBER> by grepping each run's logs (`gh run view <RUN_ID> --repo <DISPATCH_REPO> --log | grep -i '<ISSUE_REF>'`). For each matching code/fix run, correlate it to a PR commit by matching the run's timestamp against the PR's commit history (no direct run-to-SHA mapping is exposed); if two candidate commits/runs fall within a short window, mark the correlation as uncertain. Then fetch that commit's changed files via `gh api repos/<REPO>/commits/<SHA>` (`.files`). Use workflow-run boundaries to define 'runs', not individual commits; a single run may produce more than one commit." | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. HIGH — "No direct run-to-SHA mapping" claim is false — the exact SHA is already in the log the subagent greps The Run discovery subagent prompt says to correlate a run to a PR commit "by matching the run's timestamp against the PR's commit history (no direct run-to-SHA mapping is exposed)" and to mark two-candidates-in-a-short-window correlations as uncertain. I verified live against a real fullsend-ai/.fullsend review.yml run ( Suggestion: Have the Run discovery subagent parse
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. HIGH — Run discovery scans up to 300 full run logs with no time bound, risking the retro's 30-minute budget and duplicating an existing cheaper approach The Run discovery subagent lists up to 100 runs each for code.yml/fix.yml/review.yml (up to 300 total) in the shared org-wide Suggestion: Bound
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. MEDIUM — Run-matching grep on bare issue number risks cross-repo false positives in the shared dispatch repo
Suggestion: Require the log to contain both
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. MEDIUM — Bulk workflow-log ingestion isn't covered by the existing redaction rule Run discovery instructs subagents to pull full workflow logs ( Suggestion: Bound log reads to the small correlated-run set (per the run-discovery-cost finding above), and extend the existing "summarize, do not paste verbatim" rule in |
||
| - **Review history:** "Fetch all reviews for PR #<PR_NUMBER> via `gh api repos/<REPO>/pulls/<PR_NUMBER>/reviews --paginate`, then fetch per-review comments. Summarize the findings from each review cycle so that finding content can be compared across cycles." | ||
| - **CI results** (after Run discovery): "For each commit SHA from the Run discovery results, query `gh api repos/<REPO>/commits/<SHA>/check-runs` and report the test pass/fail results." | ||
|
|
||
| Then check for these patterns: | ||
|
|
||
| 1. **File oscillation:** the same file was changed in two or more consecutive runs, and the changes reverse each other (lines added in run N were removed in run N+1, or vice versa). | ||
| 2. **Test result flipping:** a test that passed after run N fails after run N+1, then passes again after run N+2, and the flapping test covers a file the agent modified in the same run. Tests that flip independently of agent changes may be pre-existing flaky tests, not agent-caused oscillation. | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. MEDIUM — Test-result-flipping signal requires a test-to-file coverage mapping that no described data source provides Pattern 2 requires knowing that "the flapping test covers a file the agent modified in the same run" to distinguish real agent-caused oscillation from pre-existing flaky tests. But the data-gathering subagent prompt only collects changed-file lists (from code/fix runs) and check-run pass/fail status per commit (via Suggestion: Either specify a concrete heuristic (e.g., match test file paths whose names substring-match a changed file's basename, or parse coverage-report artifacts if one exists), or relax the pattern to something checkable from the collected data (e.g., "a test flips status across 3+ runs; treat as higher-confidence flapping if a related-by-name file also changed in the same runs") and note the strict per-file-coverage version as a future refinement once that data source exists. |
||
| 3. **Cycle count:** more than 2 review-fix cycles on the same PR without convergence (the review keeps requesting changes on the same or alternating findings, e.g. a fix for one issue reintroducing a previously resolved one counts as flapping too). This threshold is a starting point; see [flapping-convergence.md](https://github.com/fullsend-ai/fullsend/blob/main/docs/problems/flapping-convergence.md) for open questions on making it configurable per repo/task type. | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. MEDIUM — Cycle-count pattern contradicts the file's own "When NOT to flag" guidance Pattern 3 flags "more than 2 review-fix cycles on the same PR without convergence," counting cycles regardless of whether changes are reversed. But "When NOT to flag" (lines 164-166) states a single rework cycle is normal and instructs to "only flag when you see the same changes being applied and reversed repeatedly." Three clean forward-progress review rounds (e.g., tests requested, then error handling requested, then approved — no reversal at all) satisfies Pattern 3's raw cycle count while explicitly violating the "When NOT to flag" rule. The two sections give an agent contradictory instructions for the same scenario. Suggestion: Pick one coherent rule: either cycle count alone (and drop/soften the "only when reversed" language in "When NOT to flag"), or require reversal/recurrence of the same finding for all three patterns, not just Patterns 1 and (implicitly) 3's parenthetical. |
||
|
|
||
| ### When flapping is detected | ||
|
|
||
| Include a proposal with these specifics: | ||
|
|
||
| - **target_repo:** the repo where the fix should land (see Localization guidance below) | ||
| - **title:** Start with "Flapping detected:" followed by what oscillated | ||
| - **what_happened:** List each cycle with the run IDs, which files changed, and how the changes reversed | ||
| - **what_could_go_better:** Identify what might be causing the loop (conflicting review criteria, flaky test, ambiguous instructions) | ||
| - **proposed_change:** Suggest a concrete intervention (clarify the conflicting instruction, fix the flaky test, add a convergence guard) | ||
| - **validation_criteria:** Define a measurable outcome tied to the specific pattern. For example: "The next 2 fix cycles touching <file> should not re-introduce the change reverted in run N+1." | ||
|
|
||
| ### When NOT to flag | ||
|
|
||
| - A single rework cycle (review requested changes, fix addressed them, review approved) is normal, not flapping. | ||
| - Different files changing across runs is normal iteration, not oscillation. | ||
| - Only flag when you see the same changes being applied and reversed repeatedly. | ||
|
|
||
|
Comment on lines
+124
to
+167
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 1. Protected skills/ file modified This PR modifies a protected governance/infrastructure path (skills/retro-analysis/SKILL.md), so it must not be auto-approved and requires explicit human review controls. Without enforcing this, governance-critical content can change without appropriate oversight. Agent Prompt
|
||
| ## Before proposing: check for existing issues | ||
|
|
||
| **This step is mandatory.** Before including any proposal in your output, verify that no open issue already covers the same improvement. The retro agent is the primary source of systemic proposals — without this check, repeated runs produce duplicate issues that waste human triage time. | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
HIGH — "Most recently updated entry" tie-break (added this round) can't be implemented with the specified command
The issue-URL branch now says: "If multiple PRs are linked, prefer the one in $REPO_FULL_NAME; otherwise use the most recently updated entry and note the ambiguity." I verified live:
gh issue view <url> --json closedByPullRequestsReferences(e.g. against this PR's own linked issue) returns onlyid,number,repository{id,name,owner}, andurlper entry — no timestamp field at all. An agent following this instruction literally has no data to determine which entry is "most recently updated." This appears to be a new gap introduced by this round's fix to a previously-flagged ambiguity (the round-6 fix added the tie-break rule but the rule references data the specified command doesn't return).Suggestion: Either specify a command that actually returns the needed timestamp (e.g., a
gh api graphqlquery requestingupdatedAtonclosedByPullRequestsReferences, or a follow-upgh pr viewper candidate), or drop the recency tie-break for a simpler, verifiable rule (e.g., highest PR number, or note all candidates without picking one).