@mmnto/totem 0.27.0 → 0.28.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.
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/ingest/file-resolver.d.ts.map +1 -1
- package/dist/ingest/file-resolver.js +31 -10
- package/dist/ingest/file-resolver.js.map +1 -1
- package/dist/ingest/file-resolver.test.js +45 -1
- package/dist/ingest/file-resolver.test.js.map +1 -1
- package/dist/lesson-format.d.ts +12 -0
- package/dist/lesson-format.d.ts.map +1 -1
- package/dist/lesson-format.js +47 -6
- package/dist/lesson-format.js.map +1 -1
- package/dist/lesson-format.test.js +77 -4
- package/dist/lesson-format.test.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -20,7 +20,7 @@ export { enrichWithAstContext } from './ast-gate.js';
|
|
|
20
20
|
export { exportLessons, formatLessonsAsMarkdown, injectSentinelBlock, SENTINEL_END, SENTINEL_START, } from './exporter.js';
|
|
21
21
|
export type { SagaViolation, ViolationType } from './saga-validator.js';
|
|
22
22
|
export { validateDocUpdate } from './saga-validator.js';
|
|
23
|
-
export { generateLessonHeading, HEADING_MAX_CHARS, truncateHeading } from './lesson-format.js';
|
|
23
|
+
export { generateLessonHeading, HEADING_MAX_CHARS, rewriteLessonHeadings, truncateHeading, } from './lesson-format.js';
|
|
24
24
|
export type { IngestionSanitizeOptions } from './sanitize.js';
|
|
25
25
|
export { BASE64_BLOB_RE, INSTRUCTIONAL_LEAKAGE_RE, sanitize, sanitizeForIngestion, UNICODE_ESCAPE_RE, XML_TAG_LEAKAGE_RE, } from './sanitize.js';
|
|
26
26
|
export { wrapXml } from './xml-format.js';
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,YAAY,EACV,aAAa,EACb,UAAU,EACV,WAAW,EACX,SAAS,EACT,iBAAiB,EACjB,YAAY,EACZ,YAAY,EACZ,WAAW,GACZ,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EACL,2BAA2B,EAC3B,mBAAmB,EACnB,gBAAgB,EAChB,iBAAiB,EACjB,uBAAuB,EACvB,eAAe,EACf,uBAAuB,EACvB,wBAAwB,EACxB,aAAa,EACb,kBAAkB,EAClB,oBAAoB,EACpB,oBAAoB,EACpB,kBAAkB,EAClB,gBAAgB,EAChB,uBAAuB,EACvB,iBAAiB,GAClB,MAAM,oBAAoB,CAAC;AAG5B,YAAY,EACV,KAAK,EACL,aAAa,EACb,YAAY,EACZ,WAAW,EACX,WAAW,EACX,SAAS,GACV,MAAM,YAAY,CAAC;AAGpB,YAAY,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AACrD,OAAO,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAGtD,YAAY,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAC;AACxD,OAAO,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAGzD,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAC3D,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AAGpD,YAAY,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,EAAE,eAAe,EAAE,UAAU,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAGtF,YAAY,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACrE,OAAO,EACL,WAAW,EACX,qBAAqB,EACrB,gBAAgB,EAChB,kBAAkB,GACnB,MAAM,qBAAqB,CAAC;AAG7B,YAAY,EACV,UAAU,EACV,YAAY,EACZ,iBAAiB,EACjB,cAAc,EACd,YAAY,EACZ,SAAS,GACV,MAAM,eAAe,CAAC;AACvB,OAAO,EACL,UAAU,EACV,qBAAqB,EACrB,kBAAkB,EAClB,uBAAuB,EACvB,oBAAoB,EACpB,iBAAiB,EACjB,UAAU,EACV,iBAAiB,EACjB,qBAAqB,EACrB,KAAK,eAAe,EACpB,iBAAiB,EACjB,aAAa,GACd,MAAM,eAAe,CAAC;AAGvB,YAAY,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAC7D,OAAO,EAAE,aAAa,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AACzE,YAAY,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AACpD,OAAO,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAC;AAGrD,OAAO,EACL,aAAa,EACb,uBAAuB,EACvB,mBAAmB,EACnB,YAAY,EACZ,cAAc,GACf,MAAM,eAAe,CAAC;AAGvB,YAAY,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACxE,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAGxD,OAAO,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,YAAY,EACV,aAAa,EACb,UAAU,EACV,WAAW,EACX,SAAS,EACT,iBAAiB,EACjB,YAAY,EACZ,YAAY,EACZ,WAAW,GACZ,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EACL,2BAA2B,EAC3B,mBAAmB,EACnB,gBAAgB,EAChB,iBAAiB,EACjB,uBAAuB,EACvB,eAAe,EACf,uBAAuB,EACvB,wBAAwB,EACxB,aAAa,EACb,kBAAkB,EAClB,oBAAoB,EACpB,oBAAoB,EACpB,kBAAkB,EAClB,gBAAgB,EAChB,uBAAuB,EACvB,iBAAiB,GAClB,MAAM,oBAAoB,CAAC;AAG5B,YAAY,EACV,KAAK,EACL,aAAa,EACb,YAAY,EACZ,WAAW,EACX,WAAW,EACX,SAAS,GACV,MAAM,YAAY,CAAC;AAGpB,YAAY,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AACrD,OAAO,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAGtD,YAAY,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAC;AACxD,OAAO,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAGzD,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAC3D,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AAGpD,YAAY,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,EAAE,eAAe,EAAE,UAAU,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAGtF,YAAY,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACrE,OAAO,EACL,WAAW,EACX,qBAAqB,EACrB,gBAAgB,EAChB,kBAAkB,GACnB,MAAM,qBAAqB,CAAC;AAG7B,YAAY,EACV,UAAU,EACV,YAAY,EACZ,iBAAiB,EACjB,cAAc,EACd,YAAY,EACZ,SAAS,GACV,MAAM,eAAe,CAAC;AACvB,OAAO,EACL,UAAU,EACV,qBAAqB,EACrB,kBAAkB,EAClB,uBAAuB,EACvB,oBAAoB,EACpB,iBAAiB,EACjB,UAAU,EACV,iBAAiB,EACjB,qBAAqB,EACrB,KAAK,eAAe,EACpB,iBAAiB,EACjB,aAAa,GACd,MAAM,eAAe,CAAC;AAGvB,YAAY,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAC7D,OAAO,EAAE,aAAa,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AACzE,YAAY,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AACpD,OAAO,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAC;AAGrD,OAAO,EACL,aAAa,EACb,uBAAuB,EACvB,mBAAmB,EACnB,YAAY,EACZ,cAAc,GACf,MAAM,eAAe,CAAC;AAGvB,YAAY,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACxE,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAGxD,OAAO,EACL,qBAAqB,EACrB,iBAAiB,EACjB,qBAAqB,EACrB,eAAe,GAChB,MAAM,oBAAoB,CAAC;AAC5B,YAAY,EAAE,wBAAwB,EAAE,MAAM,eAAe,CAAC;AAC9D,OAAO,EACL,cAAc,EACd,wBAAwB,EACxB,QAAQ,EACR,oBAAoB,EACpB,iBAAiB,EACjB,kBAAkB,GACnB,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -13,7 +13,7 @@ export { enrichWithAstContext } from './ast-gate.js';
|
|
|
13
13
|
export { exportLessons, formatLessonsAsMarkdown, injectSentinelBlock, SENTINEL_END, SENTINEL_START, } from './exporter.js';
|
|
14
14
|
export { validateDocUpdate } from './saga-validator.js';
|
|
15
15
|
// Utilities
|
|
16
|
-
export { generateLessonHeading, HEADING_MAX_CHARS, truncateHeading } from './lesson-format.js';
|
|
16
|
+
export { generateLessonHeading, HEADING_MAX_CHARS, rewriteLessonHeadings, truncateHeading, } from './lesson-format.js';
|
|
17
17
|
export { BASE64_BLOB_RE, INSTRUCTIONAL_LEAKAGE_RE, sanitize, sanitizeForIngestion, UNICODE_ESCAPE_RE, XML_TAG_LEAKAGE_RE, } from './sanitize.js';
|
|
18
18
|
export { wrapXml } from './xml-format.js';
|
|
19
19
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAWA,OAAO,EACL,2BAA2B,EAC3B,mBAAmB,EACnB,gBAAgB,EAChB,iBAAiB,EACjB,uBAAuB,EACvB,eAAe,EACf,uBAAuB,EACvB,wBAAwB,EACxB,aAAa,EACb,kBAAkB,EAClB,oBAAoB,EACpB,oBAAoB,EACpB,kBAAkB,EAClB,gBAAgB,EAChB,uBAAuB,EACvB,iBAAiB,GAClB,MAAM,oBAAoB,CAAC;AAc5B,OAAO,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAItD,OAAO,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAEzD,QAAQ;AACR,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAC3D,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AAIpD,OAAO,EAAE,eAAe,EAAE,UAAU,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAItF,OAAO,EACL,WAAW,EACX,qBAAqB,EACrB,gBAAgB,EAChB,kBAAkB,GACnB,MAAM,qBAAqB,CAAC;AAW7B,OAAO,EACL,UAAU,EACV,qBAAqB,EACrB,kBAAkB,EAClB,uBAAuB,EACvB,oBAAoB,EACpB,iBAAiB,EACjB,UAAU,EACV,iBAAiB,EACjB,qBAAqB,EAErB,iBAAiB,EACjB,aAAa,GACd,MAAM,eAAe,CAAC;AAIvB,OAAO,EAAE,aAAa,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAEzE,OAAO,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAC;AAErD,WAAW;AACX,OAAO,EACL,aAAa,EACb,uBAAuB,EACvB,mBAAmB,EACnB,YAAY,EACZ,cAAc,GACf,MAAM,eAAe,CAAC;AAIvB,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAExD,YAAY;AACZ,OAAO,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAWA,OAAO,EACL,2BAA2B,EAC3B,mBAAmB,EACnB,gBAAgB,EAChB,iBAAiB,EACjB,uBAAuB,EACvB,eAAe,EACf,uBAAuB,EACvB,wBAAwB,EACxB,aAAa,EACb,kBAAkB,EAClB,oBAAoB,EACpB,oBAAoB,EACpB,kBAAkB,EAClB,gBAAgB,EAChB,uBAAuB,EACvB,iBAAiB,GAClB,MAAM,oBAAoB,CAAC;AAc5B,OAAO,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAItD,OAAO,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAEzD,QAAQ;AACR,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAC3D,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AAIpD,OAAO,EAAE,eAAe,EAAE,UAAU,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAItF,OAAO,EACL,WAAW,EACX,qBAAqB,EACrB,gBAAgB,EAChB,kBAAkB,GACnB,MAAM,qBAAqB,CAAC;AAW7B,OAAO,EACL,UAAU,EACV,qBAAqB,EACrB,kBAAkB,EAClB,uBAAuB,EACvB,oBAAoB,EACpB,iBAAiB,EACjB,UAAU,EACV,iBAAiB,EACjB,qBAAqB,EAErB,iBAAiB,EACjB,aAAa,GACd,MAAM,eAAe,CAAC;AAIvB,OAAO,EAAE,aAAa,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAEzE,OAAO,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAC;AAErD,WAAW;AACX,OAAO,EACL,aAAa,EACb,uBAAuB,EACvB,mBAAmB,EACnB,YAAY,EACZ,cAAc,GACf,MAAM,eAAe,CAAC;AAIvB,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAExD,YAAY;AACZ,OAAO,EACL,qBAAqB,EACrB,iBAAiB,EACjB,qBAAqB,EACrB,eAAe,GAChB,MAAM,oBAAoB,CAAC;AAE5B,OAAO,EACL,cAAc,EACd,wBAAwB,EACxB,QAAQ,EACR,oBAAoB,EACpB,iBAAiB,EACjB,kBAAkB,GACnB,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"file-resolver.d.ts","sourceRoot":"","sources":["../../src/ingest/file-resolver.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAGxD,MAAM,WAAW,YAAY;IAC3B,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,YAAY,CAAC;CACtB;
|
|
1
|
+
{"version":3,"file":"file-resolver.d.ts","sourceRoot":"","sources":["../../src/ingest/file-resolver.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAGxD,MAAM,WAAW,YAAY;IAC3B,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,YAAY,CAAC;CACtB;AAkED,sEAAsE;AACtE,wBAAgB,YAAY,CAC1B,OAAO,EAAE,YAAY,EAAE,EACvB,WAAW,EAAE,MAAM,EACnB,cAAc,GAAE,MAAM,EAA4B,EAClD,MAAM,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,GAC7B,YAAY,EAAE,CA2BhB;AAKD;;;;GAIG;AACH,wBAAgB,eAAe,CAC7B,WAAW,EAAE,MAAM,EACnB,QAAQ,GAAE,MAAiB,EAC3B,MAAM,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,GAC7B,MAAM,EAAE,GAAG,IAAI,CA8CjB;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,WAAW,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,GAAG,MAAM,GAAG,IAAI,CAa7F"}
|
|
@@ -2,22 +2,43 @@ import { execFileSync } from 'node:child_process';
|
|
|
2
2
|
import * as path from 'node:path';
|
|
3
3
|
import { globSync } from 'glob';
|
|
4
4
|
import { DEFAULT_IGNORE_PATTERNS } from '../config-schema.js';
|
|
5
|
+
/**
|
|
6
|
+
* Parse null-delimited git output into normalized forward-slash paths.
|
|
7
|
+
*/
|
|
8
|
+
function parseGitPaths(output) {
|
|
9
|
+
return output
|
|
10
|
+
.split('\0')
|
|
11
|
+
.filter(Boolean)
|
|
12
|
+
.map((f) => f.replace(/\\/g, '/'));
|
|
13
|
+
}
|
|
5
14
|
/**
|
|
6
15
|
* Get the set of non-gitignored files in the project.
|
|
16
|
+
* Includes files inside git submodules via --recurse-submodules.
|
|
7
17
|
* Returns null if git is unavailable or the project is not a git repo.
|
|
8
18
|
*/
|
|
9
19
|
function getGitNonIgnoredFiles(projectRoot, onWarn) {
|
|
20
|
+
const execOpts = {
|
|
21
|
+
cwd: projectRoot,
|
|
22
|
+
encoding: 'utf-8',
|
|
23
|
+
maxBuffer: 10 * 1024 * 1024,
|
|
24
|
+
shell: process.platform === 'win32',
|
|
25
|
+
};
|
|
10
26
|
try {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
27
|
+
// Parent repo: tracked + untracked (non-ignored) files
|
|
28
|
+
const output = execFileSync('git', ['ls-files', '-z', '--cached', '--others', '--exclude-standard'], execOpts);
|
|
29
|
+
const files = new Set(parseGitPaths(output));
|
|
30
|
+
// Submodules: --recurse-submodules only supports --cached,
|
|
31
|
+
// but submodule files we care about are always committed.
|
|
32
|
+
try {
|
|
33
|
+
const subOutput = execFileSync('git', ['ls-files', '-z', '--cached', '--recurse-submodules'], execOpts);
|
|
34
|
+
for (const f of parseGitPaths(subOutput)) {
|
|
35
|
+
files.add(f);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
catch {
|
|
39
|
+
// --recurse-submodules unsupported or no submodules — ignore
|
|
40
|
+
}
|
|
41
|
+
return files;
|
|
21
42
|
}
|
|
22
43
|
catch (err) {
|
|
23
44
|
const errorMsg = err instanceof Error ? err.message : String(err);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"file-resolver.js","sourceRoot":"","sources":["../../src/ingest/file-resolver.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAElC,OAAO,EAAE,QAAQ,EAAE,MAAM,MAAM,CAAC;AAGhC,OAAO,EAAE,uBAAuB,EAAE,MAAM,qBAAqB,CAAC;AAQ9D
|
|
1
|
+
{"version":3,"file":"file-resolver.js","sourceRoot":"","sources":["../../src/ingest/file-resolver.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,9 +1,13 @@
|
|
|
1
1
|
import * as childProcess from 'node:child_process';
|
|
2
|
+
import { globSync } from 'glob';
|
|
2
3
|
import { afterEach, describe, expect, it, vi } from 'vitest';
|
|
3
|
-
import { getChangedFiles, getHeadSha } from './file-resolver.js';
|
|
4
|
+
import { getChangedFiles, getHeadSha, resolveFiles } from './file-resolver.js';
|
|
4
5
|
vi.mock('node:child_process', () => ({
|
|
5
6
|
execFileSync: vi.fn(),
|
|
6
7
|
}));
|
|
8
|
+
vi.mock('glob', () => ({
|
|
9
|
+
globSync: vi.fn(() => []),
|
|
10
|
+
}));
|
|
7
11
|
afterEach(() => {
|
|
8
12
|
vi.restoreAllMocks();
|
|
9
13
|
});
|
|
@@ -81,4 +85,44 @@ describe('getChangedFiles', () => {
|
|
|
81
85
|
expect(result).toEqual([]);
|
|
82
86
|
});
|
|
83
87
|
});
|
|
88
|
+
describe('resolveFiles — submodule support', () => {
|
|
89
|
+
it('includes submodule files from --recurse-submodules call', () => {
|
|
90
|
+
vi.mocked(childProcess.execFileSync).mockImplementation((_cmd, args) => {
|
|
91
|
+
if (args && args.includes('--recurse-submodules')) {
|
|
92
|
+
return 'src/a.ts\0.strategy/north-star.md\0';
|
|
93
|
+
}
|
|
94
|
+
// Parent repo ls-files: does NOT include submodule files
|
|
95
|
+
return 'src/a.ts\0';
|
|
96
|
+
});
|
|
97
|
+
vi.mocked(globSync).mockReturnValue(['.strategy/north-star.md']);
|
|
98
|
+
const result = resolveFiles([{ glob: '.strategy/**/*.md', type: 'spec', strategy: 'markdown-heading' }], '/project');
|
|
99
|
+
expect(result).toHaveLength(1);
|
|
100
|
+
expect(result[0].relativePath).toBe('.strategy/north-star.md');
|
|
101
|
+
});
|
|
102
|
+
it('excludes submodule files not matched by glob', () => {
|
|
103
|
+
vi.mocked(childProcess.execFileSync).mockImplementation((_cmd, args) => {
|
|
104
|
+
if (args && args.includes('--recurse-submodules')) {
|
|
105
|
+
return '.strategy/north-star.md\0.strategy/archive/old.md\0';
|
|
106
|
+
}
|
|
107
|
+
return '';
|
|
108
|
+
});
|
|
109
|
+
// Glob only matches the non-archived file (archive excluded via ignorePatterns)
|
|
110
|
+
vi.mocked(globSync).mockReturnValue(['.strategy/north-star.md']);
|
|
111
|
+
const result = resolveFiles([{ glob: '.strategy/**/*.md', type: 'spec', strategy: 'markdown-heading' }], '/project', ['.strategy/archive/**']);
|
|
112
|
+
expect(result).toHaveLength(1);
|
|
113
|
+
expect(result[0].relativePath).toBe('.strategy/north-star.md');
|
|
114
|
+
});
|
|
115
|
+
it('works when --recurse-submodules is unsupported', () => {
|
|
116
|
+
vi.mocked(childProcess.execFileSync).mockImplementation((_cmd, args) => {
|
|
117
|
+
if (args && args.includes('--recurse-submodules')) {
|
|
118
|
+
throw new Error('unknown option');
|
|
119
|
+
}
|
|
120
|
+
return 'src/a.ts\0';
|
|
121
|
+
});
|
|
122
|
+
vi.mocked(globSync).mockReturnValue(['src/a.ts']);
|
|
123
|
+
const result = resolveFiles([{ glob: 'src/**/*.ts', type: 'code', strategy: 'typescript-ast' }], '/project');
|
|
124
|
+
expect(result).toHaveLength(1);
|
|
125
|
+
expect(result[0].relativePath).toBe('src/a.ts');
|
|
126
|
+
});
|
|
127
|
+
});
|
|
84
128
|
//# sourceMappingURL=file-resolver.test.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"file-resolver.test.js","sourceRoot":"","sources":["../../src/ingest/file-resolver.test.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,YAAY,MAAM,oBAAoB,CAAC;AAEnD,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAE7D,OAAO,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"file-resolver.test.js","sourceRoot":"","sources":["../../src/ingest/file-resolver.test.ts"],"names":[],"mappings":"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"}
|
package/dist/lesson-format.d.ts
CHANGED
|
@@ -2,6 +2,8 @@ export declare const HEADING_MAX_CHARS = 60;
|
|
|
2
2
|
/**
|
|
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
|
+
* Also trims dangling prepositions/articles/conjunctions that leave the
|
|
6
|
+
* heading feeling incomplete (e.g. "must be tested against the" → "must be tested").
|
|
5
7
|
*/
|
|
6
8
|
export declare function truncateHeading(heading: string): string;
|
|
7
9
|
/**
|
|
@@ -10,4 +12,14 @@ export declare function truncateHeading(heading: string): string;
|
|
|
10
12
|
* and truncates to HEADING_MAX_CHARS.
|
|
11
13
|
*/
|
|
12
14
|
export declare function generateLessonHeading(body: string): string;
|
|
15
|
+
/**
|
|
16
|
+
* Rewrite a lessons.md file content, cleaning up truncated headings.
|
|
17
|
+
* Applies `truncateHeading()` to every `## Lesson — ...` heading,
|
|
18
|
+
* trimming dangling prepositions/articles/conjunctions.
|
|
19
|
+
* Returns the number of headings that were modified.
|
|
20
|
+
*/
|
|
21
|
+
export declare function rewriteLessonHeadings(content: string): {
|
|
22
|
+
output: string;
|
|
23
|
+
rewritten: number;
|
|
24
|
+
};
|
|
13
25
|
//# sourceMappingURL=lesson-format.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lesson-format.d.ts","sourceRoot":"","sources":["../src/lesson-format.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,iBAAiB,KAAK,CAAC;
|
|
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"}
|
package/dist/lesson-format.js
CHANGED
|
@@ -1,8 +1,15 @@
|
|
|
1
1
|
export const HEADING_MAX_CHARS = 60;
|
|
2
2
|
const MIN_WORD_BREAK = 20;
|
|
3
|
+
/**
|
|
4
|
+
* Words that leave a heading feeling incomplete when they appear at the end.
|
|
5
|
+
* Trimming past these produces cleaner, self-contained phrases.
|
|
6
|
+
*/
|
|
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;
|
|
3
8
|
/**
|
|
4
9
|
* Truncate a heading string to HEADING_MAX_CHARS at a word boundary.
|
|
5
10
|
* Strips trailing ellipsis/periods added by LLMs before enforcing the limit.
|
|
11
|
+
* Also trims dangling prepositions/articles/conjunctions that leave the
|
|
12
|
+
* heading feeling incomplete (e.g. "must be tested against the" → "must be tested").
|
|
6
13
|
*/
|
|
7
14
|
export function truncateHeading(heading) {
|
|
8
15
|
// Strip trailing ellipsis (…) or triple-dot (...) that LLMs love to add
|
|
@@ -10,11 +17,31 @@ export function truncateHeading(heading) {
|
|
|
10
17
|
.replace(/[…]+$/, '')
|
|
11
18
|
.replace(/\.{3,}$/, '')
|
|
12
19
|
.trim();
|
|
13
|
-
if (text.length <= HEADING_MAX_CHARS)
|
|
14
|
-
|
|
20
|
+
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;
|
|
31
|
+
}
|
|
15
32
|
const truncated = text.slice(0, HEADING_MAX_CHARS);
|
|
16
33
|
const lastSpace = truncated.lastIndexOf(' ');
|
|
17
34
|
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
|
+
}
|
|
18
45
|
return text;
|
|
19
46
|
}
|
|
20
47
|
/**
|
|
@@ -51,11 +78,25 @@ export function generateLessonHeading(body) {
|
|
|
51
78
|
text = text.slice(0, sentenceEnd + 1);
|
|
52
79
|
}
|
|
53
80
|
else if (text.length > HEADING_MAX_CHARS) {
|
|
54
|
-
//
|
|
55
|
-
|
|
56
|
-
const lastSpace = truncated.lastIndexOf(' ');
|
|
57
|
-
text = (lastSpace > MIN_WORD_BREAK ? truncated.slice(0, lastSpace) : truncated).trimEnd();
|
|
81
|
+
// Delegate to truncateHeading which handles dangling tails
|
|
82
|
+
text = truncateHeading(text);
|
|
58
83
|
}
|
|
59
84
|
return text;
|
|
60
85
|
}
|
|
86
|
+
/**
|
|
87
|
+
* Rewrite a lessons.md file content, cleaning up truncated headings.
|
|
88
|
+
* Applies `truncateHeading()` to every `## Lesson — ...` heading,
|
|
89
|
+
* trimming dangling prepositions/articles/conjunctions.
|
|
90
|
+
* Returns the number of headings that were modified.
|
|
91
|
+
*/
|
|
92
|
+
export function rewriteLessonHeadings(content) {
|
|
93
|
+
let rewritten = 0;
|
|
94
|
+
const output = content.replace(/^(## Lesson — )(.+)$/gm, (_match, prefix, heading) => {
|
|
95
|
+
const cleaned = truncateHeading(heading);
|
|
96
|
+
if (cleaned !== heading)
|
|
97
|
+
rewritten++;
|
|
98
|
+
return `${prefix}${cleaned}`;
|
|
99
|
+
});
|
|
100
|
+
return { output, rewritten };
|
|
101
|
+
}
|
|
61
102
|
//# sourceMappingURL=lesson-format.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lesson-format.js","sourceRoot":"","sources":["../src/lesson-format.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,iBAAiB,GAAG,EAAE,CAAC;AACpC,MAAM,cAAc,GAAG,EAAE,CAAC;AAE1B;;;GAGG;AACH,MAAM,UAAU,eAAe,CAAC,OAAe;IAC7C,wEAAwE;IACxE,IAAI,IAAI,GAAG,OAAO;SACf,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC;SACpB,OAAO,CAAC,SAAS,EAAE,EAAE,CAAC;SACtB,IAAI,EAAE,CAAC;IAEV,IAAI,IAAI,CAAC,MAAM,IAAI,iBAAiB;
|
|
1
|
+
{"version":3,"file":"lesson-format.js","sourceRoot":"","sources":["../src/lesson-format.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { describe, expect, it } from 'vitest';
|
|
2
|
-
import { generateLessonHeading, HEADING_MAX_CHARS, truncateHeading } from './lesson-format.js';
|
|
2
|
+
import { generateLessonHeading, HEADING_MAX_CHARS, rewriteLessonHeadings, truncateHeading, } from './lesson-format.js';
|
|
3
3
|
describe('generateLessonHeading', () => {
|
|
4
4
|
it('extracts first sentence from plain text', () => {
|
|
5
5
|
expect(generateLessonHeading('Always use strict mode. It catches bugs early.')).toBe('Always use strict mode.');
|
|
@@ -56,13 +56,12 @@ describe('truncateHeading', () => {
|
|
|
56
56
|
it('strips trailing triple-dot from LLM output', () => {
|
|
57
57
|
expect(truncateHeading('Sentinel-based injection systems should always...')).toBe('Sentinel-based injection systems should always');
|
|
58
58
|
});
|
|
59
|
-
it('truncates long headings at word boundary
|
|
59
|
+
it('truncates long headings at word boundary and trims dangling tails', () => {
|
|
60
60
|
const long = 'When a configuration file is an executed script like totem config it has arbitrary code execution';
|
|
61
61
|
const result = truncateHeading(long);
|
|
62
62
|
expect(result.length).toBeLessThanOrEqual(HEADING_MAX_CHARS);
|
|
63
63
|
expect(result).not.toContain('…');
|
|
64
|
-
//
|
|
65
|
-
expect(long.startsWith(result)).toBe(true);
|
|
64
|
+
// Word boundary gives "...script like totem"; "totem" is not dangling so kept as-is
|
|
66
65
|
expect(result).toBe('When a configuration file is an executed script like totem');
|
|
67
66
|
});
|
|
68
67
|
it('enforces HEADING_MAX_CHARS limit', () => {
|
|
@@ -73,5 +72,79 @@ describe('truncateHeading', () => {
|
|
|
73
72
|
const exact = 'x'.repeat(HEADING_MAX_CHARS);
|
|
74
73
|
expect(truncateHeading(exact)).toBe(exact);
|
|
75
74
|
});
|
|
75
|
+
it('trims dangling "the" after word-boundary truncation', () => {
|
|
76
|
+
expect(truncateHeading('Custom glob matching functions must be tested against the directory-prefixed convention')).toBe('Custom glob matching functions must be tested');
|
|
77
|
+
});
|
|
78
|
+
it('trims chained dangling words (e.g. "for the")', () => {
|
|
79
|
+
// After 60-char truncation: "Implement validation logic for the configuration files in" → ends with "in" (dangling) → trim → "...files" (fine)
|
|
80
|
+
expect(truncateHeading('Implement validation logic for the configuration files in the project root directory')).toBe('Implement validation logic for the configuration files');
|
|
81
|
+
});
|
|
82
|
+
it('trims dangling preposition from short heading after ellipsis strip', () => {
|
|
83
|
+
// Under 60 chars after ellipsis strip, but "; use" — "use" is not in dangling list
|
|
84
|
+
// The semicolon makes this tricky; the real fix is the improved prompt
|
|
85
|
+
const result = truncateHeading('LLMs are notoriously poor at character counting; use…');
|
|
86
|
+
expect(result).toBe('LLMs are notoriously poor at character counting; use');
|
|
87
|
+
});
|
|
88
|
+
it('trims dangling article from short heading after ellipsis strip', () => {
|
|
89
|
+
expect(truncateHeading('Always iterate through all regex matches via the…')).toBe('Always iterate through all regex matches');
|
|
90
|
+
});
|
|
91
|
+
it('does not trim valid ending words', () => {
|
|
92
|
+
expect(truncateHeading('Always sanitize Git outputs')).toBe('Always sanitize Git outputs');
|
|
93
|
+
});
|
|
94
|
+
it('does not trim when final word is not dangling', () => {
|
|
95
|
+
// "config" is not a dangling word, so the heading stays intact
|
|
96
|
+
expect(truncateHeading('Guard reversed marker ordering in config')).toBe('Guard reversed marker ordering in config');
|
|
97
|
+
});
|
|
98
|
+
it('trims dangling word from short heading', () => {
|
|
99
|
+
// "in" at end is a dangling word
|
|
100
|
+
expect(truncateHeading('Guard reversed marker ordering in')).toBe('Guard reversed marker ordering');
|
|
101
|
+
});
|
|
102
|
+
});
|
|
103
|
+
// ─── rewriteLessonHeadings ─────────────────────────────
|
|
104
|
+
describe('rewriteLessonHeadings', () => {
|
|
105
|
+
it('rewrites headings with dangling tails', () => {
|
|
106
|
+
const input = `## Lesson — Custom glob matching functions must be tested against the
|
|
107
|
+
|
|
108
|
+
**Tags:** glob, testing
|
|
109
|
+
|
|
110
|
+
Body text here.`;
|
|
111
|
+
const { output, rewritten } = rewriteLessonHeadings(input);
|
|
112
|
+
expect(rewritten).toBe(1);
|
|
113
|
+
expect(output).toContain('## Lesson — Custom glob matching functions must be tested');
|
|
114
|
+
expect(output).not.toContain('against the');
|
|
115
|
+
});
|
|
116
|
+
it('preserves clean headings', () => {
|
|
117
|
+
const input = `## Lesson — Always sanitize Git outputs
|
|
118
|
+
|
|
119
|
+
**Tags:** security`;
|
|
120
|
+
const { output, rewritten } = rewriteLessonHeadings(input);
|
|
121
|
+
expect(rewritten).toBe(0);
|
|
122
|
+
expect(output).toBe(input);
|
|
123
|
+
});
|
|
124
|
+
it('handles multiple headings', () => {
|
|
125
|
+
const input = `## Lesson — First heading is clean
|
|
126
|
+
|
|
127
|
+
Body 1.
|
|
128
|
+
|
|
129
|
+
## Lesson — Second heading ends with the
|
|
130
|
+
|
|
131
|
+
Body 2.
|
|
132
|
+
|
|
133
|
+
## Lesson — Third heading ends with for
|
|
134
|
+
|
|
135
|
+
Body 3.`;
|
|
136
|
+
const { output, rewritten } = rewriteLessonHeadings(input);
|
|
137
|
+
expect(rewritten).toBe(2);
|
|
138
|
+
expect(output).toContain('## Lesson — First heading is clean');
|
|
139
|
+
expect(output).toContain('## Lesson — Second heading ends');
|
|
140
|
+
expect(output).toContain('## Lesson — Third heading ends');
|
|
141
|
+
});
|
|
142
|
+
it('strips ellipsis from headings', () => {
|
|
143
|
+
const input = '## Lesson — Sentinel-based injection systems should always…';
|
|
144
|
+
const { output, rewritten } = rewriteLessonHeadings(input);
|
|
145
|
+
expect(rewritten).toBe(1);
|
|
146
|
+
expect(output).toContain('## Lesson — Sentinel-based injection systems should');
|
|
147
|
+
expect(output).not.toContain('…');
|
|
148
|
+
});
|
|
76
149
|
});
|
|
77
150
|
//# sourceMappingURL=lesson-format.test.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lesson-format.test.js","sourceRoot":"","sources":["../src/lesson-format.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAE9C,OAAO,
|
|
1
|
+
{"version":3,"file":"lesson-format.test.js","sourceRoot":"","sources":["../src/lesson-format.test.ts"],"names":[],"mappings":"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"}
|