Skip to main content

Module hook

Module hook 

Source
Expand description

Truth Gate: a narrow Stop-hook check for responses that claim completion while leaving work unfinished or deferred. It is not a fact-checker.

Deterministic rules (default):

  • match whole words only (incomplete is not complete, already is not ready);
  • ignore a completion word or placeholder that is negated just before it (not done, no placeholder text remains);
  • ignore fenced and inline code, where TODOs are usually quoted legacy code;
  • normalize first (Unicode NFC, curly apostrophes, zero-width characters, every whitespace character except newline to a space) and use ASCII word boundaries, so the Rust and Python implementations agree on unusual Unicode;
  • block only when an un-negated completion claim co-occurs with an un-negated unfinished marker or a first-person future-work promise;
  • a word that names a thing is not a marker: todo, tbd or fixme followed by a feature noun such as list or app (the TODO list widget), coming soon followed by a UI word such as badge or page, and placeholder after input, search or field. Each still counts when the rest of its clause says it is open (remains, left, pending, still needs). todo, tbd or fixme followed by comment or item names a thing only when the rest of its clause says it was dealt with (the TODO comment in proxy.ts is now handled) and nothing in the clause says it is open, because I left a TODO comment is open work. placeholder before text (the older rule) is always UI. A term right after an opening quote is mentioned (the badge reads "Coming soon"), except marker syntax ("TODO: retries", FIXME(), which always counts;
  • a clause ends at ., !, ?, ; or a newline, but not at a . directly followed by a letter or digit (proxy.ts, v2.1);
  • a promise left to the user is an offer, not deferred work: an idiom asking for the user’s permission or trigger (if you want, once you approve, when you're ready, let me know if you'd like, would you like) in the promise’s own comma-delimited segment or opening the segment before it (If you want, I'll ...). A condition about product behaviour (when you visit /old, if you add two plans) is not one, and a condition cannot reach across a coordinated clause (..., and I'll ...), past a neighbouring promise, or past a clause end.

Optional engine mode: a typed decision engine (for example Jev) estimates the probability that the completion claim would fail verification (a test run of the requested change). The gate blocks when the rules block or p >= threshold. By default the deterministic rules are a hard floor an engine cannot lift, and the engine can only add blocks. Opting in with a lift value (GateSettings::lift, HIKMAH_HOOK_ENGINE_LIFT) lets an admitted engine answer with p < lift remove a rules block; nothing removes an engine block. Any engine failure, abstention, or rejected response leaves the rules’ verdict in place.

Why this question and threshold: on 600 held-out real agent “done” messages (harness-bench run 1), the rules caught 1 of 295 false completions, the previous engine question (“does the message admit unfinished work?”) caught 8.5%, and this outcome question caught 16.3% with a 7.9% false-block rate at 0.60, a threshold chosen on a separate dev set. The message alone cannot catch most false completions; treat this as a screen, not a verifier.

Opt-in measurement: with a record store (HIKMAH_HOOK_RECORD), every probability the engine answers is appended there as a prediction trace (family truth_gate.false_completion.v2) after the verdict is written, so outcomes recorded later can set the threshold from data (hikmah gate-threshold). Recording is best effort and never changes the verdict.

hooks/truth_gate_cases.json holds golden cases shared with the Python fallback.

Structs§

GateSettings
How the Truth Gate combines its rules with an engine’s answer.
GateVerdict
Full explanation of one Truth Gate decision (what hikmah gate-explain prints).

Enums§

GatePath
Which path produced a Truth Gate verdict.

Constants§

DEFAULT_ENGINE_THRESHOLD
Chosen on harness-bench run 1 dev (300 messages; highest recall with a false-block rate of at most 10%) and confirmed on its held-out test split. Re-measure on your own traffic with HIKMAH_HOOK_RECORD, hikmah outcome, and hikmah gate-threshold.
GATE_FAMILY
Calibration family of the v2 outcome question. Calibration must not mix it with v1.

Functions§

evaluate_message
Decide one message. The Stop hook and hikmah gate-explain both call this, so the benchmark measures exactly the code path the hook runs.
explain_batch
hikmah gate-explain --batch: one JSON object per input line ({"id": ..., "last_assistant_message": ...}), one verdict per output line, input order kept.
explain_stop_event
hikmah gate-explain (without --batch): the verdict the Stop hook reaches for this stdin, through the same parsing and the same evaluate_message. When the hook would allow without judging, skipped says why and nothing is sent to an engine.
false_completion_request
The question an engine answers in engine mode: would this completion claim fail verification? The wording is the one benchmarked in harness-bench; changing it invalidates that evidence.
rules_verdict
Deterministic verdict: true means block.
run_stop_hook
Rules-only Stop hook (the default).
run_stop_hook_recording
Stop hook that can also record the engine’s answer. When record names a memory store and the engine answered, the prediction is appended there after the verdict is written and flushed. Any recording failure (or panic) is swallowed: it can never change the verdict, the output, or the exit status.
run_stop_hook_with
Stop hook with an optional decision engine. Always prints valid JSON.