@mmnto/totem 1.34.0 → 1.34.2

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.
@@ -4,8 +4,14 @@ export declare const SENTINEL_END = "<!-- totem:generated:end -->";
4
4
  /**
5
5
  * Format parsed lessons as a markdown block for injection into AI config files.
6
6
  * Always generates sentinel markers (even for empty lessons) to preserve idempotency.
7
+ *
8
+ * When `archivedReasonByHash` is provided, lessons whose content-hash is in the
9
+ * map get an `_(archived: <reason>)_` suffix so a reading agent can weight the
10
+ * guidance appropriately. Empty / missing reasons fall back to a plain bullet
11
+ * (Tenet 4 spirit — surface the rule loudly even with degraded metadata).
12
+ * Per mmnto-ai/totem#1873.
7
13
  */
8
- export declare function formatLessonsAsMarkdown(lessons: ParsedLesson[]): string;
14
+ export declare function formatLessonsAsMarkdown(lessons: ParsedLesson[], archivedReasonByHash?: ReadonlyMap<string, string>): string;
9
15
  /**
10
16
  * Inject a generated block between sentinel markers in file content.
11
17
  * - If sentinels exist: replaces content between them (inclusive)
@@ -16,6 +22,10 @@ export declare function injectSentinelBlock(existingContent: string, generatedBl
16
22
  /**
17
23
  * Export formatted lessons to a target file path.
18
24
  * Creates directories if needed. Uses sentinel-based injection for idempotent updates.
25
+ *
26
+ * When `archivedReasonByHash` is provided, lessons whose content-hash appears
27
+ * in the map render with an `_(archived: <reason>)_` annotation suffix
28
+ * (mmnto-ai/totem#1873).
19
29
  */
20
- export declare function exportLessons(lessons: ParsedLesson[], targetPath: string): void;
30
+ export declare function exportLessons(lessons: ParsedLesson[], targetPath: string, archivedReasonByHash?: ReadonlyMap<string, string>): void;
21
31
  //# sourceMappingURL=exporter.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"exporter.d.ts","sourceRoot":"","sources":["../src/exporter.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAKxD,eAAO,MAAM,cAAc,mCAAmC,CAAC;AAC/D,eAAO,MAAM,YAAY,iCAAiC,CAAC;AAI3D;;;GAGG;AACH,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,YAAY,EAAE,GAAG,MAAM,CAoBvE;AAID;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,eAAe,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,GAAG,MAAM,CA6B3F;AAID;;;GAGG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,YAAY,EAAE,EAAE,UAAU,EAAE,MAAM,GAAG,IAAI,CAe/E"}
