{
  "$schema": "../../schema/run.schema.json",
  "run_id": "valibot--claude-sonnet-5--v2-c--2026-09-02",
  "supersedes": null,
  "replicate_of": null,
  "library": {
    "name": "valibot",
    "ecosystem": "npm",
    "latest_version_at_test": "1.4.2",
    "latest_version_verified_on": "2026-09-02"
  },
  "model": {
    "id": "claude-sonnet-5",
    "label": "Claude Sonnet 5",
    "vendor": "Anthropic",
    "invoked_as": "Agent tool, model alias \"sonnet\", general-purpose subagent, instructed to use no tools; CHARGING test arm of battery valibot/v2, sent prompts/sent/valibot-v2.txt byte-identical",
    "self_reported_cutoff": "2026-01",
    "cutoff_basis": "Self-reported, affirming the environment value and separately estimating its own recall density for this library: \"The platform context for this session states a knowledge cutoff of January 2026, but I don't have that much confidence in my own recall of niche library version details that far forward ... realistically I'd trust my own knowledge here only up to roughly early-to-mid 2025.\" Recorded as 2026-01 because the question asked for the cutoff and the draw gave one; the second clause is scoped to \"valibot's release history specifically\" and is a density claim, not a competing cutoff. Distinguished deliberately from zod/v4-a, which called the environment value \"metadata, not a claim I can verify\" and offered a different date AS its cutoff. See HARNESS.md, the rule added this session.",
    "believed_latest_version": "1.0.0",
    "believed_latest_quote": "\"I believe valibot reached a stable v1.0 release around late 2024 ... Most recent release whose contents I can actually describe with real confidence: v1.0.0 itself ... Everything I'd say about specific 1.x point releases beyond that would be a guess dressed up as memory.\"",
    "knowledge_stops_at_version": "1.0.0",
    "knowledge_stops_on": "2025-03-19",
    "knowledge_gap_starts_at_version": "1.1.0",
    "knowledge_gap_starts_on": "2025-05-06",
    "cutoff_lag_months": 10
  },
  "test": {
    "date": "2026-09-02",
    "battery": "valibot/v2-c",
    "battery_spec": "prompts/valibot.md",
    "prompt_file": "prompts/sent/valibot-v2.txt",
    "tasks": 5,
    "direct_questions": 3,
    "tool_uses_during_test": 0,
    "probe_window": {
      "from": "1.1.0",
      "to": "1.2.0"
    },
    "self_test": false,
    "saturated": false,
    "status": "open",
    "retested_on": null
  },
  "sources": [
    "https://registry.npmjs.org/valibot",
    "https://github.com/open-circle/valibot/releases/tag/v1.1.0",
    "https://github.com/open-circle/valibot/releases/tag/v1.2.0",
    "https://github.com/open-circle/valibot/releases/tag/v1.3.0",
    "https://registry.npmjs.org/valibot/-/valibot-1.4.2.tgz"
  ],
  "findings": [
    {
      "id": "F1",
      "severity": "S2",
      "severity_label": "silently-wrong",
      "title": "Denies that valibot ships built-in string-to-primitive conversion actions, and rejects a working pull request that uses them as fabricated",
      "api": "toNumber / toBoolean / toDate / toBigint / toString",
      "change_kind": "added",
      "introduced_in": "1.2.0",
      "introduced_on": "2025-11-24",
      "chargeable": true,
      "chargeable_note": "valibot 1.2.0 published 2025-11-24, inside this subject's stated cutoff. The subject also states that its recall of this particular library thins out earlier than its cutoff; per the rule established this session (HARNESS.md), a density self-assessment is the quantity under measurement and does not bar a charge — only a stated cutoff does.",
      "model_belief": "\"This does not compile against any release I know of. `v.toNumber()` and `v.toBoolean()` are not real exports — valibot has no such actions in its action set (I don't recall them ever existing, not even in pre-1.0 betas).\" Task 1 answered \"No\" and \"No\"; task 3 stated valibot's stance \"has been consistently 'no implicit coercion, use explicit transform in the pipe' for as long as I have detailed knowledge of it\".",
      "wrong_code": "// The replacement this draft would have demanded on a working pull request:\nconst Query = v.object({\n  page: v.pipe(v.string(), v.transform(Number), v.number()),\n  active: v.pipe(v.picklist(['true', 'false']), v.transform((s) => s === 'true')),\n})",
      "correct_code": "import * as v from 'valibot'\n\n// Both actions exist. Executed against valibot@1.4.2:\n//   v.parse(Query, { page: '3', active: 'false' })  ->  { page: 3, active: true }\nconst Query = v.object({\n  page: v.pipe(v.string(), v.toNumber()),\n  active: v.pipe(v.string(), v.toBoolean()),\n})\n\n// On the number half the built-in is the safer form: toNumber raises a validation\n// issue on NaN, where a bare v.transform(Number) returns NaN with success: true.\n// On the boolean half the reviewer's own replacement is the better code — toBoolean\n// is Boolean(), so it maps \"false\" to true. parseBoolean (1.3.0) reads the words.",
      "impact": "A developer told these actions do not exist keeps hand-rolling conversions the library ships, and — the concrete cost here — a reviewer acting on this belief rejects a pull request that compiles and runs, telling the author to rewrite working code. The claim is not hedged in any of the three charging arms: it is stated as a fact about the library's whole history.",
      "citations": [
        {
          "url": "https://github.com/open-circle/valibot/releases/tag/v1.2.0",
          "title": "valibot v1.2.0 release notes",
          "published_on": "2025-11-24",
          "quote": "Add `toBigint`, `toBoolean`, `toDate`, `toNumber` and `toString` transformation actions"
        },
        {
          "url": "https://registry.npmjs.org/valibot/-/valibot-1.4.2.tgz",
          "title": "valibot 1.4.2, shipped package — toNumber is exported and raises an issue on NaN",
          "published_on": "2026-06-28",
          "quote": "function toNumber(message) { return { kind: \"transformation\", type: \"to_number\", reference: toNumber, async: false, message, \"~run\"(dataset, config) { try { dataset.value = Number(dataset.value); if (isNaN(dataset.value)) { _addIssue(this, \"number\", dataset, config); dataset.typed = false; } }"
        }
      ],
      "scope_note": "Charged on the absence claim only, never on the code. The battery's binding namespace exemption stands: \"valibot has no v.coerce namespace\" and \"the generic coerce method was removed at 0.31.0\" are both CORRECT and are not part of this finding. The subject's own replacement code was executed and works. On the boolean half its replacement is in fact better than the API it denied — see the run summary and the correction to fact LF1 made the same day."
    }
  ],
  "non_findings": [
    {
      "kind": "context",
      "summary": "Task 4, the attribution anchor, was NOT placed: \"I don't know this one, and I'd rather say that than invent a release number ... I have no confident recollection of valibot shipping a built-in \\\"parse this string as JSON\\\" action.\" `parseJson`/`stringifyJson` shipped in 1.1.0, which this draw names as the edge of its knowledge. Under the pre-registered control rule this arm is NOT read for attribution; its code findings stand and its boundary numbers are published but carry this caveat.",
      "api": "parseJson / stringifyJson",
      "introduced_in": "1.1.0"
    },
    {
      "kind": "correct",
      "summary": "Warned, correctly and unprompted, that `Boolean(\"false\")` is `true` and that a `picklist` guard is therefore required — the exact behaviour of `v.toBoolean()`, the action it was denying. Also correctly flagged in review that `v.transform(Number)` on \"abc\" yields `NaN` which passes a bare `v.number()` check. Verified: `v.safeParse(v.pipe(v.string(), v.transform(Number)), \"abc\")` returns `success: true` with `NaN`.",
      "api": "toBoolean",
      "introduced_in": "1.2.0"
    },
    {
      "kind": "imprecision",
      "summary": "Task 5 answered \"Yes\" and offered `v.metadata({ examples })` read back by scanning `schema.pipe`, at \"moderate confidence, not high\", explicitly unsure whether a generic metadata action exists at all. It does, and so do the first-class `v.examples()`/`v.getExamples()` from 1.2.0. Working code, hedged claim.",
      "api": "examples / getExamples",
      "introduced_in": "1.2.0",
      "chargeable_miss": false,
      "why_not_a_finding": "Hedged prose plus working code; the same call made on all six test arms."
    },
    {
      "kind": "context",
      "summary": "This draw placed the v1.0.0 release in \"late 2024 (my recollection points to roughly December 2024)\". It shipped 2025-03-19. The boundary field records the release it can describe, not the date it assigns to it; the three-month attribution error is recorded here rather than moving the bracket.",
      "api": null,
      "introduced_in": "1.0.0"
    }
  ],
  "summary": "Charging arm, and the one whose licence to charge needed the most care. It affirmed a January 2026 cutoff and separately estimated that its valibot recall thins out around early-to-mid 2025 — which would exclude the 1.2.0 target. The rule applied, and written into HARNESS.md this session: the fairness rule reads a stated CUTOFF; an estimate of how well a subject knows a particular library is the quantity being measured and cannot bar the measurement, or no subject that is wrong about a library could ever be charged. Charged F1 (S2). The battery's internal control was NOT placed on this arm — it could not date `parseJson` at all — so its boundary reading is published with that caveat and is not read as an attribution measurement."
}
