mirror of
https://github.com/ruvnet/ruflo.git
synced 2026-10-23 03:47:00 +09:00
Reconciling the shipped similarity code against docs/metaharness-user-guide.md
turned up three divergences between what ADR-152 specifies, what the code does,
and what the docs promise.
1. Cost normalization (vector index 8) was inert below $0.999.
ADR-152 Table 1 specified `log10(usd + 0.001) / log10(10)` clamped to [0,1].
`Math.log10(10)` is 1, so the division was a no-op and the expression reduced
to `clamp(log10(usd + 0.001), 0, 1)`. Because log10 is negative for every
usd < 0.999, the clamp flattened that entire range to a constant 0 — including
the $0.048 baseline the plugin README records. Two harnesses differing only in
cost scored `cosine === 1`; the documented 9-dim vector was effectively 8-dim.
Replaced with an explicit log band: $0.001 -> 0, $10 -> 1, log-interpolated
between, monotonic and non-finite-safe. Exported as `normalizeCost()` with the
band in `COST_BAND_USD`.
2. The verdict bands had two encodings, and they disagreed.
`audit-trend.mjs` inlined the bands with a 0.80 `minor-drift` floor while the
user guide documented 0.85; `drift-from-history` prints that verdict, so the
two diverged in the 0.80-0.85 band. The bands now live once as
`VERDICT_THRESHOLDS` + `verdictFor()` in `_similarity.mjs`, `audit-trend.mjs`
imports them, and `similarity()` returns `verdict` beside `overall`. The
documented 0.85 floor is canonical.
Deliberate user-visible change: structural similarity in [0.80, 0.85) now
reports `moderate-drift` instead of `minor-drift`. `--threshold` comparison is
unaffected (it tests `overall`), but consumers branching on the verdict string
should be re-checked.
3. The user guide's weight table said 0.4/0.3/0.3; ADR-152 and the code both say
0.6/0.25/0.15. Corrected the guide, which was the outlier.
The ADR gains a dated Revision section recording both fixes and the behaviour
change. The §Spike-result figures are unchanged (the LEGAL/SUPPORT fixtures are
near-identical on the cost axis), so test-similarity.mjs Phase 8 keeps pinning
the original anchors; new Phase 7b/7c/7d coverage pins the corrected semantics.
Note this does NOT address the coarse-cosine limitation ADR-152 itself flags
("numerical cosine alone is too coarse"): uniform quality degradation still
reads as high similarity. Drift gates that must catch absolute loss should pair
structural similarity with the absolute gates rather than rely on --threshold.
Verification:
node plugins/ruflo-metaharness/scripts/test-similarity.mjs -> 128 passed, 0 failed (was 102)
node plugins/ruflo-metaharness/scripts/_spike-similarity.mjs -> both invariants hold
Co-authored-by: longxinjun-ai <longxinjun-ai@users.noreply.github.com>
Co-authored-by: rUv <ruv@ruv.net>