mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-12 14:16:12 +00:00
test(insights): add the per-metric tone harness
A deterministic grader over the assembled assessment prompts and the deterministic fallback text. No provider, no network, no database — it runs in the normal suite in under half a second, which is the point: the live-judge eval needs a key and can only advise, so the regressions that actually shipped need a check that can block. Three classes are blocking. A surface stops leading with meaning (it drops the shared opening contract, or its user prompt loses the meaning-first instruction). A locale collapses (fr/es/it/pl fall back to the German body or lose the reply-language directive). A prompt reintroduces a value-first instruction — matched with negation handling, since the shared prompts quote that failure mode in order to ban it. The deterministic fallbacks are graded on the same axis, including the asymmetry that matters: a signal with no baseline supports no confident read, so that one line honestly opens on the value. Pinning it stops a future "always lead with meaning" edit from pushing the surface into claiming something the data does not support. A coverage guard fails when an assessment prompt module has no harness entry, so the next surface cannot stay uncovered the way the biomarker card did.
This commit is contained in:
1 parent
ed049661b7
commit
1b50dc0909
1 file changed
+22
@@ -253,6 +253,20 @@ const CLINICAL_VERDICT =
|
||||
const VALUE_LED_OPENER =
|
||||
/^(Your|Dein|Deine|Ihr|Ihre)\s+\S+(\s+\S+)?\s+(is|ist|liegt)\s+\d/i;
|
||||
|
||||
/**
|
||||
* The OTHER way a deterministic line stops leading with meaning: it opens on a
|
||||
* bare order.
|
||||
*
|
||||
* This is what the no-signal floors were — "Measure blood pressure at rest and
|
||||
* under comparable conditions", "Bewerte Gewicht vor allem im Verlauf". Not a
|
||||
* value-led opener, so the number rules never saw it, but it is the same
|
||||
* failure: the surface tells the reader what to do before it says anything
|
||||
* about what it can and cannot see. A pointer is fine LATER in the line; it
|
||||
* may not be the opening move.
|
||||
*/
|
||||
const IMPERATIVE_OPENER =
|
||||
/^(Measure|Track|Evaluate|Monitor|Check|Watch|Log|React|Use|Keep|Pay|Consider|Make sure)\b|^(Miss|Bewerte|Beobachte|Achte|Nutze|Halte|Reagiere|Prüfe|Vergleiche|Erfasse)\b/;
|
||||
|
||||
function firstSentence(text: string): string {
|
||||
const m = /^[^.!?]*[.!?]/.exec(text.trim());
|
||||
return (m ? m[0] : text.trim()).trim();
|
||||
@@ -289,6 +303,14 @@ export function checkFallbackTone(input: {
|
||||
excerpt: opener,
|
||||
});
|
||||
}
|
||||
if (IMPERATIVE_OPENER.test(opener)) {
|
||||
violations.push({
|
||||
rule: "fallback-no-imperative-opener",
|
||||
detail:
|
||||
"the line opens on an order rather than on what the surface can honestly say",
|
||||
excerpt: opener,
|
||||
});
|
||||
}
|
||||
if (VALUE_LED_OPENER.test(opener)) {
|
||||
violations.push({
|
||||
rule: "fallback-no-value-led-opener",
|
||||
|
||||
Reference in new issue
Block a user