Skip to content

chore: bump the engine past the quote attribution withdrawal - #64

Merged
dereuromark merged 1 commit into
mainfrom
chore/carve-rb-pin-6436a4ec
Aug 15, 2026
Merged

chore: bump the engine past the quote attribution withdrawal#64
dereuromark merged 1 commit into
mainfrom
chore/carve-rb-pin-6436a4ec

Conversation

@dereuromark

Copy link
Copy Markdown
Contributor

ext/carve/Cargo.toml pinned carve-rs at 971aecf, 17 commits behind that
engine's main. The daily AST conformance run in markup-carve/carve#1147
reports the BINDING PARITY gate failing on it: this binding's tree differed
from carve-rs on 9 of 1006 corpus documents. A binding over carve-rs has no
vote of its own, so all nine were this gem's.

This bumps the pin to carve-rs 8dada737, the current merged tip of that
repo's main, regenerates ext/carve/Cargo.lock, and rebuilds the extension.

Why the nine

971aecf is markup-carve/carve-rs#959, the commit that made a ^ line under a
block quote an ATTRIBUTION. markup-carve/carve-rs#984 then withdrew it, per the
maintainer's ruling in markup-carve/carve#1213: a captioned quote is a figure
again. The binding was still one side of that round trip.

For this input:

> Stay hungry, stay foolish.
^ Steve Jobs

carve-rs at 8dada737 publishes a figure wrapping the quote:

{"type": "figure", "target": {"type": "block_quote", "children": [...]}, "caption": [...]}

while carve-rb at the old pin published the quote with a field the schema does
not name:

{"type": "block_quote", "children": [...], "attribution": [...]}

That extra field is also why CorpusAstSchemaShapeTest failed alongside the
parity gate, reporting 9x block_quote.attribution: not a property the schema names.

The measurement, both directions

Both runs compare this gem's Carve.parse tree against a release build of
carve-rs at 8dada737, using the same shape function
scripts/ast-conformance.mjs uses for its BINDING PARITY gate, over every
corpus document rather than a sample.

At the old pin 971aecf, extension rebuilt:

compared=1006 drifted=9 errors=0
  DRIFT 05-lists-20
  DRIFT 07-blockquote-with-attribution
  DRIFT 282-two-blank-lines-detach-a-caption-5
  DRIFT 306-a-captioned-quote-holds-more-than-one-block
  DRIFT 306-a-captioned-quote-holds-more-than-one-block-2
  DRIFT 306-a-captioned-quote-holds-more-than-one-block-3
  DRIFT 306-a-captioned-quote-holds-more-than-one-block-4
  DRIFT 306-a-captioned-quote-holds-more-than-one-block-5
  DRIFT 55-blockquote-caption-after-a-blank-line

At the new pin 8dada737, extension rebuilt:

compared=1006 drifted=0 errors=0

Then the pin was reverted to 971aecf and the extension rebuilt a third time,
to show the bump is what moved it rather than something else in the session:

compared=1006 drifted=9 errors=0
  DRIFT 05-lists-20
  DRIFT 07-blockquote-with-attribution
  DRIFT 282-two-blank-lines-detach-a-caption-5
  DRIFT 306-a-captioned-quote-holds-more-than-one-block
  DRIFT 306-a-captioned-quote-holds-more-than-one-block-2
  DRIFT 306-a-captioned-quote-holds-more-than-one-block-3
  DRIFT 306-a-captioned-quote-holds-more-than-one-block-4
  DRIFT 306-a-captioned-quote-holds-more-than-one-block-5
  DRIFT 55-blockquote-caption-after-a-blank-line

The same nine, and only those nine, in both directions. The pin was restored
before pushing.

The rebuild, not the manifest

A pin bump without a recompile changes nothing, and this repo has been caught by
exactly that, so the artifact was checked rather than the manifest. The
installed lib/carve/carve.so embeds the cargo git checkout path of the
revision it was built from, and it tracks the pin across all three builds:

git/checkouts/carve-rs-7867d825a4352386/8dada73    (bumped)
git/checkouts/carve-rs-7867d825a4352386/971aecf    (reverted)
git/checkouts/carve-rs-7867d825a4352386/8dada73    (restored)

The behavior agrees: at the new pin the binding returns figure for the
captioned quote above and no attribution key anywhere in the tree.

One note on the reference side of the comparison. The carve-rs binary in the
sibling checkout is from 2026-08-11 and sits on a dirty tree several commits
back, so it describes neither pin. Every number here comes from a fresh release
build of 8dada737 in a detached worktree, not from that binary.

