Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions .agents/scripts/commands/full-loop.md
Original file line number Diff line number Diff line change
Expand Up @@ -531,6 +531,30 @@ waste entire sessions guessing at root causes. Common pitfalls:
- Assuming infrastructure issues (OOM, timeouts) when the test itself is wrong
- Not checking if another PR (e.g., a CI investigation PR) already identified the fix

**Quality-debt blast radius cap (t1422 — MANDATORY for quality-debt tasks):**

When working on a quality-debt, simplification-debt, or batch-fix task (any task whose issue has `quality-debt` or `simplification-debt` labels, or whose description mentions "batch", "across N files", or "harden N scripts"), the PR must touch **at most 5 files**. This is a hard cap — not a guideline.

**Why:** Large batch PRs (10-69 files) conflict with every other PR in flight. When multiple batch PRs exist concurrently, each merge moves main and invalidates the others, creating a cascade where 63%+ of open PRs become `CONFLICTING`. Small PRs merge cleanly in any order.

**How to comply:**

1. If the issue describes fixes across more than 5 files, implement only the first 5 (prioritise by severity). Commit and create the PR for those 5.
2. File follow-up issues for the remaining files — one issue per 5-file batch, or one issue per file for complex fixes.
3. Do NOT attempt to fix all files in a single PR. A partial PR that merges cleanly is worth more than a complete PR that conflicts.

**Detection:** Before creating the PR, count the files you've changed:

```bash
CHANGED_FILES=$(git diff --name-only origin/main | wc -l | tr -d ' ')
if [[ "$CHANGED_FILES" -gt 5 ]]; then
echo "[t1422] WARNING: $CHANGED_FILES files changed — quality-debt PRs must touch at most 5 files"
echo "Split into multiple PRs or file follow-up issues for remaining files"
fi
```

If you exceed 5 files, split the work before creating the PR. This rule does NOT apply to feature PRs, bug fixes, or refactors — only to automated quality-debt and batch-fix tasks.

**Headless dispatch rules (MANDATORY for supervisor-dispatched workers - t158/t174):**

When running as a headless worker (dispatched by the supervisor via `opencode run` or `Claude -p`), the `--headless` flag is passed automatically. The full-loop-helper.sh script enforces these rules:
Expand Down
51 changes: 51 additions & 0 deletions .agents/scripts/commands/pulse.md
Original file line number Diff line number Diff line change
Expand Up @@ -580,6 +580,57 @@ QUALITY_DEBT_MAX=$(( MAX_WORKERS * 30 / 100 ))

If `QUALITY_DEBT_CURRENT >= QUALITY_DEBT_MAX`, do not dispatch more quality-debt issues this cycle.

### Quality-debt PR blast radius cap (t1422)

Quality-debt PRs that touch many files conflict with every other PR in flight. When multiple large-batch quality-debt PRs are created concurrently, they cascade into merge conflicts — each merge moves main, invalidating the next PR's base. This was observed in March 2026: 19 of 30 open PRs were conflicting, with individual PRs touching up to 69 files.

**Rule: quality-debt PRs must touch at most 5 files.** This is a hard cap enforced by the worker (see `full-loop.md` "Quality-debt blast radius cap"). The pulse enforces it at dispatch time by scoping issue descriptions:

1. **Per-file issues preferred.** When creating quality-debt issues (via `quality-feedback-helper.sh`, code-simplifier, or manual filing), create one issue per file or per tightly-coupled file group (max 5 files). An issue titled "Fix shellcheck violations in dispatch.sh" will produce a 1-file PR that conflicts with nothing. An issue titled "Fix shellcheck violations across 20 scripts" will produce a 20-file PR that conflicts with everything.

2. **File-level dedup before dispatch.** Before dispatching a quality-debt worker, check whether any open PR already touches the same files. If overlap exists, skip the issue this cycle — the existing PR must merge first.

```bash
# Get files that would be touched by this issue (from issue body or title)
# Then check open PRs for overlap
OPEN_PR_FILES=$(gh pr list --repo <slug> --state open --json number,files \
--jq '[.[].files[].path] | unique | .[]')

# If the issue mentions specific files, check for overlap
# This is a judgment call — read the issue body for file paths
# If overlap is found, skip: "Skipping quality-debt #NNN — files overlap with open PR #MMM"
```

3. **Serial merge for quality-debt.** Do not dispatch a second quality-debt worker for the same repo while a quality-debt PR is open and mergeable. Wait for the first to merge, then dispatch the next. This prevents the conflict cascade at the source. Feature PRs are unaffected — they touch different files by nature.

```bash
# Check for open quality-debt PRs in this repo
OPEN_DEBT_PRS=$(gh pr list --repo <slug> --state open \
--json number,title,labels \
--jq '[.[] | select(.labels[]?.name == "quality-debt" or (.title | test("quality.debt|fix:.*batch|fix:.*harden"; "i")))] | length' \
|| echo 0)

# If there's already an open quality-debt PR, skip dispatching more
if [[ "$OPEN_DEBT_PRS" -gt 0 ]]; then
echo "Skipping quality-debt dispatch — $OPEN_DEBT_PRS quality-debt PR(s) already open for <slug>"
# Focus on merging the existing PR instead
fi
```

**Why 5 files?** A 5-file PR has a ~10% chance of conflicting with another random 5-file PR in a 200-file repo. A 50-file PR has a ~95% chance. The conflict probability scales quadratically with file count — small PRs are exponentially safer.

### Stale quality-debt PR cleanup

When the pulse detects quality-debt PRs that have been `CONFLICTING` for 24+ hours, close them with a comment explaining they'll be superseded by smaller, atomic PRs:

```bash
# For each conflicting quality-debt PR older than 24 hours:
gh pr close <number> --repo <slug> \
-c "Closing — this PR has merge conflicts and touches too many files (blast radius issue, see t1422). The underlying fixes will be re-created as smaller PRs (max 5 files each) to prevent conflict cascades."
```

After closing, ensure the corresponding issues are relabelled `status:available` so they re-enter the dispatch queue. The next dispatch cycle will create properly-scoped PRs.

### Simplification-debt concurrency cap (10%)

Issues labelled `simplification-debt` (created by `/code-simplifier` analysis, approved by a human) represent maintainability improvements that preserve all functionality and knowledge. These are the lowest-priority automated work -- post-deployment nice-to-haves.
Expand Down