explico 0.8.0 → 0.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +1239 -1
- package/README.md +60 -15
- package/dist/compiler/astro.d.ts +6 -1
- package/dist/compiler/cli.d.ts +46 -2
- package/dist/compiler/cli.js +70 -4
- package/dist/compiler/collections.d.ts +35 -2
- package/dist/compiler/collections.js +68 -5
- package/dist/compiler/course-config.d.ts +3 -194
- package/dist/compiler/course-config.js +78 -5
- package/dist/compiler/exports/standalone-html.d.ts +6 -1
- package/dist/compiler/knowledge-version.js +1 -1
- package/dist/compiler/lesson-derivation.d.ts +27 -10
- package/dist/compiler/lesson-derivation.js +23 -8
- package/dist/compiler/logging.d.ts +4 -1
- package/dist/compiler/logging.js +4 -1
- package/dist/compiler/manifest.d.ts +204 -31
- package/dist/compiler/manifest.js +270 -55
- package/dist/compiler/resolution-report.d.ts +6 -1
- package/dist/course-config-Dsnri9Tk.d.ts +464 -0
- package/dist/reference/base-accents.d.mts +26 -0
- package/dist/reference/base-accents.mjs +31 -0
- package/dist/reference/base-roman-labels.d.mts +2 -2
- package/dist/reference/base-roman-labels.mjs +2 -2
- package/dist/reference/consistency.d.ts +14 -2
- package/dist/reference/consistency.js +108 -4
- package/dist/reference/delimiter-size.d.ts +3 -2
- package/dist/reference/diagrams-validate.d.ts +7 -2
- package/dist/reference/diagrams-validate.js +9 -1
- package/dist/reference/equations-validate.d.ts +8 -5
- package/dist/reference/equations-validate.js +1 -0
- package/dist/reference/equations.d.mts +60 -31
- package/dist/reference/equations.mjs +83 -43
- package/dist/reference/examples-validate.d.ts +31 -0
- package/dist/reference/examples-validate.js +48 -0
- package/dist/reference/figures-validate.d.ts +1 -1
- package/dist/reference/figures-validate.js +4 -1
- package/dist/reference/folds-validate.d.ts +33 -0
- package/dist/reference/folds-validate.js +32 -0
- package/dist/reference/gate-abbreviations.d.ts +3 -1
- package/dist/reference/gate-abbreviations.js +1 -0
- package/dist/reference/gate-course-rules.d.ts +32 -0
- package/dist/reference/gate-course-rules.js +85 -0
- package/dist/reference/gate-heading-length.d.ts +5 -2
- package/dist/reference/gate-heading-length.js +45 -21
- package/dist/reference/gate-heading-structure.d.ts +41 -0
- package/dist/reference/gate-heading-structure.js +113 -0
- package/dist/reference/gate-math-punctuation.d.ts +71 -0
- package/dist/reference/gate-math-punctuation.js +251 -0
- package/dist/reference/gate-math.d.ts +22 -6
- package/dist/reference/gate-math.js +42 -8
- package/dist/reference/gate-part-pages.d.ts +50 -0
- package/dist/reference/gate-part-pages.js +118 -0
- package/dist/reference/gate-prose-notation.d.ts +21 -11
- package/dist/reference/gate-prose-notation.js +25 -7
- package/dist/reference/katex-delimiters.mjs +20 -7
- package/dist/reference/keyed-float-validate.d.ts +27 -10
- package/dist/reference/keyed-float-validate.js +15 -1
- package/dist/reference/keyed-jsx-floats.d.mts +11 -5
- package/dist/reference/keyed-jsx-floats.mjs +73 -20
- package/dist/reference/knowledge-checks-validate.d.ts +1 -1
- package/dist/reference/knowledge-checks.d.mts +3 -1
- package/dist/reference/knowledge-checks.mjs +9 -4
- package/dist/reference/lab-math-scope.d.ts +1 -0
- package/dist/reference/lab-math-slot.d.ts +34 -0
- package/dist/reference/lab-math-slot.js +6 -0
- package/dist/reference/math-glyphs.d.mts +80 -4
- package/dist/reference/math-glyphs.mjs +572 -37
- package/dist/reference/page-notation.d.ts +6 -1
- package/dist/reference/raw-floats-validate.js +1 -1
- package/dist/reference/raw-floats.mjs +1 -1
- package/dist/reference/rehype-heading-anchors.d.mts +14 -0
- package/dist/reference/rehype-heading-anchors.mjs +116 -17
- package/dist/reference/rehype-table-header-labels.d.mts +6 -1
- package/dist/reference/rehype-table-header-labels.mjs +21 -3
- package/dist/reference/remark-asides.d.mts +3 -0
- package/dist/reference/remark-asides.mjs +180 -0
- package/dist/reference/remark-memo.d.mts +3 -1
- package/dist/reference/remark-memo.mjs +42 -11
- package/dist/reference/remark-notation.d.mts +60 -10
- package/dist/reference/remark-notation.mjs +387 -36
- package/dist/reference/render-lab-math.d.ts +4 -26
- package/dist/reference/render-lab-math.js +4 -4
- package/dist/reference/sections-validate.d.ts +27 -0
- package/dist/reference/sections-validate.js +41 -0
- package/dist/reference/sections.d.mts +97 -0
- package/dist/reference/sections.mjs +306 -0
- package/dist/reference/tables-validate.d.ts +1 -1
- package/dist/reference/types.d.ts +17 -1
- package/dist/reference/unit-words.d.ts +37 -0
- package/dist/reference/unit-words.js +170 -0
- package/dist/rules/catalog.d.ts +176 -0
- package/dist/rules/catalog.js +983 -0
- package/dist/rules/course-rules.d.ts +115 -0
- package/dist/rules/course-rules.js +292 -0
- package/dist/rules/course-rules.schema.json +138 -0
- package/dist/rules/in-effect.d.ts +53 -0
- package/dist/rules/in-effect.js +142 -0
- package/dist/rules/rules.schema.json +1072 -0
- package/dist/rules/settings.d.ts +3 -0
- package/dist/rules/settings.js +290 -0
- package/dist/rules/waivers.d.ts +53 -0
- package/dist/rules/waivers.js +132 -0
- package/dist/session/PreferenceStore.d.ts +5 -0
- package/dist/session/PreferenceStore.js +9 -0
- package/docs/VERSIONING.md +2 -2
- package/docs/authoring/README.md +232 -40
- package/docs/authoring/agents.md +55 -9
- package/docs/authoring/components.md +178 -22
- package/docs/authoring/migrating.md +1096 -2
- package/docs/authoring/notation.md +576 -322
- package/docs/authoring/prose.md +551 -0
- package/docs/authoring/retired.md +35 -0
- package/docs/authoring/structure-rules.md +422 -40
- package/docs/authoring/structure.md +445 -62
- package/docs/authoring/versioning.md +20 -28
- package/docs/authoring/visualizations.md +142 -20
- package/package.json +2 -2
- package/src/compiler/cli.ts +116 -6
- package/src/compiler/collections.ts +111 -7
- package/src/compiler/course-config.ts +273 -34
- package/src/compiler/knowledge-version.ts +1 -1
- package/src/compiler/lesson-derivation.ts +54 -15
- package/src/compiler/logging.ts +8 -2
- package/src/compiler/manifest.ts +573 -104
- package/src/components/BlockHeading.astro +113 -0
- package/src/components/CourseContents.astro +221 -0
- package/src/components/CurriculumMap.astro +5 -6
- package/src/components/FloatIndex.astro +200 -0
- package/src/components/HoverPanel.astro +431 -79
- package/src/components/PartBridge.astro +27 -0
- package/src/components/PartOverview.astro +401 -0
- package/src/components/PartScope.astro +27 -0
- package/src/components/abbreviation/AbbreviationLayer.astro +49 -51
- package/src/components/assessments/AssessmentRunner.tsx +8 -5
- package/src/components/assessments/AssessmentSet.astro +23 -26
- package/src/components/block-heading.ts +146 -0
- package/src/components/card-arrow.ts +243 -0
- package/src/components/card-drag.ts +631 -0
- package/src/components/card-jump.ts +45 -0
- package/src/components/card-manager.ts +1589 -0
- package/src/components/card-memory.ts +177 -0
- package/src/components/card-placement.ts +504 -0
- package/src/components/card-side.ts +336 -0
- package/src/components/card-travel.ts +197 -0
- package/src/components/citation/CitationLayer.astro +77 -76
- package/src/components/diagram/Diagram.astro +161 -316
- package/src/components/disclosure/course-disclosure.ts +24 -0
- package/src/components/disclosure/hover-preview.ts +122 -42
- package/src/components/disclosure/persisted-disclosure.ts +3 -3
- package/src/components/disclosure/print-as-shown.ts +252 -0
- package/src/components/examples/CompactExample.astro +3 -1
- package/src/components/examples/CompactExamples.astro +101 -94
- package/src/components/figure/Figure.astro +174 -274
- package/src/components/figure/FloatCaption.astro +87 -0
- package/src/components/figure/figure-state.ts +58 -0
- package/src/components/figure/figure-tools.ts +87 -0
- package/src/components/float-name.ts +101 -0
- package/src/components/fold/Fold.astro +125 -0
- package/src/components/fold/fold-id.ts +40 -0
- package/src/components/memo/Memo.astro +162 -231
- package/src/components/memo/ShortNote.astro +6 -6
- package/src/components/notation/NotationFormula.astro +5 -1
- package/src/components/notation/NotationGlossary.astro +3 -4
- package/src/components/notation/NotationLayer.astro +169 -162
- package/src/components/notation/NotationMath.astro +10 -1
- package/src/components/reference/FloatRefLayer.astro +485 -423
- package/src/components/starlight/AboutPanel.astro +5 -4
- package/src/components/starlight/CollapsibleSections.astro +207 -93
- package/src/components/starlight/DiagramEnhancer.astro +15 -138
- package/src/components/starlight/HeadingAnchorEnhancer.astro +193 -1
- package/src/components/starlight/KeyedFloatEnhancer.astro +100 -9
- package/src/components/starlight/LayoutHeader.astro +298 -19
- package/src/components/starlight/LayoutPageSidebar.astro +99 -12
- package/src/components/starlight/LayoutPageTitle.astro +120 -0
- package/src/components/starlight/LayoutSidebar.astro +229 -11
- package/src/components/starlight/LessonExportActions.astro +53 -72
- package/src/components/starlight/LessonFooter.astro +26 -4
- package/src/components/starlight/section-parts.ts +15 -2
- package/src/components/starlight/section-summary.ts +181 -0
- package/src/components/table/Table.astro +95 -76
- package/src/components/table/TableOverflowExpander.astro +65 -28
- package/src/content-config.ts +40 -4
- package/src/reference/base-accents.mjs +31 -0
- package/src/reference/base-roman-labels.mjs +2 -2
- package/src/reference/consistency.ts +176 -5
- package/src/reference/delimiter-size.ts +3 -2
- package/src/reference/diagrams-validate.ts +17 -1
- package/src/reference/equations-validate.ts +10 -5
- package/src/reference/equations.mjs +83 -43
- package/src/reference/examples-validate.ts +97 -0
- package/src/reference/figures-validate.ts +6 -1
- package/src/reference/folds-validate.ts +65 -0
- package/src/reference/gate-abbreviations.ts +1 -0
- package/src/reference/gate-course-rules.ts +134 -0
- package/src/reference/gate-heading-length.ts +66 -35
- package/src/reference/gate-heading-structure.ts +193 -0
- package/src/reference/gate-math-punctuation.ts +381 -0
- package/src/reference/gate-math.ts +69 -10
- package/src/reference/gate-part-pages.ts +217 -0
- package/src/reference/gate-prose-notation.ts +59 -12
- package/src/reference/katex-delimiters.mjs +20 -7
- package/src/reference/keyed-float-validate.ts +45 -11
- package/src/reference/keyed-jsx-floats.mjs +73 -20
- package/src/reference/knowledge-checks-validate.ts +1 -1
- package/src/reference/knowledge-checks.mjs +9 -4
- package/src/reference/lab-math-slot.ts +36 -0
- package/src/reference/math-glyphs.mjs +572 -37
- package/src/reference/raw-floats-validate.ts +1 -1
- package/src/reference/raw-floats.mjs +1 -1
- package/src/reference/rehype-heading-anchors.mjs +116 -17
- package/src/reference/rehype-table-header-labels.mjs +21 -3
- package/src/reference/remark-asides.mjs +180 -0
- package/src/reference/remark-memo.mjs +42 -11
- package/src/reference/remark-notation.mjs +387 -36
- package/src/reference/render-lab-math.ts +16 -31
- package/src/reference/sections-validate.ts +81 -0
- package/src/reference/sections.mjs +306 -0
- package/src/reference/tables-validate.ts +2 -1
- package/src/reference/types.ts +17 -0
- package/src/reference/unit-words.ts +233 -0
- package/src/rules/catalog.ts +1298 -0
- package/src/rules/course-rules.ts +456 -0
- package/src/rules/in-effect.ts +235 -0
- package/src/rules/settings.ts +448 -0
- package/src/rules/waivers.ts +249 -0
- package/src/session/PreferenceStore.ts +15 -0
- package/src/styles/global.css +1471 -163
- package/src/styles/surfaces.css +182 -0
- package/src/components/hover-panel.ts +0 -339
- package/src/components/popup-stack.ts +0 -345
|
@@ -11,105 +11,100 @@ and "Review-only" mean here, and how to amend a rule.
|
|
|
11
11
|
|
|
12
12
|
---
|
|
13
13
|
|
|
14
|
-
##
|
|
15
|
-
|
|
16
|
-
**The normal distribution is `\mathcal{N}`.**
|
|
17
|
-
|
|
18
|
-
Write a Gaussian as `\mathcal{N}(\mu, \sigma^2)` — calligraphic `N`,
|
|
19
|
-
parameterised by **mean and variance**. Name any other named distribution the
|
|
20
|
-
same way: a calligraphic letter through `\mathcal{…}`.
|
|
21
|
-
|
|
22
|
-
Do not use `N(\mu, \sigma^2)`, `\mathrm{N}`, `Norm(...)`, or `\mathbb{N}` — the
|
|
23
|
-
last is the natural numbers ([N2](#n2)) and a build-reserved token.
|
|
14
|
+
## N2
|
|
24
15
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
16
|
+
**A reserved spelling means only what it is reserved for, and every other styled
|
|
17
|
+
letter is a symbol of its own.**
|
|
18
|
+
|
|
19
|
+
A course keeps a short table of spellings that are fixed to one meaning: nothing
|
|
20
|
+
else may use them. Whether a reserved spelling *also* needs a notation entry is a
|
|
21
|
+
separate question, and rule [N4](#n4)'s gate answers it — reserving a spelling is
|
|
22
|
+
a convention, not an exemption. The shipped table (`rules.N2.reserved` in
|
|
23
|
+
`course.settings.json`) is:
|
|
24
|
+
|
|
25
|
+
| Spelling | Means | Notation entry |
|
|
26
|
+
| --- | --- | --- |
|
|
27
|
+
| `\mathbb{N}`, `\mathbb{Z}`, `\mathbb{R}`, `\mathbb{C}` | the naturals, integers, reals, complexes | not needed — the only four tokens the resolver treats as universal (`IGNORED_MATH_TOKENS`) |
|
|
28
|
+
| `\mathbb{P}` | probability | yes, like any other identifier |
|
|
29
|
+
| `\mathcal{N}(\mu, \sigma^2)` | the normal distribution, by mean and variance | yes |
|
|
30
|
+
| `\mathrm{d}` | the differential | not needed — a `\mathrm{…}` body is skipped whole ([N10](#n10)) |
|
|
31
|
+
|
|
32
|
+
Every _other_ styled letter — `\mathbb{E}`, `\mathbb{Q}`, `\mathbb{1}`,
|
|
33
|
+
`\mathcal{L}`, `\mathbf{v}`, an italic `d` used as a variable — is an ordinary
|
|
34
|
+
symbol that resolves to a notation entry of its own, even when the plain letter
|
|
35
|
+
already has one ([N4](#n4)).
|
|
36
|
+
|
|
37
|
+
_Rationale._ Two facts, one rule. A reserved spelling is genuinely universal, so
|
|
38
|
+
a per-page definition of `\mathbb{R}` would be noise — and reserving it stops a
|
|
39
|
+
second meaning ("`\mathbb{N}` for the sample size") from colliding with the
|
|
40
|
+
first. Everything outside the table is domain-specific and earns a card: a
|
|
41
|
+
styled letter is a different glyph from its plain letter, and a reader who sees
|
|
42
|
+
`\mathbb{E}` hovers it expecting the expectation, not an energy `E`.
|
|
29
43
|
|
|
30
44
|
_How to apply._
|
|
31
45
|
|
|
32
|
-
-
|
|
33
|
-
|
|
46
|
+
- **The number systems** need nothing: write `\mathbb{R}^n`, `x \in \mathbb{Z}`.
|
|
47
|
+
Need the rationals as a set on one lesson? `\mathbb{Q}` is not reserved, so
|
|
48
|
+
give it an entry (or `\explain{...}{\mathbb{Q}}`) and note it in the domain
|
|
49
|
+
vocabulary.
|
|
50
|
+
|
|
51
|
+
- **Probability** is `\mathbb{P}(A)` — never a bare `P` (a price, a power, a
|
|
52
|
+
point), never `\Pr`, never `\text{Prob}`. Conditional probability is
|
|
53
|
+
`\mathbb{P}(A \mid B)`, with `\mid`, not a bare `|` ([N15](#n15)).
|
|
54
|
+
Expectation is the same family, `\mathbb{E}[X]`, and — being outside the
|
|
55
|
+
table — takes an entry:
|
|
34
56
|
|
|
35
57
|
```yaml
|
|
36
|
-
key: prob.
|
|
37
|
-
latex: \
|
|
38
|
-
label:
|
|
39
|
-
meaning:
|
|
58
|
+
key: prob.p
|
|
59
|
+
latex: \mathbb{P}
|
|
60
|
+
label: Probability
|
|
61
|
+
meaning: Probability of an event.
|
|
40
62
|
```
|
|
41
63
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
the
|
|
59
|
-
|
|
64
|
+
Introduce it in prose with `[[prob.p]]` before its first appearance in math
|
|
65
|
+
([N4](#n4)). A course doing measure theory may add `\mathbb{Q}` as the
|
|
66
|
+
risk-neutral measure to its own `reserved` list, and state the split once in
|
|
67
|
+
the domain notes.
|
|
68
|
+
|
|
69
|
+
- **The normal distribution** is `\mathcal{N}(\mu, \sigma^2)` — calligraphic
|
|
70
|
+
`N`, parameterised by mean and variance; not `N(\mu, \sigma^2)`,
|
|
71
|
+
`\mathrm{N}`, `Norm(...)`, or `\mathbb{N}`. Name any other distribution the
|
|
72
|
+
same way, with a calligraphic letter. `\mathcal{N}` needs an entry of its own
|
|
73
|
+
even on a page that defines a plain `N` as a count, and it composes with `\Phi`
|
|
74
|
+
for its CDF and `\varphi` for its PDF — pick those two once per course.
|
|
75
|
+
|
|
76
|
+
- **The differential** is upright `\mathrm{d}`: `\int_a^b f(x)\,\mathrm{d}x`
|
|
77
|
+
(thin space, then `\mathrm{d}x`), `\dfrac{\mathrm{d}f}{\mathrm{d}x}`,
|
|
78
|
+
`\dfrac{\mathrm{d}^2 f}{\mathrm{d}x^2}`, `\mathrm{d}s`, `\mathrm{d}A`,
|
|
79
|
+
`\mathrm{d}t`. An italic `d` is always a variable (a distance, a day count).
|
|
80
|
+
This is the ISO 80000-2 convention, and it keeps the differential clear of a
|
|
81
|
+
lesson that binds `d`. A partial derivative uses `\partial` bare —
|
|
82
|
+
`\dfrac{\partial f}{\partial x}` — which is already distinct; do not wrap
|
|
83
|
+
it. `\mathrm{d}` is a typographic label, not a bindable atom, so it needs no
|
|
84
|
+
key of its own ([N10](#n10)); only the variable of integration still has to
|
|
85
|
+
resolve.
|
|
86
|
+
|
|
87
|
+
- **Changing the table** is a course decision, made in one place:
|
|
88
|
+
`rules.N2.reserved` in `course.settings.json`, which the settings form editor
|
|
89
|
+
renders as a list. A course with no probability drops those two lines; a
|
|
90
|
+
course that parameterises the normal by standard deviation writes
|
|
91
|
+
`\mathcal{N}(\mu, \sigma)` there and then uses that form everywhere. The
|
|
92
|
+
effective table is printed on `build/rules-in-effect.md`, so an agent reads it
|
|
93
|
+
without opening this page.
|
|
94
|
+
|
|
95
|
+
_Enforcement._ Review-only. The completeness gate ([N4](#n4)) forces every
|
|
96
|
+
styled letter but the four number systems to resolve — to its own entry, since a
|
|
97
|
+
styled letter never falls back to the plain letter's card and the base library
|
|
98
|
+
has no card for it — and an unresolved one fails at `file:line:token`. But
|
|
99
|
+
*which* spelling was chosen for a meaning, and whether a reserved one was reused
|
|
100
|
+
for something else, is convention, caught in review. The two lists are
|
|
101
|
+
deliberately different things: `IGNORED_MATH_TOKENS`
|
|
102
|
+
(`src/reference/math-glyphs.mjs`) is what needs no key, `rules.N2.reserved` is
|
|
103
|
+
what may not mean anything else.
|
|
60
104
|
|
|
61
105
|
_Exceptions._ Quoting a source that uses a different glyph **and** showing the
|
|
62
|
-
mapping to
|
|
63
|
-
|
|
64
|
-
---
|
|
65
|
-
|
|
66
|
-
## N2
|
|
67
|
-
|
|
68
|
-
**`\mathbb{N}`, `\mathbb{Z}`, `\mathbb{R}`, `\mathbb{C}` are reserved for the
|
|
69
|
-
number systems.**
|
|
70
|
-
|
|
71
|
-
These four blackboard-bold tokens mean the naturals, integers, reals, and
|
|
72
|
-
complexes, always, and need no notation key. Every _other_ `\mathbb{…}` —
|
|
73
|
-
`\mathbb{E}`, `\mathbb{P}`, `\mathbb{Q}`, `\mathbb{1}` — is an ordinary
|
|
74
|
-
identifier that must resolve to a semantic key.
|
|
75
|
-
|
|
76
|
-
_Rationale._ The universal sets are genuinely universal; forcing a per-page
|
|
77
|
-
definition of `\mathbb{R}` would be noise. Everything else in blackboard bold
|
|
78
|
-
is domain-specific (an expectation, a probability measure, an indicator) and
|
|
79
|
-
earns a card.
|
|
80
|
-
|
|
81
|
-
_How to apply._ Need the rationals as a set on one lesson? That collides with a
|
|
82
|
-
reserved token — reach for `\explain{...}{\mathbb{Q}}` or a differently-styled
|
|
83
|
-
glyph, and note it in the domain vocabulary.
|
|
84
|
-
|
|
85
|
-
_Enforcement._ Partial. The gate forces every non-reserved `\mathbb{…}` to
|
|
86
|
-
resolve; keeping `N/Z/R/C` for the number systems (not, say, `\mathbb{N}` for a
|
|
87
|
-
sample size) is convention.
|
|
88
|
-
|
|
89
|
-
_Exceptions._ None for the four reserved tokens.
|
|
90
|
-
|
|
91
|
-
---
|
|
92
|
-
|
|
93
|
-
## N3
|
|
94
|
-
|
|
95
|
-
**Multi-letter roman labels use `\mathrm{…}`.**
|
|
96
|
-
|
|
97
|
-
An upright multi-letter name — `\mathrm{PV}`, `\mathrm{opt}`, `\mathrm{max}`
|
|
98
|
-
where no built-in operator exists — is wrapped in `\mathrm{}`. Never write it as
|
|
99
|
-
a run of bare italic letters (`PV`), which reads as a product `P \cdot V`.
|
|
100
|
-
|
|
101
|
-
_Rationale._ `\mathrm{}` is a typographic label, not a bindable atom — the glyph
|
|
102
|
-
resolver skips its body whole. Bare letter runs are parsed as identifier atoms,
|
|
103
|
-
so `PV` asks the gate to resolve `P` and `V` separately: a build failure at
|
|
104
|
-
best, a wrong binding at worst.
|
|
105
|
-
|
|
106
|
-
_How to apply._ Subscripts too: `v_{\mathrm{max}}`, not `v_{max}`.
|
|
107
|
-
|
|
108
|
-
_Enforcement._ Build-enforced indirectly — bare multi-letter runs hit the
|
|
109
|
-
completeness gate as unresolved identifiers.
|
|
110
|
-
|
|
111
|
-
_Exceptions._ Genuine products, and single-letter subscripts that are
|
|
112
|
-
themselves notation keys.
|
|
106
|
+
mapping to the reserved spelling in the same passage. None for the four number
|
|
107
|
+
systems.
|
|
113
108
|
|
|
114
109
|
---
|
|
115
110
|
|
|
@@ -184,7 +179,22 @@ notation," at `pnpm validate:content` time. Wrap the whole declared form —
|
|
|
184
179
|
`\explain{z-statistic}{Z_N}` — instead; bare `Z_N` elsewhere on the page then
|
|
185
180
|
resolves automatically. The same applies to accent-wrapped forms
|
|
186
181
|
(`latex: \widehat{\theta}`): wrap the accent and its argument together, not
|
|
187
|
-
just the inner letter.
|
|
182
|
+
just the inner letter. A whole-form entry like that is one of three ways to
|
|
183
|
+
satisfy [N22](#n22), which treats every accent or mark as an operator.
|
|
184
|
+
|
|
185
|
+
A **font-styled letter is its own glyph.** `\mathbf{x}`, `\boldsymbol{\beta}`,
|
|
186
|
+
`\bm{x}`, `\mathcal{N}`, `\mathscr{L}`, `\mathfrak{g}`, `\mathbb{E}`,
|
|
187
|
+
`\mathsf{x}` and `\mathtt{x}` never borrow the card of the plain letter on the
|
|
188
|
+
same page: a bold vector is not the scalar, and an expectation is not an
|
|
189
|
+
energy. Each needs its own entry (`latex: \mathbf{x}`) or an
|
|
190
|
+
`\explain{key}{\mathbf{x}}` wrap, or it fails as `unresolved-glyph`, with a
|
|
191
|
+
hint that it is a different symbol. A styled base-library letter
|
|
192
|
+
(`\mathbf{e}`, `\boldsymbol{\pi}`) is not Euler's number or π either. The
|
|
193
|
+
exceptions are `\mathit{x}` and `\mathnormal{x}`, which render the plain
|
|
194
|
+
italic letter and so share its card, and the four reserved number systems
|
|
195
|
+
([N2](#n2)). The leak ran one way only: a `\mathcal{N}` entry never bound a
|
|
196
|
+
plain `N`. This applies to every rendered-math context — lesson body,
|
|
197
|
+
formulas, assessments and labs.
|
|
188
198
|
|
|
189
199
|
Math authored inside a nested Astro component is outside the lesson MDX scan,
|
|
190
200
|
so the component must declare the formula text at render time. `Diagram` and
|
|
@@ -210,8 +220,14 @@ lesson and supplied component/formula context; a final Astro build check also
|
|
|
210
220
|
rejects any `data-notation-key` in generated HTML that has no matching
|
|
211
221
|
`data-notation-entry` source.
|
|
212
222
|
|
|
213
|
-
_Enforcement._ Build-enforced
|
|
214
|
-
|
|
223
|
+
_Enforcement._ Build-enforced. The completeness gate (`gate-math.ts`, `pnpm
|
|
224
|
+
validate:content`; `astro build` re-runs the same resolver) fails on an
|
|
225
|
+
unresolved glyph (`unresolved-glyph`) in every rendered-math context;
|
|
226
|
+
`consistency.ts` adds the corpus-level lints `glyph-unique-in-corpus`
|
|
227
|
+
(warning), `weak-local`, `gloss-wants-promoting`, `card-wants-demoting`
|
|
228
|
+
(info); a final rendered-trigger/payload parity check backs it at render time.
|
|
229
|
+
This rule is **locked** — the notation layer is this rule, so a course cannot
|
|
230
|
+
turn it off.
|
|
215
231
|
|
|
216
232
|
_Exceptions._ None. Genuinely different meanings need different glyphs or
|
|
217
233
|
different pages.
|
|
@@ -226,98 +242,33 @@ If prose points back at a display equation — this page or another — the equa
|
|
|
226
242
|
has `\label{eq:key}` and the reference is `[[eq-key]]`. Do not hand-number
|
|
227
243
|
equations in the text.
|
|
228
244
|
|
|
229
|
-
_Rationale._ The engine numbers every display equation
|
|
230
|
-
is the sidebar group's position in
|
|
231
|
-
|
|
232
|
-
chapter
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
245
|
+
_Rationale._ The engine numbers every display equation
|
|
246
|
+
`‹part›.‹chapter›.‹n›` — the part is the sidebar group's position in
|
|
247
|
+
`courseConfig.parts`, the chapter the lesson's position in its part, and `n`
|
|
248
|
+
counts the chapter's display equations in appearance order (`##` and `###`
|
|
249
|
+
headings do not affect it; a course may count across the whole part instead,
|
|
250
|
+
see [`structure.md` § Numbering](structure.md#numbering)) — and derives the
|
|
251
|
+
anchor and any cross-lesson link from the label. A hand-typed "(3)" goes stale
|
|
252
|
+
the moment an equation is inserted above it, or the chapter moves within its
|
|
253
|
+
part. `<Table>` and `<Figure>` are numbered the same way, each with its own
|
|
254
|
+
counter.
|
|
237
255
|
|
|
238
256
|
_How to apply._ Only label equations you actually reference; an unlabelled
|
|
239
|
-
display equation is still fine.
|
|
257
|
+
display equation is still fine. An equation may also carry a short caption,
|
|
258
|
+
`\caption{Range formula}`, next to its label inside the `$$…$$`: it is
|
|
259
|
+
stripped before KaTeX like the label, heads the `[[eq-…]]` preview card and
|
|
260
|
+
names the copy action ("Copy LaTeX — Range formula"). An equation takes no
|
|
261
|
+
long caption ([components.md § The caption pair](components.md#the-caption-pair)).
|
|
240
262
|
|
|
241
|
-
_Enforcement._
|
|
242
|
-
|
|
263
|
+
_Enforcement._ Partial. The converse is checked: `equations-validate.ts`
|
|
264
|
+
reports `eq-key-unused` (info) for a labelled equation nothing references.
|
|
265
|
+
An unlabelled-but-referenced equation builds; a reviewer catches the
|
|
266
|
+
hand-numbering.
|
|
243
267
|
|
|
244
268
|
_Exceptions._ None worth stating.
|
|
245
269
|
|
|
246
270
|
---
|
|
247
271
|
|
|
248
|
-
## N6
|
|
249
|
-
|
|
250
|
-
**Probability is `\mathbb{P}` — double-struck `P`.**
|
|
251
|
-
|
|
252
|
-
Write a probability as `\mathbb{P}(A)` — blackboard-bold `P`. Not `P(A)` (a bare
|
|
253
|
-
`P` is a variable — a price, a power, a point), not `\Pr`, not `\text{Prob}`.
|
|
254
|
-
Expectation is the same family: `\mathbb{E}[X]`.
|
|
255
|
-
|
|
256
|
-
_Rationale._ `\mathbb{P}` is unmistakably the probability functional, never a
|
|
257
|
-
quantity. It reads next to `\mathbb{E}` and `\mathbb{Q}` as one notation family
|
|
258
|
-
and never collides with a `P` the lesson uses for something physical.
|
|
259
|
-
|
|
260
|
-
_How to apply._
|
|
261
|
-
|
|
262
|
-
- Define it once, like [N1](#n1):
|
|
263
|
-
|
|
264
|
-
```yaml
|
|
265
|
-
key: prob.p
|
|
266
|
-
latex: \mathbb{P}
|
|
267
|
-
label: Probability
|
|
268
|
-
meaning: Probability of an event.
|
|
269
|
-
```
|
|
270
|
-
|
|
271
|
-
Introduce it in prose with `[[prob.p]]` before its first appearance in math.
|
|
272
|
-
|
|
273
|
-
- Conditional probability is `\mathbb{P}(A \mid B)` — `\mid`, not a bare `|`.
|
|
274
|
-
|
|
275
|
-
- A course doing measure theory may define `\mathbb{P}` as the real-world
|
|
276
|
-
measure and `\mathbb{Q}` as a risk-neutral one, consistent with the reserved
|
|
277
|
-
reading of `\mathbb{Q}` ([N2](#n2)). State that split once in the domain
|
|
278
|
-
notes.
|
|
279
|
-
|
|
280
|
-
_Enforcement._ Build-enforced that the symbol resolves to a key — `\mathbb{P}`
|
|
281
|
-
is a non-reserved `\mathbb{…}` and the completeness gate demands a binding
|
|
282
|
-
([N2](#n2)). The choice of `\mathbb{P}` over `P` / `\Pr` is convention.
|
|
283
|
-
|
|
284
|
-
_Exceptions._ Quoting a source that writes `\Pr` or `P` **and** showing the
|
|
285
|
-
mapping to `\mathbb{P}` in the same passage.
|
|
286
|
-
|
|
287
|
-
---
|
|
288
|
-
|
|
289
|
-
## N7
|
|
290
|
-
|
|
291
|
-
**The differential `d` is upright `\mathrm{d}`.**
|
|
292
|
-
|
|
293
|
-
The `d` of an integrand and the `d` of a derivative are the same operator and
|
|
294
|
-
get the same upright form — distinct from an italic `d`, which is always a
|
|
295
|
-
variable (a distance, a day count, a dimension):
|
|
296
|
-
|
|
297
|
-
- `\int_a^b f(x)\,\mathrm{d}x` — thin space `\,`, then `\mathrm{d}x`.
|
|
298
|
-
- `\dfrac{\mathrm{d}f}{\mathrm{d}x}`, `\dfrac{\mathrm{d}^2 f}{\mathrm{d}x^2}`.
|
|
299
|
-
- `\mathrm{d}s`, `\mathrm{d}A`, `\mathrm{d}V`, `\mathrm{d}t` — same rule for
|
|
300
|
-
every differential.
|
|
301
|
-
|
|
302
|
-
A partial derivative uses `\partial` bare — `\dfrac{\partial f}{\partial x}` —
|
|
303
|
-
which is already distinct; do not wrap it in anything.
|
|
304
|
-
|
|
305
|
-
_Rationale._ This is the ISO 80000-2 convention. Upright `\mathrm{d}` cannot be
|
|
306
|
-
read as a factor `d \cdot x`, and it stays clear of a notation key `d` on a
|
|
307
|
-
lesson that happens to have one.
|
|
308
|
-
|
|
309
|
-
_How to apply._ `\mathrm{d}` is a typographic operator, not a bindable atom —
|
|
310
|
-
the glyph resolver skips its body like any `\mathrm{…}` label ([N3](#n3)), so it
|
|
311
|
-
needs no notation key. Only the variable of integration (`x`, `t`) still has to
|
|
312
|
-
resolve.
|
|
313
|
-
|
|
314
|
-
_Enforcement._ Build-enforced indirectly — a bare `\int f(x) dx` puts an
|
|
315
|
-
unresolved identifier `d` in front of the completeness gate ([N3](#n3)).
|
|
316
|
-
|
|
317
|
-
_Exceptions._ A verbatim quotation of a source in a blockquote.
|
|
318
|
-
|
|
319
|
-
---
|
|
320
|
-
|
|
321
272
|
## N8
|
|
322
273
|
|
|
323
274
|
**A named operator is universal, or it is explained.**
|
|
@@ -325,12 +276,12 @@ _Exceptions._ A verbatim quotation of a source in a blockquote.
|
|
|
325
276
|
Every named operator a lesson uses — `\exp`, `\int`, `\sin`, … as built-ins,
|
|
326
277
|
`\operatorname{Var}`, `\operatorname{Cov}`, `\operatorname{E}` as declared ones
|
|
327
278
|
— is either on the shipped operator baseline (`src/reference/base-operators.mjs`
|
|
328
|
-
plus this course's `
|
|
279
|
+
plus this course's `rules.N8.allow` in `course.settings.json`) or it carries a
|
|
329
280
|
notation entry the reader can hover.
|
|
330
281
|
|
|
331
282
|
_Rationale._ The completeness gate has no opinion about operators: KaTeX parses
|
|
332
283
|
`\exp` as an operator node and `\operatorname{Var}` as an `operatorname` node,
|
|
333
|
-
and the glyph resolver skips both whole ([
|
|
284
|
+
and the glyph resolver skips both whole ([N10](#n10)). So `\operatorname{Var}`
|
|
334
285
|
renders fine while the reader is never told what "Var" means. `\exp` and `\int`
|
|
335
286
|
need no such help — everyone knows them — but a domain operator does, and the
|
|
336
287
|
line between the two is a course decision, made once, not per lesson.
|
|
@@ -353,7 +304,7 @@ _How to apply._
|
|
|
353
304
|
|
|
354
305
|
Then introduce it in prose with `[[stats.variance]]` before its first
|
|
355
306
|
appearance in math, and write it `\operatorname{Var}(X)` — never `Var(X)`
|
|
356
|
-
(bare letters, [
|
|
307
|
+
(bare letters, [N10](#n10)) and never `\mathrm{Var}` (a label, not an operator).
|
|
357
308
|
|
|
358
309
|
- A course whose domain treats an operator as common — `\operatorname{Var}`,
|
|
359
310
|
`\operatorname{Cov}`, `\operatorname{Corr}`, `\operatorname{sgn}` in a
|
|
@@ -364,13 +315,17 @@ _How to apply._
|
|
|
364
315
|
```
|
|
365
316
|
|
|
366
317
|
Names are the `\operatorname{…}` body, or the command without its backslash
|
|
367
|
-
for a built-in. `
|
|
318
|
+
for a built-in. `rules.N8.deny` forces a baseline operator to be explained
|
|
368
319
|
anyway.
|
|
369
320
|
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
321
|
+
- Decorations (`\hat`, `'`, `^*`) are operators too, with a rule of their
|
|
322
|
+
own: [N22](#n22).
|
|
323
|
+
|
|
324
|
+
_Enforcement._ Tier-3 warning (`operator-explained`, `consistency.ts`
|
|
325
|
+
`checkOperatorExplained`), surfaced by `pnpm validate:content`, recorded in
|
|
326
|
+
the manifest, and silenced only by a reviewed line in `lint-ignore.yml`
|
|
327
|
+
(`operator-explained:Var — <reason>`). Like `formula` before it (D15), the
|
|
328
|
+
tier can be promoted once a corpus is clean.
|
|
374
329
|
|
|
375
330
|
_Exceptions._ Quoting a source that uses an operator glyph **and** showing what
|
|
376
331
|
it means in the same passage.
|
|
@@ -397,18 +352,31 @@ the unit portion in `\text{}` and fold it into the _same_ math span as the
|
|
|
397
352
|
symbol it modifies (`$t\ \text{(s)}$`, not two adjacent spans `$t$
|
|
398
353
|
$\text{(s)}$`) — and prefer the short symbol over the spelled-out word even
|
|
399
354
|
inside `\text{}` (`\text{(s)}`, not `\text{(seconds)}`), the same way a
|
|
400
|
-
variable is `v_0` and not "initial velocity" once it's introduced.
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
355
|
+
variable is `v_0` and not "initial velocity" once it's introduced.
|
|
356
|
+
|
|
357
|
+
That holds in flowing prose too: a unit that quantifies something is a symbol,
|
|
358
|
+
not a word. "A time of 4 seconds" is `a time of $4\ \text{s}$`; "2 meters per
|
|
359
|
+
second squared" is `$2\ \text{m/s}^2$`; "30 degrees above the horizontal" is
|
|
360
|
+
`$30^{\circ}$ above the horizontal`; "$x = 3$ meters" is `$x = 3\ \text{m}$` —
|
|
361
|
+
the number and its unit share one span. A unit **named** without a quantity
|
|
362
|
+
stays a word ("a position measured in meters", "what is its range, in
|
|
363
|
+
meters?"), and so does a non-unit use of the same word ("the second
|
|
364
|
+
derivative", "three degrees of freedom"). Where a sentence _defines_ a unit
|
|
365
|
+
("one meter per second is the speed that covers one meter each second"),
|
|
366
|
+
waive that block rather than contort it:
|
|
367
|
+
|
|
368
|
+
```mdx
|
|
369
|
+
{/* explico-allow N9: this sentence defines the unit */}
|
|
370
|
+
One meter per second is the speed that covers one meter each second.
|
|
371
|
+
```
|
|
405
372
|
|
|
406
373
|
This also does not apply inside a JSX component prop (`<Figure caption="…">`,
|
|
407
374
|
`<Table caption="…">`, `title="…"`) — a prop string is handed to the DOM as
|
|
408
375
|
plain text with no math rendering at all, so `$…$` there would show up as
|
|
409
376
|
broken literal dollar signs instead of rendering; write the unit as a word or
|
|
410
377
|
the symbol as plain Unicode there instead ("peaks at 45°" in a caption is
|
|
411
|
-
fine).
|
|
378
|
+
fine). The same goes for an assessment's choice `label`, which renders as
|
|
379
|
+
plain text too.
|
|
412
380
|
|
|
413
381
|
_Rationale._ A reader who can hover `$v_0$` for its notation card gets nothing
|
|
414
382
|
from the same quantity spelled `v0` in a table header — the two look
|
|
@@ -438,7 +406,7 @@ _How to apply._
|
|
|
438
406
|
|
|
439
407
|
- A specific (per-unit) quantity like kinetic energy per unit mass is
|
|
440
408
|
`\mathrm{KE}/m`, not `KE/m` — multi-letter roman labels still take
|
|
441
|
-
`\mathrm{}` ([
|
|
409
|
+
`\mathrm{}` ([N10](#n10)) inside the math span.
|
|
442
410
|
|
|
443
411
|
- A unit exponent is a real LaTeX superscript (`\text{m/s}^2`), never the
|
|
444
412
|
Unicode "²"/"³" character — KaTeX's strict mode rejects those as unknown
|
|
@@ -474,8 +442,7 @@ _How to apply._
|
|
|
474
442
|
to work with. A bare `$t$`/`$x$` already does, via the ordinary `[[key]]`
|
|
475
443
|
intro + auto-resolution every other bound glyph on the page uses; the one
|
|
476
444
|
case that doesn't is a `\mathrm{…}` compound like `\mathrm{KE}/m`, because
|
|
477
|
-
the glyph resolver never looks inside a bare `\mathrm{}` body ([
|
|
478
|
-
[N10](#n10)) — explicitly `\explain{}`-wrap each side there
|
|
445
|
+
the glyph resolver never looks inside a bare `\mathrm{}` body ([N10](#n10)) — explicitly `\explain{}`-wrap each side there
|
|
479
446
|
(`\explain{kinetic-energy}{\mathrm{KE}}/\explain{mass}{m}`) so the plugin
|
|
480
447
|
has something to read; a header with more than one bound key composes them
|
|
481
448
|
joined by `" / "`.
|
|
@@ -492,14 +459,29 @@ just as invisible to a hover card as one in a lesson. Both look for: an
|
|
|
492
459
|
escaped `\|`; a numeral glued to an abbreviated unit (`45 m/s`); a bare unit
|
|
493
460
|
in parens (`(s)`, `(m/s²)`); a hand-typed `_`/`^` between alphanumerics; and a
|
|
494
461
|
`/` between two short alphabetic tokens that isn't on a small reviewed idiom
|
|
495
|
-
allowlist (`and/or`, `his/her`, …) in the check's own source
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
462
|
+
allowlist (`and/or`, `his/her`, …) in the check's own source — all reported
|
|
463
|
+
as `prose-notation`. A unit written as a word is reported as `spelled-unit`
|
|
464
|
+
(`unit-words.ts`, called from both entry points): an SI-style unit word
|
|
465
|
+
(meter, second, minute, hour, gram, newton, joule, watt, hertz, pascal,
|
|
466
|
+
volt, ampere, kelvin, mole, liter, radian, degree, and their common
|
|
467
|
+
prefixed forms) after a number in digits or words (`4 seconds`, `two-meter`)
|
|
468
|
+
or after a typeset number (`$x = 3$ meters`), before or after `per`, or with
|
|
469
|
+
`square` / `cubic` / `squared` / `cubed`. The message spells out the math to
|
|
470
|
+
write instead. "Degrees of freedom", a hyphenated compound (`second-order`)
|
|
471
|
+
and a unit word standing alone are not flagged; calendar time and currency
|
|
472
|
+
are not in the list. Unlike every other build-enforced rule here, N9 ships
|
|
473
|
+
as a hard error with no Tier-3 warming-up period and no `lint-ignore.yml`
|
|
474
|
+
entry, because each part landed in the same change that brought the whole
|
|
475
|
+
corpus to zero — see the two files for the exact patterns.
|
|
476
|
+
|
|
477
|
+
_Settings._ `rules.N9.allow` in the course settings lists unit words the
|
|
478
|
+
course lets prose spell out (`["hour", "minute"]`), singular or plural; a
|
|
479
|
+
phrase is skipped only when every unit word in it is allowed.
|
|
480
|
+
|
|
481
|
+
_Exceptions._ One place is excused with a waiver on the line above its block,
|
|
482
|
+
`{/* explico-allow N9: reason */}` — a sentence that defines a unit, or quotes
|
|
483
|
+
a source verbatim. None acknowledged through `lint-ignore.yml`: that registry
|
|
484
|
+
is for corpus-level warnings a reviewer accepts, and N9 has no warning tier to
|
|
503
485
|
accept into. A genuinely non-mathematical slash idiom (`input/output`, …) is
|
|
504
486
|
added to the allowlist in `gate-prose-notation.ts` itself, reviewed like any
|
|
505
487
|
other change to this file.
|
|
@@ -508,25 +490,34 @@ other change to this file.
|
|
|
508
490
|
|
|
509
491
|
## N10
|
|
510
492
|
|
|
511
|
-
**A `\mathrm{…}
|
|
493
|
+
**A multi-letter roman label is written `\mathrm{…}`, and it is universal or it
|
|
494
|
+
is explained.**
|
|
512
495
|
|
|
513
|
-
|
|
514
|
-
`\mathrm{
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
496
|
+
A word-like name inside math — `KE`, `PV`, `opt`, `max` where no built-in
|
|
497
|
+
operator exists — is wrapped in `\mathrm{}`: `\mathrm{KE}`,
|
|
498
|
+
`v_{\mathrm{max}}`, never a bare run of italic letters. And the label itself is
|
|
499
|
+
either on the shipped roman-label baseline
|
|
500
|
+
(`src/reference/base-roman-labels.mjs` plus this course's `rules.N10.allow` in
|
|
501
|
+
`course.settings.json`) or it carries a notation entry the reader can hover.
|
|
518
502
|
|
|
519
|
-
_Rationale._
|
|
520
|
-
|
|
503
|
+
_Rationale._ Two halves of one mistake. `\mathrm{}` is a typographic label, not
|
|
504
|
+
a bindable atom: a bare `PV` is parsed as identifier atoms, so it asks the gate
|
|
505
|
+
to resolve `P` and `V` separately — a build failure at best, a wrong binding at
|
|
506
|
+
worst. Wrapping it fixes the parse but not the reader, because — same as an
|
|
521
507
|
`\operatorname{}` body ([N8](#n8)) — the glyph resolver skips a `\mathrm{}`
|
|
522
|
-
body whole
|
|
508
|
+
body whole, so nothing about the wrap requires a definition to exist. N9's
|
|
523
509
|
enforcement fixed one direction of this exact page (`KE`/`PE` typed as plain
|
|
524
|
-
text); this rule closes the other: `KE
|
|
525
|
-
but with no card at all, which N9 cannot see
|
|
526
|
-
inside `$…$`.
|
|
510
|
+
text); this rule closes the other two: `KE` typed as bare italics, and
|
|
511
|
+
`\mathrm{KE}` typed correctly but with no card at all, which N9 cannot see
|
|
512
|
+
because the notation is already inside `$…$`.
|
|
527
513
|
|
|
528
514
|
_How to apply._
|
|
529
515
|
|
|
516
|
+
- **Write the label upright.** `\mathrm{PV}`, `\mathrm{opt}`,
|
|
517
|
+
`v_{\mathrm{max}}` — subscripts too, `v_{\mathrm{max}}` and never `v_{max}`.
|
|
518
|
+
A genuine product stays bare letters, and a single-letter subscript that is
|
|
519
|
+
itself a notation key stays a key.
|
|
520
|
+
|
|
530
521
|
- A generic qualifier that functions like an operator's extremum subscript —
|
|
531
522
|
`x_{\mathrm{opt}}`, an "optimal" reading with no quantity of its own — just
|
|
532
523
|
works. The full baseline is the greppable set in `base-roman-labels.mjs`,
|
|
@@ -555,18 +546,22 @@ _How to apply._
|
|
|
555
546
|
romanLabels: { allow: ['PV', 'NPV'] }
|
|
556
547
|
```
|
|
557
548
|
|
|
558
|
-
Names are the `\mathrm{…}` body. `
|
|
549
|
+
Names are the `\mathrm{…}` body. `rules.N10.deny` forces a baseline label
|
|
559
550
|
to be explained anyway.
|
|
560
551
|
|
|
561
|
-
_Enforcement._ Tier-3 warning (`roman-label-explained`
|
|
562
|
-
`pnpm validate:content`, recorded in
|
|
563
|
-
reviewed line in `lint-ignore.yml`
|
|
552
|
+
_Enforcement._ Tier-3 warning (`roman-label-explained`, `consistency.ts`
|
|
553
|
+
`checkRomanLabelExplained`), surfaced by `pnpm validate:content`, recorded in
|
|
554
|
+
the manifest, and silenced only by a reviewed line in `lint-ignore.yml`
|
|
555
|
+
(`roman-label-explained:KE — <reason>`).
|
|
564
556
|
Same rollout shape as [N8](#n8): the tier can be promoted once a corpus is
|
|
565
|
-
clean.
|
|
557
|
+
clean. Partial, because the first half has no check of its own: a bare
|
|
558
|
+
multi-letter run is reported by [N4](#n4)'s completeness gate as unresolved
|
|
559
|
+
one-letter symbols, which is a different message for the same mistake, and a
|
|
560
|
+
run whose letters all happen to be bound slips through.
|
|
566
561
|
|
|
567
562
|
_Exceptions._ Quoting a source that uses a roman-label glyph **and** showing
|
|
568
563
|
what it means in the same passage. A single-letter `\mathrm{…}` body (`d`,
|
|
569
|
-
[
|
|
564
|
+
the differential, [N2](#n2)) is out of scope entirely — that is a fixed typographic operator,
|
|
570
565
|
not a named quantity.
|
|
571
566
|
|
|
572
567
|
---
|
|
@@ -662,6 +657,16 @@ notation — a comma separating two side-by-side equations in one display block
|
|
|
662
657
|
(`x = \ldots, \qquad y = \ldots`) is a list separator inside the math, not
|
|
663
658
|
prose leaking in, and is unaffected by this rule.
|
|
664
659
|
|
|
660
|
+
The same holds for each row of a multi-line block: a row of an `aligned` or
|
|
661
|
+
`cases` block never ends in a comma or full stop before its `\\`. The comma
|
|
662
|
+
between a `cases` value and its condition (`1, & x > 0`) is notation and
|
|
663
|
+
stays.
|
|
664
|
+
|
|
665
|
+
Two endings that look like notation are not allowed either. A trailing
|
|
666
|
+
decimal point (`\hat{\beta} = 5.`) is sometimes used to say "exactly this
|
|
667
|
+
precision", but a reader cannot tell it from the full stop. Write `5`, or
|
|
668
|
+
`5.0` when the precision matters. A typed `...` is `\ldots`.
|
|
669
|
+
|
|
665
670
|
_Rationale._ A trailing period or comma inside `$…$` becomes part of the
|
|
666
671
|
LaTeX source: KaTeX renders it in math italic/spacing rather than as
|
|
667
672
|
punctuation, it is included in whatever `\text{}` it landed inside (turning a
|
|
@@ -678,16 +683,26 @@ this corpus (see [N5](#n5)'s `\label{eq:…}` pattern) already ends bare. For
|
|
|
678
683
|
inline math (`$x = 5$` mid-sentence), put the period or comma after the
|
|
679
684
|
closing `$`, where it has always belonged.
|
|
680
685
|
|
|
681
|
-
_Enforcement._
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
686
|
+
_Enforcement._ Build-enforced (`gate-math-punctuation.ts`, wired into the
|
|
687
|
+
same `pnpm validate:content` pass as [N9](#n9), code
|
|
688
|
+
`math-trailing-punctuation`, an error). `gateMathPunctuation` reads every
|
|
689
|
+
`$…$` / `$$…$$` span in a lesson body — the same spans the completeness gate
|
|
690
|
+
resolves, table cells and component slots included — and
|
|
691
|
+
`gateMathPunctuationInAssessments` every assessment `prompt` /
|
|
692
|
+
`explanation`. It flags a `.`, `,`, `;` or `:` that is the last visible
|
|
693
|
+
thing in the span, or in a row before a `\\`. It looks through what renders
|
|
694
|
+
nothing there: spacing (`\,`, `\quad`), `\label{…}` / `\tag{…}`, a row
|
|
695
|
+
break, `\end{…}`, the null delimiter `\right.`. It looks into a closing
|
|
696
|
+
`\text{…}` / `\mathrm{…}`, so `5\ \text{m,}` is caught. A finding is located
|
|
697
|
+
at the mark, so a per-place waiver can cover it.
|
|
698
|
+
|
|
699
|
+
_Exceptions._ An upright dotted abbreviation that is itself notation may end
|
|
700
|
+
the math: `+ \text{h.c.}`, `+ \text{c.c.}`, `X_n \to X\ \text{a.s.}`. The
|
|
701
|
+
shipped list is `a.e.`, `a.s.`, `c.c.`, `const.`, `h.c.`, `i.i.d.`; a course
|
|
702
|
+
adds one with `rules.N12.allow` and drops one with `rules.N12.deny` in
|
|
703
|
+
`course.settings.json`. Set in math italic (`h.c.` without `\text{}`), it is
|
|
704
|
+
not on the list. Anything else is waived in place with
|
|
705
|
+
`{/* explico-allow N12: reason */}`.
|
|
691
706
|
|
|
692
707
|
---
|
|
693
708
|
|
|
@@ -742,7 +757,7 @@ _How to apply._
|
|
|
742
757
|
_Enforcement._ Build-enforced, with no partial-corpus warm-up tier — like
|
|
743
758
|
[N9](#n9), it ships as a hard error. `resolveMathGlyphs`
|
|
744
759
|
(`src/reference/math-glyphs.mjs`) walks the parsed KaTeX tree for every
|
|
745
|
-
rendered-math context this engine has — the same single resolver [
|
|
760
|
+
rendered-math context this engine has — the same single resolver [N2](#n2)
|
|
746
761
|
through [N10](#n10) already rely on — and fails the moment a
|
|
747
762
|
`PARENTHESIZED_FUNCTIONS` name is not immediately followed by a visible
|
|
748
763
|
opening delimiter. Because every context (lesson body, `notation.formula`,
|
|
@@ -769,7 +784,7 @@ does not require reproducing it.
|
|
|
769
784
|
Every all-caps acronym (`OLS`, `MSE`, `SSR`) or dotted abbreviation (`w.r.t.`,
|
|
770
785
|
`i.i.d.`) a lesson uses in ordinary prose — outside any `$…$` — is either on
|
|
771
786
|
the shipped abbreviation baseline (`src/reference/base-abbreviations.mjs`
|
|
772
|
-
plus this course's `
|
|
787
|
+
plus this course's `rules.N14.allow` in `course.settings.json`), carries an
|
|
773
788
|
entry in the `abbreviations` content collection
|
|
774
789
|
(`content/abbreviations/*.md`), or is already explained as a math quantity on
|
|
775
790
|
the same page ([N8](#n8) / [N10](#n10)). A term resolved by the table is not
|
|
@@ -815,7 +830,7 @@ _How to apply._
|
|
|
815
830
|
abbreviations: { allow: ['GDP', 'CPU'] }
|
|
816
831
|
```
|
|
817
832
|
|
|
818
|
-
`
|
|
833
|
+
`rules.N14.deny` forces a shipped baseline entry (`e.g.`, `i.e.`, …) to
|
|
819
834
|
be explained anyway.
|
|
820
835
|
|
|
821
836
|
_Enforcement._ Build-enforced (`gate-abbreviations.ts`), wired into the same
|
|
@@ -829,7 +844,7 @@ was added.
|
|
|
829
844
|
|
|
830
845
|
_Exceptions._ None acknowledged through `lint-ignore.yml`. A genuinely
|
|
831
846
|
universal abbreviation this course's readers cannot be expected to look up is
|
|
832
|
-
added to `
|
|
847
|
+
added to `rules.N14.allow` in `course.settings.json`, reviewed like any other
|
|
833
848
|
change to that file.
|
|
834
849
|
|
|
835
850
|
---
|
|
@@ -885,7 +900,7 @@ _How to apply._
|
|
|
885
900
|
- A `|` has no distinct open/close glyph, so a lone pair — `\left|x\right|`,
|
|
886
901
|
or bare `|x|` when it is not nested in anything — reads as one absolute
|
|
887
902
|
value/norm, matched left to right. Conditional probability still prefers
|
|
888
|
-
`\mid` over a bare `|` regardless of nesting ([
|
|
903
|
+
`\mid` over a bare `|` regardless of nesting ([N2](#n2)).
|
|
889
904
|
- A delimiter inside `\text{…}` is display text, not a sizing mark — a unit
|
|
890
905
|
written `\text{(s)}` ([N9](#n9)) is untouched by this rule even when the
|
|
891
906
|
math around it also uses `(`.
|
|
@@ -914,91 +929,14 @@ notation.
|
|
|
914
929
|
|
|
915
930
|
---
|
|
916
931
|
|
|
917
|
-
## N16
|
|
918
|
-
|
|
919
|
-
**In AI-generated mathematical content, alternate delimiter types for nested
|
|
920
|
-
grouping when their shape is stylistic; preserve every conventional or
|
|
921
|
-
semantic delimiter shape.**
|
|
922
|
-
|
|
923
|
-
For a nest whose delimiters do nothing except group an expression, prefer this
|
|
924
|
-
cycle from the inside out:
|
|
925
|
-
|
|
926
|
-
1. `( ... )`
|
|
927
|
-
2. `[ ... ]`
|
|
928
|
-
3. `\{ ... \}`
|
|
929
|
-
4. repeat the cycle if another grouping level is genuinely necessary.
|
|
930
|
-
|
|
931
|
-
This is a preference for generated notation, not a mechanical rewrite. Do not
|
|
932
|
-
change or alternate a delimiter whose type is part of the mathematical
|
|
933
|
-
notation. Preserve, among other conventional forms:
|
|
934
|
-
|
|
935
|
-
- function application such as `f(x)`;
|
|
936
|
-
- expectation notation such as `\mathbb{E}[X]`;
|
|
937
|
-
- intervals such as `[a,b]` and `(a,b]`;
|
|
938
|
-
- sets and set-builder notation;
|
|
939
|
-
- tuples and coordinates;
|
|
940
|
-
- commutators and probability notation;
|
|
941
|
-
- matrices, vectors, indexing, norms, and absolute values.
|
|
942
|
-
|
|
943
|
-
When there is doubt about whether the delimiter is semantic, keep the
|
|
944
|
-
conventional notation. Do not alternate merely to complete the cycle.
|
|
945
|
-
|
|
946
|
-
_Rationale._ Repeating the same shape at every purely stylistic grouping level
|
|
947
|
-
makes the boundaries harder to scan. Alternation can expose the grouping
|
|
948
|
-
structure, but only mathematical context can distinguish a disposable grouping
|
|
949
|
-
mark from notation whose shape carries meaning. That judgment belongs to the
|
|
950
|
-
authoring agent or reviewer, not a syntax linter.
|
|
951
|
-
|
|
952
|
-
_How to apply._ Decide whether each pair is stylistic before choosing its
|
|
953
|
-
shape. Alternate only the pairs that pass that test. Sizes are not your
|
|
954
|
-
concern: [N17](#n17) hands every nested pair to the engine, which grows each
|
|
955
|
-
level automatically. Shape is an authoring decision; size is not.
|
|
956
|
-
|
|
957
|
-
```text
|
|
958
|
-
\left[
|
|
959
|
-
a+
|
|
960
|
-
\left(
|
|
961
|
-
b+
|
|
962
|
-
\left[
|
|
963
|
-
c+
|
|
964
|
-
\left(d+e\right)
|
|
965
|
-
\right]
|
|
966
|
-
\right)
|
|
967
|
-
\right] ✓
|
|
968
|
-
```
|
|
969
|
-
|
|
970
|
-
Semantic notation stays intact even when stylistic grouping surrounds it:
|
|
971
|
-
|
|
972
|
-
```text
|
|
973
|
-
\left[
|
|
974
|
-
\mathbb{E}\!\left[
|
|
975
|
-
f\!\left(X\right)
|
|
976
|
-
\right]
|
|
977
|
-
+
|
|
978
|
-
\left(
|
|
979
|
-
a+b
|
|
980
|
-
\right)
|
|
981
|
-
\right] ✓
|
|
982
|
-
```
|
|
983
|
-
|
|
984
|
-
In particular, never turn `\mathbb{E}[X]` into another delimiter type merely
|
|
985
|
-
to alternate shapes.
|
|
986
|
-
|
|
987
|
-
_Enforcement._ Review-only. Delimiter semantics cannot be inferred reliably
|
|
988
|
-
from LaTeX syntax, so no automated check enforces alternation. The N17 linter
|
|
989
|
-
checks sizing syntax only and never recommends changing a delimiter type.
|
|
990
|
-
|
|
991
|
-
_Exceptions._ Every conventional or semantically meaningful delimiter is
|
|
992
|
-
outside the alternation preference. Preserving established mathematical
|
|
993
|
-
notation takes precedence over the stylistic cycle.
|
|
994
|
-
|
|
995
|
-
---
|
|
996
|
-
|
|
997
932
|
## N17
|
|
998
933
|
|
|
999
|
-
**A
|
|
1000
|
-
|
|
1001
|
-
|
|
934
|
+
**A delimiter's shape carries its meaning and never changes to show nesting: a
|
|
935
|
+
nest is sized by the engine — `\left ... \right` at every level, never
|
|
936
|
+
`\bigl`, `\Bigl`, `\biggl`, or `\Biggl` inside it.**
|
|
937
|
+
|
|
938
|
+
Two decisions, one rule, and neither is the author's to improvise. *Shape* is
|
|
939
|
+
fixed by what the delimiter means; *size* belongs to the engine.
|
|
1002
940
|
|
|
1003
941
|
```text
|
|
1004
942
|
\left[a+\left(b+\left[c+\left(d+e\right)\right]\right)\right] ✓
|
|
@@ -1030,9 +968,17 @@ _How to apply._
|
|
|
1030
968
|
- Do not "help" the engine with a manual size. If a nest still looks wrong,
|
|
1031
969
|
the expression is too deep to read — restructure it, or pull an inner group
|
|
1032
970
|
into its own display, rather than hand-sizing it.
|
|
1033
|
-
-
|
|
1034
|
-
|
|
1035
|
-
|
|
971
|
+
- **Keep every shape as its meaning requires it.** Function application
|
|
972
|
+
`f(x)`, expectation `\mathbb{E}[X]`, an interval `[a, b)`, a set or
|
|
973
|
+
set-builder `\{…\}`, a tuple, a commutator, a matrix, an index, a norm
|
|
974
|
+
`\|·\|`, an absolute value — the shape is part of the notation and never
|
|
975
|
+
changes. A plain parenthesis is the shape for grouping.
|
|
976
|
+
- **Never alternate shapes to mark depth.** `( [ \{ … \} ] )` for a nest whose
|
|
977
|
+
delimiters only group is not this house's style: with the sizing below, depth
|
|
978
|
+
is already visible, and a reader who meets `[` inside a grouping nest has to
|
|
979
|
+
rule out an interval, an expectation and a matrix first. When in doubt about
|
|
980
|
+
whether a pair is semantic, keep the conventional notation — which is the
|
|
981
|
+
same answer as "do not alternate".
|
|
1036
982
|
- A *lone* hand-sized pair that is not part of a nest is untouched — a tuple
|
|
1037
983
|
written `\bigl(x(t),\ y(t)\bigr)` has no hierarchy to get wrong and stays a
|
|
1038
984
|
deliberate typographic choice.
|
|
@@ -1053,9 +999,317 @@ suggests the `\left`/`\right` replacement, repeating the exact opening and
|
|
|
1053
999
|
closing delimiter shapes it found. Malformed pairs remain KaTeX syntax errors;
|
|
1054
1000
|
the linter does not guess at their structure.
|
|
1055
1001
|
|
|
1056
|
-
The automated check deliberately does **not** infer mathematical semantics
|
|
1057
|
-
|
|
1002
|
+
The automated check deliberately does **not** infer mathematical semantics, so
|
|
1003
|
+
the shape half of this rule is review-only: `delimiter-manual-size` parses
|
|
1004
|
+
sizing syntax and never decides whether a bracket is semantic or suggests
|
|
1005
|
+
turning one shape into another. A bare nested delimiter is [N15](#n15)'s error
|
|
1006
|
+
rather than this rule's warning.
|
|
1058
1007
|
|
|
1059
1008
|
_Exceptions._ None inside a nest. Bare, non-nested semantic notation such as
|
|
1060
1009
|
`f(x)` or `\mathbb{E}[X]` is outside this linter and remains governed by the
|
|
1061
1010
|
mathematical convention and [N15](#n15)'s separate bare-nesting rule.
|
|
1011
|
+
|
|
1012
|
+
---
|
|
1013
|
+
|
|
1014
|
+
## N18
|
|
1015
|
+
|
|
1016
|
+
**Write a multi-step derivation as one chain: one step per line, aligned at
|
|
1017
|
+
the relation sign, with any justification on the same line after `\qquad`.**
|
|
1018
|
+
|
|
1019
|
+
When a display takes an expression through two or more steps — `a = b = c`,
|
|
1020
|
+
or `a = b \le c` — write it as an `aligned` block. The first line carries the
|
|
1021
|
+
left-hand side. Every later line starts with `&` directly before its relation
|
|
1022
|
+
(`&=`, `&\le`, `&\approx`, `&\propto`), so the relation signs stand in one
|
|
1023
|
+
column. A step that needs a reason gets it at the end of its own line, after
|
|
1024
|
+
`\qquad` (or `\quad` when the line is tight), inside `\text{…}`:
|
|
1025
|
+
|
|
1026
|
+
```text
|
|
1027
|
+
$$
|
|
1028
|
+
\begin{aligned}
|
|
1029
|
+
\operatorname{Var}(Y)
|
|
1030
|
+
&=\mathbb{E}\left[\left(Y-\mathbb{E}[Y]\right)^2\right]
|
|
1031
|
+
\qquad\text{definition of the variance}\\
|
|
1032
|
+
&=\mathbb{E}\left[Y^2\right]-\mathbb{E}[Y]^2
|
|
1033
|
+
\qquad\text{linearity of }\mathbb{E}
|
|
1034
|
+
\end{aligned}
|
|
1035
|
+
\label{eq:variance-shortcut}
|
|
1036
|
+
$$ ✓
|
|
1037
|
+
```
|
|
1038
|
+
|
|
1039
|
+
```text
|
|
1040
|
+
$$
|
|
1041
|
+
\operatorname{Var}(Y)=\mathbb{E}\left[\left(Y-\mathbb{E}[Y]\right)^2\right]=\mathbb{E}\left[Y^2\right]-\mathbb{E}[Y]^2
|
|
1042
|
+
$$ ✗ one line: grows sideways, no room for reasons
|
|
1043
|
+
|
|
1044
|
+
$$\operatorname{Var}(Y)=\mathbb{E}\left[\left(Y-\mathbb{E}[Y]\right)^2\right]$$
|
|
1045
|
+
which, by linearity of the expectation, equals
|
|
1046
|
+
$$\mathbb{E}\left[Y^2\right]-\mathbb{E}[Y]^2$$ ✗ one chain split by prose
|
|
1047
|
+
```
|
|
1048
|
+
|
|
1049
|
+
_Rationale._ A chain written on one line grows sideways with every step and
|
|
1050
|
+
soon runs past the reading column, where it scrolls or spills; an aligned
|
|
1051
|
+
chain grows downward and is only as wide as its widest step. Relation signs
|
|
1052
|
+
in one column let a reader compare consecutive right-hand sides and check
|
|
1053
|
+
each step on its own. A reason on the step's own line sits next to what it
|
|
1054
|
+
justifies, where a reason in the following paragraph ("the second equality
|
|
1055
|
+
holds because …") has to be matched back to a position by counting. And the
|
|
1056
|
+
whole derivation stays one display equation: one number ([N5](#n5)), one
|
|
1057
|
+
link target, one copy-LaTeX unit.
|
|
1058
|
+
|
|
1059
|
+
_How to apply._
|
|
1060
|
+
|
|
1061
|
+
- Use `aligned` inside `$$…$$`. End every line but the last with `\\`.
|
|
1062
|
+
- Put `&` directly before the relation, never after it, so the relation signs
|
|
1063
|
+
line up; a continuation line starts with `&=` (or its own relation).
|
|
1064
|
+
- A justification goes after the step's math and before its `\\`, separated
|
|
1065
|
+
by `\qquad`, as `\text{…}`. Math inside a justification leaves the text
|
|
1066
|
+
group: `\text{linearity of }\mathbb{E}`.
|
|
1067
|
+
- A justification names the fact it uses — a definition, a property, an
|
|
1068
|
+
assumption, a named result ("independence of the errors", "Jensen's
|
|
1069
|
+
inequality"). Never type another equation's number into the math:
|
|
1070
|
+
[N5](#n5) forbids hand numbering, and the engine cannot link from inside
|
|
1071
|
+
math. When a step rests on another display equation, link that equation
|
|
1072
|
+
with `[[eq-key]]` in the sentence that introduces the chain ("Substituting
|
|
1073
|
+
[[eq-mean]] gives"), and name it in the step if the reader needs the
|
|
1074
|
+
reminder there.
|
|
1075
|
+
- Label the chain once, if prose refers to it ([N5](#n5)). It gets one
|
|
1076
|
+
number. If later prose must cite a single line of it, end the chain before
|
|
1077
|
+
that line and give the rest its own display and label.
|
|
1078
|
+
- A step whose explanation needs more than a short phrase belongs in prose:
|
|
1079
|
+
end the chain, explain, and continue with a new chain.
|
|
1080
|
+
- Keep the sentence's own punctuation out of the chain ([N12](#n12)).
|
|
1081
|
+
|
|
1082
|
+
_Enforcement._ Review-only. It could be surfaced as an info-level
|
|
1083
|
+
diagnostic — a display with two or more top-level relation signs outside an
|
|
1084
|
+
`aligned` block — but no such check exists yet.
|
|
1085
|
+
|
|
1086
|
+
_Exceptions._
|
|
1087
|
+
|
|
1088
|
+
- A chain of short relations that fits comfortably on one line —
|
|
1089
|
+
`0 \le p \le 1`, `a = b = 0` — may stay on one line.
|
|
1090
|
+
- Side-by-side results that are not steps of one derivation
|
|
1091
|
+
(`x = \ldots, \qquad y = \ldots`) are a list, not a chain.
|
|
1092
|
+
- Quoting a source whose layout carries meaning, with the passage saying so.
|
|
1093
|
+
|
|
1094
|
+
## N19
|
|
1095
|
+
|
|
1096
|
+
**A notation entry states its `units`, or declares itself `dimensionless`,
|
|
1097
|
+
using the units vocabulary.**
|
|
1098
|
+
|
|
1099
|
+
Every entry in `content/notation/` and every `notation.local` definition
|
|
1100
|
+
carries either a `units:` string built from the tokens in
|
|
1101
|
+
`src/reference/units-vocab.ts` (`m`, `s`, `kg`, `m/s`, `m/s^2`, `rad`, `1`,
|
|
1102
|
+
…) or `dimensionless: true`.
|
|
1103
|
+
|
|
1104
|
+
```yaml
|
|
1105
|
+
# content/notation/motion.velocity.md
|
|
1106
|
+
key: motion.velocity
|
|
1107
|
+
label: velocity
|
|
1108
|
+
units: m/s
|
|
1109
|
+
|
|
1110
|
+
# content/notation/motion.launch-angle.md
|
|
1111
|
+
key: motion.launch-angle
|
|
1112
|
+
label: launch angle
|
|
1113
|
+
units: rad
|
|
1114
|
+
|
|
1115
|
+
# a pure count or ratio
|
|
1116
|
+
dimensionless: true
|
|
1117
|
+
```
|
|
1118
|
+
|
|
1119
|
+
_Rationale._ The hover card, the table-header label
|
|
1120
|
+
(`rehype-table-header-labels.mjs`), and a worked example's dimensional check
|
|
1121
|
+
(N11) all read `units` from the entry. An entry without it renders a card with
|
|
1122
|
+
no unit, and a unit spelled outside the vocabulary (`meters/sec`) cannot be
|
|
1123
|
+
matched against the one in the prose.
|
|
1124
|
+
|
|
1125
|
+
_How to apply._ Add `units:` from the vocabulary, or `dimensionless: true`.
|
|
1126
|
+
Compose with `/` and `^`: `kg·m/s^2` is `kg*m/s^2`. If the vocabulary lacks a
|
|
1127
|
+
unit the course needs, add it to `units-vocab.ts` in the engine first.
|
|
1128
|
+
|
|
1129
|
+
_Enforcement._ Build-enforced (`consistency.ts` `checkNotationUnits`,
|
|
1130
|
+
`pnpm validate:content`) — warnings `notation-units` (neither field present)
|
|
1131
|
+
and `units-vocab` (a token outside the vocabulary).
|
|
1132
|
+
|
|
1133
|
+
_Exceptions._ A `lint-ignore.yml` entry (`- notation-units:<key> — <reason>`)
|
|
1134
|
+
for a symbol whose unit is genuinely context-dependent.
|
|
1135
|
+
|
|
1136
|
+
## N20
|
|
1137
|
+
|
|
1138
|
+
**A notation entry's source citation carries a locator.**
|
|
1139
|
+
|
|
1140
|
+
Each item under an entry's `sources:` names *where* in the source the symbol is
|
|
1141
|
+
defined — a section, a page, an equation number — not just which source.
|
|
1142
|
+
|
|
1143
|
+
```yaml
|
|
1144
|
+
sources:
|
|
1145
|
+
- id: halliday-fundamentals
|
|
1146
|
+
locator: "§4.3, eq. (4-12)"
|
|
1147
|
+
```
|
|
1148
|
+
|
|
1149
|
+
_Rationale._ A bare source id says "this book somewhere". The hover card shows
|
|
1150
|
+
the locator, so a reader can open the source at the right page; a reviewer can
|
|
1151
|
+
check the definition against it without re-reading the chapter.
|
|
1152
|
+
|
|
1153
|
+
_How to apply._ Fill `locator:` with the smallest unit the source has:
|
|
1154
|
+
`"§3.2"`, `"p. 41"`, `"eq. (2.7)"`, `"Table 4"`. Never leave it empty or
|
|
1155
|
+
omit it.
|
|
1156
|
+
|
|
1157
|
+
_Enforcement._ Build-enforced (`consistency.ts` `checkNotationSourceLocator`,
|
|
1158
|
+
`pnpm validate:content`) — warning `notation-source-locator` per source item
|
|
1159
|
+
without a non-empty locator.
|
|
1160
|
+
|
|
1161
|
+
_Exceptions._ A source that is one page long (a datasheet, a standard's
|
|
1162
|
+
definition table) may cite the whole; say so in the locator (`"whole"`).
|
|
1163
|
+
|
|
1164
|
+
## N21
|
|
1165
|
+
|
|
1166
|
+
**A gloss is named by a short noun phrase, not described by a sentence.**
|
|
1167
|
+
|
|
1168
|
+
A gloss binds a symbol on one page with a `label` shown in the hover card. The
|
|
1169
|
+
label *names* the symbol; it does not explain it.
|
|
1170
|
+
|
|
1171
|
+
```yaml
|
|
1172
|
+
# A name.
|
|
1173
|
+
- key: launch-angle
|
|
1174
|
+
label: launch angle
|
|
1175
|
+
|
|
1176
|
+
# A description — belongs in a full notation entry's body, not a gloss label.
|
|
1177
|
+
- key: launch-angle
|
|
1178
|
+
label: the angle between the launch velocity and the horizontal, which we vary
|
|
1179
|
+
```
|
|
1180
|
+
|
|
1181
|
+
_Rationale._ A gloss is the lightweight form: a name and a glyph. Once the
|
|
1182
|
+
label grows a clause or a sentence it is doing a notation entry's job without
|
|
1183
|
+
that entry's units, sources, or shared identity — and the card shows a wall of
|
|
1184
|
+
text where every other card shows a name.
|
|
1185
|
+
|
|
1186
|
+
_How to apply._ Keep the label to a few words with no sentence punctuation or
|
|
1187
|
+
relative clause. If the symbol needs a description, promote the gloss to a
|
|
1188
|
+
notation entry (the `gloss-wants-promoting` hint under N4 says when).
|
|
1189
|
+
|
|
1190
|
+
_Enforcement._ Build-enforced (`consistency.ts` `checkGlossNameShape`, `pnpm
|
|
1191
|
+
validate:content`) — warning `gloss-name-shape` for a label over the word
|
|
1192
|
+
limit or containing sentence punctuation / a relative clause.
|
|
1193
|
+
|
|
1194
|
+
_Exceptions._ None — a label that cannot be short is a notation entry.
|
|
1195
|
+
|
|
1196
|
+
---
|
|
1197
|
+
|
|
1198
|
+
## N22
|
|
1199
|
+
|
|
1200
|
+
**An accent or mark on a symbol is an operator: universal, explained, or part
|
|
1201
|
+
of the symbol's own entry.**
|
|
1202
|
+
|
|
1203
|
+
`\hat{\beta}` reads as "hat applied to β". β keeps its own card, and the hat is
|
|
1204
|
+
either universal for this course (`rules.N22.allow`; the shipped list is
|
|
1205
|
+
empty), explained by an operator entry (`latex: \hat{}`, meaning "estimate
|
|
1206
|
+
of"), or the decorated form has its own entry (`latex: \hat{\beta}`), which
|
|
1207
|
+
wins for that exact form. Decorations are accents (`\hat`, `\widehat`, `\bar`,
|
|
1208
|
+
`\tilde`, `\dot`, `\vec`, …), `\overline` / `\underline`, and the superscript
|
|
1209
|
+
marks `'` (any run of primes), `*` (or `\ast`) and `\dagger`. `\widehat` and
|
|
1210
|
+
`\hat` are different operators. `^\top`, `^{-1}`, powers, subscripts and fonts
|
|
1211
|
+
are not decorations; a font makes a different symbol ([N4](#n4)).
|
|
1212
|
+
|
|
1213
|
+
_Rationale._ The glyph resolver binds a letter by its own shape, so before this
|
|
1214
|
+
rule it walked straight through a hat: `\hat{\beta}` got β's card, and the hat
|
|
1215
|
+
was never explained. That is the same gap [N8](#n8) closes for named
|
|
1216
|
+
operators — `\operatorname{Var}(X)` gives `Var` and `X` a card each. A
|
|
1217
|
+
decoration means different things in different fields: `\hat` is an
|
|
1218
|
+
estimator, a unit vector or a Fourier transform; `\bar` a mean, a conjugate or
|
|
1219
|
+
a closure; `'` a derivative or "another one". So none is universal by default.
|
|
1220
|
+
|
|
1221
|
+
_How to apply._ Pick one of three, in this order of precedence:
|
|
1222
|
+
|
|
1223
|
+
1. **Whole form** — the decorated symbol is a quantity in its own right, with
|
|
1224
|
+
its own formula or distribution. Give it its own entry; that exact form gets
|
|
1225
|
+
that card, hat included:
|
|
1226
|
+
|
|
1227
|
+
```yaml
|
|
1228
|
+
key: coef-estimate
|
|
1229
|
+
latex: \hat{\beta}
|
|
1230
|
+
label: Estimated coefficient
|
|
1231
|
+
```
|
|
1232
|
+
|
|
1233
|
+
2. **Operator entry** — the decoration means the same thing wherever it
|
|
1234
|
+
appears on the page. Give the decoration over an empty group its own
|
|
1235
|
+
entry — `\hat{}`, `\overline{}`, `{}'`, `{}^{*}`, `{}^{\dagger}` — as a
|
|
1236
|
+
shared card introduced with `[[key]]` or a `notation.local` entry, like an
|
|
1237
|
+
N8 operator. The reader then hovers the hat for its card, and the letter
|
|
1238
|
+
under it for the letter's:
|
|
1239
|
+
|
|
1240
|
+
```yaml
|
|
1241
|
+
key: stats.estimate
|
|
1242
|
+
latex: \hat{}
|
|
1243
|
+
label: Estimate
|
|
1244
|
+
meaning: The value of a quantity computed from a sample, as opposed to its true value.
|
|
1245
|
+
```
|
|
1246
|
+
|
|
1247
|
+
3. **Universal for the course** — a course that uses a decoration one way
|
|
1248
|
+
throughout lists it once in `course.settings.json`:
|
|
1249
|
+
|
|
1250
|
+
```json
|
|
1251
|
+
"rules": { "N22": { "allow": ["\\dot", "\\vec"] } }
|
|
1252
|
+
```
|
|
1253
|
+
|
|
1254
|
+
`rules.N22.deny` exists for symmetry with N8; the shipped list is empty.
|
|
1255
|
+
|
|
1256
|
+
A letter under a decoration still needs its own card ([N4](#n4)); the
|
|
1257
|
+
decoration adds a card, it never replaces one.
|
|
1258
|
+
|
|
1259
|
+
### Suspending an operator on one page
|
|
1260
|
+
|
|
1261
|
+
Sometimes a decoration is not an operator on one page: `b'`, `b''`, `b'''` are
|
|
1262
|
+
successive versions of `b`, not derivatives. Say so in the lesson's
|
|
1263
|
+
frontmatter, with the reason:
|
|
1264
|
+
|
|
1265
|
+
```yaml
|
|
1266
|
+
notation:
|
|
1267
|
+
suspend:
|
|
1268
|
+
- operator: "'"
|
|
1269
|
+
reason: marks successive versions of b, not derivatives
|
|
1270
|
+
local:
|
|
1271
|
+
- key: b-v1
|
|
1272
|
+
latex: b'
|
|
1273
|
+
# …
|
|
1274
|
+
```
|
|
1275
|
+
|
|
1276
|
+
On that page the decoration never composes: every decorated symbol that uses
|
|
1277
|
+
it must be a whole form — its own entry, or an `\explain{key}{b''}` wrap around
|
|
1278
|
+
the whole of it — or the build fails. That catches a forgotten `b''''`, and an
|
|
1279
|
+
`f'(x)` that still means a derivative. An `\explain{key}{b}''` around the letter
|
|
1280
|
+
alone is not a whole form. Other pages keep the operator reading.
|
|
1281
|
+
|
|
1282
|
+
`operator` takes the same names as `rules.N22.allow` (`"'"`, `\hat`, `*`, …).
|
|
1283
|
+
A name that is not a decoration, a decoration suspended twice, and a
|
|
1284
|
+
`notation.local` operator entry for a decoration the same page suspends each
|
|
1285
|
+
fail the load. A shared operator card may still be cited on a suspending page
|
|
1286
|
+
with `[[key]]`, to explain the difference.
|
|
1287
|
+
|
|
1288
|
+
Suspension covers lesson-body math only — the same scope as `notation.local`.
|
|
1289
|
+
A notation formula, an assessment prompt and a lab keep the operator reading.
|
|
1290
|
+
The Page notation panel tells the reader that the decoration is not an
|
|
1291
|
+
operator on the page, and why.
|
|
1292
|
+
|
|
1293
|
+
| Code | Severity | When |
|
|
1294
|
+
| --- | --- | --- |
|
|
1295
|
+
| `suspended-operator-unresolved` | error | a decorated form of a suspended decoration has no whole form |
|
|
1296
|
+
| `operator-suspended` | info | a suspension with a `reason` — recorded, nothing to fix |
|
|
1297
|
+
| `operator-suspension-reason` | warning | a suspension without a `reason` |
|
|
1298
|
+
| `operator-shadowed` | info | a whole-form entry decorates with an operator that is explained or universal on its page, and the page does not suspend it |
|
|
1299
|
+
|
|
1300
|
+
`operator-shadowed` is a note, not a fault: "β̂ is the OLS estimate" under a
|
|
1301
|
+
course-wide `\hat` = "estimate of" card is a legitimate refinement. It
|
|
1302
|
+
suggests suspension in case the decoration never means the operator there.
|
|
1303
|
+
|
|
1304
|
+
_Enforcement._ Tier-3 warning `accent-explained` (`consistency.ts`
|
|
1305
|
+
`checkAccentExplained`) for a decoration that composes with no operator entry
|
|
1306
|
+
and is not on the allow list, one per decoration per lesson, surfaced by `pnpm
|
|
1307
|
+
validate:content` and silenced only by a reviewed line in `lint-ignore.yml`
|
|
1308
|
+
(`accent-explained:\hat — <reason>`). Suspension is build-enforced: the
|
|
1309
|
+
completeness gate (`gate-math.ts`) and the render path (`remark-notation.mjs`)
|
|
1310
|
+
both fail `suspended-operator-unresolved`; `checkOperatorSuspension` emits the
|
|
1311
|
+
other three codes.
|
|
1312
|
+
|
|
1313
|
+
_Exceptions._ Suspension (above) is the sanctioned way to give a decoration a
|
|
1314
|
+
different meaning on one page. Quoting a source that uses a decoration
|
|
1315
|
+
differently **and** showing what it means in the same passage.
|