Skip to content

docs(architecture): show the public surface, and pin it - #375

Merged
FBumann merged 1 commit into
mainfrom
docs/public-api-surface
Jul 31, 2026
Merged

docs(architecture): show the public surface, and pin it#375
FBumann merged 1 commit into
mainfrom
docs/public-api-surface

Conversation

@FBumann

@FBumann FBumann commented Jul 31, 2026

Copy link
Copy Markdown
Owner

Follow-up to #373. Hard rule 5 says "the public interface is a declared model, not a Python API" — but nothing said what that was worth in names, and nothing stopped it growing. Narrow is a feature; it should be countable, visible, and enforced like every other fence in this file.

Pinned

PUBLIC_API in tests/test_architecture.py, checked in both directions:

  • __all__ must match the table — catches a name documented and never exported, or exported and never documented.
  • No public non-module attribute may exist outside it — catches a helper that leaked into the namespace by being imported at the top of __init__.py.

Either alone rots. The second half found one on its first run: lpspec.PackageNotFoundError, an stdlib exception public in the package namespace since the version shim was written. It is now _PackageNotFoundError, matching the _installed_version alias directly beside it.

A second test holds the linopy shim to its two verbs — build makes a model, extend adds to one. A third would mean the shim had started being a lane of its own, which hard rule 3 spends its length refusing.

Shown

New "The Python surface" section: the whole surface as one table, grouped the way the diagram is — load it · show it · check it · run it · read it · catch it — with a "you want to" column so a name is reachable from the question that leads to it. Hard rule 5 links to it.

Italic rows are the entries the shape makes cheap and nobody has built (watch what a build is doing, will that solver take it, re-solve with new numbers). They are in the same table as the rest, because the claim being made is precisely that they are not a rewrite.

The consumers diagram

Rebuilt, and smaller than it was. It had three subgraphs of three unconnected nodes each, so direction TB did nothing and mermaid laid it out nine boxes wide — and its leaves duplicated the table directly below it.

A diagram should carry what is actually shaped: the narrow waist and the fan-out. A list of twelve capabilities is not shaped, it is a list. So it is now five boxes on one line —

your math ──▶ the whole model ──┬──▶ show it
                                ├──▶ check it
                                └──▶ run it ──▶ your answers

— and the twelve leaves are rows in the table. "Ships today vs. cheap to build" was a line style the caption had to explain; it is now an italic row.

Both diagrams re-rendered through mermaid-cli to confirm, since multi-line labels in stadium nodes overflow their rounded caps.

Verification

709 passed / 4 skipped / 1 xfailed · ruff check clean · pyrefly 0 errors · mkdocs build --strict clean.

The only source change in the PR is the private alias for PackageNotFoundError. Removing a name from a package namespace is technically breaking, but it was never exported, never documented, and is importlib.metadata's own class — anyone who wanted it was importing it from the stdlib.

Not done

  • docs/index.md has six landing-page feature cards and none is about the API surface. A seventh — "sixteen names" — is probably the strongest version of this point for a first-time reader, but that page is the pitch, so it is your call rather than mine.
  • The pipeline diagram (the four-fence one from refactor(architecture): four directories, four enforced fences #373) is tall, and typeset/ renders as a small box wedged between the two big lanes, which understates it. Left alone here rather than churned in a docs PR.

🤖 Generated with Claude Code

Hard rule 5 says the public interface is a declared model rather than a Python
API. Nothing said what that was worth in names, and nothing stopped it growing.

- PUBLIC_API in tests/test_architecture.py pins the surface by role, checked
  in both directions: __all__ must match the table, and no public non-module
  attribute may exist outside it. The second half caught PackageNotFoundError,
  an stdlib exception sitting in lpspec's namespace since the version shim was
  written — now imported privately, like the version helper beside it.
- A second test holds the linopy shim to its two verbs; a third would mean it
  had started being a lane of its own.
- ARCHITECTURE.md gains "The Python surface": sixteen names in four groups,
  plus the shim and the Result methods. Hard rule 5 links to it.
- The consumers diagram carries the names, one per box, so solid-vs-dashed
  reads as "has a name today" rather than needing the caption to say so.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@read-the-docs-community

Copy link
Copy Markdown

Documentation build overview

📚 lpspec | 🛠️ Build #33848753 | 📁 Comparing 015508a against latest (ea4b9c2)

  🔍 Preview build  

2 files changed
± ARCHITECTURE/index.html
± changelog/index.html

@FBumann
FBumann merged commit bdb6b11 into main Jul 31, 2026
3 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