@untangle-code/chunker 0.0.0-stage → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (75) hide show
  1. package/LICENSE +661 -0
  2. package/NOTICE +90 -0
  3. package/README.md +206 -2
  4. package/THIRD_PARTY_LICENSES.md +24 -0
  5. package/dist/byte-text.d.ts +39 -0
  6. package/dist/byte-text.d.ts.map +1 -0
  7. package/dist/byte-text.js +59 -0
  8. package/dist/byte-text.js.map +1 -0
  9. package/dist/chunker.d.ts +11 -0
  10. package/dist/chunker.d.ts.map +1 -0
  11. package/dist/chunker.js +112 -0
  12. package/dist/chunker.js.map +1 -0
  13. package/dist/config.d.ts +17 -0
  14. package/dist/config.d.ts.map +1 -0
  15. package/dist/config.js +28 -0
  16. package/dist/config.js.map +1 -0
  17. package/dist/context.d.ts +48 -0
  18. package/dist/context.d.ts.map +1 -0
  19. package/dist/context.js +0 -0
  20. package/dist/context.js.map +1 -0
  21. package/dist/coverage.d.ts +44 -0
  22. package/dist/coverage.d.ts.map +1 -0
  23. package/dist/coverage.js +95 -0
  24. package/dist/coverage.js.map +1 -0
  25. package/dist/index.d.ts +23 -0
  26. package/dist/index.d.ts.map +1 -0
  27. package/dist/index.js +28 -0
  28. package/dist/index.js.map +1 -0
  29. package/dist/minified-detection.d.ts +27 -0
  30. package/dist/minified-detection.d.ts.map +1 -0
  31. package/dist/minified-detection.js +46 -0
  32. package/dist/minified-detection.js.map +1 -0
  33. package/dist/prepared-text.d.ts +48 -0
  34. package/dist/prepared-text.d.ts.map +1 -0
  35. package/dist/prepared-text.js +57 -0
  36. package/dist/prepared-text.js.map +1 -0
  37. package/dist/split.d.ts +36 -0
  38. package/dist/split.d.ts.map +1 -0
  39. package/dist/split.js +126 -0
  40. package/dist/split.js.map +1 -0
  41. package/dist/strategies/ast-chunk-strategy.d.ts +52 -0
  42. package/dist/strategies/ast-chunk-strategy.d.ts.map +1 -0
  43. package/dist/strategies/ast-chunk-strategy.js +0 -0
  44. package/dist/strategies/ast-chunk-strategy.js.map +1 -0
  45. package/dist/strategies/line-fallback-strategy.d.ts +4 -0
  46. package/dist/strategies/line-fallback-strategy.d.ts.map +1 -0
  47. package/dist/strategies/line-fallback-strategy.js +79 -0
  48. package/dist/strategies/line-fallback-strategy.js.map +1 -0
  49. package/dist/strategies/minified-strategy.d.ts +4 -0
  50. package/dist/strategies/minified-strategy.d.ts.map +1 -0
  51. package/dist/strategies/minified-strategy.js +42 -0
  52. package/dist/strategies/minified-strategy.js.map +1 -0
  53. package/dist/token-estimator.d.ts +28 -0
  54. package/dist/token-estimator.d.ts.map +1 -0
  55. package/dist/token-estimator.js +37 -0
  56. package/dist/token-estimator.js.map +1 -0
  57. package/dist/types.d.ts +114 -0
  58. package/dist/types.d.ts.map +1 -0
  59. package/dist/types.js +20 -0
  60. package/dist/types.js.map +1 -0
  61. package/package.json +61 -3
  62. package/src/byte-text.ts +85 -0
  63. package/src/chunker.ts +142 -0
  64. package/src/config.ts +32 -0
  65. package/src/context.ts +0 -0
  66. package/src/coverage.ts +143 -0
  67. package/src/index.ts +63 -0
  68. package/src/minified-detection.ts +66 -0
  69. package/src/prepared-text.ts +118 -0
  70. package/src/split.ts +164 -0
  71. package/src/strategies/ast-chunk-strategy.ts +0 -0
  72. package/src/strategies/line-fallback-strategy.ts +108 -0
  73. package/src/strategies/minified-strategy.ts +49 -0
  74. package/src/token-estimator.ts +48 -0
  75. package/src/types.ts +138 -0
@@ -0,0 +1,48 @@
1
+ import type { ChunkKind, CodeChunkDraft, MetricsScope, ParseQuality, SourceRange } from "@untangle-code/domain";
2
+ import { type LineIndex } from "./byte-text.js";
3
+ import type { ChunkerConfig, ChunkFileIdentity } from "./types.js";
4
+ /** Header/metrics-scope metadata attached to one emitted chunk. */
5
+ export interface HeaderMeta {
6
+ symbolId?: string;
7
+ symbolName?: string;
8
+ symbolFqn?: string;
9
+ symbolKind?: string;
10
+ /** Signature or short symbol header; mandatory on `symbol_fragment` (spec.md §8.5). */
11
+ signature?: string;
12
+ astHash?: string;
13
+ metricsScope: MetricsScope;
14
+ metricsScopeId: string;
15
+ }
16
+ export interface BuildContext {
17
+ identity: ChunkFileIdentity;
18
+ lineIndex: LineIndex;
19
+ fileRange: SourceRange;
20
+ config: ChunkerConfig;
21
+ parseQuality: ParseQuality;
22
+ /** Per-(scopeId, chunkKind) emission counters feeding `chunk_ordinal` (spec.md §5.6). */
23
+ ordinals: Map<string, number>;
24
+ }
25
+ export declare function createBuildContext(identity: ChunkFileIdentity, content: string, config: ChunkerConfig, parseQuality: ParseQuality): BuildContext;
26
+ export declare function contentOf(ctx: BuildContext, range: SourceRange): string;
27
+ /**
28
+ * Token estimate of the FULL prepared dense text (header included) that
29
+ * `content` would produce under `header` — the quantity every splitting
30
+ * decision must budget against (architecture.md §14.4: "the header counts
31
+ * toward the token budget").
32
+ */
33
+ export declare function estimateTokensWithHeader(ctx: BuildContext, content: string, header: Pick<HeaderMeta, "symbolFqn" | "signature">): number;
34
+ export interface EmitParams {
35
+ range: SourceRange;
36
+ content: string;
37
+ /** Symbol id, or file id for file-scoped chunks (spec.md §5.6). */
38
+ scopeId: string;
39
+ chunkKind: ChunkKind;
40
+ header: HeaderMeta;
41
+ fragmentIndex?: number;
42
+ fragmentCount?: number;
43
+ /** Marks generated (non-byte-exact) content — see domain `CodeChunkDraft.synthesized`. */
44
+ synthesized?: boolean;
45
+ }
46
+ /** The single factory for `CodeChunkDraft`s; every strategy goes through this. */
47
+ export declare function emitChunk(ctx: BuildContext, params: EmitParams): CodeChunkDraft;
48
+ //# sourceMappingURL=context.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EACV,SAAS,EACT,cAAc,EACd,YAAY,EACZ,YAAY,EACZ,WAAW,EACZ,MAAM,uBAAuB,CAAC;AAE/B,OAAO,EAAkB,KAAK,SAAS,EAAc,MAAM,gBAAgB,CAAC;AAG5E,OAAO,KAAK,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAEnE,mEAAmE;AACnE,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,uFAAuF;IACvF,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,YAAY,CAAC;IAC3B,cAAc,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,YAAY;IAC3B,QAAQ,EAAE,iBAAiB,CAAC;IAC5B,SAAS,EAAE,SAAS,CAAC;IACrB,SAAS,EAAE,WAAW,CAAC;IACvB,MAAM,EAAE,aAAa,CAAC;IACtB,YAAY,EAAE,YAAY,CAAC;IAC3B,yFAAyF;IACzF,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC/B;AAED,wBAAgB,kBAAkB,CAChC,QAAQ,EAAE,iBAAiB,EAC3B,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,aAAa,EACrB,YAAY,EAAE,YAAY,GACzB,YAAY,CASd;AASD,wBAAgB,SAAS,CAAC,GAAG,EAAE,YAAY,EAAE,KAAK,EAAE,WAAW,GAAG,MAAM,CAEvE;AAED;;;;;GAKG;AACH,wBAAgB,wBAAwB,CACtC,GAAG,EAAE,YAAY,EACjB,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,IAAI,CAAC,UAAU,EAAE,WAAW,GAAG,WAAW,CAAC,GAClD,MAAM,CAYR;AAED,MAAM,WAAW,UAAU;IACzB,KAAK,EAAE,WAAW,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,mEAAmE;IACnE,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,SAAS,CAAC;IACrB,MAAM,EAAE,UAAU,CAAC;IACnB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,0FAA0F;IAC1F,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AA+CD,kFAAkF;AAClF,wBAAgB,SAAS,CAAC,GAAG,EAAE,YAAY,EAAE,MAAM,EAAE,UAAU,GAAG,cAAc,CA8D/E"}
Binary file
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context.js","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,44 @@
1
+ /**
2
+ * Coverage ledger construction (architecture.md §14.1; spec.md §8.4).
3
+ *
4
+ * The validator itself (`validateCoverage`) already lives in
5
+ * `@untangle-code/domain` as a pure function — it is the shared contract
6
+ * every producer must satisfy, so it is not redefined here. This module only
7
+ * builds the ledger entries as chunks are produced, and fills any residual
8
+ * gap the strategies left behind so the lossless invariant always holds
9
+ * before a file's chunking result is returned.
10
+ */
11
+ import type { CodeChunkDraft, CoverageEntry, SourceRange } from "@untangle-code/domain";
12
+ import { type LineIndex } from "./byte-text.js";
13
+ /** One "chunked" ledger entry for a single emitted chunk. */
14
+ export declare function chunkedEntry(range: SourceRange, chunkId: string): CoverageEntry;
15
+ /** One "excluded" ledger entry; `reason` is mandatory (spec.md §8.4). */
16
+ export declare function excludedEntry(range: SourceRange, reason: string): CoverageEntry;
17
+ /** The chunk fields `assertTruthfulLedger` needs (a structural subset of `CodeChunkDraft`). */
18
+ export type LedgerChunkView = Pick<CodeChunkDraft, "chunkId" | "chunkKind" | "range" | "content" | "synthesized">;
19
+ /**
20
+ * Asserts every ledger claim is TRUE, not merely byte-complete
21
+ * (spec.md §8.4; docs/BUILD_PLAN.md E4 — no silent masking of content):
22
+ *
23
+ * - every NON-synthesized chunk's `content` is byte-exactly the source
24
+ * bytes of its `range` (the `CodeChunkDraft.content` contract), so any
25
+ * "chunked" entry lying inside such a chunk's range is literally carried;
26
+ * - every "chunked" entry that is only backed by SYNTHESIZED chunks claims
27
+ * nothing beyond what those chunks literally carry: the claimed range's
28
+ * text (whitespace-trimmed) must appear verbatim in a claiming chunk's
29
+ * content;
30
+ * - every `chunkIds` reference resolves to an emitted chunk.
31
+ *
32
+ * A violation is an error (`UntangleError("ANALYSIS_INCOMPLETE")`), never a
33
+ * warning: a ledger entry that claims bytes no chunk content carries would
34
+ * silently mask content exactly as spec.md §8.4 forbids.
35
+ */
36
+ export declare function assertTruthfulLedger(lineIndex: LineIndex, drafts: readonly LedgerChunkView[], entries: readonly CoverageEntry[], filePath: string): void;
37
+ /**
38
+ * Asserts the lossless invariant holds for `entries` over `fileRange`, or
39
+ * throws `UntangleError("ANALYSIS_INCOMPLETE")` naming the concrete gaps
40
+ * (spec.md §8.4: hard truncation without a follow-up chunk is a bug, not a
41
+ * warning). Every chunking strategy MUST call this before returning.
42
+ */
43
+ export declare function assertLosslessCoverage(entries: readonly CoverageEntry[], fileRange: SourceRange, filePath: string): void;
44
+ //# sourceMappingURL=coverage.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"coverage.d.ts","sourceRoot":"","sources":["../src/coverage.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,KAAK,EAAE,cAAc,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAGxF,OAAO,EAAE,KAAK,SAAS,EAAc,MAAM,gBAAgB,CAAC;AAE5D,6DAA6D;AAC7D,wBAAgB,YAAY,CAAC,KAAK,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,GAAG,aAAa,CAE/E;AAED,yEAAyE;AACzE,wBAAgB,aAAa,CAAC,KAAK,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,GAAG,aAAa,CAE/E;AAED,+FAA+F;AAC/F,MAAM,MAAM,eAAe,GAAG,IAAI,CAChC,cAAc,EACd,SAAS,GAAG,WAAW,GAAG,OAAO,GAAG,SAAS,GAAG,aAAa,CAC9D,CAAC;AAEF;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,oBAAoB,CAClC,SAAS,EAAE,SAAS,EACpB,MAAM,EAAE,SAAS,eAAe,EAAE,EAClC,OAAO,EAAE,SAAS,aAAa,EAAE,EACjC,QAAQ,EAAE,MAAM,GACf,IAAI,CAiEN;AAED;;;;;GAKG;AACH,wBAAgB,sBAAsB,CACpC,OAAO,EAAE,SAAS,aAAa,EAAE,EACjC,SAAS,EAAE,WAAW,EACtB,QAAQ,EAAE,MAAM,GACf,IAAI,CAYN"}
@@ -0,0 +1,95 @@
1
+ import { UntangleError, validateCoverage } from "@untangle-code/domain";
2
+ import { sliceBytes } from "./byte-text.js";
3
+ /** One "chunked" ledger entry for a single emitted chunk. */
4
+ export function chunkedEntry(range, chunkId) {
5
+ return { range, status: "chunked", chunkIds: [chunkId] };
6
+ }
7
+ /** One "excluded" ledger entry; `reason` is mandatory (spec.md §8.4). */
8
+ export function excludedEntry(range, reason) {
9
+ return { range, status: "excluded", exclusionReason: reason };
10
+ }
11
+ /**
12
+ * Asserts every ledger claim is TRUE, not merely byte-complete
13
+ * (spec.md §8.4; docs/BUILD_PLAN.md E4 — no silent masking of content):
14
+ *
15
+ * - every NON-synthesized chunk's `content` is byte-exactly the source
16
+ * bytes of its `range` (the `CodeChunkDraft.content` contract), so any
17
+ * "chunked" entry lying inside such a chunk's range is literally carried;
18
+ * - every "chunked" entry that is only backed by SYNTHESIZED chunks claims
19
+ * nothing beyond what those chunks literally carry: the claimed range's
20
+ * text (whitespace-trimmed) must appear verbatim in a claiming chunk's
21
+ * content;
22
+ * - every `chunkIds` reference resolves to an emitted chunk.
23
+ *
24
+ * A violation is an error (`UntangleError("ANALYSIS_INCOMPLETE")`), never a
25
+ * warning: a ledger entry that claims bytes no chunk content carries would
26
+ * silently mask content exactly as spec.md §8.4 forbids.
27
+ */
28
+ export function assertTruthfulLedger(lineIndex, drafts, entries, filePath) {
29
+ const violations = [];
30
+ const byId = new Map();
31
+ for (const draft of drafts) {
32
+ byId.set(draft.chunkId, draft);
33
+ }
34
+ for (const draft of drafts) {
35
+ if (draft.synthesized === true) {
36
+ continue;
37
+ }
38
+ const sourceText = sliceBytes(lineIndex, draft.range.startByte, draft.range.endByte);
39
+ if (draft.content !== sourceText) {
40
+ violations.push(`non-synthesized ${draft.chunkKind} chunk ${draft.chunkId} content is not byte-exact for its range ${draft.range.startByte}..${draft.range.endByte}`);
41
+ }
42
+ }
43
+ for (const entry of entries) {
44
+ if (entry.status !== "chunked") {
45
+ continue;
46
+ }
47
+ const claimedTrimmed = sliceBytes(lineIndex, entry.range.startByte, entry.range.endByte).trim();
48
+ let proven = false;
49
+ for (const chunkId of entry.chunkIds ?? []) {
50
+ const draft = byId.get(chunkId);
51
+ if (draft === undefined) {
52
+ violations.push(`chunked entry ${entry.range.startByte}..${entry.range.endByte} references unknown chunk ${chunkId}`);
53
+ continue;
54
+ }
55
+ if (draft.synthesized !== true) {
56
+ // Content is byte-exact (checked above), so containment of the
57
+ // claimed byte range in the chunk range proves the claim literally.
58
+ if (draft.range.startByte <= entry.range.startByte &&
59
+ entry.range.endByte <= draft.range.endByte) {
60
+ proven = true;
61
+ break;
62
+ }
63
+ }
64
+ else if (draft.content.includes(claimedTrimmed)) {
65
+ proven = true;
66
+ break;
67
+ }
68
+ }
69
+ if (!proven) {
70
+ violations.push(`chunked entry ${entry.range.startByte}..${entry.range.endByte} claims bytes none of its chunks [${(entry.chunkIds ?? []).join(", ")}] literally carries`);
71
+ }
72
+ }
73
+ if (violations.length > 0) {
74
+ throw new UntangleError("ANALYSIS_INCOMPLETE", `coverage ledger of "${filePath}" claims content its chunks do not literally carry (spec.md §8.4)`, {
75
+ operation: "chunker.assertTruthfulLedger",
76
+ context: { filePath, violations },
77
+ });
78
+ }
79
+ }
80
+ /**
81
+ * Asserts the lossless invariant holds for `entries` over `fileRange`, or
82
+ * throws `UntangleError("ANALYSIS_INCOMPLETE")` naming the concrete gaps
83
+ * (spec.md §8.4: hard truncation without a follow-up chunk is a bug, not a
84
+ * warning). Every chunking strategy MUST call this before returning.
85
+ */
86
+ export function assertLosslessCoverage(entries, fileRange, filePath) {
87
+ const result = validateCoverage(entries, fileRange);
88
+ if (!result.complete) {
89
+ throw new UntangleError("ANALYSIS_INCOMPLETE", `chunking left the source of "${filePath}" incompletely covered (spec.md §8.4)`, {
90
+ operation: "chunker.assertLosslessCoverage",
91
+ context: { filePath, gaps: result.gaps, issues: result.issues },
92
+ });
93
+ }
94
+ }
95
+ //# sourceMappingURL=coverage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"coverage.js","sourceRoot":"","sources":["../src/coverage.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,23 @@
1
+ /**
2
+ * @untangle-code/chunker — lossless, token-budgeted AST chunking
3
+ * (spec.md §8, architecture.md §6.6 and §14).
4
+ *
5
+ * The only public export of this package. Consumers pass in what a
6
+ * `LanguageAdapter` (from `@untangle-code/domain`, implemented by
7
+ * `parser-registry`) already produced — `ParseResult`, `AstRegion[]`,
8
+ * `ExtractedSymbol[]` — plus file identity and raw content, and get back
9
+ * `CodeChunkDraft[]` ready for embedding and storage.
10
+ */
11
+ export { chunkFile } from "./chunker.js";
12
+ export { DEFAULT_LINE_FALLBACK_CONFIG, DEFAULT_MAX_TOKENS_PER_CHUNK, DEFAULT_MINIFIED_STRATEGY_CONFIG, resolveChunkerConfig, } from "./config.js";
13
+ export { CHUNK_DEGRADATION_REASONS } from "./types.js";
14
+ export type { ChunkDegradation, ChunkDegradationReason, ChunkerConfig, ChunkerConfigInput, ChunkFileIdentity, ChunkFileParams, ChunkFileResult, LineFallbackConfig, MinifiedStrategyConfig, } from "./types.js";
15
+ export { DEFAULT_TOKEN_ESTIMATOR_CONFIG, estimateTokens } from "./token-estimator.js";
16
+ export type { TokenEstimatorConfig } from "./token-estimator.js";
17
+ export { DEFAULT_MINIFIED_DETECTION_CONFIG, detectMinifiedContent } from "./minified-detection.js";
18
+ export type { MinifiedDetectionConfig } from "./minified-detection.js";
19
+ export { buildBm25Text, buildBm25TextForDraft, buildPreparedDenseText, buildPreparedDenseTextForDraft, } from "./prepared-text.js";
20
+ export type { Bm25TextMeta, PreparedTextContext, PreparedTextMeta } from "./prepared-text.js";
21
+ export { assertLosslessCoverage, assertTruthfulLedger, chunkedEntry, excludedEntry, } from "./coverage.js";
22
+ export type { LedgerChunkView } from "./coverage.js";
23
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAGH,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAGzC,OAAO,EACL,4BAA4B,EAC5B,4BAA4B,EAC5B,gCAAgC,EAChC,oBAAoB,GACrB,MAAM,aAAa,CAAC;AAErB,OAAO,EAAE,yBAAyB,EAAE,MAAM,YAAY,CAAC;AACvD,YAAY,EACV,gBAAgB,EAChB,sBAAsB,EACtB,aAAa,EACb,kBAAkB,EAClB,iBAAiB,EACjB,eAAe,EACf,eAAe,EACf,kBAAkB,EAClB,sBAAsB,GACvB,MAAM,YAAY,CAAC;AAIpB,OAAO,EAAE,8BAA8B,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtF,YAAY,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAIjE,OAAO,EAAE,iCAAiC,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAC;AACnG,YAAY,EAAE,uBAAuB,EAAE,MAAM,yBAAyB,CAAC;AAGvE,OAAO,EACL,aAAa,EACb,qBAAqB,EACrB,sBAAsB,EACtB,8BAA8B,GAC/B,MAAM,oBAAoB,CAAC;AAC5B,YAAY,EAAE,YAAY,EAAE,mBAAmB,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAI9F,OAAO,EACL,sBAAsB,EACtB,oBAAoB,EACpB,YAAY,EACZ,aAAa,GACd,MAAM,eAAe,CAAC;AACvB,YAAY,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,28 @@
1
+ /**
2
+ * @untangle-code/chunker — lossless, token-budgeted AST chunking
3
+ * (spec.md §8, architecture.md §6.6 and §14).
4
+ *
5
+ * The only public export of this package. Consumers pass in what a
6
+ * `LanguageAdapter` (from `@untangle-code/domain`, implemented by
7
+ * `parser-registry`) already produced — `ParseResult`, `AstRegion[]`,
8
+ * `ExtractedSymbol[]` — plus file identity and raw content, and get back
9
+ * `CodeChunkDraft[]` ready for embedding and storage.
10
+ */
11
+ // Main entry point (spec.md §8.3)
12
+ export { chunkFile } from "./chunker.js";
13
+ // Configuration
14
+ export { DEFAULT_LINE_FALLBACK_CONFIG, DEFAULT_MAX_TOKENS_PER_CHUNK, DEFAULT_MINIFIED_STRATEGY_CONFIG, resolveChunkerConfig, } from "./config.js";
15
+ // E4-Abstufungsledger (WP-165): warum die AST-Strategie nicht lief.
16
+ export { CHUNK_DEGRADATION_REASONS } from "./types.js";
17
+ // Token estimation (architecture.md §14.4) — exposed so callers can budget
18
+ // consistently, e.g. when deciding how many chunks fit a query context.
19
+ export { DEFAULT_TOKEN_ESTIMATOR_CONFIG, estimateTokens } from "./token-estimator.js";
20
+ // Minified-content detection (spec.md §8.3 step 10) — exposed so a scanner
21
+ // can pre-classify files without re-implementing the heuristic.
22
+ export { DEFAULT_MINIFIED_DETECTION_CONFIG, detectMinifiedContent } from "./minified-detection.js";
23
+ // Prepared text builder (spec.md §8.6)
24
+ export { buildBm25Text, buildBm25TextForDraft, buildPreparedDenseText, buildPreparedDenseTextForDraft, } from "./prepared-text.js";
25
+ // Coverage ledger helpers (architecture.md §14.1; spec.md §8.4) — the
26
+ // validator itself is `validateCoverage` from `@untangle-code/domain`.
27
+ export { assertLosslessCoverage, assertTruthfulLedger, chunkedEntry, excludedEntry, } from "./coverage.js";
28
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,kCAAkC;AAClC,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAEzC,gBAAgB;AAChB,OAAO,EACL,4BAA4B,EAC5B,4BAA4B,EAC5B,gCAAgC,EAChC,oBAAoB,GACrB,MAAM,aAAa,CAAC;AACrB,oEAAoE;AACpE,OAAO,EAAE,yBAAyB,EAAE,MAAM,YAAY,CAAC;AAavD,2EAA2E;AAC3E,wEAAwE;AACxE,OAAO,EAAE,8BAA8B,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAGtF,2EAA2E;AAC3E,gEAAgE;AAChE,OAAO,EAAE,iCAAiC,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAC;AAGnG,uCAAuC;AACvC,OAAO,EACL,aAAa,EACb,qBAAqB,EACrB,sBAAsB,EACtB,8BAA8B,GAC/B,MAAM,oBAAoB,CAAC;AAG5B,sEAAsE;AACtE,uEAAuE;AACvE,OAAO,EACL,sBAAsB,EACtB,oBAAoB,EACpB,YAAY,EACZ,aAAa,GACd,MAAM,eAAe,CAAC"}
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Minified-content detection (spec.md §8.3 step 10).
3
+ *
4
+ * Untangle decision (documented in README "Entscheidungen"): minification is
5
+ * detected from the raw text alone, BEFORE looking at parse results, because
6
+ * minified code can parse perfectly well while still being useless for
7
+ * per-symbol AST chunking (a bundled `.min.js` often has its entire runtime
8
+ * as one statement on one line). Detection is a simple, explainable
9
+ * character-shape heuristic — no dependency on a bundler manifest or file
10
+ * name convention, since generated output does not always carry one.
11
+ */
12
+ import type { TextFormatKind } from "@untangle-code/domain";
13
+ export interface MinifiedDetectionConfig {
14
+ /** Below this file size (bytes), never classify as minified (avoids false positives on tiny files). */
15
+ minSizeBytes: number;
16
+ /** Average bytes-per-line at or above which content is considered minified. */
17
+ avgLineLengthThreshold: number;
18
+ /** A single long line is sufficient only for structured data, not code or prose. */
19
+ maxLineLengthThreshold: number;
20
+ }
21
+ export declare const DEFAULT_MINIFIED_DETECTION_CONFIG: MinifiedDetectionConfig;
22
+ /**
23
+ * Heuristically classifies `content` as minified. Pure, deterministic,
24
+ * offline — no tokenizer, no bundler introspection.
25
+ */
26
+ export declare function detectMinifiedContent(content: string, config?: MinifiedDetectionConfig, textFormat?: TextFormatKind | null): boolean;
27
+ //# sourceMappingURL=minified-detection.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"minified-detection.d.ts","sourceRoot":"","sources":["../src/minified-detection.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAGH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAE5D,MAAM,WAAW,uBAAuB;IACtC,uGAAuG;IACvG,YAAY,EAAE,MAAM,CAAC;IACrB,+EAA+E;IAC/E,sBAAsB,EAAE,MAAM,CAAC;IAC/B,oFAAoF;IACpF,sBAAsB,EAAE,MAAM,CAAC;CAChC;AAED,eAAO,MAAM,iCAAiC,EAAE,uBAO/C,CAAC;AAEF;;;GAGG;AACH,wBAAgB,qBAAqB,CACnC,OAAO,EAAE,MAAM,EACf,MAAM,GAAE,uBAA2D,EACnE,UAAU,CAAC,EAAE,cAAc,GAAG,IAAI,GACjC,OAAO,CAwBT"}
@@ -0,0 +1,46 @@
1
+ /**
2
+ * Minified-content detection (spec.md §8.3 step 10).
3
+ *
4
+ * Untangle decision (documented in README "Entscheidungen"): minification is
5
+ * detected from the raw text alone, BEFORE looking at parse results, because
6
+ * minified code can parse perfectly well while still being useless for
7
+ * per-symbol AST chunking (a bundled `.min.js` often has its entire runtime
8
+ * as one statement on one line). Detection is a simple, explainable
9
+ * character-shape heuristic — no dependency on a bundler manifest or file
10
+ * name convention, since generated output does not always carry one.
11
+ */
12
+ import { DEFAULT_MINIFIED_RULE, isMinifiedShape } from "@untangle-code/domain";
13
+ export const DEFAULT_MINIFIED_DETECTION_CONFIG = {
14
+ minSizeBytes: 2000,
15
+ avgLineLengthThreshold: 300,
16
+ // Welle 13: von 1000 auf 500 angeglichen. Der Scanner entschied ohnehin bei
17
+ // 500, und im Indexpfad kam dieser Wert nie zum Zug — zwei Schwellen fuer
18
+ // eine Frage waren der Fehler, nicht die eine oder die andere Zahl.
19
+ maxLineLengthThreshold: DEFAULT_MINIFIED_RULE.maxLineLengthThreshold,
20
+ };
21
+ /**
22
+ * Heuristically classifies `content` as minified. Pure, deterministic,
23
+ * offline — no tokenizer, no bundler introspection.
24
+ */
25
+ export function detectMinifiedContent(content, config = DEFAULT_MINIFIED_DETECTION_CONFIG, textFormat) {
26
+ const size = Buffer.byteLength(content, "utf8");
27
+ if (size < config.minSizeBytes) {
28
+ return false;
29
+ }
30
+ const lines = content.split("\n");
31
+ let maxLineLength = 0;
32
+ for (const line of lines) {
33
+ if (line.length > maxLineLength) {
34
+ maxLineLength = line.length;
35
+ }
36
+ }
37
+ // Entschieden wird in `@untangle-code/domain`: dieselbe Frage darf nicht an
38
+ // zwei Orten mit zwei Schwellen beantwortet werden. Bis Welle 13 galt hier
39
+ // 1000 und im Scanner 500 — welche Regel griff, hing am Aufrufpfad.
40
+ const avgLineLength = content.length / lines.length;
41
+ return isMinifiedShape({ maxLineLength, averageLineLength: avgLineLength }, { textFormat: textFormat ?? null }, {
42
+ maxLineLengthThreshold: config.maxLineLengthThreshold,
43
+ averageLineLengthThreshold: config.avgLineLengthThreshold,
44
+ });
45
+ }
46
+ //# sourceMappingURL=minified-detection.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"minified-detection.js","sourceRoot":"","sources":["../src/minified-detection.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,qBAAqB,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAY/E,MAAM,CAAC,MAAM,iCAAiC,GAA4B;IACxE,YAAY,EAAE,IAAI;IAClB,sBAAsB,EAAE,GAAG;IAC3B,4EAA4E;IAC5E,0EAA0E;IAC1E,oEAAoE;IACpE,sBAAsB,EAAE,qBAAqB,CAAC,sBAAsB;CACrE,CAAC;AAEF;;;GAGG;AACH,MAAM,UAAU,qBAAqB,CACnC,OAAe,EACf,SAAkC,iCAAiC,EACnE,UAAkC;IAElC,MAAM,IAAI,GAAG,MAAM,CAAC,UAAU,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;IAChD,IAAI,IAAI,GAAG,MAAM,CAAC,YAAY,EAAE,CAAC;QAC/B,OAAO,KAAK,CAAC;IACf,CAAC;IACD,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAClC,IAAI,aAAa,GAAG,CAAC,CAAC;IACtB,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,IAAI,IAAI,CAAC,MAAM,GAAG,aAAa,EAAE,CAAC;YAChC,aAAa,GAAG,IAAI,CAAC,MAAM,CAAC;QAC9B,CAAC;IACH,CAAC;IACD,4EAA4E;IAC5E,2EAA2E;IAC3E,oEAAoE;IACpE,MAAM,aAAa,GAAG,OAAO,CAAC,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC;IACpD,OAAO,eAAe,CACpB,EAAE,aAAa,EAAE,iBAAiB,EAAE,aAAa,EAAE,EACnD,EAAE,UAAU,EAAE,UAAU,IAAI,IAAI,EAAE,EAClC;QACE,sBAAsB,EAAE,MAAM,CAAC,sBAAsB;QACrD,0BAA0B,EAAE,MAAM,CAAC,sBAAsB;KAC1D,CACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,48 @@
1
+ /**
2
+ * Prepared text builder (spec.md §8.6).
3
+ *
4
+ * Dense text gets a metadata header (repository/ref/path/language/symbol/
5
+ * signature) followed by a blank line and the raw content — this header
6
+ * counts toward the chunk's token budget (architecture.md §14.4), which is
7
+ * why every function here is also usable standalone during chunk planning,
8
+ * before a `CodeChunkDraft` object exists.
9
+ *
10
+ * BM25 text is deliberately undecorated: raw code, path, symbol names and a
11
+ * light identifier extraction, with no natural-language framing, so a
12
+ * lexical index scores on the same surface a keyword search would use.
13
+ */
14
+ import type { CodeChunkDraft } from "@untangle-code/domain";
15
+ /** Header fields that are not part of a `CodeChunkDraft` (spec.md §8.6). */
16
+ export interface PreparedTextContext {
17
+ /** Corresponds to `EmbeddingProfile.documentPrefix` (spec.md §5.7, §9). */
18
+ documentPrefix: string;
19
+ /** Human-readable repository label (`repo_label`), e.g. "untangle". */
20
+ repoLabel: string;
21
+ /** Human-readable ref name (`ref_name`), e.g. "main". */
22
+ refName: string;
23
+ }
24
+ /** The subset of chunk metadata the dense header needs. */
25
+ export interface PreparedTextMeta {
26
+ filePath: string;
27
+ language: string;
28
+ symbolFqn?: string | undefined;
29
+ signature?: string | undefined;
30
+ }
31
+ /** Builds the dense document text of spec.md §8.6 from loose metadata + content. */
32
+ export declare function buildPreparedDenseText(ctx: PreparedTextContext, meta: PreparedTextMeta, content: string): string;
33
+ /** Convenience wrapper of {@link buildPreparedDenseText} for an existing draft. */
34
+ export declare function buildPreparedDenseTextForDraft(ctx: PreparedTextContext, draft: CodeChunkDraft): string;
35
+ /** The subset of chunk metadata the BM25 text needs. */
36
+ export interface Bm25TextMeta {
37
+ filePath: string;
38
+ symbolName?: string | undefined;
39
+ symbolFqn?: string | undefined;
40
+ }
41
+ /**
42
+ * Builds the BM25 text of spec.md §8.6: raw code, path, symbol names and
43
+ * identifiers, without natural-language decoration.
44
+ */
45
+ export declare function buildBm25Text(meta: Bm25TextMeta, content: string): string;
46
+ /** Convenience wrapper of {@link buildBm25Text} for an existing draft. */
47
+ export declare function buildBm25TextForDraft(draft: CodeChunkDraft): string;
48
+ //# sourceMappingURL=prepared-text.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prepared-text.d.ts","sourceRoot":"","sources":["../src/prepared-text.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAE5D,4EAA4E;AAC5E,MAAM,WAAW,mBAAmB;IAClC,2EAA2E;IAC3E,cAAc,EAAE,MAAM,CAAC;IACvB,uEAAuE;IACvE,SAAS,EAAE,MAAM,CAAC;IAClB,yDAAyD;IACzD,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,2DAA2D;AAC3D,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC/B,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAChC;AAmBD,oFAAoF;AACpF,wBAAgB,sBAAsB,CACpC,GAAG,EAAE,mBAAmB,EACxB,IAAI,EAAE,gBAAgB,EACtB,OAAO,EAAE,MAAM,GACd,MAAM,CAER;AAED,mFAAmF;AACnF,wBAAgB,8BAA8B,CAC5C,GAAG,EAAE,mBAAmB,EACxB,KAAK,EAAE,cAAc,GACpB,MAAM,CAWR;AAaD,wDAAwD;AACxD,MAAM,WAAW,YAAY;IAC3B,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAChC,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAChC;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAWzE;AAED,0EAA0E;AAC1E,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,cAAc,GAAG,MAAM,CAKnE"}
@@ -0,0 +1,57 @@
1
+ function buildDenseHeader(ctx, meta) {
2
+ // Trailing "\n\n" reproduces the blank line spec.md §8.6 shows between the
3
+ // header's last line ("signature: ...") and "{content}" — a `join("\n")`
4
+ // over the header lines alone only yields a single trailing newline.
5
+ return ([
6
+ ctx.documentPrefix,
7
+ `repository: ${ctx.repoLabel}`,
8
+ `ref: ${ctx.refName}`,
9
+ `path: ${meta.filePath}`,
10
+ `language: ${meta.language}`,
11
+ `symbol: ${meta.symbolFqn ?? ""}`,
12
+ `signature: ${meta.signature ?? ""}`,
13
+ ].join("\n") + "\n\n");
14
+ }
15
+ /** Builds the dense document text of spec.md §8.6 from loose metadata + content. */
16
+ export function buildPreparedDenseText(ctx, meta, content) {
17
+ return buildDenseHeader(ctx, meta) + content;
18
+ }
19
+ /** Convenience wrapper of {@link buildPreparedDenseText} for an existing draft. */
20
+ export function buildPreparedDenseTextForDraft(ctx, draft) {
21
+ return buildPreparedDenseText(ctx, {
22
+ filePath: draft.filePath,
23
+ language: draft.language,
24
+ symbolFqn: draft.symbolFqn,
25
+ signature: draft.signature,
26
+ }, draft.content);
27
+ }
28
+ /** Identifier-shaped tokens: letters/digits/underscore/`$`, not starting with a digit. */
29
+ const IDENTIFIER_PATTERN = /[A-Za-z_$][A-Za-z0-9_$]*/g;
30
+ function extractIdentifiers(text) {
31
+ const seen = new Set();
32
+ for (const match of text.matchAll(IDENTIFIER_PATTERN)) {
33
+ seen.add(match[0]);
34
+ }
35
+ return [...seen];
36
+ }
37
+ /**
38
+ * Builds the BM25 text of spec.md §8.6: raw code, path, symbol names and
39
+ * identifiers, without natural-language decoration.
40
+ */
41
+ export function buildBm25Text(meta, content) {
42
+ const parts = [meta.filePath];
43
+ if (meta.symbolFqn) {
44
+ parts.push(meta.symbolFqn);
45
+ }
46
+ if (meta.symbolName) {
47
+ parts.push(meta.symbolName);
48
+ }
49
+ parts.push(...extractIdentifiers(content));
50
+ parts.push(content);
51
+ return parts.join("\n");
52
+ }
53
+ /** Convenience wrapper of {@link buildBm25Text} for an existing draft. */
54
+ export function buildBm25TextForDraft(draft) {
55
+ return buildBm25Text({ filePath: draft.filePath, symbolName: draft.symbolName, symbolFqn: draft.symbolFqn }, draft.content);
56
+ }
57
+ //# sourceMappingURL=prepared-text.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prepared-text.js","sourceRoot":"","sources":["../src/prepared-text.ts"],"names":[],"mappings":"AAiCA,SAAS,gBAAgB,CAAC,GAAwB,EAAE,IAAsB;IACxE,2EAA2E;IAC3E,yEAAyE;IACzE,qEAAqE;IACrE,OAAO,CACL;QACE,GAAG,CAAC,cAAc;QAClB,eAAe,GAAG,CAAC,SAAS,EAAE;QAC9B,QAAQ,GAAG,CAAC,OAAO,EAAE;QACrB,SAAS,IAAI,CAAC,QAAQ,EAAE;QACxB,aAAa,IAAI,CAAC,QAAQ,EAAE;QAC5B,WAAW,IAAI,CAAC,SAAS,IAAI,EAAE,EAAE;QACjC,cAAc,IAAI,CAAC,SAAS,IAAI,EAAE,EAAE;KACrC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,MAAM,CACtB,CAAC;AACJ,CAAC;AAED,oFAAoF;AACpF,MAAM,UAAU,sBAAsB,CACpC,GAAwB,EACxB,IAAsB,EACtB,OAAe;IAEf,OAAO,gBAAgB,CAAC,GAAG,EAAE,IAAI,CAAC,GAAG,OAAO,CAAC;AAC/C,CAAC;AAED,mFAAmF;AACnF,MAAM,UAAU,8BAA8B,CAC5C,GAAwB,EACxB,KAAqB;IAErB,OAAO,sBAAsB,CAC3B,GAAG,EACH;QACE,QAAQ,EAAE,KAAK,CAAC,QAAQ;QACxB,QAAQ,EAAE,KAAK,CAAC,QAAQ;QACxB,SAAS,EAAE,KAAK,CAAC,SAAS;QAC1B,SAAS,EAAE,KAAK,CAAC,SAAS;KAC3B,EACD,KAAK,CAAC,OAAO,CACd,CAAC;AACJ,CAAC;AAED,0FAA0F;AAC1F,MAAM,kBAAkB,GAAG,2BAA2B,CAAC;AAEvD,SAAS,kBAAkB,CAAC,IAAY;IACtC,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;IAC/B,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,QAAQ,CAAC,kBAAkB,CAAC,EAAE,CAAC;QACtD,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IACrB,CAAC;IACD,OAAO,CAAC,GAAG,IAAI,CAAC,CAAC;AACnB,CAAC;AASD;;;GAGG;AACH,MAAM,UAAU,aAAa,CAAC,IAAkB,EAAE,OAAe;IAC/D,MAAM,KAAK,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IAC9B,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;QACnB,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IAC7B,CAAC;IACD,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC;QACpB,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IAC9B,CAAC;IACD,KAAK,CAAC,IAAI,CAAC,GAAG,kBAAkB,CAAC,OAAO,CAAC,CAAC,CAAC;IAC3C,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IACpB,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC;AAED,0EAA0E;AAC1E,MAAM,UAAU,qBAAqB,CAAC,KAAqB;IACzD,OAAO,aAAa,CAClB,EAAE,QAAQ,EAAE,KAAK,CAAC,QAAQ,EAAE,UAAU,EAAE,KAAK,CAAC,UAAU,EAAE,SAAS,EAAE,KAAK,CAAC,SAAS,EAAE,EACtF,KAAK,CAAC,OAAO,CACd,CAAC;AACJ,CAAC"}
@@ -0,0 +1,36 @@
1
+ /**
2
+ * Region splitting mechanics shared by the AST strategy (spec.md §8.3 steps
3
+ * 6-8) and reused defensively by the fallback strategies:
4
+ *
5
+ * 1. `flattenToAtoms` — recursive AST-block splitting (step 6) plus
6
+ * statement grouping (step 7): descends into `AstRegion.children` only as
7
+ * far as needed, filling any gap between/around children with a raw
8
+ * "leftover text" atom so the atom list always covers the parent range
9
+ * exactly, then greedily re-merges adjacent atoms under the token budget.
10
+ * 2. `splitByTokenBoundary` — safe token/byte-boundary splitting (step 8):
11
+ * the last resort for a single atom that is still too large on its own
12
+ * (e.g. one enormous statement with no further AST structure).
13
+ */
14
+ import type { AstRegion, SourceRange } from "@untangle-code/domain";
15
+ import { type BuildContext, type HeaderMeta } from "./context.js";
16
+ type Header = Pick<HeaderMeta, "symbolFqn" | "signature">;
17
+ /** Greedily merges adjacent (contiguous, ordered) atoms while staying under budget. */
18
+ export declare function groupAtomsByBudget(ctx: BuildContext, atoms: readonly SourceRange[], header: Header): SourceRange[];
19
+ /**
20
+ * Recursively splits `node` into an ordered, gap-free list of ranges that
21
+ * together cover `node.range` exactly. A node that already fits the budget
22
+ * is returned whole. A node with no further AST structure that still does
23
+ * not fit is returned whole too — {@link splitByTokenBoundary} handles it.
24
+ */
25
+ export declare function flattenToAtoms(ctx: BuildContext, node: AstRegion, header: Header): SourceRange[];
26
+ /**
27
+ * Splits `range` into an ordered, gap-free, non-overlapping list of ranges,
28
+ * each within the token budget, at safe UTF-8 boundaries (architecture.md
29
+ * §14.4). Last-resort splitter: used only on atoms `flattenToAtoms` could
30
+ * not shrink through AST structure.
31
+ */
32
+ export declare function splitByTokenBoundary(ctx: BuildContext, range: SourceRange, header: Header): SourceRange[];
33
+ /** Re-exported for strategies that need a raw byte slice without going through an `AstRegion`. */
34
+ export declare function sliceRange(ctx: BuildContext, range: SourceRange): string;
35
+ export {};
36
+ //# sourceMappingURL=split.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"split.d.ts","sourceRoot":"","sources":["../src/split.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,OAAO,KAAK,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAGpE,OAAO,EACL,KAAK,YAAY,EAGjB,KAAK,UAAU,EAChB,MAAM,cAAc,CAAC;AAEtB,KAAK,MAAM,GAAG,IAAI,CAAC,UAAU,EAAE,WAAW,GAAG,WAAW,CAAC,CAAC;AAY1D,uFAAuF;AACvF,wBAAgB,kBAAkB,CAChC,GAAG,EAAE,YAAY,EACjB,KAAK,EAAE,SAAS,WAAW,EAAE,EAC7B,MAAM,EAAE,MAAM,GACb,WAAW,EAAE,CAkBf;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,YAAY,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,GAAG,WAAW,EAAE,CAqBhG;AAwCD;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAClC,GAAG,EAAE,YAAY,EACjB,KAAK,EAAE,WAAW,EAClB,MAAM,EAAE,MAAM,GACb,WAAW,EAAE,CAqBf;AAED,kGAAkG;AAClG,wBAAgB,UAAU,CAAC,GAAG,EAAE,YAAY,EAAE,KAAK,EAAE,WAAW,GAAG,MAAM,CAExE"}