Merge agent-B: cost-line fix + static_message + per-repo model override

# Conflicts:
#	pilot/ai_review.py
#	tests/pilot/test_ai_review.py
This commit is contained in:
Marcos
2026-08-22 15:01:38 +00:00
2 changed files with 223 additions and 12 deletions
+128
View File
@@ -410,6 +410,81 @@ def test_parse_repo_config_partial_and_bad():
assert parse_repo_config('{"instructions":" "}') == {"enabled": False}
def test_parse_repo_config_reads_static_message():
cfg = parse_repo_config(json.dumps({"static_message": " NOTE: this repo is in maintenance mode "}))
assert cfg.get("static_message") == "NOTE: this repo is in maintenance mode"
assert cfg.get("enabled") is False
def test_parse_repo_config_static_message_caps_length():
long_text = "x" * 9999
cfg = parse_repo_config(json.dumps({"static_message": long_text}))
assert "static_message" in cfg
assert len(cfg["static_message"]) <= 400
def test_parse_repo_config_static_message_ignores_blank():
assert "static_message" not in parse_repo_config(json.dumps({"static_message": " "}))
assert "static_message" not in parse_repo_config(json.dumps({"static_message": ""}))
assert "static_message" not in parse_repo_config(json.dumps({"static_message": 42}))
def test_parse_repo_config_reads_model_override():
# Per-repo override is validated against cost_model.PRICES. Only keys
# the cost model knows about can override the review engine.
cfg = parse_repo_config(json.dumps({"model": "claude-sonnet-5"}))
assert cfg.get("model") == "claude-sonnet-5"
def test_parse_repo_config_rejects_unknown_model(capsys):
cfg = parse_repo_config(json.dumps({"model": "not-in-prices"}))
assert "model" not in cfg
# Repos that pin a typo should get a stderr hint pointing at the valid set.
err = capsys.readouterr().err
assert "model" in err.lower() or "prices" in err.lower() or "unknown" in err.lower()
def test_parse_repo_config_model_must_be_string():
assert "model" not in parse_repo_config(json.dumps({"model": 42}))
assert "model" not in parse_repo_config(json.dumps({"model": []}))
assert "model" not in parse_repo_config(json.dumps({"model": None}))
def test_resolve_display_model_precedence(monkeypatch):
# Order is OPENCODE_MODEL env > config['model'] > headroom/{base}.
monkeypatch.delenv("OPENCODE_MODEL", raising=False)
# 1. No env, no config → headroom/<base>
assert ai_review._resolve_display_model("MiniMax-M2.7", None) == "headroom/MiniMax-M2.7"
assert ai_review._resolve_display_model("MiniMax-M2.7", {}) == "headroom/MiniMax-M2.7"
# 2. No env, config has model → use config model as-is (already a known key)
assert (
ai_review._resolve_display_model("MiniMax-M2.7", {"model": "claude-sonnet-5"})
== "claude-sonnet-5"
)
# 3. Env wins over config
monkeypatch.setenv("OPENCODE_MODEL", "headroom/MiniMax-M2.7")
assert (
ai_review._resolve_display_model("MiniMax-M2.7", {"model": "claude-sonnet-5"})
== "headroom/MiniMax-M2.7"
)
# 4. Env alone, no config
monkeypatch.delenv("OPENCODE_MODEL")
assert ai_review._resolve_display_model("x", {}) == "headroom/x"
def test_format_review_body_uses_override_for_cost_paren():
# End-to-end sanity: when the caller passes the resolved override as the
# `model` arg to format_review_body, both the header AND the cost line
# show the override — i.e. callers DO substitute the resolved display
# name into both the opencode subprocess ref and the review body.
body = format_review_body(
"- [high] x:1 — bug. fix.", "claude-sonnet-5", "abcdef1234567890",
)
assert "claude-sonnet-5" in body
assert "MiniMax-M2.7" not in body # the base didn't leak through
assert "🤖" in body # header rendered
# ---------------------------------------------------------------------------
# dedupe / prior-context parsing
# ---------------------------------------------------------------------------
@@ -789,6 +864,39 @@ def test_render_collapsible_usage_cost_nonzero_drops_free_tier_note():
"cache_write": 0, "total": 10, "cost": 0.0123, "steps": 1, "duration_s": 1.0}
sec = _render_collapsible_usage(usage, "m", config=None)
assert "$0.0123" in sec
# Was hardcoded "free tier" previously; now says "billed" since cost > 0.
assert "billed" in sec
assert "free tier" not in sec
def test_render_collapsible_usage_uses_passed_model_for_free_tier_clause():
# Regression: the cost parenthetical must reflect the actually-routed model,
# not a stale hardcoded `headroom glm-5.2:cloud` literal that predates the
# MiniMax / Anthropic switch.
usage = {"input": 10, "output": 0, "reasoning": 0, "cache_read": 0,
"cache_write": 0, "total": 10, "cost": 0.0, "steps": 1, "duration_s": 1.0}
sec = _render_collapsible_usage(usage, "MiniMax-M2.7", config=None)
# The parenthetical clause is "(<model> — free tier)" — a model name MUST
# sit immediately before "— free tier".
assert "(MiniMax-M2.7 — free tier)" in sec
# And the stale hardcoded model name must no longer appear anywhere.
assert "glm-5.2:cloud" not in sec
def test_render_collapsible_usage_full_provider_prefix_in_display():
# When the caller has resolved a provider-prefixed model ref (the opencode
# subprocess path), the parenthetical should mirror that verbatim.
usage = {"input": 10, "output": 0, "reasoning": 0, "cache_read": 0,
"cache_write": 0, "total": 10, "cost": 0.0, "steps": 1, "duration_s": 1.0}
sec = _render_collapsible_usage(usage, "headroom/MiniMax-M2.7", config=None)
assert "(headroom/MiniMax-M2.7 — free tier)" in sec
def test_render_collapsible_usage_nonzero_cost_says_billed():
usage = {"input": 10, "output": 0, "reasoning": 0, "cache_read": 0,
"cache_write": 0, "total": 10, "cost": 0.123, "steps": 1, "duration_s": 1.0}
sec = _render_collapsible_usage(usage, "MiniMax-M2.7", config=None)
assert "(MiniMax-M2.7 — billed)" in sec
assert "free tier" not in sec
@@ -808,6 +916,22 @@ def test_format_review_body_no_usage_section_omitted():
assert "AI usage" not in body
def test_format_review_body_renders_static_message_banner():
body = format_review_body(
"", "glm-5.2:cloud", "abcdef1234567890",
static_message="NOTE: this repo is in maintenance mode.",
)
assert "> NOTE: this repo is in maintenance mode." in body
# Banner sits under the header and above the rest of the body.
assert body.index("NOTE") > body.index("🤖")
assert body.index("NOTE") < body.index("### Summary of Changes")
def test_format_review_body_omits_static_message_when_blank():
body = format_review_body("", "glm-5.2:cloud", "abcdef1234567890")
assert "> " not in body
def test_format_review_body_with_summary_changes_and_risks():
body = format_review_body(
"", "glm-5.2:cloud", "abcdef1234567890",
@@ -1141,7 +1265,11 @@ def test_usage_block_shows_equivalent_provider_cost():
# grok-4.5; cost_target defaults to sonnet-5 (bolded).
assert "🔋 AI Usage & Run Details" in sec
assert "**Actual**: $0.00" in sec
# The "free tier" clause must mention the routed model verbatim, not the
# stale hardcoded `headroom glm-5.2:cloud` literal.
assert "free tier" in sec
assert "glm-5.2:cloud" in sec
# Equivalent should be > 0 for non-trivial token counts.
assert "$0.00" in sec # the actual line
# Multi-provider table header present, default roster rendered, default
# cost_target (Sonnet 5) is the bolded row.