1
+ {"version":3,"file":"exporter.d.ts","sourceRoot":"","sources":["../src/exporter.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAKxD,eAAO,MAAM,cAAc,mCAAmC,CAAC;AAC/D,eAAO,MAAM,YAAY,iCAAiC,CAAC;AAI3D;;;;;;;;;GASG;AACH,wBAAgB,uBAAuB,CACrC,OAAO,EAAE,YAAY,EAAE,EACvB,oBAAoB,CAAC,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,GACjD,MAAM,CA6BR;AAID;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,eAAe,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,GAAG,MAAM,CA6B3F;AAID;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAC3B,OAAO,EAAE,YAAY,EAAE,EACvB,UAAU,EAAE,MAAM,EAClB,oBAAoB,CAAC,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,GACjD,IAAI,CAeN"}
package/dist/exporter.js CHANGED
@@ -1,5 +1,6 @@
1
1
  import * as fs from 'node:fs';
2
2
  import * as path from 'node:path';
3
+ import { hashLesson } from './compiler.js';
3
4
  import { TotemParseError } from './errors.js';
4
5
  // ─── Constants ─────────────────────────────────────────
5
6
  export const SENTINEL_START = '<!-- totem:generated:start -->';
@@ -8,8 +9,14 @@ export const SENTINEL_END = '<!-- totem:generated:end -->';
8
9
  /**
9
10
  * Format parsed lessons as a markdown block for injection into AI config files.
10
11
  * Always generates sentinel markers (even for empty lessons) to preserve idempotency.
12
+ *
13
+ * When `archivedReasonByHash` is provided, lessons whose content-hash is in the
14
+ * map get an `_(archived: <reason>)_` suffix so a reading agent can weight the
15
+ * guidance appropriately. Empty / missing reasons fall back to a plain bullet
16
+ * (Tenet 4 spirit — surface the rule loudly even with degraded metadata).
17
+ * Per mmnto-ai/totem#1873.
11
18
  */
12
- export function formatLessonsAsMarkdown(lessons) {
19
+ export function formatLessonsAsMarkdown(lessons, archivedReasonByHash) {
13
20
  const lines = [
14
21
  SENTINEL_START,
15
22
  '<!-- Auto-generated by `totem compile --export`. Do not edit between these markers. -->',
@@ -17,12 +24,22 @@ export function formatLessonsAsMarkdown(lessons) {
17
24
  '## Totem Project Rules',
18
25
  '',
19
26
  ];
27
+ const escapeMarkdown = (s) => s.replace(/[*_]/g, '\\$&');
28
+ // Strip C0 control bytes (incl. CR/LF/TAB) so an archivedReason copied
29
+ // from an operator's terminal session cannot break the bullet shape or
30
+ // bleed across lines. Mirrors the sanitizing discipline applied to
31
+ // lesson body content above (per CR mmnto-ai/totem#1878).
32
+ const sanitizeReason = (s) => escapeMarkdown(s.replace(/[\x00-\x1F\x7F]/g, ' ').trim());
20
33
  for (const lesson of lessons) {
21
- const escapeMarkdown = (s) => s.replace(/[*_]/g, '\\$&');
22
34
  const heading = escapeMarkdown(lesson.heading);
23
35
  const bodyOneLine = escapeMarkdown(lesson.body.replace(/\n+/g, ' ').trim());
24
- const suffix = lesson.tags.length > 0 ? ` ${bodyOneLine} _(${lesson.tags.join(', ')})_` : ` ${bodyOneLine}`;
25
- lines.push(`- **${heading}** -${suffix}`);
36
+ const tagSuffix = lesson.tags.length > 0 ? ` _(${lesson.tags.join(', ')})_` : '';
37
+ const rawReason = archivedReasonByHash
38
+ ? archivedReasonByHash.get(hashLesson(lesson.heading, lesson.body))
39
+ : undefined;
40
+ const cleanedReason = rawReason ? sanitizeReason(rawReason) : '';
41
+ const archivedSuffix = cleanedReason ? ` _(archived: ${cleanedReason})_` : '';
42
+ lines.push(`- **${heading}** - ` + bodyOneLine + tagSuffix + archivedSuffix);
26
43
  }
27
44
  lines.push('', SENTINEL_END);
28
45
  return lines.join('\n');
@@ -60,13 +77,17 @@ export function injectSentinelBlock(existingContent, generatedBlock) {
60
77
  /**
61
78
  * Export formatted lessons to a target file path.
62
79
  * Creates directories if needed. Uses sentinel-based injection for idempotent updates.
80
+ *
81
+ * When `archivedReasonByHash` is provided, lessons whose content-hash appears
82
+ * in the map render with an `_(archived: <reason>)_` annotation suffix
83
+ * (mmnto-ai/totem#1873).
63
84
  */
64
- export function exportLessons(lessons, targetPath) {
85
+ export function exportLessons(lessons, targetPath, archivedReasonByHash) {
65
86
  const dir = path.dirname(targetPath);
66
87
  if (!fs.existsSync(dir)) {
67
88
  fs.mkdirSync(dir, { recursive: true });
68
89
  }
69
- const generatedBlock = formatLessonsAsMarkdown(lessons);
90
+ const generatedBlock = formatLessonsAsMarkdown(lessons, archivedReasonByHash);
70
91
  if (fs.existsSync(targetPath)) {
71
92
  const existing = fs.readFileSync(targetPath, 'utf-8');
72
93
  const updated = injectSentinelBlock(existing, generatedBlock);
@@ -1 +1 @@
1
- {"version":3,"file":"exporter.js","sourceRoot":"","sources":["../src/exporter.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"exporter.js","sourceRoot":"","sources":["../src/exporter.ts"],"names":[],"mappings":"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"}
@@ -3,7 +3,9 @@ export declare const HEADING_MAX_CHARS = 60;
3
3
  * Truncate a heading string to HEADING_MAX_CHARS at a word boundary.
4
4
  * Strips trailing ellipsis/periods added by LLMs before enforcing the limit.
5
5
  * Also trims dangling prepositions/articles/conjunctions that leave the
6
- * heading feeling incomplete (e.g. "must be tested against the" → "must be tested").
6
+ * heading feeling incomplete (e.g. "must be tested against the" → "must be tested"),
7
+ * and clause-internal-cut tails where a verb/adjective follows a preposition
8
+ * (e.g. "to prevent" → drop both, per mmnto-ai/totem#1872).
7
9
  */
8
10
  export declare function truncateHeading(heading: string): string;
9
11
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"lesson-format.d.ts","sourceRoot":"","sources":["../src/lesson-format.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,iBAAiB,KAAK,CAAC;AAUpC;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAmCvD;AAED;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAkC1D;AAED;;;;;GAKG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,MAAM,GAAG;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,CAW5F"}
1
+ {"version":3,"file":"lesson-format.d.ts","sourceRoot":"","sources":["../src/lesson-format.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,iBAAiB,KAAK,CAAC;AAqHpC;;;;;;;GAOG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAgBvD;AAED;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAkC1D;AAED;;;;;GAKG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,MAAM,GAAG;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,CAW5F"}
@@ -5,11 +5,118 @@ const MIN_WORD_BREAK = 20;
5
5
  * Trimming past these produces cleaner, self-contained phrases.
6
6
  */
7
7
  const DANGLING_TAIL_RE = /\s+(?:the|a|an|of|for|in|on|at|to|by|with|from|into|via|and|or|but|is|are|was|were|that|this|its|their|your|against|between|within|about|after|before|during|through|across|can|must|should|when|if|as|than|like|e\.g\.?)$/i;
8
+ /**
9
+ * Prepositions that, when they immediately precede an expectant-tail run,
10
+ * signal a mid-clause cut. The prep must be the IMMEDIATE anchor of the
11
+ * run — an article like "the" between the prep and the trailing word
12
+ * (as in "Pass the props to the component") stops the run at the noun and
13
+ * leaves the heading kept.
14
+ */
15
+ const ANCHOR_PREPS = new Set([
16
+ 'to',
17
+ 'for',
18
+ 'by',
19
+ 'with',
20
+ 'from',
21
+ 'into',
22
+ 'via',
23
+ 'against',
24
+ 'between',
25
+ 'within',
26
+ 'about',
27
+ 'after',
28
+ 'before',
29
+ 'during',
30
+ 'through',
31
+ 'across',
32
+ 'of',
33
+ 'on',
34
+ 'at',
35
+ 'in',
36
+ ]);
37
+ /**
38
+ * Suffixes that strongly signal a trailing word is a verb or attributive
39
+ * adjective expecting a noun complement. Used to detect "expectant runs"
40
+ * — consecutive trailing words like "enable auditable" — that signal an
41
+ * incomplete clause when anchored to a preposition.
42
+ *
43
+ * Note: many common English nouns (component, client, state, environment,
44
+ * string) also match these suffixes. The walk-backwards-collect logic
45
+ * relies on the IMMEDIATE-anchor check (must be a preposition with no
46
+ * intervening article/noun) to avoid over-stripping those.
47
+ */
48
+ const EXPECTANT_SUFFIX_RE = /(?:ate|ize|ise|ify|able|ible|ing|ent|ant)$/i;
49
+ function isExpectantWord(word) {
50
+ // Hyphenated words (fixed-size, real-time, multi-tenant) are almost
51
+ // always attributive adjectives — treat as expectant.
52
+ if (word.includes('-'))
53
+ return true;
54
+ return EXPECTANT_SUFFIX_RE.test(word);
55
+ }
56
+ /**
57
+ * Strip a trailing run of expectant words (one or more verb/adjective-shaped
58
+ * words at the end of the heading) when the run is IMMEDIATELY anchored to
59
+ * a preposition. Examples (mmnto-ai/totem#1872 regression evidence):
60
+ *
61
+ * "Validate ... to prevent" → strip "prevent" (anchored to "to")
62
+ * "RON tuple ... for fixed-size" → strip "fixed-size" (anchored to "for")
63
+ * "Snapshot ... to isolate" → strip "isolate" (anchored to "to")
64
+ * "Document ... to enable auditable" → strip "enable auditable" (anchored to "to")
65
+ *
66
+ * The run is collected by walking backwards from the end as long as each
67
+ * word is "expectant" (verb/adjective-shaped or hyphenated). The anchor is
68
+ * the word immediately before the run. If the anchor is in ANCHOR_PREPS,
69
+ * strip the run; the existing dangling-tail check then strips the preposition.
70
+ *
71
+ * False positives are avoided by the immediate-adjacency check: in "Pass
72
+ * the props to the component", the anchor before "component" is "the"
73
+ * (not a preposition), so the heading is kept.
74
+ */
75
+ function trimIncompleteClause(text) {
76
+ const words = text.split(/\s+/);
77
+ if (words.length < 2)
78
+ return text;
79
+ let runStart = words.length;
80
+ while (runStart > 0 && isExpectantWord(words[runStart - 1])) {
81
+ runStart--;
82
+ }
83
+ if (runStart === words.length)
84
+ return text; // no trailing expectant run
85
+ if (runStart === 0)
86
+ return text; // entire heading is expectant — no anchor
87
+ const anchor = words[runStart - 1];
88
+ if (!ANCHOR_PREPS.has(anchor.toLowerCase()))
89
+ return text;
90
+ const trimmed = words.slice(0, runStart).join(' ').trimEnd();
91
+ if (trimmed.length < MIN_WORD_BREAK)
92
+ return text;
93
+ return trimmed;
94
+ }
95
+ /**
96
+ * Iteratively trim trailing fragments that leave a heading mid-clause.
97
+ * Chains the existing dangling-tail strip with the clause-incomplete strip
98
+ * so multi-word tails ("to enable auditable") collapse cleanly.
99
+ */
100
+ function trimTrailingFragments(text) {
101
+ let prev = text;
102
+ for (;;) {
103
+ let next = prev;
104
+ if (DANGLING_TAIL_RE.test(next)) {
105
+ next = next.replace(DANGLING_TAIL_RE, '').trimEnd();
106
+ }
107
+ next = trimIncompleteClause(next);
108
+ if (next === prev || next.length < MIN_WORD_BREAK)
109
+ return next.length < MIN_WORD_BREAK ? prev : next;
110
+ prev = next;
111
+ }
112
+ }
8
113
  /**
9
114
  * Truncate a heading string to HEADING_MAX_CHARS at a word boundary.
10
115
  * Strips trailing ellipsis/periods added by LLMs before enforcing the limit.
11
116
  * Also trims dangling prepositions/articles/conjunctions that leave the
12
- * heading feeling incomplete (e.g. "must be tested against the" → "must be tested").
117
+ * heading feeling incomplete (e.g. "must be tested against the" → "must be tested"),
118
+ * and clause-internal-cut tails where a verb/adjective follows a preposition
119
+ * (e.g. "to prevent" → drop both, per mmnto-ai/totem#1872).
13
120
  */
14
121
  export function truncateHeading(heading) {
15
122
  // Strip trailing ellipsis (…) or triple-dot (...) that LLMs love to add
@@ -18,31 +125,12 @@ export function truncateHeading(heading) {
18
125
  .replace(/\.{3,}$/, '')
19
126
  .trim();
20
127
  if (text.length <= HEADING_MAX_CHARS) {
21
- // Even short headings can have dangling tails from LLM ellipsis stripping
22
- let cleaned = text;
23
- let prev = cleaned;
24
- while (DANGLING_TAIL_RE.test(cleaned)) {
25
- cleaned = cleaned.replace(DANGLING_TAIL_RE, '').trimEnd();
26
- if (cleaned === prev || cleaned.length < MIN_WORD_BREAK)
27
- return prev;
28
- prev = cleaned;
29
- }
30
- return cleaned || text;
128
+ return trimTrailingFragments(text) || text;
31
129
  }
32
130
  const truncated = text.slice(0, HEADING_MAX_CHARS);
33
131
  const lastSpace = truncated.lastIndexOf(' ');
34
132
  text = (lastSpace > MIN_WORD_BREAK ? truncated.slice(0, lastSpace) : truncated).trimEnd();
35
- // Trim dangling tail words (may need multiple passes for chains like "for the")
36
- let prev = text;
37
- while (DANGLING_TAIL_RE.test(text)) {
38
- text = text.replace(DANGLING_TAIL_RE, '').trimEnd();
39
- if (text === prev || text.length < MIN_WORD_BREAK) {
40
- text = prev;
41
- break;
42
- }
43
- prev = text;
44
- }
45
- return text;
133
+ return trimTrailingFragments(text);
46
134
  }
47
135
  /**
48
136
  * Generate a descriptive lesson heading from the lesson body.
@@ -1 +1 @@
1
- {"version":3,"file":"lesson-format.js","sourceRoot":"","sources":["../src/lesson-format.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"lesson-format.js","sourceRoot":"","sources":["../src/lesson-format.ts"],"names":[],"mappings":"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"}
@@ -106,6 +106,70 @@ describe('truncateHeading', () => {
106
106
  // "in" at end is a dangling word
107
107
  expect(truncateHeading('Guard reversed marker ordering in')).toBe('Guard reversed marker ordering');
108
108
  });
109
+ // ─── Clause-internal truncation (mmnto-ai/totem#1872) ──
110
+ // Empirical regressions from mmnto-ai/liquid-city#229 / #234 / #238:
111
+ // headings ≤60 chars whose final word is a complete English word
112
+ // (prevent, fixed-size, isolate, auditable) but in context completes
113
+ // an incomplete prepositional/infinitival phrase. The trailing word
114
+ // alone passes the single-word dangling-tail check, but the phrase
115
+ // reads as mid-clause cut.
116
+ it('trims trailing infinitive after "to" (LC#229)', () => {
117
+ expect(truncateHeading('Validate const_name suffix before codegen to prevent')).toBe('Validate const_name suffix before codegen');
118
+ });
119
+ it('trims trailing hyphenated adjective after "for" (LC#229)', () => {
120
+ expect(truncateHeading('RON tuple syntax differs from array syntax for fixed-size')).toBe('RON tuple syntax differs from array syntax');
121
+ });
122
+ it('trims trailing -ate verb after "to" (LC#229)', () => {
123
+ expect(truncateHeading('Snapshot canonical form should exclude metadata to isolate')).toBe('Snapshot canonical form should exclude metadata');
124
+ });
125
+ it('trims chained trailing expectant words (LC#234)', () => {
126
+ // "to enable auditable" — strip "auditable" (-able), then "enable" (-able),
127
+ // then "to" (dangling prep) — three iterations
128
+ expect(truncateHeading('Document pre-resource call sites to enable auditable')).toBe('Document pre-resource call sites');
129
+ });
130
+ it('does NOT trim bare verb at end when no preceding preposition', () => {
131
+ // "validate" has -ate suffix but no preposition before it in heading
132
+ expect(truncateHeading('Always validate')).toBe('Always validate');
133
+ });
134
+ it('does NOT trim valid prepositional phrase ending in plain noun', () => {
135
+ // "from user" / "in CI" / "for tests" — trailing word is a plain noun
136
+ // (no expectant suffix, no hyphen), so the prep+noun pair is kept.
137
+ expect(truncateHeading('Sanitize input from user')).toBe('Sanitize input from user');
138
+ expect(truncateHeading('Run integration tests in CI')).toBe('Run integration tests in CI');
139
+ });
140
+ // ─── False-positive guards (totem review CRITICAL on this PR) ──
141
+ // The first iteration of the fix used a non-adjacent prep check
142
+ // ("does the heading contain ANY prep") and over-stripped common
143
+ // programming nouns ending in expectant suffixes. The walk-back-then-
144
+ // immediate-anchor approach should preserve all of these.
145
+ it('does NOT strip when anchor before expectant word is an article', () => {
146
+ // "component" matches -ent suffix but anchor "the" is an article (not a prep)
147
+ expect(truncateHeading('Pass the props to the component')).toBe('Pass the props to the component');
148
+ });
149
+ it('does NOT strip when consecutive expectant words have non-prep anchor', () => {
150
+ // "client state" — both -ent/-ate, anchor is "Restore" (verb, not prep)
151
+ expect(truncateHeading('Restore client state')).toBe('Restore client state');
152
+ });
153
+ it('does NOT strip hyphenated noun with non-prep anchor', () => {
154
+ // "load-balancer" hyphenated, but anchor "Configure" is not a prep
155
+ expect(truncateHeading('Configure load-balancer')).toBe('Configure load-balancer');
156
+ });
157
+ it('does NOT strip expectant-suffixed common nouns with article anchor', () => {
158
+ // "environment" / "variable" / "string" all match suffixes but anchor "the"
159
+ expect(truncateHeading('Detect the environment')).toBe('Detect the environment');
160
+ expect(truncateHeading('Reset the variable')).toBe('Reset the variable');
161
+ expect(truncateHeading('Parse the string')).toBe('Parse the string');
162
+ });
163
+ it('handles >60-char heading with mid-clause cut at word boundary', () => {
164
+ // After cutting to 60 chars at word boundary the heading should still
165
+ // strip trailing incomplete-clause tails.
166
+ const long = 'Ensure all consumer repos qualify cross-repo references to prevent broken links';
167
+ // Truncates to "Ensure all consumer repos qualify cross-repo references" (~54 chars)
168
+ // No trailing prep+verb after truncation, so it stays clean.
169
+ const result = truncateHeading(long);
170
+ expect(result.length).toBeLessThanOrEqual(HEADING_MAX_CHARS);
171
+ expect(result).not.toMatch(/\sto\s+prevent$/);
172
+ });
109
173
  });
110
174
  // ─── rewriteLessonHeadings ─────────────────────────────
111
175
  describe('rewriteLessonHeadings', () => {
@@ -1 +1 @@
1
- {"version":3,"file":"lesson-format.test.js","sourceRoot":"","sources":["../src/lesson-format.test.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"lesson-format.test.js","sourceRoot":"","sources":["../src/lesson-format.test.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mmnto/totem",
3
- "version": "1.34.0",
3
+ "version": "1.34.2",
4
4
  "description": "Persistent memory and context layer for AI agents",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",