Skip to content

softschema 0.6.2

Choose a tag to compare

@jlevy jlevy released this 22 Aug 23:11
5da09d8

softschema 0.6.2 fixes a validation gap that could pass a build while checking nothing:
the CLI bound every artifact to the frontmatter-md profile, so a conforming pure-yaml
artifact — including the spec's own example — could not be validated at all. Upgrading is
safe and requires no changes; the inspect JSON output gains one key.

What's Changed

Fixes

  • validate and inspect resolve the artifact profile instead of assuming
    frontmatter-md
    (#38). Both CLIs read every artifact with the frontmatter reader and
    built a Contract with no profile, so the pure-yaml branch of validate_artifact was
    unreachable from the command line and any pure-YAML file failed with no_frontmatter.
    The library was correct throughout; only the binding was wrong.

    The gap was silent rather than loud, which is what made it worth a patch: a project
    could adopt pure-YAML datasets, mark them status: enforced, wire softschema validate
    into CI, and get a passing build that validated nothing — the exact failure status
    exists to prevent. An enforced pure-yaml artifact that violates its bound schema now
    fails with exit 1.

    Profile resolution is --profile > a *.yaml/*.yml file name > a fenceless document
    whose root mapping carries a softschema: block > frontmatter-md. The file name is
    checked before the frontmatter fence, because a YAML document may open with the ---
    document-start marker that the frontmatter reader would otherwise scan as the start of a
    fence. Requiring the metadata block for the content case is what separates a pure-yaml
    artifact from prose that happens to parse as YAML, so a Markdown document without
    frontmatter reports no_frontmatter exactly as before.

  • Envelope inference no longer applies to pure-yaml artifacts. The spec exempts the
    profile from single-key inference and multi-key ambiguity rejection, because a pure-yaml
    artifact's whole root minus the metadata block is the payload. Reaching that branch
    through the CLI would otherwise have rejected a two-key pure-yaml document as ambiguous.

New features

  • --profile {frontmatter-md,pure-yaml} on validate and inspect in both
    implementations: the explicit escape hatch for an artifact whose name and content do not
    settle its shape.

  • inspect reports the resolved profile, and reads a pure-yaml artifact's root
    metadata block rather than reporting metadata: null for it. has_frontmatter stays
    literal — a pure-yaml artifact has none — and profile is what explains the populated
    metadata beside it. This adds one key to the inspect JSON output.

  • clearValidatorCache is exported from the TypeScript package, matching Python's
    clear_validator_cache.

Performance

  • TypeScript compiled schemas are memoized, closing the last gap with the Python cache
    shipped in 0.5.0. validateStructural constructed a fresh Ajv instance and recompiled
    the schema on every call, so a suite validating many artifacts against one schema paid
    full compilation each time; on a repeated validation of the movie example the per-call
    cost drops from roughly 17ms to 0.03ms.

    Both runtimes now key the cache on the schema's own content plus the enforced overlay,
    so a rewritten schema can never be served a stale entry and two paths holding identical
    schemas share one. Validation with resources supplied builds fresh in both, rather than
    risk a wrong key, and only a schema that compiles is cached.

Documentation

  • The spec now states how a conforming implementation resolves the profile, which was
    previously unspecified — the spec presented pure-yaml as a fully conforming profile
    with no indication of how an implementation should recognize one.

Testing and release safety

The profile fix is owned by the shared golden corpus, which runs against Python, Node, and
Bun: a pure-yaml artifact validating with no flags, an enforced pure-yaml artifact
failing its bound schema (the regression guard for the silent-pass hole), a declared
envelope, --profile overriding detection, detection without a *.yaml name, and
inspect on a pure-yaml artifact. The validator cache is covered by TypeScript unit tests,
since it is runtime-specific.

Full end-to-end runbook run before tagging: lint, both unit suites, the golden corpus on
all three runtimes, cross-implementation parity, clean-environment installs of the wheel
and npm tarball, the quickstart from an empty directory, and the skill bootstrap.
Both implementations were additionally swept over 14 profile-detection edge cases and
agree on all of them.

Full Changelog: v0.6.1...v0.6.2