docs(design): the v7 public api plan - #831
Merged
Merged
Conversation
Records what the next major changes in the public headers and why: one road per operation instead of the several we grew, the removals the design doc deferred until a major, and the enum-ordinal constraint only a major can lift. Counts the duplication rather than asserting it - twenty-two ways to decode a file, twelve to ask what one is, twenty translate overloads - and names the three cases that are the same code twice, including open_document_file, which repeats open_file's cascade engine for engine. Splits the work into nine pull requests in an order where each compiles alone. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016hxDa2rev11eLUEJZJ5nmz
This was referenced Sep 6, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
🤖 Generated with Claude Code
We cut a major soon. This records what it should change in
src/odr/*.hpp, why,and in which pull requests — so the eight code PRs behind it can each be small
and reviewed against a stated target rather than a vibe.
No code.
docs/design/api-v7.mdplus its line in the design index.The premise
The public API grew several ways to do each thing, and the count is
uncomfortable once you actually take it:
html::translateoverloadsThree of those are not merely redundant, they are the same code twice:
odr::openis a pure forward.odr.cpp:203-230is six one-linereturn DecodedFile(...). The split leaked into the bindings — JNI exposesboth (
jni_core.cpp:227vsjni_file.cpp:93), Python binds all sixopenoverloads and the
DocumentFilefactories.DocumentFile::type/::metadecode the whole file to read one field, andthrow for anything that is not a document.
open_strategy::open_document_filerepeatsopen_file's cascade enginefor engine for zip and cfb, and both ends throw
NoDocumentFile— whichas_document_file()throws too.open(f).as_document_file()is a drop-in,so ~90 of the 737 lines in
open_strategy.cppsay the same thing twice.Underneath the noise sits one real asymmetry:
CsvFile::from_filebypassesopen_strategyentirely, soDecodePreferenceandCsvOptionsare two"how to decode" knobs on different roads and a caller who wants to name a
separator cannot get there through
open. The overload count is the symptom;that is the bug.
The wasm binding already converged on the shape we want —
odr.open(bytes, { name }),openAs,detect. C++ is the layer that never got the cleanup.What the plan proposes
Two
openfunctions where there were twenty-two, fourtranslateoverloadswhere there were twenty, one editing entry point, and the removals
docs/design/README.mdalready flagged as "the breaking change thisdeliberately is not".
It also argues against two things worth arguing against: renumbering the
enums (cosmetic payoff, silent failure in a stale binding — pin the values and
test them instead), and regrouping
HtmlConfig(breaking in five bindings forreadability, and #764 changes the field list anyway).
The nine PRs
refactor(api)!: drop the inert globalsrefactor(api)!: drop the inert config and charset surfacerefactor(html)!: cut translate to its four inputsrefactor(api)!: one way to ask what a file isrefactor(api)!: one way to open a filefeat(api)!: fold the decode options into one structrefactor(document)!: one way to edit a documenttest(api): pin the enum ordinalsOrdered so each compiles alone, and so bindings move in the same PR as the
header they mirror — a lagging binding is a build break, not a deprecation.