From a218a310552191f5c5d5d04c6090d6c960dc5b6f Mon Sep 17 00:00:00 2001 From: Oleks Date: Thu, 30 Jul 2026 05:30:48 +0300 Subject: [PATCH] Dedup MIN_SHARE_OF_SPEND: boundary-classify imports it from ia_store MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit bin/boundary-classify defined its own copy of the spec §5.2.7 filing threshold that only happened to match ia_store.py's copy, which bin/stability-classify's FR-4.5 stability gate actually reads. Tuning either constant independently would silently desynchronize the gate from the classifier it's meant to gate. ia_store.py is now the single definition; boundary-classify imports it. MIN_INVOCATIONS/MIN_ATTRIBUTED_TURNS are left as-is: stability-classify does not import or use them, so their duplication doesn't create the same fail-silently risk. Centralizing all thresholds via references/signals-catalog.md remains a separate, larger follow-up per the issue's "Related / proper fix" note. Fixes kotkan/claude-plugin-inference-arbitrage#14 --- .claude-plugin/plugin.json | 2 +- bin/boundary-classify | 8 ++++++-- bin/ia_store.py | 9 +++++---- 3 files changed, 12 insertions(+), 7 deletions(-) diff --git a/.claude-plugin/plugin.json b/.claude-plugin/plugin.json index 59c80c1..9428698 100644 --- a/.claude-plugin/plugin.json +++ b/.claude-plugin/plugin.json @@ -1,6 +1,6 @@ { "name": "inference-arbitrage", - "version": "0.6.0", + "version": "0.6.1", "description": "Audits a Claude Code plugin's definitions and usage transcripts to find steps that should be a deterministic script instead of raw LLM inference, and files the well-evidenced ones as issues on the target repo.", "author": { "name": "oleks" diff --git a/bin/boundary-classify b/bin/boundary-classify index 1b0d743..ee6b3d5 100755 --- a/bin/boundary-classify +++ b/bin/boundary-classify @@ -13,14 +13,18 @@ import argparse import json import sys +from ia_store import MIN_SHARE_OF_SPEND + RUBRIC_VERSION = "1.0.0" OFFLOADABLE_POSITIONS = {"pure-script", "llm-over-script-digest"} POSITIONS = OFFLOADABLE_POSITIONS | {"script-with-compiled-judgment", "pure-inference"} TESTS = ("T1", "T2", "T3", "T4", "T5") -# spec §5.2.7 filing threshold -MIN_SHARE_OF_SPEND = 0.02 +# spec §5.2.7 filing threshold — single definition lives in ia_store.py +# (kotkan/claude-plugin-inference-arbitrage#14); FR-4.5's stability gate +# (bin/stability-classify) imports the same constant, so tuning it here +# can no longer desynchronize the gate. # Below these, the dynamic pass is too thin to carry the share-of-spend gate on # its own. Derived from the Phase 3 finding that a skill invoked once inside a # multi-topic session produces a share that is arithmetically real but not diff --git a/bin/ia_store.py b/bin/ia_store.py index 735e4a5..8dd0e4a 100644 --- a/bin/ia_store.py +++ b/bin/ia_store.py @@ -20,10 +20,11 @@ import sys DEFAULT_STORE = "~/.cache/inference-arbitrage/wiki" -# spec §5.2.7's filing threshold, mirroring bin/boundary-classify — a candidate -# must clear the same bar to be called fixed, or stable, that it had to clear to -# be filed. Changing one without the others would make those words mean -# something the filing gate never meant. +# spec §5.2.7's filing threshold — single definition (kotkan/claude-plugin- +# inference-arbitrage#14). bin/boundary-classify imports this rather than +# keeping its own copy, so a candidate must clear the same bar to be called +# fixed, or stable, that it had to clear to be filed. Changing it here changes +# it everywhere; the two can no longer drift apart silently. MIN_SHARE_OF_SPEND = 0.02 MIN_INVOCATIONS = 3