@mmnto/totem 1.34.1 → 1.34.3
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/dist/describe.d.ts.map +1 -1
- package/dist/describe.js +9 -2
- package/dist/describe.js.map +1 -1
- package/dist/describe.test.d.ts +2 -0
- package/dist/describe.test.d.ts.map +1 -0
- package/dist/describe.test.js +79 -0
- package/dist/describe.test.js.map +1 -0
- package/dist/exporter.d.ts +12 -2
- package/dist/exporter.d.ts.map +1 -1
- package/dist/exporter.js +27 -6
- package/dist/exporter.js.map +1 -1
- package/package.json +1 -1
package/dist/describe.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"describe.d.ts","sourceRoot":"","sources":["../src/describe.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAGtD,MAAM,WAAW,kBAAkB;IACjC,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,IAAI,EAAE,MAAM,GAAG,UAAU,GAAG,MAAM,CAAC;IACnC,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;IACrC,KAAK,EAAE,MAAM,EAAE,CAAC;CACjB;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,GAAG,kBAAkB,
|
|
1
|
+
{"version":3,"file":"describe.d.ts","sourceRoot":"","sources":["../src/describe.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAGtD,MAAM,WAAW,kBAAkB;IACjC,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,IAAI,EAAE,MAAM,GAAG,UAAU,GAAG,MAAM,CAAC;IACnC,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;IACrC,KAAK,EAAE,MAAM,EAAE,CAAC;CACjB;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,GAAG,kBAAkB,CAoE3F"}
|
package/dist/describe.js
CHANGED
|
@@ -24,13 +24,20 @@ export function describeProject(config, configRoot) {
|
|
|
24
24
|
// package.json missing or malformed — use directory name
|
|
25
25
|
}
|
|
26
26
|
const tier = getConfigTier(config);
|
|
27
|
-
// Rule count from compiled rules
|
|
27
|
+
// Rule count from compiled rules. `compiled-rules.json` is an object of
|
|
28
|
+
// shape `{ version, rules: CompiledRule[], nonCompilable: [...] }` — NOT
|
|
29
|
+
// an array. Reading `parsed.rules.length` is the canonical access
|
|
30
|
+
// pattern used by `loadCompiledRulesFile` and the rest of the codebase
|
|
31
|
+
// (mmnto-ai/totem#1884 R1 — prior `Array.isArray(parsed)` check always
|
|
32
|
+
// failed, reporting 0 rules in every orientation banner).
|
|
28
33
|
let rules = 0;
|
|
29
34
|
try {
|
|
30
35
|
const rulesPath = path.join(totemDir, 'compiled-rules.json');
|
|
31
36
|
if (fs.existsSync(rulesPath)) {
|
|
32
37
|
const parsed = JSON.parse(fs.readFileSync(rulesPath, 'utf-8'));
|
|
33
|
-
|
|
38
|
+
if (parsed && typeof parsed === 'object' && Array.isArray(parsed.rules)) {
|
|
39
|
+
rules = parsed.rules.length;
|
|
40
|
+
}
|
|
34
41
|
}
|
|
35
42
|
}
|
|
36
43
|
catch {
|
package/dist/describe.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"describe.js","sourceRoot":"","sources":["../src/describe.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAGlC,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAanD;;;GAGG;AACH,MAAM,UAAU,eAAe,CAAC,MAAmB,EAAE,UAAkB;IACrE,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC;IAExD,+CAA+C;IAC/C,IAAI,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC;IACxC,IAAI,WAA+B,CAAC;IACpC,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,cAAc,CAAC,CAAC;QACtD,IAAI,EAAE,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;YAC3B,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,YAAY,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC;YAC1D,IAAI,GAAG,CAAC,IAAI;gBAAE,OAAO,GAAG,GAAG,CAAC,IAAI,CAAC;YACjC,IAAI,GAAG,CAAC,WAAW;gBAAE,WAAW,GAAG,GAAG,CAAC,WAAW,CAAC;QACrD,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,yDAAyD;IAC3D,CAAC;IAED,MAAM,IAAI,GAAG,aAAa,CAAC,MAAM,CAAC,CAAC;IAEnC,
|
|
1
|
+
{"version":3,"file":"describe.js","sourceRoot":"","sources":["../src/describe.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"describe.test.d.ts","sourceRoot":"","sources":["../src/describe.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import * as fs from 'node:fs';
|
|
2
|
+
import * as os from 'node:os';
|
|
3
|
+
import * as path from 'node:path';
|
|
4
|
+
import { afterEach, beforeEach, describe, expect, it } from 'vitest';
|
|
5
|
+
import { TotemConfigSchema } from './config-schema.js';
|
|
6
|
+
import { describeProject } from './describe.js';
|
|
7
|
+
// ─── Fixture helpers ─────────────────────────────────
|
|
8
|
+
function makeTmpDir() {
|
|
9
|
+
return fs.mkdtempSync(path.join(os.tmpdir(), 'totem-describe-'));
|
|
10
|
+
}
|
|
11
|
+
function makeMinimalConfig() {
|
|
12
|
+
// Use schema parse to fill in defaults for fields describeProject
|
|
13
|
+
// doesn't read but `TotemConfig` requires (lanceDir, ignorePatterns,
|
|
14
|
+
// shieldIgnorePatterns, contextWarningThreshold, etc).
|
|
15
|
+
return TotemConfigSchema.parse({
|
|
16
|
+
targets: [{ glob: '**/*.ts', type: 'code', strategy: 'typescript-ast' }],
|
|
17
|
+
totemDir: '.totem',
|
|
18
|
+
orchestrator: {
|
|
19
|
+
provider: 'shell',
|
|
20
|
+
command: 'echo unused',
|
|
21
|
+
defaultModel: 'test-model',
|
|
22
|
+
},
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
function writeRulesFile(totemDir, ruleCount) {
|
|
26
|
+
fs.mkdirSync(totemDir, { recursive: true });
|
|
27
|
+
const rules = Array.from({ length: ruleCount }, (_, i) => ({
|
|
28
|
+
lessonHash: `hash${String(i).padStart(8, '0')}`,
|
|
29
|
+
lessonHeading: `Rule ${i}`,
|
|
30
|
+
pattern: 'dummy',
|
|
31
|
+
message: `Rule ${i} message`,
|
|
32
|
+
engine: 'regex',
|
|
33
|
+
compiledAt: '2026-05-11T00:00:00Z',
|
|
34
|
+
}));
|
|
35
|
+
fs.writeFileSync(path.join(totemDir, 'compiled-rules.json'), JSON.stringify({ version: 1, rules, nonCompilable: [] }, null, 2) + '\n', 'utf-8');
|
|
36
|
+
}
|
|
37
|
+
// ─── Tests ──────────────────────────────────────────
|
|
38
|
+
describe('describeProject — rules count (mmnto-ai/totem#1884 R1)', () => {
|
|
39
|
+
let tmpDir;
|
|
40
|
+
beforeEach(() => {
|
|
41
|
+
tmpDir = makeTmpDir();
|
|
42
|
+
});
|
|
43
|
+
afterEach(() => {
|
|
44
|
+
fs.rmSync(tmpDir, { recursive: true, force: true });
|
|
45
|
+
});
|
|
46
|
+
it('reports the rules array length from a well-formed compiled-rules.json', () => {
|
|
47
|
+
// Regression test for the prior `Array.isArray(parsed)` bug that
|
|
48
|
+
// checked the top-level object (always false) instead of `parsed.rules`
|
|
49
|
+
// (the actual array). Pre-fix, this assertion would have failed with
|
|
50
|
+
// `received: 0` for every non-zero rule count.
|
|
51
|
+
const totemDir = path.join(tmpDir, '.totem');
|
|
52
|
+
writeRulesFile(totemDir, 7);
|
|
53
|
+
const result = describeProject(makeMinimalConfig(), tmpDir);
|
|
54
|
+
expect(result.rules).toBe(7);
|
|
55
|
+
});
|
|
56
|
+
it('reports 0 when compiled-rules.json is absent (graceful fallback)', () => {
|
|
57
|
+
fs.mkdirSync(path.join(tmpDir, '.totem'), { recursive: true });
|
|
58
|
+
const result = describeProject(makeMinimalConfig(), tmpDir);
|
|
59
|
+
expect(result.rules).toBe(0);
|
|
60
|
+
});
|
|
61
|
+
it('reports 0 when compiled-rules.json is malformed (does not throw)', () => {
|
|
62
|
+
const totemDir = path.join(tmpDir, '.totem');
|
|
63
|
+
fs.mkdirSync(totemDir, { recursive: true });
|
|
64
|
+
fs.writeFileSync(path.join(totemDir, 'compiled-rules.json'), 'not valid json {', 'utf-8');
|
|
65
|
+
const result = describeProject(makeMinimalConfig(), tmpDir);
|
|
66
|
+
expect(result.rules).toBe(0);
|
|
67
|
+
});
|
|
68
|
+
it('reports 0 when compiled-rules.json is an array (defensive against schema drift)', () => {
|
|
69
|
+
// The defensive guard returns 0 if `parsed.rules` is not an array,
|
|
70
|
+
// including the degenerate case where someone hand-writes an array at
|
|
71
|
+
// the top level instead of the canonical object envelope.
|
|
72
|
+
const totemDir = path.join(tmpDir, '.totem');
|
|
73
|
+
fs.mkdirSync(totemDir, { recursive: true });
|
|
74
|
+
fs.writeFileSync(path.join(totemDir, 'compiled-rules.json'), JSON.stringify([{ lessonHash: 'x', lessonHeading: 'y' }], null, 2), 'utf-8');
|
|
75
|
+
const result = describeProject(makeMinimalConfig(), tmpDir);
|
|
76
|
+
expect(result.rules).toBe(0);
|
|
77
|
+
});
|
|
78
|
+
});
|
|
79
|
+
//# sourceMappingURL=describe.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"describe.test.js","sourceRoot":"","sources":["../src/describe.test.ts"],"names":[],"mappings":"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"}
|
package/dist/exporter.d.ts
CHANGED
|
@@ -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
|
package/dist/exporter.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"exporter.d.ts","sourceRoot":"","sources":["../src/exporter.ts"],"names":[],"mappings":"
|
|
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
|
|
25
|
-
|
|
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);
|
package/dist/exporter.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"exporter.js","sourceRoot":"","sources":["../src/exporter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"exporter.js","sourceRoot":"","sources":["../src/exporter.ts"],"names":[],"mappings":"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"}
|