CI & Build / Python lint (push) Successful in 3s
CI & Build / Plugin hooks (push) Successful in 13s
CI & Build / TypeScript typecheck (push) Successful in 55s
CI & Build / integration (push) Successful in 1m7s
CI & Build / Python tests (push) Failing after 1m30s
CI & Build / Build & push image (push) Skipped
prompt_rule, pre_tool_rule and write_path_rule now share one settings key, RULE_FLOOR_KEY = "kb_rule_threshold", default 0.70. The reply backstop keeps its own 0.80, because there the floor is a stop bar. Moving the shared floor through tune_retrieval or the Settings form records a tuning event on every surface that reads it (set_dial, via retrieval_surfaces.sharing_floor), and the result names the surfaces it carried as `moved_with`. Settings shows one "Standing-rule confidence threshold" control where it showed three. Operator ruling (2026-10-05): one shared bar for the rule arms, "especially since we're only taking the first x number of them" -- the budget limits what is shown; the bar only decides what is worth ranking. Kept a dial. Why 0.70, from records read rather than percentiles: - write_path_rule near-misses at 0.7199-0.72 were all false positives (rule 149 against a Lidarr comment, 157 against a retention Svelte file, 121 against an Archives restore, 164 against a config test, 131 against a Go package), so the old 0.72 was not hiding real hits -- but the band does noise control on this arm, so dropping 0.02 costs little. - prompt_rule: the operator set 0.70 by hand on 2026-09-18, after a 0.60 experiment admitted junk and was reverted. 0.70 is the number with a human decision behind it. - pre_tool_rule lines near 0.68 this session were mostly noise; rising to 0.70 trims them, and the band still narrows what clears. Retired keys: kb_promptrule_threshold, kb_toolrule_threshold and kb_rulehint_threshold are no longer read. Rows an install stored under them stay in the settings table, inert. On this instance the effective bars move pre_tool_rule 0.68 -> 0.70, write_path_rule 0.72 -> 0.70, prompt_rule stays 0.70; record_release_defaults writes those per-surface release rows on boot, so the telemetry shift has an event to explain it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
134 lines
5.9 KiB
Python
134 lines
5.9 KiB
Python
"""The Settings UI shows the default the server actually uses.
|
|
|
|
WHY THIS EXISTS
|
|
|
|
A retrieval threshold lives in two places by necessity: a Python constant the
|
|
arm reads when no row is stored, and a Vue `ref` the Settings form shows when
|
|
the operator has never touched it. Neither can import the other.
|
|
|
|
So the form's initial value is a CLAIM about the server's behaviour, and it is
|
|
the kind of claim that rots quietly. Retune the Python constant and the input
|
|
keeps rendering the old number — the operator reads it as the bar in force,
|
|
sees no reason to change anything, and the form has misinformed them about the
|
|
one fact it exists to convey. Nothing errors, nothing looks wrong, and the
|
|
value they are shown is simply not the value being applied.
|
|
|
|
WHAT THIS PINS
|
|
|
|
The RELATIONSHIP, never the number: for each threshold, the Vue ref's initial
|
|
string equals the Python default. Retuning either stays free as long as both
|
|
move — which is the point, because these are tuning values and they move.
|
|
|
|
The Vue side is read from SOURCE, because that file cannot be imported at all.
|
|
The Python side is read from source for a loose constant and IMPORTED for a
|
|
registry surface — the registry is a plain table of frozen dataclasses with
|
|
nothing to trigger on import, and importing it means this guard checks the value
|
|
the server will actually resolve rather than a literal that happens to look
|
|
right.
|
|
|
|
It cannot check that the form WRITES the right key — that is behaviour, and
|
|
the keys are asserted where they are built. It catches the drift that has no
|
|
other alarm.
|
|
"""
|
|
from __future__ import annotations
|
|
|
|
import pathlib
|
|
import re
|
|
|
|
import pytest
|
|
|
|
ROOT = pathlib.Path(__file__).resolve().parents[1]
|
|
_SERVICES = ROOT / "src" / "grimoire" / "services"
|
|
_VUE = ROOT / "frontend" / "src" / "views" / "SettingsView.vue"
|
|
|
|
# THE RETRIEVAL FLOORS live in one registry, so their side of
|
|
# the pairing is a SURFACE NAME rather than a module constant. That is strictly
|
|
# better for this guard: the surface name is also the telemetry source, so a row
|
|
# here names the same arm the readout does, and a floor that moved cannot be
|
|
# checked against a stale constant that happened to keep its old value.
|
|
_SURFACE_PAIRS = (
|
|
("auto_inject", "kbInjectThreshold"),
|
|
("write_path", "kbWritePathThreshold"),
|
|
# The three rule hints read one bar, so one control serves them.
|
|
("write_path_rule", "kbRuleThreshold"),
|
|
("pre_tool_rule", "kbRuleThreshold"),
|
|
("prompt_rule", "kbRuleThreshold"),
|
|
("reply_rule", "kbReplyRuleThreshold"),
|
|
)
|
|
|
|
# (services module, python constant, vue ref) for the defaults that are NOT
|
|
# retrieval surfaces. Hand-written because the pairing is an editorial fact —
|
|
# the names share no convention either side could derive — and asserted to
|
|
# exist on both sides, so a rename fails loudly rather than silently dropping
|
|
# that threshold from the check.
|
|
_CONSTANT_PAIRS = (
|
|
# The plan gate: it blocks a create, so a form showing a
|
|
# looser bar than the one in force would be the more misleading drift. Not
|
|
# a push surface, so it has no registry entry and keeps the older shape.
|
|
("dedup.py", "PLAN_MATCH_DEFAULT_THRESHOLD", "kbPlanMatchThreshold"),
|
|
)
|
|
|
|
|
|
def _python_default(module: str, name: str) -> float:
|
|
m = re.search(rf"^{re.escape(name)}\s*=\s*([0-9.]+)\s*$",
|
|
(_SERVICES / module).read_text(), re.M)
|
|
assert m, (
|
|
f"{name} is no longer a bare module-level float in "
|
|
f"services/{module}. If it moved or was renamed, update "
|
|
f"_PAIRS; if it was retired, drop its row — leaving it here checks "
|
|
f"nothing while looking like coverage."
|
|
)
|
|
return float(m.group(1))
|
|
|
|
|
|
def _vue_default(ref_name: str) -> float:
|
|
m = re.search(rf"const {re.escape(ref_name)} = ref\(\"([0-9.]+)\"\)",
|
|
_VUE.read_text())
|
|
assert m, (
|
|
f"{ref_name} is no longer a `ref(\"<number>\")` in SettingsView.vue. "
|
|
f"If the control was renamed, update _PAIRS; if it was removed, the "
|
|
f"setting has lost its UI and that is the thing to fix."
|
|
)
|
|
return float(m.group(1))
|
|
|
|
|
|
def _assert_agrees(server: float, form: float, ref_name: str, what: str) -> None:
|
|
assert form == server, (
|
|
f"SettingsView shows {form} for {ref_name} while the server defaults "
|
|
f"to {server} ({what}). An operator who has never set this reads the "
|
|
f"form as the value in force, so the two must move together — retune "
|
|
f"both, or neither."
|
|
)
|
|
|
|
|
|
@pytest.mark.parametrize(("surface", "ref_name"), _SURFACE_PAIRS,
|
|
ids=[p[0] for p in _SURFACE_PAIRS])
|
|
def test_the_form_shows_the_floor_the_surface_uses(surface, ref_name):
|
|
"""An untouched control must render the bar actually in force."""
|
|
from grimoire.services.retrieval_surfaces import get_surface
|
|
|
|
_assert_agrees(get_surface(surface).floor_default, _vue_default(ref_name),
|
|
ref_name, f"{surface} floor")
|
|
|
|
|
|
def test_every_tunable_surface_has_a_control():
|
|
"""A number an operator may need different has a UI or it is
|
|
not shipped. Derived from the registry, so a seventh surface arrives here
|
|
as a failure rather than as a setting only the model can reach."""
|
|
from grimoire.services.retrieval_surfaces import surface_names
|
|
|
|
covered = {s for s, _ref in _SURFACE_PAIRS}
|
|
missing = [n for n in surface_names() if n not in covered]
|
|
assert not missing, (
|
|
f"these surfaces are tunable with no Settings control: {missing}. "
|
|
"Add the control and its row, or say in _SURFACE_PAIRS why it has none."
|
|
)
|
|
|
|
|
|
@pytest.mark.parametrize(("module", "constant", "ref_name"), _CONSTANT_PAIRS,
|
|
ids=[p[1] for p in _CONSTANT_PAIRS])
|
|
def test_the_form_shows_the_default_the_server_uses(module, constant, ref_name):
|
|
"""Same claim, for the defaults that are not retrieval surfaces."""
|
|
_assert_agrees(_python_default(module, constant), _vue_default(ref_name),
|
|
ref_name, constant)
|