What else the range brought

The corpus HTML test moved from 17 mismatches out of 1006 to 0. Eight of those
seventeen are not the attribution: 313-a-reference-link-s-text-survives-its-own-frame
-2 and -4, the three 314-a-footnote-in-an-unresolved-reference-is-not-a-reference
documents, and 315-an-inline-note-s-content-resolves-after-the-note -3, -4
and -5. Three reference-resolution fixes in the same 17-commit range account
for them: a reference inside an inline note or a critic insertion or deletion
now resolves, a footnote inside an unresolved reference stays a footnote, and a
reference tail no longer seals its own link text.

All eight are catch-up rather than regression, and the direction is what makes
that checkable: each one moved from disagreeing with the spec's own expected
HTML to matching it byte for byte. No fixture was regenerated to reach the
green run.

The rest of the range is not reachable from this gem's API. carve-rs' new lint
surface, the carve fmt writer corrections, and the Markdown and HTML importer
fixes have no Ruby entry point here, and the Markdown, ANSI and plain targets
are not exposed either. The one further caller-visible item is
attrs.keyValues, which now serializes in the author's source order rather
than alphabetically, agreeing with the attrs.order field beside it.

CHANGELOG

The attribution paragraph comes out rather than gaining a withdrawal note.
v0.1.0 is the only released version - v0.1.1 is still a draft - and its
engine pin predates the attribution entirely. The corpus expectation for a
captioned quote is byte-identical before and after the round trip, so the net
delta from v0.1.0 for that construct is nothing, and a state that existed
only between releases is invisible to the only reader the file has. The three
reference-resolution fixes and the keyValues ordering are added, since those
are real deltas from v0.1.0.

The pin sat at carve-rs 971aecf while the engine moved 17 commits, and the
daily AST conformance job reported the BINDING PARITY gate failing: this
binding's tree differed from carve-rs on 9 of 1006 corpus documents. A binding
over carve-rs has no vote of its own, so every one of those was this gem's.

All nine were the same shape. 971aecf is the commit that made a `^` line under
a block quote an attribution; carve-rs then withdrew that and a captioned quote
is a figure again, so the binding was still publishing `block_quote` with an
`attribution` field where the engine publishes a `figure` wrapping the quote.
`attribution` is not a property PART 12's schema names, which is why the shape
test failed alongside the parity gate.

Measured before, against a carve-rs release build of the merged tip 8dada737:

    compared=1006 drifted=9 errors=0
      DRIFT 05-lists-20
      DRIFT 07-blockquote-with-attribution
      DRIFT 282-two-blank-lines-detach-a-caption-5
      DRIFT 306-a-captioned-quote-holds-more-than-one-block
      DRIFT 306-a-captioned-quote-holds-more-than-one-block-2
      DRIFT 306-a-captioned-quote-holds-more-than-one-block-3
      DRIFT 306-a-captioned-quote-holds-more-than-one-block-4
      DRIFT 306-a-captioned-quote-holds-more-than-one-block-5
      DRIFT 55-blockquote-caption-after-a-blank-line

and after the bump and a rebuild of the extension:

    compared=1006 drifted=0 errors=0

The rebuild is the step that changes behavior, so it is what was checked: the
installed `lib/carve/carve.so` embeds the cargo git checkout path for
8dada73, and the binding now returns `figure` with no `attribution` for

    > Stay hungry, stay foolish.
    ^ Steve Jobs

The corpus HTML test moved from 17 mismatches to 0. Eight of those seventeen
are not the attribution: the 313, 314 and 315 documents were fixed by three
reference-resolution corrections in the same range. No fixture was regenerated
to reach the green run - every one of the seventeen moved toward the spec's own
expected output.

The rest of the range is not reachable from this gem's API. carve-rs' new lint
surface, the fmt writer corrections, and the Markdown and HTML importer fixes
have no Ruby entry point here, and the Markdown, ANSI and plain targets are not
exposed either. What is reachable and moved is the captioned quote, the three
reference-resolution fixes, and `attrs.keyValues` publishing in source order.

The CHANGELOG loses the attribution paragraph rather than gaining a withdrawal
note. v0.1.0 is the only released version, and its engine predates the
attribution entirely - the corpus expectation for a captioned quote is
byte-identical before and after that round trip. A state that existed only
between releases is invisible to the only reader the file has.
@dereuromark
dereuromark merged commit 907406a into main Aug 15, 2026
2 checks passed
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