Skip to content

fix(engine): reorder cross-provider fallback to claude → copilot → gemini - #571

Merged
don-petry merged 10 commits into
mainfrom
fix/engine-fallback-order
Jun 12, 2026
Merged

fix(engine): reorder cross-provider fallback to claude → copilot → gemini#571
don-petry merged 10 commits into
mainfrom
fix/engine-fallback-order

Conversation

@don-petry

@don-petry don-petry commented Jun 11, 2026

Copy link
Copy Markdown
Collaborator

Why

The cross-provider rate-limit fallback chain was claude → gemini → copilot, so when Claude is exhausted it falls to Gemini before Copilot. With Gemini's prepayment credits depleted, that surfaced as hard 429 RESOURCE_EXHAUSTED failures (found by the post-implementation health check — markets dev-lead fix-bot-comment).

Per the intended engine preference — Claude default → Copilot → Gemini — Gemini should be the last resort. (Note: DEV_LEAD_ENGINE default is already claude and no override is set; the bug was purely the fallback order.)

Change

  • engine.sh run_writer_with_fallback (dev-lead path): loop order claude copilot gemini.
  • review-batch.sh (pr-review batch path): reorder the cascade so a Claude rate-limit falls to Copilot first, then Gemini; each engine's availability check travels with it.
  • Comments + bats updated to the new order (test_engine_fallback, test_provider_headroom); where a test specifically targets the Gemini fallback, Copilot is forced to skip via a classic-PAT token.

Validation

  • 22/22 engine bats pass (fallback + headroom); shellcheck clean (only pre-existing INFO notes).

Rollout

engine.sh is shared, so this ships via both agent releases: cut pr-review/vX + dev-lead/vX and promote both channels.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Chores

    • Changed provider fallback order on rate-limit from Claude → Gemini → Copilot to Claude → Copilot → Gemini; batch review flow now may prefer Copilot first and will skip a PR if final fallback isn’t available.
  • Tests

    • Updated unit tests to reflect the new provider fallback ordering and deterministic skip behavior.
  • Documentation / Config

    • Expanded security-scan allowlists and added docs/comments to suppress known false positives for example tokens and manifest checksums.

@don-petry
don-petry requested a review from a team as a code owner June 11, 2026 20:00
@coderabbitai

coderabbitai Bot commented Jun 11, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@don-petry, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 26 minutes and 46 seconds. Learn how PR review limits work.

Your organization has run out of usage credits. Purchase more credits in the billing tab to continue.

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: a0e82f1c-dc4c-491e-8ed8-c4951c78e01b

📥 Commits

Reviewing files that changed from the base of the PR and between 17168f3 and 11392e6.

📒 Files selected for processing (2)
  • .gitleaks.toml
  • scripts/review-batch.sh
📝 Walkthrough

Walkthrough

The PR reorders the AI engine fallback sequence from claude → gemini → copilot to claude → copilot → gemini, updating engine-layer iteration, batch orchestration, unit tests, and gitleaks allowlists/comments.

Changes

AI Engine Fallback Reordering

Layer / File(s) Summary
Engine-layer fallback reordering
scripts/engine.sh
Documentation comments (lines 21, 64, 1041) and the run_writer_with_fallback loop initialization (line 1051) are updated to sequence engines as claude → copilot → gemini on rate-limit.
Batch-level rate-limit orchestration
scripts/review-batch.sh
Engine fallback chain comment (line 10) and rate-limit handling logic (lines 160–199) are reworked to try Copilot first from Claude, handle Copilot “unavailable” exits (55/127) by attempting Gemini, and skip the PR when Gemini is unavailable.
Test updates validating new fallback sequence
tests/dev-lead/unit/test_engine_fallback.bats, tests/dev-lead/unit/test_provider_headroom.bats
Unit tests updated to reflect new fallback order; tests set COPILOT_GITHUB_TOKEN or ghp_stub where needed to force Copilot skipping so Gemini is reached and assertions match claude → copilot → gemini.
Gitleaks allowlists and docs comments
.gitleaks.toml
Adds documentation comments about example expired JWTs, a new allowlist rule for expiredToken in .claude/skills/**/resources/knowledge/api-testing-patterns.md, and expands _bmad/_config/files-manifest.csv allowlist regexes to include 64-hex SHA-256 digests.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 66.67% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and specifically describes the main change: reordering the cross-provider fallback sequence from claude → gemini → copilot to claude → copilot → gemini, which is the primary objective across all modified files.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/engine-fallback-order

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request updates the cross-provider fallback order from claude → gemini → copilot to claude → copilot → gemini across the engine and batch scripts, with corresponding updates to the test suites. The review feedback points out that using raw gh command checks to verify Copilot availability bypasses pre-flight checks and can cause runtime failures if unsupported classic PATs are used. It is recommended to use the pre-flight COPILOT_AVAILABLE flag and explicitly guard against ghp_* tokens to ensure a robust fallback to Gemini.

