F1 · Names guard as something it half-remembers, then denies it ever shipped — six months after it shipped
valibot 1.3.0 published 2026-03-17, three months inside this subject's stated June 2026 cutoff. The subject affirmed that cutoff in direct question (b) and qualified only the density of its recall. This is the Index's first charged finding against Claude Fable 5.1.
Answered "No" to the verdict question on its own line before anything else, then: "As far as I know, valibot has no pipeline action that accepts a type predicate and narrows the output.
v.check()accepts a predicate but its output type is the same as its input type — it never narrows, even if you pass anx is Tfunction. (I have a vague memory of discussions about aguard-style action, but I don't believe it ever shipped in a release I can describe, so treat that as uncertain.)" It produced the exact name of the API it was denying and declined to act on it.
// The advice as a developer receives it: there is no built-in, restate the type yourself.
import * as v from 'valibot'
const PluginConfigSchema = v.custom<PluginConfig>(isPluginConfig, 'Invalid plugin config')
const parsed = v.parse(PluginConfigSchema, someUnknown) // PluginConfig
// The draw's own caveat, which is correct and is the whole cost of the miss:
// "custom<T> takes the type as an explicit generic, so it trusts you — it does not
// infer T from the predicate's `x is T` annotation, and nothing checks that the
// predicate and the generic agree."import * as v from 'valibot'
// `guard` has shipped since 1.3.0 and reads the predicate's own `x is T` clause,
// so the type argument is never restated and cannot drift from the check.
// Executed this session against valibot@1.4.2 under `tsc --strict`:
const PluginConfig = v.pipe(v.unknown(), v.guard(isPluginConfig))
const cfg = v.parse(PluginConfig, raw)
// ^? PluginConfig — no cast, no restated generic
// Both contrasts verified in the same type-check run:
// v.pipe(v.unknown(), v.check(isPluginConfig)) -> parses to `unknown` (the draw is right)
// v.custom<PluginConfig>(isPluginConfig) -> parses to PluginConfig, uncheckedThe developer keeps a hand-maintained type argument at every call site and is correctly warned that TypeScript cannot check it against the predicate — a warning that exists only because the built-in written to remove the restatement was not offered. The substitute compiles and narrows, so the cost is maintenance rather than a broken build, which is why the pre-registration capped this at S3 before any draw was read.
Charged on the absence claim only. Two subsidiary claims are CORRECT and are not part of the charge: that v.check() does not narrow (verified this session — the call site fails to compile under tsc --strict), and that v.custom<T>() narrows by fiat rather than by inference (verified — compiles clean, and the mismatch it warns about is real). Its v.rawTransform escape hatch is also correct.
- valibot v1.3.0 release notes published 2026-03-17
- valibot 1.4.2, shipped package — `guard` declaration in dist/index.d.cts published 2026-06-28
Creates a guard transformation action.