explico 0.1.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.
Files changed (113) hide show
  1. package/README.md +108 -0
  2. package/dist/analytics/AnalyticsEmitter.d.ts +22 -0
  3. package/dist/analytics/AnalyticsEmitter.js +5 -0
  4. package/dist/compiler/cli.d.ts +189 -0
  5. package/dist/compiler/cli.js +552 -0
  6. package/dist/compiler/collections.d.ts +70 -0
  7. package/dist/compiler/collections.js +383 -0
  8. package/dist/compiler/course-config.d.ts +31 -0
  9. package/dist/compiler/course-config.js +0 -0
  10. package/dist/compiler/lesson-derivation.d.ts +89 -0
  11. package/dist/compiler/lesson-derivation.js +91 -0
  12. package/dist/compiler/manifest.d.ts +178 -0
  13. package/dist/compiler/manifest.js +345 -0
  14. package/dist/compiler/resolution-report.d.ts +45 -0
  15. package/dist/compiler/resolution-report.js +97 -0
  16. package/dist/curriculum/validation.d.ts +76 -0
  17. package/dist/curriculum/validation.js +320 -0
  18. package/dist/progress/ProgressRepository.d.ts +53 -0
  19. package/dist/progress/ProgressRepository.js +12 -0
  20. package/dist/reference/base-library.mjs +27 -0
  21. package/dist/reference/citation-format.mjs +133 -0
  22. package/dist/reference/consistency.d.ts +64 -0
  23. package/dist/reference/consistency.js +234 -0
  24. package/dist/reference/curriculum-alignment.d.ts +7 -0
  25. package/dist/reference/curriculum-alignment.js +166 -0
  26. package/dist/reference/equations-validate.d.ts +50 -0
  27. package/dist/reference/equations-validate.js +90 -0
  28. package/dist/reference/equations.mjs +144 -0
  29. package/dist/reference/gate-math.d.ts +41 -0
  30. package/dist/reference/gate-math.js +151 -0
  31. package/dist/reference/katex-options.mjs +91 -0
  32. package/dist/reference/lab-math-scope.d.ts +21 -0
  33. package/dist/reference/lab-math-scope.js +28 -0
  34. package/dist/reference/label.d.ts +11 -0
  35. package/dist/reference/label.js +38 -0
  36. package/dist/reference/lint-ignore.d.ts +32 -0
  37. package/dist/reference/lint-ignore.js +39 -0
  38. package/dist/reference/math-glyphs.mjs +830 -0
  39. package/dist/reference/prose.d.ts +15 -0
  40. package/dist/reference/prose.js +12 -0
  41. package/dist/reference/references.d.ts +17 -0
  42. package/dist/reference/references.js +42 -0
  43. package/dist/reference/registry.d.ts +6 -0
  44. package/dist/reference/registry.js +548 -0
  45. package/dist/reference/rehype-fail-katex-errors.mjs +55 -0
  46. package/dist/reference/remark-citation.mjs +0 -0
  47. package/dist/reference/remark-notation.mjs +753 -0
  48. package/dist/reference/render-lab-math.d.ts +21 -0
  49. package/dist/reference/render-lab-math.js +58 -0
  50. package/dist/reference/types.d.ts +151 -0
  51. package/dist/reference/types.js +0 -0
  52. package/dist/reference/units-vocab.d.ts +26 -0
  53. package/dist/reference/units-vocab.js +119 -0
  54. package/dist/session/PreferenceStore.d.ts +28 -0
  55. package/dist/session/PreferenceStore.js +30 -0
  56. package/dist/session/user-context.d.ts +7 -0
  57. package/dist/session/user-context.js +10 -0
  58. package/dist/session/user.d.ts +21 -0
  59. package/dist/session/user.js +8 -0
  60. package/package.json +53 -0
  61. package/src/analytics/AnalyticsEmitter.ts +23 -0
  62. package/src/compiler/cli.ts +866 -0
  63. package/src/compiler/collections.ts +554 -0
  64. package/src/compiler/course-config.ts +32 -0
  65. package/src/compiler/lesson-derivation.ts +186 -0
  66. package/src/compiler/manifest.ts +601 -0
  67. package/src/compiler/resolution-report.ts +150 -0
  68. package/src/components/CurriculumMap.astro +208 -0
  69. package/src/components/HoverPanel.astro +67 -0
  70. package/src/components/assessments/AssessmentRunner.tsx +320 -0
  71. package/src/components/assessments/AssessmentSet.astro +54 -0
  72. package/src/components/citation/CitationLayer.astro +173 -0
  73. package/src/components/examples/CompactExample.astro +34 -0
  74. package/src/components/examples/CompactExamples.astro +253 -0
  75. package/src/components/hover-panel.ts +273 -0
  76. package/src/components/notation/NotationGlossary.astro +412 -0
  77. package/src/components/notation/NotationLayer.astro +594 -0
  78. package/src/components/notation/NotationMath.astro +24 -0
  79. package/src/components/notation/SafeMathNode.astro +23 -0
  80. package/src/components/notation/render-notation-math.ts +223 -0
  81. package/src/components/starlight/EquationEnhancer.astro +72 -0
  82. package/src/components/starlight/LayoutHeader.astro +102 -0
  83. package/src/components/starlight/LayoutPageSidebar.astro +33 -0
  84. package/src/components/starlight/LayoutSidebar.astro +29 -0
  85. package/src/components/starlight/LessonFooter.astro +58 -0
  86. package/src/content-config.ts +259 -0
  87. package/src/curriculum/validation.ts +481 -0
  88. package/src/progress/ProgressRepository.ts +64 -0
  89. package/src/reference/base-library.mjs +27 -0
  90. package/src/reference/citation-format.mjs +133 -0
  91. package/src/reference/consistency.ts +375 -0
  92. package/src/reference/curriculum-alignment.ts +228 -0
  93. package/src/reference/equations-validate.ts +167 -0
  94. package/src/reference/equations.mjs +144 -0
  95. package/src/reference/gate-math.ts +250 -0
  96. package/src/reference/katex-options.mjs +91 -0
  97. package/src/reference/lab-math-scope.ts +54 -0
  98. package/src/reference/label.ts +47 -0
  99. package/src/reference/lint-ignore.ts +75 -0
  100. package/src/reference/math-glyphs.mjs +830 -0
  101. package/src/reference/prose.ts +21 -0
  102. package/src/reference/references.ts +82 -0
  103. package/src/reference/registry.ts +723 -0
  104. package/src/reference/rehype-fail-katex-errors.mjs +55 -0
  105. package/src/reference/remark-citation.mjs +0 -0
  106. package/src/reference/remark-notation.mjs +753 -0
  107. package/src/reference/render-lab-math.ts +99 -0
  108. package/src/reference/types.ts +182 -0
  109. package/src/reference/units-vocab.ts +143 -0
  110. package/src/session/PreferenceStore.ts +54 -0
  111. package/src/session/user-context.ts +18 -0
  112. package/src/session/user.ts +24 -0
  113. package/src/styles/global.css +763 -0