Comment thread scripts/review-batch.sh Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@scripts/review-batch.sh`:
- Around line 163-181: Replace the gh-based Copilot gate with the preflight
COPILOT_AVAILABLE flag and ensure Gemini is selected when Copilot is not
available or runtime returns fallback codes: check the COPILOT_AVAILABLE
env/flag before attempting the Copilot fallback (instead of `gh`), only run
`bash scripts/review-one-pr.sh` with REVIEW_ENGINE=copilot when
COPILOT_AVAILABLE is truthy, and on failure codes (55 or 127) or when
COPILOT_AVAILABLE is false set rc=2 and export REVIEW_ENGINE=gemini (update
engine_fallbacks/fallback_engines only when Copilot actually runs) so the
cascade proceeds to Gemini as intended.
- Around line 184-186: Change the fallback conditional that checks
rc/REVIEW_ENGINE/GEMINI_AVAILABLE to use the Bash conditional form [[ ... ]]
instead of [ ... ] (locate the if block that tests rc, REVIEW_ENGINE and
GEMINI_AVAILABLE), and ensure GEMINI_AVAILABLE is referenced with the
parameter-expansion default like ${GEMINI_AVAILABLE:-false} inside the [[ ...
]]; also run ShellCheck with -x to follow sourced scripts (validate_engines.sh,
engine.sh) so SC1091 warnings are suppressed during CI validation.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 599a74b7-a08d-4413-8b60-aff20fe437fd

📥 Commits

Reviewing files that changed from the base of the PR and between 803e63f and 70fc2fa.

📒 Files selected for processing (4)
  • scripts/engine.sh
  • scripts/review-batch.sh
  • tests/dev-lead/unit/test_engine_fallback.bats
  • tests/dev-lead/unit/test_provider_headroom.bats

Comment thread scripts/review-batch.sh Outdated
Comment thread scripts/review-batch.sh Outdated
@don-petry

Copy link
Copy Markdown
Collaborator Author

@coderabbitai resolve

@don-petry

Copy link
Copy Markdown
Collaborator Author

Dev-Lead — review-changes (applied)

Changes committed and pushed.

@don-petry
don-petry enabled auto-merge (squash) June 11, 2026 20:16
coderabbitai[bot]
coderabbitai Bot previously approved these changes Jun 11, 2026
@coderabbitai

coderabbitai Bot commented Jun 11, 2026

Copy link
Copy Markdown
✅ Action performed

Comments resolved and changes approved.

@don-petry
don-petry disabled auto-merge June 11, 2026 20:17
@don-petry

Copy link
Copy Markdown
Collaborator Author

Dev-Lead — fix-bot-comment (applied)

Changes committed and pushed.

@don-petry

Copy link
Copy Markdown
Collaborator Author

Dev-Lead — review-changes (applied)

Changes committed and pushed.

@don-petry
don-petry enabled auto-merge (squash) June 11, 2026 20:29
coderabbitai[bot]
coderabbitai Bot previously approved these changes Jun 11, 2026
@don-petry
don-petry disabled auto-merge June 11, 2026 20:30
@don-petry

Copy link
Copy Markdown
Collaborator Author

Dev-Lead — review-changes (no-changes)

No changes were needed for this PR.

@don-petry
don-petry enabled auto-merge (squash) June 11, 2026 20:35
@don-petry
don-petry disabled auto-merge June 11, 2026 21:31
@don-petry

Copy link
Copy Markdown
Collaborator Author

Dev-Lead — review-changes (no-changes)

No changes were needed for this PR.

@don-petry
don-petry enabled auto-merge (squash) June 11, 2026 21:33
@don-petry

Copy link
Copy Markdown
Collaborator Author

Auto-rebase failed — merge conflict — this branch has conflicts with main that must be resolved.

Claude will attempt to resolve this automatically. If it cannot, a follow-up comment will explain what needs manual attention.

To resolve manually instead:

git fetch origin
git merge origin/main
# resolve conflicts, then:
git add .
git commit
git push

@don-petry

Copy link
Copy Markdown
Collaborator Author

Dev-Lead — rebase (no-changes)

Agent reasoning
PR: #571
Rebased onto: main
Conflicts resolved: 1 file
- .gitleaks.toml: HEAD had a broad commit-SHA-based suppression for bda766be;
  PR (d0c3c37) replaced it with two targeted path+regex allowlists (JWT in
  api-testing-patterns.md, SHA256 hashes in files-manifest.csv). Kept the
  PR version per the "prefer PR changes" constraint.
Push: success
```

