diff --git a/.github/workflows/autoloop.lock.yml b/.github/workflows/autoloop.lock.yml index c575851..f9dd301 100644 --- a/.github/workflows/autoloop.lock.yml +++ b/.github/workflows/autoloop.lock.yml @@ -29,7 +29,6 @@ # - Persists all state via repo-memory (human-readable, human-editable) # - Commits accepted improvements to a long-running branch per program # - Maintains a single draft PR per program that accumulates all accepted iterations -# - Maintains a living experiment log as a GitHub issue # # Source: githubnext/autoloop # @@ -238,7 +237,7 @@ jobs: cat "${RUNNER_TEMP}/gh-aw/prompts/safe_outputs_prompt.md" cat << 'GH_AW_PROMPT_25eda8a50024125e_EOF' - Tools: add_comment(max:7), create_issue(max:2), update_issue(max:3), create_pull_request(max:2), add_labels(max:2), remove_labels(max:2), push_to_pull_request_branch(max:2), missing_tool, missing_data, noop + Tools: add_comment(max:7), create_issue(max:1), update_issue(max:3), create_pull_request(max:2), add_labels(max:2), remove_labels(max:2), push_to_pull_request_branch(max:2), missing_tool, missing_data, noop GH_AW_PROMPT_25eda8a50024125e_EOF cat "${RUNNER_TEMP}/gh-aw/prompts/safe_outputs_create_pull_request.md" cat "${RUNNER_TEMP}/gh-aw/prompts/safe_outputs_push_to_pr_branch.md" @@ -490,7 +489,7 @@ jobs: mkdir -p /tmp/gh-aw/safeoutputs mkdir -p /tmp/gh-aw/mcp-logs/safeoutputs cat > ${RUNNER_TEMP}/gh-aw/safeoutputs/config.json << 'GH_AW_SAFE_OUTPUTS_CONFIG_4cb88c61a21f151b_EOF' - {"add_comment":{"hide_older_comments":false,"max":7,"target":"*"},"add_labels":{"max":2,"target":"*"},"create_issue":{"labels":["automation","autoloop"],"max":2,"title_prefix":"[Autoloop] "},"create_pull_request":{"draft":true,"labels":["automation","autoloop"],"max":2,"max_patch_size":1024,"protected_files":["package.json","bun.lockb","bunfig.toml","deno.json","deno.jsonc","deno.lock","global.json","NuGet.Config","Directory.Packages.props","mix.exs","mix.lock","go.mod","go.sum","stack.yaml","stack.yaml.lock","pom.xml","build.gradle","build.gradle.kts","settings.gradle","settings.gradle.kts","gradle.properties","package-lock.json","yarn.lock","pnpm-lock.yaml","npm-shrinkwrap.json","requirements.txt","Pipfile","Pipfile.lock","pyproject.toml","setup.py","setup.cfg","Gemfile","Gemfile.lock","uv.lock","CODEOWNERS"],"protected_files_policy":"fallback-to-issue","protected_path_prefixes":[".github/",".agents/"],"title_prefix":"[Autoloop] "},"missing_data":{},"missing_tool":{},"noop":{"max":1,"report-as-issue":"true"},"push_repo_memory":{"memories":[{"dir":"/tmp/gh-aw/repo-memory/default","id":"default","max_file_count":100,"max_file_size":10240,"max_patch_size":10240}]},"push_to_pull_request_branch":{"if_no_changes":"warn","max":2,"max_patch_size":1024,"protected_files":["package.json","bun.lockb","bunfig.toml","deno.json","deno.jsonc","deno.lock","global.json","NuGet.Config","Directory.Packages.props","mix.exs","mix.lock","go.mod","go.sum","stack.yaml","stack.yaml.lock","pom.xml","build.gradle","build.gradle.kts","settings.gradle","settings.gradle.kts","gradle.properties","package-lock.json","yarn.lock","pnpm-lock.yaml","npm-shrinkwrap.json","requirements.txt","Pipfile","Pipfile.lock","pyproject.toml","setup.py","setup.cfg","Gemfile","Gemfile.lock","uv.lock","CODEOWNERS"],"protected_path_prefixes":[".github/",".agents/"],"target":"*","title_prefix":"[Autoloop] "},"remove_labels":{"max":2,"target":"*"},"update_issue":{"allow_body":true,"max":3,"target":"*","title_prefix":"[Autoloop] "}} + {"add_comment":{"hide_older_comments":false,"max":7,"target":"*"},"add_labels":{"max":2,"target":"*"},"create_issue":{"labels":["automation","autoloop"],"max":1,"title_prefix":"[Autoloop] "},"create_pull_request":{"draft":true,"labels":["automation","autoloop"],"max":2,"max_patch_size":1024,"protected_files":["package.json","bun.lockb","bunfig.toml","deno.json","deno.jsonc","deno.lock","global.json","NuGet.Config","Directory.Packages.props","mix.exs","mix.lock","go.mod","go.sum","stack.yaml","stack.yaml.lock","pom.xml","build.gradle","build.gradle.kts","settings.gradle","settings.gradle.kts","gradle.properties","package-lock.json","yarn.lock","pnpm-lock.yaml","npm-shrinkwrap.json","requirements.txt","Pipfile","Pipfile.lock","pyproject.toml","setup.py","setup.cfg","Gemfile","Gemfile.lock","uv.lock","CODEOWNERS"],"protected_files_policy":"fallback-to-issue","protected_path_prefixes":[".github/",".agents/"],"title_prefix":"[Autoloop] "},"missing_data":{},"missing_tool":{},"noop":{"max":1,"report-as-issue":"true"},"push_repo_memory":{"memories":[{"dir":"/tmp/gh-aw/repo-memory/default","id":"default","max_file_count":100,"max_file_size":10240,"max_patch_size":10240}]},"push_to_pull_request_branch":{"if_no_changes":"warn","max":2,"max_patch_size":1024,"protected_files":["package.json","bun.lockb","bunfig.toml","deno.json","deno.jsonc","deno.lock","global.json","NuGet.Config","Directory.Packages.props","mix.exs","mix.lock","go.mod","go.sum","stack.yaml","stack.yaml.lock","pom.xml","build.gradle","build.gradle.kts","settings.gradle","settings.gradle.kts","gradle.properties","package-lock.json","yarn.lock","pnpm-lock.yaml","npm-shrinkwrap.json","requirements.txt","Pipfile","Pipfile.lock","pyproject.toml","setup.py","setup.cfg","Gemfile","Gemfile.lock","uv.lock","CODEOWNERS"],"protected_path_prefixes":[".github/",".agents/"],"target":"*","title_prefix":"[Autoloop] "},"remove_labels":{"max":2,"target":"*"},"update_issue":{"allow_body":true,"max":3,"target":"*","title_prefix":"[Autoloop] "}} GH_AW_SAFE_OUTPUTS_CONFIG_4cb88c61a21f151b_EOF - name: Write Safe Outputs Tools run: | @@ -499,7 +498,7 @@ jobs: "description_suffixes": { "add_comment": " CONSTRAINTS: Maximum 7 comment(s) can be added. Target: *.", "add_labels": " CONSTRAINTS: Maximum 2 label(s) can be added. Target: *.", - "create_issue": " CONSTRAINTS: Maximum 2 issue(s) can be created. Title will be prefixed with \"[Autoloop] \". Labels [\"automation\" \"autoloop\"] will be automatically added.", + "create_issue": " CONSTRAINTS: Maximum 1 issue(s) can be created. Title will be prefixed with \"[Autoloop] \". Labels [\"automation\" \"autoloop\"] will be automatically added.", "create_pull_request": " CONSTRAINTS: Maximum 2 pull request(s) can be created. Title will be prefixed with \"[Autoloop] \". Labels [\"automation\" \"autoloop\"] will be automatically added. PRs will be created as drafts.", "push_to_pull_request_branch": " CONSTRAINTS: Maximum 2 push(es) can be made. The target pull request title must start with \"[Autoloop] \".", "remove_labels": " CONSTRAINTS: Maximum 2 label(s) can be removed. Target: *.", @@ -1275,7 +1274,7 @@ jobs: uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8 env: WORKFLOW_NAME: "Autoloop" - WORKFLOW_DESCRIPTION: "An iterative optimization loop inspired by Karpathy's Autoresearch and Claude Code's /loop.\nRuns on a configurable schedule to autonomously improve a target artifact toward a measurable goal.\nEach iteration: reads the program definition, proposes a change, evaluates against a metric,\nand accepts or rejects the change. Tracks all iterations in a rolling GitHub issue.\n- User defines the optimization goal and evaluation criteria in a program.md file\n- Accepts changes only when they improve the metric (ratchet pattern)\n- Persists all state via repo-memory (human-readable, human-editable)\n- Commits accepted improvements to a long-running branch per program\n- Maintains a single draft PR per program that accumulates all accepted iterations\n- Maintains a living experiment log as a GitHub issue" + WORKFLOW_DESCRIPTION: "An iterative optimization loop inspired by Karpathy's Autoresearch and Claude Code's /loop.\nRuns on a configurable schedule to autonomously improve a target artifact toward a measurable goal.\nEach iteration: reads the program definition, proposes a change, evaluates against a metric,\nand accepts or rejects the change.\n- User defines the optimization goal and evaluation criteria in a program.md file\n- Accepts changes only when they improve the metric (ratchet pattern)\n- Persists all state via repo-memory (human-readable, human-editable)\n- Commits accepted improvements to a long-running branch per program\n- Maintains a single draft PR per program that accumulates all accepted iterations" HAS_PATCH: ${{ needs.agent.outputs.has_patch }} with: script: | diff --git a/.github/workflows/autoloop.md b/.github/workflows/autoloop.md index 1290679..b467625 100644 --- a/.github/workflows/autoloop.md +++ b/.github/workflows/autoloop.md @@ -3,13 +3,12 @@ description: | An iterative optimization loop inspired by Karpathy's Autoresearch and Claude Code's /loop. Runs on a configurable schedule to autonomously improve a target artifact toward a measurable goal. Each iteration: reads the program definition, proposes a change, evaluates against a metric, - and accepts or rejects the change. Tracks all iterations in a rolling GitHub issue. + and accepts or rejects the change. - User defines the optimization goal and evaluation criteria in a program.md file - Accepts changes only when they improve the metric (ratchet pattern) - Persists all state via repo-memory (human-readable, human-editable) - Commits accepted improvements to a long-running branch per program - Maintains a single draft PR per program that accumulates all accepted iterations - - Maintains a living experiment log as a GitHub issue on: schedule: every 6h @@ -53,7 +52,7 @@ safe-outputs: create-issue: title-prefix: "[Autoloop] " labels: [automation, autoloop] - max: 2 + max: 1 update-issue: target: "*" title-prefix: "[Autoloop] " @@ -570,7 +569,6 @@ GitHub Issues (labeled 'autoloop-program'): Each program runs independently with its own: - Goal, target files, and evaluation command - Metric tracking and best-metric history -- Experiment log issue: `[Autoloop: {program-name}] Experiment Log {YYYY-MM}` - Steering issue: `[Autoloop: {program-name}] Steering` (persistent, links branch/PR/state) - Long-running branch: `autoloop/{program-name}` (persists across iterations) - Single draft PR per program: `[Autoloop: {program-name}]` (accumulates all accepted iterations) @@ -715,81 +713,38 @@ Each run executes **one iteration for the single selected program**: - Body includes: a summary of the program goal, link to the steering issue, the current best metric, and AI disclosure: `🤖 *This PR is maintained by Autoloop. Each accepted iteration adds a commit to this branch.*` If a draft PR already exists, update the PR body with the latest metric and a summary of the most recent accepted iteration. Add a comment to the PR summarizing the iteration: what changed, old metric, new metric, improvement delta, and a link to the actions run. 4. Ensure the steering issue exists (see [Steering Issue](#steering-issue) below). Add a comment to the steering issue linking to the commit and actions run. -5. Add an entry to the experiment log issue. -6. Update the state file `{program-name}.md` in the repo-memory folder: +5. Update the state file `{program-name}.md` in the repo-memory folder: - Update the **⚙️ Machine State** table: reset `consecutive_errors` to 0, set `best_metric`, increment `iteration_count`, set `last_run` to current UTC timestamp, append `"accepted"` to `recent_statuses` (keep last 10), set `paused` to false. - Prepend an entry to **📊 Iteration History** (newest first) with status ✅, metric, PR link, and a one-line summary of what changed and why it worked. - Update **📚 Lessons Learned** if this iteration revealed something new about the problem or what works. - Update **🔭 Future Directions** if this iteration opened new promising paths. -7. **If this is an issue-based program** (`selected_issue` is not null): update the status comment and post a per-run comment on the source issue (see [Issue-Based Program Updates](#issue-based-program-updates)). -8. **Check halting condition** (see [Halting Condition](#halting-condition)): If the program has a `target-metric` in its frontmatter and the new `best_metric` meets or surpasses the target, mark the program as completed. +6. **If this is an issue-based program** (`selected_issue` is not null): update the status comment and post a per-run comment on the source issue (see [Issue-Based Program Updates](#issue-based-program-updates)). +7. **Check halting condition** (see [Halting Condition](#halting-condition)): If the program has a `target-metric` in its frontmatter and the new `best_metric` meets or surpasses the target, mark the program as completed. **If the metric did not improve**: 1. Discard the code changes (do not commit them to the long-running branch). -2. Add a "rejected" entry to the experiment log issue. -3. Update the state file `{program-name}.md` in the repo-memory folder: +2. Update the state file `{program-name}.md` in the repo-memory folder: - Update the **⚙️ Machine State** table: increment `iteration_count`, set `last_run`, append `"rejected"` to `recent_statuses` (keep last 10). - Prepend an entry to **📊 Iteration History** with status ❌, metric, and a one-line summary of what was tried. - If this approach is conclusively ruled out (e.g., tried multiple variations and all fail), add it to **🚧 Foreclosed Avenues** with a clear explanation. - Update **🔭 Future Directions** if this rejection clarified what to try next. -4. **If this is an issue-based program** (`selected_issue` is not null): update the status comment and post a per-run comment on the source issue (see [Issue-Based Program Updates](#issue-based-program-updates)). +3. **If this is an issue-based program** (`selected_issue` is not null): update the status comment and post a per-run comment on the source issue (see [Issue-Based Program Updates](#issue-based-program-updates)). **If evaluation could not run** (build failure, missing dependencies, etc.): 1. Discard the code changes (do not commit them to the long-running branch). -2. Add an "error" entry to the experiment log issue. -3. Update the state file `{program-name}.md` in the repo-memory folder: +2. Update the state file `{program-name}.md` in the repo-memory folder: - Update the **⚙️ Machine State** table: increment `consecutive_errors`, increment `iteration_count`, set `last_run`, append `"error"` to `recent_statuses` (keep last 10). - If `consecutive_errors` reaches 3+, set `paused` to `true` and set `pause_reason` in the Machine State table, and create an issue describing the problem. - Prepend an entry to **📊 Iteration History** with status ⚠️ and a brief error description. -4. **If this is an issue-based program** (`selected_issue` is not null): update the status comment and post a per-run comment on the source issue (see [Issue-Based Program Updates](#issue-based-program-updates)). - -## Experiment Log Issue - -Maintain a single open issue **per program** titled `[Autoloop: {program-name}] Experiment Log {YYYY}-{MM}` as a rolling record of that program's iterations. - -### Issue Body Format - -```markdown -🤖 *Autoloop — an iterative optimization agent for this repository.* - -## Program - -**Goal**: {one-line summary from program.md} -**Target files**: {list of target files} -**Metric**: {metric name} ({higher/lower} is better) -**Current best**: {best_metric} (established in iteration {N}) - -## Iteration History - -### Iteration {N} — {YYYY-MM-DD HH:MM UTC} — [Run]({run_url}) -- **Status**: ✅ Accepted / ❌ Rejected / ⚠️ Error -- **Change**: {one-line description} -- **Metric**: {value} (previous best: {previous_best}, delta: {delta}) -- **Commit**: {short_sha} (if accepted) - -### Iteration {N-1} — {YYYY-MM-DD HH:MM UTC} — [Run]({run_url}) -- **Status**: ❌ Rejected -- **Change**: {one-line description} -- **Metric**: {value} (previous best: {previous_best}, delta: {delta}) -- **Reason**: {why it was rejected} -``` - -### Format Rules - -- Iterations in **reverse chronological order** (newest first). -- Each iteration heading links to its GitHub Actions run. -- Use `${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}` for the current run URL. -- Close the previous month's issue and create a new one at month boundaries. -- Maximum 50 iterations per issue; create a continuation issue if exceeded. +3. **If this is an issue-based program** (`selected_issue` is not null): update the status comment and post a per-run comment on the source issue (see [Issue-Based Program Updates](#issue-based-program-updates)). ## Steering Issue -Maintain a single **persistent** open issue per program titled `[Autoloop: {program-name}] Steering`. Unlike experiment log issues (which rotate monthly), the steering issue lives for the entire lifetime of the program. +Maintain a single **persistent** open issue per program titled `[Autoloop: {program-name}] Steering`. The steering issue lives for the entire lifetime of the program. -The steering issue serves as the central coordination point linking together the program's three key resources: +The steering issue serves as the central coordination point linking together the program's key resources: - The **long-running branch** `autoloop/{program-name}` and its draft PR - The **state file** `{program-name}.md` in repo-memory (on the `memory/autoloop` branch) -- The **experiment log** issues ### Steering Issue Body Format @@ -801,7 +756,6 @@ The steering issue serves as the central coordination point linking together the - **Branch**: [`autoloop/{program-name}`](https://github.com/{owner}/{repo}/tree/autoloop/{program-name}) - **Pull Request**: #{pr_number} - **State File**: [`{program-name}.md`](https://github.com/{owner}/{repo}/blob/memory/autoloop/{program-name}.md) -- **Experiment Log**: #{experiment_log_issue_number} ## Program @@ -814,14 +768,14 @@ The steering issue serves as the central coordination point linking together the ### Steering Issue Rules - Create the steering issue on the **first accepted iteration** for the program if it does not already exist. -- **Update the issue body** whenever the best metric, PR number, or experiment log issue changes. +- **Update the issue body** whenever the best metric or PR number changes. - **Add a comment** on each accepted iteration with a link to the commit and actions run. - The steering issue is labeled `[automation, autoloop]`. - Do NOT close the steering issue when the PR is merged — the branch continues to accumulate future iterations. ## Issue-Based Program Updates -When a program is defined via a GitHub issue (i.e., `selected_issue` is not null in `/tmp/gh-aw/autoloop.json`), the source issue itself serves as the program definition **and** as the primary interface for steering and monitoring the program. In addition to the normal iteration workflow (state file, experiment log, steering issue, PR), you must also update the source issue. +When a program is defined via a GitHub issue (i.e., `selected_issue` is not null in `/tmp/gh-aw/autoloop.json`), the source issue itself serves as the program definition **and** as the primary interface for steering and monitoring the program. In addition to the normal iteration workflow (state file, steering issue, PR), you must also update the source issue. ### Status Comment @@ -845,7 +799,6 @@ Find the status comment by searching for a comment containing ``) is maintained on the source issue, and a per-run comment is posted after each iteration diff --git a/create-program.md b/create-program.md index 860251d..33aff3c 100644 --- a/create-program.md +++ b/create-program.md @@ -24,7 +24,7 @@ Autoloop is a GitHub Agentic Workflow that runs iterative optimization loops. Ea .autoloop/programs/.md ``` -A repository can have multiple programs running independently. Each gets its own schedule, metric tracking, experiment log issue, long-running branch (`autoloop/`), and draft PR. +A repository can have multiple programs running independently. Each gets its own schedule, metric tracking, long-running branch (`autoloop/`), and draft PR. ## Step 1: Understand the Repository diff --git a/workflows/autoloop.md b/workflows/autoloop.md index 1290679..b467625 100644 --- a/workflows/autoloop.md +++ b/workflows/autoloop.md @@ -3,13 +3,12 @@ description: | An iterative optimization loop inspired by Karpathy's Autoresearch and Claude Code's /loop. Runs on a configurable schedule to autonomously improve a target artifact toward a measurable goal. Each iteration: reads the program definition, proposes a change, evaluates against a metric, - and accepts or rejects the change. Tracks all iterations in a rolling GitHub issue. + and accepts or rejects the change. - User defines the optimization goal and evaluation criteria in a program.md file - Accepts changes only when they improve the metric (ratchet pattern) - Persists all state via repo-memory (human-readable, human-editable) - Commits accepted improvements to a long-running branch per program - Maintains a single draft PR per program that accumulates all accepted iterations - - Maintains a living experiment log as a GitHub issue on: schedule: every 6h @@ -53,7 +52,7 @@ safe-outputs: create-issue: title-prefix: "[Autoloop] " labels: [automation, autoloop] - max: 2 + max: 1 update-issue: target: "*" title-prefix: "[Autoloop] " @@ -570,7 +569,6 @@ GitHub Issues (labeled 'autoloop-program'): Each program runs independently with its own: - Goal, target files, and evaluation command - Metric tracking and best-metric history -- Experiment log issue: `[Autoloop: {program-name}] Experiment Log {YYYY-MM}` - Steering issue: `[Autoloop: {program-name}] Steering` (persistent, links branch/PR/state) - Long-running branch: `autoloop/{program-name}` (persists across iterations) - Single draft PR per program: `[Autoloop: {program-name}]` (accumulates all accepted iterations) @@ -715,81 +713,38 @@ Each run executes **one iteration for the single selected program**: - Body includes: a summary of the program goal, link to the steering issue, the current best metric, and AI disclosure: `🤖 *This PR is maintained by Autoloop. Each accepted iteration adds a commit to this branch.*` If a draft PR already exists, update the PR body with the latest metric and a summary of the most recent accepted iteration. Add a comment to the PR summarizing the iteration: what changed, old metric, new metric, improvement delta, and a link to the actions run. 4. Ensure the steering issue exists (see [Steering Issue](#steering-issue) below). Add a comment to the steering issue linking to the commit and actions run. -5. Add an entry to the experiment log issue. -6. Update the state file `{program-name}.md` in the repo-memory folder: +5. Update the state file `{program-name}.md` in the repo-memory folder: - Update the **⚙️ Machine State** table: reset `consecutive_errors` to 0, set `best_metric`, increment `iteration_count`, set `last_run` to current UTC timestamp, append `"accepted"` to `recent_statuses` (keep last 10), set `paused` to false. - Prepend an entry to **📊 Iteration History** (newest first) with status ✅, metric, PR link, and a one-line summary of what changed and why it worked. - Update **📚 Lessons Learned** if this iteration revealed something new about the problem or what works. - Update **🔭 Future Directions** if this iteration opened new promising paths. -7. **If this is an issue-based program** (`selected_issue` is not null): update the status comment and post a per-run comment on the source issue (see [Issue-Based Program Updates](#issue-based-program-updates)). -8. **Check halting condition** (see [Halting Condition](#halting-condition)): If the program has a `target-metric` in its frontmatter and the new `best_metric` meets or surpasses the target, mark the program as completed. +6. **If this is an issue-based program** (`selected_issue` is not null): update the status comment and post a per-run comment on the source issue (see [Issue-Based Program Updates](#issue-based-program-updates)). +7. **Check halting condition** (see [Halting Condition](#halting-condition)): If the program has a `target-metric` in its frontmatter and the new `best_metric` meets or surpasses the target, mark the program as completed. **If the metric did not improve**: 1. Discard the code changes (do not commit them to the long-running branch). -2. Add a "rejected" entry to the experiment log issue. -3. Update the state file `{program-name}.md` in the repo-memory folder: +2. Update the state file `{program-name}.md` in the repo-memory folder: - Update the **⚙️ Machine State** table: increment `iteration_count`, set `last_run`, append `"rejected"` to `recent_statuses` (keep last 10). - Prepend an entry to **📊 Iteration History** with status ❌, metric, and a one-line summary of what was tried. - If this approach is conclusively ruled out (e.g., tried multiple variations and all fail), add it to **🚧 Foreclosed Avenues** with a clear explanation. - Update **🔭 Future Directions** if this rejection clarified what to try next. -4. **If this is an issue-based program** (`selected_issue` is not null): update the status comment and post a per-run comment on the source issue (see [Issue-Based Program Updates](#issue-based-program-updates)). +3. **If this is an issue-based program** (`selected_issue` is not null): update the status comment and post a per-run comment on the source issue (see [Issue-Based Program Updates](#issue-based-program-updates)). **If evaluation could not run** (build failure, missing dependencies, etc.): 1. Discard the code changes (do not commit them to the long-running branch). -2. Add an "error" entry to the experiment log issue. -3. Update the state file `{program-name}.md` in the repo-memory folder: +2. Update the state file `{program-name}.md` in the repo-memory folder: - Update the **⚙️ Machine State** table: increment `consecutive_errors`, increment `iteration_count`, set `last_run`, append `"error"` to `recent_statuses` (keep last 10). - If `consecutive_errors` reaches 3+, set `paused` to `true` and set `pause_reason` in the Machine State table, and create an issue describing the problem. - Prepend an entry to **📊 Iteration History** with status ⚠️ and a brief error description. -4. **If this is an issue-based program** (`selected_issue` is not null): update the status comment and post a per-run comment on the source issue (see [Issue-Based Program Updates](#issue-based-program-updates)). - -## Experiment Log Issue - -Maintain a single open issue **per program** titled `[Autoloop: {program-name}] Experiment Log {YYYY}-{MM}` as a rolling record of that program's iterations. - -### Issue Body Format - -```markdown -🤖 *Autoloop — an iterative optimization agent for this repository.* - -## Program - -**Goal**: {one-line summary from program.md} -**Target files**: {list of target files} -**Metric**: {metric name} ({higher/lower} is better) -**Current best**: {best_metric} (established in iteration {N}) - -## Iteration History - -### Iteration {N} — {YYYY-MM-DD HH:MM UTC} — [Run]({run_url}) -- **Status**: ✅ Accepted / ❌ Rejected / ⚠️ Error -- **Change**: {one-line description} -- **Metric**: {value} (previous best: {previous_best}, delta: {delta}) -- **Commit**: {short_sha} (if accepted) - -### Iteration {N-1} — {YYYY-MM-DD HH:MM UTC} — [Run]({run_url}) -- **Status**: ❌ Rejected -- **Change**: {one-line description} -- **Metric**: {value} (previous best: {previous_best}, delta: {delta}) -- **Reason**: {why it was rejected} -``` - -### Format Rules - -- Iterations in **reverse chronological order** (newest first). -- Each iteration heading links to its GitHub Actions run. -- Use `${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}` for the current run URL. -- Close the previous month's issue and create a new one at month boundaries. -- Maximum 50 iterations per issue; create a continuation issue if exceeded. +3. **If this is an issue-based program** (`selected_issue` is not null): update the status comment and post a per-run comment on the source issue (see [Issue-Based Program Updates](#issue-based-program-updates)). ## Steering Issue -Maintain a single **persistent** open issue per program titled `[Autoloop: {program-name}] Steering`. Unlike experiment log issues (which rotate monthly), the steering issue lives for the entire lifetime of the program. +Maintain a single **persistent** open issue per program titled `[Autoloop: {program-name}] Steering`. The steering issue lives for the entire lifetime of the program. -The steering issue serves as the central coordination point linking together the program's three key resources: +The steering issue serves as the central coordination point linking together the program's key resources: - The **long-running branch** `autoloop/{program-name}` and its draft PR - The **state file** `{program-name}.md` in repo-memory (on the `memory/autoloop` branch) -- The **experiment log** issues ### Steering Issue Body Format @@ -801,7 +756,6 @@ The steering issue serves as the central coordination point linking together the - **Branch**: [`autoloop/{program-name}`](https://github.com/{owner}/{repo}/tree/autoloop/{program-name}) - **Pull Request**: #{pr_number} - **State File**: [`{program-name}.md`](https://github.com/{owner}/{repo}/blob/memory/autoloop/{program-name}.md) -- **Experiment Log**: #{experiment_log_issue_number} ## Program @@ -814,14 +768,14 @@ The steering issue serves as the central coordination point linking together the ### Steering Issue Rules - Create the steering issue on the **first accepted iteration** for the program if it does not already exist. -- **Update the issue body** whenever the best metric, PR number, or experiment log issue changes. +- **Update the issue body** whenever the best metric or PR number changes. - **Add a comment** on each accepted iteration with a link to the commit and actions run. - The steering issue is labeled `[automation, autoloop]`. - Do NOT close the steering issue when the PR is merged — the branch continues to accumulate future iterations. ## Issue-Based Program Updates -When a program is defined via a GitHub issue (i.e., `selected_issue` is not null in `/tmp/gh-aw/autoloop.json`), the source issue itself serves as the program definition **and** as the primary interface for steering and monitoring the program. In addition to the normal iteration workflow (state file, experiment log, steering issue, PR), you must also update the source issue. +When a program is defined via a GitHub issue (i.e., `selected_issue` is not null in `/tmp/gh-aw/autoloop.json`), the source issue itself serves as the program definition **and** as the primary interface for steering and monitoring the program. In addition to the normal iteration workflow (state file, steering issue, PR), you must also update the source issue. ### Status Comment @@ -845,7 +799,6 @@ Find the status comment by searching for a comment containing `