Skip to content

docs: each piecewise method has a page showing what it expands to - #578

Merged
FBumann merged 3 commits into
claude/mathspec-piecewise-api-7j0wptfrom
docs/piecewise-ladder
Sep 20, 2026
Merged

FBumann merged 3 commits into
claude/mathspec-piecewise-api-7j0wptfrom
docs/piecewise-ladder

Conversation

@FBumann

@FBumann FBumann commented Sep 19, 2026 •

Copy link
Copy Markdown
Contributor

Prompt: "THe lpspec (and mathspec?) Prs should add multiple different piecewise examples with increasing complexity. And also show how they are encoded...?"

and, on the second commit: "Do the sidecar fix"

Note

The following content was generated by AI.

What this changes

piecewise: expands into plain variables and constraints before anything builds. The reference page says so in prose, with nothing to look at: the four models under examples/ had no gallery page at all, so the one thing a reader wants — what the block becomes — was printed nowhere.

Four pages fix that, and they are one model with method: changed, so the diff between them is the encoding and nothing else:

page what it emits
a curve by convex combination λ; convexity, and one row per link
a curve that is not convex and z, a binary per segment; and the pick and adjacency rows
a curve as a special-ordered set the binaries and their two rows gone, a declaration in their place
a curve as segment lines no auxiliary variable at all; a chord row per segment, and two domain rows

docs/examples/index.md carries the reading order, one bullet per page saying what that method adds. The Read the Docs preview on this PR renders all four.

One new model. adjacency is the default method and nothing under examples/ used it — so the rung that costs the most, the binaries, was the rung with no example. examples/piecewise_adjacency.yaml is that model. The other three are piecewise.yaml, sos.yaml and piecewise_lp.yaml unchanged; they already differed only in method: and their descriptions, which is what makes the comparison honest.

Second commit: the pages print from their own symbol tables

tools/gallery.py passed each model's symbol table in declared_block and not in model_block, so every page in MODELS mode rendered identifiers where a table existed saying otherwise:

was   dispatch = Σ_b  cost_curve_lam_{t,g,b} · bp_x_{g,b}
now   dispatch = Σ_b  λ_{t,g,b} · x_{g,b}

examples/symbols/piecewise.yaml exists to say exactly this, and its own comment gives the reason: a weight named after the block that declared it is "right in the file and unreadable in an equation that names it six times". The new examples/symbols/piecewise_adjacency.yaml is that table plus the segment binary, so the adjacency row reads λ_b ≤ z_b + z_{b−1}.

dispatch.md moves with it, and it is the same correction — it has carried a symbol table since it was written and has never printed from it. It now reads Σ_g dispatch_{s,g} = ℓ_s rather than Σ_g dispatch_{t,g} = load_t. commitment.md has no table and is untouched, which is the check that this reaches the models that asked for it and no others.

Why these are model pages, not a tutorial or a how-to

The docs-writing skill settles it in one sentence: "A worked example is neither a tutorial nor a how-to: it teaches no path and names no task, it shows that the language says a model."

A tutorial is "one path… It explains nothing and offers no choice: a choice is a how-to leaking in" — and a method ladder is nothing but choice. A how-to "names the goal", and "show me how a curve is encoded" is not a task anyone arrives with. What these are is named directly: "A model page is reference in its own form" — a paragraph of the page's own, then the file verbatim and the math the typesetter prints, between the generator's markers, in the Reference section.

The reading order by increasing complexity lives in the hand-written catalogue, which is where the skill puts it.

Rebased onto main at bda1fc5

