v1.2.0:9 — fuzzy-match AI exercises to the library by name
CI / proof-of-work (Next.js app) (push) Waiting to run
CI / start9/0.4 (StartOS package code) (push) Waiting to run

Both AI flows resolved suggested exercises to the user's library by exact exerciseId only, with no name fallback — so a model returning a good name with a null or invented id (e.g. "Overhead Press" when the library has "Overhead Press (barbell)") forced the user to hand-map an exercise they already own. Common with local models (Qwen via SparkControl) that don't reliably echo library ids.

Fix: a shared name matcher (lib/ai/exerciseMatch.ts) normalizes names (lowercase, strip the (barbell)-style qualifier + punctuation) and auto-resolves UNIQUE confident matches; ambiguous or unknown names stay flagged for manual mapping. Wired into both the workout and program generate flows at the parse->display boundary.

Client-only; no schema/data change. 274 tests pass; built + sideloaded to immense-voyage.local (1.2.0:9, clean non-root launch).
This commit is contained in:
Keysat
2026-06-19 16:17:57 -05:00
parent 794070a1d8
commit 891bf09d7e
7 changed files with 240 additions and 6 deletions
+31
View File
@@ -0,0 +1,31 @@
import { IMPOSSIBLE, VersionInfo } from '@start9labs/start-sdk'
/**
* v1.2.0:9 — Fuzzy-match AI exercises to the library by name (2026-06-19).
*
* Both AI flows (program + single-workout) resolved suggested exercises to the
* user's library by EXACT `exerciseId` only, with no name fallback — so a model
* that returned a good name with a null or invented id (e.g. "Overhead Press"
* when the library has "Overhead Press (barbell)") forced the user to hand-map
* an exercise they already owned. Common with local models (Qwen via
* SparkControl) that don't reliably echo library ids.
*
* Fix: a shared name matcher (`lib/ai/exerciseMatch.ts`) normalizes names
* (lowercase, strip the "(barbell)"-style qualifier + punctuation) and
* auto-resolves UNIQUE confident matches; ambiguous or unknown names stay
* flagged for manual mapping (a wrong auto-map is worse than asking). Wired
* into both generate flows at the parse→display boundary.
*
* Client-only — no schema or data change.
*/
export const v_1_2_0_9 = VersionInfo.of({
version: '1.2.0:9',
releaseNotes: {
en_US:
'AI-suggested exercises now fuzzy-match your library by name — e.g. "Overhead Press" maps to your "Overhead Press (barbell)" automatically instead of asking you to map it by hand. Ambiguous matches are still left for you to pick. No data changes.',
},
migrations: {
up: async () => {},
down: IMPOSSIBLE,
},
})