@@ -0,0 +1,259 @@
1
+ import { defineCollection } from 'astro:content';
2
+ import { glob } from 'astro/loaders';
3
+ import { z } from 'astro/zod';
4
+ import { docsSchema } from '@astrojs/starlight/schema';
5
+ import { isSubstantiveMeaning } from './reference/prose';
6
+
7
+ // Phase F: content lives in the top-level `content/` folder, not `src/content/`.
8
+ // `docsLoader()` is hard-wired to `<srcDir>/content/docs`, so the `docs`
9
+ // collection uses a plain glob with the same extensions and `_`-prefix ignore.
10
+ const CONTENT_DIR = './content';
11
+ const docsGlob = glob({
12
+ base: `${CONTENT_DIR}/docs`,
13
+ pattern: '**/[^_]*.{md,mdx}',
14
+ });
15
+
16
+ const editorialStatus = z.enum(['draft', 'in-review', 'reviewed']);
17
+ const id = z.string().regex(/^[a-z0-9]+(?:[.-][a-z0-9]+)*$/);
18
+
19
+ /**
20
+ * Notation `meaning` / `summary`: plain prose (no `$`, `\`, backticks), and —
21
+ * the C1b safeguard — substantive, not a placeholder. A short or blocklisted
22
+ * phrase fails the build so a local symbol cannot get a glossary-style panel
23
+ * for a throwaway definition.
24
+ */
25
+ const notationProse = z
26
+ .string()
27
+ .min(1)
28
+ .refine((value) => !/[\\$`]/.test(value), {
29
+ message:
30
+ 'Notation meaning/summary must be plain prose; render the symbol or formula in its dedicated field.',
31
+ })
32
+ .refine(isSubstantiveMeaning, {
33
+ message:
34
+ 'Notation meaning must be substantive prose (at least four words, not a placeholder).',
35
+ });
36
+
37
+ const notationAlignment = z.discriminatedUnion('kind', [
38
+ z.object({
39
+ kind: z.literal('competency'),
40
+ introducedByCompetency: id,
41
+ introducedInLesson: id,
42
+ }),
43
+ z.object({
44
+ kind: z.literal('general'),
45
+ rationale: z.string().min(1),
46
+ }),
47
+ ]);
48
+ const notationAlignmentDefault = notationAlignment.default({
49
+ kind: 'general',
50
+ rationale: 'General notation.',
51
+ });
52
+
53
+ /**
54
+ * A citation on a notation definition: a bare id (locator pending, see D6/g) or
55
+ * `{id, locator}` — a per-claim locator verified against the cited text.
56
+ */
57
+ const notationSource = z.union([
58
+ id,
59
+ z.object({ id, locator: z.string().min(1) }),
60
+ ]);
61
+
62
+ /**
63
+ * One notation entry shape (Phase C1b), shared by page-local `notation.local`
64
+ * and the standalone `notation` collection.
65
+ *
66
+ * Authored: `key`, `latex`, `meaning`, optional `formula`, optional `units`
67
+ * (or `dimensionless: true`), `seeAlso`, `sources` (`{id, locator}`),
68
+ * optional `alignment` (defaults to `general`), optional `label`.
69
+ *
70
+ * The display label defaults to the humanized `key` (see `reference/label.ts`);
71
+ * `label` is authored only where that reads wrong. The `notationProse`
72
+ * refinement rejects an under-specified `meaning`.
73
+ */
74
+ const notationEntryShape = z.object({
75
+ key: id,
76
+ latex: z.string().min(1),
77
+ meaning: notationProse,
78
+ formula: z.string().min(1).optional(),
79
+ units: z.string().min(1).optional(),
80
+ dimensionless: z.literal(true).optional(),
81
+ seeAlso: z.array(id).default([]),
82
+ sources: z.array(notationSource).default([]),
83
+ alignment: notationAlignmentDefault,
84
+ label: z.string().min(1).optional(),
85
+ });
86
+
87
+ const localNotationDefinition = notationEntryShape;
88
+
89
+ const lessonNotation = z
90
+ .object({
91
+ // `notation.uses` is retired (D3): a lesson pulls a shared key into scope
92
+ // by referencing it in prose (`[[key]]`) or math (`\explain`).
93
+ local: z.array(localNotationDefinition).default([]),
94
+ })
95
+ .default({ local: [] });
96
+
97
+ /**
98
+ * Lesson frontmatter — reduced shape (Phase C1 schema, C2 codemod applied).
99
+ *
100
+ * Authored: `title`, `description` (Starlight base), `teaches` (ordered — the
101
+ * curriculum contract, never derived), `assumptions`,
102
+ * `notation.local` (page-local symbols only).
103
+ * Artifact: `editorialStatus` (human-set trust flag).
104
+ * Derived (in `content/collections.ts` + `content/lesson-derivation.ts`, never
105
+ * authored): `lessonId` (doc slug), `requires` (direct competency-DAG
106
+ * prerequisites of `teaches`, minus `teaches`), `sources` (`[@…]`
107
+ * occurrences), `assessments` (colocated `<lesson>.checks.yml`),
108
+ * `sidebar` order (track order).
109
+ * Dropped: `aiAssisted`, `lastReviewed`, `riskTier`, `estimatedMinutes`
110
+ * (git history + `editorialStatus` + `NEEDS_SOURCE` carry provenance);
111
+ * `notation.uses` (D3 — a shared symbol is imported by using it).
112
+ */
113
+ const docs = defineCollection({
114
+ loader: docsGlob,
115
+ schema: docsSchema({
116
+ extend: z.object({
117
+ editorialStatus: editorialStatus.default('draft'),
118
+ teaches: z.array(id).default([]),
119
+ assumptions: z.array(z.string().min(1)).default([]),
120
+ notation: lessonNotation,
121
+ }),
122
+ }),
123
+ });
124
+
125
+ const competencies = defineCollection({
126
+ loader: glob({
127
+ pattern: '**/*.json',
128
+ base: './content/competencies',
129
+ }),
130
+ schema: z.object({
131
+ id,
132
+ title: z.string().min(1),
133
+ domain: id,
134
+ facet: z.enum([
135
+ 'knowledge',
136
+ 'calculation',
137
+ 'interpretation',
138
+ 'convention',
139
+ 'risk',
140
+ ]),
141
+ outcome: z.string().min(1),
142
+ prerequisites: z.array(id).default([]),
143
+ evidence: z.object({
144
+ minimumIndependentItems: z.number().int().min(1),
145
+ requiresTransfer: z.boolean(),
146
+ requiresUnassistedPass: z.boolean(),
147
+ }),
148
+ misconceptions: z.array(z.string().min(1)).default([]),
149
+ editorialStatus,
150
+ }),
151
+ });
152
+
153
+ const assessmentItemBase = z.object({
154
+ id,
155
+ competencyId: id,
156
+ evidenceKind: z.enum(['direct', 'transfer']),
157
+ prompt: z.string().min(1),
158
+ explanation: z.string().min(1),
159
+ });
160
+
161
+ const assessments = defineCollection({
162
+ loader: glob({
163
+ pattern: '**/*.json',
164
+ base: './content/assessments',
165
+ }),
166
+ schema: z.object({
167
+ id,
168
+ title: z.string().min(1),
169
+ editorialStatus,
170
+ items: z
171
+ .array(
172
+ z.discriminatedUnion('type', [
173
+ assessmentItemBase.extend({
174
+ type: z.literal('numeric'),
175
+ answer: z.object({
176
+ value: z.number(),
177
+ tolerance: z.number().positive(),
178
+ }),
179
+ }),
180
+ assessmentItemBase.extend({
181
+ type: z.literal('single-choice'),
182
+ options: z
183
+ .array(
184
+ z.object({
185
+ id,
186
+ label: z.string().min(1),
187
+ }),
188
+ )
189
+ .min(2),
190
+ correctOptionId: id,
191
+ }),
192
+ ]),
193
+ )
194
+ .min(1),
195
+ }),
196
+ });
197
+
198
+ const tracks = defineCollection({
199
+ loader: glob({ pattern: '**/*.json', base: './content/tracks' }),
200
+ schema: z.object({
201
+ id,
202
+ title: z.string().min(1),
203
+ description: z.string().min(1),
204
+ audience: z.string().min(1),
205
+ entryAssumptions: z.array(z.string().min(1)),
206
+ lessons: z.array(id).min(1),
207
+ editorialStatus,
208
+ }),
209
+ });
210
+
211
+ const sources = defineCollection({
212
+ loader: glob({ pattern: '**/*.json', base: './content/sources' }),
213
+ schema: z.object({
214
+ id,
215
+ type: z.enum([
216
+ 'primary',
217
+ 'official-guidance',
218
+ 'paper',
219
+ 'book',
220
+ 'secondary',
221
+ ]),
222
+ title: z.string().min(1),
223
+ authors: z.array(z.string().min(1)).optional(),
224
+ organization: z.string().min(1).optional(),
225
+ edition: z.string().optional(),
226
+ publisher: z.string().optional(),
227
+ year: z.number().int().optional(),
228
+ isbn: z.string().optional(),
229
+ url: z.url().optional(),
230
+ locator: z.string().optional(),
231
+ accessed: z.coerce.date().optional(),
232
+ licenseNotes: z.string().optional(),
233
+ editorialStatus,
234
+ }),
235
+ });
236
+
237
+ /**
238
+ * Standalone notation collection — the one `notationEntry` shape plus the
239
+ * shared-only extras: `domain`, `aliases`, its own `editorialStatus`, and a
240
+ * Markdown body.
241
+ */
242
+ const notation = defineCollection({
243
+ loader: glob({ pattern: '**/*.md', base: './content/notation' }),
244
+ schema: notationEntryShape.extend({
245
+ domain: id,
246
+ aliases: z.array(z.string().min(1)).default([]),
247
+ editorialStatus,
248
+ aiAssisted: z.boolean().default(false),
249
+ }),
250
+ });
251
+
252
+ export const collections = {
253
+ docs,
254
+ competencies,
255
+ assessments,
256
+ tracks,
257
+ sources,
258
+ notation,
259
+ };