githubnext / githubnext/autoloop
Duplicate programs created because auto-created program issue title gets double-prefixed with [Autoloop] and scheduler treats it as a separate program
- Vorherrschende Sprache
- Python
- Sterne
- 71
- Forks
- 6
- PR-Merge-Kennzahlen
- Keine gemergten PRs in 30 T.
Beschreibung
## Summary
The program-issue auto-creation from #38 has two latent bugs that combine to produce **duplicate programs** (and therefore duplicate branches and PRs) the moment a file-based program runs its first iteration:
1. **Double `[Autoloop]` prefix** on the auto-created program issue title. The safe-outputs `create-issue: title-prefix: "[Autoloop] "` auto-prepends the prefix, and the agent prompt also instructs the agent to use `[Autoloop: {program-name}]` — so the final title is `[Autoloop] [Autoloop: {program-name}]`.
2. **No dedupe between file-based and issue-based program discovery.** `slugify_issue_title` produces `autoloop-autoloop-{name}` for the double-prefixed title, which does not match the file-based program name `{name}`. On the next scheduler run, both get discovered as separate programs and both get scheduled.
Result: one file-based program ends up with its own branch/PR/state file, and *additionally* a shadow "autoloop-autoloop-{name}" program with its own branch/PR/state file. Work gets duplicated, the population in the state file splits, and maintainers see two draft PRs they can't reconcile.
## Evidence — how I can tell upstream has this bug
### Evidence for Bug 1 (double prefix)
In `workflows/autoloop.md`:
```yaml
safe-outputs:
create-issue:
title-prefix: "[Autoloop] "
...
```
(line ~54)
And later:
```markdown
### Auto-Creation for File-Based Programs
If `selected_issue` is `null` in `/tmp/gh-aw/autoloop.json`, the program is file-based **and** has no program issue yet. On the first run, create one with `create-issue`:
- **Title**: `[Autoloop: {program-name}]` (the `[Autoloop] ` prefix is added automatically by the safe-output `title-prefix`, so pass the title as `{program-name}`).
```
(line ~530)
The parenthetical advises the agent to pass "the title as `{program-name}`" — i.e. a bare name like `my-program`. But the bold line right before says "Title: `[Autoloop: {program-name}]`" — i.e. the brackets+prefix form. Agents in practice follow the bold line and supply `[Autoloop: my-program]` as the title; the safe-output then prepends `[Autoloop] ` → `[Autoloop] [Autoloop: my-program]`.
### Evidence for Bug 2 (no dedupe)
`workflows/scripts/autoloop_scheduler.py::slugify_issue_title`:
```python
def slugify_issue_title(title, number=None):
"""Slugify a GitHub issue title into a program name."""
slug = re.sub(r"[^a-z0-9]+", "-", (title or "").lower()).strip("-")
slug = re.sub(r"-+", "-", slug) # collapse consecutive hyphens
if not slug:
slug = "issue-{}".format(number) if number is not None else "issue"
return slug
```
Given `[Autoloop] [Autoloop: my-program]`, this produces `autoloop-autoloop-my-program`. That doesn't match the file-based name `my-program`, so the scheduler treats them as two programs.
There is no subsequent "match issue title to file-based program name" step that would collapse them.
## Fix
Three coordinated changes.
### Fix 1 — remove the double-prefix ambiguity in the agent prompt
Pick one:
**Option A (recommended) — remove the conflict in the prose:**
```diff
### Auto-Creation for File-Based Programs
If `selected_issue` is `null` in `/tmp/gh-aw/autoloop.json`, the program is file-based **and** has no program issue yet. On the first run, create one with `create-issue`:
-- **Title**: `[Autoloop: {program-name}]` (the `[Autoloop] ` prefix is added automatically by the safe-output `title-prefix`, so pass the title as `{program-name}`).
+- **Title**: supply `[Autoloop: {program-name}]` as the title. **Do not prepend `[Autoloop] `** — the `create-issue` safe-output adds that automatically. Final rendered title will be `[Autoloop] [Autoloop: {program-name}]`, which is intentional: the outer `[Autoloop] ` is the repo-wide filter prefix, and the inner `[Autoloop: {program-name}]` is the program identifier.
```
That makes the agent's correct behaviour unambiguous. But it also commits to the "double-prefix" rendered title being intentional — which makes Fix 2 mandatory rather than optional.
**Option B — drop the outer prefix for `create-issue` on program issues:**
Remove `title-prefix: "[Autoloop] "` from the `create-issue` safe-outputs config, and have the agent supply the full title (`[Autoloop: {program-name}]`) directly. Cleaner semantics, smaller rendered title, no double prefix. Downside: other agentic workflows may rely on the prefix convention for filtering across the whole repo.
Prefer A for minimal disruption.
### Fix 2 — extract the canonical name from issue titles before slugifying
Change `slugify_issue_title` (or the callers, which seems cleaner) to first check for the canonical `[Autoloop: {name}]` pattern and prefer `{name}` as the program slug. Fall back to the existing slugify for issues authored by humans with free-form titles.
```python
# workflows/scripts/autoloop_scheduler.py
ISSUE_TITLE_RE = re.compile(
r"^(?:\[Autoloop\]\s+)?\[Autoloop:\s+(?P[^\]]+)\]\s*$",
re.IGNORECASE,
)
def extract_program_name_from_issue_title(title: str) -> str | None:
"""Return the canonical program name if the title matches the auto-created
`[Autoloop] [Autoloop: ]` or `[Autoloop: ]` pattern. Otherwise
None — callers should fall back to `slugify_issue_title`."""
m = ISSUE_TITLE_RE.match((title or "").strip())
if m:
return m.group("name").strip()
return None
```
The regex:
- Optional outer `[Autoloop] ` prefix (from safe-outputs, if present).
- Required inner `[Autoloop: ]` that the agent supplies.
- Trailing whitespace tolerated.
- Case-insensitive so typos in issue edits don't break discovery.
### Fix 3 — dedupe file-based and issue-based program discovery
In `_fetch_issue_programs`, after computing the slug:
```python
# Pseudocode — adapt to the actual call site structure.
for issue in autoloop_program_issues:
canonical = extract_program_name_from_issue_title(issue["title"])
if canonical is not None:
slug = canonical
else:
slug = slugify_issue_title(issue["title"], issue["number"])
if slug in file_based_programs:
# This issue IS the program issue for the existing file-based program.
# Attach the issue number to that program; do not create a new one.
file_based_programs[slug].setdefault("program_issue", issue["number"])
continue
# True issue-based program — no file backing.
issue_programs[slug] = {
"issue_number": issue["number"],
"file": write_issue_body_to_temp(issue["body"], slug),
"title": issue["title"],
}
```
With this logic:
- A title `[Autoloop] [Autoloop: my-program]` → canonical name `my-program` → matches the file-based program → the issue's number gets attached to the file-based program's record (available as `program_issue` for the agent). No duplicate program.
- A title `My weekly plan` authored by a human with the `autoloop-program` label → canonical returns None → slugifies to `my-weekly-plan` → registered as a standalone issue-based program as today.
- A title `[Autoloop: my-program]` (Option B of Fix 1) → canonical returns `my-program` → same dedupe path. Works under either Fix 1 option.
### Cleanup for existing deployments
Maintainers who already have shadow programs (auto-created from previous runs) can:
1. Close the duplicated draft PR.
2. Delete the `autoloop/autoloop-` branch.
3. Delete the `autoloop-autoloop-.md` state file on `memory/autoloop`.
4. Rename the program issue from `[Autoloop] [Autoloop: ]` to `[Autoloop: ]` (single prefix).
Document this cleanup in the release notes for whatever version lands this fix.
## Acceptance
- A file-based program whose first run auto-creates a program issue ends up with **exactly one** open draft PR (on branch `autoloop/{name}`) and exactly one state file (`{name}.md`). No shadow `autoloop-{name}` or `autoloop-autoloop-{name}` anything.
- Issue-based programs authored by humans with arbitrary titles keep working under the slugify fallback. Tests cover both paths.
- After the fix, re-running discovery against an existing repo that has the old double-prefix title collapses the duplicated program by matching the canonical name; no further duplication.
## Related
- #38 — introduced the auto-created program issue that triggered this collision; this issue is a follow-up fix, not a regression of #38.
- #46 — versioning/release-notes: cleanup instructions for affected deployments should ship in the release notes of whichever version lands this fix.
Beitragsleitfaden
Für dieses Repository ist kein Beitragsleitfaden indexiert
Rechercherichtung
Beginne mit workflows/scripts/autoloop_scheduler.py, insbesondere mit slugify_issue_title und _fetch_issue_programs, und prüfe anschließend die Anweisungen zur automatischen Erstellung in workflows/autoloop.md. Füge Tests hinzu, die den Abgleich kanonischer Titel, die Fallback-Slugifizierung und die Deduplizierung von Dateien und Issues abdecken; die Arbeit ist abgeschlossen, wenn vorhandene Issues mit doppeltem Präfix keine Schattenprogramme mehr erstellen und die genannten Akzeptanzbedingungen für einen einzelnen Branch und eine einzelne Zustandsdatei erfüllt sind.
Vom Indexierungsmodell aus dem Issue-Text verfasst.
Bewertung
- Tech-Stack
- python
- Bereich
- tooling
- Issue-Typ
- Bug
- Schwierigkeit
- 4/5
- Geschätzter Aufwand
- 3-5 Tage
- Aktivitätsstatus
- Ruhig
- Klarheit
- Klar beschrieben
- Anfängerfreundlichkeit
- 58/100