Merged, not replayed: the hard rule here is never to force-push. main came
in at the bottom of the stack (#494) and was carried up through every branch
between, so this one's base is current.

Clean at this level: no conflict, and the suite passes unchanged.

The 5 failures this body reported were ModuleNotFoundError: mkdocs in the
gate environment, not the branch. With the docs plugins installed the suite is
1440 passed, 6 skipped, with no failures.

Gates
gate result
pytest 1440 passed, 6 skipped (#569: 1432 passed, 6 skipped)
python -m tools.gallery --check 13 pages current
ruff check, ruff format --check clean
prettier --check on the hand-written files clean
docs-build --strict, compile-tex, reuse lint not run here — CI ran all three green on c7b136f

The 5 failures reported earlier were the gate environment, not this branch — ModuleNotFoundError: mkdocs in docs/static/hooks.py. With the docs plugins installed the suite is green.

Gates ran through the math-spec source on Python 3.12 rather than pixi, which this environment's egress proxy will not install — a departure from the pixi run default. The three gates this environment cannot install all passed in CI on the first commit; the second adds one file, an MIT-headered sidecar beside eleven others.

Prose measured per the skill, counting only the hand-written part above each generator marker: medians 10, 14, 14 and 17 words, none over 25. index.md keeps one 27-word bullet, which is list-shaped.

What this deliberately leaves

This is rungs 1–4 of a longer ladder, and they are the ones that change the encoding. The rungs that change what the block can say are separate and not here: a bounded link, ragged curves under points:, activity:, where:, into: alone, and the by/over/into refinement that piecewise_coupling.yaml already demonstrates. That model also still has no page.

Stacked on #569, because sos.yaml and the reference page it links both take that branch's along: spelling.

🤖 Generated with Claude Code

https://claude.ai/code/session_01Hh3uK8SqVcXKuLnYHAjrVW


Generated by Claude Code

…one model

`piecewise:` expands into plain variables and constraints before anything
builds, and the reference page said so in prose with nothing to look at. The
four examples that exist had no gallery page at all, so the one thing a reader
wants to see — what the block becomes — was printed nowhere.

The four pages are one model with the method changed, so the diff between them
is the encoding and nothing else:

| page | what it emits |
| --- | --- |
| a curve by convex combination | `cost_curve_lam`; convexity, and one row per link |
| a curve that is not convex | and `cost_curve_seg`, a binary per segment; and the pick and adjacency rows |
| a curve as a special-ordered set | the binaries and their two rows gone, a declaration in their place |
| a curve as segment lines | no auxiliary variable at all; a chord row per segment, and two domain rows |

`examples/piecewise_adjacency.yaml` is the one new model. `adjacency` is the
default method and nothing under `examples/` used it, so the rung that costs
the most — the binaries — was the rung with no example.

The other three models are `piecewise.yaml`, `sos.yaml` and `piecewise_lp.yaml`
unchanged. They already differed from each other only in `method:` and their
descriptions, which is what makes the comparison honest.

Every block is written by `tools/gallery.py` in `MODELS` mode: the file
verbatim, then the document the typesetter prints from it. The pages join
`.prettierignore` for the reason the ones above them are there, and
`docs/examples/index.md` carries the reading order, one bullet per page saying
what that method adds.

Prose measured per the docs-writing skill, counting only the hand-written part
above each generator marker: medians 10, 14, 14 and 17 words, none over 25.
`index.md` keeps one 27-word bullet, which is list-shaped.

Ran `pytest` (1391 passed, 5 failed, 20 skipped) and `python -m tools.gallery
--check` (13 pages current). The 5 failures are `ModuleNotFoundError: mkdocs`
in `docs/static/hooks.py`, identical on the base commit, which reports 1387
passed and the same 5 — so this adds 4 passing tests and no failure. `ruff
check` and `ruff format --check` clean on `tools/gallery.py`; `prettier
--check` clean on `docs/examples/index.md` and `mkdocs.yml`.

Not run: `docs-build --strict` and `compile-tex`, neither of which this
environment can install, and `reuse lint`. The new pages carry the CC-BY-4.0
header the other pages use and the new model the MIT one, but nothing here
checked them.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Hh3uK8SqVcXKuLnYHAjrVW
…t reads as lambda

`tools/gallery.py` passed each model's symbol table in `declared_block` and not
in `model_block`, so every page in `MODELS` mode rendered its identifiers
instead. The four pages added in the commit before this one are the ones where
it costs most: `examples/symbols/piecewise.yaml` exists to say exactly this, and
its own comment says why.

    was   dispatch = sum_b cost_curve_lam_{t,g,b} * bp_x_{g,b}
    now   dispatch = sum_b lambda_{t,g,b} * x_{g,b}

`examples/symbols/piecewise_adjacency.yaml` is new, the table `piecewise.yaml`
carries plus the segment binary this method adds, so the adjacency row reads
`lambda_b <= z_b + z_{b-1}` rather than naming two emitted variables in full.

`dispatch.md` moves with it, and it is the same correction: it has carried a
symbol table since it was written and has never printed from it. The page now
reads `sum_g dispatch_{s,g} = l_s` rather than `sum_g dispatch_{t,g} =
load_t`, and the sidecar renames the index too. `commitment.md` has no table
and is untouched, which is the check that this reaches models that asked for it
and no others.

The legend's closing sentence — upright is given, italic is chosen — drops from
a page under a table, because a table that writes a parameter as `\bar p`
breaks the convention that sentence states. The typesetter already handled
this; nothing here changed it.

Ran `pytest` (1391 passed, 5 failed, 20 skipped — the same `ModuleNotFoundError:
mkdocs` five as before, identical on the base) and `python -m tools.gallery
--check` (13 pages current). `ruff check`, `ruff format --check` and `prettier
--check` clean.

Not run: `docs-build --strict`, `compile-tex` and `reuse lint`, which this
environment cannot install. CI ran all three green on the commit before this
one, and this commit adds one file, an MIT-headered sidecar beside eleven
others.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Hh3uK8SqVcXKuLnYHAjrVW

FBumann commented Sep 19, 2026

Copy link
Copy Markdown
Contributor Author

Note

The following content was generated by AI.

docs/readthedocs.org:math-spec failed on 7500014. I cannot read its log from this environment, so here is what I established and what I need.

Two independent runs of the same build command pass on that exact commit.

run result
this repo's CI workflow on 7500014 — lint, test, docs-build --strict, compile-tex success
mkdocs build --strict locally on the same tree success, 0 warnings, 0 errors

The local run needed one change to get going: the single inventories: https://docs.python.org/3/objects.inv line dropped, because this environment's egress proxy answers it with a 403. That edit was local only and is not in the branch — mkdocs.yml is unmodified in the diff. With it gone the build is clean, so nothing on the five changed pages is a dead link, a stale anchor or a missing nav entry.

Read the Docs is not broadly down. It succeeded on #568 at 22:42, thirty minutes before this failure, and on this PR's own previous commit c7b136f at 22:32. So I am not claiming infrastructure on the evidence of timing alone.

What I could not check. Both app.readthedocs.org and math-spec--578.org.readthedocs.build are blocked by the egress proxy here, so the build log and the preview are equally unreadable to me.

The one step Read the Docs does that CI does not is in .readthedocs.yml: asdf install pixi latest on every build, then pixi install -e default --frozen. That resolves a fresh pixi against a committed lockfile and is the part of the pipeline that can fail with every page correct. I offer that as the first place to look, not as a diagnosis — I have not seen the log.

No re-run. I have no means to trigger a Read the Docs rebuild, and kicking it with an empty commit is not something I will do.

What would settle it: the build log from https://app.readthedocs.org/projects/math-spec/builds/34654519/. If it names a page, a link or an anchor, it is mine and I will fix it. If it dies in create_environment or pixi install, it is not, and a later commit will clear it on its own.

Keeping this PR watched until it is green.


Generated by Claude Code

@FBumann FBumann changed the title docs: four pages show what each piecewise method expands to, against one model docs: each piecewise method has a page showing what it expands to Sep 19, 2026
Carries origin/main up the stack of #494.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DUyQztqnwapp3vHPhzBLw5
@FBumann
FBumann removed this pull request from stack #575 September 20, 2026 20:34
@FBumann
FBumann marked this pull request as ready for review September 20, 2026 20:34
@FBumann
FBumann merged commit 22a36be into claude/mathspec-piecewise-api-7j0wpt Sep 20, 2026
6 checks passed
@FBumann FBumann added the docs Documentation pages, guides, reference and README label Sep 24, 2026 — with Claude
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

docs Documentation pages, guides, reference and README

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants