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.
Summary
$docCellContextDefaultmaps"Tech Note"and"Tutorial"toCellContext -> CellGroup, the same asSymbolandGuide. 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 -> CellGroupeach 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## Definitionunder the defaultAutomatic), and bakes the threaded results into the output cells. ButCellContext -> CellGroupthen 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(at486a861):setDocMetadata(MarkdownToNotebook.wl:3707) reads this default at line 3723 and emitsCellContext -> ccon the notebook unlesscc === Automatic. TheTutorialbuilder keeps theCellGroupentry on purpose (comment atMarkdownToNotebook.wl:4170).Minimal reproduction
Two sections: A defines
x, B uses it.EvaluateSeparator -> Nonethreads state at build time, so section B's output cell is baked as11. The notebook is stampedCellContext -> CellGroup, so a reader who re-evaluates section B in the front end runs in a private cell-group context that never sawx = 1and gets10 + 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:ibm = ServiceConnect["IBMQuantumPlatform", ...], and a later-section cellibm["Backends"]returned the unevaluatedibm[Backends]when the notebook was evaluated, becauseibmwas undefined in the later private context.ps/tn/netare reused across sections.Uis defined in one section and used in the next.The workaround shipped in all three was to add
CellContext: Globalplus a backtick to the technote frontmatter, which MTN honors, emittingCellContext -> "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.mdframes 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" (## Definitionpreservation andEvaluateSeparator); the tech-note skill calls a Tech Note "free-flowing prose and code, like a tutorial" with "no fixed sections" and points authors toEvaluateSeparator"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 atCellGroup(per-example self-containment stays correct there).Two shared-context settings work:
Automatic: emit noCellContextoption, so the notebook inherits the front end default"Global"`, one shared context.Notebook: a single notebook-private shared context.Automaticis the better default. The native DocumentationTools tutorial and tech-note base templates carry no notebook-levelCellContextoption, 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 frontmatterCellContextoverride from #19 stays fully working, so an author can still pinNotebook,Global`, or any explicit context.