Skip to content

Design document: which capabilities belong in the kernel package, and which ship separately (#746 item 78) #1008

Description

@Rafael-SOWNet

Item 78 of #746, filed as its own issue because it is the one thing that roadmap names as "worth settling before v2.0 adds anything large, because published package boundaries cannot be moved afterwards" — and three releases have since added large subsystems to the kernel without it being settled.

"A Design document for the package split: which capabilities belong in the kernel package, which ship separately, and what the dependency rules between them are."

This is a request for a decision, not for code. Nothing here proposes moving anything yet.

Where we actually are

Measured on master at 6b93b401 (2.3.0).

Four packages are published, by .github/workflows/Nuget.yml: AngouriMath, AngouriMath.FSharp, AngouriMath.Interactive, AngouriMath.Terminal.

Two corrections to #746's own premise, which describes the existing split as "kernel, FSharp, Interactive, Terminal, CPP and Experimental":

  • Experimental is not a package. It is Sources/AngouriMath/Convenience/Experimental/MathS.Experimental.cs, a folder inside the kernel.
  • The C++ wrapper is not published. AngouriMath.CPP.Exporting and .Importing build and are tested in CI; neither is pushed to NuGet.

So the pattern the roadmap says to extend is narrower than it was described as, which is worth knowing before extending it.

The kernel is now 211 files and 53,665 lines, and this is what has arrived in it since the roadmap was written, none of it with a boundary decision in front of it:

in the kernel lines
Functions/Algebra/Polynomials 4,184
Core/Transformations 2,899
Functions/Algebra/Groebner 929
Functions/Boolean (incl. the Quine–McCluskey minimiser) 621
Functions/Output/ToSympy 591
Functions/Quantum 414
Functions/Algebra/MonoidAlgebra 288
Core/Entity/GenericMath 233

Partial mitigation, and it is real: the polynomial and Gröbner layers are internal, so they add size without adding surface. That caps the compatibility cost of moving them later — it does not cap the download.

What the design document has to answer

  1. What is the kernel? Goal: Math OS — a ten-year vision for AngouriMath as an open mathematical reasoning platform #746's architecture says "someone who wants only the expression tree and the rewrite engine gets a fast, boring, dependency-light library — and that must stay a supported way to use AngouriMath forever". That sentence is a package boundary if it is anything. Where is it drawn — does the kernel keep Simplify, or is even that a layer above the tree and the rules?
  2. What ships separately, and what is the dependency rule between them? Goal: Math OS — a ten-year vision for AngouriMath as an open mathematical reasoning platform #746's second architectural rule is that no layer reaches around the layer below. A package split makes that mechanically checkable rather than aspirational, which is most of the value.
  3. What is the cost, stated honestly? Goal: Math OS — a ten-year vision for AngouriMath as an open mathematical reasoning platform #746 states it: "every boundary widens the version matrix, the CI time and the number of ways a user can assemble something we never tested, so a split earns its place only where the boundary is load-bearing." A document that lists benefits and not that is not the document.
  4. How does this interact with trimming? If the answer to "the common case pays for nothing it does not use" is a trimmer rather than a package boundary, that is a legitimate answer and a much cheaper one — but it is currently unavailable, because there is no PublishTrimmed, IsTrimmable or IsAotCompatible anywhere in the tree and the compilation path still resolves methods by string at run time (AOT-supported Linq compilation #363). Settling that may change the answer here, so the two want deciding together.
  5. What does a knowledge package look like? Goal: Math OS — a ten-year vision for AngouriMath as an open mathematical reasoning platform #746 tier 9 needs statically declared contents rather than assembly scanning. Whatever boundary is chosen now is the one that shape has to fit through.

Acceptance criteria

  • A written document — in Sources/AngouriMath/Docs/Contributing/, beside CanonicalForm.md and SimplificationContract.md, which are the precedent for a decision written down and checkable — naming, for every top-level area of the kernel, whether it stays or moves, and why.
  • A stated dependency rule between packages, and a way to fail a build that violates it.
  • The cost side written out: how many packages, what the version matrix becomes, what CI time it adds.
  • An explicit answer on whether trimming makes some of the split unnecessary.
  • No code. If the document concludes that the current single kernel is right and the boundary should not move, that is a successful outcome and closes the item.

Related

Raised originally by @darkfader in the #746 thread, and named there as a precondition rather than a task.

Activity

  1. added
    Opinions wantedWe are interested in your opinion about the topic
    Design documentFor issues representing detailed design of new API or feature
    on Aug 23, 2026
  2. Rafael-SOWNet commented on Sep 5, 2026

    @Rafael-SOWNet
    MemberAuthor

    The document this asks for exists. Docs/Contributing/Packaging.md (#1023), plus
    NodeContract.md (#1040) and Trimming.md. Every acceptance criterion here is met except one — a
    way to fail a build that violates the dependency rule.
    I would close this and open one small issue
    for that gate.

    Re-measuring the central claim rather than quoting it

    Trimmed self-contained linux-x64, TrimMode=full:

    app trimmed AngouriMath.dll
    untrimmed 1,449,472 B
    parse only 1,021,440 B
    parse + Simplify 1,021,440 B (137 bytes differ — header and MVID)
    AotSmokeTest (44 checks over parse, Simplify, Solve, Differentiate, Integrate, Limit, Compile) 1,177,600 B

    The whole spread between the narrowest and the broadest use of the library is 156,160 B — 10.8% of
    the assembly
    , against 8.4% at 2.3.0. Adding Simplify to a parse-only app changes the trimmed size
    by zero bytes: parsing already drags in the whole simplifier.

    So no boundary should move on size grounds, and I would move none. §4's rule holds.

    The kernel has grown since the boundary was decided — 211 files / 53,665 lines → 234 / 68,683 (+28%),
    Core/Transformations 2,899 → 10,138, the shipped net10.0 assembly 1,184,256 → 1,449,472 B (+22.4%) —
    and that changes nothing here. Large and inert is exactly the case §4 permits.

    Two things have drifted

    The recorded dependency list is already stale. GetReferencedAssemblies() is now 14, not 13:
    System.Text.Json arrived with Core/Serialization. The NuGet groups are unchanged, so nothing
    reached a consumer's restore — but this is precisely the change §7's gate was proposed to catch, and
    nothing caught it. There is no such test, no NetArchTest, no Directory.Packages.props. That gate
    is the one piece of work I would do
    , and it is small.

    Domain packages are blocked by more than #1026 records. Eight non-public abstract members now, not
    five: the original five plus StringizeNode, LatexizeNode (#1047) and Set.SpecialSet.ToDomain.
    NodeContract.md decides this, but the decision is unimplemented — every one is still internal or
    private protected. Moving the LaTeX printer or the SymPy export out is impossible until it ships.

    One thing has been fixed: EverythingBuild.yml now builds the Terminal, so §7's gap there is closed.

    MathS.ExperimentalFeatures — 191 lines, in the kernel under a pinned AssemblyVersion — remains the
    only move that buys anything, and it is a judgement rather than a measurement.

    Where the evidence does not settle it

    Restore and download time, the Blazor WebAssembly payload, and whether the ~11% spread survives an
    e-graph landing. Also worth saying plainly: this issue has no comments and neither does #783, so no
    consumer has asked for a subset build. The demand side is unmeasured, not absent.

  3. Rafael-SOWNet commented on Sep 5, 2026

    @Rafael-SOWNet
    MemberAuthor

    Closing as answered. Docs/Contributing/Packaging.md (#1023) is the document this asked for, with NodeContract.md and Trimming.md beside it, and every acceptance criterion is met except one — a way to fail a build that violates the dependency rule.

    Re-measured before closing rather than quoting: the whole trimmed-size spread between the narrowest and broadest use of the library is 10.8% of the assembly, and adding Simplify to a parse-only app costs zero bytes. So no boundary should move, which is the substantive answer.

    The missing gate is worth having on its own — the recorded dependency list has already drifted from 13 assemblies to 14 with nothing noticing — and I am building it rather than leaving it filed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Design documentFor issues representing detailed design of new API or featureOpinions wantedWe are interested in your opinion about the topic

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions