Files
proof-of-work/start9/0.4/startos/versions/v1.2.0.8.ts
T
Keysat 794070a1d8
CI / proof-of-work (Next.js app) (push) Waiting to run
CI / start9/0.4 (StartOS package code) (push) Waiting to run
v1.2.0:8 — tolerate decimal integers in AI output
Local models (Qwen via SparkControl, surfaced on the first SparkControl smoke test) sometimes emit a decimal where the AI-output schema expects an integer — e.g. a half-step "rpe": 7.5 or "reps": 8.0. Zod's .int() rejected these and failed the ENTIRE parse, so one stray decimal killed an otherwise good generation.

Fix: a shared looseInt helper rounds a number to the nearest int before the .int() check, applied to every integer field in both the program and single-workout schemas (rpe, reps, sets, gear, order, durationSeconds, rest/week/day numbers). RPE/reps/sets are stored as integers downstream, so rounding is the correct landing. Transform-before-validate, so inferred types are unchanged.

Parse-only; no schema/data change. 261 tests pass; built + sideloaded to immense-voyage.local (1.2.0:8, clean non-root launch). SparkControl now confirmed working end-to-end.
2026-06-19 15:30:06 -05:00

32 lines
1.3 KiB
TypeScript

import { IMPOSSIBLE, VersionInfo } from '@start9labs/start-sdk'
/**
* v1.2.0:8 — Tolerate decimal integers in AI output (2026-06-19).
*
* Local models (notably Qwen via SparkControl, surfaced on the first
* SparkControl smoke test) sometimes emit a decimal where the AI-output
* schema expects an integer — e.g. a half-step `"rpe": 7.5`, or `"reps": 8.0`.
* Zod's `.int()` rejected these and failed the ENTIRE parse ("JSON did not
* match the expected shape"), so a single stray decimal killed an otherwise
* good generation.
*
* Fix: a shared `looseInt` helper rounds a number to the nearest integer
* BEFORE the `.int()` check, applied to every integer field in both the
* program and single-workout schemas (rpe, reps, sets, gear, order,
* durationSeconds, rest/week/day numbers, …). RPE/reps/sets are stored as
* integers downstream, so rounding is the correct landing.
*
* Client-/parse-only — no schema or data change.
*/
export const v_1_2_0_8 = VersionInfo.of({
version: '1.2.0:8',
releaseNotes: {
en_US:
'AI generation is now tolerant of decimal values from local models (e.g. a half-step RPE like 7.5) — they round to the nearest whole number instead of failing the whole generation. No data changes.',
},
migrations: {
up: async () => {},
down: IMPOSSIBLE,
},
})