diff --git a/create-dev-loop.md b/create-dev-loop.md index 950c6db..0fa97b6 100644 --- a/create-dev-loop.md +++ b/create-dev-loop.md @@ -486,6 +486,8 @@ Repo-specific entries: {{DO_NOT_AUTO_MERGE}} {{/if}} +**A path match outranks any merge authorization granted before the diff existed.** A run-level pre-authorization (a dispatch-time flag such as `--allow-merge`, a merge allow-list, a standing "you may merge" instruction) is a property of the *run*; a protected-path match is a property of the *change*, evaluated after any grant. The grant can widen how much merges without review, but it cannot clear a path match, because nobody granting it could see which protected path the diff would touch. When the two disagree, the path match wins: leave the PR open, post a comment naming the matched path and why it is protected, and hand the decision back. Only an authorization given with sight of the matched path clears the hold (the codeowner exception below). + If no modified path matches, proceed: \`\`\`bash @@ -570,6 +572,7 @@ Return to Phase 1. **{{EXTERNAL_SIGNAL_LABEL}} has never been green on `{{DEFAULT_BRANCH}}` (structurally red — e.g. a required job fails on absent credentials or an unset secret):** this is not the same as red-on-this-branch, and no change the loop can write will satisfy the gate. Record it at triage (Phase 1), assess per-job signal in Phase 4 so a job carrying no signal for the diff is neither counted as blocking nor mistaken for verification, and hand off in Phase 8 naming the blocking condition and the issue tracking it rather than reporting an ordinary "awaiting review". **An issue requires a harness-blocked operation (editing `CLAUDE.md`/agent-loaded config, registering an external submodule):** recognize it at triage (Phase 1) — surface to the user for explicit authorization rather than attempting it mid-cycle; never remove a path while `CLAUDE.md` still references it. **Autonomous multi-cycle batch (`/ until …`):** skip/cap the Phase-5 human-review wait (rubric + green anchor is the gate); still hand off do-not-auto-merge/charter PRs. Stop when only blocked, charter-gated, or too-large work remains, or a cycle yields no scoped work. +**A protected path matches while a blanket merge pre-authorization is in force:** the pre-authorization does not clear the hold — it was granted before the diff existed (Phase 8). Leave the PR open, name the matched path in a comment, and hand the decision back. **A concurrent session holds the tree or an open PR:** adopt its PR (bring current with `{{DEFAULT_BRANCH}}`, re-run the anchor, review, merge if green) rather than doing nothing; work in a `git worktree` to avoid colliding, and treat a harmless local `--delete-branch` failure as success once `gh pr view --json state` confirms the merge. **Put the worktree inside the repository checkout** (e.g. `.worktrees/`, added to `.git/info/exclude` so an untracked directory doesn't pollute `git status`), never in `/tmp` or anywhere else outside it: a path-restricted sandbox refuses every read and edit outside the checkout, so a worktree placed there locks the session out of its own working tree one file operation at a time. **In a headless dispatch (e.g. `gardener tend`), do not create a worktree at all** — the run already owns a clone dedicated to it, so there is no concurrent session to collide with, and the checkout can be used directly. The harness scratchpad is a third resource sibling loops contend for, alongside the shared tree and the shared `origin/{{DEFAULT_BRANCH}}`, and unlike those two it fails silently: a scratch file named generically is overwritten by the other loop with no error, so name scratch files uniquely per repo and per cycle (Phase 3) and re-verify anything published from one. **A test fails intermittently (suspected flake):** re-run the test command once. If the same test fails again, treat it as a real failure and investigate. If it passes on the second run, note the flake in the PR body and proceed — do not suppress or `@Ignore` a test without understanding why it is flaky. **A review comment is a false positive:** reply with evidence, do not apply the change.