From f18b42077ee5436f73c78c6b4420873ab5a71944 Mon Sep 17 00:00:00 2001 From: mrjf Date: Thu, 19 Mar 2026 07:59:48 -0700 Subject: [PATCH 1/2] Autoloop bootstrap: use draft PR instead of direct push Stop committing template files directly to the default branch during bootstrap. Instead, leave them unstaged so the agent creates a draft PR, giving maintainers a chance to review before merge. Co-Authored-By: Claude Opus 4.6 (1M context) --- workflows/autoloop.md | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/workflows/autoloop.md b/workflows/autoloop.md index e94e687..01cb773 100644 --- a/workflows/autoloop.md +++ b/workflows/autoloop.md @@ -118,11 +118,8 @@ steps: ]) with open(template_file, "w") as f: f.write(template) - # Commit the template so the user can see and edit it - os.system(f'git add "{template_file}"') - os.system('git commit -m "[Autoloop] Bootstrap: add program template for configuration"') - os.system('git push') - print(f"BOOTSTRAPPED: created {template_file} and pushed to repo") + # Leave the template unstaged — the agent will create a draft PR with it + print(f"BOOTSTRAPPED: created {template_file} locally (agent will create a draft PR)") # Find all program files program_files = sorted(glob.glob(os.path.join(programs_dir, "*.md"))) @@ -326,14 +323,19 @@ At the start of every run, check each program file for this sentinel. For any pr If **all** programs are unconfigured, exit after creating the setup issues. Otherwise, proceed with the configured programs. +**Important**: When creating or modifying template/program files during setup, always do so via a draft PR — never commit directly to the default branch. Only iteration state files (`state.json`) should be committed directly. + ### Reading Programs The pre-step has already determined which programs are due, unconfigured, or skipped. Read `/tmp/gh-aw/autoloop.json` at the start of your run to get: - **`due`**: List of program names to run iterations for this run. -- **`unconfigured`**: Programs that still have the sentinel or placeholder content — run the **Setup Guard** for each of these (create setup issues). +- **`unconfigured`**: Programs that still have the sentinel or placeholder content. For each unconfigured program: + 1. Check whether the program file actually exists on the default branch (use `git show HEAD:.github/autoloop/programs/{name}.md`). If it does NOT exist on the default branch, **you must create a draft PR** (branch: `autoloop/setup-template`) that adds the template file. The pre-step may have created the file locally in the working directory, so it will be available to commit — just create a branch, commit it, and open the PR. + 2. If no setup issue exists for this program, create one (see Setup Guard above). + 3. If the file already exists on the default branch and a setup issue already exists, then no action is needed for this program. - **`skipped`**: Programs not due yet based on their per-program schedule — ignore these entirely. -- **`no_programs`**: If `true`, no program files exist at all — create a single issue explaining how to add a program. +- **`no_programs`**: If `true`, no program files exist at all. The pre-step should have bootstrapped a template locally. Follow the same steps as `unconfigured` above — create a draft PR with the template and a setup issue. For each program in `due`: 1. Read the program file from `.github/autoloop/programs/{name}.md`. From 04084443d0107df1b64243e0fb76a1fffceb1973 Mon Sep 17 00:00:00 2001 From: mrjf Date: Thu, 19 Mar 2026 08:19:00 -0700 Subject: [PATCH 2/2] Move autoloop config directory from .github/autoloop/ to .autoloop/ MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Aligns with the w3k deployment convention — keeps autoloop config at the repo root rather than nested under .github/. Co-Authored-By: Claude Opus 4.6 (1M context) --- workflows/autoloop.md | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/workflows/autoloop.md b/workflows/autoloop.md index 01cb773..785257e 100644 --- a/workflows/autoloop.md +++ b/workflows/autoloop.md @@ -70,8 +70,8 @@ steps: import os, json, re, glob, sys from datetime import datetime, timezone, timedelta - programs_dir = ".github/autoloop/programs" - state_file = ".github/autoloop/state.json" + programs_dir = ".autoloop/programs" + state_file = ".autoloop/state.json" template_file = os.path.join(programs_dir, "example.md") # Bootstrap: create programs directory and template if missing @@ -125,7 +125,7 @@ steps: program_files = sorted(glob.glob(os.path.join(programs_dir, "*.md"))) if not program_files: # Fallback to single-file locations - for path in [".github/autoloop/program.md", "program.md"]: + for path in [".autoloop/program.md", "program.md"]: if os.path.isfile(path): program_files = [path] break @@ -248,7 +248,7 @@ An iterative optimization agent that proposes changes, evaluates them against a Take heed of **instructions**: "${{ steps.sanitized.outputs.text }}" If these are non-empty (not ""), then you have been triggered via `/autoloop `. The instructions may be: -- **A one-off directive targeting a specific program**: e.g., `/autoloop training: try a different approach to the loss function`. The text before the colon is the program name (matching a file in `.github/autoloop/programs/`). Execute it as a single iteration for that program, then report results. +- **A one-off directive targeting a specific program**: e.g., `/autoloop training: try a different approach to the loss function`. The text before the colon is the program name (matching a file in `.autoloop/programs/`). Execute it as a single iteration for that program, then report results. - **A general directive**: e.g., `/autoloop try cosine annealing`. If no program name prefix is given and only one program exists, use that one. If multiple exist, ask which program to target. - **A configuration change**: e.g., `/autoloop training: set metric to accuracy instead of loss`. Update the relevant program file and confirm. @@ -256,10 +256,10 @@ Then exit — do not run the normal loop after completing the instructions. ## Multiple Programs -Autoloop supports **multiple independent optimization loops** in the same repository. Each loop is defined by a separate markdown file in `.github/autoloop/programs/`. For example: +Autoloop supports **multiple independent optimization loops** in the same repository. Each loop is defined by a separate markdown file in `.autoloop/programs/`. For example: ``` -.github/autoloop/programs/ +.autoloop/programs/ ├── training.md ← optimize model training ├── coverage.md ← maximize test coverage └── build-perf.md ← minimize build time @@ -296,7 +296,7 @@ This lets you run a fast coverage check every hour while running a slow training ## Program Definition -Each program file in `.github/autoloop/programs/` defines three things: +Each program file in `.autoloop/programs/` defines three things: 1. **Goal**: What the agent is trying to optimize (natural language description) 2. **Target**: Which files the agent is allowed to modify @@ -306,7 +306,7 @@ The **program name** is the filename without the `.md` extension (e.g., `trainin ### Setup Guard -A template program file is installed at `.github/autoloop/programs/example.md`. **Programs will not run until the user has edited them.** Each template contains a sentinel line: +A template program file is installed at `.autoloop/programs/example.md`. **Programs will not run until the user has edited them.** Each template contains a sentinel line: ``` @@ -331,14 +331,14 @@ The pre-step has already determined which programs are due, unconfigured, or ski - **`due`**: List of program names to run iterations for this run. - **`unconfigured`**: Programs that still have the sentinel or placeholder content. For each unconfigured program: - 1. Check whether the program file actually exists on the default branch (use `git show HEAD:.github/autoloop/programs/{name}.md`). If it does NOT exist on the default branch, **you must create a draft PR** (branch: `autoloop/setup-template`) that adds the template file. The pre-step may have created the file locally in the working directory, so it will be available to commit — just create a branch, commit it, and open the PR. + 1. Check whether the program file actually exists on the default branch (use `git show HEAD:.autoloop/programs/{name}.md`). If it does NOT exist on the default branch, **you must create a draft PR** (branch: `autoloop/setup-template`) that adds the template file. The pre-step may have created the file locally in the working directory, so it will be available to commit — just create a branch, commit it, and open the PR. 2. If no setup issue exists for this program, create one (see Setup Guard above). 3. If the file already exists on the default branch and a setup issue already exists, then no action is needed for this program. - **`skipped`**: Programs not due yet based on their per-program schedule — ignore these entirely. - **`no_programs`**: If `true`, no program files exist at all. The pre-step should have bootstrapped a template locally. Follow the same steps as `unconfigured` above — create a draft PR with the template and a setup issue. For each program in `due`: -1. Read the program file from `.github/autoloop/programs/{name}.md`. +1. Read the program file from `.autoloop/programs/{name}.md`. 2. Parse the three sections: Goal, Target, Evaluation. 3. Read the current state of all target files. 4. Read repo memory for that program's metric history (keyed by program name). @@ -350,7 +350,7 @@ Each run executes **one iteration per configured program**. For each program: ### Step 1: Read State 1. Read the program file to understand the goal, targets, and evaluation method. -2. Read `.github/autoloop/state.json` for this program's `best_metric` and `iteration_count`. +2. Read `.autoloop/state.json` for this program's `best_metric` and `iteration_count`. 3. Read repo memory (keyed by program name) for detailed history: - `history`: Summary of recent iterations (last 20). - `rejected_approaches`: Approaches that were tried and failed (to avoid repeating). @@ -446,7 +446,7 @@ Maintain a single open issue **per program** titled `[Autoloop: {program-name}] Autoloop uses **two persistence layers**: -### 1. State file (`.github/autoloop/state.json`) — lightweight, committed to repo +### 1. State file (`.autoloop/state.json`) — lightweight, committed to repo This file is read by the **pre-step** (before the agent starts) to decide which programs are due. The agent **must update this file and commit it** at the end of every iteration. This is the only way the pre-step can check schedules, plateaus, and pause flags on future runs.