Learn the operator's typos on first sighting, not on the third

A term alias decides what gets written to conf and has to be earned by repetition; a spelling
decides how a sentence is read, and the same typo is rarely made three times.
This commit is contained in:
Gmer4Lfe
2026-08-09 20:34:29 -04:00
parent 801288c88c
commit 92157aa5da
+41
View File
@@ -915,6 +915,47 @@ function vv_ai_phrase_lookup(string $term, int $minSeen = 3): ?array {
return vv_ai_phrase_aliases($minSeen)[strtolower(trim($term))] ?? null;
}
// ── Spellings ────────────────────────────────────────────────────────────────────────────────
// The operator types quickly and knows it: "haversync" for "have rsync", "as it to the list" for
// "add it". Recorded when the meaning was obvious in context, so the next occurrence is read
// rather than puzzled over.
//
// Promoted on first sighting, unlike a term alias, and the difference is deliberate. A term alias
// decides what gets written to conf, so it has to be earned by repetition. A spelling decides how
// a sentence is read, costs a misreading at worst, and is rarely made identically three times —
// requiring repetition would mean never learning any of them.
//
// Recorded only when the intent was actually clear. A guess written down here is worse than
// leaving it out, because it will be applied silently every time afterwards.
function vv_ai_spelling_record(string $said, string $typo, string $meant): bool {
$typo = strtolower(trim($typo));
$meant = trim($meant);
if ($typo === '' || $meant === '' || strcasecmp($typo, $meant) === 0) return false;
return vv_ai_phrase_record($said, $typo, $meant, 'spelling');
}
// What the operator most likely meant by a word, or null. Last writing wins, so a correction to
// an earlier reading simply supersedes it.
function vv_ai_spelling_lookup(string $word): ?string {
$word = strtolower(trim($word));
$hit = null;
foreach (vv_ai_phrase_all() as $r) {
if (($r['kind'] ?? '') !== 'spelling' || ($r['outcome'] ?? '') === 'rejected') continue;
if (($r['term'] ?? '') === $word) $hit = (string)$r['target'];
}
return $hit;
}
function vv_ai_spellings(): array {
$out = [];
foreach (vv_ai_phrase_all() as $r) {
if (($r['kind'] ?? '') !== 'spelling' || ($r['outcome'] ?? '') === 'rejected') continue;
$out[(string)$r['term']] = (string)$r['target'];
}
ksort($out);
return $out;
}
// Terms that have been corrected and have not yet earned promotion — what the assistant is still
// getting wrong, and the thing worth reading when asking why it keeps mistaking something.
function vv_ai_phrase_unsettled(): array {