You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Autoloop: duplicate PRs opening because program-issue title gets double-prefixed with [Autoloop] and scheduler treats file + issue as two programs #192
Both target the same file (src/core/series.ts), both run the same benchmark, both propose evolutions to Series.sortValues. The two populations have diverged and now each iteration burns twice the cost for one real program's worth of progress.
The program issue is #189, titled [Autoloop] [Autoloop: tsb-perf-evolve] — note the duplicated [Autoloop] prefix. That title is the thing that made this possible.
Root cause — two overlapping bugs
Bug A: [Autoloop] title-prefix is applied twice
Per #165's single-issue-per-program work, the agent creates a program issue titled [Autoloop: {program-name}] via the create-issue safe output. But .github/workflows/autoloop.md's safe-outputs config also sets:
Bug B: File-based and issue-based program discovery do not deduplicate
.github/workflows/scripts/autoloop_scheduler.py discovers programs from two sources:
File-based: directories under .autoloop/programs/<name>/. Program name = directory name.
Issue-based: GitHub issues with the autoloop-program label. Program name = slugified title.
When the auto-created program issue from Bug A is picked up on the next scheduler run, its title slugifies:
# from the current schedulerslug=re.sub(r'[^a-z0-9]+', '-', title.lower()).strip('-')
# "[Autoloop] [Autoloop: tsb-perf-evolve]" → "autoloop-autoloop-tsb-perf-evolve"
That slug doesn't match the file-based program name tsb-perf-evolve, so the scheduler treats them as two independent programs and schedules both. Each produces its own canonical branch, PR, state file.
Delete the branchautoloop/autoloop-autoloop-tsb-perf-evolve on the remote.
Delete the stranded state fileautoloop-autoloop-tsb-perf-evolve.md on the memory/autoloop branch.
Rename issue [Autoloop: tsb-perf-evolve] #189 from [Autoloop] [Autoloop: tsb-perf-evolve] to [Autoloop: tsb-perf-evolve] (strip the duplicated prefix). The safe-outputs title-prefix: "[Autoloop] " will not re-add it on rename — prefixes are a create-time concern.
Fix 1 — single source of truth for the [Autoloop] prefix
Pick one of these; do not do both:
Option A (preferred) — remove the duplicated prefix from the agent prompt. Let the safe-output do it. In .github/workflows/autoloop.md, change the instructions for creating a program issue from:
Title: [Autoloop: {program-name}]
to:
Title: [Autoloop: {program-name}] — do not prepend [Autoloop] , the create-issue safe output adds that automatically.
And audit the agent's prompt for any other place it constructs [Autoloop] ... titles explicitly. The title the agent supplies is just the content after the prefix.
Option B — remove title-prefix: "[Autoloop] " from the create-issue safe-outputs config. The agent supplies the full title, including any [Autoloop: ...] pattern. Downside: every other agentic workflow in the repo relies on the prefix convention for filtering; changing it repo-wide is a bigger surface area.
Option A is less disruptive.
Fix 2 — dedupe file-based and issue-based program discovery
.github/workflows/scripts/autoloop_scheduler.py currently emits both the file-based and the issue-based program as separate entries in /tmp/gh-aw/autoloop.json. Change the discovery logic so that:
When an issue with autoloop-program label has title matching ^(\[Autoloop\]\s+)?\[Autoloop:\s+(?P<name>[^\]]+)\]\s*$, extract <name>.
If a file-based program with that exact name exists, merge: the issue is that program's program issue (store its number in selected_issue or a new program_issue field), not a separate program.
Only create a new issue-based program when the title's extracted name does not match any file-based name.
Sketch:
ISSUE_TITLE_RE=re.compile(
r'^(?:\[Autoloop\]\s+)?\[Autoloop:\s+(?P<name>[^\]]+)\]\s*$',
re.IGNORECASE
)
defextract_program_name_from_issue_title(title: str) ->str|None:
m=ISSUE_TITLE_RE.match(title.strip())
ifm:
returnm.group("name").strip()
returnNone# During discovery:forissueinautoloop_program_issues:
name=extract_program_name_from_issue_title(issue["title"])
ifnameisNone:
# Title doesn't match the canonical pattern — fall back to slugification.# These are user-authored issue-based programs from before this fix.name=slugify(issue["title"])
ifnameinfile_based_programs:
# This issue IS the program issue for an existing file-based program.# Attach the issue number to that program; do not create a new program.file_based_programs[name]["program_issue"] =issue["number"]
else:
# True issue-based program (no file backing). Register normally.issue_based_programs[name] =issue
The existing slugify path stays as the fallback for issues authored by humans with arbitrary titles — we just prefer the canonical extract when the title matches the [Autoloop: …] pattern.
Fix 3 — defensive slug normalisation
Even after Fix 1 is live, old issues in the wild still have [Autoloop] [Autoloop: …] titles. Strip known prefixes before slugifying so the scheduler is robust:
defslugify(title: str) ->str:
s=title.strip()
# Strip a leading "[Autoloop]" marker (with optional whitespace) — the# safe-outputs prefix convention. Repeat until absent so doubly-prefixed# titles collapse cleanly.prefix=re.compile(r'^\[Autoloop\]\s*', re.IGNORECASE)
whileprefix.match(s):
s=prefix.sub('', s, count=1)
# Also strip a leading "[Autoloop: name]" pattern when present, so we# slugify just the name portion.m=re.match(r'^\[Autoloop:\s+([^\]]+)\]\s*', s, re.IGNORECASE)
ifm:
s=m.group(1)
returnre.sub(r'[^a-z0-9]+', '-', s.lower()).strip('-')
This makes the scheduler self-healing against prefix mistakes in issue titles — whether introduced by safe-outputs, by a human, or by a future agent that follows old prompting.
The scheduler's next run emits exactly one program entry for tsb-perf-evolve with program_issue: 189 attached. No autoloop-autoloop-tsb-perf-evolve entry anywhere.
Creating a new file-based program end-to-end (scaffold + let autoloop auto-create its program issue + wait two scheduler runs) produces exactly one program and exactly one open draft PR — never two.
Issue-based programs authored by humans (titles without the [Autoloop: ...] pattern) continue to work under the slugify fallback.
The autoloop.md prompt has several other places where [Autoloop] prefixes are assembled manually (PR titles, experiment log comments). Audit all of them while fixing Build tsb: pandas → TypeScript migration #1.
Symptom
Two concurrent PRs opened for the same program within 45 minutes:
autoloop/tsb-perf-evolve, state filetsb-perf-evolve.md.autoloop/autoloop-autoloop-tsb-perf-evolve, state fileautoloop-autoloop-tsb-perf-evolve.md.Both target the same file (
src/core/series.ts), both run the same benchmark, both propose evolutions toSeries.sortValues. The two populations have diverged and now each iteration burns twice the cost for one real program's worth of progress.The program issue is #189, titled
[Autoloop] [Autoloop: tsb-perf-evolve]— note the duplicated[Autoloop]prefix. That title is the thing that made this possible.Root cause — two overlapping bugs
Bug A:
[Autoloop]title-prefix is applied twicePer #165's single-issue-per-program work, the agent creates a program issue titled
[Autoloop: {program-name}]via thecreate-issuesafe output. But.github/workflows/autoloop.md's safe-outputs config also sets:The safe-output machinery auto-prepends that prefix. Final title:
Evidence: issue #189 has exactly that title.
Bug B: File-based and issue-based program discovery do not deduplicate
.github/workflows/scripts/autoloop_scheduler.pydiscovers programs from two sources:.autoloop/programs/<name>/. Program name = directory name.autoloop-programlabel. Program name = slugified title.When the auto-created program issue from Bug A is picked up on the next scheduler run, its title slugifies:
That slug doesn't match the file-based program name
tsb-perf-evolve, so the scheduler treats them as two independent programs and schedules both. Each produces its own canonical branch, PR, state file.Result:
tsb-perf-evolveautoloop/tsb-perf-evolvetsb-perf-evolve.mdautoloop-autoloop-tsb-perf-evolveautoloop/autoloop-autoloop-tsb-perf-evolveautoloop-autoloop-tsb-perf-evolve.mdThis will recur for every new file-based program the moment it auto-creates its program issue. It's not a one-off.
Near-term cleanup
Before landing any fix, undo the split so tsb-perf-evolve has one home:
autoloop/autoloop-autoloop-tsb-perf-evolveon the remote.autoloop-autoloop-tsb-perf-evolve.mdon thememory/autoloopbranch.[Autoloop] [Autoloop: tsb-perf-evolve]to[Autoloop: tsb-perf-evolve](strip the duplicated prefix). The safe-outputstitle-prefix: "[Autoloop] "will not re-add it on rename — prefixes are a create-time concern.tsb-perf-evolve(match-on-name, see fix [Autoloop] [Autoloop: build-tsb-pandas-typescript-migration] #2 below). Do not proceed until the next run schedules exactly one program.Root-cause fixes
Fix 1 — single source of truth for the
[Autoloop]prefixPick one of these; do not do both:
Option A (preferred) — remove the duplicated prefix from the agent prompt. Let the safe-output do it. In
.github/workflows/autoloop.md, change the instructions for creating a program issue from:to:
And audit the agent's prompt for any other place it constructs
[Autoloop] ...titles explicitly. The title the agent supplies is just the content after the prefix.Option B — remove
title-prefix: "[Autoloop] "from thecreate-issuesafe-outputs config. The agent supplies the full title, including any[Autoloop: ...]pattern. Downside: every other agentic workflow in the repo relies on the prefix convention for filtering; changing it repo-wide is a bigger surface area.Option A is less disruptive.
Fix 2 — dedupe file-based and issue-based program discovery
.github/workflows/scripts/autoloop_scheduler.pycurrently emits both the file-based and the issue-based program as separate entries in/tmp/gh-aw/autoloop.json. Change the discovery logic so that:autoloop-programlabel has title matching^(\[Autoloop\]\s+)?\[Autoloop:\s+(?P<name>[^\]]+)\]\s*$, extract<name>.selected_issueor a newprogram_issuefield), not a separate program.Sketch:
The existing
slugifypath stays as the fallback for issues authored by humans with arbitrary titles — we just prefer the canonical extract when the title matches the[Autoloop: …]pattern.Fix 3 — defensive slug normalisation
Even after Fix 1 is live, old issues in the wild still have
[Autoloop] [Autoloop: …]titles. Strip known prefixes before slugifying so the scheduler is robust:This makes the scheduler self-healing against prefix mistakes in issue titles — whether introduced by safe-outputs, by a human, or by a future agent that follows old prompting.
Acceptance
[Autoloop: tsb-perf-evolve]; no duplicate prefix.tsb-perf-evolvewithprogram_issue: 189attached. Noautoloop-autoloop-tsb-perf-evolveentry anywhere.[Autoloop: ...]pattern) continue to work under the slugify fallback.Related
[Autoloop]prefixes are assembled manually (PR titles, experiment log comments). Audit all of them while fixing Build tsb: pandas → TypeScript migration #1.