@ts-runtypes/devtools 0.11.0 → 0.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. package/dist/eslint/diagnosticRouting.d.ts.map +1 -1
  2. package/dist/eslint/diagnosticRouting.js +1 -1
  3. package/dist/eslint/diagnosticRouting.js.map +1 -1
  4. package/dist/eslint/index.d.ts.map +1 -1
  5. package/dist/eslint/index.js +8 -3
  6. package/dist/eslint/index.js.map +1 -1
  7. package/dist/eslint/lint-worker.js +1 -29
  8. package/dist/eslint/lint-worker.js.map +1 -1
  9. package/dist/eslint/prefilter.d.ts +8 -2
  10. package/dist/eslint/prefilter.d.ts.map +1 -1
  11. package/dist/eslint/prefilter.js +8 -5
  12. package/dist/eslint/prefilter.js.map +1 -1
  13. package/dist/eslint/session-protocol.d.ts +8 -0
  14. package/dist/eslint/session-protocol.d.ts.map +1 -1
  15. package/dist/eslint/session-protocol.js +1 -1
  16. package/dist/eslint/session-protocol.js.map +1 -1
  17. package/dist/go-generated/diagnosticCatalog.generated.d.ts.map +1 -1
  18. package/dist/go-generated/diagnosticCatalog.generated.js +294 -274
  19. package/dist/go-generated/diagnosticCatalog.generated.js.map +1 -1
  20. package/dist/go-generated/runtypes-constants.generated.d.ts +8 -0
  21. package/dist/go-generated/runtypes-constants.generated.d.ts.map +1 -1
  22. package/dist/go-generated/runtypes-constants.generated.js +4 -0
  23. package/dist/go-generated/runtypes-constants.generated.js.map +1 -1
  24. package/dist/go-generated/tsconfig-plugin-keys.generated.d.ts +1 -1
  25. package/dist/go-generated/tsconfig-plugin-keys.generated.d.ts.map +1 -1
  26. package/dist/go-generated/tsconfig-plugin-keys.generated.js +4 -2
  27. package/dist/go-generated/tsconfig-plugin-keys.generated.js.map +1 -1
  28. package/dist/packages/ts-runtypes-devtools/tsconfig.test.tsbuildinfo +1 -1
  29. package/dist/plugin-option-keys.d.ts.map +1 -1
  30. package/dist/plugin-option-keys.js +5 -2
  31. package/dist/plugin-option-keys.js.map +1 -1
  32. package/dist/protocol.d.ts +1 -10
  33. package/dist/protocol.d.ts.map +1 -1
  34. package/dist/protocol.js.map +1 -1
  35. package/dist/resolver-client.d.ts +15 -11
  36. package/dist/resolver-client.d.ts.map +1 -1
  37. package/dist/resolver-client.js +25 -22
  38. package/dist/resolver-client.js.map +1 -1
  39. package/dist/unplugin.d.ts +8 -2
  40. package/dist/unplugin.d.ts.map +1 -1
  41. package/dist/unplugin.js +26 -15
  42. package/dist/unplugin.js.map +1 -1
  43. package/package.json +3 -3
@@ -1,375 +1,395 @@
1
1
  export const DIAGNOSTIC_CATALOG = {
2
2
  CES001: {
3
- headline: '`cloneExactShape` does not support unions with object members the emitter cannot know which declared shape to rebuild at runtime.',
3
+ headline: '`cloneExactShape` does not support unions with object members: the emitter cannot know which declared shape to rebuild at runtime.',
4
4
  severity: 'error',
5
5
  detail: 'A clone built from the declared shape needs to know WHICH union arm the\nruntime value matches; v1 has no arm discrimination, and silently keeping\nunknown keys would defeat the strip guarantee, so the build fails instead.\n\nWorkarounds: narrow the value to one arm before cloning (one\n`createCloneExactShapeFn<Arm>()` per arm), or restructure the union into a\nsingle object with optional properties.',
6
6
  },
7
7
  CES003: {
8
8
  headline: '`cloneExactShape` cannot clone a function-typed value.',
9
9
  severity: 'error',
10
- detail: "Functions aren't data there is no declared shape to rebuild. Function-typed\nPROPERTIES are dropped from the clone (CES010/CES011); a function at the root\nor a propagating position fails the build.",
10
+ detail: "Functions aren't data: there is no declared shape to rebuild. Function-typed\nPROPERTIES are dropped from the clone (CES010/CES011); a function at the root\nor a propagating position fails the build.",
11
11
  },
12
12
  CES010: {
13
- headline: 'Property `{0}` is a function `cloneExactShape` cannot rebuild it, so it is kept on the clone, SHARED BY REFERENCE.',
13
+ headline: 'Property `{0}` is a function: `cloneExactShape` cannot rebuild it, so it is kept on the clone, SHARED BY REFERENCE.',
14
14
  severity: 'warning',
15
- detail: "Declared members are never dropped (only UNDECLARED keys are that is the\nstrip guarantee). Functions cannot be rebuilt from a declared shape, so the\nclone's property points at the SAME function as the input's. Class METHODS\ndiffer: they ride the shared prototype and are not copied as own props\n(CES011).",
15
+ detail: "Declared members are never dropped (only UNDECLARED keys are; that is the\nstrip guarantee). Functions cannot be rebuilt from a declared shape, so the\nclone's property points at the SAME function as the input's. Class METHODS\ndiffer: they ride the shared prototype and are not copied as own props\n(CES011).",
16
16
  },
17
17
  CES011: {
18
- headline: "Method `{0}` is not copied onto the clone's own properties methods ride the prototype.",
18
+ headline: "Method `{0}` is not copied onto the clone's own properties: methods ride the prototype.",
19
19
  severity: 'warning',
20
20
  detail: 'For a plain class instance the clone preserves the PROTOTYPE\n(`Object.create(Object.getPrototypeOf(v))`), so methods keep working via the\nprototype chain; they are simply not copied as own properties. For object\nliterals a method-typed member is omitted like any function value.',
21
21
  },
22
22
  CES012: {
23
- headline: 'Static member `{0}` is not part of instance data `cloneExactShape` skips it.',
23
+ headline: 'Static member `{0}` is not part of instance data: `cloneExactShape` skips it.',
24
24
  severity: 'warning',
25
25
  detail: 'Statics live on the class, not the instance; the clone rebuilds instance\ndata only.',
26
26
  },
27
27
  CES015: {
28
- headline: 'Property `{0}` has a value type `cloneExactShape` cannot rebuild (symbol, Promise, or a non-serialisable built-in) it is kept on the clone, SHARED BY REFERENCE.',
28
+ headline: 'Property `{0}` has a value type `cloneExactShape` cannot rebuild (symbol, Promise, or a non-serialisable built-in): it is kept on the clone, SHARED BY REFERENCE.',
29
29
  severity: 'warning',
30
- detail: "Declared members are never dropped (only UNDECLARED keys are that is the\nstrip guarantee). A value the emitter cannot rebuild passes through by\nreference instead: the clone's property points at the SAME handle as the\ninput's, so mutations through it are visible on both sides. Register\n`overrideCloneExactShape<T>()` if this type needs custom copying.",
30
+ detail: "Declared members are never dropped (only UNDECLARED keys are; that is the\nstrip guarantee). A value the emitter cannot rebuild passes through by\nreference instead: the clone's property points at the SAME handle as the\ninput's, so mutations through it are visible on both sides. Register\n`overrideCloneExactShape<T>()` if this type needs custom copying.",
31
31
  },
32
32
  CFG001: {
33
- headline: 'Project tsconfig failed to load ({0}) the build, the linter, and the CLI all read this config, so nothing can run until it loads.',
33
+ headline: 'Project tsconfig failed to load ({0}): the build, the linter, and the CLI all read this config, so nothing can run until it loads.',
34
34
  severity: 'error',
35
- detail: 'RunTypes derives every type query from your project tsconfig, the same\nfile your build uses. A tsconfig that was named (or found next to your\nproject) but is missing or does not parse stops the operation, exactly\nlike `tsc --project` would, instead of silently falling back to defaults\nthat could resolve your types differently.\n\nFix repair the tsconfig (the message names the first parse problem),\nor point the tooling at the right file (the plugin/lint `tsconfig`\nsetting, or the CLI `--tsconfig` flag).',
35
+ detail: 'RunTypes derives every type query from your project tsconfig, the same\nfile your build uses. A tsconfig that was named (or found next to your\nproject) but is missing or does not parse stops the operation, exactly\nlike `tsc --project` would, instead of silently falling back to defaults\nthat could resolve your types differently.\n\nFix: repair the tsconfig (the message names the first parse problem),\nor point the tooling at the right file (the plugin/lint `tsconfig`\nsetting, or the CLI `--tsconfig` flag).',
36
36
  },
37
37
  CLS001: {
38
38
  headline: 'class `{0}` is serialized structurally; register it via `registerClassSerializer({0}, { deserialize })` to round-trip a real instance.',
39
39
  severity: 'warning',
40
- detail: "By default a user class is serialized by its declared properties and\ndecoded back to a prototype-less plain object `instanceof {0}` is\nfalse on the decoded value, and any class methods / getters are gone.\nThis is fine when you only care about the data.\n\nTo round-trip a real `{0}` instance, register it once, passing the class\nitself (not a name string):\n import {registerClassSerializer} from '@ts-runtypes/core';\n\n // zero-arg constructor: nothing else needed\n registerClassSerializer({0});\n\n // non-empty constructor: only `deserialize` is required\n registerClassSerializer({0}, {\n deserialize: (data) => new {0}(/* rebuild from data */),\n });\n\n`serialize` is optional (default: structural, same as any interface);\n`deserialize` is optional for a zero-arg class (default:\n`Object.assign(new {0}(), data)`). The same registration is used by the\nJSON and binary families. `validate` / `getValidationErrors` are\nunaffected they always validate structurally.",
40
+ detail: "By default a user class is serialized by its declared properties and\ndecoded back to a prototype-less plain object: `instanceof {0}` is\nfalse on the decoded value, and any class methods / getters are gone.\nThis is fine when you only care about the data.\n\nTo round-trip a real `{0}` instance, register it once, passing the class\nitself (not a name string):\n import {registerClassSerializer} from '@ts-runtypes/core';\n\n // zero-arg constructor: nothing else needed\n registerClassSerializer({0});\n\n // non-empty constructor: only `deserialize` is required\n registerClassSerializer({0}, {\n deserialize: (data) => new {0}(/* rebuild from data */),\n });\n\n`serialize` is optional (default: structural, same as any interface);\n`deserialize` is optional for a zero-arg class (default:\n`Object.assign(new {0}(), data)`). The same registration is used by the\nJSON and binary families. `validate` / `getValidationErrors` are\nunaffected: they always validate structurally.",
41
41
  },
42
42
  CTA001: {
43
43
  headline: '`CompTimeArgs<T>` argument must be a literal at the call site, or a `const` whose initializer is itself entirely literal (a same-module or imported `const` both work).',
44
44
  severity: 'error',
45
- detail: "The build resolves the argument before running, so it needs to read its\nvalue from the source. Function-call results, property accesses, ternary\nexpressions, and `let`/`var` bindings can't be evaluated at build time.\nAccepted: an inline literal, or a `const` whose initializer is itself\nfully literal including a `const` imported from another module. (An\nobject `const` must be `as const` so its members stay literal; see CTA004.)\n\nFix inline at the call site:\n- const opts = getOpts();\n- const isUser = createValidateFn<User>(undefined, opts);\n+ const isUser = createValidateFn<User>(undefined, {mode: 'unsafe'});\n\nFix use a const of literals (here or in another module):\n const opts = {mode: 'unsafe'} as const; // literal initializer ✓\n const isUser = createValidateFn<User>(undefined, opts);",
45
+ detail: "The build resolves the argument before running, so it needs to read its\nvalue from the source. Function-call results, property accesses, ternary\nexpressions, and `let`/`var` bindings can't be evaluated at build time.\nAccepted: an inline literal, or a `const` whose initializer is itself\nfully literal, including a `const` imported from another module. (An\nobject `const` must be `as const` so its members stay literal; see CTA004.)\n\nFix: inline at the call site:\n- const opts = getOpts();\n- const isUser = createValidateFn<User>(undefined, opts);\n+ const isUser = createValidateFn<User>(undefined, {mode: 'unsafe'});\n\nFix: use a const of literals (here or in another module):\n const opts = {mode: 'unsafe'} as const; // literal initializer ✓\n const isUser = createValidateFn<User>(undefined, opts);",
46
46
  },
47
47
  CTA002: {
48
- headline: '`CompTimeArgs<T>` literal nesting exceeds the depth cap (16) refactor to flatten.',
48
+ headline: '`CompTimeArgs<T>` literal nesting exceeds the depth cap (16), refactor to flatten.',
49
49
  severity: 'error',
50
- detail: 'Deeply nested literal walks are capped at 16 levels to keep the build\npredictable. If you hit this, the value is almost certainly not what\nyou want at compile time split it across multiple smaller\n`CompTimeArgs<T>` arguments, or flatten the nesting.',
50
+ detail: 'Deeply nested literal walks are capped at 16 levels to keep the build\npredictable. If you hit this, the value is almost certainly not what\nyou want at compile time: split it across multiple smaller\n`CompTimeArgs<T>` arguments, or flatten the nesting.',
51
51
  },
52
52
  CTA003: {
53
53
  headline: '`CompTimeArgs<T>` literal contains a forbidden construct ({0}). Only literals and nested literals are allowed.',
54
54
  severity: 'error',
55
- detail: "The Go scanner cannot statically evaluate computed property names,\nfunction calls, ternary expressions, or template-string substitutions.\nInside a `CompTimeArgs<T>` literal every node must be a direct literal\n(string / number / bigint / boolean / null / undefined / regex / arrow /\nobject literal / array literal) or a const-traced identifier that\nresolves to one.\n\nSpread IS allowed when its operand resolves to a literal container of the\nmatching kind a `const`-bound (or imported) object literal for an\nobject spread, an array literal for an array spread:\n const base = {strict: true};\n const a = {...base, mode: 'unsafe'}; // ok merges a const fragment\n\nA spread is still rejected when the operand can't be statically merged —\na dynamic value, or a shape mismatch:\n - const a = {...getDefaults(), mode: 'unsafe'}; // dynamic operand\n - const a = {...[1, 2], mode: 'unsafe'}; // object spread of an array",
55
+ detail: "The Go scanner cannot statically evaluate computed property names,\nfunction calls, ternary expressions, or template-string substitutions.\nInside a `CompTimeArgs<T>` literal every node must be a direct literal\n(string / number / bigint / boolean / null / undefined / regex / arrow /\nobject literal / array literal) or a const-traced identifier that\nresolves to one.\n\nSpread IS allowed when its operand resolves to a literal container of the\nmatching kind: a `const`-bound (or imported) object literal for an\nobject spread, an array literal for an array spread:\n const base = {strict: true};\n const a = {...base, mode: 'unsafe'}; // ok, merges a const fragment\n\nA spread is still rejected when the operand can't be statically merged:\na dynamic value, or a shape mismatch:\n - const a = {...getDefaults(), mode: 'unsafe'}; // dynamic operand\n - const a = {...[1, 2], mode: 'unsafe'}; // object spread of an array",
56
56
  },
57
57
  CTA004: {
58
- headline: '`CompTimeArgs<T>` value comes from a `const` with a widened (non-literal) member ({0}) declare the const `as const`.',
58
+ headline: '`CompTimeArgs<T>` value comes from a `const` with a widened (non-literal) member ({0}); declare the const `as const`.',
59
59
  severity: 'error',
60
- detail: "A `const` used as a CompTimeArgs / CompTimeFnArgs argument (a whole option\nbag, or a builder child) must carry LITERAL value types, so the value the\nbuild reads matches the type TypeScript resolves the call against. Without\n`as const`, an object literal's members widen `{strategy: 'mutate'}`\nbecomes `{strategy: string}` which can let the type system select one\nfunction variant while the build injects another.\n\nWhole imported consts now resolve cross-module (like a spread fragment), so\nthis rule keeps that path sound.\n\nFix add `as const`:\n- const preset = {strategy: 'mutate'};\n+ const preset = {strategy: 'mutate'} as const;\n createJsonEncoderFn(undefined, preset);",
60
+ detail: "A `const` used as a CompTimeArgs / CompTimeFnArgs argument (a whole option\nbag, or a builder child) must carry LITERAL value types, so the value the\nbuild reads matches the type TypeScript resolves the call against. Without\n`as const`, an object literal's members widen (`{strategy: 'mutate'}`\nbecomes `{strategy: string}`), which can let the type system select one\nfunction variant while the build injects another.\n\nWhole imported consts now resolve cross-module (like a spread fragment), so\nthis rule keeps that path sound.\n\nFix: add `as const`:\n- const preset = {strategy: 'mutate'};\n+ const preset = {strategy: 'mutate'} as const;\n createJsonEncoderFn(undefined, preset);",
61
61
  },
62
62
  FB001: {
63
- headline: 'Type `{0}` can never be deserialised from binary the generated function will always fail.',
63
+ headline: 'Type `{0}` can never be deserialised from binary: the generated function will always fail.',
64
64
  severity: 'error',
65
- detail: "`never` is the empty type no value can ever inhabit it. A field\ntyped `never` cannot carry a runtime value, so there is nothing to\nencode/decode/validate.\n\nFix use `unknown` if you really want to accept any value:\n interface User {\n- tag: never;\n+ tag: unknown; // narrow before use\n }\n\nFix pick a concrete type matching your real data:\n interface User {\n- tag: never;\n+ tag: 'pending' | 'active' | 'done';\n }",
65
+ detail: "`never` is the empty type: no value can ever inhabit it. A field\ntyped `never` cannot carry a runtime value, so there is nothing to\nencode/decode/validate.\n\nFix: use `unknown` if you really want to accept any value:\n interface User {\n- tag: never;\n+ tag: unknown; // narrow before use\n }\n\nFix: pick a concrete type matching your real data:\n interface User {\n- tag: never;\n+ tag: 'pending' | 'active' | 'done';\n }",
66
66
  },
67
67
  FB002: {
68
- headline: 'Type `{0}` can never be deserialised from binary the generated function will always fail.',
68
+ headline: 'Type `{0}` can never be deserialised from binary: the generated function will always fail.',
69
69
  severity: 'error',
70
- detail: "Built-in classes like `Map`, `Set`, `WeakMap`, `WeakSet`, `Int8Array`,\n`Uint8Array`, `Buffer`, and `Promise` carry runtime state that doesn't\nsurvive a JSON or binary round-trip. Their instance identity is lost the\nmoment they're serialised.\n\nFix convert to a plain object/array before serialising:\n // for Map<K, V>:\n const data = Object.fromEntries(yourMap);\n // for Set<T>:\n const data = [...yourSet];\n // for typed arrays:\n const data = Array.from(yourBuffer);\n\nFix change the field type to a serialisable shape:\n interface User {\n- tags: Set<string>;\n+ tags: string[];\n }",
70
+ detail: "Built-in classes like `Map`, `Set`, `WeakMap`, `WeakSet`, `Int8Array`,\n`Uint8Array`, `Buffer`, and `Promise` carry runtime state that doesn't\nsurvive a JSON or binary round-trip. Their instance identity is lost the\nmoment they're serialised.\n\nFix: convert to a plain object/array before serialising:\n // for Map<K, V>:\n const data = Object.fromEntries(yourMap);\n // for Set<T>:\n const data = [...yourSet];\n // for typed arrays:\n const data = Array.from(yourBuffer);\n\nFix: change the field type to a serialisable shape:\n interface User {\n- tags: Set<string>;\n+ tags: string[];\n }",
71
71
  },
72
72
  FB003: {
73
- headline: 'Type `{0}` can never be deserialised from binary the generated function will always fail.',
73
+ headline: 'Type `{0}` can never be deserialised from binary: the generated function will always fail.',
74
74
  severity: 'error',
75
- detail: "Functions have no value form to serialise their closure, prototype,\nand bound state aren't representable in JSON or binary.\n\nFix drop the function from your type, or replace it with the data the\nfunction would produce:\n interface User {\n- getName: () => string;\n+ name: string;\n }",
75
+ detail: "Functions have no value form to serialise: their closure, prototype,\nand bound state aren't representable in JSON or binary.\n\nFix: drop the function from your type, or replace it with the data the\nfunction would produce:\n interface User {\n- getName: () => string;\n+ name: string;\n }",
76
76
  },
77
77
  FB004: {
78
- headline: 'Type `{0}` can never be deserialised from binary the generated function will always fail.',
78
+ headline: 'Type `{0}` can never be deserialised from binary: the generated function will always fail.',
79
79
  severity: 'error',
80
- detail: "Arrays of un-serialisable elements (`symbol[]`, `(() => void)[]`,\n`Map<K, V>[]`, etc.) can't be encoded every element would need to be\nrepresentable, and these aren't. Dropping individual elements would\nchange the array length, so the encoder refuses rather than silently\nshipping a different shape.\n\nFix change the element type to something serialisable:\n - type Items = (() => void)[];\n+ type Items = string[];",
80
+ detail: "Arrays of un-serialisable elements (`symbol[]`, `(() => void)[]`,\n`Map<K, V>[]`, etc.) can't be encoded: every element would need to be\nrepresentable, and these aren't. Dropping individual elements would\nchange the array length, so the encoder refuses rather than silently\nshipping a different shape.\n\nFix: change the element type to something serialisable:\n - type Items = (() => void)[];\n+ type Items = string[];",
81
81
  },
82
82
  FB005: {
83
- headline: 'Type `{0}` can never be deserialised from binary the generated function will always fail.',
83
+ headline: 'Type `{0}` can never be deserialised from binary: the generated function will always fail.',
84
84
  severity: 'error',
85
- detail: "Built-in classes like `Map`, `Set`, `WeakMap`, `WeakSet`, `Int8Array`,\n`Uint8Array`, `Buffer`, and `Promise` carry runtime state that doesn't\nsurvive a JSON or binary round-trip. Their instance identity is lost the\nmoment they're serialised.\n\nFix convert to a plain object/array before serialising:\n // for Map<K, V>:\n const data = Object.fromEntries(yourMap);\n // for Set<T>:\n const data = [...yourSet];\n // for typed arrays:\n const data = Array.from(yourBuffer);\n\nFix change the field type to a serialisable shape:\n interface User {\n- tags: Set<string>;\n+ tags: string[];\n }",
85
+ detail: "Built-in classes like `Map`, `Set`, `WeakMap`, `WeakSet`, `Int8Array`,\n`Uint8Array`, `Buffer`, and `Promise` carry runtime state that doesn't\nsurvive a JSON or binary round-trip. Their instance identity is lost the\nmoment they're serialised.\n\nFix: convert to a plain object/array before serialising:\n // for Map<K, V>:\n const data = Object.fromEntries(yourMap);\n // for Set<T>:\n const data = [...yourSet];\n // for typed arrays:\n const data = Array.from(yourBuffer);\n\nFix: change the field type to a serialisable shape:\n interface User {\n- tags: Set<string>;\n+ tags: string[];\n }",
86
86
  },
87
87
  FB006: {
88
- headline: 'Type `{0}` can never be deserialised from binary the generated function will always fail.',
88
+ headline: 'Type `{0}` can never be deserialised from binary: the generated function will always fail.',
89
89
  severity: 'error',
90
- detail: "Every `symbol` value carries a unique runtime identity (`Symbol() !==\nSymbol()` even with the same description). That identity disappears the\nmoment it's serialised, and two symbols can't be compared across realms,\nworkers, or process boundaries. A validator that asserts \"this is a\nsymbol\" gives a false sense of safety the value can't actually\nround-trip.\n\nFix use a stable string key (often a literal union):\n - type Status = symbol;\n+ type Status = 'pending' | 'active' | 'done';",
90
+ detail: "Every `symbol` value carries a unique runtime identity (`Symbol() !==\nSymbol()` even with the same description). That identity disappears the\nmoment it's serialised, and two symbols can't be compared across realms,\nworkers, or process boundaries. A validator that asserts \"this is a\nsymbol\" gives a false sense of safety: the value can't actually\nround-trip.\n\nFix: use a stable string key (often a literal union):\n - type Status = symbol;\n+ type Status = 'pending' | 'active' | 'done';",
91
91
  },
92
92
  FB010: {
93
- headline: 'Property `{0}` is a function `fromBinary` does not handle function values, so this property is silently not deserialised.',
93
+ headline: 'Property `{0}` is a function: `fromBinary` does not handle function values, so this property is silently not deserialised.',
94
94
  severity: 'warning',
95
- detail: '`fromBinary` works on JSON-shaped data; functions don\'t survive JSON, so\nthe emitter drops them. The rest of the object\'s behaviour is unaffected.\n\nThis is by design see the "validate contract serializable data only"\nsection in CLAUDE.md. If you need a stricter checker that fails on\nmissing/extra function-typed members, watch the project roadmap.',
95
+ detail: '`fromBinary` works on JSON-shaped data; functions don\'t survive JSON, so\nthe emitter drops them. The rest of the object\'s behaviour is unaffected.\n\nThis is by design, see the "one contract: serializable data only"\nsection in CLAUDE.md. If you need a stricter checker that fails on\nmissing/extra function-typed members, watch the project roadmap.',
96
96
  },
97
97
  FB011: {
98
- headline: "Method `{0}` is silently not deserialised by `fromBinary` methods aren't data.",
98
+ headline: "Method `{0}` is silently not deserialised by `fromBinary`: methods aren't data.",
99
99
  severity: 'warning',
100
100
  detail: "Class and object methods aren't part of the serialisable shape, so\n`fromBinary` excludes them. The rest of the type still works.\n\nIf you wanted the method's return value validated/serialised, expose it\nas a data property instead.",
101
101
  },
102
102
  FB012: {
103
- headline: "Static member `{0}` is silently not deserialised by `fromBinary` statics aren't part of instance data.",
103
+ headline: "Static member `{0}` is silently not deserialised by `fromBinary`: statics aren't part of instance data.",
104
104
  severity: 'warning',
105
105
  detail: 'Class static members live on the class, not on individual instances.\n`fromBinary` operates on instance shape, so statics are excluded.',
106
106
  },
107
107
  FB013: {
108
- headline: "Symbol-keyed property `{0}` is silently not deserialised by `fromBinary` symbol keys aren't JSON-representable.",
108
+ headline: "Symbol-keyed property `{0}` is silently not deserialised by `fromBinary`: symbol keys aren't JSON-representable.",
109
109
  severity: 'warning',
110
- detail: "JSON only supports string keys; symbol-keyed properties are dropped\nfrom the serialised form. `fromBinary` follows the same rule.\n\nFix use a string key:\n - [Symbol.for('id')]: string;\n+ id: string;",
110
+ detail: "JSON only supports string keys; symbol-keyed properties are dropped\nfrom the serialised form. `fromBinary` follows the same rule.\n\nFix: use a string key:\n - [Symbol.for('id')]: string;\n+ id: string;",
111
111
  },
112
112
  FB014: {
113
- headline: "Union member(s) of type `{0}` can't be represented as data `fromBinary` drops them, so the union is deserialised as its remaining members.",
113
+ headline: "Union member(s) of type `{0}` can't be represented as data: `fromBinary` drops them, so the union is deserialised as its remaining members.",
114
114
  severity: 'warning',
115
- detail: 'A union projects to its serialisable members only: `DataOnly<Date | symbol>`\nis `Date`. The dropped member(s) ({0}) carry no JSON-shaped value (symbol,\nfunction, Promise, or a non-serialisable built-in like `Map` / `Set` /\ntyped arrays), so `fromBinary` deserialised only the members that remain.\n\nThis is by design see the "validate contract serializable data only"\nsection in CLAUDE.md. If EVERY member of the union is non-serialisable the\nprojection is `never`, and `fromBinary` throws at build time instead.',
115
+ detail: 'A union projects to its serialisable members only: `DataOnly<Date | symbol>`\nis `Date`. The dropped member(s) ({0}) carry no JSON-shaped value (symbol,\nfunction, Promise, or a non-serialisable built-in like `Map` / `Set` /\ntyped arrays), so `fromBinary` deserialised only the members that remain.\n\nThis is by design, see the "one contract: serializable data only"\nsection in CLAUDE.md. If EVERY member of the union is non-serialisable the\nprojection is `never`, and `fromBinary` throws at build time instead.',
116
116
  },
117
117
  FB015: {
118
- headline: 'Property `{0}` has a non-serialisable value type (symbol, Promise, or a non-serialisable built-in) `fromBinary` drops it, so this property is silently not deserialised.',
118
+ headline: 'Property `{0}` has a non-serialisable value type (symbol, Promise, or a non-serialisable built-in): `fromBinary` drops it, so this property is silently not deserialised.',
119
119
  severity: 'warning',
120
- detail: '`fromBinary` works on JSON-shaped data. A property whose value is a symbol,\na Promise, or a non-serialisable built-in (typed array, ArrayBuffer, …) carries\nno JSON-shaped value, so it is dropped: `DataOnly<{ {0}: symbol }>` is `{}`.\nThe rest of the object\'s behaviour is unaffected.\n\nNote the difference from a property that is only STRUCTURALLY unserialisable —\n`{0}: symbol[]` or `{0}: Map<string, symbol>` which CANNOT be safely\ndropped (DataOnly keeps it as `never[]`): there `fromBinary` throws at build\ntime instead.\n\nThis is by design see the "validate contract serializable data only"\nsection in CLAUDE.md.',
120
+ detail: '`fromBinary` works on JSON-shaped data. A property whose value is a symbol,\na Promise, or a non-serialisable built-in (typed array, ArrayBuffer, …) carries\nno JSON-shaped value, so it is dropped: `DataOnly<{ {0}: symbol }>` is `{}`.\nThe rest of the object\'s behaviour is unaffected.\n\nNote the difference from a property that is only STRUCTURALLY unserialisable\n(`{0}: symbol[]` or `{0}: Map<string, symbol>`), which CANNOT be safely\ndropped (DataOnly keeps it as `never[]`): there `fromBinary` throws at build\ntime instead.\n\nThis is by design, see the "one contract: serializable data only"\nsection in CLAUDE.md.',
121
121
  },
122
122
  FMT001: {
123
- headline: 'TypeFormat mockSample "{0}" does not match its pattern /{1}/ fix the sample or the pattern.',
123
+ headline: 'TypeFormat mockSample "{0}" does not match its pattern /{1}/; fix the sample or the pattern.',
124
124
  severity: 'error',
125
125
  },
126
126
  FMT002: {
127
- headline: 'Invalid type-format params {0}',
127
+ headline: 'Invalid type-format params: {0}',
128
128
  severity: 'error',
129
129
  },
130
130
  FMT003: {
131
- headline: 'TypeFormat mockSample violates a sibling constraint {0}',
131
+ headline: 'TypeFormat mockSample violates a sibling constraint: {0}',
132
132
  severity: 'error',
133
- detail: "A mockSample is meant to be a canonical VALID value for the format, so it\nmust satisfy the format's own statically checkable siblings (length /\nminLength / maxLength, and the plain-string allowedChars / disallowedChars /\ndisallowedValues ops). A sample that its siblings reject means\n`createMockDataFn` would either produce an invalid value or filter every\nsample out and throw at mock time.\n\nLengths are counted in UTF-16 code units, exactly as the emitted validator's\n`.length` check counts them.\n\nFix adjust the offending sample(s), or relax the constraint:\n - String<{minLength: 5; pattern: {source: '^b+$'; mockSamples: ['b', 'bb']}}>\n+ String<{minLength: 1; pattern: {source: '^b+$'; mockSamples: ['b', 'bb']}}>",
133
+ detail: "A mockSample is meant to be a canonical VALID value for the format, so it\nmust satisfy the format's own statically checkable siblings (length /\nminLength / maxLength, and the plain-string allowedChars / disallowedChars /\ndisallowedValues ops). A sample that its siblings reject means\n`createMockDataFn` would either produce an invalid value or filter every\nsample out and throw at mock time.\n\nLengths are counted in UTF-16 code units, exactly as the emitted validator's\n`.length` check counts them.\n\nFix: adjust the offending sample(s), or relax the constraint:\n - String<{minLength: 5; pattern: {source: '^b+$'; mockSamples: ['b', 'bb']}}>\n+ String<{minLength: 1; pattern: {source: '^b+$'; mockSamples: ['b', 'bb']}}>",
134
134
  },
135
135
  FMT004: {
136
- headline: "TypeFormat pattern /{0}/ carries mockSamples but uses JS-only regex features RE2 can't compile ({1}) samples can't be verified at build time.",
136
+ headline: 'TypeFormat pattern /{0}/ cannot be checked: {1}; pattern validation requires a JavaScript runtime; install one or pass --js-runtime.',
137
137
  severity: 'error',
138
- detail: "The build-time sample check compiles the pattern with Go's RE2 engine, which\ndoesn't support JS-only features (lookarounds, backreferences). The build\nfails closed rather than ship samples it can't verify.\n\nFix set `allowUncheckedPatterns` (plugin option / tsconfig plugin key)\nto assert that the JS linter owns the check, then wire the ts-runtypes lint\nplugin into your editor + CI: it evaluates the real `RegExp.test(sample)` and\nreports any mismatch (as FMT001) at the definition site.\n\nFix or rewrite the pattern using RE2-compatible syntax so the fast\nbuild-time check can run (no lookarounds / backreferences).",
138
+ detail: "Pattern checks (does the regex compile, do the mockSamples match it) run on\na real JS engine (the same `new RegExp` the emitted validator uses at\nruntime), driven by the resolver as a small sidecar under a JavaScript\nruntime. No runtime could be started, so the pattern is unverifiable and\nthe build fails closed rather than ship samples it can't verify.\n\nFix: install node or bun (both are found automatically on PATH), or point\nthe --js-runtime flag or the RT_JS_RUNTIME environment variable at any\nother runtime that can run the bundled checker (deno and most\nnode-compatible runtimes work). Projects with no patterns never need this.",
139
+ },
140
+ FMT005: {
141
+ headline: 'Cannot auto-generate mockSamples for pattern /{0}/: {1}; declare mockSamples explicitly.',
142
+ severity: 'error',
143
+ detail: "A pattern with no declared mockSamples gets them generated at build time:\nthe JS engine draws candidate strings from the regex (patternSampleCount of\nthem, a fresh pool per build, or a reproducible one when a literal\n{mock: {seed}} rides a createMockDataFn call site) and keeps the ones the\nreal compiled pattern and the declared length bounds accept. This one\nproduced nothing: generation is disabled (patternSampleCount 0), the\ngenerator cannot handle a construct in the pattern (lookarounds are the\nusual case), or every draw in the retry budget (patternSampleCount ×\npatternSampleRetries) failed the pattern's own constraints.\n\nFix: declare the samples yourself; they are validated against the pattern\nat build time, so they stay trustworthy:\n- String<{pattern: {source: '(?<=x)y'}}>\n+ String<{pattern: {source: '(?<=x)y'; mockSamples: ['xy']}}>\n\nOr, if generation was disabled on purpose, re-enable it by raising\npatternSampleCount above 0 (and patternSampleRetries if the pattern is\nheavily constrained).",
144
+ },
145
+ FMT006: {
146
+ headline: 'Two sites share one cache entry for format `{0}` but declare different mockSamples: `{1}` here vs `{2}` at {3}. Make the pools identical, or declare one and leave the other out.',
147
+ severity: 'error',
148
+ detail: "mockSamples describe how to GENERATE a sample value; they are not part of\nwhat the format validates. So two formats identical apart from their pools\nare the same validator, and they intern as ONE cache entry. That dedup is\ndeliberate, and it is why the samples are excluded from the structural id.\n\nThe catch is that one entry can only carry one pool. When both sites declare\none and the pools differ, the entry keeps whichever it saw first, so which\npool survives depends on scan order, and adding or reordering unrelated\ncode elsewhere can flip it. Rather than pick silently, the build stops here.\n\nFix: declare the same pool at both sites:\n- type A = String<{maxLength: 5; mockSamples: ['aaa']}>;\n- type B = String<{maxLength: 5; mockSamples: ['bbb']}>;\n+ type A = String<{maxLength: 5; mockSamples: ['aaa']}>;\n+ type B = String<{maxLength: 5; mockSamples: ['aaa']}>;\n\nFix: or declare it once and leave the other alone; a site that declares\nnothing is not an opinion, so the declared pool is adopted for the shared\nentry:\n type A = String<{maxLength: 5; mockSamples: ['aaa']}>;\n type B = String<{maxLength: 5}>;\n\nIf the two really are different types, give them something the id DOES\nfold (a distinct pattern, bound, or brand) so they stop sharing an entry.",
139
149
  },
140
150
  FT002: {
141
- headline: 'Unknown field `{0}` the type does not declare it, so this FriendlyText entry is dead.',
151
+ headline: 'Unknown field `{0}`: the type does not declare it, so this FriendlyText entry is dead.',
142
152
  severity: 'error',
143
- detail: "The FriendlyText map names a field the source type does not have\n(removed, renamed, or a typo). Its labels and messages can never be\nused.\n\nExample `nick` no longer exists on the type:\n interface User { name: string }\n export const friendlyUser: FriendlyText<User> = {\n name: {rt$label: 'Name'},\n- nick: {rt$label: 'Nickname'},\n };\n\nFix remove the entry, or re-run the reconcile so the mirror follows\nthe type (a renamed field carries its authored values along):\n ts-runtypes enrich <source.ts> <Type> --update",
153
+ detail: "The FriendlyText map names a field the source type does not have\n(removed, renamed, or a typo). Its labels and messages can never be\nused.\n\nExample: `nick` no longer exists on the type:\n interface User { name: string }\n export const friendlyUser: FriendlyText<User> = {\n name: {rt$label: 'Name'},\n- nick: {rt$label: 'Nickname'},\n };\n\nFix: remove the entry, or re-run the reconcile so the mirror follows\nthe type (a renamed field carries its authored values along):\n ts-runtypes enrich <source.ts> <Type> --update",
144
154
  },
145
155
  FT003: {
146
- headline: 'Error key `{0}` is not a declared constraint of this field the message can never fire.',
156
+ headline: 'Error key `{0}` is not a declared constraint of this field: the message can never fire.',
147
157
  severity: 'warning',
148
- detail: "`rt$errors` keys must name a failure the field can actually produce:\n`type`, `rt$default`, or one of the field's declared format constraints\n(`minLength`, `pattern`, `min`, …). An undeclared key is dead\nconfiguration.\n\nExample the field has no `maxLength` constraint:\n interface User { name: string & FormatString<{minLength: 2}> }\n export const friendlyUser: FriendlyText<User> = {\n name: {\n rt$errors: {\n minLength: 'Name needs at least 2 characters',\n- maxLength: 'Name is too long',\n },\n },\n };\n\nFix remove the key, or declare the matching constraint on the field's\nTypeFormat so the message has a failure to describe.",
158
+ detail: "`rt$errors` keys must name a failure the field can actually produce:\n`type`, `rt$default`, or one of the field's declared format constraints\n(`minLength`, `pattern`, `min`, …). An undeclared key is dead\nconfiguration.\n\nExample: the field has no `maxLength` constraint:\n interface User { name: string & FormatString<{minLength: 2}> }\n export const friendlyUser: FriendlyText<User> = {\n name: {\n rt$errors: {\n minLength: 'Name needs at least 2 characters',\n- maxLength: 'Name is too long',\n },\n },\n };\n\nFix: remove the key, or declare the matching constraint on the field's\nTypeFormat so the message has a failure to describe.",
149
159
  },
150
160
  FT005: {
151
- headline: 'Unknown placeholder `$[{0}]` expected one of `$[label]`, `$[val]`, `$[path]`, `$[index]`.',
161
+ headline: 'Unknown placeholder `$[{0}]`: expected one of `$[label]`, `$[val]`, `$[path]`, `$[index]`.',
152
162
  severity: 'warning',
153
- detail: "Error-message templates substitute a fixed placeholder set; an unknown\nname renders literally instead of substituting.\n\nExample:\n- rt$errors: {minLength: '$[name] is too short'}\n+ rt$errors: {minLength: '$[label] is too short'}\n\nFix use one of the recognised placeholders, or write the literal text\nwithout the `$[…]` wrapper.",
163
+ detail: "Error-message templates substitute a fixed placeholder set; an unknown\nname renders literally instead of substituting.\n\nExample:\n- rt$errors: {minLength: '$[name] is too short'}\n+ rt$errors: {minLength: '$[label] is too short'}\n\nFix: use one of the recognised placeholders, or write the literal text\nwithout the `$[…]` wrapper.",
154
164
  },
155
165
  FT006: {
156
- headline: 'Plural error template is missing the mandatory `other` arm the render has no backstop.',
166
+ headline: 'Plural error template is missing the mandatory `other` arm: the render has no backstop.',
157
167
  severity: 'error',
158
- detail: "Plural templates render the CLDR arm matching the count, and `other` is\nthe arm every locale falls back to. Without it some counts have no\nmessage at all.\n\nExample:\n rt$errors: {\n minLength: {\n one: 'Needs one more character',\n+ other: 'Needs $[val] more characters',\n },\n }\n\nFix add the `other` arm to the plural object.",
168
+ detail: "Plural templates render the CLDR arm matching the count, and `other` is\nthe arm every locale falls back to. Without it some counts have no\nmessage at all.\n\nExample:\n rt$errors: {\n minLength: {\n one: 'Needs one more character',\n+ other: 'Needs $[val] more characters',\n },\n }\n\nFix: add the `other` arm to the plural object.",
159
169
  },
160
170
  FT007: {
161
- headline: 'Unknown plural arm `{0}` CLDR categories are `zero`, `one`, `two`, `few`, `many`, `other`.',
171
+ headline: 'Unknown plural arm `{0}`: CLDR categories are `zero`, `one`, `two`, `few`, `many`, `other`.',
162
172
  severity: 'warning',
163
- detail: "Plural template keys must be CLDR plural categories; anything else can\nnever be selected by any locale's plural rules.\n\nExample:\n rt$errors: {\n minLength: {\n- single: 'Needs one more character',\n+ one: 'Needs one more character',\n other: 'Needs $[val] more characters',\n },\n }\n\nFix rename the arm to one of the six categories, or remove it.",
173
+ detail: "Plural template keys must be CLDR plural categories; anything else can\nnever be selected by any locale's plural rules.\n\nExample:\n rt$errors: {\n minLength: {\n- single: 'Needs one more character',\n+ one: 'Needs one more character',\n other: 'Needs $[val] more characters',\n },\n }\n\nFix: rename the arm to one of the six categories, or remove it.",
164
174
  },
165
175
  FT008: {
166
- headline: 'Constraint `{0}` carries no count a plural template here has dead arms; use a plain string.',
176
+ headline: 'Constraint `{0}` carries no count: a plural template here has dead arms; use a plain string.',
167
177
  severity: 'warning',
168
- detail: "Only count-bearing constraints (`minLength`, `maxLength`, `min`, `max`,\n…) can select a plural arm. On a non-count constraint only `other` ever\nrenders, so the remaining arms are dead configuration.\n\nExample `pattern` has no count:\n rt$errors: {\n- pattern: {one: 'One bad character', other: 'Invalid characters'},\n+ pattern: 'Only letters and numbers are allowed',\n }\n\nFix replace the plural object with a plain string message.",
178
+ detail: "Only count-bearing constraints (`minLength`, `maxLength`, `min`, `max`,\n…) can select a plural arm. On a non-count constraint only `other` ever\nrenders, so the remaining arms are dead configuration.\n\nExample: `pattern` has no count:\n rt$errors: {\n- pattern: {one: 'One bad character', other: 'Invalid characters'},\n+ pattern: 'Only letters and numbers are allowed',\n }\n\nFix: replace the plural object with a plain string message.",
169
179
  },
170
180
  FT009: {
171
- headline: '`rt$default` is mutually exclusive with per-constraint messages use one mode or the other.',
181
+ headline: '`rt$default` is mutually exclusive with per-constraint messages; use one mode or the other.',
172
182
  severity: 'error',
173
- detail: "An `rt$errors` record is either ONE `rt$default` catch-all or a set of\nper-constraint keys, mirroring the TypeScript union. Mixing them makes\nthe intent ambiguous (which message wins?).\n\nExample:\n rt$errors: {\n- rt$default: 'Invalid name',\n minLength: 'Name is too short',\n }\n\nFix keep `{rt$default: '…'}` alone, or keep the per-constraint keys\nand drop `rt$default`.",
183
+ detail: "An `rt$errors` record is either ONE `rt$default` catch-all or a set of\nper-constraint keys, mirroring the TypeScript union. Mixing them makes\nthe intent ambiguous (which message wins?).\n\nExample:\n rt$errors: {\n- rt$default: 'Invalid name',\n minLength: 'Name is too short',\n }\n\nFix: keep `{rt$default: '…'}` alone, or keep the per-constraint keys\nand drop `rt$default`.",
174
184
  },
175
185
  FT011: {
176
- headline: 'Property `{0}` collides with the reserved `rt$` enrichment prefix the type cannot be enriched.',
186
+ headline: 'Property `{0}` collides with the reserved `rt$` enrichment prefix: the type cannot be enriched.',
177
187
  severity: 'error',
178
- detail: '`rt$`-prefixed keys are reserved for enrichment meta (`rt$label`,\n`rt$errors`, `rt$items`, …); a source property with that prefix is\nindistinguishable from node meta, so gen refuses the type and the\nFriendlyType checker reports it here.\n\nFix rename the property (a plain `$` prefix is fine; only `rt$` is\nreserved):\n interface Config {\n- rt$mode: string;\n+ $mode: string;\n }',
188
+ detail: '`rt$`-prefixed keys are reserved for enrichment meta (`rt$label`,\n`rt$errors`, `rt$items`, …); a source property with that prefix is\nindistinguishable from node meta, so gen refuses the type and the\nFriendlyType checker reports it here.\n\nFix: rename the property (a plain `$` prefix is fine; only `rt$` is\nreserved):\n interface Config {\n- rt$mode: string;\n+ $mode: string;\n }',
179
189
  },
180
190
  FT020: {
181
- headline: 'Unfilled `@todo` placeholder fill in the real labels/messages, then delete the `@todo` line.',
191
+ headline: 'Unfilled `@todo` placeholder; fill in the real labels/messages, then delete the `@todo` line.',
182
192
  severity: 'error',
183
- detail: "The generator stamps a `@todo` line on every freshly-scaffolded const in\na FriendlyText mirror file. It means \"this skeleton still carries\ngenerated blanks\". A clean, committed mirror has none.\n\nExample a fresh scaffold:\n /** @rtType User#a1b2c3 @rtIds {name: d4e5f6} */\n- // @todo: generated skeleton fill in real data, then delete this line\n export const friendlyUser: FriendlyText<User> = {\n- name: {rt$label: ''},\n+ name: {rt$label: 'Name'},\n };\n\nFix author the real labels and error messages for the const, then\ndelete the whole `@todo` line (the compiler never removes it for you).",
193
+ detail: "The generator stamps a `@todo` line on every freshly-scaffolded const in\na FriendlyText mirror file. It means \"this skeleton still carries\ngenerated blanks\". A clean, committed mirror has none.\n\nExample: a fresh scaffold:\n /** @rtType User#a1b2c3 @rtIds {name: d4e5f6} */\n- // @todo: generated skeleton, fill in real data, then delete this line\n export const friendlyUser: FriendlyText<User> = {\n- name: {rt$label: ''},\n+ name: {rt$label: 'Name'},\n };\n\nFix: author the real labels and error messages for the const, then\ndelete the whole `@todo` line (the compiler never removes it for you).",
184
194
  },
185
195
  FT021: {
186
- headline: 'Stale `@rtOrphan` carcass run `ts-runtypes enrich --prune` to remove it (or restore the type).',
196
+ headline: 'Stale `@rtOrphan` carcass; run `ts-runtypes enrich --prune` to remove it (or restore the type).',
187
197
  severity: 'error',
188
- detail: 'The reconcile commented this FriendlyText const out because its source\ntype was deleted or renamed. The carcass preserves your authored labels\nand messages so a reappearing type can restore them but a clean,\ncommitted mirror has none.\n\nFix if the type is really gone, prune the carcass:\n ts-runtypes enrich --prune\n\nFix if the type was renamed, re-run the reconcile; a matching carcass\nis restored with your values intact:\n ts-runtypes enrich <source.ts> <NewName> --update',
198
+ detail: 'The reconcile commented this FriendlyText const out because its source\ntype was deleted or renamed. The carcass preserves your authored labels\nand messages so a reappearing type can restore them, but a clean,\ncommitted mirror has none.\n\nFix: if the type is really gone, prune the carcass:\n ts-runtypes enrich --prune\n\nFix: if the type was renamed, re-run the reconcile; a matching carcass\nis restored with your values intact:\n ts-runtypes enrich <source.ts> <NewName> --update',
189
199
  },
190
200
  FT022: {
191
- headline: 'Stale `@rtOrphanChild` field carcass run `ts-runtypes enrich --prune` to remove it (or restore the field).',
201
+ headline: 'Stale `@rtOrphanChild` field carcass; run `ts-runtypes enrich --prune` to remove it (or restore the field).',
192
202
  severity: 'error',
193
- detail: "The reconcile commented this field out because the source type no longer\ndeclares it. The carcass preserves your authored value inline but a\nclean, committed mirror has none.\n\nExample:\n export const friendlyUser: FriendlyText<User> = {\n- /* @rtOrphanChild nick: {rt$label: 'Nickname'}, */\n name: {rt$label: 'Name'},\n };\n\nFix if the field is really gone: `ts-runtypes enrich --prune`.\nFix if the field was renamed, re-run `--update`; the authored value\nmoves to the renamed field when the ids match.",
203
+ detail: "The reconcile commented this field out because the source type no longer\ndeclares it. The carcass preserves your authored value inline, but a\nclean, committed mirror has none.\n\nExample:\n export const friendlyUser: FriendlyText<User> = {\n- /* @rtOrphanChild nick: {rt$label: 'Nickname'}, */\n name: {rt$label: 'Name'},\n };\n\nFix: if the field is really gone: `ts-runtypes enrich --prune`.\nFix: if the field was renamed, re-run `--update`; the authored value\nmoves to the renamed field when the ids match.",
194
204
  },
195
205
  FT023: {
196
- headline: 'Unfilled blank value a scaffolded label or message is still empty; fill in the real text.',
206
+ headline: 'Unfilled blank value: a scaffolded label or message is still empty; fill in the real text.',
197
207
  severity: 'error',
198
- detail: "An empty string (`''`) at a `rt$label` / `rt$errors` slot is a generated\nblank that never got authored it ships blank to the UI wherever the\nfriendly text is shown, so it is exactly as incomplete as a `@todo`\nmarker. This is why removing the `@todo` line without filling the values\nis not \"done\".\n\nExample:\n export const friendlyUser: FriendlyText<User> = {\n- name: {rt$label: ''},\n+ name: {rt$label: 'Name'},\n };\n\nFix author the real label / message. Only the completeness gate\n(`ts-runtypes enrich --require-complete`) fails on it; a plain\n`--no-emit` health check reports it without failing.",
208
+ detail: "An empty string (`''`) at a `rt$label` / `rt$errors` slot is a generated\nblank that never got authored: it ships blank to the UI wherever the\nfriendly text is shown, so it is exactly as incomplete as a `@todo`\nmarker. This is why removing the `@todo` line without filling the values\nis not \"done\".\n\nExample:\n export const friendlyUser: FriendlyText<User> = {\n- name: {rt$label: ''},\n+ name: {rt$label: 'Name'},\n };\n\nFix: author the real label / message. Only the completeness gate\n(`ts-runtypes enrich --require-complete`) fails on it; a plain\n`--no-emit` health check reports it without failing.",
199
209
  },
200
210
  GE000: {
201
211
  headline: 'Cannot read enrichment mirror file: {0}',
202
212
  severity: 'error',
203
- detail: 'The drift check could not read this mirror file (permissions, a broken\nsymlink, or a race with a concurrent write).\n\nFix make the file readable and re-run `ts-runtypes enrich --no-emit`.',
213
+ detail: 'The drift check could not read this mirror file (permissions, a broken\nsymlink, or a race with a concurrent write).\n\nFix: make the file readable and re-run `ts-runtypes enrich --no-emit`.',
204
214
  },
205
215
  GE001: {
206
- headline: 'Mirror location drift the source maps to `{0}` but this file lives at `{1}`; re-run `ts-runtypes enrich` to relocate.',
216
+ headline: 'Mirror location drift: the source maps to `{0}` but this file lives at `{1}`; re-run `ts-runtypes enrich` to relocate.',
207
217
  severity: 'warning',
208
- detail: 'Each source file mirrors to ONE computed path per family under the\nenrich root (friendly/… and mock/…, plus per-locale translation twins).\nThis file is not at its computed location usually after a source move,\na genDir change, or a pre-split combined mirror that still needs\nmigrating.\n\nFix re-run the generator; it writes the per-family files at the right\npaths and migrates a legacy combined mirror:\n ts-runtypes enrich <source.ts> <Type> --update',
218
+ detail: 'Each source file mirrors to ONE computed path per family under the\nenrich root (friendly/… and mock/…, plus per-locale translation twins).\nThis file is not at its computed location, usually after a source move,\na genDir change, or a pre-split combined mirror that still needs\nmigrating.\n\nFix: re-run the generator; it writes the per-family files at the right\npaths and migrates a legacy combined mirror:\n ts-runtypes enrich <source.ts> <Type> --update',
209
219
  },
210
220
  GE002: {
211
- headline: 'Breadcrumb source `{0}` no longer exists ({1}) the mirror is orphaned; delete it or re-run `ts-runtypes enrich`.',
221
+ headline: 'Breadcrumb source `{0}` no longer exists ({1}): the mirror is orphaned; delete it or re-run `ts-runtypes enrich`.',
212
222
  severity: 'error',
213
- detail: "The mirror's `import type { … } from '<source>'` breadcrumb resolves to\na file that is gone. Its consts describe types that no longer exist\nanywhere.\n\nFix if the source was deleted, delete the mirror file (both family\nfiles and any translation twins).\nFix if the source moved, re-run the generator from the new location\nand prune the old mirror.",
223
+ detail: "The mirror's `import type { … } from '<source>'` breadcrumb resolves to\na file that is gone. Its consts describe types that no longer exist\nanywhere.\n\nFix: if the source was deleted, delete the mirror file (both family\nfiles and any translation twins).\nFix: if the source moved, re-run the generator from the new location\nand prune the old mirror.",
214
224
  },
215
225
  GE003: {
216
- headline: 'Source {0} no longer declares type `{1}` re-run `ts-runtypes enrich`.',
226
+ headline: 'Source {0} no longer declares type `{1}`; re-run `ts-runtypes enrich`.',
217
227
  severity: 'error',
218
- detail: 'The mirror imports a type name its source file no longer declares (the\ntype was renamed or removed). The reconcile turns its consts into\n`@rtOrphan` carcasses so your authored values survive.\n\nFix re-run the reconcile against the current source, then prune any\ncarcasses that should not come back:\n ts-runtypes enrich <source.ts> <Type> --update\n ts-runtypes enrich --prune',
228
+ detail: 'The mirror imports a type name its source file no longer declares (the\ntype was renamed or removed). The reconcile turns its consts into\n`@rtOrphan` carcasses so your authored values survive.\n\nFix: re-run the reconcile against the current source, then prune any\ncarcasses that should not come back:\n ts-runtypes enrich <source.ts> <Type> --update\n ts-runtypes enrich --prune',
219
229
  },
220
230
  HUK010: {
221
- headline: 'Property `{0}` is a function `hasUnknownKeys` does not handle function values, so this property is silently not checked.',
231
+ headline: 'Property `{0}` is a function: `hasUnknownKeys` does not handle function values, so this property is silently not checked.',
222
232
  severity: 'warning',
223
- detail: '`hasUnknownKeys` works on JSON-shaped data; functions don\'t survive JSON, so\nthe emitter drops them. The rest of the object\'s behaviour is unaffected.\n\nThis is by design see the "validate contract serializable data only"\nsection in CLAUDE.md. If you need a stricter checker that fails on\nmissing/extra function-typed members, watch the project roadmap.',
233
+ detail: '`hasUnknownKeys` works on JSON-shaped data; functions don\'t survive JSON, so\nthe emitter drops them. The rest of the object\'s behaviour is unaffected.\n\nThis is by design, see the "one contract: serializable data only"\nsection in CLAUDE.md. If you need a stricter checker that fails on\nmissing/extra function-typed members, watch the project roadmap.',
224
234
  },
225
235
  JCP001: {
226
- headline: 'Internal error: JSON composite `{0}` references primitive entry `{1}` (type `{2}`) which was never rendered please file an issue.',
236
+ headline: 'Internal error: JSON composite `{0}` references primitive entry `{1}` (type `{2}`) which was never rendered; please file an issue.',
227
237
  severity: 'error',
228
238
  },
229
239
  MD001: {
230
- headline: 'Unknown field `{0}` the type does not declare it, so this MockData entry is dead.',
240
+ headline: 'Unknown field `{0}`: the type does not declare it, so this MockData entry is dead.',
231
241
  severity: 'error',
232
- detail: "The MockData map names a field the source type does not have (removed,\nrenamed, or a typo). Its pool/range can never feed a generated mock.\n\nExample `nick` no longer exists on the type:\n interface User { name: string }\n export const mockUser: MockData<User> = {\n name: {pool: ['Ada', 'Linus']},\n- nick: {pool: ['ada99']},\n };\n\nFix remove the entry, or re-run the reconcile so the mirror follows\nthe type:\n ts-runtypes enrich <source.ts> <Type> --update",
242
+ detail: "The MockData map names a field the source type does not have (removed,\nrenamed, or a typo). Its pool/range can never feed a generated mock.\n\nExample: `nick` no longer exists on the type:\n interface User { name: string }\n export const mockUser: MockData<User> = {\n name: {pool: ['Ada', 'Linus']},\n- nick: {pool: ['ada99']},\n };\n\nFix: remove the entry, or re-run the reconcile so the mirror follows\nthe type:\n ts-runtypes enrich <source.ts> <Type> --update",
233
243
  },
234
244
  MD011: {
235
- headline: 'Property `{0}` collides with the reserved `rt$` enrichment prefix the type cannot be enriched.',
245
+ headline: 'Property `{0}` collides with the reserved `rt$` enrichment prefix: the type cannot be enriched.',
236
246
  severity: 'error',
237
- detail: '`rt$`-prefixed keys are reserved for enrichment meta (`rt$items`,\n`rt$length`, `rt$optional`, …); a source property with that prefix is\nindistinguishable from node meta, so gen refuses the type and the\nMockData checker reports it here.\n\nFix rename the property (a plain `$` prefix is fine; only `rt$` is\nreserved):\n interface Config {\n- rt$size: number;\n+ $size: number;\n }',
247
+ detail: '`rt$`-prefixed keys are reserved for enrichment meta (`rt$items`,\n`rt$length`, `rt$optional`, …); a source property with that prefix is\nindistinguishable from node meta, so gen refuses the type and the\nMockData checker reports it here.\n\nFix: rename the property (a plain `$` prefix is fine; only `rt$` is\nreserved):\n interface Config {\n- rt$size: number;\n+ $size: number;\n }',
238
248
  },
239
249
  MD020: {
240
- headline: 'Unfilled `@todo` placeholder fill in the real sample pools/ranges, then delete the `@todo` line.',
250
+ headline: 'Unfilled `@todo` placeholder; fill in the real sample pools/ranges, then delete the `@todo` line.',
241
251
  severity: 'error',
242
- detail: "The generator stamps a `@todo` line on every freshly-scaffolded const in\na MockData mirror file. It means \"this skeleton still carries generated\nblanks\". A clean, committed mirror has none.\n\nExample a fresh scaffold:\n /** @rtType User#a1b2c3 @rtIds {name: d4e5f6} */\n- // @todo: generated skeleton fill in real data, then delete this line\n export const mockUser: MockData<User> = {\n- name: {pool: []},\n+ name: {pool: ['Ada Lovelace', 'Linus Torvalds']},\n };\n\nFix author realistic sample pools/ranges for the const, then delete\nthe whole `@todo` line (the compiler never removes it for you).",
252
+ detail: "The generator stamps a `@todo` line on every freshly-scaffolded const in\na MockData mirror file. It means \"this skeleton still carries generated\nblanks\". A clean, committed mirror has none.\n\nExample: a fresh scaffold:\n /** @rtType User#a1b2c3 @rtIds {name: d4e5f6} */\n- // @todo: generated skeleton, fill in real data, then delete this line\n export const mockUser: MockData<User> = {\n- name: {pool: []},\n+ name: {pool: ['Ada Lovelace', 'Linus Torvalds']},\n };\n\nFix: author realistic sample pools/ranges for the const, then delete\nthe whole `@todo` line (the compiler never removes it for you).",
243
253
  },
244
254
  MD021: {
245
- headline: 'Stale `@rtOrphan` carcass run `ts-runtypes enrich --prune` to remove it (or restore the type).',
255
+ headline: 'Stale `@rtOrphan` carcass; run `ts-runtypes enrich --prune` to remove it (or restore the type).',
246
256
  severity: 'error',
247
- detail: 'The reconcile commented this MockData const out because its source type\nwas deleted or renamed. The carcass preserves your authored pools and\nranges so a reappearing type can restore them but a clean, committed\nmirror has none.\n\nFix if the type is really gone, prune the carcass:\n ts-runtypes enrich --prune\n\nFix if the type was renamed, re-run the reconcile; a matching carcass\nis restored with your values intact:\n ts-runtypes enrich <source.ts> <NewName> --update',
257
+ detail: 'The reconcile commented this MockData const out because its source type\nwas deleted or renamed. The carcass preserves your authored pools and\nranges so a reappearing type can restore them, but a clean, committed\nmirror has none.\n\nFix: if the type is really gone, prune the carcass:\n ts-runtypes enrich --prune\n\nFix: if the type was renamed, re-run the reconcile; a matching carcass\nis restored with your values intact:\n ts-runtypes enrich <source.ts> <NewName> --update',
248
258
  },
249
259
  MD022: {
250
- headline: 'Stale `@rtOrphanChild` field carcass run `ts-runtypes enrich --prune` to remove it (or restore the field).',
260
+ headline: 'Stale `@rtOrphanChild` field carcass; run `ts-runtypes enrich --prune` to remove it (or restore the field).',
251
261
  severity: 'error',
252
- detail: "The reconcile commented this field out because the source type no longer\ndeclares it. The carcass preserves your authored value inline but a\nclean, committed mirror has none.\n\nExample:\n export const mockUser: MockData<User> = {\n- /* @rtOrphanChild nick: {pool: ['ada99']}, */\n name: {pool: ['Ada', 'Linus']},\n };\n\nFix if the field is really gone: `ts-runtypes enrich --prune`.\nFix if the field was renamed, re-run `--update`; the authored value\nmoves to the renamed field when the ids match.",
262
+ detail: "The reconcile commented this field out because the source type no longer\ndeclares it. The carcass preserves your authored value inline, but a\nclean, committed mirror has none.\n\nExample:\n export const mockUser: MockData<User> = {\n- /* @rtOrphanChild nick: {pool: ['ada99']}, */\n name: {pool: ['Ada', 'Linus']},\n };\n\nFix: if the field is really gone: `ts-runtypes enrich --prune`.\nFix: if the field was renamed, re-run `--update`; the authored value\nmoves to the renamed field when the ids match.",
253
263
  },
254
264
  MD023: {
255
- headline: 'Unfilled blank value a scaffolded sample pool or range is still empty; fill in real data.',
265
+ headline: 'Unfilled blank value: a scaffolded sample pool or range is still empty; fill in real data.',
256
266
  severity: 'error',
257
- detail: "An empty pool (`pool: []`) is a generated blank that never got authored —\nit mocks nothing, so it is exactly as incomplete as a `@todo` marker.\nThis is why removing the `@todo` line without filling the values is not\n\"done\".\n\nExample:\n export const mockUser: MockData<User> = {\n- name: {pool: []},\n+ name: {pool: ['Ada Lovelace', 'Linus Torvalds']},\n };\n\nFix author realistic sample data. Only the completeness gate\n(`ts-runtypes enrich --require-complete`) fails on it; a plain\n`--no-emit` health check reports it without failing.",
267
+ detail: "An empty pool (`pool: []`) is a generated blank that never got authored:\nit mocks nothing, so it is exactly as incomplete as a `@todo` marker.\nThis is why removing the `@todo` line without filling the values is not\n\"done\".\n\nExample:\n export const mockUser: MockData<User> = {\n- name: {pool: []},\n+ name: {pool: ['Ada Lovelace', 'Linus Torvalds']},\n };\n\nFix: author realistic sample data. Only the completeness gate\n(`ts-runtypes enrich --require-complete`) fails on it; a plain\n`--no-emit` health check reports it without failing.",
258
268
  },
259
269
  MKR001: {
260
- headline: '`{0}()` is being called at runtime just so the marker can read its return type side effects, throws, or async work run for nothing.',
270
+ headline: '`{0}()` is being called at runtime just so the marker can read its return type: side effects, throws, or async work run for nothing.',
261
271
  severity: 'warning',
262
- detail: 'Reflect-form markers (`createValidateFn(value)`, `getRunTypeId(value)`)\ninvoke their argument expression at runtime; the value is then discarded —\nonly its inferred type is used.\n\nFix use the static form with `ReturnType<>`:\n - const isUser = createValidateFn({0}());\n+ const isUser = createValidateFn<ReturnType<typeof {0}>>();\n\nFix pass an existing value of the desired type:\n const existingUser: User = ...;\n const isUser = getRunTypeId(existingUser);',
272
+ detail: 'Reflect-form markers (`createValidateFn(value)`, `getRunTypeId(value)`)\ninvoke their argument expression at runtime; the value is then discarded;\nonly its inferred type is used.\n\nFix: use the static form with `ReturnType<>`:\n - const isUser = createValidateFn({0}());\n+ const isUser = createValidateFn<ReturnType<typeof {0}>>();\n\nFix: pass an existing value of the desired type:\n const existingUser: User = ...;\n const isUser = getRunTypeId(existingUser);',
263
273
  },
264
274
  MKR003: {
265
- headline: 'Marker call is inside a generic function the type argument is unresolved, so no id can be computed at build time.',
275
+ headline: 'Marker call is inside a generic function: the type argument is unresolved, so no id can be computed at build time.',
266
276
  severity: 'error',
267
- detail: "The build can only compute an id for a concrete type (`User`,\n`{name: string}`, etc.). A type parameter like `T` is abstract it\ntakes a different value at each call site of the surrounding function,\nso a single id can't represent it.\n\nFix inline the marker at each concrete call site:\n function isUser(value: unknown) {\n return createValidateFn<User>()(value);\n }\n\nFix accept a pre-computed id from the caller:\n function makeChecker<T>(id: InjectRunTypeId<T>) {\n return createValidateFn<T>(id);\n }\n const isUser = makeChecker<User>(getRunTypeId<User>());",
277
+ detail: "The build can only compute an id for a concrete type (`User`,\n`{name: string}`, etc.). A type parameter like `T` is abstract: it\ntakes a different value at each call site of the surrounding function,\nso a single id can't represent it.\n\nFix: inline the marker at each concrete call site:\n function isUser(value: unknown) {\n return createValidateFn<User>()(value);\n }\n\nFix: accept a pre-computed id from the caller:\n function makeChecker<T>(id: InjectRunTypeId<T>) {\n return createValidateFn<T>(id);\n }\n const isUser = makeChecker<User>(getRunTypeId<User>());",
268
278
  },
269
279
  MKR004: {
270
- headline: "`noLiterals: true` has no effect here the type argument doesn't resolve to literal values.",
280
+ headline: "`noLiterals: true` has no effect here: the type argument doesn't resolve to literal values.",
271
281
  severity: 'warning',
272
- detail: "The `noLiterals` validate option skips the exact-value check that literal\ntypes (`'admin'`, `42`, `true`) compile to. This call's type argument\nresolves to a non-literal type, so there is no literal check to skip and\nthe option is a silent no-op.\n\nFix drop the option:\n- const isRole = createValidateFn<string>({noLiterals: true});\n+ const isRole = createValidateFn<string>();\n\nOr, if you meant to relax a literal union, point the option at the type\nthat actually carries the literals:\n const isRole = createValidateFn<'admin' | 'user'>({noLiterals: true});",
282
+ detail: "The `noLiterals` validate option skips the exact-value check that literal\ntypes (`'admin'`, `42`, `true`) compile to. This call's type argument\nresolves to a non-literal type, so there is no literal check to skip and\nthe option is a silent no-op.\n\nFix: drop the option:\n- const isRole = createValidateFn<string>({noLiterals: true});\n+ const isRole = createValidateFn<string>();\n\nOr, if you meant to relax a literal union, point the option at the type\nthat actually carries the literals:\n const isRole = createValidateFn<'admin' | 'user'>({noLiterals: true});",
273
283
  },
274
284
  MKR005: {
275
- headline: '`noIsArrayCheck: true` has no effect here the type argument is not an array type.',
285
+ headline: '`noIsArrayCheck: true` has no effect here: the type argument is not an array type.',
276
286
  severity: 'warning',
277
- detail: "The `noIsArrayCheck` validate option skips the `Array.isArray` guard that\narray types compile to. This call's type argument resolves to a non-array\ntype, so there is no guard to skip and the option is a silent no-op.\n\nFix drop the option:\n- const isUser = createValidateFn<User>({noIsArrayCheck: true});\n+ const isUser = createValidateFn<User>();\n\nOr point it at the array type you meant:\n const isUsers = createValidateFn<User[]>({noIsArrayCheck: true});",
287
+ detail: "The `noIsArrayCheck` validate option skips the `Array.isArray` guard that\narray types compile to. This call's type argument resolves to a non-array\ntype, so there is no guard to skip and the option is a silent no-op.\n\nFix: drop the option:\n- const isUser = createValidateFn<User>({noIsArrayCheck: true});\n+ const isUser = createValidateFn<User>();\n\nOr point it at the array type you meant:\n const isUsers = createValidateFn<User[]>({noIsArrayCheck: true});",
278
288
  },
279
289
  MKR006: {
280
- headline: '`InjectTypeFnArgs` names the function family `{0}` more than once remove the duplicate key.',
290
+ headline: '`InjectTypeFnArgs` names the function family `{0}` more than once; remove the duplicate key.',
281
291
  severity: 'error',
282
- detail: "An `InjectTypeFnArgs<T, …>` marker names each function family it needs for\n`T` once, in declaration order; the build injects one entry-module tuple\nper name and the wrapper forwards each to its factory. Naming a family\ntwice would inject a redundant identical tuple with no consumer, so it is\nalmost always a copy-paste slip and the build stops.\n\nFix name each family at most once:\n- id?: InjectTypeFnArgs<T, 'verr', 'jsonDecoder', 'verr'>;\n+ id?: InjectTypeFnArgs<T, 'verr', 'jsonDecoder', 'jsonEncoder'>;",
292
+ detail: "An `InjectTypeFnArgs<T, …>` marker names each function family it needs for\n`T` once, in declaration order; the build injects one entry-module tuple\nper name and the wrapper forwards each to its factory. Naming a family\ntwice would inject a redundant identical tuple with no consumer, so it is\nalmost always a copy-paste slip and the build stops.\n\nFix: name each family at most once:\n- id?: InjectTypeFnArgs<T, 'verr', 'jsonDecoder', 'verr'>;\n+ id?: InjectTypeFnArgs<T, 'verr', 'jsonDecoder', 'jsonEncoder'>;",
283
293
  },
284
294
  MKR007: {
285
- headline: 'Marker type resolved to `any` because this file has an unresolved import (`{0}`) the generated functions would silently accept anything.',
295
+ headline: 'Marker type resolved to `any` because this file has an unresolved import (`{0}`): the generated functions would silently accept anything.',
286
296
  severity: 'error',
287
- detail: "TypeScript could not resolve the import, so the type it should have\nprovided checked as `any` at this marker call. A validator over `any` is\nthe always-true identity, a mock over `any` is `undefined`, and encoders\npass values through untouched with no runtime signal that anything is\nwrong. This usually means the build tool and the type scanner resolve\nmodules differently (e.g. an extensionless relative import under\n`moduleResolution: NodeNext`, a missing dependency, or a `paths` alias the\nscan tsconfig doesn't declare).\n\nFix make the import resolve for the type scanner:\n- import {User} from './user.runtype';\n+ import {User} from './user.runtype.ts';\n\nOr align the tsconfig the plugin scans with the one your bundler uses.\nIf the `any` is genuinely intentional, write the marker over an alias\ndeclared in resolving code (e.g. `type Loose = any`) in a file with no\nfailing imports.",
297
+ detail: "TypeScript could not resolve the import, so the type it should have\nprovided checked as `any` at this marker call. A validator over `any` is\nthe always-true identity, a mock over `any` is `undefined`, and encoders\npass values through untouched, with no runtime signal that anything is\nwrong. This usually means the build tool and the type scanner resolve\nmodules differently (e.g. an extensionless relative import under\n`moduleResolution: NodeNext`, a missing dependency, or a `paths` alias the\nscan tsconfig doesn't declare).\n\nFix: make the import resolve for the type scanner:\n- import {User} from './user.runtype';\n+ import {User} from './user.runtype.ts';\n\nOr align the tsconfig the plugin scans with the one your bundler uses.\nIf the `any` is genuinely intentional, write the marker over an alias\ndeclared in resolving code (e.g. `type Loose = any`) in a file with no\nfailing imports.",
288
298
  },
289
299
  MKR008: {
290
- headline: 'This type is too deeply nested to reflect computing its structural id hit the recursion depth cap, so the build stops here instead of crashing.',
300
+ headline: 'This type is too deeply nested to reflect: computing its structural id hit the recursion depth cap, so the build stops here instead of crashing.',
291
301
  severity: 'error',
292
- detail: 'The build computes a structural id by walking the type, and the walk is\ncapped at a depth far beyond any realistic shape. Hitting the cap with no\nsingle recurring type on the path means literally written (or generated)\nnesting hundreds of levels deep.\n\nFix reflect a concrete, bounded projection of the type (e.g. the element\nor data type you actually send), or restructure the recursion so the same\nnamed type recurs by reference (a plain recursive interface is fine).',
302
+ detail: 'The build computes a structural id by walking the type, and the walk is\ncapped at a depth far beyond any realistic shape. Hitting the cap with no\nsingle recurring type on the path means literally written (or generated)\nnesting hundreds of levels deep.\n\nFix: reflect a concrete, bounded projection of the type (e.g. the element\nor data type you actually send), or restructure the recursion so the same\nnamed type recurs by reference (a plain recursive interface is fine).',
293
303
  },
294
304
  MKR009: {
295
305
  headline: 'Type `{0}` re-instantiates itself with fresh type arguments at every level (a self-instantiating generic), so its structural id never resolves. Reflect a monomorphic shape instead.',
296
306
  severity: 'error',
297
- detail: "A generic method's own type parameters (the `U` in `map<U>(fn: (x: T) => U):\nIter<U>`) are bound at each CALL of the method, so they can never be resolved\nwhile reflecting the containing type and when such a method returns a fresh\ninstantiation of its own container, the type graph grows a new level forever.\nRenaming the type parameters does not resolve them; the fix is a monomorphic\n(fully resolved) recursive shape, which closes by reference:\n\n- interface Iter<T> { map<U>(fn: (x: T) => U): Iter<U> }\n+ interface NumberIter { map(fn: (x: string) => number): NumberIter }\n\nOrdinary generics are unaffected: instantiated types (Map<string, User>, a\nconcrete Iter<string>'s data members) and generic methods that do not\nre-instantiate their container reflect fine. Validators also drop methods\nentirely (methods aren't data), so reflecting just the data shape usually\nsidesteps the problem.",
307
+ detail: "A generic method's own type parameters (the `U` in `map<U>(fn: (x: T) => U):\nIter<U>`) are bound at each CALL of the method, so they can never be resolved\nwhile reflecting the containing type, and when such a method returns a fresh\ninstantiation of its own container, the type graph grows a new level forever.\nRenaming the type parameters does not resolve them; the fix is a monomorphic\n(fully resolved) recursive shape, which closes by reference:\n\n- interface Iter<T> { map<U>(fn: (x: T) => U): Iter<U> }\n+ interface NumberIter { map(fn: (x: string) => number): NumberIter }\n\nOrdinary generics are unaffected: instantiated types (Map<string, User>, a\nconcrete Iter<string>'s data members) and generic methods that do not\nre-instantiate their container reflect fine. Validators also drop methods\nentirely (methods aren't data), so reflecting just the data shape usually\nsidesteps the problem.",
298
308
  },
299
309
  MKR010: {
300
- headline: 'Type argument contains the unresolved type parameter `{0}` a generic must be fully resolved at the marker call, so no id can be computed. See Related for where `{0}` is declared.',
310
+ headline: 'Type argument contains the unresolved type parameter `{0}`: a generic must be fully resolved at the marker call, so no id can be computed. See Related for where `{0}` is declared.',
301
311
  severity: 'error',
302
- detail: "The build can only compute an id for a fully concrete type. `{0}` is a type\nparameter of the surrounding generic it takes a different type at each call\nsite, so a single build-time id would alias every instantiation onto one\n(wrong) shape. A parameter DEFAULT does not help here: defaults resolve where\na caller omits the argument, never inside the generic's own body.\n\nFix resolve the generic before reflecting it:\n interface Box<T> { value: T }\n type BoxString = Box<string>;\n const isBoxString = createValidateFn<BoxString>(); // resolved ok\n\nFix or accept a pre-computed id from the caller and inline the marker at\neach concrete call site (same patterns as MKR003):\n function makeChecker<T>(id: InjectRunTypeId<T>) {\n return createValidateFn<T>(id);\n }\n const isBox = makeChecker<Box<string>>(getRunTypeId<Box<string>>());\n\nGeneric METHODS on a concrete type (`find<T>(query: string): T[]`) are\nunaffected their own type parameters are bound per call of the method and\nmethods aren't data.",
312
+ detail: "The build can only compute an id for a fully concrete type. `{0}` is a type\nparameter of the surrounding generic: it takes a different type at each call\nsite, so a single build-time id would alias every instantiation onto one\n(wrong) shape. A parameter DEFAULT does not help here: defaults resolve where\na caller omits the argument, never inside the generic's own body.\n\nFix: resolve the generic before reflecting it:\n interface Box<T> { value: T }\n type BoxString = Box<string>;\n const isBoxString = createValidateFn<BoxString>(); // resolved, ok\n\nFix: or accept a pre-computed id from the caller and inline the marker at\neach concrete call site (same patterns as MKR003):\n function makeChecker<T>(id: InjectRunTypeId<T>) {\n return createValidateFn<T>(id);\n }\n const isBox = makeChecker<Box<string>>(getRunTypeId<Box<string>>());\n\nGeneric METHODS on a concrete type (`find<T>(query: string): T[]`) are\nunaffected: their own type parameters are bound per call of the method and\nmethods aren't data.",
303
313
  },
304
314
  MKR011: {
305
- headline: 'Generic type `{0}` is used without its required type argument(s) parameter `{1}` has no default, so the type cannot resolve to an id. See Related for where `{1}` is declared.',
315
+ headline: 'Generic type `{0}` is used without its required type argument(s): parameter `{1}` has no default, so the type cannot resolve to an id. See Related for where `{1}` is declared.',
316
+ severity: 'error',
317
+ detail: "TypeScript itself rejects this usage (TS2314), but dev-server builds don't\nrun the type checker, so the scan reads the written type arguments and stops\nthe build here instead of silently reflecting `any` (a validator over `any`\naccepts everything).\n\nFix: pass the missing type argument:\n- const isA = createValidateFn<A>();\n+ const isA = createValidateFn<A<string>>();\n\nFix: or give the parameter a default, which the compiler resolves at every\nbare use site:\n- interface A<S extends string> { a: S }\n+ interface A<S extends string = string> { a: S }\n const isA = createValidateFn<A>(); // now resolves to A<string>",
318
+ },
319
+ MKR012: {
320
+ headline: '`{0}` here was declared by `{1}`, which this project does not trust as a marker package, so the type argument was dropped and this call reflects `unknown`.',
321
+ severity: 'warning',
322
+ detail: 'A marker only counts when it is BOTH named correctly and declared by a\ntrusted package, so a same-named type of your own never drives rewrites.\nThis one has the right name but comes from a package that is not on the\nlist, so its type argument was ignored: the call still compiles and still\ngenerates a function, but for `unknown` rather than for your type — a\nvalidator over `unknown` accepts everything.\n\nFix: trust the package in your tsconfig plugin entry:\n {\n "name": "ts-runtypes",\n+ "markers": {"packages": ["{1}"]}\n }\n\nThe list is additive, so `@ts-runtypes/core` keeps working alongside it.\nThe same setting exists on the bundler plugin (`markers`) and as the\n`--marker-packages` CLI flag.\n\nIf the package re-exports the markers rather than declaring its own\n(`export type {InjectRunTypeId} from \'@ts-runtypes/core\'`), no setting is\nneeded — a re-export keeps RunTypes as the declaring package, so check\nwhether the package meant to re-export instead.',
323
+ },
324
+ MKR013: {
325
+ headline: 'Marker type resolved to `any` that was never written: `{0}` failed to resolve (or its declaration references a name that does not), so the generated functions would silently accept anything.',
306
326
  severity: 'error',
307
- detail: "TypeScript itself rejects this usage (TS2314), but dev-server builds don't\nrun the type checker, so the scan reads the written type arguments and stops\nthe build here instead of silently reflecting `any` (a validator over `any`\naccepts everything).\n\nFix pass the missing type argument:\n- const isA = createValidateFn<A>();\n+ const isA = createValidateFn<A<string>>();\n\nFix or give the parameter a default, which the compiler resolves at every\nbare use site:\n- interface A<S extends string> { a: S }\n+ interface A<S extends string = string> { a: S }\n const isA = createValidateFn<A>(); // now resolves to A<string>",
327
+ detail: "The type checker keeps a distinct internal ERROR type for names it could\nnot resolve; it behaves like `any`, so without this guard the validator\nbecomes the always-true identity, the mock `undefined`, and encoders pass\nvalues through with exit code 0 and no signal. A deliberately written\n`any`, and an alias like `type Loose = any`, are the real `any` and never\ntrip this.\n\nCommon causes and fixes:\n- A typo in the type name: fix the spelling.\n- A dependency whose types are not installed: install/declare them.\n- An ambient declaration (`declare interface ...` in a `.d.ts`) that is\n not part of the scanned program: make sure the `.d.ts` is matched by the\n tsconfig `include`/`files` set. The dev server and lint read that file\n list when they start, so after ADDING a new `.d.ts`, restart the dev\n server (or the editor's lint process) for it to be seen.",
308
328
  },
309
329
  NE001: {
310
- headline: 'Property `{0}` is tagged @nonEnumerable but is required the guard only applies to optional properties, so the tag has no effect. Make it optional (`{0}?`) or remove the tag.',
330
+ headline: 'Property `{0}` is tagged @nonEnumerable but is required: the guard only applies to optional properties, so the tag has no effect. Make it optional (`{0}?`) or remove the tag.',
311
331
  severity: 'error',
312
- detail: "The runtime enumerability guard (which lets a value omit a property from\nthe wire when it isn't an enumerable own property) is applied ONLY to\noptional properties. That keeps the decoder's `DataOnly<T>` return type\nhonest: a guarded property is always one the type already allows to be\nabsent. A `@nonEnumerable` tag on a REQUIRED property is therefore ignored\n— the property still serializes unconditionally.\n\nFix make the property optional:\n- /** @nonEnumerable */ token: string;\n+ /** @nonEnumerable */ token?: string;",
332
+ detail: "The runtime enumerability guard (which lets a value omit a property from\nthe wire when it isn't an enumerable own property) is applied ONLY to\noptional properties. That keeps the decoder's `DataOnly<T>` return type\nhonest: a guarded property is always one the type already allows to be\nabsent. A `@nonEnumerable` tag on a REQUIRED property is therefore ignored;\nthe property still serializes unconditionally.\n\nFix: make the property optional:\n- /** @nonEnumerable */ token: string;\n+ /** @nonEnumerable */ token?: string;",
313
333
  },
314
334
  OVR001: {
315
- headline: 'Duplicate override for `{0}` there can be exactly one override per (type, function).',
335
+ headline: 'Duplicate override for `{0}`: there can be exactly one override per (type, function).',
316
336
  severity: 'error',
317
- detail: 'Two `overrideX<T>()` declarations target the same type and the same\nfunction family. Which one wins would depend on scan order, so a second\noverride is rejected regardless of its body. The Related: line above\npoints at the override that was registered first.\n\nFix keep one canonical override and delete the other:\n- overrideValidate<User>((utl) => (value) => checkA(value)); // first\n- overrideValidate<User>((utl) => (value) => checkB(value)); // duplicate\n+ overrideValidate<User>((utl) => (value) => checkA(value) && checkB(value));',
337
+ detail: 'Two `overrideX<T>()` declarations target the same type and the same\nfunction family. Which one wins would depend on scan order, so a second\noverride is rejected regardless of its body. The Related: line above\npoints at the override that was registered first.\n\nFix: keep one canonical override and delete the other:\n- overrideValidate<User>((utl) => (value) => checkA(value)); // first\n- overrideValidate<User>((utl) => (value) => checkB(value)); // duplicate\n+ overrideValidate<User>((utl) => (value) => checkA(value) && checkB(value));',
318
338
  },
319
339
  OVR002: {
320
- headline: 'Override entry `{0}` references compiled function `{1}` which did not render this would throw at runtime, so the build stops.',
340
+ headline: 'Override entry `{0}` references compiled function `{1}` which did not render: this would throw at runtime, so the build stops.',
321
341
  severity: 'error',
322
- detail: "An override redirect body loads its compiled function from the cache\n(`usePureFn('cfn::…')`), but that module never rendered into the entry\ngraph. Calling the override would throw at runtime, so the build surfaces\nthe miss now. This is an internal emitter tripwire and should never fire\nin normal operation.\n\nFix re-run with a clean cache first (delete the .runtypes cache dir /\nrestart the dev server). If it persists, the emitter dropped a module it\nshould have rendered: please open an issue with the type + override that\ntriggers it.",
342
+ detail: "An override redirect body loads its compiled function from the cache\n(`usePureFn('cfn::…')`), but that module never rendered into the entry\ngraph. Calling the override would throw at runtime, so the build surfaces\nthe miss now. This is an internal emitter tripwire and should never fire\nin normal operation.\n\nFix: re-run with a clean cache first (delete the .runtypes cache dir /\nrestart the dev server). If it persists, the emitter dropped a module it\nshould have rendered: please open an issue with the type + override that\ntriggers it.",
323
343
  },
324
344
  OVR010: {
325
345
  headline: 'Overriding `validate` for this type also changes how JSON and binary decoders narrow unions containing it.',
326
346
  severity: 'warning',
327
- detail: "`validate` is a shared dependency across function families: JSON and\nbinary union decoders call the member validators to pick the matching\nbranch. An `overrideValidate<T>()` therefore reaches past\n`createValidateFn<T>()` decoders of any union containing T now narrow\nwith YOUR function.\n\nThis is informational; the build proceeds. If the override should only\naffect direct validation, give the union members a discriminant so\ndecoders never fall back to member validation:\n type Event = {kind: 'click'; x: number} | {kind: 'key'; code: string};",
347
+ detail: "`validate` is a shared dependency across function families: JSON and\nbinary union decoders call the member validators to pick the matching\nbranch. An `overrideValidate<T>()` therefore reaches past\n`createValidateFn<T>()`: decoders of any union containing T now narrow\nwith YOUR function.\n\nThis is informational; the build proceeds. If the override should only\naffect direct validation, give the union members a discriminant so\ndecoders never fall back to member validation:\n type Event = {kind: 'click'; x: number} | {kind: 'key'; code: string};",
328
348
  },
329
349
  PFE9004: {
330
- headline: 'Duplicate `registerPureFnFactory` for `{0}` with a different body only one definition can win.',
350
+ headline: 'Duplicate `registerPureFnFactory` for `{0}` with a different body; only one definition can win.',
331
351
  severity: 'error',
332
- detail: 'Two calls register the same `namespace::functionId` key but the factory\nbodies differ. The cache can only hold one definition, so one call site\nsilently loses its version at runtime.\n\nFix make all registrations identical, or pick one canonical site and\ndelete the others. The Related: line above points at the first\nregistration the extractor saw.',
352
+ detail: 'Two calls register the same `namespace::functionId` key but the factory\nbodies differ. The cache can only hold one definition, so one call site\nsilently loses its version at runtime.\n\nFix: make all registrations identical, or pick one canonical site and\ndelete the others. The Related: line above points at the first\nregistration the extractor saw.',
333
353
  },
334
354
  PFE9005: {
335
- headline: 'Pure-fn factory `{0}` uses destructured parameters only simple identifier params are supported.',
355
+ headline: 'Pure-fn factory `{0}` uses destructured parameters; only simple identifier params are supported.',
336
356
  severity: 'error',
337
- detail: "The build inlines parameter references by name when it materialises the\nfactory. Destructuring patterns (`({a, b})`, `([x, y])`) don't have a\nsingle name to substitute.\n\nFix destructure inside the body:\n - registerPureFnFactory('ns::fn', (utl) => ({a, b}) => ...);\n+ registerPureFnFactory('ns::fn', (utl) => (params) => {\n+ const {a, b} = params;\n+ return ...;\n+ });",
357
+ detail: "The build inlines parameter references by name when it materialises the\nfactory. Destructuring patterns (`({a, b})`, `([x, y])`) don't have a\nsingle name to substitute.\n\nFix: destructure inside the body:\n - registerPureFnFactory('ns::fn', (utl) => ({a, b}) => ...);\n+ registerPureFnFactory('ns::fn', (utl) => (params) => {\n+ const {a, b} = params;\n+ return ...;\n+ });",
338
358
  },
339
359
  PFE9006: {
340
- headline: "`this` is not allowed inside a `registerPureFnFactory` factory body pure functions can't depend on a calling context.",
360
+ headline: "`this` is not allowed inside a `registerPureFnFactory` factory body; pure functions can't depend on a calling context.",
341
361
  severity: 'error',
342
- detail: "Pure functions are materialised standalone at build time; there's no\n`this` to bind to.\n\nFix replace `this` with an explicit parameter, or move the function\nout of the class/object method that owns the `this`:\n registerPureFnFactory('ns::fn', (utl) => (self, input) => {\n return self.field + input;\n });",
362
+ detail: "Pure functions are materialised standalone at build time; there's no\n`this` to bind to.\n\nFix: replace `this` with an explicit parameter, or move the function\nout of the class/object method that owns the `this`:\n registerPureFnFactory('ns::fn', (utl) => (self, input) => {\n return self.field + input;\n });",
343
363
  },
344
364
  PFE9007: {
345
365
  headline: '`async`/`await` is not allowed inside a `registerPureFnFactory` factory body.',
346
366
  severity: 'error',
347
- detail: "Pure functions must run synchronously so the build can call them at\ncompile time. `async` introduces a Promise that won't resolve until\nruntime.\n\nFix make the factory synchronous; move async work to the caller:\n registerPureFnFactory('ns::fn', (utl) => {\n- return async (input) => { const r = await heavy(); return r; };\n+ return (resolvedValue) => transform(resolvedValue);\n });",
367
+ detail: "Pure functions must run synchronously so the build can call them at\ncompile time. `async` introduces a Promise that won't resolve until\nruntime.\n\nFix: make the factory synchronous; move async work to the caller:\n registerPureFnFactory('ns::fn', (utl) => {\n- return async (input) => { const r = await heavy(); return r; };\n+ return (resolvedValue) => transform(resolvedValue);\n });",
348
368
  },
349
369
  PFE9008: {
350
370
  headline: '`yield` / generators are not allowed inside a `registerPureFnFactory` factory body.',
351
371
  severity: 'error',
352
- detail: "Generators carry resumption state that can't be materialised\nstatically.\n\nFix return an array or a plain iterable instead:\n registerPureFnFactory('ns::fn', (utl) => (input) => {\n return [...computeAll(input)];\n });",
372
+ detail: "Generators carry resumption state that can't be materialised\nstatically.\n\nFix: return an array or a plain iterable instead:\n registerPureFnFactory('ns::fn', (utl) => (input) => {\n return [...computeAll(input)];\n });",
353
373
  },
354
374
  PFE9009: {
355
375
  headline: '`import()` is not allowed inside a `registerPureFnFactory` factory body.',
356
376
  severity: 'error',
357
- detail: 'Dynamic imports load modules at runtime the build needs every\ndependency available statically.\n\nFix use a top-level `import` statement, or pass the imported module\nin as a parameter.',
377
+ detail: 'Dynamic imports load modules at runtime, the build needs every\ndependency available statically.\n\nFix: use a top-level `import` statement, or pass the imported module\nin as a parameter.',
358
378
  },
359
379
  PFE9010: {
360
380
  headline: '`{0}` is not allowed inside a `registerPureFnFactory` factory body.',
361
381
  severity: 'error',
362
- detail: "Globals like `eval`, `Function`, `fetch`, `XMLHttpRequest`, `require`,\n`process`, `globalThis`, `window`, `document` are blocked from pure-fn\nbodies they either execute arbitrary code or depend on a runtime\nenvironment the build can't reproduce.\n\nFix remove the reference, or pass the needed value in as a parameter.",
382
+ detail: "Globals like `eval`, `Function`, `fetch`, `XMLHttpRequest`, `require`,\n`process`, `globalThis`, `window`, `document` are blocked from pure-fn\nbodies: they either execute arbitrary code or depend on a runtime\nenvironment the build can't reproduce.\n\nFix: remove the reference, or pass the needed value in as a parameter.",
363
383
  },
364
384
  PFE9011: {
365
- headline: "`{0}` is captured from outer scope inside a `registerPureFnFactory` factory pure functions can't reach outside their own body.",
385
+ headline: "`{0}` is captured from outer scope inside a `registerPureFnFactory` factory; pure functions can't reach outside their own body.",
366
386
  severity: 'error',
367
- detail: "The build inlines factory bodies without their lexical environment, so\nany free variable becomes `undefined` at runtime.\n\nFix pass `{0}` in as a parameter:\n registerPureFnFactory('ns::fn', (utl) => ({0}, value) => ...);\n\nFix inline its value if it's a known constant:\n registerPureFnFactory('ns::fn', (utl) => (value) => {\n const {0} = 42;\n ...\n });\n\nFix import `{0}` directly inside the factory if it's a module export.",
387
+ detail: "The build inlines factory bodies without their lexical environment, so\nany free variable becomes `undefined` at runtime.\n\nFix: pass `{0}` in as a parameter:\n registerPureFnFactory('ns::fn', (utl) => ({0}, value) => ...);\n\nFix: inline its value if it's a known constant:\n registerPureFnFactory('ns::fn', (utl) => (value) => {\n const {0} = 42;\n ...\n });\n\nFix: import `{0}` directly inside the factory if it's a module export.",
368
388
  },
369
389
  PFE9012: {
370
- headline: "Pure-fn `{0}` is referenced by a RT function but never registered call `registerPureFnFactory('{1}::{2}', …)` first.",
390
+ headline: "Pure-fn `{0}` is referenced by a RT function but never registered; call `registerPureFnFactory('{1}::{2}', …)` first.",
371
391
  severity: 'error',
372
- detail: "A RT validator/encoder calls `utl.usePureFn('{0}')` (or similar) but\nno `registerPureFnFactory` call with that namespace+function pair was\nfound in any scanned source file.\n\nFix register the function in the expected location ({3}, if known).\nMake sure the file is included in the scan set.",
392
+ detail: "A RT validator/encoder calls `utl.usePureFn('{0}')` (or similar) but\nno `registerPureFnFactory` call with that namespace+function pair was\nfound in any scanned source file.\n\nFix: register the function in the expected location ({3}, if known).\nMake sure the file is included in the scan set.",
373
393
  },
374
394
  PFE9013: {
375
395
  headline: '`{0}.{1}` dependency argument must be a string literal or a same-scope `const` string.',
@@ -379,397 +399,397 @@ export const DIAGNOSTIC_CATALOG = {
379
399
  PFN001: {
380
400
  headline: '`PureFunction<F>` argument must be an INLINE arrow or function expression.',
381
401
  severity: 'error',
382
- detail: "The build extracts and AOT-compiles the function body, so it must see the\nliteral inline at the call site. A named reference even a module-private\n`const f = …` or `function f(){}` is not accepted, because the literal\nmust have no handle anything else can reach; the compiled copy is then the\nonly one that can run. (An imported or exported literal is rejected as PFN002.)\n\nFix inline the function at the call site:\n- const validate = (v: unknown) => typeof v === 'string';\n- registerValidator(validate);\n+ registerValidator((v: unknown) => typeof v === 'string');",
402
+ detail: "The build extracts and AOT-compiles the function body, so it must see the\nliteral inline at the call site. A named reference (even a module-private\n`const f = …` or `function f(){}`) is not accepted, because the literal\nmust have no handle anything else can reach; the compiled copy is then the\nonly one that can run. (An imported or exported literal is rejected as PFN002.)\n\nFix: inline the function at the call site:\n- const validate = (v: unknown) => typeof v === 'string';\n- registerValidator(validate);\n+ registerValidator((v: unknown) => typeof v === 'string');",
383
403
  },
384
404
  PFN002: {
385
- headline: '`PureFunction<F>` literal must not be imported or exported the compiled copy must be the only one that can run.',
405
+ headline: '`PureFunction<F>` literal must not be imported or exported: the compiled copy must be the only one that can run.',
386
406
  severity: 'error',
387
- detail: "The build extracts and AOT-compiles the function body, and the compiled\ncopy is the single source of truth. If the original literal stays reachable\nas a value imported from another module, or exported so another module can\nimport it a caller could invoke the un-compiled function and diverge from\nthe compiled behaviour.\n\nUnder the literal-only rule a named binding isn't allowed at all (see PFN001),\nso the fix is to inline the function at the call site:\n- import {validate} from './validators'; // imported rejected\n- export const validate = (v) => …; // exported rejected\n+ registerValidator((v: unknown) => typeof v === 'string'); // inline ok",
407
+ detail: "The build extracts and AOT-compiles the function body, and the compiled\ncopy is the single source of truth. If the original literal stays reachable\nas a value (imported from another module, or exported so another module can\nimport it), a caller could invoke the un-compiled function and diverge from\nthe compiled behaviour.\n\nUnder the literal-only rule a named binding isn't allowed at all (see PFN001),\nso the fix is to inline the function at the call site:\n- import {validate} from './validators'; // imported, rejected\n- export const validate = (v) => …; // exported, rejected\n+ registerValidator((v: unknown) => typeof v === 'string'); // inline, ok",
388
408
  },
389
409
  PJ001: {
390
- headline: 'Type `{0}` can never be encoded to JSON the generated function will always fail.',
410
+ headline: 'Type `{0}` can never be encoded to JSON: the generated function will always fail.',
391
411
  severity: 'error',
392
- detail: "`never` is the empty type no value can ever inhabit it. A field\ntyped `never` cannot carry a runtime value, so there is nothing to\nencode/decode/validate.\n\nFix use `unknown` if you really want to accept any value:\n interface User {\n- tag: never;\n+ tag: unknown; // narrow before use\n }\n\nFix pick a concrete type matching your real data:\n interface User {\n- tag: never;\n+ tag: 'pending' | 'active' | 'done';\n }",
412
+ detail: "`never` is the empty type: no value can ever inhabit it. A field\ntyped `never` cannot carry a runtime value, so there is nothing to\nencode/decode/validate.\n\nFix: use `unknown` if you really want to accept any value:\n interface User {\n- tag: never;\n+ tag: unknown; // narrow before use\n }\n\nFix: pick a concrete type matching your real data:\n interface User {\n- tag: never;\n+ tag: 'pending' | 'active' | 'done';\n }",
393
413
  },
394
414
  PJ002: {
395
- headline: 'Type `{0}` can never be encoded to JSON the generated function will always fail.',
415
+ headline: 'Type `{0}` can never be encoded to JSON: the generated function will always fail.',
396
416
  severity: 'error',
397
- detail: "Built-in classes like `Map`, `Set`, `WeakMap`, `WeakSet`, `Int8Array`,\n`Uint8Array`, `Buffer`, and `Promise` carry runtime state that doesn't\nsurvive a JSON or binary round-trip. Their instance identity is lost the\nmoment they're serialised.\n\nFix convert to a plain object/array before serialising:\n // for Map<K, V>:\n const data = Object.fromEntries(yourMap);\n // for Set<T>:\n const data = [...yourSet];\n // for typed arrays:\n const data = Array.from(yourBuffer);\n\nFix change the field type to a serialisable shape:\n interface User {\n- tags: Set<string>;\n+ tags: string[];\n }",
417
+ detail: "Built-in classes like `Map`, `Set`, `WeakMap`, `WeakSet`, `Int8Array`,\n`Uint8Array`, `Buffer`, and `Promise` carry runtime state that doesn't\nsurvive a JSON or binary round-trip. Their instance identity is lost the\nmoment they're serialised.\n\nFix: convert to a plain object/array before serialising:\n // for Map<K, V>:\n const data = Object.fromEntries(yourMap);\n // for Set<T>:\n const data = [...yourSet];\n // for typed arrays:\n const data = Array.from(yourBuffer);\n\nFix: change the field type to a serialisable shape:\n interface User {\n- tags: Set<string>;\n+ tags: string[];\n }",
398
418
  },
399
419
  PJ003: {
400
- headline: 'Type `{0}` can never be encoded to JSON the generated function will always fail.',
420
+ headline: 'Type `{0}` can never be encoded to JSON: the generated function will always fail.',
401
421
  severity: 'error',
402
- detail: "Functions have no value form to serialise their closure, prototype,\nand bound state aren't representable in JSON or binary.\n\nFix drop the function from your type, or replace it with the data the\nfunction would produce:\n interface User {\n- getName: () => string;\n+ name: string;\n }",
422
+ detail: "Functions have no value form to serialise: their closure, prototype,\nand bound state aren't representable in JSON or binary.\n\nFix: drop the function from your type, or replace it with the data the\nfunction would produce:\n interface User {\n- getName: () => string;\n+ name: string;\n }",
403
423
  },
404
424
  PJ004: {
405
- headline: 'Type `{0}` can never be encoded to JSON the generated function will always fail.',
425
+ headline: 'Type `{0}` can never be encoded to JSON: the generated function will always fail.',
406
426
  severity: 'error',
407
- detail: "Arrays of un-serialisable elements (`symbol[]`, `(() => void)[]`,\n`Map<K, V>[]`, etc.) can't be encoded every element would need to be\nrepresentable, and these aren't. Dropping individual elements would\nchange the array length, so the encoder refuses rather than silently\nshipping a different shape.\n\nFix change the element type to something serialisable:\n - type Items = (() => void)[];\n+ type Items = string[];",
427
+ detail: "Arrays of un-serialisable elements (`symbol[]`, `(() => void)[]`,\n`Map<K, V>[]`, etc.) can't be encoded: every element would need to be\nrepresentable, and these aren't. Dropping individual elements would\nchange the array length, so the encoder refuses rather than silently\nshipping a different shape.\n\nFix: change the element type to something serialisable:\n - type Items = (() => void)[];\n+ type Items = string[];",
408
428
  },
409
429
  PJ005: {
410
- headline: 'Type `{0}` can never be encoded to JSON the generated function will always fail.',
430
+ headline: 'Type `{0}` can never be encoded to JSON: the generated function will always fail.',
411
431
  severity: 'error',
412
- detail: "Every `symbol` value carries a unique runtime identity (`Symbol() !==\nSymbol()` even with the same description). That identity disappears the\nmoment it's serialised, and two symbols can't be compared across realms,\nworkers, or process boundaries. A validator that asserts \"this is a\nsymbol\" gives a false sense of safety the value can't actually\nround-trip.\n\nFix use a stable string key (often a literal union):\n - type Status = symbol;\n+ type Status = 'pending' | 'active' | 'done';",
432
+ detail: "Every `symbol` value carries a unique runtime identity (`Symbol() !==\nSymbol()` even with the same description). That identity disappears the\nmoment it's serialised, and two symbols can't be compared across realms,\nworkers, or process boundaries. A validator that asserts \"this is a\nsymbol\" gives a false sense of safety: the value can't actually\nround-trip.\n\nFix: use a stable string key (often a literal union):\n - type Status = symbol;\n+ type Status = 'pending' | 'active' | 'done';",
413
433
  },
414
434
  PJ010: {
415
- headline: 'Property `{0}` is a function `prepareForJson` does not handle function values, so this property is silently not encoded.',
435
+ headline: 'Property `{0}` is a function: `prepareForJson` does not handle function values, so this property is silently not encoded.',
416
436
  severity: 'warning',
417
- detail: '`prepareForJson` works on JSON-shaped data; functions don\'t survive JSON, so\nthe emitter drops them. The rest of the object\'s behaviour is unaffected.\n\nThis is by design see the "validate contract serializable data only"\nsection in CLAUDE.md. If you need a stricter checker that fails on\nmissing/extra function-typed members, watch the project roadmap.',
437
+ detail: '`prepareForJson` works on JSON-shaped data; functions don\'t survive JSON, so\nthe emitter drops them. The rest of the object\'s behaviour is unaffected.\n\nThis is by design, see the "one contract: serializable data only"\nsection in CLAUDE.md. If you need a stricter checker that fails on\nmissing/extra function-typed members, watch the project roadmap.',
418
438
  },
419
439
  PJ011: {
420
- headline: "Method `{0}` is silently not encoded by `prepareForJson` methods aren't data.",
440
+ headline: "Method `{0}` is silently not encoded by `prepareForJson`: methods aren't data.",
421
441
  severity: 'warning',
422
442
  detail: "Class and object methods aren't part of the serialisable shape, so\n`prepareForJson` excludes them. The rest of the type still works.\n\nIf you wanted the method's return value validated/serialised, expose it\nas a data property instead.",
423
443
  },
424
444
  PJ012: {
425
- headline: "Static member `{0}` is silently not encoded by `prepareForJson` statics aren't part of instance data.",
445
+ headline: "Static member `{0}` is silently not encoded by `prepareForJson`: statics aren't part of instance data.",
426
446
  severity: 'warning',
427
447
  detail: 'Class static members live on the class, not on individual instances.\n`prepareForJson` operates on instance shape, so statics are excluded.',
428
448
  },
429
449
  PJ013: {
430
- headline: "Symbol-keyed property `{0}` is silently not encoded by `prepareForJson` symbol keys aren't JSON-representable.",
450
+ headline: "Symbol-keyed property `{0}` is silently not encoded by `prepareForJson`: symbol keys aren't JSON-representable.",
431
451
  severity: 'warning',
432
- detail: "JSON only supports string keys; symbol-keyed properties are dropped\nfrom the serialised form. `prepareForJson` follows the same rule.\n\nFix use a string key:\n - [Symbol.for('id')]: string;\n+ id: string;",
452
+ detail: "JSON only supports string keys; symbol-keyed properties are dropped\nfrom the serialised form. `prepareForJson` follows the same rule.\n\nFix: use a string key:\n - [Symbol.for('id')]: string;\n+ id: string;",
433
453
  },
434
454
  PJ014: {
435
- headline: "Union member(s) of type `{0}` can't be represented as data `prepareForJson` drops them, so the union is encoded as its remaining members.",
455
+ headline: "Union member(s) of type `{0}` can't be represented as data: `prepareForJson` drops them, so the union is encoded as its remaining members.",
436
456
  severity: 'warning',
437
- detail: 'A union projects to its serialisable members only: `DataOnly<Date | symbol>`\nis `Date`. The dropped member(s) ({0}) carry no JSON-shaped value (symbol,\nfunction, Promise, or a non-serialisable built-in like `Map` / `Set` /\ntyped arrays), so `prepareForJson` encoded only the members that remain.\n\nThis is by design see the "validate contract serializable data only"\nsection in CLAUDE.md. If EVERY member of the union is non-serialisable the\nprojection is `never`, and `prepareForJson` throws at build time instead.',
457
+ detail: 'A union projects to its serialisable members only: `DataOnly<Date | symbol>`\nis `Date`. The dropped member(s) ({0}) carry no JSON-shaped value (symbol,\nfunction, Promise, or a non-serialisable built-in like `Map` / `Set` /\ntyped arrays), so `prepareForJson` encoded only the members that remain.\n\nThis is by design, see the "one contract: serializable data only"\nsection in CLAUDE.md. If EVERY member of the union is non-serialisable the\nprojection is `never`, and `prepareForJson` throws at build time instead.',
438
458
  },
439
459
  PJ015: {
440
- headline: 'Property `{0}` has a non-serialisable value type (symbol, Promise, or a non-serialisable built-in) `prepareForJson` drops it, so this property is silently not encoded.',
460
+ headline: 'Property `{0}` has a non-serialisable value type (symbol, Promise, or a non-serialisable built-in): `prepareForJson` drops it, so this property is silently not encoded.',
441
461
  severity: 'warning',
442
- detail: '`prepareForJson` works on JSON-shaped data. A property whose value is a symbol,\na Promise, or a non-serialisable built-in (typed array, ArrayBuffer, …) carries\nno JSON-shaped value, so it is dropped: `DataOnly<{ {0}: symbol }>` is `{}`.\nThe rest of the object\'s behaviour is unaffected.\n\nNote the difference from a property that is only STRUCTURALLY unserialisable —\n`{0}: symbol[]` or `{0}: Map<string, symbol>` which CANNOT be safely\ndropped (DataOnly keeps it as `never[]`): there `prepareForJson` throws at build\ntime instead.\n\nThis is by design see the "validate contract serializable data only"\nsection in CLAUDE.md.',
462
+ detail: '`prepareForJson` works on JSON-shaped data. A property whose value is a symbol,\na Promise, or a non-serialisable built-in (typed array, ArrayBuffer, …) carries\nno JSON-shaped value, so it is dropped: `DataOnly<{ {0}: symbol }>` is `{}`.\nThe rest of the object\'s behaviour is unaffected.\n\nNote the difference from a property that is only STRUCTURALLY unserialisable\n(`{0}: symbol[]` or `{0}: Map<string, symbol>`), which CANNOT be safely\ndropped (DataOnly keeps it as `never[]`): there `prepareForJson` throws at build\ntime instead.\n\nThis is by design, see the "one contract: serializable data only"\nsection in CLAUDE.md.',
443
463
  },
444
464
  PJS001: {
445
- headline: 'Type `{0}` can never be encoded to JSON the generated function will always fail.',
465
+ headline: 'Type `{0}` can never be encoded to JSON: the generated function will always fail.',
446
466
  severity: 'error',
447
- detail: "`never` is the empty type no value can ever inhabit it. A field\ntyped `never` cannot carry a runtime value, so there is nothing to\nencode/decode/validate.\n\nFix use `unknown` if you really want to accept any value:\n interface User {\n- tag: never;\n+ tag: unknown; // narrow before use\n }\n\nFix pick a concrete type matching your real data:\n interface User {\n- tag: never;\n+ tag: 'pending' | 'active' | 'done';\n }",
467
+ detail: "`never` is the empty type: no value can ever inhabit it. A field\ntyped `never` cannot carry a runtime value, so there is nothing to\nencode/decode/validate.\n\nFix: use `unknown` if you really want to accept any value:\n interface User {\n- tag: never;\n+ tag: unknown; // narrow before use\n }\n\nFix: pick a concrete type matching your real data:\n interface User {\n- tag: never;\n+ tag: 'pending' | 'active' | 'done';\n }",
448
468
  },
449
469
  PJS002: {
450
- headline: 'Type `{0}` can never be encoded to JSON the generated function will always fail.',
470
+ headline: 'Type `{0}` can never be encoded to JSON: the generated function will always fail.',
451
471
  severity: 'error',
452
- detail: "Built-in classes like `Map`, `Set`, `WeakMap`, `WeakSet`, `Int8Array`,\n`Uint8Array`, `Buffer`, and `Promise` carry runtime state that doesn't\nsurvive a JSON or binary round-trip. Their instance identity is lost the\nmoment they're serialised.\n\nFix convert to a plain object/array before serialising:\n // for Map<K, V>:\n const data = Object.fromEntries(yourMap);\n // for Set<T>:\n const data = [...yourSet];\n // for typed arrays:\n const data = Array.from(yourBuffer);\n\nFix change the field type to a serialisable shape:\n interface User {\n- tags: Set<string>;\n+ tags: string[];\n }",
472
+ detail: "Built-in classes like `Map`, `Set`, `WeakMap`, `WeakSet`, `Int8Array`,\n`Uint8Array`, `Buffer`, and `Promise` carry runtime state that doesn't\nsurvive a JSON or binary round-trip. Their instance identity is lost the\nmoment they're serialised.\n\nFix: convert to a plain object/array before serialising:\n // for Map<K, V>:\n const data = Object.fromEntries(yourMap);\n // for Set<T>:\n const data = [...yourSet];\n // for typed arrays:\n const data = Array.from(yourBuffer);\n\nFix: change the field type to a serialisable shape:\n interface User {\n- tags: Set<string>;\n+ tags: string[];\n }",
453
473
  },
454
474
  PJS003: {
455
- headline: 'Type `{0}` can never be encoded to JSON the generated function will always fail.',
475
+ headline: 'Type `{0}` can never be encoded to JSON: the generated function will always fail.',
456
476
  severity: 'error',
457
- detail: "Functions have no value form to serialise their closure, prototype,\nand bound state aren't representable in JSON or binary.\n\nFix drop the function from your type, or replace it with the data the\nfunction would produce:\n interface User {\n- getName: () => string;\n+ name: string;\n }",
477
+ detail: "Functions have no value form to serialise: their closure, prototype,\nand bound state aren't representable in JSON or binary.\n\nFix: drop the function from your type, or replace it with the data the\nfunction would produce:\n interface User {\n- getName: () => string;\n+ name: string;\n }",
458
478
  },
459
479
  PJS004: {
460
- headline: 'Type `{0}` can never be encoded to JSON the generated function will always fail.',
480
+ headline: 'Type `{0}` can never be encoded to JSON: the generated function will always fail.',
461
481
  severity: 'error',
462
- detail: "Arrays of un-serialisable elements (`symbol[]`, `(() => void)[]`,\n`Map<K, V>[]`, etc.) can't be encoded every element would need to be\nrepresentable, and these aren't. Dropping individual elements would\nchange the array length, so the encoder refuses rather than silently\nshipping a different shape.\n\nFix change the element type to something serialisable:\n - type Items = (() => void)[];\n+ type Items = string[];",
482
+ detail: "Arrays of un-serialisable elements (`symbol[]`, `(() => void)[]`,\n`Map<K, V>[]`, etc.) can't be encoded: every element would need to be\nrepresentable, and these aren't. Dropping individual elements would\nchange the array length, so the encoder refuses rather than silently\nshipping a different shape.\n\nFix: change the element type to something serialisable:\n - type Items = (() => void)[];\n+ type Items = string[];",
463
483
  },
464
484
  PJS005: {
465
- headline: 'Type `{0}` can never be encoded to JSON the generated function will always fail.',
485
+ headline: 'Type `{0}` can never be encoded to JSON: the generated function will always fail.',
466
486
  severity: 'error',
467
- detail: "Every `symbol` value carries a unique runtime identity (`Symbol() !==\nSymbol()` even with the same description). That identity disappears the\nmoment it's serialised, and two symbols can't be compared across realms,\nworkers, or process boundaries. A validator that asserts \"this is a\nsymbol\" gives a false sense of safety the value can't actually\nround-trip.\n\nFix use a stable string key (often a literal union):\n - type Status = symbol;\n+ type Status = 'pending' | 'active' | 'done';",
487
+ detail: "Every `symbol` value carries a unique runtime identity (`Symbol() !==\nSymbol()` even with the same description). That identity disappears the\nmoment it's serialised, and two symbols can't be compared across realms,\nworkers, or process boundaries. A validator that asserts \"this is a\nsymbol\" gives a false sense of safety: the value can't actually\nround-trip.\n\nFix: use a stable string key (often a literal union):\n - type Status = symbol;\n+ type Status = 'pending' | 'active' | 'done';",
468
488
  },
469
489
  PJS010: {
470
- headline: 'Property `{0}` is a function `prepareForJsonSafe` does not handle function values, so this property is silently not encoded.',
490
+ headline: 'Property `{0}` is a function: `prepareForJsonSafe` does not handle function values, so this property is silently not encoded.',
471
491
  severity: 'warning',
472
- detail: '`prepareForJsonSafe` works on JSON-shaped data; functions don\'t survive JSON, so\nthe emitter drops them. The rest of the object\'s behaviour is unaffected.\n\nThis is by design see the "validate contract serializable data only"\nsection in CLAUDE.md. If you need a stricter checker that fails on\nmissing/extra function-typed members, watch the project roadmap.',
492
+ detail: '`prepareForJsonSafe` works on JSON-shaped data; functions don\'t survive JSON, so\nthe emitter drops them. The rest of the object\'s behaviour is unaffected.\n\nThis is by design, see the "one contract: serializable data only"\nsection in CLAUDE.md. If you need a stricter checker that fails on\nmissing/extra function-typed members, watch the project roadmap.',
473
493
  },
474
494
  PJS011: {
475
- headline: "Method `{0}` is silently not encoded by `prepareForJsonSafe` methods aren't data.",
495
+ headline: "Method `{0}` is silently not encoded by `prepareForJsonSafe`: methods aren't data.",
476
496
  severity: 'warning',
477
497
  detail: "Class and object methods aren't part of the serialisable shape, so\n`prepareForJsonSafe` excludes them. The rest of the type still works.\n\nIf you wanted the method's return value validated/serialised, expose it\nas a data property instead.",
478
498
  },
479
499
  PJS012: {
480
- headline: "Static member `{0}` is silently not encoded by `prepareForJsonSafe` statics aren't part of instance data.",
500
+ headline: "Static member `{0}` is silently not encoded by `prepareForJsonSafe`: statics aren't part of instance data.",
481
501
  severity: 'warning',
482
502
  detail: 'Class static members live on the class, not on individual instances.\n`prepareForJsonSafe` operates on instance shape, so statics are excluded.',
483
503
  },
484
504
  PJS013: {
485
- headline: "Symbol-keyed property `{0}` is silently not encoded by `prepareForJsonSafe` symbol keys aren't JSON-representable.",
505
+ headline: "Symbol-keyed property `{0}` is silently not encoded by `prepareForJsonSafe`: symbol keys aren't JSON-representable.",
486
506
  severity: 'warning',
487
- detail: "JSON only supports string keys; symbol-keyed properties are dropped\nfrom the serialised form. `prepareForJsonSafe` follows the same rule.\n\nFix use a string key:\n - [Symbol.for('id')]: string;\n+ id: string;",
507
+ detail: "JSON only supports string keys; symbol-keyed properties are dropped\nfrom the serialised form. `prepareForJsonSafe` follows the same rule.\n\nFix: use a string key:\n - [Symbol.for('id')]: string;\n+ id: string;",
488
508
  },
489
509
  PJS014: {
490
- headline: "Union member(s) of type `{0}` can't be represented as data `prepareForJsonSafe` drops them, so the union is encoded as its remaining members.",
510
+ headline: "Union member(s) of type `{0}` can't be represented as data: `prepareForJsonSafe` drops them, so the union is encoded as its remaining members.",
491
511
  severity: 'warning',
492
- detail: 'A union projects to its serialisable members only: `DataOnly<Date | symbol>`\nis `Date`. The dropped member(s) ({0}) carry no JSON-shaped value (symbol,\nfunction, Promise, or a non-serialisable built-in like `Map` / `Set` /\ntyped arrays), so `prepareForJsonSafe` encoded only the members that remain.\n\nThis is by design see the "validate contract serializable data only"\nsection in CLAUDE.md. If EVERY member of the union is non-serialisable the\nprojection is `never`, and `prepareForJsonSafe` throws at build time instead.',
512
+ detail: 'A union projects to its serialisable members only: `DataOnly<Date | symbol>`\nis `Date`. The dropped member(s) ({0}) carry no JSON-shaped value (symbol,\nfunction, Promise, or a non-serialisable built-in like `Map` / `Set` /\ntyped arrays), so `prepareForJsonSafe` encoded only the members that remain.\n\nThis is by design, see the "one contract: serializable data only"\nsection in CLAUDE.md. If EVERY member of the union is non-serialisable the\nprojection is `never`, and `prepareForJsonSafe` throws at build time instead.',
493
513
  },
494
514
  PJS015: {
495
- headline: 'Property `{0}` has a non-serialisable value type (symbol, Promise, or a non-serialisable built-in) `prepareForJsonSafe` drops it, so this property is silently not encoded.',
515
+ headline: 'Property `{0}` has a non-serialisable value type (symbol, Promise, or a non-serialisable built-in): `prepareForJsonSafe` drops it, so this property is silently not encoded.',
496
516
  severity: 'warning',
497
- detail: '`prepareForJsonSafe` works on JSON-shaped data. A property whose value is a symbol,\na Promise, or a non-serialisable built-in (typed array, ArrayBuffer, …) carries\nno JSON-shaped value, so it is dropped: `DataOnly<{ {0}: symbol }>` is `{}`.\nThe rest of the object\'s behaviour is unaffected.\n\nNote the difference from a property that is only STRUCTURALLY unserialisable —\n`{0}: symbol[]` or `{0}: Map<string, symbol>` which CANNOT be safely\ndropped (DataOnly keeps it as `never[]`): there `prepareForJsonSafe` throws at build\ntime instead.\n\nThis is by design see the "validate contract serializable data only"\nsection in CLAUDE.md.',
517
+ detail: '`prepareForJsonSafe` works on JSON-shaped data. A property whose value is a symbol,\na Promise, or a non-serialisable built-in (typed array, ArrayBuffer, …) carries\nno JSON-shaped value, so it is dropped: `DataOnly<{ {0}: symbol }>` is `{}`.\nThe rest of the object\'s behaviour is unaffected.\n\nNote the difference from a property that is only STRUCTURALLY unserialisable\n(`{0}: symbol[]` or `{0}: Map<string, symbol>`), which CANNOT be safely\ndropped (DataOnly keeps it as `never[]`): there `prepareForJsonSafe` throws at build\ntime instead.\n\nThis is by design, see the "one contract: serializable data only"\nsection in CLAUDE.md.',
498
518
  },
499
519
  RJ001: {
500
- headline: 'Type `{0}` can never be decoded from JSON the generated function will always fail.',
520
+ headline: 'Type `{0}` can never be decoded from JSON: the generated function will always fail.',
501
521
  severity: 'error',
502
- detail: "`never` is the empty type no value can ever inhabit it. A field\ntyped `never` cannot carry a runtime value, so there is nothing to\nencode/decode/validate.\n\nFix use `unknown` if you really want to accept any value:\n interface User {\n- tag: never;\n+ tag: unknown; // narrow before use\n }\n\nFix pick a concrete type matching your real data:\n interface User {\n- tag: never;\n+ tag: 'pending' | 'active' | 'done';\n }",
522
+ detail: "`never` is the empty type: no value can ever inhabit it. A field\ntyped `never` cannot carry a runtime value, so there is nothing to\nencode/decode/validate.\n\nFix: use `unknown` if you really want to accept any value:\n interface User {\n- tag: never;\n+ tag: unknown; // narrow before use\n }\n\nFix: pick a concrete type matching your real data:\n interface User {\n- tag: never;\n+ tag: 'pending' | 'active' | 'done';\n }",
503
523
  },
504
524
  RJ002: {
505
- headline: 'Type `{0}` can never be decoded from JSON the generated function will always fail.',
525
+ headline: 'Type `{0}` can never be decoded from JSON: the generated function will always fail.',
506
526
  severity: 'error',
507
- detail: "Built-in classes like `Map`, `Set`, `WeakMap`, `WeakSet`, `Int8Array`,\n`Uint8Array`, `Buffer`, and `Promise` carry runtime state that doesn't\nsurvive a JSON or binary round-trip. Their instance identity is lost the\nmoment they're serialised.\n\nFix convert to a plain object/array before serialising:\n // for Map<K, V>:\n const data = Object.fromEntries(yourMap);\n // for Set<T>:\n const data = [...yourSet];\n // for typed arrays:\n const data = Array.from(yourBuffer);\n\nFix change the field type to a serialisable shape:\n interface User {\n- tags: Set<string>;\n+ tags: string[];\n }",
527
+ detail: "Built-in classes like `Map`, `Set`, `WeakMap`, `WeakSet`, `Int8Array`,\n`Uint8Array`, `Buffer`, and `Promise` carry runtime state that doesn't\nsurvive a JSON or binary round-trip. Their instance identity is lost the\nmoment they're serialised.\n\nFix: convert to a plain object/array before serialising:\n // for Map<K, V>:\n const data = Object.fromEntries(yourMap);\n // for Set<T>:\n const data = [...yourSet];\n // for typed arrays:\n const data = Array.from(yourBuffer);\n\nFix: change the field type to a serialisable shape:\n interface User {\n- tags: Set<string>;\n+ tags: string[];\n }",
508
528
  },
509
529
  RJ003: {
510
- headline: 'Type `{0}` can never be decoded from JSON the generated function will always fail.',
530
+ headline: 'Type `{0}` can never be decoded from JSON: the generated function will always fail.',
511
531
  severity: 'error',
512
- detail: "Functions have no value form to serialise their closure, prototype,\nand bound state aren't representable in JSON or binary.\n\nFix drop the function from your type, or replace it with the data the\nfunction would produce:\n interface User {\n- getName: () => string;\n+ name: string;\n }",
532
+ detail: "Functions have no value form to serialise: their closure, prototype,\nand bound state aren't representable in JSON or binary.\n\nFix: drop the function from your type, or replace it with the data the\nfunction would produce:\n interface User {\n- getName: () => string;\n+ name: string;\n }",
513
533
  },
514
534
  RJ004: {
515
- headline: 'Type `{0}` can never be decoded from JSON the generated function will always fail.',
535
+ headline: 'Type `{0}` can never be decoded from JSON: the generated function will always fail.',
516
536
  severity: 'error',
517
- detail: "Arrays of un-serialisable elements (`symbol[]`, `(() => void)[]`,\n`Map<K, V>[]`, etc.) can't be encoded every element would need to be\nrepresentable, and these aren't. Dropping individual elements would\nchange the array length, so the encoder refuses rather than silently\nshipping a different shape.\n\nFix change the element type to something serialisable:\n - type Items = (() => void)[];\n+ type Items = string[];",
537
+ detail: "Arrays of un-serialisable elements (`symbol[]`, `(() => void)[]`,\n`Map<K, V>[]`, etc.) can't be encoded: every element would need to be\nrepresentable, and these aren't. Dropping individual elements would\nchange the array length, so the encoder refuses rather than silently\nshipping a different shape.\n\nFix: change the element type to something serialisable:\n - type Items = (() => void)[];\n+ type Items = string[];",
518
538
  },
519
539
  RJ005: {
520
- headline: 'Type `{0}` can never be decoded from JSON the generated function will always fail.',
540
+ headline: 'Type `{0}` can never be decoded from JSON: the generated function will always fail.',
521
541
  severity: 'error',
522
- detail: "Every `symbol` value carries a unique runtime identity (`Symbol() !==\nSymbol()` even with the same description). That identity disappears the\nmoment it's serialised, and two symbols can't be compared across realms,\nworkers, or process boundaries. A validator that asserts \"this is a\nsymbol\" gives a false sense of safety the value can't actually\nround-trip.\n\nFix use a stable string key (often a literal union):\n - type Status = symbol;\n+ type Status = 'pending' | 'active' | 'done';",
542
+ detail: "Every `symbol` value carries a unique runtime identity (`Symbol() !==\nSymbol()` even with the same description). That identity disappears the\nmoment it's serialised, and two symbols can't be compared across realms,\nworkers, or process boundaries. A validator that asserts \"this is a\nsymbol\" gives a false sense of safety: the value can't actually\nround-trip.\n\nFix: use a stable string key (often a literal union):\n - type Status = symbol;\n+ type Status = 'pending' | 'active' | 'done';",
523
543
  },
524
544
  RJ010: {
525
- headline: 'Property `{0}` is a function `restoreFromJson` does not handle function values, so this property is silently not decoded.',
545
+ headline: 'Property `{0}` is a function: `restoreFromJson` does not handle function values, so this property is silently not decoded.',
526
546
  severity: 'warning',
527
- detail: '`restoreFromJson` works on JSON-shaped data; functions don\'t survive JSON, so\nthe emitter drops them. The rest of the object\'s behaviour is unaffected.\n\nThis is by design see the "validate contract serializable data only"\nsection in CLAUDE.md. If you need a stricter checker that fails on\nmissing/extra function-typed members, watch the project roadmap.',
547
+ detail: '`restoreFromJson` works on JSON-shaped data; functions don\'t survive JSON, so\nthe emitter drops them. The rest of the object\'s behaviour is unaffected.\n\nThis is by design, see the "one contract: serializable data only"\nsection in CLAUDE.md. If you need a stricter checker that fails on\nmissing/extra function-typed members, watch the project roadmap.',
528
548
  },
529
549
  RJ011: {
530
- headline: "Method `{0}` is silently not decoded by `restoreFromJson` methods aren't data.",
550
+ headline: "Method `{0}` is silently not decoded by `restoreFromJson`: methods aren't data.",
531
551
  severity: 'warning',
532
552
  detail: "Class and object methods aren't part of the serialisable shape, so\n`restoreFromJson` excludes them. The rest of the type still works.\n\nIf you wanted the method's return value validated/serialised, expose it\nas a data property instead.",
533
553
  },
534
554
  RJ012: {
535
- headline: "Static member `{0}` is silently not decoded by `restoreFromJson` statics aren't part of instance data.",
555
+ headline: "Static member `{0}` is silently not decoded by `restoreFromJson`: statics aren't part of instance data.",
536
556
  severity: 'warning',
537
557
  detail: 'Class static members live on the class, not on individual instances.\n`restoreFromJson` operates on instance shape, so statics are excluded.',
538
558
  },
539
559
  RJ013: {
540
- headline: "Symbol-keyed property `{0}` is silently not decoded by `restoreFromJson` symbol keys aren't JSON-representable.",
560
+ headline: "Symbol-keyed property `{0}` is silently not decoded by `restoreFromJson`: symbol keys aren't JSON-representable.",
541
561
  severity: 'warning',
542
- detail: "JSON only supports string keys; symbol-keyed properties are dropped\nfrom the serialised form. `restoreFromJson` follows the same rule.\n\nFix use a string key:\n - [Symbol.for('id')]: string;\n+ id: string;",
562
+ detail: "JSON only supports string keys; symbol-keyed properties are dropped\nfrom the serialised form. `restoreFromJson` follows the same rule.\n\nFix: use a string key:\n - [Symbol.for('id')]: string;\n+ id: string;",
543
563
  },
544
564
  RJ014: {
545
- headline: "Union member(s) of type `{0}` can't be represented as data `restoreFromJson` drops them, so the union is decoded as its remaining members.",
565
+ headline: "Union member(s) of type `{0}` can't be represented as data: `restoreFromJson` drops them, so the union is decoded as its remaining members.",
546
566
  severity: 'warning',
547
- detail: 'A union projects to its serialisable members only: `DataOnly<Date | symbol>`\nis `Date`. The dropped member(s) ({0}) carry no JSON-shaped value (symbol,\nfunction, Promise, or a non-serialisable built-in like `Map` / `Set` /\ntyped arrays), so `restoreFromJson` decoded only the members that remain.\n\nThis is by design see the "validate contract serializable data only"\nsection in CLAUDE.md. If EVERY member of the union is non-serialisable the\nprojection is `never`, and `restoreFromJson` throws at build time instead.',
567
+ detail: 'A union projects to its serialisable members only: `DataOnly<Date | symbol>`\nis `Date`. The dropped member(s) ({0}) carry no JSON-shaped value (symbol,\nfunction, Promise, or a non-serialisable built-in like `Map` / `Set` /\ntyped arrays), so `restoreFromJson` decoded only the members that remain.\n\nThis is by design, see the "one contract: serializable data only"\nsection in CLAUDE.md. If EVERY member of the union is non-serialisable the\nprojection is `never`, and `restoreFromJson` throws at build time instead.',
548
568
  },
549
569
  RJ015: {
550
- headline: 'Property `{0}` has a non-serialisable value type (symbol, Promise, or a non-serialisable built-in) `restoreFromJson` drops it, so this property is silently not decoded.',
570
+ headline: 'Property `{0}` has a non-serialisable value type (symbol, Promise, or a non-serialisable built-in): `restoreFromJson` drops it, so this property is silently not decoded.',
551
571
  severity: 'warning',
552
- detail: '`restoreFromJson` works on JSON-shaped data. A property whose value is a symbol,\na Promise, or a non-serialisable built-in (typed array, ArrayBuffer, …) carries\nno JSON-shaped value, so it is dropped: `DataOnly<{ {0}: symbol }>` is `{}`.\nThe rest of the object\'s behaviour is unaffected.\n\nNote the difference from a property that is only STRUCTURALLY unserialisable —\n`{0}: symbol[]` or `{0}: Map<string, symbol>` which CANNOT be safely\ndropped (DataOnly keeps it as `never[]`): there `restoreFromJson` throws at build\ntime instead.\n\nThis is by design see the "validate contract serializable data only"\nsection in CLAUDE.md.',
572
+ detail: '`restoreFromJson` works on JSON-shaped data. A property whose value is a symbol,\na Promise, or a non-serialisable built-in (typed array, ArrayBuffer, …) carries\nno JSON-shaped value, so it is dropped: `DataOnly<{ {0}: symbol }>` is `{}`.\nThe rest of the object\'s behaviour is unaffected.\n\nNote the difference from a property that is only STRUCTURALLY unserialisable\n(`{0}: symbol[]` or `{0}: Map<string, symbol>`), which CANNOT be safely\ndropped (DataOnly keeps it as `never[]`): there `restoreFromJson` throws at build\ntime instead.\n\nThis is by design, see the "one contract: serializable data only"\nsection in CLAUDE.md.',
553
573
  },
554
574
  SJ001: {
555
- headline: 'Type `{0}` can never be stringified to JSON the generated function will always fail.',
575
+ headline: 'Type `{0}` can never be stringified to JSON: the generated function will always fail.',
556
576
  severity: 'error',
557
- detail: "`never` is the empty type no value can ever inhabit it. A field\ntyped `never` cannot carry a runtime value, so there is nothing to\nencode/decode/validate.\n\nFix use `unknown` if you really want to accept any value:\n interface User {\n- tag: never;\n+ tag: unknown; // narrow before use\n }\n\nFix pick a concrete type matching your real data:\n interface User {\n- tag: never;\n+ tag: 'pending' | 'active' | 'done';\n }",
577
+ detail: "`never` is the empty type: no value can ever inhabit it. A field\ntyped `never` cannot carry a runtime value, so there is nothing to\nencode/decode/validate.\n\nFix: use `unknown` if you really want to accept any value:\n interface User {\n- tag: never;\n+ tag: unknown; // narrow before use\n }\n\nFix: pick a concrete type matching your real data:\n interface User {\n- tag: never;\n+ tag: 'pending' | 'active' | 'done';\n }",
558
578
  },
559
579
  SJ002: {
560
- headline: 'Type `{0}` can never be stringified to JSON the generated function will always fail.',
580
+ headline: 'Type `{0}` can never be stringified to JSON: the generated function will always fail.',
561
581
  severity: 'error',
562
- detail: "Built-in classes like `Map`, `Set`, `WeakMap`, `WeakSet`, `Int8Array`,\n`Uint8Array`, `Buffer`, and `Promise` carry runtime state that doesn't\nsurvive a JSON or binary round-trip. Their instance identity is lost the\nmoment they're serialised.\n\nFix convert to a plain object/array before serialising:\n // for Map<K, V>:\n const data = Object.fromEntries(yourMap);\n // for Set<T>:\n const data = [...yourSet];\n // for typed arrays:\n const data = Array.from(yourBuffer);\n\nFix change the field type to a serialisable shape:\n interface User {\n- tags: Set<string>;\n+ tags: string[];\n }",
582
+ detail: "Built-in classes like `Map`, `Set`, `WeakMap`, `WeakSet`, `Int8Array`,\n`Uint8Array`, `Buffer`, and `Promise` carry runtime state that doesn't\nsurvive a JSON or binary round-trip. Their instance identity is lost the\nmoment they're serialised.\n\nFix: convert to a plain object/array before serialising:\n // for Map<K, V>:\n const data = Object.fromEntries(yourMap);\n // for Set<T>:\n const data = [...yourSet];\n // for typed arrays:\n const data = Array.from(yourBuffer);\n\nFix: change the field type to a serialisable shape:\n interface User {\n- tags: Set<string>;\n+ tags: string[];\n }",
563
583
  },
564
584
  SJ003: {
565
- headline: 'Type `{0}` can never be stringified to JSON the generated function will always fail.',
585
+ headline: 'Type `{0}` can never be stringified to JSON: the generated function will always fail.',
566
586
  severity: 'error',
567
- detail: "Functions have no value form to serialise their closure, prototype,\nand bound state aren't representable in JSON or binary.\n\nFix drop the function from your type, or replace it with the data the\nfunction would produce:\n interface User {\n- getName: () => string;\n+ name: string;\n }",
587
+ detail: "Functions have no value form to serialise: their closure, prototype,\nand bound state aren't representable in JSON or binary.\n\nFix: drop the function from your type, or replace it with the data the\nfunction would produce:\n interface User {\n- getName: () => string;\n+ name: string;\n }",
568
588
  },
569
589
  SJ004: {
570
- headline: 'Type `{0}` can never be stringified to JSON the generated function will always fail.',
590
+ headline: 'Type `{0}` can never be stringified to JSON: the generated function will always fail.',
571
591
  severity: 'error',
572
- detail: "Arrays of un-serialisable elements (`symbol[]`, `(() => void)[]`,\n`Map<K, V>[]`, etc.) can't be encoded every element would need to be\nrepresentable, and these aren't. Dropping individual elements would\nchange the array length, so the encoder refuses rather than silently\nshipping a different shape.\n\nFix change the element type to something serialisable:\n - type Items = (() => void)[];\n+ type Items = string[];",
592
+ detail: "Arrays of un-serialisable elements (`symbol[]`, `(() => void)[]`,\n`Map<K, V>[]`, etc.) can't be encoded: every element would need to be\nrepresentable, and these aren't. Dropping individual elements would\nchange the array length, so the encoder refuses rather than silently\nshipping a different shape.\n\nFix: change the element type to something serialisable:\n - type Items = (() => void)[];\n+ type Items = string[];",
573
593
  },
574
594
  SJ005: {
575
- headline: 'Type `{0}` can never be stringified to JSON the generated function will always fail.',
595
+ headline: 'Type `{0}` can never be stringified to JSON: the generated function will always fail.',
576
596
  severity: 'error',
577
- detail: "Every `symbol` value carries a unique runtime identity (`Symbol() !==\nSymbol()` even with the same description). That identity disappears the\nmoment it's serialised, and two symbols can't be compared across realms,\nworkers, or process boundaries. A validator that asserts \"this is a\nsymbol\" gives a false sense of safety the value can't actually\nround-trip.\n\nFix use a stable string key (often a literal union):\n - type Status = symbol;\n+ type Status = 'pending' | 'active' | 'done';",
597
+ detail: "Every `symbol` value carries a unique runtime identity (`Symbol() !==\nSymbol()` even with the same description). That identity disappears the\nmoment it's serialised, and two symbols can't be compared across realms,\nworkers, or process boundaries. A validator that asserts \"this is a\nsymbol\" gives a false sense of safety: the value can't actually\nround-trip.\n\nFix: use a stable string key (often a literal union):\n - type Status = symbol;\n+ type Status = 'pending' | 'active' | 'done';",
578
598
  },
579
599
  SJ010: {
580
- headline: 'Property `{0}` is a function `stringifyJson` does not handle function values, so this property is silently not stringified.',
600
+ headline: 'Property `{0}` is a function: `stringifyJson` does not handle function values, so this property is silently not stringified.',
581
601
  severity: 'warning',
582
- detail: '`stringifyJson` works on JSON-shaped data; functions don\'t survive JSON, so\nthe emitter drops them. The rest of the object\'s behaviour is unaffected.\n\nThis is by design see the "validate contract serializable data only"\nsection in CLAUDE.md. If you need a stricter checker that fails on\nmissing/extra function-typed members, watch the project roadmap.',
602
+ detail: '`stringifyJson` works on JSON-shaped data; functions don\'t survive JSON, so\nthe emitter drops them. The rest of the object\'s behaviour is unaffected.\n\nThis is by design, see the "one contract: serializable data only"\nsection in CLAUDE.md. If you need a stricter checker that fails on\nmissing/extra function-typed members, watch the project roadmap.',
583
603
  },
584
604
  SJ011: {
585
- headline: "Method `{0}` is silently not stringified by `stringifyJson` methods aren't data.",
605
+ headline: "Method `{0}` is silently not stringified by `stringifyJson`: methods aren't data.",
586
606
  severity: 'warning',
587
607
  detail: "Class and object methods aren't part of the serialisable shape, so\n`stringifyJson` excludes them. The rest of the type still works.\n\nIf you wanted the method's return value validated/serialised, expose it\nas a data property instead.",
588
608
  },
589
609
  SJ012: {
590
- headline: "Static member `{0}` is silently not stringified by `stringifyJson` statics aren't part of instance data.",
610
+ headline: "Static member `{0}` is silently not stringified by `stringifyJson`: statics aren't part of instance data.",
591
611
  severity: 'warning',
592
612
  detail: 'Class static members live on the class, not on individual instances.\n`stringifyJson` operates on instance shape, so statics are excluded.',
593
613
  },
594
614
  SJ013: {
595
- headline: "Symbol-keyed property `{0}` is silently not stringified by `stringifyJson` symbol keys aren't JSON-representable.",
615
+ headline: "Symbol-keyed property `{0}` is silently not stringified by `stringifyJson`: symbol keys aren't JSON-representable.",
596
616
  severity: 'warning',
597
- detail: "JSON only supports string keys; symbol-keyed properties are dropped\nfrom the serialised form. `stringifyJson` follows the same rule.\n\nFix use a string key:\n - [Symbol.for('id')]: string;\n+ id: string;",
617
+ detail: "JSON only supports string keys; symbol-keyed properties are dropped\nfrom the serialised form. `stringifyJson` follows the same rule.\n\nFix: use a string key:\n - [Symbol.for('id')]: string;\n+ id: string;",
598
618
  },
599
619
  SJ014: {
600
- headline: "Union member(s) of type `{0}` can't be represented as data `stringifyJson` drops them, so the union is stringified as its remaining members.",
620
+ headline: "Union member(s) of type `{0}` can't be represented as data: `stringifyJson` drops them, so the union is stringified as its remaining members.",
601
621
  severity: 'warning',
602
- detail: 'A union projects to its serialisable members only: `DataOnly<Date | symbol>`\nis `Date`. The dropped member(s) ({0}) carry no JSON-shaped value (symbol,\nfunction, Promise, or a non-serialisable built-in like `Map` / `Set` /\ntyped arrays), so `stringifyJson` stringified only the members that remain.\n\nThis is by design see the "validate contract serializable data only"\nsection in CLAUDE.md. If EVERY member of the union is non-serialisable the\nprojection is `never`, and `stringifyJson` throws at build time instead.',
622
+ detail: 'A union projects to its serialisable members only: `DataOnly<Date | symbol>`\nis `Date`. The dropped member(s) ({0}) carry no JSON-shaped value (symbol,\nfunction, Promise, or a non-serialisable built-in like `Map` / `Set` /\ntyped arrays), so `stringifyJson` stringified only the members that remain.\n\nThis is by design, see the "one contract: serializable data only"\nsection in CLAUDE.md. If EVERY member of the union is non-serialisable the\nprojection is `never`, and `stringifyJson` throws at build time instead.',
603
623
  },
604
624
  SJ015: {
605
- headline: 'Property `{0}` has a non-serialisable value type (symbol, Promise, or a non-serialisable built-in) `stringifyJson` drops it, so this property is silently not stringified.',
625
+ headline: 'Property `{0}` has a non-serialisable value type (symbol, Promise, or a non-serialisable built-in): `stringifyJson` drops it, so this property is silently not stringified.',
606
626
  severity: 'warning',
607
- detail: '`stringifyJson` works on JSON-shaped data. A property whose value is a symbol,\na Promise, or a non-serialisable built-in (typed array, ArrayBuffer, …) carries\nno JSON-shaped value, so it is dropped: `DataOnly<{ {0}: symbol }>` is `{}`.\nThe rest of the object\'s behaviour is unaffected.\n\nNote the difference from a property that is only STRUCTURALLY unserialisable —\n`{0}: symbol[]` or `{0}: Map<string, symbol>` which CANNOT be safely\ndropped (DataOnly keeps it as `never[]`): there `stringifyJson` throws at build\ntime instead.\n\nThis is by design see the "validate contract serializable data only"\nsection in CLAUDE.md.',
627
+ detail: '`stringifyJson` works on JSON-shaped data. A property whose value is a symbol,\na Promise, or a non-serialisable built-in (typed array, ArrayBuffer, …) carries\nno JSON-shaped value, so it is dropped: `DataOnly<{ {0}: symbol }>` is `{}`.\nThe rest of the object\'s behaviour is unaffected.\n\nNote the difference from a property that is only STRUCTURALLY unserialisable\n(`{0}: symbol[]` or `{0}: Map<string, symbol>`), which CANNOT be safely\ndropped (DataOnly keeps it as `never[]`): there `stringifyJson` throws at build\ntime instead.\n\nThis is by design, see the "one contract: serializable data only"\nsection in CLAUDE.md.',
608
628
  },
609
629
  TB001: {
610
- headline: 'Type `{0}` can never be serialised to binary the generated function will always fail.',
630
+ headline: 'Type `{0}` can never be serialised to binary: the generated function will always fail.',
611
631
  severity: 'error',
612
- detail: "`never` is the empty type no value can ever inhabit it. A field\ntyped `never` cannot carry a runtime value, so there is nothing to\nencode/decode/validate.\n\nFix use `unknown` if you really want to accept any value:\n interface User {\n- tag: never;\n+ tag: unknown; // narrow before use\n }\n\nFix pick a concrete type matching your real data:\n interface User {\n- tag: never;\n+ tag: 'pending' | 'active' | 'done';\n }",
632
+ detail: "`never` is the empty type: no value can ever inhabit it. A field\ntyped `never` cannot carry a runtime value, so there is nothing to\nencode/decode/validate.\n\nFix: use `unknown` if you really want to accept any value:\n interface User {\n- tag: never;\n+ tag: unknown; // narrow before use\n }\n\nFix: pick a concrete type matching your real data:\n interface User {\n- tag: never;\n+ tag: 'pending' | 'active' | 'done';\n }",
613
633
  },
614
634
  TB002: {
615
- headline: 'Type `{0}` can never be serialised to binary the generated function will always fail.',
635
+ headline: 'Type `{0}` can never be serialised to binary: the generated function will always fail.',
616
636
  severity: 'error',
617
- detail: "Built-in classes like `Map`, `Set`, `WeakMap`, `WeakSet`, `Int8Array`,\n`Uint8Array`, `Buffer`, and `Promise` carry runtime state that doesn't\nsurvive a JSON or binary round-trip. Their instance identity is lost the\nmoment they're serialised.\n\nFix convert to a plain object/array before serialising:\n // for Map<K, V>:\n const data = Object.fromEntries(yourMap);\n // for Set<T>:\n const data = [...yourSet];\n // for typed arrays:\n const data = Array.from(yourBuffer);\n\nFix change the field type to a serialisable shape:\n interface User {\n- tags: Set<string>;\n+ tags: string[];\n }",
637
+ detail: "Built-in classes like `Map`, `Set`, `WeakMap`, `WeakSet`, `Int8Array`,\n`Uint8Array`, `Buffer`, and `Promise` carry runtime state that doesn't\nsurvive a JSON or binary round-trip. Their instance identity is lost the\nmoment they're serialised.\n\nFix: convert to a plain object/array before serialising:\n // for Map<K, V>:\n const data = Object.fromEntries(yourMap);\n // for Set<T>:\n const data = [...yourSet];\n // for typed arrays:\n const data = Array.from(yourBuffer);\n\nFix: change the field type to a serialisable shape:\n interface User {\n- tags: Set<string>;\n+ tags: string[];\n }",
618
638
  },
619
639
  TB003: {
620
- headline: 'Type `{0}` can never be serialised to binary the generated function will always fail.',
640
+ headline: 'Type `{0}` can never be serialised to binary: the generated function will always fail.',
621
641
  severity: 'error',
622
- detail: "Functions have no value form to serialise their closure, prototype,\nand bound state aren't representable in JSON or binary.\n\nFix drop the function from your type, or replace it with the data the\nfunction would produce:\n interface User {\n- getName: () => string;\n+ name: string;\n }",
642
+ detail: "Functions have no value form to serialise: their closure, prototype,\nand bound state aren't representable in JSON or binary.\n\nFix: drop the function from your type, or replace it with the data the\nfunction would produce:\n interface User {\n- getName: () => string;\n+ name: string;\n }",
623
643
  },
624
644
  TB004: {
625
- headline: 'Type `{0}` can never be serialised to binary the generated function will always fail.',
645
+ headline: 'Type `{0}` can never be serialised to binary: the generated function will always fail.',
626
646
  severity: 'error',
627
- detail: "Arrays of un-serialisable elements (`symbol[]`, `(() => void)[]`,\n`Map<K, V>[]`, etc.) can't be encoded every element would need to be\nrepresentable, and these aren't. Dropping individual elements would\nchange the array length, so the encoder refuses rather than silently\nshipping a different shape.\n\nFix change the element type to something serialisable:\n - type Items = (() => void)[];\n+ type Items = string[];",
647
+ detail: "Arrays of un-serialisable elements (`symbol[]`, `(() => void)[]`,\n`Map<K, V>[]`, etc.) can't be encoded: every element would need to be\nrepresentable, and these aren't. Dropping individual elements would\nchange the array length, so the encoder refuses rather than silently\nshipping a different shape.\n\nFix: change the element type to something serialisable:\n - type Items = (() => void)[];\n+ type Items = string[];",
628
648
  },
629
649
  TB005: {
630
- headline: 'Type `{0}` can never be serialised to binary the generated function will always fail.',
650
+ headline: 'Type `{0}` can never be serialised to binary: the generated function will always fail.',
631
651
  severity: 'error',
632
- detail: "Built-in classes like `Map`, `Set`, `WeakMap`, `WeakSet`, `Int8Array`,\n`Uint8Array`, `Buffer`, and `Promise` carry runtime state that doesn't\nsurvive a JSON or binary round-trip. Their instance identity is lost the\nmoment they're serialised.\n\nFix convert to a plain object/array before serialising:\n // for Map<K, V>:\n const data = Object.fromEntries(yourMap);\n // for Set<T>:\n const data = [...yourSet];\n // for typed arrays:\n const data = Array.from(yourBuffer);\n\nFix change the field type to a serialisable shape:\n interface User {\n- tags: Set<string>;\n+ tags: string[];\n }",
652
+ detail: "Built-in classes like `Map`, `Set`, `WeakMap`, `WeakSet`, `Int8Array`,\n`Uint8Array`, `Buffer`, and `Promise` carry runtime state that doesn't\nsurvive a JSON or binary round-trip. Their instance identity is lost the\nmoment they're serialised.\n\nFix: convert to a plain object/array before serialising:\n // for Map<K, V>:\n const data = Object.fromEntries(yourMap);\n // for Set<T>:\n const data = [...yourSet];\n // for typed arrays:\n const data = Array.from(yourBuffer);\n\nFix: change the field type to a serialisable shape:\n interface User {\n- tags: Set<string>;\n+ tags: string[];\n }",
633
653
  },
634
654
  TB006: {
635
- headline: 'Type `{0}` can never be serialised to binary the generated function will always fail.',
655
+ headline: 'Type `{0}` can never be serialised to binary: the generated function will always fail.',
636
656
  severity: 'error',
637
- detail: "Every `symbol` value carries a unique runtime identity (`Symbol() !==\nSymbol()` even with the same description). That identity disappears the\nmoment it's serialised, and two symbols can't be compared across realms,\nworkers, or process boundaries. A validator that asserts \"this is a\nsymbol\" gives a false sense of safety the value can't actually\nround-trip.\n\nFix use a stable string key (often a literal union):\n - type Status = symbol;\n+ type Status = 'pending' | 'active' | 'done';",
657
+ detail: "Every `symbol` value carries a unique runtime identity (`Symbol() !==\nSymbol()` even with the same description). That identity disappears the\nmoment it's serialised, and two symbols can't be compared across realms,\nworkers, or process boundaries. A validator that asserts \"this is a\nsymbol\" gives a false sense of safety: the value can't actually\nround-trip.\n\nFix: use a stable string key (often a literal union):\n - type Status = symbol;\n+ type Status = 'pending' | 'active' | 'done';",
638
658
  },
639
659
  TB010: {
640
- headline: 'Property `{0}` is a function `toBinary` does not handle function values, so this property is silently not serialised.',
660
+ headline: 'Property `{0}` is a function: `toBinary` does not handle function values, so this property is silently not serialised.',
641
661
  severity: 'warning',
642
- detail: '`toBinary` works on JSON-shaped data; functions don\'t survive JSON, so\nthe emitter drops them. The rest of the object\'s behaviour is unaffected.\n\nThis is by design see the "validate contract serializable data only"\nsection in CLAUDE.md. If you need a stricter checker that fails on\nmissing/extra function-typed members, watch the project roadmap.',
662
+ detail: '`toBinary` works on JSON-shaped data; functions don\'t survive JSON, so\nthe emitter drops them. The rest of the object\'s behaviour is unaffected.\n\nThis is by design, see the "one contract: serializable data only"\nsection in CLAUDE.md. If you need a stricter checker that fails on\nmissing/extra function-typed members, watch the project roadmap.',
643
663
  },
644
664
  TB011: {
645
- headline: "Method `{0}` is silently not serialised by `toBinary` methods aren't data.",
665
+ headline: "Method `{0}` is silently not serialised by `toBinary`: methods aren't data.",
646
666
  severity: 'warning',
647
667
  detail: "Class and object methods aren't part of the serialisable shape, so\n`toBinary` excludes them. The rest of the type still works.\n\nIf you wanted the method's return value validated/serialised, expose it\nas a data property instead.",
648
668
  },
649
669
  TB012: {
650
- headline: "Static member `{0}` is silently not serialised by `toBinary` statics aren't part of instance data.",
670
+ headline: "Static member `{0}` is silently not serialised by `toBinary`: statics aren't part of instance data.",
651
671
  severity: 'warning',
652
672
  detail: 'Class static members live on the class, not on individual instances.\n`toBinary` operates on instance shape, so statics are excluded.',
653
673
  },
654
674
  TB013: {
655
- headline: "Symbol-keyed property `{0}` is silently not serialised by `toBinary` symbol keys aren't JSON-representable.",
675
+ headline: "Symbol-keyed property `{0}` is silently not serialised by `toBinary`: symbol keys aren't JSON-representable.",
656
676
  severity: 'warning',
657
- detail: "JSON only supports string keys; symbol-keyed properties are dropped\nfrom the serialised form. `toBinary` follows the same rule.\n\nFix use a string key:\n - [Symbol.for('id')]: string;\n+ id: string;",
677
+ detail: "JSON only supports string keys; symbol-keyed properties are dropped\nfrom the serialised form. `toBinary` follows the same rule.\n\nFix: use a string key:\n - [Symbol.for('id')]: string;\n+ id: string;",
658
678
  },
659
679
  TB014: {
660
- headline: "Union member(s) of type `{0}` can't be represented as data `toBinary` drops them, so the union is serialised as its remaining members.",
680
+ headline: "Union member(s) of type `{0}` can't be represented as data: `toBinary` drops them, so the union is serialised as its remaining members.",
661
681
  severity: 'warning',
662
- detail: 'A union projects to its serialisable members only: `DataOnly<Date | symbol>`\nis `Date`. The dropped member(s) ({0}) carry no JSON-shaped value (symbol,\nfunction, Promise, or a non-serialisable built-in like `Map` / `Set` /\ntyped arrays), so `toBinary` serialised only the members that remain.\n\nThis is by design see the "validate contract serializable data only"\nsection in CLAUDE.md. If EVERY member of the union is non-serialisable the\nprojection is `never`, and `toBinary` throws at build time instead.',
682
+ detail: 'A union projects to its serialisable members only: `DataOnly<Date | symbol>`\nis `Date`. The dropped member(s) ({0}) carry no JSON-shaped value (symbol,\nfunction, Promise, or a non-serialisable built-in like `Map` / `Set` /\ntyped arrays), so `toBinary` serialised only the members that remain.\n\nThis is by design, see the "one contract: serializable data only"\nsection in CLAUDE.md. If EVERY member of the union is non-serialisable the\nprojection is `never`, and `toBinary` throws at build time instead.',
663
683
  },
664
684
  TB015: {
665
- headline: 'Property `{0}` has a non-serialisable value type (symbol, Promise, or a non-serialisable built-in) `toBinary` drops it, so this property is silently not serialised.',
685
+ headline: 'Property `{0}` has a non-serialisable value type (symbol, Promise, or a non-serialisable built-in): `toBinary` drops it, so this property is silently not serialised.',
666
686
  severity: 'warning',
667
- detail: '`toBinary` works on JSON-shaped data. A property whose value is a symbol,\na Promise, or a non-serialisable built-in (typed array, ArrayBuffer, …) carries\nno JSON-shaped value, so it is dropped: `DataOnly<{ {0}: symbol }>` is `{}`.\nThe rest of the object\'s behaviour is unaffected.\n\nNote the difference from a property that is only STRUCTURALLY unserialisable —\n`{0}: symbol[]` or `{0}: Map<string, symbol>` which CANNOT be safely\ndropped (DataOnly keeps it as `never[]`): there `toBinary` throws at build\ntime instead.\n\nThis is by design see the "validate contract serializable data only"\nsection in CLAUDE.md.',
687
+ detail: '`toBinary` works on JSON-shaped data. A property whose value is a symbol,\na Promise, or a non-serialisable built-in (typed array, ArrayBuffer, …) carries\nno JSON-shaped value, so it is dropped: `DataOnly<{ {0}: symbol }>` is `{}`.\nThe rest of the object\'s behaviour is unaffected.\n\nNote the difference from a property that is only STRUCTURALLY unserialisable\n(`{0}: symbol[]` or `{0}: Map<string, symbol>`), which CANNOT be safely\ndropped (DataOnly keeps it as `never[]`): there `toBinary` throws at build\ntime instead.\n\nThis is by design, see the "one contract: serializable data only"\nsection in CLAUDE.md.',
668
688
  },
669
689
  TMP001: {
670
- headline: "Temporal type `{0}` resolved to `any` the Temporal lib isn't in your tsconfig `lib`, so the generated validator would accept any value.",
690
+ headline: "Temporal type `{0}` resolved to `any`: the Temporal lib isn't in your tsconfig `lib`, so the generated validator would accept any value.",
671
691
  severity: 'error',
672
- detail: 'ts-runtypes reads types through TypeScript\'s lib definitions, so it\ncan only validate `Temporal.*` types when the Temporal namespace is loaded.\nWith the lib missing, `{0}` silently degrades to `any` and the validator\nbecomes a no-op that accepts everything almost never what you intended.\n\nFix add "ESNext.Temporal" to your tsconfig:\n {\n "compilerOptions": {\n "lib": ["ES2023", "ESNext.Temporal"]\n }\n }',
692
+ detail: 'ts-runtypes reads types through TypeScript\'s lib definitions, so it\ncan only validate `Temporal.*` types when the Temporal namespace is loaded.\nWith the lib missing, `{0}` silently degrades to `any` and the validator\nbecomes a no-op that accepts everything, almost never what you intended.\n\nFix: add "ESNext.Temporal" to your tsconfig:\n {\n "compilerOptions": {\n "lib": ["ES2023", "ESNext.Temporal"]\n }\n }',
673
693
  },
674
694
  UKE010: {
675
- headline: 'Property `{0}` is a function `unknownKeyErrors` does not handle function values, so this property is silently not checked.',
695
+ headline: 'Property `{0}` is a function: `unknownKeyErrors` does not handle function values, so this property is silently not checked.',
676
696
  severity: 'warning',
677
- detail: '`unknownKeyErrors` works on JSON-shaped data; functions don\'t survive JSON, so\nthe emitter drops them. The rest of the object\'s behaviour is unaffected.\n\nThis is by design see the "validate contract serializable data only"\nsection in CLAUDE.md. If you need a stricter checker that fails on\nmissing/extra function-typed members, watch the project roadmap.',
697
+ detail: '`unknownKeyErrors` works on JSON-shaped data; functions don\'t survive JSON, so\nthe emitter drops them. The rest of the object\'s behaviour is unaffected.\n\nThis is by design, see the "one contract: serializable data only"\nsection in CLAUDE.md. If you need a stricter checker that fails on\nmissing/extra function-typed members, watch the project roadmap.',
678
698
  },
679
699
  UKU010: {
680
- headline: 'Property `{0}` is a function `unknownKeysToUndefined` does not handle function values, so this property is silently not cleared.',
700
+ headline: 'Property `{0}` is a function: `unknownKeysToUndefined` does not handle function values, so this property is silently not cleared.',
681
701
  severity: 'warning',
682
- detail: '`unknownKeysToUndefined` works on JSON-shaped data; functions don\'t survive JSON, so\nthe emitter drops them. The rest of the object\'s behaviour is unaffected.\n\nThis is by design see the "validate contract serializable data only"\nsection in CLAUDE.md. If you need a stricter checker that fails on\nmissing/extra function-typed members, watch the project roadmap.',
702
+ detail: '`unknownKeysToUndefined` works on JSON-shaped data; functions don\'t survive JSON, so\nthe emitter drops them. The rest of the object\'s behaviour is unaffected.\n\nThis is by design, see the "one contract: serializable data only"\nsection in CLAUDE.md. If you need a stricter checker that fails on\nmissing/extra function-typed members, watch the project roadmap.',
683
703
  },
684
704
  UKW010: {
685
- headline: 'Property `{0}` is a function `unknownKeysToUndefinedWire` does not handle function values, so this property is silently not cleared.',
705
+ headline: 'Property `{0}` is a function: `unknownKeysToUndefinedWire` does not handle function values, so this property is silently not cleared.',
686
706
  severity: 'warning',
687
- detail: '`unknownKeysToUndefinedWire` works on JSON-shaped data; functions don\'t survive JSON, so\nthe emitter drops them. The rest of the object\'s behaviour is unaffected.\n\nThis is by design see the "validate contract serializable data only"\nsection in CLAUDE.md. If you need a stricter checker that fails on\nmissing/extra function-typed members, watch the project roadmap.',
707
+ detail: '`unknownKeysToUndefinedWire` works on JSON-shaped data; functions don\'t survive JSON, so\nthe emitter drops them. The rest of the object\'s behaviour is unaffected.\n\nThis is by design, see the "one contract: serializable data only"\nsection in CLAUDE.md. If you need a stricter checker that fails on\nmissing/extra function-typed members, watch the project roadmap.',
688
708
  },
689
709
  VE001: {
690
- headline: 'Type `{0}` can never be validated the generated function will always fail.',
710
+ headline: 'Type `{0}` can never be validated: the generated function will always fail.',
691
711
  severity: 'error',
692
- detail: "Built-in classes like `Map`, `Set`, `WeakMap`, `WeakSet`, `Int8Array`,\n`Uint8Array`, `Buffer`, and `Promise` carry runtime state that doesn't\nsurvive a JSON or binary round-trip. Their instance identity is lost the\nmoment they're serialised.\n\nFix convert to a plain object/array before serialising:\n // for Map<K, V>:\n const data = Object.fromEntries(yourMap);\n // for Set<T>:\n const data = [...yourSet];\n // for typed arrays:\n const data = Array.from(yourBuffer);\n\nFix change the field type to a serialisable shape:\n interface User {\n- tags: Set<string>;\n+ tags: string[];\n }",
712
+ detail: "Built-in classes like `Map`, `Set`, `WeakMap`, `WeakSet`, `Int8Array`,\n`Uint8Array`, `Buffer`, and `Promise` carry runtime state that doesn't\nsurvive a JSON or binary round-trip. Their instance identity is lost the\nmoment they're serialised.\n\nFix: convert to a plain object/array before serialising:\n // for Map<K, V>:\n const data = Object.fromEntries(yourMap);\n // for Set<T>:\n const data = [...yourSet];\n // for typed arrays:\n const data = Array.from(yourBuffer);\n\nFix: change the field type to a serialisable shape:\n interface User {\n- tags: Set<string>;\n+ tags: string[];\n }",
693
713
  },
694
714
  VE002: {
695
- headline: 'Type `{0}` can never be validated the generated function will always fail.',
715
+ headline: 'Type `{0}` can never be validated: the generated function will always fail.',
696
716
  severity: 'error',
697
- detail: "Every `symbol` value carries a unique runtime identity (`Symbol() !==\nSymbol()` even with the same description). That identity disappears the\nmoment it's serialised, and two symbols can't be compared across realms,\nworkers, or process boundaries. A validator that asserts \"this is a\nsymbol\" gives a false sense of safety the value can't actually\nround-trip.\n\nFix use a stable string key (often a literal union):\n - type Status = symbol;\n+ type Status = 'pending' | 'active' | 'done';",
717
+ detail: "Every `symbol` value carries a unique runtime identity (`Symbol() !==\nSymbol()` even with the same description). That identity disappears the\nmoment it's serialised, and two symbols can't be compared across realms,\nworkers, or process boundaries. A validator that asserts \"this is a\nsymbol\" gives a false sense of safety: the value can't actually\nround-trip.\n\nFix: use a stable string key (often a literal union):\n - type Status = symbol;\n+ type Status = 'pending' | 'active' | 'done';",
698
718
  },
699
719
  VE010: {
700
- headline: 'Property `{0}` is a function `validationErrors` does not handle function values, so this property is silently not checked.',
720
+ headline: 'Property `{0}` is a function: `validationErrors` does not handle function values, so this property is silently not checked.',
701
721
  severity: 'warning',
702
- detail: '`validationErrors` works on JSON-shaped data; functions don\'t survive JSON, so\nthe emitter drops them. The rest of the object\'s behaviour is unaffected.\n\nThis is by design see the "validate contract serializable data only"\nsection in CLAUDE.md. If you need a stricter checker that fails on\nmissing/extra function-typed members, watch the project roadmap.',
722
+ detail: '`validationErrors` works on JSON-shaped data; functions don\'t survive JSON, so\nthe emitter drops them. The rest of the object\'s behaviour is unaffected.\n\nThis is by design, see the "one contract: serializable data only"\nsection in CLAUDE.md. If you need a stricter checker that fails on\nmissing/extra function-typed members, watch the project roadmap.',
703
723
  },
704
724
  VE011: {
705
- headline: "Method `{0}` is silently not checked by `validationErrors` methods aren't data.",
725
+ headline: "Method `{0}` is silently not checked by `validationErrors`: methods aren't data.",
706
726
  severity: 'warning',
707
727
  detail: "Class and object methods aren't part of the serialisable shape, so\n`validationErrors` excludes them. The rest of the type still works.\n\nIf you wanted the method's return value validated/serialised, expose it\nas a data property instead.",
708
728
  },
709
729
  VE012: {
710
- headline: "Static member `{0}` is silently not checked by `validationErrors` statics aren't part of instance data.",
730
+ headline: "Static member `{0}` is silently not checked by `validationErrors`: statics aren't part of instance data.",
711
731
  severity: 'warning',
712
732
  detail: 'Class static members live on the class, not on individual instances.\n`validationErrors` operates on instance shape, so statics are excluded.',
713
733
  },
714
734
  VE013: {
715
- headline: "Symbol-keyed property `{0}` is silently not checked by `validationErrors` symbol keys aren't JSON-representable.",
735
+ headline: "Symbol-keyed property `{0}` is silently not checked by `validationErrors`: symbol keys aren't JSON-representable.",
716
736
  severity: 'warning',
717
- detail: "JSON only supports string keys; symbol-keyed properties are dropped\nfrom the serialised form. `validationErrors` follows the same rule.\n\nFix use a string key:\n - [Symbol.for('id')]: string;\n+ id: string;",
737
+ detail: "JSON only supports string keys; symbol-keyed properties are dropped\nfrom the serialised form. `validationErrors` follows the same rule.\n\nFix: use a string key:\n - [Symbol.for('id')]: string;\n+ id: string;",
718
738
  },
719
739
  VE015: {
720
- headline: 'Property `{0}` has a non-serialisable value type (symbol, Promise, or a non-serialisable built-in) `validationErrors` drops it, so this property is silently not checked.',
740
+ headline: 'Property `{0}` has a non-serialisable value type (symbol, Promise, or a non-serialisable built-in): `validationErrors` drops it, so this property is silently not checked.',
721
741
  severity: 'warning',
722
- detail: '`validationErrors` works on JSON-shaped data. A property whose value is a symbol,\na Promise, or a non-serialisable built-in (typed array, ArrayBuffer, …) carries\nno JSON-shaped value, so it is dropped: `DataOnly<{ {0}: symbol }>` is `{}`.\nThe rest of the object\'s behaviour is unaffected.\n\nNote the difference from a property that is only STRUCTURALLY unserialisable —\n`{0}: symbol[]` or `{0}: Map<string, symbol>` which CANNOT be safely\ndropped (DataOnly keeps it as `never[]`): there `validationErrors` throws at build\ntime instead.\n\nThis is by design see the "validate contract serializable data only"\nsection in CLAUDE.md.',
742
+ detail: '`validationErrors` works on JSON-shaped data. A property whose value is a symbol,\na Promise, or a non-serialisable built-in (typed array, ArrayBuffer, …) carries\nno JSON-shaped value, so it is dropped: `DataOnly<{ {0}: symbol }>` is `{}`.\nThe rest of the object\'s behaviour is unaffected.\n\nNote the difference from a property that is only STRUCTURALLY unserialisable\n(`{0}: symbol[]` or `{0}: Map<string, symbol>`), which CANNOT be safely\ndropped (DataOnly keeps it as `never[]`): there `validationErrors` throws at build\ntime instead.\n\nThis is by design, see the "one contract: serializable data only"\nsection in CLAUDE.md.',
723
743
  },
724
744
  VE020: {
725
- headline: '`validationErrors` on `any` / `unknown` always returns an empty error array nothing is checked.',
745
+ headline: '`validationErrors` on `any` / `unknown` always returns an empty error array: nothing is checked.',
726
746
  severity: 'warning',
727
- detail: 'Same reason as VL021: `any` and `unknown` describe "anything", so the\nchecker has no structure to compare against. The returned error array\nwill always be empty.\n\nFix narrow the type to the actual shape you expect:\n - const errors = createGetValidationErrorsFn<unknown>()(value);\n+ const errors = createGetValidationErrorsFn<User>()(value);',
747
+ detail: 'Same reason as VL021: `any` and `unknown` describe "anything", so the\nchecker has no structure to compare against. The returned error array\nwill always be empty.\n\nFix: narrow the type to the actual shape you expect:\n - const errors = createGetValidationErrorsFn<unknown>()(value);\n+ const errors = createGetValidationErrorsFn<User>()(value);',
728
748
  },
729
749
  VL001: {
730
- headline: 'Type `{0}` can never be validated the generated function will always fail.',
750
+ headline: 'Type `{0}` can never be validated: the generated function will always fail.',
731
751
  severity: 'error',
732
- detail: "Built-in classes like `Map`, `Set`, `WeakMap`, `WeakSet`, `Int8Array`,\n`Uint8Array`, `Buffer`, and `Promise` carry runtime state that doesn't\nsurvive a JSON or binary round-trip. Their instance identity is lost the\nmoment they're serialised.\n\nFix convert to a plain object/array before serialising:\n // for Map<K, V>:\n const data = Object.fromEntries(yourMap);\n // for Set<T>:\n const data = [...yourSet];\n // for typed arrays:\n const data = Array.from(yourBuffer);\n\nFix change the field type to a serialisable shape:\n interface User {\n- tags: Set<string>;\n+ tags: string[];\n }",
752
+ detail: "Built-in classes like `Map`, `Set`, `WeakMap`, `WeakSet`, `Int8Array`,\n`Uint8Array`, `Buffer`, and `Promise` carry runtime state that doesn't\nsurvive a JSON or binary round-trip. Their instance identity is lost the\nmoment they're serialised.\n\nFix: convert to a plain object/array before serialising:\n // for Map<K, V>:\n const data = Object.fromEntries(yourMap);\n // for Set<T>:\n const data = [...yourSet];\n // for typed arrays:\n const data = Array.from(yourBuffer);\n\nFix: change the field type to a serialisable shape:\n interface User {\n- tags: Set<string>;\n+ tags: string[];\n }",
733
753
  },
734
754
  VL002: {
735
- headline: 'Type `{0}` can never be validated the generated function will always fail.',
755
+ headline: 'Type `{0}` can never be validated: the generated function will always fail.',
736
756
  severity: 'error',
737
- detail: "Every `symbol` value carries a unique runtime identity (`Symbol() !==\nSymbol()` even with the same description). That identity disappears the\nmoment it's serialised, and two symbols can't be compared across realms,\nworkers, or process boundaries. A validator that asserts \"this is a\nsymbol\" gives a false sense of safety the value can't actually\nround-trip.\n\nFix use a stable string key (often a literal union):\n - type Status = symbol;\n+ type Status = 'pending' | 'active' | 'done';",
757
+ detail: "Every `symbol` value carries a unique runtime identity (`Symbol() !==\nSymbol()` even with the same description). That identity disappears the\nmoment it's serialised, and two symbols can't be compared across realms,\nworkers, or process boundaries. A validator that asserts \"this is a\nsymbol\" gives a false sense of safety: the value can't actually\nround-trip.\n\nFix: use a stable string key (often a literal union):\n - type Status = symbol;\n+ type Status = 'pending' | 'active' | 'done';",
738
758
  },
739
759
  VL010: {
740
- headline: 'Property `{0}` is a function `validate` does not handle function values, so this property is silently not validated.',
760
+ headline: 'Property `{0}` is a function: `validate` does not handle function values, so this property is silently not validated.',
741
761
  severity: 'warning',
742
- detail: '`validate` works on JSON-shaped data; functions don\'t survive JSON, so\nthe emitter drops them. The rest of the object\'s behaviour is unaffected.\n\nThis is by design see the "validate contract serializable data only"\nsection in CLAUDE.md. If you need a stricter checker that fails on\nmissing/extra function-typed members, watch the project roadmap.',
762
+ detail: '`validate` works on JSON-shaped data; functions don\'t survive JSON, so\nthe emitter drops them. The rest of the object\'s behaviour is unaffected.\n\nThis is by design, see the "one contract: serializable data only"\nsection in CLAUDE.md. If you need a stricter checker that fails on\nmissing/extra function-typed members, watch the project roadmap.',
743
763
  },
744
764
  VL011: {
745
- headline: "Method `{0}` is silently not validated by `validate` methods aren't data.",
765
+ headline: "Method `{0}` is silently not validated by `validate`: methods aren't data.",
746
766
  severity: 'warning',
747
767
  detail: "Class and object methods aren't part of the serialisable shape, so\n`validate` excludes them. The rest of the type still works.\n\nIf you wanted the method's return value validated/serialised, expose it\nas a data property instead.",
748
768
  },
749
769
  VL012: {
750
- headline: "Static member `{0}` is silently not validated by `validate` statics aren't part of instance data.",
770
+ headline: "Static member `{0}` is silently not validated by `validate`: statics aren't part of instance data.",
751
771
  severity: 'warning',
752
772
  detail: 'Class static members live on the class, not on individual instances.\n`validate` operates on instance shape, so statics are excluded.',
753
773
  },
754
774
  VL013: {
755
- headline: "Symbol-keyed property `{0}` is silently not validated by `validate` symbol keys aren't JSON-representable.",
775
+ headline: "Symbol-keyed property `{0}` is silently not validated by `validate`: symbol keys aren't JSON-representable.",
756
776
  severity: 'warning',
757
- detail: "JSON only supports string keys; symbol-keyed properties are dropped\nfrom the serialised form. `validate` follows the same rule.\n\nFix use a string key:\n - [Symbol.for('id')]: string;\n+ id: string;",
777
+ detail: "JSON only supports string keys; symbol-keyed properties are dropped\nfrom the serialised form. `validate` follows the same rule.\n\nFix: use a string key:\n - [Symbol.for('id')]: string;\n+ id: string;",
758
778
  },
759
779
  VL014: {
760
- headline: "Union member(s) of type `{0}` can't be represented as data `validate` drops them, so the union is validated as its remaining members.",
780
+ headline: "Union member(s) of type `{0}` can't be represented as data: `validate` drops them, so the union is validated as its remaining members.",
761
781
  severity: 'warning',
762
- detail: 'A union projects to its serialisable members only: `DataOnly<Date | symbol>`\nis `Date`. The dropped member(s) ({0}) carry no JSON-shaped value (symbol,\nfunction, Promise, or a non-serialisable built-in like `Map` / `Set` /\ntyped arrays), so `validate` validated only the members that remain.\n\nThis is by design see the "validate contract serializable data only"\nsection in CLAUDE.md. If EVERY member of the union is non-serialisable the\nprojection is `never`, and `validate` throws at build time instead.',
782
+ detail: 'A union projects to its serialisable members only: `DataOnly<Date | symbol>`\nis `Date`. The dropped member(s) ({0}) carry no JSON-shaped value (symbol,\nfunction, Promise, or a non-serialisable built-in like `Map` / `Set` /\ntyped arrays), so `validate` validated only the members that remain.\n\nThis is by design, see the "one contract: serializable data only"\nsection in CLAUDE.md. If EVERY member of the union is non-serialisable the\nprojection is `never`, and `validate` throws at build time instead.',
763
783
  },
764
784
  VL015: {
765
- headline: 'Property `{0}` has a non-serialisable value type (symbol, Promise, or a non-serialisable built-in) `validate` drops it, so this property is silently not validated.',
785
+ headline: 'Property `{0}` has a non-serialisable value type (symbol, Promise, or a non-serialisable built-in): `validate` drops it, so this property is silently not validated.',
766
786
  severity: 'warning',
767
- detail: '`validate` works on JSON-shaped data. A property whose value is a symbol,\na Promise, or a non-serialisable built-in (typed array, ArrayBuffer, …) carries\nno JSON-shaped value, so it is dropped: `DataOnly<{ {0}: symbol }>` is `{}`.\nThe rest of the object\'s behaviour is unaffected.\n\nNote the difference from a property that is only STRUCTURALLY unserialisable —\n`{0}: symbol[]` or `{0}: Map<string, symbol>` which CANNOT be safely\ndropped (DataOnly keeps it as `never[]`): there `validate` throws at build\ntime instead.\n\nThis is by design see the "validate contract serializable data only"\nsection in CLAUDE.md.',
787
+ detail: '`validate` works on JSON-shaped data. A property whose value is a symbol,\na Promise, or a non-serialisable built-in (typed array, ArrayBuffer, …) carries\nno JSON-shaped value, so it is dropped: `DataOnly<{ {0}: symbol }>` is `{}`.\nThe rest of the object\'s behaviour is unaffected.\n\nNote the difference from a property that is only STRUCTURALLY unserialisable\n(`{0}: symbol[]` or `{0}: Map<string, symbol>`), which CANNOT be safely\ndropped (DataOnly keeps it as `never[]`): there `validate` throws at build\ntime instead.\n\nThis is by design, see the "one contract: serializable data only"\nsection in CLAUDE.md.',
768
788
  },
769
789
  VL021: {
770
- headline: '`validate` on `any` / `unknown` always returns true the validator accepts every value.',
790
+ headline: '`validate` on `any` / `unknown` always returns true: the validator accepts every value.',
771
791
  severity: 'warning',
772
- detail: '`any` and `unknown` describe "anything", so a structural validator has\nnothing to check. The resulting function passes for every input —\nincluding the ones you probably wanted to reject.\n\nFix narrow the type to the actual shape you expect:\n - const isUser = createValidateFn<unknown>();\n+ const isUser = createValidateFn<User>();',
792
+ detail: '`any` and `unknown` describe "anything", so a structural validator has\nnothing to check. The resulting function passes for every input,\nincluding the ones you probably wanted to reject.\n\nFix: narrow the type to the actual shape you expect:\n - const isUser = createValidateFn<unknown>();\n+ const isUser = createValidateFn<User>();',
773
793
  },
774
794
  };
775
795
  //# sourceMappingURL=diagnosticCatalog.generated.js.map