diff --git a/crates/headroom-core/src/transforms/recommendations.rs b/crates/headroom-core/src/transforms/recommendations.rs index a2efee865..6c5c842ab 100644 --- a/crates/headroom-core/src/transforms/recommendations.rs +++ b/crates/headroom-core/src/transforms/recommendations.rs @@ -28,6 +28,7 @@ //! auth_mode = "payg" //! model_family = "claude-3-5" //! structure_hash = "deadbeef..." +//! skip_compression_recommended = false //! strategy_hint = "smart_crusher" //! confidence = 0.87 //! observations = 142 @@ -71,6 +72,8 @@ pub struct Recommendation { pub auth_mode: String, pub model_family: String, pub structure_hash: String, + #[serde(default)] + pub skip_compression_recommended: bool, pub strategy_hint: String, pub confidence: f64, pub observations: u64, @@ -270,6 +273,7 @@ mod tests { auth_mode = "payg" model_family = "claude-3-5" structure_hash = "deadbeef" +skip_compression_recommended = true strategy_hint = "smart_crusher" confidence = 0.87 observations = 142 @@ -292,11 +296,21 @@ observations = 60 let r = store .lookup(AuthMode::Payg, "claude-3-5", "deadbeef") .expect("hit"); + assert!(r.skip_compression_recommended); assert_eq!(r.strategy_hint, "smart_crusher"); assert!((r.confidence - 0.87).abs() < 1e-9); assert_eq!(r.observations, 142); } + #[test] + fn from_toml_str_defaults_missing_skip_field_to_false() { + let store = RecommendationStore::from_toml_str(sample_toml()).expect("parses"); + let r = store + .lookup(AuthMode::OAuth, "gpt-4o", "cafebabe") + .expect("hit"); + assert!(!r.skip_compression_recommended); + } + #[test] fn lookup_returns_none_for_missing_slice() { let store = RecommendationStore::from_toml_str(sample_toml()).expect("parses"); diff --git a/headroom/cli/toin_publish.py b/headroom/cli/toin_publish.py index c067b0828..89a408bab 100644 --- a/headroom/cli/toin_publish.py +++ b/headroom/cli/toin_publish.py @@ -15,6 +15,7 @@ result as TOML the Rust proxy loads at startup auth_mode = "payg" model_family = "claude-3-5" structure_hash = "deadbeef..." + skip_compression_recommended = false strategy_hint = "smart_crusher" confidence = 0.87 observations = 142 @@ -30,7 +31,9 @@ alongside the Rust binary, and the proxy reads it once at startup. # Output stability Rows are sorted by ``(auth_mode, model_family, structure_hash)`` so the -file diffs cleanly across publishes. Strategies ship as the +file diffs cleanly across publishes. Rows with +``skip_compression_recommended = true`` publish +``strategy_hint = "skip_compression"``. Other rows ship the ToolPattern's learned ``optimal_strategy`` (or the dominant entry of ``strategy_success_rates``). Confidence is the pattern's existing confidence score — bounded ``[0.0, 0.95]`` by the confidence calculator. @@ -98,16 +101,19 @@ def _format_row( auth_mode: str, model_family: str, structure_hash: str, + skip_compression_recommended: bool, strategy_hint: str, confidence: float, observations: int, ) -> str: """Render one ``[[recommendation]]`` block.""" + skip_flag = "true" if skip_compression_recommended else "false" return ( "[[recommendation]]\n" f'auth_mode = "{_toml_escape(auth_mode)}"\n' f'model_family = "{_toml_escape(model_family)}"\n' f'structure_hash = "{_toml_escape(structure_hash)}"\n' + f"skip_compression_recommended = {skip_flag}\n" f'strategy_hint = "{_toml_escape(strategy_hint)}"\n' f"confidence = {confidence:.4f}\n" f"observations = {observations}\n" @@ -132,12 +138,18 @@ def _eligible_rows( if observations < min_observations: continue auth_mode, model_family, sig_hash = key + strategy_hint = ( + "skip_compression" + if pattern.skip_compression_recommended + else _select_strategy(pattern) + ) rows.append( { "auth_mode": auth_mode, "model_family": model_family, "structure_hash": sig_hash, - "strategy_hint": _select_strategy(pattern), + "skip_compression_recommended": pattern.skip_compression_recommended, + "strategy_hint": strategy_hint, "confidence": float(pattern.confidence), "observations": observations, } diff --git a/tests/test_toin_publish.py b/tests/test_toin_publish.py index 1104acf89..a6c2bbe11 100644 --- a/tests/test_toin_publish.py +++ b/tests/test_toin_publish.py @@ -5,7 +5,8 @@ Pins: 1. ``publish()`` writes a TOML file the stdlib ``tomllib`` can parse. 2. Slices below ``--min-observations`` are filtered out. 3. Rows include ``auth_mode``, ``model_family``, ``structure_hash``, - ``strategy_hint``, ``confidence``, ``observations`` — the schema + ``skip_compression_recommended``, ``strategy_hint``, ``confidence``, + ``observations`` — the schema ``crates/headroom-core/src/transforms/recommendations.rs`` consumes. 4. The CLI entry point honors ``--output`` / ``--min-observations``. """ @@ -99,6 +100,7 @@ def test_publish_command_writes_toml(fresh_toin: ToolIntelligenceNetwork, tmp_pa "auth_mode", "model_family", "structure_hash", + "skip_compression_recommended", "strategy_hint", "confidence", "observations", @@ -106,12 +108,49 @@ def test_publish_command_writes_toml(fresh_toin: ToolIntelligenceNetwork, tmp_pa assert row["auth_mode"] == "payg" assert row["model_family"] == "claude-3-5" assert row["structure_hash"] == sig.structure_hash + assert row["skip_compression_recommended"] is False assert row["strategy_hint"] == "smart_crusher" assert isinstance(row["confidence"], float) assert 0.0 <= row["confidence"] <= 1.0 assert row["observations"] == 60 +def test_publish_preserves_skip_recommendation( + fresh_toin: ToolIntelligenceNetwork, + tmp_path: Path, +) -> None: + """Skip-eligible rows publish the skip flag and skip strategy hint.""" + items = [{"id": i, "status": "ok"} for i in range(20)] + sig = _record( + fresh_toin, + items=items, + n=60, + auth_mode="payg", + model_family="claude-3-5", + ) + for _ in range(49): + fresh_toin.record_retrieval( + tool_signature_hash=sig.structure_hash, + retrieval_type="full", + strategy="smart_crusher", + auth_mode="payg", + model_family="claude-3-5", + ) + + output = tmp_path / "recommendations.toml" + rows_written = publish( + output_path=output, + min_observations=50, + toin=fresh_toin, + ) + assert rows_written == 1 + + parsed = tomllib.loads(output.read_text(encoding="utf-8")) + row = parsed["recommendation"][0] + assert row["skip_compression_recommended"] is True + assert row["strategy_hint"] == "skip_compression" + + def test_publish_filters_below_min_observations( fresh_toin: ToolIntelligenceNetwork, tmp_path: Path,