explico 0.8.0 → 0.11.1
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 +1257 -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 +5 -3
- 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 +1152 -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 +1467 -163
- package/src/styles/surfaces.css +182 -0
- package/src/components/hover-panel.ts +0 -339
- package/src/components/popup-stack.ts +0 -345
package/docs/authoring/README.md
CHANGED
|
@@ -39,8 +39,59 @@ whether it complies.
|
|
|
39
39
|
3. Author discretion, recorded in the diff.
|
|
40
40
|
|
|
41
41
|
A course may add its own rules on top — a house style for prose, a domain glyph
|
|
42
|
-
table
|
|
43
|
-
|
|
42
|
+
table — in `courseRules` in its `course.settings.json` (see
|
|
43
|
+
[Rules of your own](#rules-of-your-own)). It must not silently relax one of
|
|
44
|
+
these; loosening a rule is a change to this folder, reviewed like any other
|
|
45
|
+
change. Turning a rule off, or tuning it, for one course is a different thing
|
|
46
|
+
and a visible one: `rules.<ID>` in the course settings
|
|
47
|
+
(`course.settings.json`), which every `validate:content` reflects in
|
|
48
|
+
`build/rules-in-effect.md` — the page an agent reads instead of this folder.
|
|
49
|
+
|
|
50
|
+
## Accessibility
|
|
51
|
+
|
|
52
|
+
Accessibility is the engine's job, not the author's: no rule here asks a course
|
|
53
|
+
author to write an accessible name, a description, `alt` text or a text
|
|
54
|
+
alternative. Every float renders a real `<figure>` and `<figcaption>`, so its
|
|
55
|
+
caption is its accessible name; a table header that is all math gets a hidden
|
|
56
|
+
text label from its notation entries; and every button and link the engine
|
|
57
|
+
draws names itself. The engine's own markup is held to that by axe in explico's
|
|
58
|
+
end-to-end tests. What an author writes anyway — a lab's `ariaLabel`, an
|
|
59
|
+
`aria-label` on an inline `<svg role="img">` — is welcome and never required.
|
|
60
|
+
|
|
61
|
+
## Waiving a rule at one place
|
|
62
|
+
|
|
63
|
+
A rule is a strong recommendation, and the diff must state the reason when
|
|
64
|
+
one is broken. The in-source form of that reason is a waiver — an MDX comment
|
|
65
|
+
on its own line, above the block it is for:
|
|
66
|
+
|
|
67
|
+
```mdx
|
|
68
|
+
{/* explico-allow N9: the unit is being defined here, not used */}
|
|
69
|
+
The unit of acceleration is written m/s² …
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
It covers the next block — from the first non-blank line after the comment to
|
|
73
|
+
the line before the next blank line — and may name several rules
|
|
74
|
+
(`explico-allow N9, N14: reason`). The reason is mandatory. What a waiver does
|
|
75
|
+
depends on the rule:
|
|
76
|
+
|
|
77
|
+
- **A rule with a check that reports a line** (`waivable` on the rules-in-effect
|
|
78
|
+
page: N9, N14, S1, N17) — the build drops the findings the waiver covers. A
|
|
79
|
+
waiver that silences nothing is a `waiver-unused` warning, so a stale one
|
|
80
|
+
gets removed.
|
|
81
|
+
- **A guide rule** (every `P` and `V` rule, N2, N11, …) — nothing to silence;
|
|
82
|
+
the waiver is the reason on record, next to the sentence it is about, and a
|
|
83
|
+
reviewer reads it as such.
|
|
84
|
+
- **One of the course's own rules** (`X1`, …) — always waivable inline: an
|
|
85
|
+
enforced one reports a line, and a guide one has nothing to silence.
|
|
86
|
+
- **A rule whose check has no line** — a notation entry (N8, N10, N19–N21), a
|
|
87
|
+
per-lesson count (S3, S4, S5), the changelog (C3) — cannot be waived inline.
|
|
88
|
+
Silence one finding per key in `lint-ignore.yml`
|
|
89
|
+
(`- <code>:<key> — <reason>`), or turn the rule off in `rules.<ID>`.
|
|
90
|
+
- **A locked rule** (N4, N13, N15) and an invariant cannot be waived: the
|
|
91
|
+
page would not render. Naming one is a `waiver-invalid` error.
|
|
92
|
+
|
|
93
|
+
A waiver comment is not prose: the `N9` / `N14` scans blank it, so the reason
|
|
94
|
+
may quote the very text it excuses.
|
|
44
95
|
|
|
45
96
|
## How a rule is written
|
|
46
97
|
|
|
@@ -49,21 +100,39 @@ speak in: what a part, a chapter, a section, and a subsection are, and which of
|
|
|
49
100
|
them an equation number counts.
|
|
50
101
|
|
|
51
102
|
Each rule has a stable ID — a letter for its area (`N` notation,
|
|
52
|
-
`V` visualizations, `C` versioning, `S` structure, `P` prose) plus a number — and this shape
|
|
103
|
+
`V` visualizations, `C` versioning, `S` structure, `P` prose) plus a number — and this shape.
|
|
104
|
+
`X` is not one of them: it is reserved for the rules a course writes for itself
|
|
105
|
+
([Rules of your own](#rules-of-your-own)), so the engine never ships an `X`
|
|
106
|
+
rule and a course can number its own without waiting for a release.
|
|
53
107
|
|
|
54
108
|
> **N1 — One-line imperative.**
|
|
55
109
|
> _Rationale._ Why the rule exists; the failure it prevents.
|
|
56
110
|
> _How to apply._ Concrete steps, with the smallest example that shows it.
|
|
57
|
-
> _Enforcement._ Build-enforced (
|
|
111
|
+
> _Enforcement._ Build-enforced (naming the gate module) or Review-only.
|
|
58
112
|
> _Exceptions._ The stateable reasons that override it, if any.
|
|
59
113
|
|
|
60
|
-
IDs are permanent
|
|
61
|
-
|
|
62
|
-
|
|
114
|
+
IDs are permanent, so a `N3` in an old commit message never goes ambiguous — but
|
|
115
|
+
a retired rule leaves this folder entirely. Its section goes, its row leaves the
|
|
116
|
+
index, and one line (ID, the sentence it had, the date, its successor, why) lands
|
|
117
|
+
in the generated table on [retired.md](retired.md). Nothing an author or an agent
|
|
118
|
+
reads while drafting mentions it. Two rules that turn out to be one idea are
|
|
119
|
+
merged that way: the text moves into the rule that keeps its ID, the other
|
|
120
|
+
becomes a row on that page.
|
|
121
|
+
|
|
122
|
+
The catalog entry adds what a machine needs and the page does not repeat: the
|
|
123
|
+
element(s) the rule is about, the diagnostic codes it owns and the module and
|
|
124
|
+
function that emit them, its course settings, and whether it is locked. The
|
|
125
|
+
page's `_Enforcement._` paragraph must name every module the entry lists;
|
|
126
|
+
`gen-rules.mjs --check` holds the two together.
|
|
63
127
|
|
|
64
128
|
## Amending
|
|
65
129
|
|
|
66
|
-
1. Open a PR that touches exactly one area file plus
|
|
130
|
+
1. Open a PR that touches exactly one area file plus its entry in
|
|
131
|
+
`src/rules/catalog.ts` (ID, title, elements, checks, settings). The index
|
|
132
|
+
table below is generated from the catalog — run
|
|
133
|
+
`node scripts/agent/gen-rules.mjs` after `pnpm build`; `--check` runs in
|
|
134
|
+
`scripts/agent/verify` and CI and fails when the table or a rule page
|
|
135
|
+
disagrees with the catalog.
|
|
67
136
|
2. Give a new rule the next unused number in its area. Never renumber.
|
|
68
137
|
3. Write the four parts above. If the rule could be build-enforced but is not
|
|
69
138
|
yet, say so and link the engine issue.
|
|
@@ -73,6 +142,82 @@ old commit message never goes ambiguous.
|
|
|
73
142
|
A new area — a new letter and file — is the same PR shape plus a row in the
|
|
74
143
|
file table.
|
|
75
144
|
|
|
145
|
+
## Rules of your own
|
|
146
|
+
|
|
147
|
+
A classroom has house style the engine does not ship — a phrase this cohort must
|
|
148
|
+
not use, a paragraph shape a department agreed on, a convention that holds for
|
|
149
|
+
one course and nowhere else. Those are the course's own rules, and they live in
|
|
150
|
+
its `course.settings.json`, next to every other course setting and editable in
|
|
151
|
+
the same form editor (`tools/vscode-settings-editor/`). No engine change, no
|
|
152
|
+
fork, no waiting for a release.
|
|
153
|
+
|
|
154
|
+
They are numbered in the **`X` area**, which is reserved for them: `X1`…`X99`.
|
|
155
|
+
The engine never ships an `X` rule, so a course can add one today and upgrade
|
|
156
|
+
`explico` tomorrow without a collision, and one ID works everywhere an engine
|
|
157
|
+
rule's does — a diagnostic, a waiver, a commit message, the rules-in-effect
|
|
158
|
+
page.
|
|
159
|
+
|
|
160
|
+
```json
|
|
161
|
+
"courseRules": [
|
|
162
|
+
{
|
|
163
|
+
"id": "X1",
|
|
164
|
+
"title": "A paragraph never ends in an exclamation.",
|
|
165
|
+
"summary": "End a paragraph on the statement it argues for. Move the emphasis into the sentence, or drop it.",
|
|
166
|
+
"elements": ["prose"],
|
|
167
|
+
"severity": "error",
|
|
168
|
+
"forbid": [
|
|
169
|
+
{
|
|
170
|
+
"scope": "paragraph",
|
|
171
|
+
"pattern": "Ni!$",
|
|
172
|
+
"message": "a paragraph ends in “Ni!” — end it on the statement instead."
|
|
173
|
+
}
|
|
174
|
+
]
|
|
175
|
+
},
|
|
176
|
+
{
|
|
177
|
+
"id": "X2",
|
|
178
|
+
"title": "Every fifth paragraph is four sentences in Object–Subject–Verb order.",
|
|
179
|
+
"summary": "Count the paragraphs of the lesson body; the fifth, tenth, … is exactly four sentences, each in OSV order.",
|
|
180
|
+
"elements": ["prose"],
|
|
181
|
+
"enabled": false,
|
|
182
|
+
"unchecked": "everything — the rule is a guide, and sentence order is not something a pattern can see."
|
|
183
|
+
}
|
|
184
|
+
]
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
**Enforced or guide, from one field.** A rule with a `forbid` pattern is
|
|
188
|
+
enforced: the build matches it and reports every hit at the rule's `severity`
|
|
189
|
+
(`error` fails `pnpm validate:content`, `warning` does not), with the rule's ID
|
|
190
|
+
as the diagnostic code — `[X1] content/docs/…:42: a paragraph ends in "Ni!" …`.
|
|
191
|
+
A rule with no pattern is a guide: it appears on the rules-in-effect page for an
|
|
192
|
+
author or an agent to follow, and nothing runs. Both kinds are real rules on
|
|
193
|
+
that page, which is what an agent reads before drafting.
|
|
194
|
+
|
|
195
|
+
**`enabled: false` parks a rule.** It stays in the file, with its text, and moves
|
|
196
|
+
to the page's "Off" list — where an agent is told not to apply it *and* not to
|
|
197
|
+
flag it in review. That is how a rule that is drafted, or agreed for next term,
|
|
198
|
+
waits without affecting this term's lessons.
|
|
199
|
+
|
|
200
|
+
**What a pattern sees.** A JavaScript regular expression, matched against the
|
|
201
|
+
lesson's prose with code fences, inline code, `$…$` and `$$…$$`, `[[key]]`
|
|
202
|
+
references, `import` lines, JSX tags and MDX comments blanked out first —
|
|
203
|
+
exactly the surface rule N9 scans, so a pattern never trips over LaTeX or a
|
|
204
|
+
component prop. `scope` picks the unit: `paragraph` (the default — a block
|
|
205
|
+
between blank lines, right-trimmed, so `^` and `$` are its ends), `prose` (the
|
|
206
|
+
whole lesson, so a pattern may span paragraphs), or `heading` (the text of each
|
|
207
|
+
Markdown heading). `flags` takes `i`, `m`, `s`, `u`; `g` is always applied. A
|
|
208
|
+
pattern that does not compile, or that matches the empty string, fails the build
|
|
209
|
+
with the path of the setting — the rule never silently does nothing.
|
|
210
|
+
|
|
211
|
+
**Waiving one.** `{/* explico-allow X1: the sentence quotes the chant */}`
|
|
212
|
+
above a block, exactly like an engine rule, reason mandatory; a waiver that
|
|
213
|
+
silences nothing is reported so it gets removed.
|
|
214
|
+
|
|
215
|
+
**Where the text lives.** `summary` is what the rules-in-effect page prints, so
|
|
216
|
+
write it as an instruction, not a rationale. For a rule that needs a page of its
|
|
217
|
+
own, put it under the course's `content/docs/` (or anywhere), and name it in
|
|
218
|
+
`doc` — a path relative to `build/`, or a URL — and the page links there instead
|
|
219
|
+
of to the settings file.
|
|
220
|
+
|
|
76
221
|
## Files
|
|
77
222
|
|
|
78
223
|
| File | Area | Covers |
|
|
@@ -80,41 +225,88 @@ file table.
|
|
|
80
225
|
| [notation.md](notation.md) | `N` | how math symbols are written and bound |
|
|
81
226
|
| [visualizations.md](visualizations.md) | `V` | diagrams, charts, interactive figures, randomness |
|
|
82
227
|
| [versioning.md](versioning.md) | `C` | the knowledge version and `content/CHANGELOG.md` |
|
|
83
|
-
| [structure-rules.md](structure-rules.md) | `S` | heading and
|
|
84
|
-
| [prose.md](prose.md) | `P` | how a lesson's sentences are worded
|
|
228
|
+
| [structure-rules.md](structure-rules.md) | `S` | heading and float title length; part page paragraphs; tables, diagrams and conventions declared so they can be cited |
|
|
229
|
+
| [prose.md](prose.md) | `P` | how a lesson's sentences, terms, and equation lead-ins are worded |
|
|
85
230
|
| [components.md](components.md) | — | _catalog_: inline/block features available in a lesson body — tooltips, tables, figures, diagrams, memos, abbreviations, citations |
|
|
86
231
|
| [agents.md](agents.md) | — | _guide_: working on a course repo (with an AI agent) |
|
|
87
232
|
| [migrating.md](migrating.md) | — | _guide_: per-version steps when bumping the `explico` dep |
|
|
233
|
+
| [retired.md](retired.md) | — | _history_: one generated row per rule no longer in force, and its successor |
|
|
88
234
|
|
|
89
235
|
## Rule index
|
|
90
236
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
|
94
|
-
|
|
|
95
|
-
| [
|
|
96
|
-
| [N4](notation.md#n4)
|
|
97
|
-
| [N5](notation.md#n5)
|
|
98
|
-
| [
|
|
99
|
-
| [
|
|
100
|
-
| [
|
|
101
|
-
| [
|
|
102
|
-
| [
|
|
103
|
-
| [
|
|
104
|
-
| [
|
|
105
|
-
| [
|
|
106
|
-
| [
|
|
107
|
-
| [
|
|
108
|
-
| [
|
|
109
|
-
| [
|
|
110
|
-
| [
|
|
111
|
-
| [
|
|
112
|
-
| [
|
|
113
|
-
| [
|
|
114
|
-
| [
|
|
115
|
-
| [
|
|
116
|
-
| [
|
|
117
|
-
| [
|
|
118
|
-
| [
|
|
119
|
-
| [
|
|
120
|
-
| [
|
|
237
|
+
<!-- RULES-INDEX:BEGIN (generated by scripts/agent/gen-rules.mjs from src/rules/catalog.ts — do not edit inside) -->
|
|
238
|
+
|
|
239
|
+
| ID | Element | Rule | Enforcement |
|
|
240
|
+
| --- | --- | --- | --- |
|
|
241
|
+
| [N2](notation.md#n2) | math | A reserved spelling is used only for its reserved meaning — settings: `reserved` = `["\\mathbb{N} — the natural numbers","\\mathbb{Z} — the integers","\\mathbb{R} — the reals","\\mathbb{C} — the complex numbers","\\mathbb{P} — probability","\\mathcal{N}(\\mu, \\sigma^2) — the normal distribution (mean, variance)","\\mathrm{d} — the differential"]` | Guide |
|
|
242
|
+
| [N4](notation.md#n4) | math, notation | One meaning per glyph; define once; `[[key]]` before first math | **Locked** — the notation layer is this rule — an unresolved glyph has no hover card and the render path needs every glyph bound. Script — `unresolved-glyph`, `glyph-unique-in-corpus` (warning), `weak-local` (info), `gloss-wants-promoting` (info), `card-wants-demoting` (info) in [`gate-math.ts`](../../src/reference/gate-math.ts) `resolveInto`; [`consistency.ts`](../../src/reference/consistency.ts) `checkGlyphUniqueness`, `checkWeakLocal`, `checkGlossWantsPromoting`, `checkCardWantsDemoting` |
|
|
243
|
+
| [N5](notation.md#n5) | equation | Referenced display equations carry `\label{eq:key}` | Partial — `eq-key-unused` (info) in [`equations-validate.ts`](../../src/reference/equations-validate.ts) `validateEquations`. review: that a referenced-in-prose equation actually carries a label |
|
|
244
|
+
| [N8](notation.md#n8) | math, notation | A named operator is universal (shipped/course list) or explained — settings: `allow` = `[]`, `deny` = `[]` | Script — `operator-explained` (warning) in [`consistency.ts`](../../src/reference/consistency.ts) `checkOperatorExplained` |
|
|
245
|
+
| [N9](notation.md#n9) | prose, assessment, table | A quantity/unit/operator is typeset in `$…$`, never as plain text — settings: `allow` = `[]` | Script — `prose-notation`, `spelled-unit` in [`gate-prose-notation.ts`](../../src/reference/gate-prose-notation.ts) `gateProseNotation`, `gateProseNotationInAssessments` |
|
|
246
|
+
| [N10](notation.md#n10) | math, notation | A multi-letter label is `\mathrm{…}`, and universal or explained — settings: `allow` = `[]`, `deny` = `[]` | Partial — `roman-label-explained` (warning) in [`consistency.ts`](../../src/reference/consistency.ts) `checkRomanLabelExplained`. review: that a bare multi-letter run was wrapped in `\mathrm{…}` at all — rule N4’s gate reports it as unresolved one-letter symbols, which is a different message for the same mistake |
|
|
247
|
+
| [N11](notation.md#n11) | math, prose | A worked example never drops a unit from a substituted value | Guide |
|
|
248
|
+
| [N12](notation.md#n12) | math, prose, assessment | Math syntax never carries the sentence's own trailing punctuation — settings: `allow` = `[]`, `deny` = `[]` | Script — `math-trailing-punctuation` in [`gate-math-punctuation.ts`](../../src/reference/gate-math-punctuation.ts) `gateMathPunctuation`, `gateMathPunctuationInAssessments` |
|
|
249
|
+
| [N13](notation.md#n13) | math | A nonlinear function always takes a parenthesized argument | **Locked** — the glyph resolver cannot tell where an unparenthesized argument ends, so it cannot bind the symbols inside it. Script — `unparenthesized-function` in [`math-glyphs.mjs`](../../src/reference/math-glyphs.mjs) `resolveMathGlyphs` |
|
|
250
|
+
| [N14](notation.md#n14) | prose | An abbreviation-shaped word in prose is universal, or explained — settings: `allow` = `[]`, `deny` = `[]` | Script — `abbreviation-unexplained` in [`gate-abbreviations.ts`](../../src/reference/gate-abbreviations.ts) `gateAbbreviations` |
|
|
251
|
+
| [N15](notation.md#n15) | math | A nested `(`, `[`, `{`, or `\|` must use scalable sizing | **Locked** — a bare `\|` is both an opener and a closer; nested, the resolver cannot pair it, so the rule is a parsing precondition. Script — `nested-bare-delimiter` in [`math-glyphs.mjs`](../../src/reference/math-glyphs.mjs) `resolveMathGlyphs` |
|
|
252
|
+
| [N17](notation.md#n17) | math | A delimiter’s shape is semantic; a nest is engine-sized, not hand-sized | Partial — `delimiter-manual-size` (warning) in [`delimiter-size.ts`](../../src/reference/delimiter-size.ts) `lintDelimiterSizes`. review: the shape half — `delimiter-manual-size` parses sizing syntax only, and never decides whether a bracket is semantic. A bare nested delimiter is rule N15’s error instead |
|
|
253
|
+
| [N18](notation.md#n18) | equation | A multi-step derivation is one aligned chain; reasons follow `\qquad` | Guide |
|
|
254
|
+
| [N19](notation.md#n19) | notation | A notation entry states `units` from the vocabulary, or `dimensionless` | Script — `notation-units` (warning), `units-vocab` (warning) in [`consistency.ts`](../../src/reference/consistency.ts) `checkNotationUnits` |
|
|
255
|
+
| [N20](notation.md#n20) | notation, source | A notation entry's source citation carries a locator | Script — `notation-source-locator` (warning) in [`consistency.ts`](../../src/reference/consistency.ts) `checkNotationSourceLocator` |
|
|
256
|
+
| [N21](notation.md#n21) | notation | A gloss is named by a short noun phrase, not a sentence | Script — `gloss-name-shape` (warning) in [`consistency.ts`](../../src/reference/consistency.ts) `checkGlossNameShape` |
|
|
257
|
+
| [N22](notation.md#n22) | math, notation | An accent or mark is an operator: universal, explained, or a whole form — settings: `allow` = `[]`, `deny` = `[]` | Script — `accent-explained` (warning), `suspended-operator-unresolved`, `operator-suspension-reason` (warning), `operator-suspended` (info), `operator-shadowed` (info) in [`consistency.ts`](../../src/reference/consistency.ts) `checkAccentExplained`, `checkOperatorSuspension`; [`gate-math.ts`](../../src/reference/gate-math.ts) `resolveInto` |
|
|
258
|
+
| [V1](visualizations.md#v1) | diagram | Graphs and flowcharts use the `Diagram` component | Guide |
|
|
259
|
+
| [V2](visualizations.md#v2) | plot | Static charts: SVG → D3 → Observable Plot, chosen per figure | Guide |
|
|
260
|
+
| [V3](visualizations.md#v3) | plot | Interactive figures: a hydrated island + the `renderLabMath` seam | Guide |
|
|
261
|
+
| [V4](visualizations.md#v4) | plot | Randomised figures expose an adjustable, deterministic seed | Guide |
|
|
262
|
+
| [V5](visualizations.md#v5) | plot | Axis ranges span the first 10 seeds at the current control values — settings: `seeds` = `10` | Guide |
|
|
263
|
+
| [V6](visualizations.md#v6) | plot | Every quantitative axis shows at least three labelled values — settings: `minLabels` = `3` | Guide |
|
|
264
|
+
| [C1](versioning.md#c1) | changelog | Every content change lands with a `content/CHANGELOG.md` entry | Guide |
|
|
265
|
+
| [C2](versioning.md#c2) | changelog | The knowledge version is semver over learning-facing content | Guide |
|
|
266
|
+
| [C3](versioning.md#c3) | changelog | `about.version` equals the newest changelog heading; a release moves both | Partial — `knowledge-version-mismatch` (warning), `knowledge-version-invalid` (warning), `knowledge-changelog-missing` (warning) in [`knowledge-version.ts`](../../src/compiler/knowledge-version.ts) `resolveKnowledgeVersion`. review: that the two edits landed in one commit — the build only ever sees the end state, so a release split across commits warns until the second half lands |
|
|
267
|
+
| [S1](structure-rules.md#s1) | heading | No heading, short caption or short-note title over 65 characters — settings: `maxLength` = `65` | Partial — `title-length` in [`gate-heading-length.ts`](../../src/reference/gate-heading-length.ts) `gateHeadingLength`. review: a lesson’s `frontmatter.title` — the gate scans the body only |
|
|
268
|
+
| [S2](structure-rules.md#s2) | part-page | A part page carries a `<PartBridge>` (earlier parts → this one) and a `<PartScope>` paragraph — settings: `bridgeMinWords` = `30`, `bridgeMaxWords` = `150`, `scopeMinWords` = `30`, `scopeMaxWords` = `150` | Partial — `part-page-paragraph` in [`gate-part-pages.ts`](../../src/reference/gate-part-pages.ts) `gatePartPages`. review: what each paragraph says — the gate cannot tell a bridge that links the parts from one that does not |
|
|
269
|
+
| [S3](structure-rules.md#s3) | table | A table is a `<Table id="…">`, never a raw Markdown/HTML table | Script — `raw-table-markdown` (warning), `raw-table-html` (warning) in [`raw-floats-validate.ts`](../../src/reference/raw-floats-validate.ts) `validateRawFloats` |
|
|
270
|
+
| [S4](structure-rules.md#s4) | diagram | A `<Diagram>` carries an `id` and sits where numbering can see it | Script — `diagram-unkeyed` (warning), `diagram-nested` (warning) in [`raw-floats-validate.ts`](../../src/reference/raw-floats-validate.ts) `validateRawFloats` |
|
|
271
|
+
| [S5](structure-rules.md#s5) | prose | A sign / perspective convention is declared once and cited elsewhere | Script — `convention-single-definition` (warning) in [`consistency.ts`](../../src/reference/consistency.ts) `checkConventionSingleDefinition` |
|
|
272
|
+
| [S6](structure-rules.md#s6) | heading | Headings descend one level at a time, from `##` | Script — `heading-skip` in [`gate-heading-structure.ts`](../../src/reference/gate-heading-structure.ts) `gateHeadingStructure` |
|
|
273
|
+
| [S7](structure-rules.md#s7) | heading | A heading is followed by body content, never by another heading | Script — `heading-adjacent` in [`gate-heading-structure.ts`](../../src/reference/gate-heading-structure.ts) `gateHeadingStructure` |
|
|
274
|
+
| [S8](structure-rules.md#s8) | prose | Prefer `<Memo>` over a Starlight aside when the content needs an anchor, a caption or collapsing | Guide |
|
|
275
|
+
| [S9](structure-rules.md#s9) | plot, table, diagram | A float’s short caption names it; the long caption goes on from that name | Guide |
|
|
276
|
+
| [P1](prose.md#p1) | prose | "or" never introduces a second name for the same thing | Guide |
|
|
277
|
+
| [P2](prose.md#p2) | prose | One term for each concept, repeated — no synonyms for variety | Guide |
|
|
278
|
+
| [P3](prose.md#p3) | prose | One meaning for each term; no technical term in its everyday sense | Guide |
|
|
279
|
+
| [P4](prose.md#p4) | prose | Use the established term; define it where the argument first needs it | Guide |
|
|
280
|
+
| [P5](prose.md#p5) | prose | Main text is literal: no idioms, metaphors, buzzwords, entertainment | Guide |
|
|
281
|
+
| [P6](prose.md#p6) | prose | Industry jargon only in an optional "Industry jargon" aside | Guide |
|
|
282
|
+
| [P7](prose.md#p7) | prose | One claim per sentence; every logical link stated | Guide |
|
|
283
|
+
| [P8](prose.md#p8) | prose, math | Words for a relation match the math exactly ("proportional to") | Guide |
|
|
284
|
+
| [P9](prose.md#p9) | prose, equation | A display equation's lead-in says what it gives and where it comes from | Guide |
|
|
285
|
+
|
|
286
|
+
_Element_ is what the rule is about; the first tag is primary. _Enforcement_ is
|
|
287
|
+
derived from the catalog: **Script** — every violation a check can see is
|
|
288
|
+
reported; **Partial** — checks exist and the rule says what they miss;
|
|
289
|
+
**Guide** — nothing runs, a reviewer (or the agent's own reading) is the
|
|
290
|
+
enforcement; **Locked** — the engine cannot run without it, so it has no
|
|
291
|
+
checkbox in the course settings. A `(warning)` / `(info)` code does not fail
|
|
292
|
+
the build. A rule with _settings_ takes them from `rules.<ID>` in the course
|
|
293
|
+
settings; the value shown is the default.
|
|
294
|
+
|
|
295
|
+
A rule that has been retired is not listed here at all — see
|
|
296
|
+
[retired.md](retired.md).
|
|
297
|
+
|
|
298
|
+
### Always enforced (invariants)
|
|
299
|
+
|
|
300
|
+
Not rules — what the syntax means. One entry per feature, always on, documented
|
|
301
|
+
next to the syntax it belongs to.
|
|
302
|
+
|
|
303
|
+
| Invariant | Element | Holds that | Codes |
|
|
304
|
+
| --- | --- | --- | --- |
|
|
305
|
+
| [`notation-references`](components.md#reference-systems) | notation, math | Notation keys are well-formed, unique, defined, and acyclic. | `undefined-reference`, `invalid-key`, `duplicate-key`, `duplicate-page`, `duplicate-definition`, `conflicting-definition`, `reference-cycle`, `gloss-collides-with-card`, `unknown-explicit-key`, `malformed-explicit-binding`, `unused-definition` (info) in [`registry.ts`](../../src/reference/registry.ts) `buildNotationRegistry`; [`math-glyphs.mjs`](../../src/reference/math-glyphs.mjs) `resolveMathGlyphs`; [`gate-math.ts`](../../src/reference/gate-math.ts) `reportUnknownScopeKeys` |
|
|
306
|
+
| [`math-syntax`](notation.md) | math | Every math span parses and resolves unambiguously. | `invalid-latex`, `invalid-latex-input`, `invalid-notation`, `invalid-definitions`, `unsupported-katex-version`, `ambiguous-span`, `ambiguous-base-fallback`, `ambiguous-canonical-notation`, `math-compile-error` in [`math-glyphs.mjs`](../../src/reference/math-glyphs.mjs) `resolveMathGlyphs`; [`gate-math.ts`](../../src/reference/gate-math.ts) `resolveInto` |
|
|
307
|
+
| [`keyed-floats`](structure.md#the-invariant-and-why-it-is-build-enforced) | equation, table, plot, diagram, assessment, heading | A keyed float’s `id` is well-formed and unique, it is named by its caption pair, and every `[[…]]` to it or to a section resolves. | `eq-duplicate-key`, `eq-ref-resolves`, `tab-invalid-key`, `tab-duplicate-key`, `tab-ref-resolves`, `tab-key-unused` (info), `tab-removed-prop`, `fig-invalid-key`, `fig-duplicate-key`, `fig-ref-resolves`, `fig-key-unused` (info), `fig-removed-prop`, `dia-invalid-key`, `dia-duplicate-key`, `dia-ref-resolves`, `dia-key-unused` (info), `dia-removed-prop`, `ex-invalid-key`, `ex-duplicate-key`, `ex-ref-resolves`, `ex-key-unused` (info), `ex-removed-prop`, `check-invalid-key`, `check-duplicate-key`, `check-ref-resolves`, `ex-missing-prop`, `sec-ref-resolves`, `fold-unnamed` in [`equations-validate.ts`](../../src/reference/equations-validate.ts) `validateEquations`; [`keyed-float-validate.ts`](../../src/reference/keyed-float-validate.ts) `validateKeyedFloats`; [`knowledge-checks-validate.ts`](../../src/reference/knowledge-checks-validate.ts) `validateKnowledgeChecks`; [`examples-validate.ts`](../../src/reference/examples-validate.ts) `validateExamples`; [`sections-validate.ts`](../../src/reference/sections-validate.ts) `validateSectionRefs`; [`folds-validate.ts`](../../src/reference/folds-validate.ts) `validateFolds` |
|
|
308
|
+
| [`course-settings`](README.md#amending) | changelog | The course settings name real rules and current keys. | `config-deprecated-key` (warning), `config-retired-rule` (warning) in [`settings.ts`](../../src/rules/settings.ts) `resolveRules` |
|
|
309
|
+
| [`waivers`](README.md#waiving-a-rule-at-one-place) | prose | A per-place waiver names a waivable rule, gives a reason, and covers something. | `waiver-malformed`, `waiver-invalid`, `waiver-unused` (warning) in [`waivers.ts`](../../src/rules/waivers.ts) `collectWaivers`, `applyWaivers` |
|
|
310
|
+
| [`curriculum`](structure.md#the-names) | changelog | The curriculum graph is well-formed. | `invalid-id`, `duplicate-id`, `unknown-reference`, `duplicate-reference`, `self-prerequisite`, `cycle`, `lesson-order`, `track-order`, `assessment-coverage`, `invalid-assessment`, `review-state`, `teaches-support`, `alignment-unknown-competency`, `alignment-unknown-lesson`, `alignment-introduction`, `alignment-unavailable`, `alignment-review-state` in [`validation.ts`](../../src/curriculum/validation.ts) `validateCurriculum`; [`curriculum-alignment.ts`](../../src/reference/curriculum-alignment.ts) `validateNotationAlignment` |
|
|
311
|
+
|
|
312
|
+
<!-- RULES-INDEX:END -->
|
package/docs/authoring/agents.md
CHANGED
|
@@ -14,6 +14,24 @@ and a rule disagree, the engine wins — see [`README.md`](README.md).
|
|
|
14
14
|
|
|
15
15
|
## The loop
|
|
16
16
|
|
|
17
|
+
- **Read the rules in effect first.** `pnpm --filter <course> content rules`
|
|
18
|
+
(or `build/rules-in-effect.md` after a `validate:content`) lists every rule
|
|
19
|
+
this course has *on*, grouped by the element it is about — prose, math,
|
|
20
|
+
equation, notation, heading, part-page, plot, diagram, table, assessment,
|
|
21
|
+
source, changelog — with its enforcement, its diagnostic codes, its
|
|
22
|
+
settings in effect, and a one-line summary. `--element table,prose` narrows
|
|
23
|
+
it to what you are editing; `--enforcement guide` shows what no script
|
|
24
|
+
checks and is therefore on you. Open a rule's page only when it is listed
|
|
25
|
+
there and you need the example. A rule that is not on the page is off for
|
|
26
|
+
this course (or does not exist): do not apply it, do not flag it in review.
|
|
27
|
+
A rule marked `waivable` there can be broken at one place with
|
|
28
|
+
`{/* explico-allow <ID>: <reason> */}` above the block — that is where the
|
|
29
|
+
reason for breaking a rule goes ([README.md § Waiving](README.md#waiving-a-rule-at-one-place)).
|
|
30
|
+
A line tagged `course` with an `X` ID is this course's own rule, written in
|
|
31
|
+
`course.settings.json` `courseRules`: it binds exactly like an engine rule,
|
|
32
|
+
and it is the one kind you may be asked to *add*
|
|
33
|
+
([README.md § Rules of your own](README.md#rules-of-your-own)) — never by
|
|
34
|
+
editing this folder.
|
|
17
35
|
- **Start from the CLI, not a file hunt.** `pnpm --filter <course> content
|
|
18
36
|
context <lesson>` prints a lesson plus exactly its notation, references, and
|
|
19
37
|
assumptions. `pnpm content status` is the draft-debt overview. `pnpm content
|
|
@@ -23,8 +41,8 @@ and a rule disagree, the engine wins — see [`README.md`](README.md).
|
|
|
23
41
|
non-zero on an error. Read those before opening files.
|
|
24
42
|
- **Validate, twice.** `pnpm --filter <course> validate:content` regenerates
|
|
25
43
|
`build/resolution/*` and then fails on the same run that changed them. Run it
|
|
26
|
-
again; the second run is clean.
|
|
27
|
-
|
|
44
|
+
again; the second run is clean. `build/` is git-ignored — there is nothing
|
|
45
|
+
to commit from it.
|
|
28
46
|
- **Before handing work back:** `validate:content` (×2) → `astro check` →
|
|
29
47
|
`astro build`. `astro build` is the only step that runs every gate the CI
|
|
30
48
|
does.
|
|
@@ -45,23 +63,51 @@ and a rule disagree, the engine wins — see [`README.md`](README.md).
|
|
|
45
63
|
- Pipe long command output to `| tail -n 40`. One-off probes and fetched pages
|
|
46
64
|
go to a scratch file you then grep — not into the conversation whole.
|
|
47
65
|
|
|
66
|
+
## Prose
|
|
67
|
+
|
|
68
|
+
Clarity comes before variety and entertainment, in lecture notes and
|
|
69
|
+
documentation alike. The `P` rules say how; which of them this course has on
|
|
70
|
+
is on the rules-in-effect page (`content rules --element prose`), so check a
|
|
71
|
+
draft against that list — not against a remembered version of
|
|
72
|
+
[`prose.md`](prose.md) — before handing it back. No script checks a `P` rule:
|
|
73
|
+
they are all `guide`, and the review is yours.
|
|
74
|
+
|
|
48
75
|
## Notation `formula:` fields (the sharp edges)
|
|
49
76
|
|
|
50
|
-
- Every glyph in a `formula:` must resolve: to the entry
|
|
51
|
-
`glosses:`, a card named with `\explain{key}{latex}`, or
|
|
52
|
-
An unresolved bare letter fails the build with the entry
|
|
77
|
+
- Every glyph in a `formula:` must resolve (rule N4, locked): to the entry
|
|
78
|
+
itself, one of its `glosses:`, a card named with `\explain{key}{latex}`, or
|
|
79
|
+
the base library. An unresolved bare letter fails the build with the entry
|
|
80
|
+
name.
|
|
53
81
|
- The notation reference graph must be **acyclic** — if `a`'s formula names `b`
|
|
54
82
|
and `b`'s names `a`, the build rejects it. Link only *down* a chain
|
|
55
83
|
(acceleration → velocity → position, not back up).
|
|
56
|
-
-
|
|
57
|
-
|
|
58
|
-
is
|
|
84
|
+
- `\mathbf` is the house style for a vector, and a bold letter is its own
|
|
85
|
+
symbol (rule N4): `\mathbf{v}` needs an entry (`latex: \mathbf{v}`) or an
|
|
86
|
+
`\explain{key}{\mathbf{v}}` wrap even when a scalar `v` is on the page. The
|
|
87
|
+
same holds for `\boldsymbol`, `\bm`, `\mathcal`, `\mathbb`, `\mathscr`,
|
|
88
|
+
`\mathfrak`, `\mathsf` and `\mathtt`. `\vec` renders, but it is a decoration
|
|
89
|
+
(rule N22), not a font.
|
|
90
|
+
|
|
91
|
+
## Decorations: `\hat`, `\bar`, `'`, `^*` (rule N22)
|
|
92
|
+
|
|
93
|
+
- A decoration is an operator. Before drafting, decide per decoration which of
|
|
94
|
+
the three it is on this page: a **whole form** with its own entry
|
|
95
|
+
(`latex: \hat{\beta}`) when the decorated symbol is a quantity in its own
|
|
96
|
+
right; an **operator entry** (`latex: \hat{}`, `{}'`, `{}^{*}`) when the
|
|
97
|
+
decoration means the same thing everywhere it appears; or on the course's
|
|
98
|
+
`rules.N22.allow` list. An unexplained one is an `accent-explained` warning.
|
|
99
|
+
- Reach for **suspension** (`notation.suspend` in the lesson frontmatter, with
|
|
100
|
+
a `reason`) only when the decoration is *not* its usual operator on that
|
|
101
|
+
page — primes that number versions (`b'`, `b''`) rather than
|
|
102
|
+
differentiate. Suspension makes every decorated form on the page need its
|
|
103
|
+
own entry, so it is stricter, not a shortcut; one whole-form entry is enough
|
|
104
|
+
when a single decorated symbol is special.
|
|
59
105
|
|
|
60
106
|
## Versioning
|
|
61
107
|
|
|
62
108
|
Every content change adds a bullet under `## [Unreleased]` in
|
|
63
109
|
`content/CHANGELOG.md`; a release moves it to a dated `## [x.y.z]` heading and
|
|
64
|
-
sets `about.version` to match, in the same commit. Rules C1–
|
|
110
|
+
sets `about.version` to match, in the same commit. Rules C1–C3,
|
|
65
111
|
[`versioning.md`](versioning.md).
|
|
66
112
|
|
|
67
113
|
## Upgrading the engine
|