@mmnto/totem 1.4.3 → 1.5.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.
Files changed (56) hide show
  1. package/dist/config-schema.d.ts +10 -0
  2. package/dist/config-schema.d.ts.map +1 -1
  3. package/dist/config-schema.js +2 -0
  4. package/dist/config-schema.js.map +1 -1
  5. package/dist/config-schema.test.js +32 -0
  6. package/dist/config-schema.test.js.map +1 -1
  7. package/dist/drift-detector.d.ts +3 -0
  8. package/dist/drift-detector.d.ts.map +1 -1
  9. package/dist/drift-detector.js.map +1 -1
  10. package/dist/index.d.ts +6 -0
  11. package/dist/index.d.ts.map +1 -1
  12. package/dist/index.js +3 -0
  13. package/dist/index.js.map +1 -1
  14. package/dist/ingest/pipeline.d.ts +1 -0
  15. package/dist/ingest/pipeline.d.ts.map +1 -1
  16. package/dist/ingest/pipeline.js +3 -0
  17. package/dist/ingest/pipeline.js.map +1 -1
  18. package/dist/lesson-frontmatter.d.ts +26 -0
  19. package/dist/lesson-frontmatter.d.ts.map +1 -0
  20. package/dist/lesson-frontmatter.js +85 -0
  21. package/dist/lesson-frontmatter.js.map +1 -0
  22. package/dist/lesson-frontmatter.test.d.ts +2 -0
  23. package/dist/lesson-frontmatter.test.d.ts.map +1 -0
  24. package/dist/lesson-frontmatter.test.js +225 -0
  25. package/dist/lesson-frontmatter.test.js.map +1 -0
  26. package/dist/lesson-io.d.ts +1 -1
  27. package/dist/lesson-io.d.ts.map +1 -1
  28. package/dist/lesson-io.js +25 -5
  29. package/dist/lesson-io.js.map +1 -1
  30. package/dist/lesson-io.test.js +111 -0
  31. package/dist/lesson-io.test.js.map +1 -1
  32. package/dist/registry.d.ts +42 -0
  33. package/dist/registry.d.ts.map +1 -0
  34. package/dist/registry.js +67 -0
  35. package/dist/registry.js.map +1 -0
  36. package/dist/registry.test.d.ts +2 -0
  37. package/dist/registry.test.d.ts.map +1 -0
  38. package/dist/registry.test.js +156 -0
  39. package/dist/registry.test.js.map +1 -0
  40. package/dist/sarif.d.ts +1 -0
  41. package/dist/sarif.d.ts.map +1 -1
  42. package/dist/sarif.js +8 -3
  43. package/dist/sarif.js.map +1 -1
  44. package/dist/sarif.test.js +1 -1
  45. package/dist/sarif.test.js.map +1 -1
  46. package/dist/store/lance-store.d.ts +2 -0
  47. package/dist/store/lance-store.d.ts.map +1 -1
  48. package/dist/store/lance-store.js +6 -0
  49. package/dist/store/lance-store.js.map +1 -1
  50. package/dist/store/lance-store.test.js +12 -0
  51. package/dist/store/lance-store.test.js.map +1 -1
  52. package/dist/types.d.ts +73 -0
  53. package/dist/types.d.ts.map +1 -1
  54. package/dist/types.js +33 -1
  55. package/dist/types.js.map +1 -1
  56. package/package.json +1 -1
