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
4 changes: 2 additions & 2 deletions scripts/aw.sh
Original file line number Diff line number Diff line change
Expand Up @@ -90,8 +90,8 @@ for field in ("name", "trigger", "engine", "permissions"):

# Validate engine — warn on unknown but don't fail (new models can be added without a code change)
known_engines = {
"claude-sonnet-4-6", "claude-haiku-4-5-20251001", "claude-opus-4-7",
"claude-haiku-4-5",
"claude-sonnet-4-6", "claude-sonnet-5-0", "claude-haiku-4-5-20251001",
"claude-opus-4-7", "claude-haiku-4-5",
}
engine = fm.get("engine", "")
if engine and engine not in known_engines:
Expand Down
14 changes: 11 additions & 3 deletions scripts/engine.sh
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ set_engine_config() {
ENGINE_AUDIT_MODEL="claude-fable-5"
ENGINE_ACTION_MODEL="claude-sonnet-4-6"
ENGINE_SINGLE_MODEL="claude-fable-5"
ENGINE_LABEL="triage: haiku 4.5 → deep: opus 4.8 + duck: o4-mini → audit: fable 5"
ENGINE_LABEL="triage: haiku 4.5 [sonnet 4.6 → sonnet 5] → deep: opus 4.8 [sonnet 4.6 → sonnet 5] + duck: o4-mini → audit: fable 5"
ENGINE_SINGLE_LABEL="single-reviewer mode: fable 5"
# Cross-engine rubber duck: use Copilot when Claude is primary
DUCK_ENGINE="copilot"
Expand All @@ -140,8 +140,16 @@ set_engine_config() {
# - adaptive thinking only; budget_tokens/temperature/top_p/top_k removed
# - omit thinking param entirely (disabled returns 400 on fable-5)
# - min cacheable prefix: fable-5 = 2048 tok, opus-4-8 = 4096 tok
CLAUDE_TRIAGE_MODEL_CHAIN="${CLAUDE_TRIAGE_MODEL_CHAIN:-claude-haiku-4-5-20251001,claude-sonnet-4-6}"
CLAUDE_DEEP_MODEL_CHAIN="${CLAUDE_DEEP_MODEL_CHAIN:-claude-opus-4-8,claude-sonnet-4-6}"
# Sonnet 5 candidate (#1098): claude-sonnet-5-0 is appended AFTER the
# sonnet-4-6 slot in the triage and deep chains as a non-default fallback
# candidate — it earns its own TPM/RPM bucket for the layer-1 rate-limit
# walk without displacing the current primaries (haiku triage / opus deep)
# or the sonnet-4-6 fallback ordering. It is NOT the fleet default; a
Comment thread
don-petry marked this conversation as resolved.
# promotion to primary rides Story 5's canary rings. The daily cap is
# shared across Claude models (#206), so this hop only helps per-model RPM/
# TPM, not the subscription cap. Action tier is out of scope (#1098).
CLAUDE_TRIAGE_MODEL_CHAIN="${CLAUDE_TRIAGE_MODEL_CHAIN:-claude-haiku-4-5-20251001,claude-sonnet-4-6,claude-sonnet-5-0}"
CLAUDE_DEEP_MODEL_CHAIN="${CLAUDE_DEEP_MODEL_CHAIN:-claude-opus-4-8,claude-sonnet-4-6,claude-sonnet-5-0}"
CLAUDE_AUDIT_MODEL_CHAIN="${CLAUDE_AUDIT_MODEL_CHAIN:-claude-fable-5,claude-opus-4-8,claude-opus-4-7}"
CLAUDE_ACTION_MODEL_CHAIN="${CLAUDE_ACTION_MODEL_CHAIN:-claude-sonnet-4-6,claude-opus-4-8}"
CLAUDE_SINGLE_MODEL_CHAIN="${CLAUDE_SINGLE_MODEL_CHAIN:-claude-fable-5,claude-opus-4-8,claude-opus-4-7}"
Expand Down
37 changes: 37 additions & 0 deletions tests/dev-lead/unit/test_engine_chain.bats
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,43 @@ _source_engine() {
grep -q "claude-opus-4-8" "$MODEL_RECORD"
}

# ── Sonnet 5 candidate wiring (#1098) ─────────────────────────────────────────
# Sonnet 5 is appended as a FALLBACK CANDIDATE after claude-sonnet-4-6 in the
# triage and deep chains (not a replacement, not the fleet default). The action
# tier is deliberately out of scope.

@test "sonnet-5 candidate: triage chain default appends claude-sonnet-5-0 after sonnet-4-6" {
_source_engine "claude"
[ "$CLAUDE_TRIAGE_MODEL_CHAIN" = "claude-haiku-4-5-20251001,claude-sonnet-4-6,claude-sonnet-5-0" ]
}

@test "sonnet-5 candidate: deep chain default appends claude-sonnet-5-0 after sonnet-4-6" {
_source_engine "claude"
[ "$CLAUDE_DEEP_MODEL_CHAIN" = "claude-opus-4-8,claude-sonnet-4-6,claude-sonnet-5-0" ]
}

@test "sonnet-5 candidate: deep opus-4-8 + sonnet-4-6 both rate-limited → claude-sonnet-5-0 reached" {
_source_engine "claude"
# Both existing deep models throttle; the walk must reach the new candidate.
export STUB_ENGINE_EXIT_BY_MODEL="claude-opus-4-8=1|claude-sonnet-4-6=1|claude-sonnet-5-0=0"
export STUB_ENGINE_RESPONSE_BY_MODEL="claude-opus-4-8=429 too many requests|claude-sonnet-4-6=429 too many requests|claude-sonnet-5-0=sonnet 5 did the work"

run run_agentic "$TEST_PROMPT" "claude-opus-4-8" "deep"

[ "$status" -eq 0 ]
grep -q "claude-opus-4-8" "$MODEL_RECORD"
grep -q "claude-sonnet-4-6" "$MODEL_RECORD"
grep -q "claude-sonnet-5-0" "$MODEL_RECORD"
[[ "$output" == *"sonnet 5 did the work"* ]]
}

@test "sonnet-5 candidate: action chain default is NOT touched (scope guard)" {
_source_engine "claude"
# Action tier is out of scope for #1098 — must stay sonnet-4-6 → opus-4-8.
[ "$CLAUDE_ACTION_MODEL_CHAIN" = "claude-sonnet-4-6,claude-opus-4-8" ]
[[ "$CLAUDE_ACTION_MODEL_CHAIN" != *"claude-sonnet-5"* ]]
}

# ── Gemini/Copilot unchanged: no chain applied ────────────────────────────────

@test "gemini: in-engine chain uses gemini model (not claude)" {
Expand Down
Loading