Skip to content

Define a non-lossy semantic round-trip contract #594

Description

@claell

Problem

The suite has many focused parser and writer tests but no explicit end-to-end definition of what ordinary parse_stringwrite_stringparse_string use must preserve. Without a central contract, a change can keep producing syntactically valid output while silently losing or reordering meaningful bibliography information.

Byte identity is too strict for the current canonical writer: line endings, indentation, spacing, optional commas, and some enclosure formatting may normalize. Short-circuiting unchanged files by returning cached raw source would also be the wrong test because it would not validate the model produced by the parser or the writer's serialization of edits.

Proposed semantic contract

Define a reusable semantic inventory over the parsed model and require it to survive a complete parse/write/reparse path. It should include, in source order:

  • block kind and block order;
  • entry type, citation key, field order, field-key spelling, and field values;
  • string definitions and preambles;
  • explicit and implicit comment content and position; and
  • retained failed-block raw source.

The contract should fail loudly when a new model block type is added without deciding how it participates.

Add separate cases for:

  • preserving block and field order unless sorting middleware is requested;
  • permitting documented layout normalization while semantic inventory remains equal;
  • normalizing whitespace-only input to empty output;
  • serializing edited and newly added fields correctly while unrelated records remain semantically unchanged; and
  • retaining failed input through the model, not through a raw-file bypass.

Scope boundary

This is a semantic round-trip contract for the existing canonical writer, not a byte-preserving concrete-syntax editing mode. A future exact mode could preserve untouched token spans and rewrite only edited nodes, but that requires a concrete-syntax model and should be proposed separately.

The failed-input portion depends on the raw-preserving default proposed in #588 / PR #589. Default macro-linkage and enclosure-style choices remain separately reviewable in #590 / PR #591 and #592 / PR #593 rather than being bundled into this contract.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions