From 56d66e85ab3cc90e31a8ab836c401fb56a435cb6 Mon Sep 17 00:00:00 2001 From: Pedro Camara Junior Date: Mon, 24 Aug 2026 17:37:51 +0200 Subject: [PATCH 01/10] fix(autopilot): install action-library plugins in CI and use PAT for retry re-label MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit claude-code-action does not read the target repo's .claude/settings.json, so the executor, gates, and metrics workflows now install the content-stack plugins explicitly via plugin_marketplaces/plugins inputs. The retry step re-adds autopilot:run with AUTOPILOT_PAT — a GITHUB_TOKEN label event never re-triggers the executor, so retries were silently inert. Co-Authored-By: Claude Fable 5 --- .../init-templates/autopilot-executor.yml.template | 12 +++++++++++- .../docs/init-templates/autopilot-gates.yml.template | 6 ++++++ .../init-templates/autopilot-metrics.yml.template | 3 +++ 3 files changed, 20 insertions(+), 1 deletion(-) diff --git a/autopilot/docs/init-templates/autopilot-executor.yml.template b/autopilot/docs/init-templates/autopilot-executor.yml.template index b03b1a0..4cdb632 100644 --- a/autopilot/docs/init-templates/autopilot-executor.yml.template +++ b/autopilot/docs/init-templates/autopilot-executor.yml.template @@ -213,6 +213,13 @@ jobs: GITHUB_TOKEN: ${{ secrets.AUTOPILOT_PAT }} with: anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }} + # The action does not read .claude/settings.json — the autopilot + # action library must be installed explicitly. + plugin_marketplaces: "https://github.com/pcamarajr/content-stack.git" + plugins: | + content-ops@content-stack + astro-builder@content-stack + content-seo@content-stack claude_args: | --max-turns ${{ needs.guard.outputs.max_turns }} --allowedTools "Bash,Read,Write,Edit,Glob,Grep,Task,WebSearch,WebFetch" @@ -291,10 +298,13 @@ jobs: echo "max_retries=$MAX_RETRIES" } >> "$GITHUB_OUTPUT" + # The re-added label below must come from the PAT: a `labeled` event + # produced by the default GITHUB_TOKEN never triggers this workflow + # again, so a GITHUB_TOKEN retry would silently retry nothing. - name: Retry if: fromJSON(steps.attempts.outputs.count) < fromJSON(steps.attempts.outputs.max_retries) env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GH_TOKEN: ${{ secrets.AUTOPILOT_PAT }} ISSUE: ${{ github.event.issue.number }} RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} run: | diff --git a/autopilot/docs/init-templates/autopilot-gates.yml.template b/autopilot/docs/init-templates/autopilot-gates.yml.template index b0141a9..c40d5f1 100644 --- a/autopilot/docs/init-templates/autopilot-gates.yml.template +++ b/autopilot/docs/init-templates/autopilot-gates.yml.template @@ -65,6 +65,9 @@ jobs: uses: anthropics/claude-code-action@v1 with: anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }} + plugin_marketplaces: "https://github.com/pcamarajr/content-stack.git" + plugins: | + astro-builder@content-stack claude_args: | --max-turns 20 --allowedTools "Bash,Read,Grep,Glob,Task" @@ -105,6 +108,9 @@ jobs: uses: anthropics/claude-code-action@v1 with: anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }} + plugin_marketplaces: "https://github.com/pcamarajr/content-stack.git" + plugins: | + content-ops@content-stack claude_args: | --max-turns 20 --allowedTools "Bash,Read,Grep,Glob,Task" diff --git a/autopilot/docs/init-templates/autopilot-metrics.yml.template b/autopilot/docs/init-templates/autopilot-metrics.yml.template index f28df78..0ff1de0 100644 --- a/autopilot/docs/init-templates/autopilot-metrics.yml.template +++ b/autopilot/docs/init-templates/autopilot-metrics.yml.template @@ -60,6 +60,9 @@ jobs: GOOGLE_APPLICATION_CREDENTIALS: ${{ runner.temp }}/gsc-service-account.json with: anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }} + plugin_marketplaces: "https://github.com/pcamarajr/content-stack.git" + plugins: | + content-seo@content-stack claude_args: | --max-turns 15 --allowedTools "Bash,Read,Write,Task" From 690f3da1119bbab4cc3773921fb71b2d57c428e2 Mon Sep 17 00:00:00 2001 From: Pedro Camara Junior Date: Mon, 24 Aug 2026 17:41:00 +0200 Subject: [PATCH 02/10] fix(autopilot): direct-merge fallback when allow_auto_merge is unavailable Private repos on the GitHub Free plan cannot enable allow_auto_merge or branch protection. The auto-merge job already runs behind all four gates, so falling back to a direct squash merge is equivalent there; SKILL.md documents the plan limitation and its trust implications. Co-Authored-By: Claude Fable 5 --- .../docs/init-templates/autopilot-gates.yml.template | 9 ++++++++- autopilot/skills/init/SKILL.md | 11 +++++++---- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/autopilot/docs/init-templates/autopilot-gates.yml.template b/autopilot/docs/init-templates/autopilot-gates.yml.template index c40d5f1..877bb6f 100644 --- a/autopilot/docs/init-templates/autopilot-gates.yml.template +++ b/autopilot/docs/init-templates/autopilot-gates.yml.template @@ -169,7 +169,14 @@ jobs: TASK_NUM=$(echo "$HEAD_REF" | grep -oP 'autopilot/task-\K[0-9]+' || true) if [ "$POLICY" = "auto" ]; then - gh pr merge --squash --auto "$PR" + # --auto requires the repo's allow_auto_merge setting, which + # private repos on the Free plan cannot enable. Gates are already + # green here (this job runs behind needs: [all gates]), so a + # direct squash merge is an equivalent fallback. + if ! gh pr merge --squash --auto "$PR"; then + echo "auto-merge unavailable on this repo — merging directly (gates are green)." + gh pr merge --squash "$PR" + fi if [ -n "$TASK_NUM" ]; then gh issue edit "$TASK_NUM" --add-label "autopilot:done" gh issue close "$TASK_NUM" --reason completed diff --git a/autopilot/skills/init/SKILL.md b/autopilot/skills/init/SKILL.md index e0b6ac7..610afe8 100644 --- a/autopilot/skills/init/SKILL.md +++ b/autopilot/skills/init/SKILL.md @@ -159,9 +159,12 @@ returns 200 without actually flipping the setting, so never trust the status cod gh api -X PATCH repos/{owner}/{repo} -f allow_auto_merge=true gh api repos/{owner}/{repo} --jq .allow_auto_merge ``` -The second command must print `true`. This requires admin on the repo. If it 403s OR -still reads `false` after the PATCH, don't stop the run — print it as a manual -follow-up instead (add it to the Step 5 checklist): +The second command must print `true`. This requires admin on the repo. Note: private +repos on the GitHub Free plan cannot enable this setting at all (the PATCH silently +no-ops) — the gates workflow handles it by falling back to a direct squash merge once +its own gates are green, so this is informational, not blocking. If it 403s OR still +reads `false` after the PATCH, don't stop the run — print it as a manual follow-up +instead (add it to the Step 5 checklist): ```text [ ] Enable "Allow auto-merge" in repo Settings → General (requires admin) — needed for the gates workflow's `gh pr merge --squash --auto` to succeed. @@ -319,5 +322,5 @@ is the one action that turns proposals into work, and this skill never does it f - Never overwrite an existing file without asking first. Identical content is skipped silently; different content stops and asks (keep / overwrite / show diff). - Never create or approve an intention issue. This skill scaffolds infrastructure only — it does not author intentions and it never applies `intention:approved`. - The executor's machine identity (PAT or GitHub App) must never be granted permission to apply `intention:approved`. That label activates work and is reserved for a human maintainer — do not add it to any token's scope, workflow `permissions:` block, or automation this skill writes. -- Gate enforcement depends on branch protection; without it (see the Step 5 checklist) the path-guard/build/audit/anti-slop boundary is advisory, not enforced — anyone with push access can bypass it. +- Gate enforcement depends on branch protection; without it (see the Step 5 checklist) the path-guard/build/audit/anti-slop boundary is advisory, not enforced — anyone with push access can bypass it. Private repos on the GitHub Free plan cannot enable branch protection at all: acceptable for a single-maintainer private repo where the only writers are the maintainer and the executor PAT, but revisit before adding collaborators or going public. - Re-running this skill must be safe: always detect what already exists (Step 0) before creating anything, and always report what was skipped, not just what was created. From fcd4dcbaa3b4084278d56f434b06c4eddecd2dbe Mon Sep 17 00:00:00 2001 From: Pedro Camara Junior Date: Mon, 24 Aug 2026 17:49:49 +0200 Subject: [PATCH 03/10] fix(autopilot): claude-code-action jobs need id-token: write (OIDC) Found live on the sandbox: the action fails during setup with 'Could not fetch an OIDC token' without it, even when authenticating via anthropic_api_key. Co-Authored-By: Claude Fable 5 --- autopilot/docs/init-templates/autopilot-executor.yml.template | 1 + autopilot/docs/init-templates/autopilot-gates.yml.template | 2 ++ autopilot/docs/init-templates/autopilot-metrics.yml.template | 1 + 3 files changed, 4 insertions(+) diff --git a/autopilot/docs/init-templates/autopilot-executor.yml.template b/autopilot/docs/init-templates/autopilot-executor.yml.template index 4cdb632..afbddf6 100644 --- a/autopilot/docs/init-templates/autopilot-executor.yml.template +++ b/autopilot/docs/init-templates/autopilot-executor.yml.template @@ -181,6 +181,7 @@ jobs: contents: write pull-requests: write issues: write + id-token: write # claude-code-action requires OIDC steps: # Executor-opened PRs must trigger the gates workflow, and the default # GITHUB_TOKEN never starts a workflow run from its own pushes/PRs — a diff --git a/autopilot/docs/init-templates/autopilot-gates.yml.template b/autopilot/docs/init-templates/autopilot-gates.yml.template index 877bb6f..29dfb61 100644 --- a/autopilot/docs/init-templates/autopilot-gates.yml.template +++ b/autopilot/docs/init-templates/autopilot-gates.yml.template @@ -57,6 +57,7 @@ jobs: runs-on: ubuntu-latest permissions: contents: read + id-token: write # claude-code-action requires OIDC steps: - name: Checkout uses: actions/checkout@v5 @@ -98,6 +99,7 @@ jobs: runs-on: ubuntu-latest permissions: contents: read + id-token: write # claude-code-action requires OIDC steps: - name: Checkout uses: actions/checkout@v5 diff --git a/autopilot/docs/init-templates/autopilot-metrics.yml.template b/autopilot/docs/init-templates/autopilot-metrics.yml.template index 0ff1de0..3c90d9c 100644 --- a/autopilot/docs/init-templates/autopilot-metrics.yml.template +++ b/autopilot/docs/init-templates/autopilot-metrics.yml.template @@ -16,6 +16,7 @@ jobs: runs-on: ubuntu-latest permissions: contents: write + id-token: write # claude-code-action requires OIDC steps: - name: Checkout uses: actions/checkout@v5 From 43630ff1042e8328caa1de8a3be569442e71398d Mon Sep 17 00:00:00 2001 From: Pedro Camara Junior Date: Mon, 24 Aug 2026 17:57:03 +0200 Subject: [PATCH 04/10] fix(autopilot): gate-job environment fixes from live sandbox run - build job: setup-node + corepack (pnpm was exit 127 on a bare runner) - executor action gets github_token: AUTOPILOT_PAT so task PRs are authored by the PAT identity, not claude[bot] - gate actions allow the claude bot actor as fallback Co-Authored-By: Claude Fable 5 --- .../init-templates/autopilot-executor.yml.template | 4 ++++ .../init-templates/autopilot-gates.yml.template | 13 +++++++++++++ 2 files changed, 17 insertions(+) diff --git a/autopilot/docs/init-templates/autopilot-executor.yml.template b/autopilot/docs/init-templates/autopilot-executor.yml.template index afbddf6..29bd015 100644 --- a/autopilot/docs/init-templates/autopilot-executor.yml.template +++ b/autopilot/docs/init-templates/autopilot-executor.yml.template @@ -214,6 +214,10 @@ jobs: GITHUB_TOKEN: ${{ secrets.AUTOPILOT_PAT }} with: anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }} + # Use the PAT as the action's own token too — otherwise it mints a + # claude[bot] app token, the PR lands authored by a bot, and the + # gate actions (which block non-human actors by default) refuse to run. + github_token: ${{ secrets.AUTOPILOT_PAT }} # The action does not read .claude/settings.json — the autopilot # action library must be installed explicitly. plugin_marketplaces: "https://github.com/pcamarajr/content-stack.git" diff --git a/autopilot/docs/init-templates/autopilot-gates.yml.template b/autopilot/docs/init-templates/autopilot-gates.yml.template index 29dfb61..c1adc15 100644 --- a/autopilot/docs/init-templates/autopilot-gates.yml.template +++ b/autopilot/docs/init-templates/autopilot-gates.yml.template @@ -46,6 +46,15 @@ jobs: - name: Checkout uses: actions/checkout@v5 + - name: Setup Node + uses: actions/setup-node@v4 + with: + node-version: 22 + + # Makes pnpm/yarn available per the repo's packageManager field; no-op for npm. + - name: Enable corepack + run: corepack enable + - name: Install dependencies run: "{{PACKAGE_MANAGER_INSTALL}}" @@ -66,6 +75,8 @@ jobs: uses: anthropics/claude-code-action@v1 with: anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }} + # Task PRs may be authored/synchronized by a bot identity. + allowed_bots: "claude" plugin_marketplaces: "https://github.com/pcamarajr/content-stack.git" plugins: | astro-builder@content-stack @@ -110,6 +121,8 @@ jobs: uses: anthropics/claude-code-action@v1 with: anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }} + # Task PRs may be authored/synchronized by a bot identity. + allowed_bots: "claude" plugin_marketplaces: "https://github.com/pcamarajr/content-stack.git" plugins: | content-ops@content-stack From d4a26bcb3d85bbe90e59751546988952178ac7e7 Mon Sep 17 00:00:00 2001 From: Pedro Camara Junior Date: Mon, 24 Aug 2026 18:05:13 +0200 Subject: [PATCH 05/10] fix(autopilot): gate reviews need 40 turns; add 20-min job timeout fuse Both gates completed their reviews on the live sandbox run but exceeded --max-turns 20 (26 and 21 turns), failing the action on principle. Co-Authored-By: Claude Fable 5 --- autopilot/docs/init-templates/autopilot-gates.yml.template | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/autopilot/docs/init-templates/autopilot-gates.yml.template b/autopilot/docs/init-templates/autopilot-gates.yml.template index c1adc15..1506d39 100644 --- a/autopilot/docs/init-templates/autopilot-gates.yml.template +++ b/autopilot/docs/init-templates/autopilot-gates.yml.template @@ -64,6 +64,7 @@ jobs: audit: if: startsWith(github.head_ref, 'autopilot/task-') runs-on: ubuntu-latest + timeout-minutes: 20 permissions: contents: read id-token: write # claude-code-action requires OIDC @@ -81,7 +82,7 @@ jobs: plugins: | astro-builder@content-stack claude_args: | - --max-turns 20 + --max-turns 40 --allowedTools "Bash,Read,Grep,Glob,Task" prompt: | Run /astro-builder:audit against this checkout. Never auto-fix @@ -108,6 +109,7 @@ jobs: anti-slop: if: startsWith(github.head_ref, 'autopilot/task-') runs-on: ubuntu-latest + timeout-minutes: 20 permissions: contents: read id-token: write # claude-code-action requires OIDC @@ -127,7 +129,7 @@ jobs: plugins: | content-ops@content-stack claude_args: | - --max-turns 20 + --max-turns 40 --allowedTools "Bash,Read,Grep,Glob,Task" prompt: | Diff this PR's head against `origin/${{ github.event.pull_request.base.ref }}` From cd3ffe75f38c7efbb062e6331c9eb037b0b9170a Mon Sep 17 00:00:00 2001 From: Pedro Camara Junior Date: Mon, 24 Aug 2026 18:08:05 +0200 Subject: [PATCH 06/10] fix(autopilot): path-guard must not shallow-refetch the base ref The job checks out with fetch-depth: 0; re-fetching base --depth=1 clobbers origin/ and loses the merge base once base advances, failing the three-dot diff with 'no merge base'. Co-Authored-By: Claude Fable 5 --- autopilot/docs/init-templates/autopilot-gates.yml.template | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/autopilot/docs/init-templates/autopilot-gates.yml.template b/autopilot/docs/init-templates/autopilot-gates.yml.template index 1506d39..345bd6d 100644 --- a/autopilot/docs/init-templates/autopilot-gates.yml.template +++ b/autopilot/docs/init-templates/autopilot-gates.yml.template @@ -27,7 +27,9 @@ jobs: - name: Reject changes to the autopilot control plane run: | - git fetch origin "${{ github.event.pull_request.base.ref }}" --depth=1 + # fetch-depth: 0 above already has full history for every ref; a + # shallow re-fetch here would clobber origin/ and lose the + # merge base once the base branch advances. CHANGED=$(git diff --name-only "origin/${{ github.event.pull_request.base.ref }}...HEAD") PROTECTED=$(echo "$CHANGED" | grep -E '^(\.autopilot/|\.github/)' || true) From 4cb7c3cca455707c43c73ee169b2ae96c18c7e1f Mon Sep 17 00:00:00 2001 From: Pedro Camara Junior Date: Mon, 24 Aug 2026 18:16:03 +0200 Subject: [PATCH 07/10] feat(autopilot): gate findings visible on the PR; executor self-review MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - audit/anti-slop gates post their P0/Must Fix findings as PR comments before writing the sentinel (red gates were silent — findings lived only in the unlogged Claude final message) - new report-failure job comments on the PR and the task issue when any gate fails, closing the triage loop - executor self-reviews content with /content-ops:review-content before opening the PR so articles don't systematically bounce off the gate Co-Authored-By: Claude Fable 5 --- .../autopilot-executor.yml.template | 6 ++- .../autopilot-gates.yml.template | 38 +++++++++++++++++-- 2 files changed, 39 insertions(+), 5 deletions(-) diff --git a/autopilot/docs/init-templates/autopilot-executor.yml.template b/autopilot/docs/init-templates/autopilot-executor.yml.template index 29bd015..ddd515a 100644 --- a/autopilot/docs/init-templates/autopilot-executor.yml.template +++ b/autopilot/docs/init-templates/autopilot-executor.yml.template @@ -249,7 +249,11 @@ jobs: 2. Create and switch to a branch named exactly `autopilot/task-${{ github.event.issue.number }}` before making any change. - 3. Do the work the skill produces, then commit it. + 3. Do the work the skill produces, then self-review before + committing: run /content-ops:review-content on every content + file you wrote and fix all Must Fix findings yourself — the + anti-slop gate applies the same standard and will reject the + PR otherwise. Then commit. 4. Push the branch and open a pull request against `{{DEFAULT_BRANCH}}` that: - has the title `autopilot: `, diff --git a/autopilot/docs/init-templates/autopilot-gates.yml.template b/autopilot/docs/init-templates/autopilot-gates.yml.template index 345bd6d..2e7ac70 100644 --- a/autopilot/docs/init-templates/autopilot-gates.yml.template +++ b/autopilot/docs/init-templates/autopilot-gates.yml.template @@ -69,6 +69,7 @@ jobs: timeout-minutes: 20 permissions: contents: read + pull-requests: write id-token: write # claude-code-action requires OIDC steps: - name: Checkout @@ -97,8 +98,10 @@ jobs: echo "FAIL" > /tmp/audit-result.txt (if any P0 issue was found) echo "PASS" > /tmp/audit-result.txt (otherwise) - Then, on the line above that command in your final message, list - every P0 issue found (or write "none"). + Before writing that file, post your findings so humans can see + them: run + gh pr comment ${{ github.event.pull_request.number }} --body "" + (GITHUB_TOKEN is already in your environment.) - name: Enforce audit result run: | @@ -114,6 +117,7 @@ jobs: timeout-minutes: 20 permissions: contents: read + pull-requests: write id-token: write # claude-code-action requires OIDC steps: - name: Checkout @@ -146,8 +150,10 @@ jobs: echo "FAIL" > /tmp/anti-slop-result.txt (if any Must Fix was found) echo "PASS" > /tmp/anti-slop-result.txt (otherwise) - Then, on the line above that command in your final message, list - every Must Fix found (or write "none"). + Before writing that file, post your findings so humans can see + them: run + gh pr comment ${{ github.event.pull_request.number }} --body "" + (GITHUB_TOKEN is already in your environment.) - name: Enforce anti-slop result run: | @@ -157,6 +163,30 @@ jobs: exit 1 fi + # Red gates must not vanish into the Actions tab: tell the PR and the + # task issue what happened so a human (or the strategist) can triage. + report-failure: + needs: [path-guard, build, audit, anti-slop] + if: failure() && startsWith(github.head_ref, 'autopilot/task-') + runs-on: ubuntu-latest + permissions: + pull-requests: write + issues: write + steps: + - name: Comment on PR and task issue + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GH_REPO: ${{ github.repository }} + PR: ${{ github.event.pull_request.number }} + HEAD_REF: ${{ github.head_ref }} + RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} + run: | + gh pr comment "$PR" --body "Autopilot gates failed: $RUN_URL — see the gate comments above for findings." + TASK_NUM=$(echo "$HEAD_REF" | grep -oP 'autopilot/task-\K[0-9]+' || true) + if [ -n "$TASK_NUM" ]; then + gh issue comment "$TASK_NUM" --body "Gates failed on PR #$PR: $RUN_URL — needs triage or a revised attempt." + fi + auto-merge: needs: [path-guard, build, audit, anti-slop] if: success() && startsWith(github.head_ref, 'autopilot/task-') From 02c7ddc58b22b0d24c72532c731d4fcbf3edca06 Mon Sep 17 00:00:00 2001 From: Pedro Camara Junior Date: Mon, 24 Aug 2026 18:17:33 +0200 Subject: [PATCH 08/10] feat(autopilot): default all CI Claude runs to Sonnet Co-Authored-By: Claude Fable 5 --- autopilot/docs/init-templates/autopilot-executor.yml.template | 1 + autopilot/docs/init-templates/autopilot-gates.yml.template | 2 ++ autopilot/docs/init-templates/autopilot-metrics.yml.template | 1 + 3 files changed, 4 insertions(+) diff --git a/autopilot/docs/init-templates/autopilot-executor.yml.template b/autopilot/docs/init-templates/autopilot-executor.yml.template index ddd515a..d0fa9cc 100644 --- a/autopilot/docs/init-templates/autopilot-executor.yml.template +++ b/autopilot/docs/init-templates/autopilot-executor.yml.template @@ -226,6 +226,7 @@ jobs: astro-builder@content-stack content-seo@content-stack claude_args: | + --model claude-sonnet-5 --max-turns ${{ needs.guard.outputs.max_turns }} --allowedTools "Bash,Read,Write,Edit,Glob,Grep,Task,WebSearch,WebFetch" prompt: | diff --git a/autopilot/docs/init-templates/autopilot-gates.yml.template b/autopilot/docs/init-templates/autopilot-gates.yml.template index 2e7ac70..acb2583 100644 --- a/autopilot/docs/init-templates/autopilot-gates.yml.template +++ b/autopilot/docs/init-templates/autopilot-gates.yml.template @@ -85,6 +85,7 @@ jobs: plugins: | astro-builder@content-stack claude_args: | + --model claude-sonnet-5 --max-turns 40 --allowedTools "Bash,Read,Grep,Glob,Task" prompt: | @@ -135,6 +136,7 @@ jobs: plugins: | content-ops@content-stack claude_args: | + --model claude-sonnet-5 --max-turns 40 --allowedTools "Bash,Read,Grep,Glob,Task" prompt: | diff --git a/autopilot/docs/init-templates/autopilot-metrics.yml.template b/autopilot/docs/init-templates/autopilot-metrics.yml.template index 3c90d9c..9f82e3d 100644 --- a/autopilot/docs/init-templates/autopilot-metrics.yml.template +++ b/autopilot/docs/init-templates/autopilot-metrics.yml.template @@ -65,6 +65,7 @@ jobs: plugins: | content-seo@content-stack claude_args: | + --model claude-sonnet-5 --max-turns 15 --allowedTools "Bash,Read,Write,Task" prompt: | From 3ce1a58909b67e30a6c68be9a0255bef7566bd15 Mon Sep 17 00:00:00 2001 From: Pedro Camara Junior Date: Mon, 24 Aug 2026 18:30:45 +0200 Subject: [PATCH 09/10] =?UTF-8?q?docs(autopilot):=20baseline=20audit=20is?= =?UTF-8?q?=20a=20prerequisite=20=E2=80=94=20the=20audit=20gate=20is=20who?= =?UTF-8?q?le-repo?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Found live: a pre-existing P0 (site missing in astro.config) blocked a clean content PR. The repo must pass /astro-builder:audit before the loop is activated. Co-Authored-By: Claude Fable 5 --- autopilot/skills/init/SKILL.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/autopilot/skills/init/SKILL.md b/autopilot/skills/init/SKILL.md index 610afe8..58abf14 100644 --- a/autopilot/skills/init/SKILL.md +++ b/autopilot/skills/init/SKILL.md @@ -306,6 +306,9 @@ Before the loop can run: -F restrictions=null \ -F allow_force_pushes=false \ -F allow_deletions=false + [ ] Baseline audit: run /astro-builder:audit on the repo and clear every P0 BEFORE + activating the loop — the audit gate reviews the whole repo, so any pre-existing + P0 blocks every task PR, no matter how clean the PR itself is [ ] Write and pin the first intention issue (goal / metric / horizon / constraints) [ ] Apply intention:approved to that issue — only a maintainer applies this label From 7a651d9ba4fa1bcdf183f48106cee3b509ceccf5 Mon Sep 17 00:00:00 2001 From: Pedro Camara Junior Date: Mon, 24 Aug 2026 18:41:34 +0200 Subject: [PATCH 10/10] fix(autopilot): allow the Skill tool in CI Claude runs; retry budget resets on unblock The executor prompt orders plugin-skill invocations but Skill was not in --allowedTools, so the run died on a permission denial. Retry counting now only considers failure markers newer than the last autopilot:blocked un-label, so a human unblock grants a fresh retry budget instead of stale markers sending the task straight back to blocked. Co-Authored-By: Claude Fable 5 --- .../docs/init-templates/autopilot-executor.yml.template | 9 +++++++-- .../docs/init-templates/autopilot-gates.yml.template | 4 ++-- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/autopilot/docs/init-templates/autopilot-executor.yml.template b/autopilot/docs/init-templates/autopilot-executor.yml.template index d0fa9cc..6ec7e88 100644 --- a/autopilot/docs/init-templates/autopilot-executor.yml.template +++ b/autopilot/docs/init-templates/autopilot-executor.yml.template @@ -228,7 +228,7 @@ jobs: claude_args: | --model claude-sonnet-5 --max-turns ${{ needs.guard.outputs.max_turns }} - --allowedTools "Bash,Read,Write,Edit,Glob,Grep,Task,WebSearch,WebFetch" + --allowedTools "Bash,Read,Write,Edit,Glob,Grep,Task,Skill,WebSearch,WebFetch" prompt: | You are the autopilot executor. You implement exactly one task issue on this repo, open a PR for it, and stop — you never merge, and you @@ -300,8 +300,13 @@ jobs: ISSUE: ${{ github.event.issue.number }} run: | MARKER="" + # Only count failures since the last time a human unblocked the + # task (removed autopilot:blocked) — otherwise stale markers from a + # long-fixed failure eat the retry budget forever. + LAST_UNBLOCK=$(gh api "repos/${{ github.repository }}/issues/$ISSUE/timeline" --paginate \ + --jq '[.[] | select(.event=="unlabeled" and .label.name=="autopilot:blocked") | .created_at] | max // ""') COUNT=$(gh issue view "$ISSUE" --json comments \ - --jq "[.comments[].body | select(startswith(\"$MARKER\"))] | length") + --jq "[.comments[] | select(.body | startswith(\"$MARKER\")) | select(.createdAt > \"$LAST_UNBLOCK\")] | length") MAX_RETRIES=$(yq '.limits.retries' .autopilot/config.yml) { echo "count=$COUNT" diff --git a/autopilot/docs/init-templates/autopilot-gates.yml.template b/autopilot/docs/init-templates/autopilot-gates.yml.template index acb2583..708e863 100644 --- a/autopilot/docs/init-templates/autopilot-gates.yml.template +++ b/autopilot/docs/init-templates/autopilot-gates.yml.template @@ -87,7 +87,7 @@ jobs: claude_args: | --model claude-sonnet-5 --max-turns 40 - --allowedTools "Bash,Read,Grep,Glob,Task" + --allowedTools "Bash,Read,Grep,Glob,Task,Skill" prompt: | Run /astro-builder:audit against this checkout. Never auto-fix anything — you are a read-only reviewer here, the repo is not @@ -138,7 +138,7 @@ jobs: claude_args: | --model claude-sonnet-5 --max-turns 40 - --allowedTools "Bash,Read,Grep,Glob,Task" + --allowedTools "Bash,Read,Grep,Glob,Task,Skill" prompt: | Diff this PR's head against `origin/${{ github.event.pull_request.base.ref }}` to find the changed content files, then run