Skip to content

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 core tier and a full tier. 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 @env properties an implementation must support to claim full conformance. Both tiers share one suiteVersion and are never versioned separately. A full-tier implementation may add transforms and @env properties beyond the baseline, and may even widen a standard-library transform (e.g. accepting an optional argument url_decode does not define) provided the baseline behavior is preserved — a conformant-but-risky freedom. The transform roster and @env namespace, 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.
  • tier field on manifest.json (format 1.1) and --full-report (reportFormat 1.1). Each manifest.json entry now carries "tier": "core" | "full" (derived from the fixture's directory — transforms/ and env-properties/ are full, everything else core), so a core-tier runner can skip the full fixtures programmatically. kbars conformance --full-report likewise tags each file with its tier and adds a summary.tiers per-tier pass/fail breakdown. See the manifest.
  • Six fixture categories, sharing five JSON Schemas:
  • grammar/ — grammar parse fixtures, validated against grammar-fixture.schema.json.
  • prepass/ — pre-pass normalization fixtures, validated against prepass-fixture.schema.json.
  • render/ — render output fixtures, validated against render-fixture.schema.json.
  • transforms/ — built-in-transform fixtures, sharing render-fixture.schema.json with render/ but held separately because the transform roster is the standard library (full tier) — see Transforms and @env are the standard library.
  • partials/{{> key }} rendering, the failure matrix, and template-stack assertions, validated against partials-fixture.schema.json.
  • env-properties/ — the @env namespace and {{= scoped variables, validated against env-property-fixture.schema.json.
  • A generated, out-of-band manifest.json (format 1.1) recording the suite version and, per fixture file, its own version, case count, and conformance tier (core/full). See the manifest.
  • A 17-entry canonical errorCode taxonomy (KB-0000KB-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 @env properties), and is mechanically checked to reference every fixture directory and non-reserved errorCode (checkSpecCoverage) and to stay in sync with the canonical .g4 grammar 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 under spec/ (see Distribution).
  • render-report.schema.json and full-report.schema.json, documenting the JSON shapes of kbars render --json and kbars conformance --full-report — see the CLI Reference.
  • JSON Schemas for every fixture shape and for the manifest envelope, each declaring a canonical $id under https://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 &#x27; (hex), not &#39; or &apos;.
  • 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 in env-properties/datetime-property.json covering 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, and partials/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 new KB-1003 (NestingTooDeep) grammar-family code — instead of overflowing the stack. The exact ceiling is implementation-defined and not portable, so KB-1003 is reserved: true and no conformance fixture pins it. See the new Tunable limits subsection, the new KB-1003 row 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, and render/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 public kbars library constant reporting the conformance-suite version the build targets, guarded by a parity test.
  • A machine-readable transform registry (transforms/registry.json, full tier, 56 cases) cataloging every built-in transform's category, since-version, summary, description, input coercion, argument list, arity, and worked-example fixture, validated against transform-registry.schema.json. See the new Transforms reference and Fixture Schemas for the registry's shape.
  • A machine-readable @env property registry (env-properties/registry.json, full tier, 1 case) cataloging the standard-library @env property (now) with its value kind, since-version, summary, description, optional sourcing note, and worked-example fixture, validated against the new env-property-registry.schema.json. The standard-library-property fixture env-properties/now.json was renamed to env-properties/env-now.json, adopting the env-<name>.json naming convention the transform registry already uses. env-property-fixture.schema.json gained 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's full-report.schema.json document 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 suite X.Y.Z at 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; @env clock 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. generateConformanceExamples builds the gallery and checkConformanceExamples (wired into check) 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: removed integer-renders-plain/whole-double-renders-without-fraction from render/number-rendering.json and null-context-interpolation/null-context-unescaped from render/null-context.json (every specialized edge case in both files is retained). See the conformance suite changelog for the full accounting.

  • The escape and escape_once transforms now emit &#x27; for a single quote, matching the core escaped-interpolation path (previously &#39;); 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 only Interpolation/UnescapedInterpolation tags 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 if arm body, or an empty else body 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.