Fix Issue — From Issue to Review-Ready PR
Drive one LFortran issue (which may involve several compiler bugs) to a single
pull request that is green in CI and clean under pr-review:
setup ─► repro-issue ─► ┌─► create-mre ─► fix-mre ─► issue check ─┐
│ │
└──────── original issue still fails ◄─────┤
│ fixed
┌──────────────────────── open draft PR ◄──────────────┘
▼
┌─► CI watch + fresh pr-review + human comments
│ │
│ ├─ clean, no label yet ─► add Tests::Run-Exhaustive ─► CI watch
│ ├─ clean + exhaustive green ─► mark PR ready ─► final report
│ ▼
└── fix subagent (commit, push)
unrelated pre-existing bugs (any phase) ─► followups.md ─► file issues, link in PR
You are the orchestrator: delegate everything
Do all the real work in subagents. Your job as the top-level agent is to
sequence phases, pass short handoffs between them, and decide what happens
next. Keep your own context small so it stays accurate across a loop that can
last hours:
- Spawn a fresh subagent for every phase and for every review/fix round.
In Claude Code use the
Agent tool; in other runtimes, use their equivalent.
Never reuse a reviewer's context for fixing, or a fixer's context for
reviewing.
- Do not read source files, diffs, test logs, or CI logs yourself. Subagents
read them and return a short report.
- Every subagent prompt must be self-contained: a fresh subagent does not
see this conversation. Include the issue identifier, branch, PR number, state
directory, which skill to load, what to do, what it is authorized to do, and
the exact report format to return. Tell it to load skills by name (Claude
Code: the
Skill tool) or to read .agents/skills/<name>/SKILL.md.
- Ask every subagent to end with a report of at most ~20 lines and to put
anything longer (logs, review text, PR body) in a file under the state
directory, returning only the path.
- Only one subagent may modify the checkout at a time. Read-only subagents
(review, follow-up filing) may run concurrently with a CI watch, never with
a fixer.
- Every report ends with an Unrelated bugs list (or
none): LFortran bugs
the subagent ran into that are not needed to fix the original issue, such
as a failure that also occurs on main or a separate bug seen while
reducing or reviewing. One line each, plus a pointer to where the details
(code, command, output) are saved. Never silently drop them, and never
bundle their fixes into this PR. Append each new one to followups.md.
State directory
Keep handoffs on disk, in .fix-issue/<id>/ at the repository root (it is
gitignored). <id> is the GitHub issue number, or a short slug for other
input. Maintain .fix-issue/<id>/state.md yourself. Keep it to a few lines:
the input, branch, fork remote, PR URL, current round, last pushed head SHA,
and status. Update it after every phase. If your context is compacted or the
session resumes, reread state.md to find where you are.
Subagents write their artifacts there: repro.md; for each MRE iteration j,
mre_<j>.md, fix_<j>.md, check_<j>.md; then pr_body.md, and for each
review round k, review_<k>.md, round_<k>.md, ci_<k>.log. You maintain
followups.md: one line per unrelated bug, with its status (unfiled,
filed #M, duplicate of #M, or regression, sent to fix loop) and the
path to its details. The reproducers themselves (run_re.sh, re_*.f90,
run.sh, mre_*.f90) live in the repository root, following the conventions
of the repro-issue and create-mre skills. Before iteration j+1 overwrites run.sh, the current
MRE files are archived to .fix-issue/<id>/mre_<j>/.
Authorization
Invoking this skill counts as the user's consent to create a branch, commit,
push to the user's fork, open a draft PR against lfortran/lfortran, push
follow-up commits to that PR, add the Tests::Run-Exhaustive label to that
PR, open new issues at lfortran/lfortran for unrelated pre-existing bugs
found along the way, and mark the PR ready for review. This overrides the
"do not commit" default in fix-mre. Pass this authorization explicitly to
the subagents that need it.
Never, under any circumstances:
- push to the upstream
lfortran/lfortran repository;
- force-push, or rebase a branch that already has an open PR (merge
upstream/main into it instead, per AGENTS.md);
- comment on, close, or relabel the original issue, add any other label to
the PR, comment on other issues or PRs (including existing issues found in
a duplicate search), or post review comments on other people's PRs;
- run
./run_tests.py -u without reviewing every reference change.
Inputs
- The issue. Accept any of:
- a GitHub issue number (
12345), #12345, or URL. Default repo:
lfortran/lfortran. This is the common case.
- a pasted Fortran snippet with an error or wrong output;
- a failure in a third-party package (project, file, command, error);
- a JupyterLite / notebook failure.
Ask the user only if the input is missing or does not describe a failure.
Procedure
Phase 0: Preflight (orchestrator, cheap commands only)
Run a few quick checks yourself. Each prints only a few lines:
gh auth status. If gh is not logged in, stop and ask the user to run
! gh auth login.
gh api user --jq .login gives <login>.
git status --porcelain --untracked-files=no must be empty. Untracked
scratch files are fine. If tracked files are modified, stop and ask the
user. Never stash or discard their work.
- Identify remotes from
git remote -v:
- upstream remote: the one whose URL points at
lfortran/lfortran
(often origin or upstream);
- fork remote: the one whose URL points at
<login>/lfortran. If none
exists, create the fork without touching existing remotes:
gh repo fork lfortran/lfortran --clone=false, then
git remote add <login> git@github.com:<login>/lfortran.git (use the
https URL if gh auth status reports the https protocol).
- For a GitHub issue, look for existing work, and stop and ask the user if
there is any:
gh issue view <N> --repo lfortran/lfortran --json state,title (closed?)
and
gh pr list --repo lfortran/lfortran --state open --search "<N> in:body,title" --json number,title,author.
Create .fix-issue/<id>/state.md.
Phase 1: Setup subagent
It should:
git fetch <upstream-remote> main, then create and check out
fix/<id>-<short-slug> from <upstream-remote>/main. Derive the slug from
the issue title or the failure. If the branch name already exists, pick a
new suffix; do not reuse or reset an existing branch.
- Rebuild:
cmake --build build -j &> .fix-issue/<id>/build.log. If build/
is not configured, use the dev config from AGENTS.md. If modfiles are
stale, do a clean rebuild.
- Put
build/src/bin first on PATH and confirm which lfortran. Also
confirm that a reference compiler (gfortran preferred) exists.
Report: branch name, base SHA, build OK or failed (with the log path).
Phase 2: Reproduce subagent
- GitHub issue: run the
repro-issue skill on the issue. Output:
run_re.sh plus re_*.f90 in the repository root.
- Pasted snippet: apply the same RE conventions as
repro-issue (faithful
code, run_re.sh that shows the reference compiler succeeds and lfortran
fails), just without fetching from GitHub.
- Third-party or notebook failure: skip this phase.
create-mre handles
that input directly.
Report, also written to repro.md: reproduced yes/no, error type, the exact
LFortran error, the reference compiler result, and whether the issue contains
several distinct bugs.
Stop and report to the user if the bug does not reproduce on current
main (it may already be fixed), or if the reference compiler also rejects
the code (the code may be invalid). Do not open a PR in either case.
Phase 3: MRE loop — reduce, fix, check until the issue is fixed
Many issues hide several compiler bugs. For this skill, "one PR" means one
PR per issue: each bug still gets its own MRE, commit, and integration test,
so reviewers can follow the commits one by one. Fixing the first one often just
exposes the next failure in the same code. Iterate j = 1, 2, ... with no
fixed cap. Every iteration adds one commit with its own integration test
to the same branch. All of them ship together in a single PR.
Stop the loop and report to the user if there is no progress: an iteration
produced no verified fix, or the issue check shows the same failure as the
previous iteration. Never open a PR for an unverified fix.
3a. Reduce subagent
If j > 1, first move the previous run.sh and mre_*.f90 to
.fix-issue/<id>/mre_<j-1>/. Then run the create-mre skill on the
current failure of the original reproducer:
- for
j = 1, the RE from Phase 2, or the third-party failure;
- for
j > 1, the failure recorded in check_<j-1>.md, which is produced by
the in-tree lfortran that already includes the earlier fixes.
Output: run.sh plus mre_*.f90.
Report, also written to mre_<j>.md: the MRE files, a one-line bug
description, the error, and confirmation that run.sh fails with the current
in-tree LFortran and succeeds with the reference compiler.
If the current failure contains several distinct bugs, reduce only one
per iteration. The loop picks up the rest.
3b. Fix subagent
Run the fix-mre skill on the MRE, with these additions to its instructions:
- Tell it which earlier iterations already committed fixes on this branch
(from
fix_<1..j-1>.md). It must not undo them, and must not duplicate
their integration tests.
- It must verify that the new integration test fails without this
iteration's fix and passes with it. For
j > 1, "without" means the
branch before this iteration's change, not main.
- It must run the full integration suite and the reference suite, with output
redirected to log files. For every failure, it must determine whether this
change caused it or whether it also fails on
main.
- Commit is authorized. Make one focused commit for this bug, with an
imperative
fix: ... message. Do not stage scratch reproducers, logs, or
.fix-issue/.
- Do not push.
Report, also written to fix_<j>.md: the commit SHA, the changed files, the
test name, fail-before/pass-after verified, integration and reference
results, any failures that already exist on main, and one paragraph of
rationale (the bug, the compiler phase at fault, and why the fix belongs
there).
3c. Issue check subagent (fresh)
It verifies the original issue, not the MRE, against the rebuilt in-tree
lfortran:
- GitHub issue or pasted snippet: reread the issue text, including
comments, and run
run_re.sh. The program must now compile and run, and its
output must match the reference compiler's output and any expected output
stated in the issue. Also check every other program, flag combination, or
scenario the issue mentions that run_re.sh does not cover. If one is
missing, add it to run_re.sh.
- Third-party failure: re-run the original failing build or test
command, and continue past the point that used to fail.
Report, also written to check_<j>.md: fully fixed yes/no. If no, report the
exact new failure (the command, the error or the output diff, and the file
involved) and whether it is the same failure as in check_<j-1>.md.
If it is fully fixed, go to Phase 4. Otherwise start iteration j+1.
Phase 4: Publish subagent
It should:
- Write
.fix-issue/<id>/pr_body.md from repro.md and all the
fix_<j>.md files. Use plain Markdown with the headings Summary, Scope,
Verification, Rationale.
- Summary: first line
Fixes #<N> (omit it for non-GitHub input), then
the issue and a bullet per bug fixed, in commit order.
- Scope: what is and is not covered, including unrelated bugs found along
the way (linked once filed, see below) and non-bug follow-ups such as
refactoring ideas or missing tests for existing behaviour.
- Verification: the integration tests added, each failing before its fix
and passing after; the original reproducer now passing; the suite
results.
- Rationale: for each bug, why the fix belongs in the chosen compiler
phase.
git push -u <fork-remote> <branch>
gh pr create --repo lfortran/lfortran --base main --head <login>:<branch> --draft --title "<title>" --body-file .fix-issue/<id>/pr_body.md.
The title is the commit subject when there is a single commit. Otherwise
it is a fix: ... summary of the issue.
Report: the PR number, URL, and head SHA. Record them in state.md.
Follow-up issues subagent
Spawn it once the PR exists if followups.md has unfiled entries, and again
whenever a later round adds more (at the latest before Phase 6). It does not
edit tracked files; it puts scratch files under
.fix-issue/<id>/followup_<m>/, never in the repository root. For each
distinct bug it:
- Confirms the bug also fails on
main, reusing the discovering subagent's
evidence or building <upstream-remote>/main in a separate worktree
(never switch the PR checkout). If it does not fail on main, it is a
regression of this PR: do not file it; mark it for the fix loop instead.
- Searches for duplicates:
gh issue list --repo lfortran/lfortran --state all --search "<keywords>".
If one exists, record duplicate of #M and do not comment on it.
- Otherwise files one issue with
gh issue create --repo lfortran/lfortran --title "<bug>" --body-file <file>. The body contains: a minimal
self-contained reproducer, the exact LFortran command and output, the
reference compiler's result showing the code is valid, confirmation that
it fails on main, and the line Found while working on #<PR> (#<N>).
- Updates
followups.md, adds every filed or duplicate issue to the Scope
section of pr_body.md, and runs
gh pr edit <PR> --repo lfortran/lfortran --body-file .fix-issue/<id>/pr_body.md.
Only bugs are filed. Non-bug follow-ups go in the PR body and the final report.
Report: issues filed, duplicates linked, regressions sent back.
Phase 5: Review and CI loop
Repeat rounds k = 1, 2, ... up to 5 rounds. Each round works on the
current head SHA.
6a. Start the CI watch and a fresh review, concurrently.
- CI watch (orchestrator): run in the background so it does not block,
and send the output to a file, not your context:
gh pr checks <PR> --repo lfortran/lfortran --watch --interval 120 \
> .fix-issue/<id>/ci_<k>.log 2>&1; echo "exit=$?"
Checks can take a minute to appear after a push or labeling. If gh
reports no checks yet, wait and retry. CI can take over an hour. Do not
poll in short loops; wait for the background command to finish. Afterwards,
get only a summary:gh pr checks <PR> --repo lfortran/lfortran --json name,bucket \
--jq 'group_by(.bucket)[] | "\(.[0].bucket): \(length) \([.[].name] | join(", "))"'
If checks sit in action_required or never start, tell the user.
- Review subagent (fresh, read-only): run the
pr-review skill on
PR <PR> in lfortran/lfortran. It must not edit, commit, or push. It may
build and run tests in the checkout to confirm a finding, as long as it
leaves the tree unchanged. It writes the full review to review_<k>.md and
reports the number of findings in each class (blocker / rework /
follow-up), with a one-line title and file:line for each blocker and rework
item. Tell it to review the PR on its merits and report only real findings
it has checked. It must not invent findings to fill a quota, and must not
soften findings because an automated agent wrote the PR.
6b. Collect human feedback (orchestrator, summary only):
gh pr view <PR> --repo lfortran/lfortran --json reviewDecision,mergeable,reviews,comments \
--jq '{reviewDecision, mergeable, reviews: [.reviews[] | {author: .author.login, state}], comments: (.comments | length)}'
gh api repos/lfortran/lfortran/pulls/<PR>/comments --jq 'length'
Treat the comment counts as new only if they changed since the last round.
The fix subagent reads the actual comment text.
6c. Decide. The PR is clean when all of these hold for the current
head SHA:
- every CI check passed, or each failing check was shown by a subagent to
also fail on
main (it is pre-existing, so report it but do not fix it
here);
- the latest fresh review has no blocker and no rework findings;
- no human review comment or requested change is unaddressed;
mergeable is not CONFLICTING.
If clean and the PR does not have the label yet, add it:
gh pr edit <PR> --repo lfortran/lfortran --add-label Tests::Run-Exhaustive.
Wait until now because the exhaustive suite is expensive, and while the label
is present it reruns on every push (.github/workflows/Exhaustive-Checks-CI.yml
triggers on labeled and synchronize). If gh lacks permission to add
labels, tell the user and ask them to add it. Record the label in state.md,
then start the next round with only the CI watch; the head SHA is unchanged,
so the review stands, and this round does not count toward the cap.
The PR is done when it is clean, the label is present, and the
Exhaustive checks workflow ran on the current head SHA (not skipped) with
every job passed or shown to also fail on main. Check with
gh pr checks <PR> --repo lfortran/lfortran --json workflow,name,bucket.
If done, go to Phase 6. Exhaustive failures go to the fix subagent like any
other CI failure.
6d. Otherwise spawn a fresh fix subagent with the list of what is
outstanding: failing check names, the path review_<k>.md, and which human
comments are new. It should:
- For CI failures: read the logs
(
gh run view <run-id> --repo lfortran/lfortran --log-failed, saved to a
file), reproduce locally where possible, and fix the root cause. If a
failure also happens on main or is plainly infrastructure flakiness, do
not fix it in this PR. Re-run it once with gh run rerun <run-id> --failed
and report it; a pre-existing LFortran bug goes on its Unrelated bugs list.
- For each review blocker and rework finding: first confirm the
finding is real by reproducing it. Then fix it, or record in
round_<k>.md exactly why it is not valid. Leave follow-up items
unfixed; list them for the final report.
- For human review comments: address each one in code, or draft a reply in
round_<k>.md. Do not post replies automatically; the user decides.
- For merge conflicts:
git merge <upstream-remote>/main, resolve, rebuild,
and retest. Never rebase or force-push.
- Rebuild, rerun the MRE, the new integration test, and the affected suites
(the full integration and reference suites whenever compiler source
changed). Update
pr_body.md and the PR description
(gh pr edit <PR> --body-file ...) if scope or rationale changed.
- Commit focused follow-up commits and push them to the fork remote (a normal
push).
Report: what was fixed, what was rejected and why, the new head SHA, and test
results. Then start round k+1.
If the same finding or CI failure survives two fix rounds, or the round cap is
reached, stop the loop and report to the user with the outstanding items.
Do not keep iterating blindly.
Phase 6: Finish
- Mark the PR ready:
gh pr ready <PR> --repo lfortran/lfortran.
- Leave the branch checked out and do not delete the scratch reproducers.
The user may want them.
- Print the final report:
PR ready for review: <URL>
Issue: #<N> — <title> (original reproducer now passes)
Branch: <fork-remote>/<branch> head <sha>
Bugs fixed (<count> MRE iterations, one commit each):
1. <one line> — integration_tests/<test>.f90 (fails before, passes after)
2. ...
CI: green (pre-existing failures on main: <none | names>)
Exhaustive CI: green (pre-existing failures on main: <none | names>)
Review: <rounds> round(s); blockers/rework fixed: <n>; rejected with reason: <n>
Follow-up issues filed: <#M, #M (duplicate of existing), ... or none>
Other follow-ups (not bugs, not filed): <list or none>
Human comments needing your reply: <list or none>
Tips
- Context discipline is the point. If you catch yourself reading a diff
or a log, hand that job to a subagent instead.
- Resume: if the session is interrupted, reread
state.md, check
git log, gh pr view, and the .fix-issue/<id>/ artifacts, then continue
from the first phase that is not finished.
- Base freshness: if
main moved a lot during a long loop and CI failures
look unrelated to the PR, have the fix subagent merge upstream/main before
debugging.
- Build errors in CI only: other platforms (Windows/MSVC, WASM, other
backends) often fail where macOS/Linux pass. The fix subagent should read
the CI step's exact command and reproduce that backend locally where
feasible (see the CI-parity notes in
AGENTS.md).
1---2name: fix-issue3description: End-to-end fix of an LFortran bug, from issue to review-ready pull request. Takes an issue (most commonly a GitHub issue number or URL at lfortran/lfortran, but also a pasted snippet, error report, or third-party failure), then orchestrates fresh subagents that run repro-issue, then create-mre and fix-mre repeatedly (one MRE per underlying bug) until the original issue is fully fixed, open a draft PR from the user's fork with `gh`, review it with pr-review, and keep fixing CI failures and review blockers until the PR is green and clean, then add the Tests::Run-Exhaustive label, fix any exhaustive CI failures, and mark it ready for review. Unrelated pre-existing bugs found along the way are filed as separate issues and linked from the PR. Triggers: fix issue, fix github issue, issue to PR, resolve issue, send PR for issue, end-to-end fix.4---56# Fix Issue — From Issue to Review-Ready PR78Drive one LFortran issue (which may involve several compiler bugs) to a single9pull request that is green in CI and clean under `pr-review`:1011```12setup ─► repro-issue ─► ┌─► create-mre ─► fix-mre ─► issue check ─┐13 │ │14 └──────── original issue still fails ◄─────┤15 │ fixed16 ┌──────────────────────── open draft PR ◄──────────────┘17 ▼18 ┌─► CI watch + fresh pr-review + human comments19 │ │20 │ ├─ clean, no label yet ─► add Tests::Run-Exhaustive ─► CI watch21 │ ├─ clean + exhaustive green ─► mark PR ready ─► final report22 │ ▼23 └── fix subagent (commit, push)2425unrelated pre-existing bugs (any phase) ─► followups.md ─► file issues, link in PR26```2728## You are the orchestrator: delegate everything2930**Do all the real work in subagents.** Your job as the top-level agent is to31sequence phases, pass short handoffs between them, and decide what happens32next. Keep your own context small so it stays accurate across a loop that can33last hours:3435- Spawn a **fresh** subagent for every phase and for every review/fix round.36 In Claude Code use the `Agent` tool; in other runtimes, use their equivalent.37 Never reuse a reviewer's context for fixing, or a fixer's context for38 reviewing.39- Do not read source files, diffs, test logs, or CI logs yourself. Subagents40 read them and return a short report.41- Every subagent prompt must be **self-contained**: a fresh subagent does not42 see this conversation. Include the issue identifier, branch, PR number, state43 directory, which skill to load, what to do, what it is authorized to do, and44 the exact report format to return. Tell it to load skills by name (Claude45 Code: the `Skill` tool) or to read `.agents/skills/<name>/SKILL.md`.46- Ask every subagent to end with a **report of at most ~20 lines** and to put47 anything longer (logs, review text, PR body) in a file under the state48 directory, returning only the path.49- Only one subagent may modify the checkout at a time. Read-only subagents50 (review, follow-up filing) may run concurrently with a CI watch, never with51 a fixer.52- Every report ends with an **Unrelated bugs** list (or `none`): LFortran bugs53 the subagent ran into that are not needed to fix the original issue, such54 as a failure that also occurs on `main` or a separate bug seen while55 reducing or reviewing. One line each, plus a pointer to where the details56 (code, command, output) are saved. Never silently drop them, and never57 bundle their fixes into this PR. Append each new one to `followups.md`.5859### State directory6061Keep handoffs on disk, in `.fix-issue/<id>/` at the repository root (it is62gitignored). `<id>` is the GitHub issue number, or a short slug for other63input. Maintain `.fix-issue/<id>/state.md` yourself. Keep it to a few lines:64the input, branch, fork remote, PR URL, current round, last pushed head SHA,65and status. Update it after every phase. If your context is compacted or the66session resumes, reread `state.md` to find where you are.6768Subagents write their artifacts there: `repro.md`; for each MRE iteration `j`,69`mre_<j>.md`, `fix_<j>.md`, `check_<j>.md`; then `pr_body.md`, and for each70review round `k`, `review_<k>.md`, `round_<k>.md`, `ci_<k>.log`. You maintain71`followups.md`: one line per unrelated bug, with its status (`unfiled`,72`filed #M`, `duplicate of #M`, or `regression, sent to fix loop`) and the73path to its details. The reproducers themselves (`run_re.sh`, `re_*.f90`,74`run.sh`, `mre_*.f90`) live in the repository root, following the conventions75of the `repro-issue` and `create-mre` skills. Before iteration `j+1` overwrites `run.sh`, the current76MRE files are archived to `.fix-issue/<id>/mre_<j>/`.7778## Authorization7980Invoking this skill counts as the user's consent to create a branch, commit,81push to **the user's fork**, open a draft PR against `lfortran/lfortran`, push82follow-up commits to that PR, add the `Tests::Run-Exhaustive` label to that83PR, open new issues at `lfortran/lfortran` for unrelated pre-existing bugs84found along the way, and mark the PR ready for review. This overrides the85"do not commit" default in `fix-mre`. Pass this authorization explicitly to86the subagents that need it.8788Never, under any circumstances:8990- push to the upstream `lfortran/lfortran` repository;91- force-push, or rebase a branch that already has an open PR (merge92 `upstream/main` into it instead, per `AGENTS.md`);93- comment on, close, or relabel the original issue, add any other label to94 the PR, comment on other issues or PRs (including existing issues found in95 a duplicate search), or post review comments on other people's PRs;96- run `./run_tests.py -u` without reviewing every reference change.9798## Inputs991001. **The issue.** Accept any of:101 - a GitHub issue number (`12345`), `#12345`, or URL. Default repo:102 `lfortran/lfortran`. This is the common case.103 - a pasted Fortran snippet with an error or wrong output;104 - a failure in a third-party package (project, file, command, error);105 - a JupyterLite / notebook failure.106107Ask the user only if the input is missing or does not describe a failure.108109## Procedure110111### Phase 0: Preflight (orchestrator, cheap commands only)112113Run a few quick checks yourself. Each prints only a few lines:1141151. `gh auth status`. If gh is not logged in, stop and ask the user to run116 `! gh auth login`.1172. `gh api user --jq .login` gives `<login>`.1183. `git status --porcelain --untracked-files=no` must be empty. Untracked119 scratch files are fine. If tracked files are modified, stop and ask the120 user. Never stash or discard their work.1214. Identify remotes from `git remote -v`:122 - **upstream remote**: the one whose URL points at `lfortran/lfortran`123 (often `origin` or `upstream`);124 - **fork remote**: the one whose URL points at `<login>/lfortran`. If none125 exists, create the fork without touching existing remotes:126 `gh repo fork lfortran/lfortran --clone=false`, then127 `git remote add <login> git@github.com:<login>/lfortran.git` (use the128 https URL if `gh auth status` reports the https protocol).1295. For a GitHub issue, look for existing work, and stop and ask the user if130 there is any:131 `gh issue view <N> --repo lfortran/lfortran --json state,title` (closed?)132 and133 `gh pr list --repo lfortran/lfortran --state open --search "<N> in:body,title" --json number,title,author`.134135Create `.fix-issue/<id>/state.md`.136137### Phase 1: Setup subagent138139It should:1401411. `git fetch <upstream-remote> main`, then create and check out142 `fix/<id>-<short-slug>` from `<upstream-remote>/main`. Derive the slug from143 the issue title or the failure. If the branch name already exists, pick a144 new suffix; do not reuse or reset an existing branch.1452. Rebuild: `cmake --build build -j &> .fix-issue/<id>/build.log`. If `build/`146 is not configured, use the dev config from `AGENTS.md`. If modfiles are147 stale, do a clean rebuild.1483. Put `build/src/bin` first on `PATH` and confirm `which lfortran`. Also149 confirm that a reference compiler (`gfortran` preferred) exists.150151Report: branch name, base SHA, build OK or failed (with the log path).152153### Phase 2: Reproduce subagent154155- **GitHub issue:** run the `repro-issue` skill on the issue. Output:156 `run_re.sh` plus `re_*.f90` in the repository root.157- **Pasted snippet:** apply the same RE conventions as `repro-issue` (faithful158 code, `run_re.sh` that shows the reference compiler succeeds and `lfortran`159 fails), just without fetching from GitHub.160- **Third-party or notebook failure:** skip this phase. `create-mre` handles161 that input directly.162163Report, also written to `repro.md`: reproduced yes/no, error type, the exact164LFortran error, the reference compiler result, and whether the issue contains165several distinct bugs.166167**Stop and report to the user** if the bug does not reproduce on current168`main` (it may already be fixed), or if the reference compiler also rejects169the code (the code may be invalid). Do not open a PR in either case.170171### Phase 3: MRE loop — reduce, fix, check until the issue is fixed172173Many issues hide several compiler bugs. For this skill, "one PR" means one174PR per issue: each bug still gets its own MRE, commit, and integration test,175so reviewers can follow the commits one by one. Fixing the first one often just176exposes the next failure in the same code. Iterate `j = 1, 2, ...` with **no177fixed cap**. Every iteration adds **one commit with its own integration test**178to the same branch. All of them ship together in a single PR.179180Stop the loop and report to the user if there is no progress: an iteration181produced no verified fix, or the issue check shows the same failure as the182previous iteration. Never open a PR for an unverified fix.183184#### 3a. Reduce subagent185186If `j > 1`, first move the previous `run.sh` and `mre_*.f90` to187`.fix-issue/<id>/mre_<j-1>/`. Then run the `create-mre` skill on the188**current** failure of the original reproducer:189190- for `j = 1`, the RE from Phase 2, or the third-party failure;191- for `j > 1`, the failure recorded in `check_<j-1>.md`, which is produced by192 the in-tree `lfortran` that already includes the earlier fixes.193194Output: `run.sh` plus `mre_*.f90`.195196Report, also written to `mre_<j>.md`: the MRE files, a one-line bug197description, the error, and confirmation that `run.sh` fails with the current198in-tree LFortran and succeeds with the reference compiler.199200If the current failure contains several distinct bugs, reduce only **one**201per iteration. The loop picks up the rest.202203#### 3b. Fix subagent204205Run the `fix-mre` skill on the MRE, with these additions to its instructions:206207- Tell it which earlier iterations already committed fixes on this branch208 (from `fix_<1..j-1>.md`). It must not undo them, and must not duplicate209 their integration tests.210- It must verify that the new integration test **fails without this211 iteration's fix and passes with it**. For `j > 1`, "without" means the212 branch before this iteration's change, not `main`.213- It must run the full integration suite and the reference suite, with output214 redirected to log files. For every failure, it must determine whether this215 change caused it or whether it also fails on `main`.216- **Commit is authorized.** Make one focused commit for this bug, with an217 imperative `fix: ...` message. Do not stage scratch reproducers, logs, or218 `.fix-issue/`.219- Do not push.220221Report, also written to `fix_<j>.md`: the commit SHA, the changed files, the222test name, fail-before/pass-after verified, integration and reference223results, any failures that already exist on `main`, and one paragraph of224rationale (the bug, the compiler phase at fault, and why the fix belongs225there).226227#### 3c. Issue check subagent (fresh)228229It verifies the **original** issue, not the MRE, against the rebuilt in-tree230`lfortran`:231232- **GitHub issue or pasted snippet:** reread the issue text, including233 comments, and run `run_re.sh`. The program must now compile and run, and its234 output must match the reference compiler's output and any expected output235 stated in the issue. Also check every other program, flag combination, or236 scenario the issue mentions that `run_re.sh` does not cover. If one is237 missing, add it to `run_re.sh`.238- **Third-party failure:** re-run the original failing build or test239 command, and continue past the point that used to fail.240241Report, also written to `check_<j>.md`: fully fixed yes/no. If no, report the242exact new failure (the command, the error or the output diff, and the file243involved) and whether it is the same failure as in `check_<j-1>.md`.244245If it is fully fixed, go to Phase 4. Otherwise start iteration `j+1`.246247### Phase 4: Publish subagent248249It should:2502511. Write `.fix-issue/<id>/pr_body.md` from `repro.md` and all the252 `fix_<j>.md` files. Use plain Markdown with the headings Summary, Scope,253 Verification, Rationale.254 - Summary: first line `Fixes #<N>` (omit it for non-GitHub input), then255 the issue and a bullet per bug fixed, in commit order.256 - Scope: what is and is not covered, including unrelated bugs found along257 the way (linked once filed, see below) and non-bug follow-ups such as258 refactoring ideas or missing tests for existing behaviour.259 - Verification: the integration tests added, each failing before its fix260 and passing after; the original reproducer now passing; the suite261 results.262 - Rationale: for each bug, why the fix belongs in the chosen compiler263 phase.2642. `git push -u <fork-remote> <branch>`2653. `gh pr create --repo lfortran/lfortran --base main --head <login>:<branch> --draft --title "<title>" --body-file .fix-issue/<id>/pr_body.md`.266 The title is the commit subject when there is a single commit. Otherwise267 it is a `fix: ...` summary of the issue.268269Report: the PR number, URL, and head SHA. Record them in `state.md`.270271#### Follow-up issues subagent272273Spawn it once the PR exists if `followups.md` has `unfiled` entries, and again274whenever a later round adds more (at the latest before Phase 6). It does not275edit tracked files; it puts scratch files under276`.fix-issue/<id>/followup_<m>/`, never in the repository root. For each277distinct bug it:2782791. Confirms the bug also fails on `main`, reusing the discovering subagent's280 evidence or building `<upstream-remote>/main` in a separate worktree281 (never switch the PR checkout). If it does not fail on `main`, it is a282 regression of this PR: do not file it; mark it for the fix loop instead.2832. Searches for duplicates:284 `gh issue list --repo lfortran/lfortran --state all --search "<keywords>"`.285 If one exists, record `duplicate of #M` and do not comment on it.2863. Otherwise files one issue with `gh issue create --repo lfortran/lfortran287 --title "<bug>" --body-file <file>`. The body contains: a minimal288 self-contained reproducer, the exact LFortran command and output, the289 reference compiler's result showing the code is valid, confirmation that290 it fails on `main`, and the line `Found while working on #<PR> (#<N>)`.2914. Updates `followups.md`, adds every filed or duplicate issue to the Scope292 section of `pr_body.md`, and runs293 `gh pr edit <PR> --repo lfortran/lfortran --body-file .fix-issue/<id>/pr_body.md`.294295Only bugs are filed. Non-bug follow-ups go in the PR body and the final report.296297Report: issues filed, duplicates linked, regressions sent back.298299### Phase 5: Review and CI loop300301Repeat rounds `k = 1, 2, ...` up to **5 rounds**. Each round works on the302current head SHA.303304**6a. Start the CI watch and a fresh review, concurrently.**305306- **CI watch (orchestrator):** run in the background so it does not block,307 and send the output to a file, not your context:308 ```bash309 gh pr checks <PR> --repo lfortran/lfortran --watch --interval 120 \310 > .fix-issue/<id>/ci_<k>.log 2>&1; echo "exit=$?"311 ```312 Checks can take a minute to appear after a push or labeling. If `gh`313 reports no checks yet, wait and retry. CI can take over an hour. Do not314 poll in short loops; wait for the background command to finish. Afterwards,315 get only a summary:316 ```bash317 gh pr checks <PR> --repo lfortran/lfortran --json name,bucket \318 --jq 'group_by(.bucket)[] | "\(.[0].bucket): \(length) \([.[].name] | join(", "))"'319 ```320 If checks sit in `action_required` or never start, tell the user.321- **Review subagent (fresh, read-only):** run the `pr-review` skill on322 PR `<PR>` in `lfortran/lfortran`. It must not edit, commit, or push. It may323 build and run tests in the checkout to confirm a finding, as long as it324 leaves the tree unchanged. It writes the full review to `review_<k>.md` and325 reports the number of findings in each class (blocker / rework /326 follow-up), with a one-line title and file:line for each blocker and rework327 item. Tell it to review the PR on its merits and report only real findings328 it has checked. It must not invent findings to fill a quota, and must not329 soften findings because an automated agent wrote the PR.330331**6b. Collect human feedback (orchestrator, summary only):**332333```bash334gh pr view <PR> --repo lfortran/lfortran --json reviewDecision,mergeable,reviews,comments \335 --jq '{reviewDecision, mergeable, reviews: [.reviews[] | {author: .author.login, state}], comments: (.comments | length)}'336gh api repos/lfortran/lfortran/pulls/<PR>/comments --jq 'length'337```338339Treat the comment counts as new only if they changed since the last round.340The fix subagent reads the actual comment text.341342**6c. Decide.** The PR is **clean** when all of these hold for the current343head SHA:344345- every CI check passed, or each failing check was shown by a subagent to346 also fail on `main` (it is pre-existing, so report it but do not fix it347 here);348- the latest fresh review has **no blocker and no rework** findings;349- no human review comment or requested change is unaddressed;350- `mergeable` is not `CONFLICTING`.351352If clean and the PR does not have the label yet, add it:353`gh pr edit <PR> --repo lfortran/lfortran --add-label Tests::Run-Exhaustive`.354Wait until now because the exhaustive suite is expensive, and while the label355is present it reruns on every push (`.github/workflows/Exhaustive-Checks-CI.yml`356triggers on `labeled` and `synchronize`). If `gh` lacks permission to add357labels, tell the user and ask them to add it. Record the label in `state.md`,358then start the next round with only the CI watch; the head SHA is unchanged,359so the review stands, and this round does not count toward the cap.360361The PR is **done** when it is clean, the label is present, and the362`Exhaustive checks` workflow ran on the current head SHA (not `skipped`) with363every job passed or shown to also fail on `main`. Check with364`gh pr checks <PR> --repo lfortran/lfortran --json workflow,name,bucket`.365If done, go to Phase 6. Exhaustive failures go to the fix subagent like any366other CI failure.367368**6d. Otherwise spawn a fresh fix subagent** with the list of what is369outstanding: failing check names, the path `review_<k>.md`, and which human370comments are new. It should:371372- For CI failures: read the logs373 (`gh run view <run-id> --repo lfortran/lfortran --log-failed`, saved to a374 file), reproduce locally where possible, and fix the root cause. If a375 failure also happens on `main` or is plainly infrastructure flakiness, do376 not fix it in this PR. Re-run it once with `gh run rerun <run-id> --failed`377 and report it; a pre-existing LFortran bug goes on its Unrelated bugs list.378- For each review **blocker** and **rework** finding: first confirm the379 finding is real by reproducing it. Then fix it, or record in380 `round_<k>.md` exactly why it is not valid. Leave **follow-up** items381 unfixed; list them for the final report.382- For human review comments: address each one in code, or draft a reply in383 `round_<k>.md`. Do not post replies automatically; the user decides.384- For merge conflicts: `git merge <upstream-remote>/main`, resolve, rebuild,385 and retest. Never rebase or force-push.386- Rebuild, rerun the MRE, the new integration test, and the affected suites387 (the full integration and reference suites whenever compiler source388 changed). Update `pr_body.md` and the PR description389 (`gh pr edit <PR> --body-file ...`) if scope or rationale changed.390- Commit focused follow-up commits and push them to the fork remote (a normal391 push).392393Report: what was fixed, what was rejected and why, the new head SHA, and test394results. Then start round `k+1`.395396If the same finding or CI failure survives two fix rounds, or the round cap is397reached, stop the loop and report to the user with the outstanding items.398Do not keep iterating blindly.399400### Phase 6: Finish4014021. Mark the PR ready: `gh pr ready <PR> --repo lfortran/lfortran`.4032. Leave the branch checked out and do not delete the scratch reproducers.404 The user may want them.4053. Print the final report:406407```408PR ready for review: <URL>409410Issue: #<N> — <title> (original reproducer now passes)411Branch: <fork-remote>/<branch> head <sha>412Bugs fixed (<count> MRE iterations, one commit each):413 1. <one line> — integration_tests/<test>.f90 (fails before, passes after)414 2. ...415416CI: green (pre-existing failures on main: <none | names>)417Exhaustive CI: green (pre-existing failures on main: <none | names>)418Review: <rounds> round(s); blockers/rework fixed: <n>; rejected with reason: <n>419Follow-up issues filed: <#M, #M (duplicate of existing), ... or none>420Other follow-ups (not bugs, not filed): <list or none>421Human comments needing your reply: <list or none>422```423424## Tips425426- **Context discipline is the point.** If you catch yourself reading a diff427 or a log, hand that job to a subagent instead.428- **Resume:** if the session is interrupted, reread `state.md`, check429 `git log`, `gh pr view`, and the `.fix-issue/<id>/` artifacts, then continue430 from the first phase that is not finished.431- **Base freshness:** if `main` moved a lot during a long loop and CI failures432 look unrelated to the PR, have the fix subagent merge `upstream/main` before433 debugging.434- **Build errors in CI only:** other platforms (Windows/MSVC, WASM, other435 backends) often fail where macOS/Linux pass. The fix subagent should read436 the CI step's exact command and reproduce that backend locally where437 feasible (see the CI-parity notes in `AGENTS.md`).