Repository navigation
softschema 0.9.1 is a patch release: doctor now recommends a command that works when
uvx or npx started it, Python reads C-first only with ruamel.yaml.clib's parser,
and the Python package requires frontmatter-format 0.5.1. Validation results and
compiled schema bytes are unchanged.
What's Changed
Compatibility
Dependency floors. The Python package requires frontmatter-format>=0.5.1 and
ruamel-yaml>=0.18,!=0.19.0. ruamel.yaml 0.19.0 alone depends on ruamel.yaml.clibz by
default, which compiles libyaml with Zig at install time, and its YAML() does not use
it. A project that pins ruamel.yaml 0.19.0 should move to 0.19.1 or a 0.18 release.
softschema validates with its own reader and uses frontmatter-format only to write
compiled schemas, so 0.5.1 matters to code that reads or writes with frontmatter-format
alongside softschema:
- Lossless writes.
fmf_writeandfmf_insert_frontmattersplit the metadata only
at LF, CRLF and CR, so a value holding LS, PS or NEL no longer gains a real line break
in the file. They also keep a shebang or PEP 723 block before hash-style frontmatter,
and a replaced file keeps its mode where the filesystem allows. - Control and line-separator characters are escaped. A string holding NEL, LS, PS,
CR or a character outside YAML 1.2c-printableis written double-quoted, as\N,
\L,\P,\r,\x1Fand so on, so it reads back exactly. softschema's compile
writer already wrote compiled schemas this way. - The C-first gate admits only
ruamel.yaml.clib's parser, the same gate
softschema's own reader now applies.
Fixes and hardening
doctorrecommends a prefix that works from the caller's shell. Run through
uvx softschema@latestornpx -y softschema@latest,doctorfound the runner's own
throwaway copy ofsoftschemaon thePATHthe runner gave it and recommended a bare
softschema, which the caller's shell cannot find. Both implementations now skip uv
cache buckets and npm's_npxcache, reportsoftschema: nowhen only such a copy
exists, and recommend the runner that started them:uvx softschema@latestor
npx -y softschema@latest. An installedsoftschemaonPATHis still recommended
first. The TypeScript CLI also counts only executable files as runners, as Python
already did.- Python reads C-first only with
ruamel.yaml.clib's parser. The gate admitted any
C parser that reported libyaml 0.1.7, which includesruamel.yaml.clibz, a different
build that the differential search behind the C-first guards has never run on. A
parser from any other module now leaves every text to pure ruamel, anddoctor's
yaml_parser_reasonsays why. No released ruamel.yaml uses clibz fromYAML(), so no
install changes mode today.
Documentation
The guide, installation, design and development docs are corrected for 0.9, the agent
skill is rewritten around the 0.9 workflow with a table of common refusals and their
fixes, and the guide gains a measured performance section: readable YAML by default,
and for megabytes parsed often, JSON syntax in Python, no tabs, ruamel.yaml.clib, and
one process for many files.
Testing and release safety
A new test runs a 5,750-text corpus through frontmatter-format's own libyaml guard and
checks that softschema refuses, routes to pure ruamel, or reads identically on every
text frontmatter-format routes to pure.
Release checklist Phases 1–4 pass on the release tree against frontmatter-format 0.5.1:
lint, 616 pytest plus 21 in the slow tier, both C-first and with
SOFTSCHEMA_PURE_YAML=1; 525 bun tests with the coverage gate, bun audit clean,
tsc/biome/publint; golden corpus 102 py / 97 node / 102 bun; cross-impl parity OK;
compile --check with no drift; and Markdown format-check clean. No golden, test or
compiled schema changed with frontmatter-format 0.5.1. The wheel and the npm tarball
were installed into clean environments and exercised on both artifact profiles, the
quickstart produced byte-identical output across implementations, and the skill
bootstrap created both mirrors from each installed CLI.
frontmatter-format 0.5.1's PyPI wheel and sdist match their published sha256 digests,
and their package sources are byte-identical to the v0.5.1 tag.
Full changelog: v0.9.0...v0.9.1