Conformance Suite Changelog¶
This page mirrors conformance/CHANGELOG.md
in the repository. It tracks the conformance suite (suiteVersion in manifest.json) — fixture
additions/removals, case-count changes, schema-shape changes, and error-code registry changes. It is
versioned independently of the kBars library; see the
library changelog for adapter/API history.
The format follows Keep a Changelog, and the suite adheres to Semantic Versioning.
[0.1.0]¶
Initial published version of the suite. 0.1.0 has not been tagged or published, so the entries
below amend it in place rather than opening a new version section — the case counts and ZIP contents
change without a suite-version bump. Had 0.1.0 already shipped, these would instead be a 0.1.1
entry.
Added¶
- Two-tier conformance: a
coretier and afulltier. Conformance now partitions into core — the template system alone (grammar, pre-pass, data model, rendering, partials, errors, locations, number rendering, iteration order, code-point semantics) — and full, which adds the standard library: the baseline roster of built-in transforms and@envproperties an implementation must support to claim full conformance. Both tiers share onesuiteVersionand are never versioned separately. A full-tier implementation may add transforms and@envproperties beyond the baseline, and may even widen a standard-library transform (e.g. accepting an optional argumenturl_decodedoes not define) provided the baseline behavior is preserved — a conformant-but-risky freedom. The transform roster and@envnamespace, formerly described as a wholly implementation-defined layer, are now the standard library, normative at the full tier. See Implementation-Defined Behavior and the Core vs. optional extensions section of the specification. tierfield onmanifest.json(format1.1) and--full-report(reportFormat1.1). Eachmanifest.jsonentry now carries"tier": "core" | "full"(derived from the fixture's directory —transforms/andenv-properties/arefull, everything elsecore), so a core-tier runner can skip thefullfixtures programmatically.kbars conformance --full-reportlikewise tags each file with itstierand adds asummary.tiersper-tier pass/fail breakdown. See the manifest.- Six fixture categories, sharing five JSON Schemas:
grammar/— grammar parse fixtures, validated againstgrammar-fixture.schema.json.prepass/— pre-pass normalization fixtures, validated againstprepass-fixture.schema.json.render/— render output fixtures, validated againstrender-fixture.schema.json.transforms/— built-in-transform fixtures, sharingrender-fixture.schema.jsonwithrender/but held separately because the transform roster is the standard library (full tier) — see Transforms and@envare the standard library.partials/—{{> key }}rendering, the failure matrix, and template-stack assertions, validated againstpartials-fixture.schema.json.env-properties/— the@envnamespace and{{=scoped variables, validated againstenv-property-fixture.schema.json.- A generated, out-of-band
manifest.json(format1.1) recording the suite version and, per fixture file, its own version, case count, and conformancetier(core/full). See the manifest. - A 17-entry canonical
errorCodetaxonomy (KB-0000–KB-5007) spanning the grammar, transform, assign, partials, and soft-fail families. See Error Codes. - Normative specifications for three behaviors that are easy to leave unspecified: ECMA-262 shortest-round-trip number rendering, insertion-order struct iteration, and Unicode-code-point source location counting.
- The Bars specification: a versioned, self-contained normative definition
of the Bars language, for which kBars is the reference implementation. Versioned identically to
this suite (
site-spec/docs/spec/<suiteVersion>/), it embeds the reference ANTLR grammar verbatim, partitions conformance into a normative core tier and a full tier that adds the standard library (the built-in transform roster and@envproperties), and is mechanically checked to reference every fixture directory and non-reservederrorCode(checkSpecCoverage) and to stay in sync with the canonical.g4grammar files (checkSpecGrammar). The specification is now the normative source of truth; this conformance suite is its executable test. It is bundled into the conformance ZIP underspec/(see Distribution). render-report.schema.jsonandfull-report.schema.json, documenting the JSON shapes ofkbars render --jsonandkbars conformance --full-report— see the CLI Reference.- JSON Schemas for every fixture shape and for the manifest envelope, each declaring a canonical
$idunderhttps://bars.commonsware.com/conformance/schema/. See Fixture Schemas. - A normative HTML escaping table in the Bars specification: exactly
five characters are escaped, and the single quote is
'(hex), not'or'. - A normative date-time render profile in the specification's data-model section: an
ISO-8601/RFC-3339 UTC instant (
YYYY-MM-DDThh:mm:ss[.f{3|6|9}]Z), pinned by new cases inenv-properties/datetime-property.jsoncovering millisecond/microsecond/nanosecond fractional precision, non-trimming of a trailing-zero fractional group, and offset-to-UTC normalization. - The specification's tunable-limits section now names kBars's
DEFAULT_MAX_PARTIAL_DEPTH(currently 64, kBars-specific) and states that no conformance fixture depends on any implementation's default recursion depth. - A dedicated torture fixture set, cited from a new "Adversarial inputs" specification section:
render/torture-deep-nesting.json(10-level nested blocks, well under any reasonable implementation's maximum block-nesting depth),render/torture-unterminated-at-eof.json, andpartials/torture-adversarial-recursion.json— see the conformance suite changelog for the full per-case breakdown. - A bounded maximum block-nesting depth, enforced at parse time. kBars was crashing with a native
stack overflow on templates nested deeper than its recursive-descent parser's native stack could
sustain. The fix is a pre-parse guard that counts running block-nesting depth ahead of the real
parser and, past kBars's internal
DEFAULT_MAX_NESTING_DEPTH, throws a clean, located hard failure — the newKB-1003(NestingTooDeep) grammar-family code — instead of overflowing the stack. The exact ceiling is implementation-defined and not portable, soKB-1003isreserved: trueand no conformance fixture pins it. See the new Tunable limits subsection, the newKB-1003row in Error Codes, and the conformance suite changelog for the full writeup. ~trim-marker tokens on every tag family that previously lacked them — block openers/closers (with/each/if/unless),{{else}}/{{else if}},{{~=(assign),{{~>(partial), and{{~!/{{!…~}}(comment) — plus the implicit standalone-line stripping rule (a tag alone on its line has that whole line's surrounding whitespace stripped even without an explicit~, with interpolation exempted) and standalone-partial re-indentation (a standalone{{> key }}re-indents every line of its rendered output). See the Bars specification's whitespace-control section for the full normative rules, and the conformance suite changelog for the full per-case fixture breakdown.render/no-reinterpolation.json(5 cases): pins that a resolved value is emitted verbatim and never re-scanned for tags.- Comment-robustness cases in
render/comments-elided.json: a comment body matching a context key is still elided; a multi-line comment body elides in full; and a comment closes at the first}}encountered rather than a balanced scan — see the lexical specification for the embedded grammar rule. - One doubled-adjacent-same-key case in each of
render/if-block.json,render/each-block.json, andrender/with-block.json: two adjacent blocks over the same key render/iterate/push-pop independently. render/interpolation-matrix.json(10 cases): a single auditable matrix crossing every JSON value type (string, integer, decimal, boolean, null) against both interpolation modes (escaped, unescaped).KbConformance.SUITE_VERSION, a publickbarslibrary constant reporting the conformance-suite version the build targets, guarded by a parity test.- A machine-readable transform registry (
transforms/registry.json,fulltier, 56 cases) cataloging every built-in transform's category, since-version, summary, description, input coercion, argument list, arity, and worked-example fixture, validated againsttransform-registry.schema.json. See the new Transforms reference and Fixture Schemas for the registry's shape. - A machine-readable
@envproperty registry (env-properties/registry.json,fulltier, 1 case) cataloging the standard-library@envproperty (now) with its value kind, since-version, summary, description, optional sourcing note, and worked-example fixture, validated against the newenv-property-registry.schema.json. The standard-library-property fixtureenv-properties/now.jsonwas renamed toenv-properties/env-now.json, adopting theenv-<name>.jsonnaming convention the transform registry already uses.env-property-fixture.schema.jsongained the same optional"spotlight"case marker the transform fixtures use. See the new Environment Properties reference and Fixture Schemas for the registry's shape. - A documented conformance-claims convention:
kbars conformance --full-report'sfull-report.schema.jsondocument is now specified as the canonical interchange format a workalike emits to prove a conformance claim, rather than a kBars-CLI-specific convenience. "Implementation I conforms to Bars suiteX.Y.Zat tier T" now names one specific, machine-checkable artifact instead of an unverified assertion. See the new Claiming Conformance page, which also reserves a "Known workalikes" section for future independently-maintained implementations to list themselves alongside their own conformance report. - A documented reference-CLI-as-oracle workflow for porters: when a question comes up mid-port
that no fixture answers, build the smallest template/context pair reproducing it and run it through
kbars render [--json]rather than guessing or re-deriving the answer from spec prose alone. See the new Using the Reference CLI as an Oracle page, which also covers matching the CLI's reported suite version (kbars --version) to the suite you're targeting and folding a generally-true finding back into the suite as a new fixture. - A generated, human-readable conformance example gallery.
site-spec/docs/spec/0.1.0/examples/mirrors the four template-and-input-driven fixture areas (render/,transforms/,partials/,env-properties/) as Markdown pages, one per fixture file with at least one successful case, showing each case's name, description, template, context, area-specific extras (partial bodies;@envclock and property overrides), and rendered output — generated directly from the fixtures themselves, not hand-written. Error cases are omitted, and a fixture file whose cases are all errors produces no page.generateConformanceExamplesbuilds the gallery andcheckConformanceExamples(wired intocheck) fails the build when the committed pages drift from the fixtures. See the new Conformance Examples section.
Changed¶
-
Consolidated redundant simple-value cases into the new
render/interpolation-matrix.json: removedinteger-renders-plain/whole-double-renders-without-fractionfromrender/number-rendering.jsonandnull-context-interpolation/null-context-unescapedfromrender/null-context.json(every specialized edge case in both files is retained). See the conformance suite changelog for the full accounting. -
The
escapeandescape_oncetransforms now emit'for a single quote, matching the core escaped-interpolation path (previously');escape_once's idempotency check was widened to recognize hex numeric entities so it does not double-escape its own output. - kBars's pre-pass normalizer now escapes every leading brace-pair of an unterminated opener, not just
the first — fixing a real bug where a 4-brace
{{{{raw-block opener at end-of-input produced a parse error instead of degrading to literal text. - Whitespace-control (
~) semantics switched from value-level trimming to template-text trimming, matching Handlebars/Mustache. Previously~trimmed characters out of the interpolated value itself, and onlyInterpolation/UnescapedInterpolationtags recognized a trim marker at all. Now~(and the new standalone-line rule) strip whitespace in the surrounding template source text, and every tag family accepts trim markers. This is a behavioral break: a port that pinned the old value-trim behavior will see surrounding template whitespace disappear where before only the interpolated value's own whitespace was touched, and will now see trimming on block/else/partial/assign/comment tags that previously had none. See the Bars specification for the full rules. - Fixed: standalone-line detection now recognizes only space and tab as indentation, not any Unicode whitespace — a line "indented" with a vertical tab or form feed is no longer incorrectly treated as standalone. See the specification's standalone-stripping section for the exact character set and the related edge cases (CRLF line endings, template-edge tags, raw blocks and escaped delimiters sharing a tag's line).
- Fixed: standalone-line detection no longer treats an empty block body, an empty
if/else ifarm body, or an emptyelsebody as a line boundary. An absent neighbor (null) is correctly blank at a template/partial edge or where a nested block directly abuts its parent's tag, but a block's own empty inner region instead places its paired tags adjacent to each other on the same line — content, not a boundary. kBars previously over-stripped in this shape (e.g.{{#if a }}{{/if}}was treated as if each tag sat alone on its own line), diverging from both the specification's prose and the Handlebars parity it claims. This is a behavioral change: a port that pinned the prior over-stripping for these empty-region shapes will now see the surrounding indentation/newline preserved. See the specification's standalone-stripping section and the conformance suite changelog for the ten new fixtures pinning this rule.