@don-petry
don-petry enabled auto-merge (squash) June 11, 2026 21:42
don-petry added a commit that referenced this pull request Jun 23, 2026
…mini (#571)

* fix(engine): reorder cross-provider fallback to claude -> copilot -> gemini

The cross-provider rate-limit fallback was claude -> gemini -> copilot, so when
Claude was exhausted it fell back to Gemini *before* Copilot. With Gemini's
prepayment credits depleted, that surfaced as hard 429 RESOURCE_EXHAUSTED
failures (observed on markets dev-lead fix-bot-comment). Per the intended
engine preference — Claude default, then Copilot, then Gemini — make Gemini the
last resort.

- engine.sh run_writer_with_fallback: loop order claude copilot gemini (dev-lead path).
- review-batch.sh: reorder the cascade so Claude rate-limit falls to Copilot first,
  then Gemini (pr-review batch path); availability checks travel with each engine.
- Update comments + bats (test_engine_fallback, test_provider_headroom) to the new
  order; force copilot-skip via a classic-PAT token where a test targets the
  Gemini fallback specifically. 22/22 engine tests pass; shellcheck clean.

Shared engine.sh affects BOTH agents → ship via pr-review + dev-lead releases.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* chore: apply manual instructions [skip ci-relay]

* fix(bot): address bot feedback [skip ci-relay]

* chore: apply manual instructions [skip ci-relay]

* fix(tests): skip copilot fallback in writer tests after claude → copilot → gemini reorder

Tests 152 and 168 in test_engine_writer.bats expected run_writer_with_fallback
to reach gemini when claude is rate-limited. With the new fallback order
(claude → copilot → gemini), copilot is tried first; without GH_TOKEN or
COPILOT_GITHUB_TOKEN set, copilot_chat returns 1 (not 2/127) and halts fallback
propagation before gemini is reached. Add `COPILOT_GITHUB_TOKEN=ghp_stub` (a
classic-PAT prefix) to both tests so the copilot leg is skipped, matching the
same approach used in test_engine_fallback.bats.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(bot): address bot feedback [skip ci-relay]

* fix(bot): address bot feedback [skip ci-relay]

---------

Co-authored-by: donpetry-bot <{}+donpetry-bot@users.noreply.github.com>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Co-authored-by: donpetry-bot <281750570+donpetry-bot@users.noreply.github.com>
don-petry added a commit that referenced this pull request Jun 23, 2026
…mini (#571)

* fix(engine): reorder cross-provider fallback to claude -> copilot -> gemini

The cross-provider rate-limit fallback was claude -> gemini -> copilot, so when
Claude was exhausted it fell back to Gemini *before* Copilot. With Gemini's
prepayment credits depleted, that surfaced as hard 429 RESOURCE_EXHAUSTED
failures (observed on markets dev-lead fix-bot-comment). Per the intended
engine preference — Claude default, then Copilot, then Gemini — make Gemini the
last resort.

- engine.sh run_writer_with_fallback: loop order claude copilot gemini (dev-lead path).
- review-batch.sh: reorder the cascade so Claude rate-limit falls to Copilot first,
  then Gemini (pr-review batch path); availability checks travel with each engine.
- Update comments + bats (test_engine_fallback, test_provider_headroom) to the new
  order; force copilot-skip via a classic-PAT token where a test targets the
  Gemini fallback specifically. 22/22 engine tests pass; shellcheck clean.

Shared engine.sh affects BOTH agents → ship via pr-review + dev-lead releases.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* chore: apply manual instructions [skip ci-relay]

* fix(bot): address bot feedback [skip ci-relay]

* chore: apply manual instructions [skip ci-relay]

* fix(tests): skip copilot fallback in writer tests after claude → copilot → gemini reorder

Tests 152 and 168 in test_engine_writer.bats expected run_writer_with_fallback
to reach gemini when claude is rate-limited. With the new fallback order
(claude → copilot → gemini), copilot is tried first; without GH_TOKEN or
COPILOT_GITHUB_TOKEN set, copilot_chat returns 1 (not 2/127) and halts fallback
propagation before gemini is reached. Add `COPILOT_GITHUB_TOKEN=ghp_stub` (a
classic-PAT prefix) to both tests so the copilot leg is skipped, matching the
same approach used in test_engine_fallback.bats.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(bot): address bot feedback [skip ci-relay]

* fix(bot): address bot feedback [skip ci-relay]

---------

Co-authored-by: donpetry-bot <{}+donpetry-bot@users.noreply.github.com>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Co-authored-by: donpetry-bot <281750570+donpetry-bot@users.noreply.github.com>
don-petry added a commit that referenced this pull request Jun 23, 2026
…mini (#571)

* fix(engine): reorder cross-provider fallback to claude -> copilot -> gemini

The cross-provider rate-limit fallback was claude -> gemini -> copilot, so when
Claude was exhausted it fell back to Gemini *before* Copilot. With Gemini's
prepayment credits depleted, that surfaced as hard 429 RESOURCE_EXHAUSTED
failures (observed on markets dev-lead fix-bot-comment). Per the intended
engine preference — Claude default, then Copilot, then Gemini — make Gemini the
last resort.

- engine.sh run_writer_with_fallback: loop order claude copilot gemini (dev-lead path).
- review-batch.sh: reorder the cascade so Claude rate-limit falls to Copilot first,
  then Gemini (pr-review batch path); availability checks travel with each engine.
- Update comments + bats (test_engine_fallback, test_provider_headroom) to the new
  order; force copilot-skip via a classic-PAT token where a test targets the
  Gemini fallback specifically. 22/22 engine tests pass; shellcheck clean.

Shared engine.sh affects BOTH agents → ship via pr-review + dev-lead releases.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* chore: apply manual instructions [skip ci-relay]

* fix(bot): address bot feedback [skip ci-relay]

* chore: apply manual instructions [skip ci-relay]

* fix(tests): skip copilot fallback in writer tests after claude → copilot → gemini reorder

Tests 152 and 168 in test_engine_writer.bats expected run_writer_with_fallback
to reach gemini when claude is rate-limited. With the new fallback order
(claude → copilot → gemini), copilot is tried first; without GH_TOKEN or
COPILOT_GITHUB_TOKEN set, copilot_chat returns 1 (not 2/127) and halts fallback
propagation before gemini is reached. Add `COPILOT_GITHUB_TOKEN=ghp_stub` (a
classic-PAT prefix) to both tests so the copilot leg is skipped, matching the
same approach used in test_engine_fallback.bats.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(bot): address bot feedback [skip ci-relay]

* fix(bot): address bot feedback [skip ci-relay]

---------

Co-authored-by: donpetry-bot <{}+donpetry-bot@users.noreply.github.com>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Co-authored-by: donpetry-bot <281750570+donpetry-bot@users.noreply.github.com>
don-petry added a commit that referenced this pull request Jun 25, 2026
…mini (#571)

* fix(engine): reorder cross-provider fallback to claude -> copilot -> gemini

The cross-provider rate-limit fallback was claude -> gemini -> copilot, so when
Claude was exhausted it fell back to Gemini *before* Copilot. With Gemini's
prepayment credits depleted, that surfaced as hard 429 RESOURCE_EXHAUSTED
failures (observed on markets dev-lead fix-bot-comment). Per the intended
engine preference — Claude default, then Copilot, then Gemini — make Gemini the
last resort.

- engine.sh run_writer_with_fallback: loop order claude copilot gemini (dev-lead path).
- review-batch.sh: reorder the cascade so Claude rate-limit falls to Copilot first,
  then Gemini (pr-review batch path); availability checks travel with each engine.
- Update comments + bats (test_engine_fallback, test_provider_headroom) to the new
  order; force copilot-skip via a classic-PAT token where a test targets the
  Gemini fallback specifically. 22/22 engine tests pass; shellcheck clean.

Shared engine.sh affects BOTH agents → ship via pr-review + dev-lead releases.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* chore: apply manual instructions [skip ci-relay]

* fix(bot): address bot feedback [skip ci-relay]

* chore: apply manual instructions [skip ci-relay]

* fix(tests): skip copilot fallback in writer tests after claude → copilot → gemini reorder

Tests 152 and 168 in test_engine_writer.bats expected run_writer_with_fallback
to reach gemini when claude is rate-limited. With the new fallback order
(claude → copilot → gemini), copilot is tried first; without GH_TOKEN or
COPILOT_GITHUB_TOKEN set, copilot_chat returns 1 (not 2/127) and halts fallback
propagation before gemini is reached. Add `COPILOT_GITHUB_TOKEN=ghp_stub` (a
classic-PAT prefix) to both tests so the copilot leg is skipped, matching the
same approach used in test_engine_fallback.bats.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(bot): address bot feedback [skip ci-relay]

* fix(bot): address bot feedback [skip ci-relay]

---------

Co-authored-by: donpetry-bot <{}+donpetry-bot@users.noreply.github.com>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Co-authored-by: donpetry-bot <281750570+donpetry-bot@users.noreply.github.com>
don-petry added a commit that referenced this pull request Jun 25, 2026
…mini (#571)

* fix(engine): reorder cross-provider fallback to claude -> copilot -> gemini

The cross-provider rate-limit fallback was claude -> gemini -> copilot, so when
Claude was exhausted it fell back to Gemini *before* Copilot. With Gemini's
prepayment credits depleted, that surfaced as hard 429 RESOURCE_EXHAUSTED
failures (observed on markets dev-lead fix-bot-comment). Per the intended
engine preference — Claude default, then Copilot, then Gemini — make Gemini the
last resort.

- engine.sh run_writer_with_fallback: loop order claude copilot gemini (dev-lead path).
- review-batch.sh: reorder the cascade so Claude rate-limit falls to Copilot first,
  then Gemini (pr-review batch path); availability checks travel with each engine.
- Update comments + bats (test_engine_fallback, test_provider_headroom) to the new
  order; force copilot-skip via a classic-PAT token where a test targets the
  Gemini fallback specifically. 22/22 engine tests pass; shellcheck clean.

Shared engine.sh affects BOTH agents → ship via pr-review + dev-lead releases.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* chore: apply manual instructions [skip ci-relay]

* fix(bot): address bot feedback [skip ci-relay]

* chore: apply manual instructions [skip ci-relay]

* fix(tests): skip copilot fallback in writer tests after claude → copilot → gemini reorder

Tests 152 and 168 in test_engine_writer.bats expected run_writer_with_fallback
to reach gemini when claude is rate-limited. With the new fallback order
(claude → copilot → gemini), copilot is tried first; without GH_TOKEN or
COPILOT_GITHUB_TOKEN set, copilot_chat returns 1 (not 2/127) and halts fallback
propagation before gemini is reached. Add `COPILOT_GITHUB_TOKEN=ghp_stub` (a
classic-PAT prefix) to both tests so the copilot leg is skipped, matching the
same approach used in test_engine_fallback.bats.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(bot): address bot feedback [skip ci-relay]

* fix(bot): address bot feedback [skip ci-relay]

---------

Co-authored-by: donpetry-bot <{}+donpetry-bot@users.noreply.github.com>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Co-authored-by: donpetry-bot <281750570+donpetry-bot@users.noreply.github.com>
don-petry added a commit that referenced this pull request Jun 25, 2026
…mini (#571)

* fix(engine): reorder cross-provider fallback to claude -> copilot -> gemini

The cross-provider rate-limit fallback was claude -> gemini -> copilot, so when
Claude was exhausted it fell back to Gemini *before* Copilot. With Gemini's
prepayment credits depleted, that surfaced as hard 429 RESOURCE_EXHAUSTED
failures (observed on markets dev-lead fix-bot-comment). Per the intended
engine preference — Claude default, then Copilot, then Gemini — make Gemini the
last resort.

- engine.sh run_writer_with_fallback: loop order claude copilot gemini (dev-lead path).
- review-batch.sh: reorder the cascade so Claude rate-limit falls to Copilot first,
  then Gemini (pr-review batch path); availability checks travel with each engine.
- Update comments + bats (test_engine_fallback, test_provider_headroom) to the new
  order; force copilot-skip via a classic-PAT token where a test targets the
  Gemini fallback specifically. 22/22 engine tests pass; shellcheck clean.

Shared engine.sh affects BOTH agents → ship via pr-review + dev-lead releases.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* chore: apply manual instructions [skip ci-relay]

* fix(bot): address bot feedback [skip ci-relay]

* chore: apply manual instructions [skip ci-relay]

* fix(tests): skip copilot fallback in writer tests after claude → copilot → gemini reorder

Tests 152 and 168 in test_engine_writer.bats expected run_writer_with_fallback
to reach gemini when claude is rate-limited. With the new fallback order
(claude → copilot → gemini), copilot is tried first; without GH_TOKEN or
COPILOT_GITHUB_TOKEN set, copilot_chat returns 1 (not 2/127) and halts fallback
propagation before gemini is reached. Add `COPILOT_GITHUB_TOKEN=ghp_stub` (a
classic-PAT prefix) to both tests so the copilot leg is skipped, matching the
same approach used in test_engine_fallback.bats.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(bot): address bot feedback [skip ci-relay]

* fix(bot): address bot feedback [skip ci-relay]

---------

Co-authored-by: donpetry-bot <{}+donpetry-bot@users.noreply.github.com>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Co-authored-by: donpetry-bot <281750570+donpetry-bot@users.noreply.github.com>
don-petry pushed a commit that referenced this pull request Jul 4, 2026
The compliance test encoded the pre-#571 contract — it required the reusable
`with:` to source target_discussion/enhance_backlog from `${{ inputs.* }}`, the
exact pattern that fails at workflow setup on the discussion trigger. Update the
assertions to the prep-routed shape (needs.prep.outputs.*, booleans via fromJSON)
and add a guard that no reusable `with:` value references the `inputs` context.

Refs: petry-projects/.github#571
don-petry added a commit that referenced this pull request Jul 4, 2026
…1113)

* fix(feature-ideation): route caller inputs through a prep job (#571)

This repo's feature-ideation caller carried the same #571 defect fixed in the
central template (petry-projects/.github#615): the `ideate` job's reusable
`with:` referenced `${{ inputs.* }}`, which is evaluated at workflow setup
regardless of the job `if:` and so fails the whole run (zero jobs) on the
`discussion: created` trigger — the exact path that auto-enhances new Ideas.

Resolve dispatch inputs in a gated `prep` job and pass them to `ideate` via
`needs.prep.outputs.*` (booleans via fromJSON). The `feature-ideation/next`
channel pin is unchanged. As the `next` ring this dogfoods the fix ahead of the
fleet rollout tracked in petry-projects/.github#614.

Refs: petry-projects/.github#571, petry-projects/.github#614

* test(feature-ideation): assert prep-routed inputs, add #571 guard

The compliance test encoded the pre-#571 contract — it required the reusable
`with:` to source target_discussion/enhance_backlog from `${{ inputs.* }}`, the
exact pattern that fails at workflow setup on the discussion trigger. Update the
assertions to the prep-routed shape (needs.prep.outputs.*, booleans via fromJSON)
and add a guard that no reusable `with:` value references the `inputs` context.

Refs: petry-projects/.github#571

---------

Co-authored-by: donpetry-bot <{}+donpetry-bot@users.noreply.github.com>
don-petry added a commit that referenced this pull request Aug 2, 2026
…mini (#571)

* fix(engine): reorder cross-provider fallback to claude -> copilot -> gemini

The cross-provider rate-limit fallback was claude -> gemini -> copilot, so when
Claude was exhausted it fell back to Gemini *before* Copilot. With Gemini's
prepayment credits depleted, that surfaced as hard 429 RESOURCE_EXHAUSTED
failures (observed on markets dev-lead fix-bot-comment). Per the intended
engine preference — Claude default, then Copilot, then Gemini — make Gemini the
last resort.

- engine.sh run_writer_with_fallback: loop order claude copilot gemini (dev-lead path).
- review-batch.sh: reorder the cascade so Claude rate-limit falls to Copilot first,
  then Gemini (pr-review batch path); availability checks travel with each engine.
- Update comments + bats (test_engine_fallback, test_provider_headroom) to the new
  order; force copilot-skip via a classic-PAT token where a test targets the
  Gemini fallback specifically. 22/22 engine tests pass; shellcheck clean.

Shared engine.sh affects BOTH agents → ship via pr-review + dev-lead releases.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* chore: apply manual instructions [skip ci-relay]

* fix(bot): address bot feedback [skip ci-relay]

* chore: apply manual instructions [skip ci-relay]

* fix(tests): skip copilot fallback in writer tests after claude → copilot → gemini reorder

Tests 152 and 168 in test_engine_writer.bats expected run_writer_with_fallback
to reach gemini when claude is rate-limited. With the new fallback order
(claude → copilot → gemini), copilot is tried first; without GH_TOKEN or
COPILOT_GITHUB_TOKEN set, copilot_chat returns 1 (not 2/127) and halts fallback
propagation before gemini is reached. Add `COPILOT_GITHUB_TOKEN=ghp_stub` (a
classic-PAT prefix) to both tests so the copilot leg is skipped, matching the
same approach used in test_engine_fallback.bats.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(bot): address bot feedback [skip ci-relay]

* fix(bot): address bot feedback [skip ci-relay]

---------

Co-authored-by: donpetry-bot <{}+donpetry-bot@users.noreply.github.com>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Co-authored-by: donpetry-bot <281750570+donpetry-bot@users.noreply.github.com>
don-petry added a commit that referenced this pull request Aug 2, 2026
…1113)

* fix(feature-ideation): route caller inputs through a prep job (#571)

This repo's feature-ideation caller carried the same #571 defect fixed in the
central template (petry-projects/.github#615): the `ideate` job's reusable
`with:` referenced `${{ inputs.* }}`, which is evaluated at workflow setup
regardless of the job `if:` and so fails the whole run (zero jobs) on the
`discussion: created` trigger — the exact path that auto-enhances new Ideas.

Resolve dispatch inputs in a gated `prep` job and pass them to `ideate` via
`needs.prep.outputs.*` (booleans via fromJSON). The `feature-ideation/next`
channel pin is unchanged. As the `next` ring this dogfoods the fix ahead of the
fleet rollout tracked in petry-projects/.github#614.

Refs: petry-projects/.github#571, petry-projects/.github#614

* test(feature-ideation): assert prep-routed inputs, add #571 guard

The compliance test encoded the pre-#571 contract — it required the reusable
`with:` to source target_discussion/enhance_backlog from `${{ inputs.* }}`, the
exact pattern that fails at workflow setup on the discussion trigger. Update the
assertions to the prep-routed shape (needs.prep.outputs.*, booleans via fromJSON)
and add a guard that no reusable `with:` value references the `inputs` context.

Refs: petry-projects/.github#571

---------

Co-authored-by: donpetry-bot <{}+donpetry-bot@users.noreply.github.com>
don-petry added a commit that referenced this pull request Aug 3, 2026
…mini (#571)

* fix(engine): reorder cross-provider fallback to claude -> copilot -> gemini

The cross-provider rate-limit fallback was claude -> gemini -> copilot, so when
Claude was exhausted it fell back to Gemini *before* Copilot. With Gemini's
prepayment credits depleted, that surfaced as hard 429 RESOURCE_EXHAUSTED
failures (observed on markets dev-lead fix-bot-comment). Per the intended
engine preference — Claude default, then Copilot, then Gemini — make Gemini the
last resort.

- engine.sh run_writer_with_fallback: loop order claude copilot gemini (dev-lead path).
- review-batch.sh: reorder the cascade so Claude rate-limit falls to Copilot first,
  then Gemini (pr-review batch path); availability checks travel with each engine.
- Update comments + bats (test_engine_fallback, test_provider_headroom) to the new
  order; force copilot-skip via a classic-PAT token where a test targets the
  Gemini fallback specifically. 22/22 engine tests pass; shellcheck clean.

Shared engine.sh affects BOTH agents → ship via pr-review + dev-lead releases.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* chore: apply manual instructions [skip ci-relay]

* fix(bot): address bot feedback [skip ci-relay]

* chore: apply manual instructions [skip ci-relay]

* fix(tests): skip copilot fallback in writer tests after claude → copilot → gemini reorder

Tests 152 and 168 in test_engine_writer.bats expected run_writer_with_fallback
to reach gemini when claude is rate-limited. With the new fallback order
(claude → copilot → gemini), copilot is tried first; without GH_TOKEN or
COPILOT_GITHUB_TOKEN set, copilot_chat returns 1 (not 2/127) and halts fallback
propagation before gemini is reached. Add `COPILOT_GITHUB_TOKEN=ghp_stub` (a
classic-PAT prefix) to both tests so the copilot leg is skipped, matching the
same approach used in test_engine_fallback.bats.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(bot): address bot feedback [skip ci-relay]

* fix(bot): address bot feedback [skip ci-relay]

---------

Co-authored-by: donpetry-bot <{}+donpetry-bot@users.noreply.github.com>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Co-authored-by: donpetry-bot <281750570+donpetry-bot@users.noreply.github.com>
don-petry added a commit that referenced this pull request Aug 3, 2026
…1113)

* fix(feature-ideation): route caller inputs through a prep job (#571)

This repo's feature-ideation caller carried the same #571 defect fixed in the
central template (petry-projects/.github#615): the `ideate` job's reusable
`with:` referenced `${{ inputs.* }}`, which is evaluated at workflow setup
regardless of the job `if:` and so fails the whole run (zero jobs) on the
`discussion: created` trigger — the exact path that auto-enhances new Ideas.

Resolve dispatch inputs in a gated `prep` job and pass them to `ideate` via
`needs.prep.outputs.*` (booleans via fromJSON). The `feature-ideation/next`
channel pin is unchanged. As the `next` ring this dogfoods the fix ahead of the
fleet rollout tracked in petry-projects/.github#614.

Refs: petry-projects/.github#571, petry-projects/.github#614

* test(feature-ideation): assert prep-routed inputs, add #571 guard

The compliance test encoded the pre-#571 contract — it required the reusable
`with:` to source target_discussion/enhance_backlog from `${{ inputs.* }}`, the
exact pattern that fails at workflow setup on the discussion trigger. Update the
assertions to the prep-routed shape (needs.prep.outputs.*, booleans via fromJSON)
and add a guard that no reusable `with:` value references the `inputs` context.

Refs: petry-projects/.github#571

---------

Co-authored-by: donpetry-bot <{}+donpetry-bot@users.noreply.github.com>
don-petry added a commit that referenced this pull request Aug 3, 2026
…mini (#571)

* fix(engine): reorder cross-provider fallback to claude -> copilot -> gemini

The cross-provider rate-limit fallback was claude -> gemini -> copilot, so when
Claude was exhausted it fell back to Gemini *before* Copilot. With Gemini's
prepayment credits depleted, that surfaced as hard 429 RESOURCE_EXHAUSTED
failures (observed on markets dev-lead fix-bot-comment). Per the intended
engine preference — Claude default, then Copilot, then Gemini — make Gemini the
last resort.

- engine.sh run_writer_with_fallback: loop order claude copilot gemini (dev-lead path).
- review-batch.sh: reorder the cascade so Claude rate-limit falls to Copilot first,
  then Gemini (pr-review batch path); availability checks travel with each engine.
- Update comments + bats (test_engine_fallback, test_provider_headroom) to the new
  order; force copilot-skip via a classic-PAT token where a test targets the
  Gemini fallback specifically. 22/22 engine tests pass; shellcheck clean.

Shared engine.sh affects BOTH agents → ship via pr-review + dev-lead releases.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* chore: apply manual instructions [skip ci-relay]

* fix(bot): address bot feedback [skip ci-relay]

* chore: apply manual instructions [skip ci-relay]

* fix(tests): skip copilot fallback in writer tests after claude → copilot → gemini reorder

Tests 152 and 168 in test_engine_writer.bats expected run_writer_with_fallback
to reach gemini when claude is rate-limited. With the new fallback order
(claude → copilot → gemini), copilot is tried first; without GH_TOKEN or
COPILOT_GITHUB_TOKEN set, copilot_chat returns 1 (not 2/127) and halts fallback
propagation before gemini is reached. Add `COPILOT_GITHUB_TOKEN=ghp_stub` (a
classic-PAT prefix) to both tests so the copilot leg is skipped, matching the
same approach used in test_engine_fallback.bats.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(bot): address bot feedback [skip ci-relay]

* fix(bot): address bot feedback [skip ci-relay]

---------

Co-authored-by: donpetry-bot <{}+donpetry-bot@users.noreply.github.com>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Co-authored-by: donpetry-bot <281750570+donpetry-bot@users.noreply.github.com>
don-petry added a commit that referenced this pull request Aug 3, 2026
…1113)

* fix(feature-ideation): route caller inputs through a prep job (#571)

This repo's feature-ideation caller carried the same #571 defect fixed in the
central template (petry-projects/.github#615): the `ideate` job's reusable
`with:` referenced `${{ inputs.* }}`, which is evaluated at workflow setup
regardless of the job `if:` and so fails the whole run (zero jobs) on the
`discussion: created` trigger — the exact path that auto-enhances new Ideas.

Resolve dispatch inputs in a gated `prep` job and pass them to `ideate` via
`needs.prep.outputs.*` (booleans via fromJSON). The `feature-ideation/next`
channel pin is unchanged. As the `next` ring this dogfoods the fix ahead of the
fleet rollout tracked in petry-projects/.github#614.

Refs: petry-projects/.github#571, petry-projects/.github#614

* test(feature-ideation): assert prep-routed inputs, add #571 guard

The compliance test encoded the pre-#571 contract — it required the reusable
`with:` to source target_discussion/enhance_backlog from `${{ inputs.* }}`, the
exact pattern that fails at workflow setup on the discussion trigger. Update the
assertions to the prep-routed shape (needs.prep.outputs.*, booleans via fromJSON)
and add a guard that no reusable `with:` value references the `inputs` context.

Refs: petry-projects/.github#571

---------

Co-authored-by: donpetry-bot <{}+donpetry-bot@users.noreply.github.com>
don-petry added a commit that referenced this pull request Aug 7, 2026
…mini (#571)

* fix(engine): reorder cross-provider fallback to claude -> copilot -> gemini

The cross-provider rate-limit fallback was claude -> gemini -> copilot, so when
Claude was exhausted it fell back to Gemini *before* Copilot. With Gemini's
prepayment credits depleted, that surfaced as hard 429 RESOURCE_EXHAUSTED
failures (observed on markets dev-lead fix-bot-comment). Per the intended
engine preference — Claude default, then Copilot, then Gemini — make Gemini the
last resort.

- engine.sh run_writer_with_fallback: loop order claude copilot gemini (dev-lead path).
- review-batch.sh: reorder the cascade so Claude rate-limit falls to Copilot first,
  then Gemini (pr-review batch path); availability checks travel with each engine.
- Update comments + bats (test_engine_fallback, test_provider_headroom) to the new
  order; force copilot-skip via a classic-PAT token where a test targets the
  Gemini fallback specifically. 22/22 engine tests pass; shellcheck clean.

Shared engine.sh affects BOTH agents → ship via pr-review + dev-lead releases.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* chore: apply manual instructions [skip ci-relay]

* fix(bot): address bot feedback [skip ci-relay]

* chore: apply manual instructions [skip ci-relay]

* fix(tests): skip copilot fallback in writer tests after claude → copilot → gemini reorder

Tests 152 and 168 in test_engine_writer.bats expected run_writer_with_fallback
to reach gemini when claude is rate-limited. With the new fallback order
(claude → copilot → gemini), copilot is tried first; without GH_TOKEN or
COPILOT_GITHUB_TOKEN set, copilot_chat returns 1 (not 2/127) and halts fallback
propagation before gemini is reached. Add `COPILOT_GITHUB_TOKEN=ghp_stub` (a
classic-PAT prefix) to both tests so the copilot leg is skipped, matching the
same approach used in test_engine_fallback.bats.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(bot): address bot feedback [skip ci-relay]

* fix(bot): address bot feedback [skip ci-relay]

---------

Co-authored-by: donpetry-bot <{}+donpetry-bot@users.noreply.github.com>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Co-authored-by: donpetry-bot <281750570+donpetry-bot@users.noreply.github.com>
don-petry added a commit that referenced this pull request Aug 7, 2026
…1113)

* fix(feature-ideation): route caller inputs through a prep job (#571)

This repo's feature-ideation caller carried the same #571 defect fixed in the
central template (petry-projects/.github#615): the `ideate` job's reusable
`with:` referenced `${{ inputs.* }}`, which is evaluated at workflow setup
regardless of the job `if:` and so fails the whole run (zero jobs) on the
`discussion: created` trigger — the exact path that auto-enhances new Ideas.

Resolve dispatch inputs in a gated `prep` job and pass them to `ideate` via
`needs.prep.outputs.*` (booleans via fromJSON). The `feature-ideation/next`
channel pin is unchanged. As the `next` ring this dogfoods the fix ahead of the
fleet rollout tracked in petry-projects/.github#614.

Refs: petry-projects/.github#571, petry-projects/.github#614

* test(feature-ideation): assert prep-routed inputs, add #571 guard

The compliance test encoded the pre-#571 contract — it required the reusable
`with:` to source target_discussion/enhance_backlog from `${{ inputs.* }}`, the
exact pattern that fails at workflow setup on the discussion trigger. Update the
assertions to the prep-routed shape (needs.prep.outputs.*, booleans via fromJSON)
and add a guard that no reusable `with:` value references the `inputs` context.

Refs: petry-projects/.github#571

---------

Co-authored-by: donpetry-bot <{}+donpetry-bot@users.noreply.github.com>
don-petry added a commit that referenced this pull request Aug 7, 2026
…mini (#571)

* fix(engine): reorder cross-provider fallback to claude -> copilot -> gemini

The cross-provider rate-limit fallback was claude -> gemini -> copilot, so when
Claude was exhausted it fell back to Gemini *before* Copilot. With Gemini's
prepayment credits depleted, that surfaced as hard 429 RESOURCE_EXHAUSTED
failures (observed on markets dev-lead fix-bot-comment). Per the intended
engine preference — Claude default, then Copilot, then Gemini — make Gemini the
last resort.

- engine.sh run_writer_with_fallback: loop order claude copilot gemini (dev-lead path).
- review-batch.sh: reorder the cascade so Claude rate-limit falls to Copilot first,
  then Gemini (pr-review batch path); availability checks travel with each engine.
- Update comments + bats (test_engine_fallback, test_provider_headroom) to the new
  order; force copilot-skip via a classic-PAT token where a test targets the
  Gemini fallback specifically. 22/22 engine tests pass; shellcheck clean.

Shared engine.sh affects BOTH agents → ship via pr-review + dev-lead releases.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* chore: apply manual instructions [skip ci-relay]

* fix(bot): address bot feedback [skip ci-relay]

* chore: apply manual instructions [skip ci-relay]

* fix(tests): skip copilot fallback in writer tests after claude → copilot → gemini reorder

Tests 152 and 168 in test_engine_writer.bats expected run_writer_with_fallback
to reach gemini when claude is rate-limited. With the new fallback order
(claude → copilot → gemini), copilot is tried first; without GH_TOKEN or
COPILOT_GITHUB_TOKEN set, copilot_chat returns 1 (not 2/127) and halts fallback
propagation before gemini is reached. Add `COPILOT_GITHUB_TOKEN=ghp_stub` (a
classic-PAT prefix) to both tests so the copilot leg is skipped, matching the
same approach used in test_engine_fallback.bats.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(bot): address bot feedback [skip ci-relay]

* fix(bot): address bot feedback [skip ci-relay]

---------

Co-authored-by: donpetry-bot <{}+donpetry-bot@users.noreply.github.com>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Co-authored-by: donpetry-bot <281750570+donpetry-bot@users.noreply.github.com>
don-petry added a commit that referenced this pull request Aug 7, 2026
…1113)

* fix(feature-ideation): route caller inputs through a prep job (#571)

This repo's feature-ideation caller carried the same #571 defect fixed in the
central template (petry-projects/.github#615): the `ideate` job's reusable
`with:` referenced `${{ inputs.* }}`, which is evaluated at workflow setup
regardless of the job `if:` and so fails the whole run (zero jobs) on the
`discussion: created` trigger — the exact path that auto-enhances new Ideas.

Resolve dispatch inputs in a gated `prep` job and pass them to `ideate` via
`needs.prep.outputs.*` (booleans via fromJSON). The `feature-ideation/next`
channel pin is unchanged. As the `next` ring this dogfoods the fix ahead of the
fleet rollout tracked in petry-projects/.github#614.

Refs: petry-projects/.github#571, petry-projects/.github#614

* test(feature-ideation): assert prep-routed inputs, add #571 guard

The compliance test encoded the pre-#571 contract — it required the reusable
`with:` to source target_discussion/enhance_backlog from `${{ inputs.* }}`, the
exact pattern that fails at workflow setup on the discussion trigger. Update the
assertions to the prep-routed shape (needs.prep.outputs.*, booleans via fromJSON)
and add a guard that no reusable `with:` value references the `inputs` context.

Refs: petry-projects/.github#571

---------

Co-authored-by: donpetry-bot <{}+donpetry-bot@users.noreply.github.com>
don-petry added a commit that referenced this pull request Aug 7, 2026
…mini (#571)

* fix(engine): reorder cross-provider fallback to claude -> copilot -> gemini

The cross-provider rate-limit fallback was claude -> gemini -> copilot, so when
Claude was exhausted it fell back to Gemini *before* Copilot. With Gemini's
prepayment credits depleted, that surfaced as hard 429 RESOURCE_EXHAUSTED
failures (observed on markets dev-lead fix-bot-comment). Per the intended
engine preference — Claude default, then Copilot, then Gemini — make Gemini the
last resort.

- engine.sh run_writer_with_fallback: loop order claude copilot gemini (dev-lead path).
- review-batch.sh: reorder the cascade so Claude rate-limit falls to Copilot first,
  then Gemini (pr-review batch path); availability checks travel with each engine.
- Update comments + bats (test_engine_fallback, test_provider_headroom) to the new
  order; force copilot-skip via a classic-PAT token where a test targets the
  Gemini fallback specifically. 22/22 engine tests pass; shellcheck clean.

Shared engine.sh affects BOTH agents → ship via pr-review + dev-lead releases.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* chore: apply manual instructions [skip ci-relay]

* fix(bot): address bot feedback [skip ci-relay]

* chore: apply manual instructions [skip ci-relay]

* fix(tests): skip copilot fallback in writer tests after claude → copilot → gemini reorder

Tests 152 and 168 in test_engine_writer.bats expected run_writer_with_fallback
to reach gemini when claude is rate-limited. With the new fallback order
(claude → copilot → gemini), copilot is tried first; without GH_TOKEN or
COPILOT_GITHUB_TOKEN set, copilot_chat returns 1 (not 2/127) and halts fallback
propagation before gemini is reached. Add `COPILOT_GITHUB_TOKEN=ghp_stub` (a
classic-PAT prefix) to both tests so the copilot leg is skipped, matching the
same approach used in test_engine_fallback.bats.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(bot): address bot feedback [skip ci-relay]

* fix(bot): address bot feedback [skip ci-relay]

---------

Co-authored-by: donpetry-bot <{}+donpetry-bot@users.noreply.github.com>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Co-authored-by: donpetry-bot <281750570+donpetry-bot@users.noreply.github.com>
don-petry added a commit that referenced this pull request Aug 7, 2026
…mini (#571)

* fix(engine): reorder cross-provider fallback to claude -> copilot -> gemini

The cross-provider rate-limit fallback was claude -> gemini -> copilot, so when
Claude was exhausted it fell back to Gemini *before* Copilot. With Gemini's
prepayment credits depleted, that surfaced as hard 429 RESOURCE_EXHAUSTED
failures (observed on markets dev-lead fix-bot-comment). Per the intended
engine preference — Claude default, then Copilot, then Gemini — make Gemini the
last resort.

- engine.sh run_writer_with_fallback: loop order claude copilot gemini (dev-lead path).
- review-batch.sh: reorder the cascade so Claude rate-limit falls to Copilot first,
  then Gemini (pr-review batch path); availability checks travel with each engine.
- Update comments + bats (test_engine_fallback, test_provider_headroom) to the new
  order; force copilot-skip via a classic-PAT token where a test targets the
  Gemini fallback specifically. 22/22 engine tests pass; shellcheck clean.

Shared engine.sh affects BOTH agents → ship via pr-review + dev-lead releases.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* chore: apply manual instructions [skip ci-relay]

* fix(bot): address bot feedback [skip ci-relay]

* chore: apply manual instructions [skip ci-relay]

* fix(tests): skip copilot fallback in writer tests after claude → copilot → gemini reorder

Tests 152 and 168 in test_engine_writer.bats expected run_writer_with_fallback
to reach gemini when claude is rate-limited. With the new fallback order
(claude → copilot → gemini), copilot is tried first; without GH_TOKEN or
COPILOT_GITHUB_TOKEN set, copilot_chat returns 1 (not 2/127) and halts fallback
propagation before gemini is reached. Add `COPILOT_GITHUB_TOKEN=ghp_stub` (a
classic-PAT prefix) to both tests so the copilot leg is skipped, matching the
same approach used in test_engine_fallback.bats.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(bot): address bot feedback [skip ci-relay]

* fix(bot): address bot feedback [skip ci-relay]

---------

Co-authored-by: donpetry-bot <{}+donpetry-bot@users.noreply.github.com>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Co-authored-by: donpetry-bot <281750570+donpetry-bot@users.noreply.github.com>
don-petry added a commit that referenced this pull request Aug 7, 2026
…1113)

* fix(feature-ideation): route caller inputs through a prep job (#571)

This repo's feature-ideation caller carried the same #571 defect fixed in the
central template (petry-projects/.github#615): the `ideate` job's reusable
`with:` referenced `${{ inputs.* }}`, which is evaluated at workflow setup
regardless of the job `if:` and so fails the whole run (zero jobs) on the
`discussion: created` trigger — the exact path that auto-enhances new Ideas.

Resolve dispatch inputs in a gated `prep` job and pass them to `ideate` via
`needs.prep.outputs.*` (booleans via fromJSON). The `feature-ideation/next`
channel pin is unchanged. As the `next` ring this dogfoods the fix ahead of the
fleet rollout tracked in petry-projects/.github#614.

Refs: petry-projects/.github#571, petry-projects/.github#614

* test(feature-ideation): assert prep-routed inputs, add #571 guard

The compliance test encoded the pre-#571 contract — it required the reusable
`with:` to source target_discussion/enhance_backlog from `${{ inputs.* }}`, the
exact pattern that fails at workflow setup on the discussion trigger. Update the
assertions to the prep-routed shape (needs.prep.outputs.*, booleans via fromJSON)
and add a guard that no reusable `with:` value references the `inputs` context.

Refs: petry-projects/.github#571

---------

Co-authored-by: donpetry-bot <{}+donpetry-bot@users.noreply.github.com>
don-petry added a commit that referenced this pull request Aug 7, 2026
…mini (#571)

* fix(engine): reorder cross-provider fallback to claude -> copilot -> gemini

The cross-provider rate-limit fallback was claude -> gemini -> copilot, so when
Claude was exhausted it fell back to Gemini *before* Copilot. With Gemini's
prepayment credits depleted, that surfaced as hard 429 RESOURCE_EXHAUSTED
failures (observed on markets dev-lead fix-bot-comment). Per the intended
engine preference — Claude default, then Copilot, then Gemini — make Gemini the
last resort.

- engine.sh run_writer_with_fallback: loop order claude copilot gemini (dev-lead path).
- review-batch.sh: reorder the cascade so Claude rate-limit falls to Copilot first,
  then Gemini (pr-review batch path); availability checks travel with each engine.
- Update comments + bats (test_engine_fallback, test_provider_headroom) to the new
  order; force copilot-skip via a classic-PAT token where a test targets the
  Gemini fallback specifically. 22/22 engine tests pass; shellcheck clean.

Shared engine.sh affects BOTH agents → ship via pr-review + dev-lead releases.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* chore: apply manual instructions [skip ci-relay]

* fix(bot): address bot feedback [skip ci-relay]

* chore: apply manual instructions [skip ci-relay]

* fix(tests): skip copilot fallback in writer tests after claude → copilot → gemini reorder

Tests 152 and 168 in test_engine_writer.bats expected run_writer_with_fallback
to reach gemini when claude is rate-limited. With the new fallback order
(claude → copilot → gemini), copilot is tried first; without GH_TOKEN or
COPILOT_GITHUB_TOKEN set, copilot_chat returns 1 (not 2/127) and halts fallback
propagation before gemini is reached. Add `COPILOT_GITHUB_TOKEN=ghp_stub` (a
classic-PAT prefix) to both tests so the copilot leg is skipped, matching the
same approach used in test_engine_fallback.bats.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(bot): address bot feedback [skip ci-relay]

* fix(bot): address bot feedback [skip ci-relay]

---------

Co-authored-by: donpetry-bot <{}+donpetry-bot@users.noreply.github.com>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Co-authored-by: donpetry-bot <281750570+donpetry-bot@users.noreply.github.com>
don-petry added a commit that referenced this pull request Aug 7, 2026
…1113)

* fix(feature-ideation): route caller inputs through a prep job (#571)

This repo's feature-ideation caller carried the same #571 defect fixed in the
central template (petry-projects/.github#615): the `ideate` job's reusable
`with:` referenced `${{ inputs.* }}`, which is evaluated at workflow setup
regardless of the job `if:` and so fails the whole run (zero jobs) on the
`discussion: created` trigger — the exact path that auto-enhances new Ideas.

Resolve dispatch inputs in a gated `prep` job and pass them to `ideate` via
`needs.prep.outputs.*` (booleans via fromJSON). The `feature-ideation/next`
channel pin is unchanged. As the `next` ring this dogfoods the fix ahead of the
fleet rollout tracked in petry-projects/.github#614.

Refs: petry-projects/.github#571, petry-projects/.github#614

* test(feature-ideation): assert prep-routed inputs, add #571 guard

The compliance test encoded the pre-#571 contract — it required the reusable
`with:` to source target_discussion/enhance_backlog from `${{ inputs.* }}`, the
exact pattern that fails at workflow setup on the discussion trigger. Update the
assertions to the prep-routed shape (needs.prep.outputs.*, booleans via fromJSON)
and add a guard that no reusable `with:` value references the `inputs` context.

Refs: petry-projects/.github#571

---------

Co-authored-by: donpetry-bot <{}+donpetry-bot@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants