Skip to content

docs: the warning-code taxonomy is undocumented, and the supported-constructs list omits catch/readonly/refine/transform #248

Description

@ssilvius

Surfaced by astro-data (019f8104-6622) while source-tracing whether .catch() is represented. Their CODE claim was wrong -- catch is fully represented, executed proof in the reply -- but the DOCS half of their claim was right, and pulling it revealed a bigger gap behind it. A fourth item was added by huttspawn from the render seat.

1. Supported-constructs list is missing wrappers it supports

README.md:146 (HEAD) / :150 (main) reads:

... plus optional, nullable, default, and describe/meta.

catch and readonly are both absent, though both are in FLAG_WRAPPERS (src/introspection/unwrap.ts:12-21) and both are peeled with inner constraints surviving. A reader source-tracing the docs concludes catch is unsupported -- which is exactly what happened.

Already fixed in the uncommitted docs rewrite on feat/monorepo-plugin-host, which lists all five wrappers in one table row. This card exists so the fix is tracked rather than riding silently on a docs branch, and to cover the parts the rewrite does NOT fix, below.

2. refine and pipe/transform appear in no supported-constructs table at all

Zero hits across README.md, docs/**, AGENTS.md. But kelex has dedicated warning codes for both (refine-unrepresented, transform-output-dropped), so it plainly encounters them. A construct kelex warns about but never names in docs is worse than one it does not handle -- the consumer has no way to anticipate the warning.

This is load-bearing for the render/authoring seats specifically: WARN-on-unrepresentable-refine rather than silent-drop was the position astro-consent, rafters and huttspawn all independently endorsed. It should be documented as a contract, not left as runtime surprise.

3. The whole warning taxonomy is undocumented -- the systemic finding

src/introspection/types.ts:57-78 defines 16 WarningCode values:

unsupported-type, refine-unrepresented, catch-fallback-dropped, default-unstable, transform-output-dropped, coerce-unrepresented, key-policy-unrepresented, format-unrecognized, check-dropped, record-key-narrowed, intersection-key-overlap, numeric-enum-as-union, discriminator-unresolved, discriminator-ambiguous, target-warning, target-field-unprocessed.

Every one of the 16 returns zero hits across README.md, docs//*.md, AGENTS.md, docs/plugins/. The taxonomy exists only in source and tests. The one doc sentence that gestures at it is README.md:165 prose -- "Anything the reader cannot represent is reported as a warning, never dropped in silence" -- which promises a mechanism it never enumerates.

So catch was not a specific documentation gap. It was the visible edge of a total absence.

The explanatory content already exists in-repo and simply was never promoted: .changeset/catch-resolution.md:5-9 explains catch semantics in prose, and .changeset/structured-warnings.md:7 lists several codes. Release-note fragments, not user-facing docs.

4. Authored-vs-derived label is recoverable but undocumented (huttspawn, 019f8102-d431)

introspect.ts:398 sets label to metaString(meta, "title") ?? nameToLabel(name). So the flat label field cannot tell a consumer whether a human authored it or kelex derived it from the key.

Render seats need that distinction, in huttspawn's words: "a derived label I override without thinking, an authored one I treat as intent and think twice."

It IS recoverable -- meta rides verbatim since #147, so meta?.title !== undefined is exactly the signal. huttspawn found this by reading source and filed no ask. That is the gap: undocumented-but-recoverable is still a gap, and no render seat should have to re-derive it from source. Document it as a consumer recipe.

Worth noting as rationale: this is the cleanest evidence for the #147 decision to carry the full meta payload verbatim rather than a title/description subset. That call was made on lossless-round-trip grounds and it bought a consumer a capability nobody designed for.

Acceptance criteria

  1. The supported-constructs table names all five peeled wrappers: optional, nullable, default, catch, readonly.
  2. refine and pipe/transform appear in the docs with their actual treatment stated (constraint recorded as present, not reasoned through; output side of a transform not represented).
  3. A warning-code reference documents all 16 codes: what triggers each, and what the consumer should do about it.
  4. The reference lives on the user-facing doc surface, not in .changeset/.
  5. README.md:165's promise of a warning mechanism links to that reference.
  6. The authored-vs-derived label recipe (meta?.title !== undefined) is documented wherever label is described, with the derived-vs-intent consequence stated.

Metadata

Metadata

Assignees

No one assigned

    Labels

    documentationImprovements or additions to documentation

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions