Skip to content

Book pages carry the first commit's facts; a statement's address first paints its trail - #806

Open
Deicyde wants to merge 2 commits into
mainfrom
feat/first-commit-facts
Open

Deicyde wants to merge 2 commits into
mainfrom
feat/first-commit-facts

Conversation

@Deicyde

@Deicyde Deicyde commented Nov 13, 2026 •

Copy link
Copy Markdown
Contributor

Part of #636: C3a of the six PRs. Book pages now carry what the explorer's first commit reads from the search catalogue, and a statement's address first paints its own trail.

Premise

  • User: a reader who opens a book page at a statement's address, such as topic/index.html#theorem; and C3b, which will make the first commit from the loaded page instead of waiting for the catalogue.
  • Problem: at a statement's address, the frame painted the topic page's trail, and the first commit then linked the topic's crumb and added the statement's title, so the trail moved as the book took over. It is the third of Explorer: open a page in the book's layout, not Material's #712's known differences. The first commit also takes three facts only from the catalogue (whether the page's place is a topic, whether a card is a result, and the statement's trail), so it can't start from the page until the page holds them.
  • Replaces: the topic page's trail as the first paint at a statement's address.
  • Deletes: nothing yet; C3b's commit reads these marks instead of the catalogue's rows. Size: +274/−40 in 7 files (code +98/−36, tests +168/−4, CHANGELOG +8).

What changes

  • autoform_cli/ui/graph_pages.py: is_result() is the search index's result rule (formalizable, not a catalog card, not a container, not on a source track), now shared with render.
  • autoform_cli/ui/render.py:
    • _render_environment marks a result's card (.bp-thmwrapper) with data-autoform-result, through is_result(). A card is never a container.
    • _integrated_page marks the reading source with data-autoform-topic when the page's place, its owner or else its scope, is a topic as the explorer's applyRoute reads one: its own scope, not a source track, not a module catalog. No result owns a page (render gives an anchorless page only to a container or to a node that is neither formalizable nor a catalog), so there is no owner result mark, and a test pins that.
    • render_site passes each page's cards to _first_paint, which adds, for a page with cards, the statement trail: the crumbs the first commit draws when a card is the route's node, with the topic linked, then each card's reading label. Its docstring now says "a page in a topic".
  • autoform_cli/ui/dag_viewer.py: render_boot writes that trail into the frame's breadcrumb as one <template data-boot-statements>: the shared crumbs, then an <li data-anchor aria-current="page"> per card. The boot script compares the address with each card's anchor as the browser normalizes a fragment (new URL("#" + anchor, location.href).hash === location.hash), as the router compares routes, and on a match puts the shared crumbs and that card's item in the trail. Template content is inert (not typeset, not in the page's text), and the frame was already left out of search.
  • Tests:
    • tests/ui/test_integrated_publication.py: on a fixture with a group page, a library catalog and a note, each page with cards holds the trail the commit draws, with the topic crumb linked and one item per card, and a page without cards holds none. The topic marks follow applyRoute's rule, the result marks equal the search index's result, and no reading source names a result.
    • tests/ui/test_explorer_shell_boot.py: the boot script and the router read the same addresses: a non-ASCII anchor typed raw or percent-encoded (café, caf%C3%A9), a space (a b, a%20b), a bare % (100%, and 100%25, which names nothing), a percent-encoded ASCII letter (ma%69n), and a section that is not a card. Both pick the same card, or none.
    • tests/ui/test_dag_viewer_browser.py: in WebKit, with the explorer's script held, a card's address first paints four crumbs, three of them links and the statement current; after the commit, the trail and the rest of the head are the same, box for box within 1 px. It runs for a card whose label holds a formula and one whose label holds &, < and quotes.
  • CHANGELOG.md: a Fixed line.

Cost

ATLAS, rendered and built before and after on scratch CI: HTML grows from 552.5 MB to 562.7 MB (+1.84%), gzipped HTML by 2.09%, and the whole site by 1.36%. 3,708 pages carry a statement trail, with 45,847 card items; 4,004 reading sources are topics, and 45,847 cards are results. check_blueprint_site.py passes on the new site. https://github.com/Deicyde/atlas-lean/actions/runs/43456932487