@@ -0,0 +1,225 @@
1
+ import { describe, expect, it } from 'vitest';
2
+ import { buildFrontmatterFromLegacy, extractFrontmatter } from './lesson-frontmatter.js';
3
+ // ─── extractFrontmatter ──────────────────────────────
4
+ describe('extractFrontmatter', () => {
5
+ it('parses valid YAML frontmatter', () => {
6
+ const content = `---
7
+ category: security
8
+ severity: warning
9
+ tags: ["auth", "jwt"]
10
+ lifecycle: nursery
11
+ ---
12
+ ## Lesson — Test heading
13
+
14
+ Body text.`;
15
+ const result = extractFrontmatter(content);
16
+ expect(result.hadYaml).toBe(true);
17
+ expect(result.validYaml).toBe(true);
18
+ expect(result.frontmatter.category).toBe('security');
19
+ expect(result.frontmatter.severity).toBe('warning');
20
+ expect(result.frontmatter.tags).toEqual(['auth', 'jwt']);
21
+ expect(result.frontmatter.lifecycle).toBe('nursery');
22
+ expect(result.body).toContain('## Lesson — Test heading');
23
+ expect(result.body).not.toContain('---');
24
+ });
25
+ it('returns defaults when no YAML present', () => {
26
+ const content = `## Lesson — No frontmatter
27
+
28
+ **Tags:** foo, bar
29
+
30
+ Body.`;
31
+ const result = extractFrontmatter(content);
32
+ expect(result.hadYaml).toBe(false);
33
+ expect(result.validYaml).toBe(false);
34
+ expect(result.frontmatter.type).toBe('trap');
35
+ expect(result.frontmatter.severity).toBe('error');
36
+ expect(result.frontmatter.tags).toEqual([]);
37
+ expect(result.frontmatter.lifecycle).toBe('stable');
38
+ expect(result.body).toBe(content);
39
+ });
40
+ it('handles malformed YAML gracefully (fail-open)', () => {
41
+ const warnings = [];
42
+ const content = `---
43
+ category: [invalid
44
+ ---
45
+ ## Lesson — Bad yaml
46
+
47
+ Body.`;
48
+ const result = extractFrontmatter(content, (msg) => warnings.push(msg));
49
+ expect(result.hadYaml).toBe(true);
50
+ expect(result.validYaml).toBe(false);
51
+ expect(result.frontmatter.type).toBe('trap');
52
+ expect(result.body).toContain('## Lesson — Bad yaml');
53
+ expect(warnings.length).toBeGreaterThan(0);
54
+ });
55
+ it('handles invalid field values gracefully (fail-open)', () => {
56
+ const warnings = [];
57
+ const content = `---
58
+ severity: critical
59
+ category: nonexistent
60
+ ---
61
+ ## Lesson — Bad values
62
+
63
+ Body.`;
64
+ const result = extractFrontmatter(content, (msg) => warnings.push(msg));
65
+ expect(result.hadYaml).toBe(true);
66
+ expect(result.validYaml).toBe(false);
67
+ expect(result.frontmatter.severity).toBe('error'); // default
68
+ expect(warnings.length).toBeGreaterThan(0);
69
+ });
70
+ it('ignores ## inside YAML block (heading safety)', () => {
71
+ const content = `---
72
+ category: architecture
73
+ tags: ["## not a heading"]
74
+ ---
75
+ ## Lesson — Real heading
76
+
77
+ Body.`;
78
+ const result = extractFrontmatter(content);
79
+ expect(result.hadYaml).toBe(true);
80
+ expect(result.frontmatter.tags).toEqual(['## not a heading']);
81
+ expect(result.body).toContain('## Lesson — Real heading');
82
+ });
83
+ it('handles CRLF line endings', () => {
84
+ const content = '---\r\ncategory: security\r\nseverity: warning\r\n---\r\n## Lesson — CRLF\r\n\r\nBody.\r\n';
85
+ const result = extractFrontmatter(content);
86
+ expect(result.hadYaml).toBe(true);
87
+ expect(result.frontmatter.category).toBe('security');
88
+ expect(result.frontmatter.severity).toBe('warning');
89
+ expect(result.body).toContain('## Lesson — CRLF');
90
+ });
91
+ it('parses compilation block', () => {
92
+ const content = `---
93
+ compilation:
94
+ engine: regex
95
+ pattern: "\\\\beval\\\\("
96
+ severity: error
97
+ ---
98
+ ## Lesson — Eval trap
99
+
100
+ Body.`;
101
+ const result = extractFrontmatter(content);
102
+ expect(result.hadYaml).toBe(true);
103
+ expect(result.frontmatter.compilation?.engine).toBe('regex');
104
+ expect(result.frontmatter.compilation?.pattern).toBe('\\beval\\(');
105
+ });
106
+ it('parses ecosystem with multiple frameworks', () => {
107
+ const content = `---
108
+ ecosystem:
109
+ frameworks: ["nextjs", "react"]
110
+ ---
111
+ ## Lesson — Multi-framework
112
+
113
+ Body.`;
114
+ const result = extractFrontmatter(content);
115
+ expect(result.frontmatter.ecosystem?.frameworks).toEqual(['nextjs', 'react']);
116
+ });
117
+ it('parses scope with globs', () => {
118
+ const content = `---
119
+ scope:
120
+ globs: ["app/**/*.tsx", "!**/*.test.tsx"]
121
+ ---
122
+ ## Lesson — Scoped
123
+
124
+ Body.`;
125
+ const result = extractFrontmatter(content);
126
+ expect(result.frontmatter.scope?.globs).toEqual(['app/**/*.tsx', '!**/*.test.tsx']);
127
+ });
128
+ it('applies defaults for empty YAML block', () => {
129
+ const content = `---
130
+
131
+ ---
132
+ ## Lesson — Empty frontmatter
133
+
134
+ Body.`;
135
+ const result = extractFrontmatter(content);
136
+ expect(result.hadYaml).toBe(true);
137
+ expect(result.validYaml).toBe(true);
138
+ expect(result.frontmatter.type).toBe('trap');
139
+ expect(result.frontmatter.severity).toBe('error');
140
+ expect(result.frontmatter.lifecycle).toBe('stable');
141
+ expect(result.frontmatter.tags).toEqual([]);
142
+ });
143
+ it('validates rpn bounds', () => {
144
+ const warnings = [];
145
+ const content = `---
146
+ rpn: 15
147
+ ---
148
+ ## Lesson — Bad rpn
149
+
150
+ Body.`;
151
+ const result = extractFrontmatter(content, (msg) => warnings.push(msg));
152
+ expect(result.hadYaml).toBe(true);
153
+ expect(result.validYaml).toBe(false);
154
+ expect(warnings.length).toBeGreaterThan(0);
155
+ expect(result.frontmatter.rpn).toBeUndefined(); // default, rpn out of range
156
+ });
157
+ it('does not match --- inside YAML values', () => {
158
+ const content = `---
159
+ compilation:
160
+ pattern: "^---$"
161
+ tags: ["a---b"]
162
+ ---
163
+ ## Lesson — Tricky dashes
164
+
165
+ Body.`;
166
+ const result = extractFrontmatter(content);
167
+ expect(result.hadYaml).toBe(true);
168
+ expect(result.validYaml).toBe(true);
169
+ expect(result.frontmatter.compilation?.pattern).toBe('^---$');
170
+ expect(result.frontmatter.tags).toEqual(['a---b']);
171
+ });
172
+ it('accepts valid rpn', () => {
173
+ const content = `---
174
+ rpn: 8
175
+ ---
176
+ ## Lesson — Valid rpn
177
+
178
+ Body.`;
179
+ const result = extractFrontmatter(content);
180
+ expect(result.frontmatter.rpn).toBe(8);
181
+ });
182
+ });
183
+ // ─── buildFrontmatterFromLegacy ──────────────────────
184
+ describe('buildFrontmatterFromLegacy', () => {
185
+ it('maps tags into frontmatter', () => {
186
+ const fm = buildFrontmatterFromLegacy(['nextjs', 'auth'], '');
187
+ expect(fm.tags).toEqual(['nextjs', 'auth']);
188
+ expect(fm.type).toBe('trap');
189
+ });
190
+ it('maps legacy Pipeline 1 fields into compilation block', () => {
191
+ const body = `Some text.
192
+
193
+ **Pattern:** \\beval\\(
194
+ **Engine:** regex
195
+ **Scope:** **/*.ts, **/*.js
196
+ **Severity:** warning`;
197
+ const fm = buildFrontmatterFromLegacy([], body);
198
+ expect(fm.compilation?.engine).toBe('regex');
199
+ expect(fm.compilation?.pattern).toBe('\\beval\\(');
200
+ expect(fm.scope?.globs).toEqual(['**/*.ts', '**/*.js']);
201
+ expect(fm.severity).toBe('warning');
202
+ });
203
+ it('handles missing optional fields', () => {
204
+ const fm = buildFrontmatterFromLegacy([], 'Just a body.');
205
+ expect(fm.compilation).toBeUndefined();
206
+ expect(fm.scope).toBeUndefined();
207
+ expect(fm.severity).toBe('error'); // default
208
+ });
209
+ it('maps ast-grep engine', () => {
210
+ const body = `**Pattern:** pattern: try { $A } catch { }
211
+ **Engine:** ast-grep
212
+ **Severity:** error`;
213
+ const fm = buildFrontmatterFromLegacy([], body);
214
+ expect(fm.compilation?.engine).toBe('ast-grep');
215
+ });
216
+ it('preserves tags alongside Pipeline 1 fields', () => {
217
+ const body = `**Pattern:** \\bfoo\\b
218
+ **Engine:** regex
219
+ **Severity:** warning`;
220
+ const fm = buildFrontmatterFromLegacy(['tag1', 'tag2'], body);
221
+ expect(fm.tags).toEqual(['tag1', 'tag2']);
222
+ expect(fm.compilation?.engine).toBe('regex');
223
+ });
224
+ });
225
+ //# sourceMappingURL=lesson-frontmatter.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lesson-frontmatter.test.js","sourceRoot":"","sources":["../src/lesson-frontmatter.test.ts"],"names":[],"mappings":"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"}
@@ -18,5 +18,5 @@ export declare function writeLessonFileAsync(lessonsDir: string, entry: string):
18
18
  * and the new `.totem/lessons/*.md` directory. Each lesson gets a `sourcePath`
19
19
  * set to its origin file for prune operations.
20
20
  */
21
- export declare function readAllLessons(totemDir: string): ParsedLesson[];
21
+ export declare function readAllLessons(totemDir: string, onWarn?: (msg: string) => void): ParsedLesson[];
22
22
  //# sourceMappingURL=lesson-io.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"lesson-io.d.ts","sourceRoot":"","sources":["../src/lesson-io.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAIxD;;;GAGG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAGtD;AAkBD;;;GAGG;AACH,wBAAgB,eAAe,CAAC,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CASzE;AAED;;GAEG;AACH,wBAAsB,oBAAoB,CAAC,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAO7F;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,YAAY,EAAE,CAsC/D"}
1
+ {"version":3,"file":"lesson-io.d.ts","sourceRoot":"","sources":["../src/lesson-io.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAKxD;;;GAGG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAGtD;AAkBD;;;GAGG;AACH,wBAAgB,eAAe,CAAC,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CASzE;AAED;;GAEG;AACH,wBAAsB,oBAAoB,CAAC,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAO7F;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,GAAG,YAAY,EAAE,CA0D/F"}
package/dist/lesson-io.js CHANGED
@@ -3,6 +3,7 @@ import * as fs from 'node:fs';
3
3
  import * as path from 'node:path';
4
4
  import { parseLessonsFile } from './drift-detector.js';
5
5
  import { truncateHeading } from './lesson-format.js';
6
+ import { buildFrontmatterFromLegacy, extractFrontmatter } from './lesson-frontmatter.js';
6
7
  /**
7
8
  * Generate a deterministic, idempotent filename for a lesson entry.
8
9
  * Format: `lesson-<sha256(content).substring(0,8)>.md`
@@ -53,7 +54,7 @@ export async function writeLessonFileAsync(lessonsDir, entry) {
53
54
  * and the new `.totem/lessons/*.md` directory. Each lesson gets a `sourcePath`
54
55
  * set to its origin file for prune operations.
55
56
  */
56
- export function readAllLessons(totemDir) {
57
+ export function readAllLessons(totemDir, onWarn) {
57
58
  const allLessons = [];
58
59
  // 1. Read legacy .totem/lessons.md if it exists
59
60
  const legacyPath = path.join(totemDir, 'lessons.md');
@@ -61,6 +62,7 @@ export function readAllLessons(totemDir) {
61
62
  const content = fs.readFileSync(legacyPath, 'utf-8');
62
63
  const lessons = parseLessonsFile(content);
63
64
  for (const lesson of lessons) {
65
+ lesson.frontmatter = buildFrontmatterFromLegacy(lesson.tags, lesson.raw);
64
66
  lesson.sourcePath = legacyPath;
65
67
  }
66
68
  allLessons.push(...lessons);
@@ -75,11 +77,29 @@ export function readAllLessons(totemDir) {
75
77
  for (const file of files) {
76
78
  const filePath = path.join(lessonsDir, file);
77
79
  const content = fs.readFileSync(filePath, 'utf-8');
78
- const lessons = parseLessonsFile(content);
79
- for (const lesson of lessons) {
80
- lesson.sourcePath = filePath;
80
+ // ADR-070: detect YAML frontmatter for individual lesson files
81
+ const warn = onWarn ? (msg) => onWarn(`${filePath}: ${msg}`) : undefined;
82
+ const { frontmatter, body: strippedBody, validYaml } = extractFrontmatter(content, warn);
83
+ if (validYaml) {
84
+ const lessons = parseLessonsFile(strippedBody);
85
+ for (const lesson of lessons) {
86
+ lesson.frontmatter = frontmatter;
87
+ // YAML tags are the source of truth (copy to avoid shared reference)
88
+ lesson.tags = [...frontmatter.tags];
89
+ lesson.sourcePath = filePath;
90
+ }
91
+ allLessons.push(...lessons);
92
+ }
93
+ else {
94
+ // No YAML or invalid YAML — fall back to legacy field mapping
95
+ const legacyContent = strippedBody !== content ? strippedBody : content;
96
+ const lessons = parseLessonsFile(legacyContent);
97
+ for (const lesson of lessons) {
98
+ lesson.frontmatter = buildFrontmatterFromLegacy(lesson.tags, lesson.raw);
99
+ lesson.sourcePath = filePath;
100
+ }
101
+ allLessons.push(...lessons);
81
102
  }
82
- allLessons.push(...lessons);
83
103
  }
84
104
  }
85
105
  // Re-index all lessons sequentially
@@ -1 +1 @@
1
- {"version":3,"file":"lesson-io.js","sourceRoot":"","sources":["../src/lesson-io.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"lesson-io.js","sourceRoot":"","sources":["../src/lesson-io.ts"],"names":[],"mappings":"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"}
@@ -147,4 +147,115 @@ describe('readAllLessons', () => {
147
147
  expect(lessons[1].heading).toBe('Z');
148
148
  });
149
149
  });
150
+ describe('readAllLessons — YAML frontmatter (ADR-070)', () => {
151
+ let tmpDir;
152
+ beforeEach(() => {
153
+ tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'totem-lesson-io-yaml-'));
154
+ });
155
+ afterEach(() => {
156
+ fs.rmSync(tmpDir, { recursive: true, force: true });
157
+ });
158
+ it('parses YAML frontmatter from individual lesson files', () => {
159
+ const lessonsDir = path.join(tmpDir, 'lessons');
160
+ fs.mkdirSync(lessonsDir, { recursive: true });
161
+ fs.writeFileSync(path.join(lessonsDir, 'lesson-yaml.md'), `---
162
+ category: security
163
+ severity: warning
164
+ tags: ["auth", "jwt"]
165
+ lifecycle: nursery
166
+ ---
167
+ ## Lesson — YAML lesson
168
+
169
+ Body text.
170
+ `, 'utf-8');
171
+ const lessons = readAllLessons(tmpDir);
172
+ expect(lessons).toHaveLength(1);
173
+ expect(lessons[0].heading).toBe('YAML lesson');
174
+ expect(lessons[0].frontmatter?.category).toBe('security');
175
+ expect(lessons[0].frontmatter?.severity).toBe('warning');
176
+ expect(lessons[0].frontmatter?.tags).toEqual(['auth', 'jwt']);
177
+ expect(lessons[0].frontmatter?.lifecycle).toBe('nursery');
178
+ });
179
+ it('falls back to legacy parsing with frontmatter populated', () => {
180
+ const lessonsDir = path.join(tmpDir, 'lessons');
181
+ fs.mkdirSync(lessonsDir, { recursive: true });
182
+ fs.writeFileSync(path.join(lessonsDir, 'lesson-legacy.md'), `## Lesson — Legacy lesson
183
+
184
+ **Tags:** foo, bar
185
+
186
+ Body text.
187
+ `, 'utf-8');
188
+ const lessons = readAllLessons(tmpDir);
189
+ expect(lessons).toHaveLength(1);
190
+ expect(lessons[0].heading).toBe('Legacy lesson');
191
+ expect(lessons[0].tags).toEqual(['foo', 'bar']);
192
+ expect(lessons[0].frontmatter).toBeDefined();
193
+ expect(lessons[0].frontmatter?.tags).toEqual(['foo', 'bar']);
194
+ });
195
+ it('YAML tags are the source of truth', () => {
196
+ const lessonsDir = path.join(tmpDir, 'lessons');
197
+ fs.mkdirSync(lessonsDir, { recursive: true });
198
+ fs.writeFileSync(path.join(lessonsDir, 'lesson-override.md'), `---
199
+ tags: ["from-yaml"]
200
+ ---
201
+ ## Lesson — Override test
202
+
203
+ Body without inline tags.
204
+ `, 'utf-8');
205
+ const lessons = readAllLessons(tmpDir);
206
+ expect(lessons).toHaveLength(1);
207
+ expect(lessons[0].tags).toEqual(['from-yaml']);
208
+ });
209
+ it('falls back to legacy parsing when YAML is invalid', () => {
210
+ const lessonsDir = path.join(tmpDir, 'lessons');
211
+ fs.mkdirSync(lessonsDir, { recursive: true });
212
+ const warnings = [];
213
+ fs.writeFileSync(path.join(lessonsDir, 'lesson-bad-yaml.md'), `---
214
+ severity: critical
215
+ ---
216
+ ## Lesson — Bad yaml fallback
217
+
218
+ **Tags:** fallback-tag
219
+
220
+ **Pattern:** \\beval\\(
221
+ **Engine:** regex
222
+ **Severity:** warning
223
+ `, 'utf-8');
224
+ const lessons = readAllLessons(tmpDir, (msg) => warnings.push(msg));
225
+ expect(lessons).toHaveLength(1);
226
+ expect(lessons[0].tags).toEqual(['fallback-tag']);
227
+ expect(lessons[0].frontmatter?.compilation?.engine).toBe('regex');
228
+ expect(lessons[0].frontmatter?.severity).toBe('warning');
229
+ expect(warnings.length).toBeGreaterThan(0);
230
+ });
231
+ it('attaches frontmatter to legacy lessons.md entries', () => {
232
+ fs.writeFileSync(path.join(tmpDir, 'lessons.md'), '## Lesson — Legacy entry\n\n**Tags:** legacy\n\nLegacy body.\n', 'utf-8');
233
+ const lessons = readAllLessons(tmpDir);
234
+ expect(lessons).toHaveLength(1);
235
+ expect(lessons[0].frontmatter).toBeDefined();
236
+ expect(lessons[0].frontmatter?.tags).toEqual(['legacy']);
237
+ expect(lessons[0].frontmatter?.type).toBe('trap');
238
+ });
239
+ it('populates frontmatter from legacy Pipeline 1 fields', () => {
240
+ const lessonsDir = path.join(tmpDir, 'lessons');
241
+ fs.mkdirSync(lessonsDir, { recursive: true });
242
+ fs.writeFileSync(path.join(lessonsDir, 'lesson-p1.md'), `## Lesson — Pipeline 1 lesson
243
+
244
+ **Tags:** cli, parsing
245
+
246
+ Explanation text.
247
+
248
+ **Pattern:** \\beval\\(
249
+ **Engine:** regex
250
+ **Scope:** **/*.ts, **/*.js
251
+ **Severity:** warning
252
+ `, 'utf-8');
253
+ const lessons = readAllLessons(tmpDir);
254
+ expect(lessons).toHaveLength(1);
255
+ expect(lessons[0].frontmatter?.compilation?.engine).toBe('regex');
256
+ expect(lessons[0].frontmatter?.compilation?.pattern).toBe('\\beval\\(');
257
+ expect(lessons[0].frontmatter?.scope?.globs).toEqual(['**/*.ts', '**/*.js']);
258
+ expect(lessons[0].frontmatter?.severity).toBe('warning');
259
+ });
260
+ });
150
261
  //# sourceMappingURL=lesson-io.test.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"lesson-io.test.js","sourceRoot":"","sources":["../src/lesson-io.test.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"lesson-io.test.js","sourceRoot":"","sources":["../src/lesson-io.test.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAElC,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAErE,OAAO,EACL,cAAc,EACd,cAAc,EACd,eAAe,EACf,oBAAoB,GACrB,MAAM,gBAAgB,CAAC;AAExB,QAAQ,CAAC,gBAAgB,EAAE,GAAG,EAAE;IAC9B,EAAE,CAAC,+CAA+C,EAAE,GAAG,EAAE;QACvD,MAAM,IAAI,GAAG,cAAc,CAAC,qBAAqB,CAAC,CAAC;QACnD,MAAM,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,0BAA0B,CAAC,CAAC;IACnD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,qDAAqD,EAAE,GAAG,EAAE;QAC7D,MAAM,CAAC,GAAG,cAAc,CAAC,cAAc,CAAC,CAAC;QACzC,MAAM,CAAC,GAAG,cAAc,CAAC,cAAc,CAAC,CAAC;QACzC,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACpB,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,oDAAoD,EAAE,GAAG,EAAE;QAC5D,MAAM,CAAC,GAAG,cAAc,CAAC,WAAW,CAAC,CAAC;QACtC,MAAM,CAAC,GAAG,cAAc,CAAC,WAAW,CAAC,CAAC;QACtC,MAAM,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACxB,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,iBAAiB,EAAE,GAAG,EAAE;IAC/B,IAAI,MAAc,CAAC;IAEnB,UAAU,CAAC,GAAG,EAAE;QACd,MAAM,GAAG,EAAE,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE,EAAE,kBAAkB,CAAC,CAAC,CAAC;IACtE,CAAC,CAAC,CAAC;IAEH,SAAS,CAAC,GAAG,EAAE;QACb,EAAE,CAAC,MAAM,CAAC,MAAM,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IACtD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,8CAA8C,EAAE,GAAG,EAAE;QACtD,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;QAChD,MAAM,KAAK,GAAG,uDAAuD,CAAC;QACtE,MAAM,QAAQ,GAAG,eAAe,CAAC,UAAU,EAAE,KAAK,CAAC,CAAC;QAEpD,MAAM,CAAC,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC3C,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QAChD,MAAM,OAAO,GAAG,EAAE,CAAC,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;QACnD,MAAM,CAAC,OAAO,CAAC,CAAC,SAAS,CAAC,kBAAkB,CAAC,CAAC;QAC9C,MAAM,CAAC,OAAO,CAAC,CAAC,SAAS,CAAC,eAAe,CAAC,CAAC;QAC3C,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC5C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,2DAA2D,EAAE,GAAG,EAAE;QACnE,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;QAChD,MAAM,KAAK,GAAG,+CAA+C,CAAC;QAC9D,MAAM,KAAK,GAAG,eAAe,CAAC,UAAU,EAAE,KAAK,CAAC,CAAC;QACjD,MAAM,KAAK,GAAG,eAAe,CAAC,UAAU,EAAE,KAAK,CAAC,CAAC;QACjD,MAAM,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC1B,MAAM,KAAK,GAAG,EAAE,CAAC,WAAW,CAAC,UAAU,CAAC,CAAC;QACzC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;IACjE,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,mDAAmD,EAAE,GAAG,EAAE;QAC3D,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;QAChD,MAAM,WAAW,GACf,iGAAiG,CAAC;QACpG,MAAM,KAAK,GAAG,eAAe,WAAW,+BAA+B,CAAC;QACxE,MAAM,QAAQ,GAAG,eAAe,CAAC,UAAU,EAAE,KAAK,CAAC,CAAC;QACpD,MAAM,OAAO,GAAG,EAAE,CAAC,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;QACnD,MAAM,YAAY,GAAG,OAAO,CAAC,KAAK,CAAC,qBAAqB,CAAC,CAAC;QAC1D,MAAM,CAAC,YAAY,CAAC,CAAC,UAAU,EAAE,CAAC;QAClC,MAAM,CAAC,YAAa,CAAC,CAAC,CAAE,CAAC,MAAM,CAAC,CAAC,mBAAmB,CAAC,EAAE,CAAC,CAAC;IAC3D,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,6CAA6C,EAAE,GAAG,EAAE;QACrD,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;QAChD,MAAM,YAAY,GAAG,eAAe,CAAC;QACrC,MAAM,KAAK,GAAG,eAAe,YAAY,+BAA+B,CAAC;QACzE,MAAM,QAAQ,GAAG,eAAe,CAAC,UAAU,EAAE,KAAK,CAAC,CAAC;QACpD,MAAM,OAAO,GAAG,EAAE,CAAC,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;QACnD,MAAM,CAAC,OAAO,CAAC,CAAC,SAAS,CAAC,eAAe,YAAY,EAAE,CAAC,CAAC;IAC3D,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,sBAAsB,EAAE,GAAG,EAAE;IACpC,IAAI,MAAc,CAAC;IAEnB,UAAU,CAAC,GAAG,EAAE;QACd,MAAM,GAAG,EAAE,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE,EAAE,wBAAwB,CAAC,CAAC,CAAC;IAC5E,CAAC,CAAC,CAAC;IAEH,SAAS,CAAC,GAAG,EAAE;QACb,EAAE,CAAC,MAAM,CAAC,MAAM,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IACtD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,kDAAkD,EAAE,KAAK,IAAI,EAAE;QAChE,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;QAChD,MAAM,KAAK,GAAG,0DAA0D,CAAC;QACzE,MAAM,QAAQ,GAAG,MAAM,oBAAoB,CAAC,UAAU,EAAE,KAAK,CAAC,CAAC;QAE/D,MAAM,CAAC,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC3C,MAAM,OAAO,GAAG,EAAE,CAAC,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;QACnD,MAAM,CAAC,OAAO,CAAC,CAAC,SAAS,CAAC,gBAAgB,CAAC,CAAC;IAC9C,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,gBAAgB,EAAE,GAAG,EAAE;IAC9B,IAAI,MAAc,CAAC;IAEnB,UAAU,CAAC,GAAG,EAAE;QACd,MAAM,GAAG,EAAE,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE,EAAE,uBAAuB,CAAC,CAAC,CAAC;IAC3E,CAAC,CAAC,CAAC;IAEH,SAAS,CAAC,GAAG,EAAE;QACb,EAAE,CAAC,MAAM,CAAC,MAAM,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IACtD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,kDAAkD,EAAE,GAAG,EAAE;QAC1D,MAAM,OAAO,GAAG,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC,CAAC;QACjE,MAAM,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IAC9B,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,8BAA8B,EAAE,GAAG,EAAE;QACtC,EAAE,CAAC,aAAa,CACd,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,YAAY,CAAC,EAC/B,yEAAyE,EACzE,OAAO,CACR,CAAC;QACF,MAAM,OAAO,GAAG,cAAc,CAAC,MAAM,CAAC,CAAC;QACvC,MAAM,CAAC,OAAO,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;QAChC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAE,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QAC3C,MAAM,CAAC,OAAO,CAAC,CAAC,CAAE,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC,CAAC;IACvE,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,8BAA8B,EAAE,GAAG,EAAE;QACtC,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;QAChD,EAAE,CAAC,SAAS,CAAC,UAAU,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAC9C,EAAE,CAAC,aAAa,CACd,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,eAAe,CAAC,EACtC,2DAA2D,EAC3D,OAAO,CACR,CAAC;QACF,MAAM,OAAO,GAAG,cAAc,CAAC,MAAM,CAAC,CAAC;QACvC,MAAM,CAAC,OAAO,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;QAChC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAE,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;QAC/C,MAAM,CAAC,OAAO,CAAC,CAAC,CAAE,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,eAAe,CAAC,CAAC,CAAC;IAC9E,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,4CAA4C,EAAE,GAAG,EAAE;QACpD,6BAA6B;QAC7B,EAAE,CAAC,aAAa,CACd,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,YAAY,CAAC,EAC/B,uFAAuF,EACvF,OAAO,CACR,CAAC;QACF,0BAA0B;QAC1B,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;QAChD,EAAE,CAAC,SAAS,CAAC,UAAU,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAC9C,EAAE,CAAC,aAAa,CACd,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,eAAe,CAAC,EACtC,2CAA2C,EAC3C,OAAO,CACR,CAAC;QAEF,MAAM,OAAO,GAAG,cAAc,CAAC,MAAM,CAAC,CAAC;QACvC,MAAM,CAAC,OAAO,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;QAChC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAE,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACvC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAE,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAE,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACvC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAE,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAE,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACvC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAE,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACpC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,0CAA0C,EAAE,GAAG,EAAE;QAClD,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;QAChD,EAAE,CAAC,SAAS,CAAC,UAAU,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAC9C,EAAE,CAAC,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,UAAU,CAAC,EAAE,EAAE,EAAE,OAAO,CAAC,CAAC;QACjE,EAAE,CAAC,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,WAAW,CAAC,EAAE,cAAc,EAAE,OAAO,CAAC,CAAC;QAC9E,EAAE,CAAC,aAAa,CACd,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,eAAe,CAAC,EACtC,sDAAsD,EACtD,OAAO,CACR,CAAC;QACF,MAAM,OAAO,GAAG,cAAc,CAAC,MAAM,CAAC,CAAC;QACvC,MAAM,CAAC,OAAO,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;QAChC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAE,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAC3C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,uCAAuC,EAAE,GAAG,EAAE;QAC/C,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;QAChD,EAAE,CAAC,SAAS,CAAC,UAAU,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAC9C,EAAE,CAAC,aAAa,CACd,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,eAAe,CAAC,EACtC,sCAAsC,EACtC,OAAO,CACR,CAAC;QACF,EAAE,CAAC,aAAa,CACd,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,eAAe,CAAC,EACtC,sCAAsC,EACtC,OAAO,CACR,CAAC;QACF,MAAM,OAAO,GAAG,cAAc,CAAC,MAAM,CAAC,CAAC;QACvC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAE,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACtC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAE,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACxC,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,6CAA6C,EAAE,GAAG,EAAE;IAC3D,IAAI,MAAc,CAAC;IAEnB,UAAU,CAAC,GAAG,EAAE;QACd,MAAM,GAAG,EAAE,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE,EAAE,uBAAuB,CAAC,CAAC,CAAC;IAC3E,CAAC,CAAC,CAAC;IAEH,SAAS,CAAC,GAAG,EAAE;QACb,EAAE,CAAC,MAAM,CAAC,MAAM,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IACtD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,sDAAsD,EAAE,GAAG,EAAE;QAC9D,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;QAChD,EAAE,CAAC,SAAS,CAAC,UAAU,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAC9C,EAAE,CAAC,aAAa,CACd,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,gBAAgB,CAAC,EACvC;;;;;;;;;CASL,EACK,OAAO,CACR,CAAC;QACF,MAAM,OAAO,GAAG,cAAc,CAAC,MAAM,CAAC,CAAC;QACvC,MAAM,CAAC,OAAO,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;QAChC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAE,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;QAChD,MAAM,CAAC,OAAO,CAAC,CAAC,CAAE,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QAC3D,MAAM,CAAC,OAAO,CAAC,CAAC,CAAE,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QAC1D,MAAM,CAAC,OAAO,CAAC,CAAC,CAAE,CAAC,WAAW,EAAE,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC,CAAC;QAC/D,MAAM,CAAC,OAAO,CAAC,CAAC,CAAE,CAAC,WAAW,EAAE,SAAS,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IAC7D,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,yDAAyD,EAAE,GAAG,EAAE;QACjE,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;QAChD,EAAE,CAAC,SAAS,CAAC,UAAU,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAC9C,EAAE,CAAC,aAAa,CACd,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,kBAAkB,CAAC,EACzC;;;;;CAKL,EACK,OAAO,CACR,CAAC;QACF,MAAM,OAAO,GAAG,cAAc,CAAC,MAAM,CAAC,CAAC;QACvC,MAAM,CAAC,OAAO,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;QAChC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAE,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;QAClD,MAAM,CAAC,OAAO,CAAC,CAAC,CAAE,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC;QACjD,MAAM,CAAC,OAAO,CAAC,CAAC,CAAE,CAAC,WAAW,CAAC,CAAC,WAAW,EAAE,CAAC;QAC9C,MAAM,CAAC,OAAO,CAAC,CAAC,CAAE,CAAC,WAAW,EAAE,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC;IAChE,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,mCAAmC,EAAE,GAAG,EAAE;QAC3C,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;QAChD,EAAE,CAAC,SAAS,CAAC,UAAU,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAC9C,EAAE,CAAC,aAAa,CACd,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,oBAAoB,CAAC,EAC3C;;;;;;CAML,EACK,OAAO,CACR,CAAC;QACF,MAAM,OAAO,GAAG,cAAc,CAAC,MAAM,CAAC,CAAC;QACvC,MAAM,CAAC,OAAO,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;QAChC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAE,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC;IAClD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,mDAAmD,EAAE,GAAG,EAAE;QAC3D,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;QAChD,EAAE,CAAC,SAAS,CAAC,UAAU,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAC9C,MAAM,QAAQ,GAAa,EAAE,CAAC;QAC9B,EAAE,CAAC,aAAa,CACd,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,oBAAoB,CAAC,EAC3C;;;;;;;;;;CAUL,EACK,OAAO,CACR,CAAC;QACF,MAAM,OAAO,GAAG,cAAc,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;QACpE,MAAM,CAAC,OAAO,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;QAChC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAE,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC;QACnD,MAAM,CAAC,OAAO,CAAC,CAAC,CAAE,CAAC,WAAW,EAAE,WAAW,EAAE,MAAM,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACnE,MAAM,CAAC,OAAO,CAAC,CAAC,CAAE,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QAC1D,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC;IAC7C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,mDAAmD,EAAE,GAAG,EAAE;QAC3D,EAAE,CAAC,aAAa,CACd,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,YAAY,CAAC,EAC/B,gEAAgE,EAChE,OAAO,CACR,CAAC;QACF,MAAM,OAAO,GAAG,cAAc,CAAC,MAAM,CAAC,CAAC;QACvC,MAAM,CAAC,OAAO,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;QAChC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAE,CAAC,WAAW,CAAC,CAAC,WAAW,EAAE,CAAC;QAC9C,MAAM,CAAC,OAAO,CAAC,CAAC,CAAE,CAAC,WAAW,EAAE,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC;QAC1D,MAAM,CAAC,OAAO,CAAC,CAAC,CAAE,CAAC,WAAW,EAAE,IAAI,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IACrD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,qDAAqD,EAAE,GAAG,EAAE;QAC7D,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;QAChD,EAAE,CAAC,SAAS,CAAC,UAAU,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAC9C,EAAE,CAAC,aAAa,CACd,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,cAAc,CAAC,EACrC;;;;;;;;;;CAUL,EACK,OAAO,CACR,CAAC;QACF,MAAM,OAAO,GAAG,cAAc,CAAC,MAAM,CAAC,CAAC;QACvC,MAAM,CAAC,OAAO,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;QAChC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAE,CAAC,WAAW,EAAE,WAAW,EAAE,MAAM,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACnE,MAAM,CAAC,OAAO,CAAC,CAAC,CAAE,CAAC,WAAW,EAAE,WAAW,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;QACzE,MAAM,CAAC,OAAO,CAAC,CAAC,CAAE,CAAC,WAAW,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC,OAAO,CAAC,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC,CAAC;QAC9E,MAAM,CAAC,OAAO,CAAC,CAAC,CAAE,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IAC5D,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -0,0 +1,42 @@
1
+ import { z } from 'zod';
2
+ export declare const RegistryEntrySchema: z.ZodObject<{
3
+ path: z.ZodString;
4
+ chunkCount: z.ZodNumber;
5
+ lastSync: z.ZodString;
6
+ embedder: z.ZodString;
7
+ }, "passthrough", z.ZodTypeAny, z.objectOutputType<{
8
+ path: z.ZodString;
9
+ chunkCount: z.ZodNumber;
10
+ lastSync: z.ZodString;
11
+ embedder: z.ZodString;
12
+ }, z.ZodTypeAny, "passthrough">, z.objectInputType<{
13
+ path: z.ZodString;
14
+ chunkCount: z.ZodNumber;
15
+ lastSync: z.ZodString;
16
+ embedder: z.ZodString;
17
+ }, z.ZodTypeAny, "passthrough">>;
18
+ export declare const RegistrySchema: z.ZodRecord<z.ZodString, z.ZodObject<{
19
+ path: z.ZodString;
20
+ chunkCount: z.ZodNumber;
21
+ lastSync: z.ZodString;
22
+ embedder: z.ZodString;
23
+ }, "passthrough", z.ZodTypeAny, z.objectOutputType<{
24
+ path: z.ZodString;
25
+ chunkCount: z.ZodNumber;
26
+ lastSync: z.ZodString;
27
+ embedder: z.ZodString;
28
+ }, z.ZodTypeAny, "passthrough">, z.objectInputType<{
29
+ path: z.ZodString;
30
+ chunkCount: z.ZodNumber;
31
+ lastSync: z.ZodString;
32
+ embedder: z.ZodString;
33
+ }, z.ZodTypeAny, "passthrough">>>;
34
+ export type TotemRegistry = z.infer<typeof RegistrySchema>;
35
+ export type RegistryEntry = z.infer<typeof RegistryEntrySchema>;
36
+ export declare function readRegistry(): TotemRegistry;
37
+ /**
38
+ * Update a single entry in the global registry.
39
+ * Uses file locking to prevent concurrent sync processes from clobbering each other.
40
+ */
41
+ export declare function updateRegistryEntry(entry: RegistryEntry): Promise<void>;
42
+ //# sourceMappingURL=registry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../src/registry.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAIxB,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;gCAOhB,CAAC;AAEjB,eAAO,MAAM,cAAc;;;;;;;;;;;;;;;iCAA4C,CAAC;AACxE,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,cAAc,CAAC,CAAC;AAC3D,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAC;AAYhE,wBAAgB,YAAY,IAAI,aAAa,CAS5C;AAED;;;GAGG;AACH,wBAAsB,mBAAmB,CAAC,KAAK,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CA+B7E"}
@@ -0,0 +1,67 @@
1
+ import fs from 'node:fs';
2
+ import os from 'node:os';
3
+ import path from 'node:path';
4
+ import { z } from 'zod';
5
+ import { acquireLock } from './lock.js';
6
+ export const RegistryEntrySchema = z
7
+ .object({
8
+ path: z.string(),
9
+ chunkCount: z.number(),
10
+ lastSync: z.string(),
11
+ embedder: z.string(),
12
+ })
13
+ .passthrough(); // Preserve unknown fields from newer CLI versions
14
+ export const RegistrySchema = z.record(z.string(), RegistryEntrySchema);
15
+ /** Resolve the registry directory lazily so tests can mock os.homedir(). */
16
+ function registryDir() {
17
+ return path.join(os.homedir(), '.totem');
18
+ }
19
+ /** Resolve the registry file path lazily so tests can mock os.homedir(). */
20
+ function registryPath() {
21
+ return path.join(registryDir(), 'registry.json');
22
+ }
23
+ export function readRegistry() {
24
+ try {
25
+ const raw = fs.readFileSync(registryPath(), 'utf-8');
26
+ const parsed = JSON.parse(raw); // totem-ignore — Zod safeParse handles validation
27
+ const result = RegistrySchema.safeParse(parsed);
28
+ return result.success ? result.data : {};
29
+ }
30
+ catch {
31
+ return {};
32
+ }
33
+ }
34
+ /**
35
+ * Update a single entry in the global registry.
36
+ * Uses file locking to prevent concurrent sync processes from clobbering each other.
37
+ */
38
+ export async function updateRegistryEntry(entry) {
39
+ const dir = registryDir();
40
+ const filePath = registryPath();
41
+ fs.mkdirSync(dir, { recursive: true });
42
+ // Acquire lock to prevent TOCTOU races from concurrent syncs
43
+ const release = await acquireLock(dir);
44
+ try {
45
+ // If the file exists but can't be read/parsed, throw to prevent silent data loss.
46
+ // The caller (sync.ts) wraps this in try/catch and logs the warning.
47
+ let registry = {};
48
+ if (fs.existsSync(filePath)) {
49
+ const raw = fs.readFileSync(filePath, 'utf-8');
50
+ const parsed = JSON.parse(raw); // totem-ignore — Zod safeParse handles validation
51
+ const result = RegistrySchema.safeParse(parsed);
52
+ if (!result.success) {
53
+ throw new Error('Registry file has invalid schema — refusing to overwrite. Delete ~/.totem/registry.json to reset.');
54
+ }
55
+ registry = result.data;
56
+ }
57
+ registry[entry.path] = entry;
58
+ // PID-unique temp file prevents collision on write
59
+ const tmpPath = `${filePath}.${process.pid}.tmp`;
60
+ fs.writeFileSync(tmpPath, JSON.stringify(registry, null, 2) + '\n');
61
+ fs.renameSync(tmpPath, filePath);
62
+ }
63
+ finally {
64
+ release();
65
+ }
66
+ }
67
+ //# sourceMappingURL=registry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry.js","sourceRoot":"","sources":["../src/registry.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=registry.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry.test.d.ts","sourceRoot":"","sources":["../src/registry.test.ts"],"names":[],"mappings":""}