Symptom
Every autoloop-authored PR is landing red, not because the iteration's change is wrong, but because main already has pre-existing biome lint violations that CI now rejects. The agent's Target list forbids touching most of the offending files, so the fix-retry loop from #176 has nothing it can do and stalls.
PR #206 (iteration 2 of tsb-perf-evolve) is a clean example:
- Agent modified only
src/core/series.ts (within Target).
- OpenEvolve benchmark check: SUCCESS — the iteration's code change is fine.
- Tests: most pass (a few unrelated test failures also exist).
- Lint step fails with violations in files the iteration never touched.
Violations surfaced by biome on this PR (all pre-existing on main):
./src/core/align.ts:86:3 lint/style/useDefaultSwitchClause
./src/core/align.ts:165:50 lint/nursery/noNestedTernary
./src/core/astype.ts:48:17 lint/complexity/noExcessiveCognitiveComplexity
./src/core/date_range.ts:533 lint/complexity/noExcessiveCognitiveComplexity
./src/core/natsort.ts:91:27 lint/nursery/noNestedTernary
./src/core/natsort.ts:226:23 lint/complexity/noExcessiveCognitiveComplexity
./src/core/frame.ts:22-27 lint/nursery/useImportRestrictions (x6)
./src/core/frame.ts:782-784 lint/complexity/useLiteralKeys (FIXABLE x3)
./src/core/reindex.ts:159:10 lint/complexity/noExcessiveCognitiveComplexity
./tests/window/rolling_apply.test.ts:6:8 lint/style/noNamespaceImport
./tests/window/expanding.test.ts:9:8 lint/style/noNamespaceImport
./.autoloop/programs/tsb-perf-evolve/code/benchmark.ts:28:10 lint/nursery/useExplicitType
Plus the final line: The number of diagnostics exceeds the number allowed by Biome. — so there may be more violations biome truncated.
Why this is happening
One of two root causes:
-
Biome was upgraded and its lint/nursery/* rules changed. The nursery group is biome's own term for experimental rules whose behavior shifts between versions. An upgrade enabled or tightened noNestedTernary, useExplicitType, useImportRestrictions — main silently picked up new violations.
-
Biome's nursery group was newly enabled in biome.json without first fixing the violations that immediately appeared.
Either way, the net effect is that main is red against biome's current ruleset, and every PR inherits the failure.
Why the fix-retry loop can't resolve it
autoloop-program Target lists (e.g. tsb-perf-evolve/program.md) correctly scope the agent to one file. The agent cannot — by design — reach into src/core/align.ts, astype.ts, natsort.ts, frame.ts, reindex.ts, or tests/window/**. The fix-retry loop from #176 will try; it will see every attempt blocked; it will eventually pause the program with ci-fix-exhausted or similar.
The one violation within Target is .autoloop/programs/tsb-perf-evolve/code/benchmark.ts:28:10 lint/nursery/useExplicitType. That one the agent can fix — and should. If it isn't, the fix-retry loop may only trigger on test/compile failures and is skipping lint failures (worth checking separately).
Fix — two tracks, run in parallel
Track 1: Clean main
Get main green against the current biome ruleset:
# Auto-fix the FIXABLE ones (useLiteralKeys, and likely several nursery rules that have autofix)
bun run lint --apply --unsafe
# Manually fix the non-auto rules. One PR per category is easier to review:
# - useDefaultSwitchClause: add default cases to switches in align.ts
# - noNestedTernary: flatten nested ternaries in align.ts, natsort.ts
# - noExcessiveCognitiveComplexity: split big functions in astype.ts, date_range.ts, natsort.ts, reindex.ts
# - useImportRestrictions: restructure the cross-file imports in frame.ts
# - noNamespaceImport: change `import * as foo` to named imports in tests/window/*
# - useExplicitType: add return-type annotations in benchmark.ts
If any of the nursery rules look like net-negative value for the codebase on review (nursery rules are, by biome's own definition, experimental), turn them off in biome.json rather than fighting them:
{
"linter": {
"rules": {
"nursery": {
"noNestedTernary": "off",
"useExplicitType": "off",
"useImportRestrictions": "off"
}
}
}
}
Nursery rules churn between biome releases; suppressing ones we don't want is defensive hygiene, not lint debt.
Track 2: Scope CI lint to changed files
Even after Track 1, biome's nursery group will keep surfacing new rules on upgrades. Protect autoloop (and humans) from being blocked by unrelated legacy violations by running lint against only the files the PR actually touched:
In .github/workflows/ci.yml, change the lint step from:
to something like:
- name: Lint changed files only
run: |
set -euo pipefail
base=${{ github.event.pull_request.base.sha || 'origin/main' }}
files=$(git diff --name-only --diff-filter=ACMR "$base" HEAD \
| grep -E '\.(ts|tsx|js|jsx|json)$' || true)
if [ -z "$files" ]; then
echo "No lint-eligible files changed."
exit 0
fi
echo "$files" | xargs bun x biome check
Pair with a nightly job on main that runs biome against the whole codebase and opens an issue (or comments on a tracking one) when new violations appear — so legacy violations don't quietly pile up forever, but they also don't block every in-flight PR.
Alternatively, pin biome to a specific version in package.json and explicitly update with a dedicated PR that fixes whatever new rules fire. Stops the silent rule churn.
Acceptance
bun run lint on main exits 0 (no violations, or nursery rules turned off if we judge them not worth fighting).
- CI on autoloop PRs passes the lint step when the iteration's change itself is clean (we can verify against a fresh iteration after Track 1 lands).
- Lint scope is decided: either whole-codebase-always-clean (Track 1 maintained going forward) or changed-files-only (Track 2). Pick one; don't silently tolerate a "main is red and so is every PR" state.
Related
Symptom
Every autoloop-authored PR is landing red, not because the iteration's change is wrong, but because main already has pre-existing biome lint violations that CI now rejects. The agent's Target list forbids touching most of the offending files, so the fix-retry loop from #176 has nothing it can do and stalls.
PR #206 (iteration 2 of
tsb-perf-evolve) is a clean example:src/core/series.ts(within Target).Violations surfaced by biome on this PR (all pre-existing on main):
Plus the final line:
The number of diagnostics exceeds the number allowed by Biome.— so there may be more violations biome truncated.Why this is happening
One of two root causes:
Biome was upgraded and its
lint/nursery/*rules changed. Thenurserygroup is biome's own term for experimental rules whose behavior shifts between versions. An upgrade enabled or tightenednoNestedTernary,useExplicitType,useImportRestrictions— main silently picked up new violations.Biome's
nurserygroup was newly enabled inbiome.jsonwithout first fixing the violations that immediately appeared.Either way, the net effect is that main is red against biome's current ruleset, and every PR inherits the failure.
Why the fix-retry loop can't resolve it
autoloop-program Target lists (e.g.
tsb-perf-evolve/program.md) correctly scope the agent to one file. The agent cannot — by design — reach intosrc/core/align.ts,astype.ts,natsort.ts,frame.ts,reindex.ts, ortests/window/**. The fix-retry loop from #176 will try; it will see every attempt blocked; it will eventually pause the program withci-fix-exhaustedor similar.The one violation within Target is
.autoloop/programs/tsb-perf-evolve/code/benchmark.ts:28:10 lint/nursery/useExplicitType. That one the agent can fix — and should. If it isn't, the fix-retry loop may only trigger on test/compile failures and is skipping lint failures (worth checking separately).Fix — two tracks, run in parallel
Track 1: Clean main
Get main green against the current biome ruleset:
If any of the
nurseryrules look like net-negative value for the codebase on review (nursery rules are, by biome's own definition, experimental), turn them off inbiome.jsonrather than fighting them:{ "linter": { "rules": { "nursery": { "noNestedTernary": "off", "useExplicitType": "off", "useImportRestrictions": "off" } } } }Nursery rules churn between biome releases; suppressing ones we don't want is defensive hygiene, not lint debt.
Track 2: Scope CI lint to changed files
Even after Track 1, biome's nursery group will keep surfacing new rules on upgrades. Protect autoloop (and humans) from being blocked by unrelated legacy violations by running lint against only the files the PR actually touched:
In
.github/workflows/ci.yml, change the lint step from:to something like:
Pair with a nightly job on
mainthat runs biome against the whole codebase and opens an issue (or comments on a tracking one) when new violations appear — so legacy violations don't quietly pile up forever, but they also don't block every in-flight PR.Alternatively, pin biome to a specific version in
package.jsonand explicitly update with a dedicated PR that fixes whatever new rules fire. Stops the silent rule churn.Acceptance
bun run lintonmainexits 0 (no violations, ornurseryrules turned off if we judge them not worth fighting).Related
githubnext/autoloop.