Not here

  • C3b makes the first commit from the page, reading these marks. Three first-paint differences go with it, each as its own fix with a parity test: a page in a topic opened at a section fragment loses its own crumb and its "← topic" row at the commit (the fourth of Explorer: open a page in the book's layout, not Material's #712's differences: selection() keys routes by the whole address); the frame shows a topic page's "← topic" row for any :target inside a card, such as a notes heading, where the commit shows it only for the card's own anchor; and a book with no roadmap README.md first paints the trail [Home], where the commit draws [Home, Book, Roadmap].
  • A legacy #node= address still first paints the page's trail; the commit draws the statement's, as on main.
  • Phones: the boot script drops the frame on a phone, so none of this reaches a phone yet.

Checks

  • Tests for the new behavior and a CHANGELOG line; no doc describes the first paint's trail.
  • make lint and make test pass on this PR's CI at 0b2305a, every job green, WebKit included: https://github.com/facebookresearch/autoform-bot/actions/runs/43466991946
  • Five boot-script mutants each fail the agreement test on its own assertion: comparing the raw anchor (fails on café), comparing the decoded address (on 100%), no swap, the statement without the topic's crumbs, and any fragment naming the first card (on café).

Posted by Claude Code, at Jack's request.

@meta-cla meta-cla Bot added the CLA Signed This label is managed by the Meta Open Source bot. label Nov 13, 2026
…ts its trail

Render now writes what the book's first commit reads from the search index, so
a later commit can start from the loaded page (#636 C3a):

- the reading marks a page whose place, its owner or else its scope, is a
  topic, as applyRoute reads one (data-autoform-topic);
- each result's card is marked as the index marks it (data-autoform-result),
  through one helper both use;
- a page with statement cards carries, in its frame, the trail the book draws
  on an address naming one of them, and the boot script puts it in there,
  matching cards as the router's routes do, by URL-normalised fragment.

No result owns a page, and a test pins it. The _first_paint docstring says "a
page in a topic", per the Lead's correction.
@Deicyde

Deicyde commented Nov 13, 2026

Copy link
Copy Markdown
Contributor Author

No blockers at 0b2305a.

I checked the four places where the first paint has to agree with the router:

  • _first_paint's topics walk gives routeTrail's crumbs on every page kind I rendered: 12 card addresses across a transparent group, a source track, a collection, a topic under a collection, top-level statements, and non-ASCII and formula titles.
  • is_result matches the index's result on every row.
  • The ATLAS size figures in the body match its run 43456932487. That run measured f86180f, which differs from this head only in CHANGELOG.md.
  • The boot script's fragment match finds the same card as the router, with one exception, below.

Shared anchors (nit, older cause). When g/a/ has no README, _anchor gives g/a-b and g/a/b the same anchor, a-b, and both cards land on one page. The boot script takes the first matching li[data-anchor] (dag_viewer.py#L170). The router's byRoute keeps the last row for a route (blueprint-navigation.js#L292). So the first paint names one card and the first commit names the other. The page already holds two id="a-b", and the commit already highlights one card while its trail names the other. A follow-up at _anchor would fix both: make anchors unique per page, or warn on a collision.

Smaller notes:

  • No test fails if html.escape is dropped from data-anchor: every tested anchor is plain ASCII, and the node test builds its template by hand. No test fails either if the topic mark loses its catalog != "module" clause, since no fixture page has a module catalog as its place.
  • The WebKit parity test covers only the module topic remote/. Neither it nor the literal lists pin collection pages, topics under a collection, or top-level statements on roadmap/README.md. Those agree today.
  • CHANGELOG.md conflicts with current main. render.py merges cleanly and keeps the change.

Posted by Claude Code, at Jack's request.

Catch up with main ce0c81c; CHANGELOG keeps both sides' entries.
@Deicyde
Deicyde marked this pull request as ready for review November 13, 2026 23:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CLA Signed This label is managed by the Meta Open Source bot.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant