Skip to content

Move the engine pin past composite figures and cell attributes - #41

Merged
dereuromark merged 1 commit into
mainfrom
chore/composite-figures-composite-sat-6436a4ec
Aug 15, 2026
Merged

Move the engine pin past composite figures and cell attributes#41
dereuromark merged 1 commit into
mainfrom
chore/composite-figures-composite-sat-6436a4ec

Conversation

@dereuromark

Copy link
Copy Markdown
Contributor

Part of markup-carve/carve#1220 (secondary-engine tracker); spec markup-carve/carve#1215, design markup-carve/carve#1122.

There is no port to write here

The tracker's checklist line for this repository reads "port parser/renderers/writer per section 4c", which describes a native engine. This one is a binding: carve-lang calls carve-rs through PyO3 and embeds it at the revision recorded in Cargo.lock. A construct the engine gains is a construct this package gains the moment the pin moves, and no Python change reaches it before that.

Both constructs the corpus was waiting on have landed upstream: markup-carve/carve-rs#986 (PART 9 section 4c, composite figures) and markup-carve/carve-rs#996 (a cell's attributes bind after its kind and alignment markers).

The change

The pin moves from 9ff08784 to 98de7874 (carve-rs main), in Cargo.toml and Cargo.lock together. That is the whole functional diff; the rest is the CHANGELOG.

Measured

Against carve 1436f39a, 1025 corpus pairs, wheel rebuilt for each row:

pin diverging
9ff08784 (main) 13
98de7874 0

The 13 were nine 318-composite-figures* documents and four 319-cell-attributes-* documents. All eleven 318-composite-figures documents and all six 319-cell-attributes-bind-after-the-kind-and-alignment-markers documents now match the spec. Nothing is allowlisted or skipped; test_corpus_renders_byte_identically compares every pair and this repository has no allowlist.

Proof, both directions

At the old pin, 318-composite-figures-4:

::: figure
![lone](l.png)
^ The only panel
:::
^ Figure #: One panel is valid

rendered the pre-section-4c shape, a generic container with the caret line surviving as a paragraph:

<div class="figure">
  <figure>
    <img src="l.png" alt="lone">
    <figcaption>The only panel</figcaption>
  </figure>
</div>
<p>^ Figure #: One panel is valid</p>

At the new pin it renders what the spec pins, and so do the other twelve.

The control now discriminates

318-composite-figures-8 is the control for the clause: an opener carrying a title or a [label] must stay a generic container rather than become a figure group. It passed at the old pin too, but vacuously - the engine had no rule separating a bare opener from a decorated one, so the mutation that should break it changed nothing.

Re-run against the new pin, stripping the title and the [label] so both openers are bare changes the production. As written:

<div class="figure">
  <p class="admonition-title">A titled figure div</p>
  <figure>
    <img src="a.png" alt="one">
    <figcaption>(a) One</figcaption>
  </figure>
</div>
<p>^ Not a group caption</p>
<div class="figure">
  <p class="div-label">g</p>
  <p>Body.</p>
</div>

mutated to bare openers:

<figure class="carve-figure-group">
  <div class="carve-figure-panels">
    <figure class="carve-figure-panel">
      <img src="a.png" alt="one">
      <figcaption>(a) One</figcaption>
    </figure>
  </div>
  <figcaption>Not a group caption</figcaption>
</figure>
<figure class="carve-figure-group">
  <div class="carve-figure-panels">
    <p>Body.</p>
  </div>
</figure>

Different element, different class, and the caret line is consumed as the group caption. The control asserts something now.

CHANGELOG placement

The entry goes under the existing 0.1.1 heading rather than a new one, and the "Embed carve-rs" bullet there now names 98de7874. v0.1.1 is a draft, not a release; the last released tag is v0.1.0, so the net delta a consumer sees from it is one engine move, not two. No version field is touched.

This binding has no parser. It calls carve-rs through PyO3, so a construct the
engine gains is a construct this package gains the moment the pin moves, and
until then thirteen corpus documents diverged here for reasons no Python change
could reach.

Both constructs have now landed upstream: markup-carve/carve-rs#986 (PART 9
section 4c, composite figures) and markup-carve/carve-rs#996 (a cell's
attributes bind after its kind and alignment markers).

The pin moves from 9ff087845ebbc31e650fed4faea01f4eea895b82 to
98de7874ad2e81f69e57764562c83f4918522ac2 (carve-rs main), in Cargo.toml and in
Cargo.lock together.

Measured against carve 1436f39a, 1025 corpus pairs, wheel rebuilt each time:

  at 9ff08784   13 diverging
  at 98de7874    0 diverging

The thirteen were the nine `318-composite-figures*` documents and the four
`319-cell-attributes-*` documents that were failing; all eleven of the former
and all six of the latter now match the spec.

The control for the clause, `318-composite-figures-8`, asserts that an opener
carrying a title or a `[label]` stays a generic container. It passed at the old
pin as well, but only because the engine had no rule separating a bare opener
from a decorated one - both spellings rendered `<div class="figure">`, so the
document could not have failed. At the new pin the same mutation, stripping the
title and the `[label]` so both openers are bare, changes the production:

    <div class="figure">
      <p class="admonition-title">A titled figure div</p>
      ...
    </div>
    <p>^ Not a group caption</p>

becomes

    <figure class="carve-figure-group">
      <div class="carve-figure-panels">
        <figure class="carve-figure-panel">
          <img src="a.png" alt="one">
          <figcaption>(a) One</figcaption>
        </figure>
      </div>
      <figcaption>Not a group caption</figcaption>
    </figure>

Nothing is allowlisted or skipped; the corpus test compares every pair.

The CHANGELOG entry lands under the existing 0.1.1 heading rather than a new
one. v0.1.1 is a draft, not a release, so the last released tag is v0.1.0 and a
consumer upgrading from it sees a single engine move.
@dereuromark
dereuromark merged commit fe93616 into main Aug 15, 2026
4 checks passed
@dereuromark
dereuromark deleted the chore/composite-figures-composite-sat-6436a4ec branch August 15, 2026 18:59
dereuromark added a commit that referenced this pull request Aug 15, 2026
EXPECTED_TYPES is this binding's own record of what the language emits, and the
assertion over it is one-directional by design: a recorded type going missing
fails, an unrecorded new type only prints. The engine bump that brought PART 9
section 4c in (#41) added a node type nothing here names, and the run duly
printed it.

Recording it is a tightening, not a widening. `figure_group` appears in no
carve-rs source file at the revision this binding pinned before that bump
(9ff08784, zero hits under src) and in eleven at the one it pins now
(98de7874), so this line would have failed the suite before the bump and passes
after it. From here on, a pin that drops the group node fails with the type
named rather than leaving nine corpus documents to explain it.

The schema assertion in the same module gains the same reach for free: it
requires the spec's ast-schema.json to define a shape for every recorded type,
and the schema does define figure_group.

Measured with CARVE_SPEC_CORPUS against carve 1436f39a, wheel rebuilt: 101
passed, 3 skipped.

No CHANGELOG entry: the construct itself is already described under 0.1.1, and a
test-only change is not something a consumer of the wheel can observe.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant