Skip to content

TechNote/Tutorial default CellContext -> CellGroup breaks cross-section symbol flow when evaluated #97

Description

@mbahram

Summary

$docCellContextDefault maps "Tech Note" and "Tutorial" to CellContext -> CellGroup, the same as Symbol and Guide. For the reference pages that is right and was the point of #19: each example is a self-contained unit, and giving every cell group its own private context keeps one example's temporary bindings from leaking into another.

Applied to a Tech Note or Tutorial it breaks the page. A tutorial is narrative, not a reference page: a symbol defined in one section is reused in a later section. Under CellContext -> CellGroup each cell group evaluates in its own private context, so when a reader evaluates a later section it runs in a different context, never sees the earlier symbol, and the cell whose build-time output was a value re-evaluates to an unevaluated expression.

This also makes the built notebook internally inconsistent. MTN evaluates a tutorial's cells in document order, threading state (EvaluateSeparator -> None, or a symbol preserved from ## Definition under the default Automatic), and bakes the threaded results into the output cells. But CellContext -> CellGroup then stops a reader from reproducing those baked outputs, because the reader's later section runs in a context that never saw the earlier binding.

Location

MarkdownToNotebook.wl:3692 (at 486a861):

$docCellContextDefault = <|"Symbol" -> CellGroup, "Guide" -> CellGroup, "Tech Note" -> CellGroup, "Tutorial" -> CellGroup,
    "Format" -> CellGroup, "Service Connection" -> CellGroup, ... |>

setDocMetadata (MarkdownToNotebook.wl:3707) reads this default at line 3723 and emits CellContext -> cc on the notebook unless cc === Automatic. The Tutorial builder keeps the CellGroup entry on purpose (comment at MarkdownToNotebook.wl:4170).

Minimal reproduction

Two sections: A defines x, B uses it.

nb = MarkdownToNotebook[
  "---\nTemplate: TechNote\nName: T\nContext: Global`\nPaclet: X/Y\nURI: X/Y/tutorial/T\n---\n\n## A\n\n```wl\nx = 1\n```\n\n## B\n\n```wl\nx + 10\n```",
  "EvaluateSeparator" -> None];

Cases[nb[[2 ;;]], HoldPattern[CellContext -> v_] :> v, Infinity, Heads -> True]
(* {CellGroup} *)

EvaluateSeparator -> None threads state at build time, so section B's output cell is baked as 11. The notebook is stamped CellContext -> CellGroup, so a reader who re-evaluates section B in the front end runs in a private cell-group context that never saw x = 1 and gets 10 + x. The displayed output (11) and the reader's re-evaluation (10 + x) disagree.

Real-world impact

Three Wolfram/QuantumFramework technotes (Template: TechNote) hit this:

  • "Sending Queries to IBM QPUs": one cell defines ibm = ServiceConnect["IBMQuantumPlatform", ...], and a later-section cell ibm["Backends"] returned the unevaluated ibm[Backends] when the notebook was evaluated, because ibm was undefined in the later private context.
  • QuantumMachineLearning: ps / tn / net are reused across sections.
  • TimeEvolution: the Liouvillian propagator U is defined in one section and used in the next.

The workaround shipped in all three was to add CellContext: Global plus a backtick to the technote frontmatter, which MTN honors, emitting CellContext -> "Global"` so every cell shares one context. Needing a manual per-page workaround for the default narrative behavior, independently in three pages, is the signal that the default is wrong for these types.

Relation to #19

#19 set this default deliberately and its migration note anticipated that "any that currently rely on shared example state across units will break". The reasoning there was the reference-page convention ("Stepping through a reference page", "shipped WFR reference pages carry CellContext -> CellGroup"), and the breakage was accepted as "the reference-page unit-isolation convention anyway".

That convention does not govern a Tech Note or Tutorial. The project's own docs describe these as narrative: docs/doc-pages.md frames cell-group isolation as "right for a reference page: each section reads as a self-contained block", and documents the opposite for tutorials under "State across sections" (## Definition preservation and EvaluateSeparator); the tech-note skill calls a Tech Note "free-flowing prose and code, like a tutorial" with "no fixed sections" and points authors to EvaluateSeparator "for state-threading multi-part tutorials". So #19's default is correct for the reference templates it was reasoned about, and over-applied to the narrative ones.

Proposed fix

Default "Tech Note" and "Tutorial" to a shared context, and leave "Symbol", "Guide", and the reference subtypes at CellGroup (per-example self-containment stays correct there).

Two shared-context settings work:

  • Automatic: emit no CellContext option, so the notebook inherits the front end default "Global"`, one shared context.
  • Notebook: a single notebook-private shared context.

Automatic is the better default. The native DocumentationTools tutorial and tech-note base templates carry no notebook-level CellContext option, so inheriting the "Global"default is exactly what a hand-authored tutorial does, and it reproduces the validatedCellContext: Globalworkaround without hardcoding a context string.setDocMetadataalready treatsAutomaticas "emit nothing", so the change is"Tech Note" -> Automatic, "Tutorial" -> Automaticin$docCellContextDefault. The frontmatter CellContextoverride from #19 stays fully working, so an author can still pinNotebook, Global`, or any explicit context.

Activity

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

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions