greprag 5.40.1 → 5.42.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 (80) hide show
  1. package/dist/archive/glyph-font.d.ts +22 -0
  2. package/dist/archive/glyph-font.js +72 -0
  3. package/dist/archive/glyph-font.js.map +1 -0
  4. package/dist/archive/page-renderer.d.ts +67 -0
  5. package/dist/archive/page-renderer.js +197 -0
  6. package/dist/archive/page-renderer.js.map +1 -0
  7. package/dist/archive/png-codec.d.ts +21 -0
  8. package/dist/archive/png-codec.js +197 -0
  9. package/dist/archive/png-codec.js.map +1 -0
  10. package/dist/archive/transcript-extract.d.ts +39 -0
  11. package/dist/archive/transcript-extract.js +187 -0
  12. package/dist/archive/transcript-extract.js.map +1 -0
  13. package/dist/ccr-store.d.ts +49 -0
  14. package/dist/ccr-store.js +171 -0
  15. package/dist/ccr-store.js.map +1 -0
  16. package/dist/commands/archive.d.ts +81 -0
  17. package/dist/commands/archive.js +358 -0
  18. package/dist/commands/archive.js.map +1 -0
  19. package/dist/commands/context-governor.d.ts +82 -0
  20. package/dist/commands/context-governor.js +344 -0
  21. package/dist/commands/context-governor.js.map +1 -0
  22. package/dist/commands/crush-stats.d.ts +36 -0
  23. package/dist/commands/crush-stats.js +142 -0
  24. package/dist/commands/crush-stats.js.map +1 -0
  25. package/dist/commands/crush.d.ts +24 -0
  26. package/dist/commands/crush.js +183 -0
  27. package/dist/commands/crush.js.map +1 -0
  28. package/dist/commands/email.js +158 -9
  29. package/dist/commands/email.js.map +1 -1
  30. package/dist/commands/inbox-watch-supervisor.js +8 -65
  31. package/dist/commands/inbox-watch-supervisor.js.map +1 -1
  32. package/dist/commands/init.js +93 -0
  33. package/dist/commands/init.js.map +1 -1
  34. package/dist/commands/pipe-wrap.d.ts +75 -0
  35. package/dist/commands/pipe-wrap.js +255 -0
  36. package/dist/commands/pipe-wrap.js.map +1 -0
  37. package/dist/commands/watcher-registry.d.ts +1 -8
  38. package/dist/commands/watcher-registry.js +10 -47
  39. package/dist/commands/watcher-registry.js.map +1 -1
  40. package/dist/crush/adaptive-sizer.d.ts +40 -0
  41. package/dist/crush/adaptive-sizer.js +156 -0
  42. package/dist/crush/adaptive-sizer.js.map +1 -0
  43. package/dist/crush/crush-keywords.d.ts +40 -0
  44. package/dist/crush/crush-keywords.js +110 -0
  45. package/dist/crush/crush-keywords.js.map +1 -0
  46. package/dist/crush/crush-types.d.ts +38 -0
  47. package/dist/crush/crush-types.js +36 -0
  48. package/dist/crush/crush-types.js.map +1 -0
  49. package/dist/crush/index.d.ts +16 -0
  50. package/dist/crush/index.js +48 -0
  51. package/dist/crush/index.js.map +1 -0
  52. package/dist/crush/json-crusher.d.ts +38 -0
  53. package/dist/crush/json-crusher.js +250 -0
  54. package/dist/crush/json-crusher.js.map +1 -0
  55. package/dist/crush/json-detectors.d.ts +48 -0
  56. package/dist/crush/json-detectors.js +211 -0
  57. package/dist/crush/json-detectors.js.map +1 -0
  58. package/dist/crush/log-compressor.d.ts +60 -0
  59. package/dist/crush/log-compressor.js +394 -0
  60. package/dist/crush/log-compressor.js.map +1 -0
  61. package/dist/crush/search-compressor.d.ts +60 -0
  62. package/dist/crush/search-compressor.js +210 -0
  63. package/dist/crush/search-compressor.js.map +1 -0
  64. package/dist/email-pull.d.ts +25 -3
  65. package/dist/email-pull.js +25 -5
  66. package/dist/email-pull.js.map +1 -1
  67. package/dist/email-send.d.ts +4 -0
  68. package/dist/email-send.js +2 -0
  69. package/dist/email-send.js.map +1 -1
  70. package/dist/hook.js +49 -1
  71. package/dist/hook.js.map +1 -1
  72. package/dist/index.js +487 -449
  73. package/dist/index.js.map +1 -1
  74. package/dist/session-id.js +7 -12
  75. package/dist/session-id.js.map +1 -1
  76. package/package.json +2 -2
  77. package/skill/greprag/SKILL.md +2 -2
  78. package/skill/greprag/docs/email.md +28 -4
  79. package/skill/mechanic/SKILL.md +1 -1
  80. package/skill/templates/chip-spawn.md +4 -2
@@ -0,0 +1,156 @@
1
+ "use strict";
2
+ /**
3
+ * MIRRORED FILE — canonical source: packages/core/src/crush/adaptive-sizer.ts.
4
+ * Byte-identical copy lives at packages/cli/src/crush/adaptive-sizer.ts (the CLI is a
5
+ * zero-dep artifact and cannot import @greprag/core). KEEP IN SYNC —
6
+ * the sync guard in tests/test-crush.cjs fails the build on drift.
7
+ *
8
+ * Adaptive keep-count via information saturation — port of Headroom's
9
+ * transforms/adaptive_sizer.rs (itself a port of adaptive_sizer.py).
10
+ *
11
+ * Decides HOW MANY items to keep, statistically: find the knee of the
12
+ * cumulative unique-bigram coverage curve (Kneedle). Coverage stops
13
+ * growing -> that's the knee -> keep that many.
14
+ *
15
+ * Deliberate divergence from Headroom: the zlib-ratio validation tier
16
+ * is dropped (it nudged k up ~20% on pathological subsets; not worth a
17
+ * compression dependency in a zero-dep core). Simhash is replaced with
18
+ * a plain FNV-1a 4-gram sketch — it only feeds the "near-total
19
+ * redundancy" fast path, where any stable hash works.
20
+ */
21
+ Object.defineProperty(exports, "__esModule", { value: true });
22
+ exports.computeUniqueBigramCurve = computeUniqueBigramCurve;
23
+ exports.findKnee = findKnee;
24
+ exports.computeOptimalK = computeOptimalK;
25
+ /** FNV-1a 32-bit over a string, with a seed offset. Stable, dependency-free. */
26
+ function fnv1a(s, seed) {
27
+ let h = (0x811c9dc5 ^ seed) >>> 0;
28
+ for (let i = 0; i < s.length; i++) {
29
+ h ^= s.charCodeAt(i);
30
+ h = Math.imul(h, 0x01000193);
31
+ }
32
+ return h >>> 0;
33
+ }
34
+ /** 64-bit-ish simhash over character 4-grams (two independent FNV seeds). */
35
+ function simhash(s) {
36
+ const votes1 = new Array(32).fill(0);
37
+ const votes2 = new Array(32).fill(0);
38
+ const text = s.length < 4 ? s + ' '.repeat(4 - s.length) : s;
39
+ for (let i = 0; i + 4 <= text.length; i++) {
40
+ const gram = text.slice(i, i + 4);
41
+ const h1 = fnv1a(gram, 0);
42
+ const h2 = fnv1a(gram, 0x9e3779b9);
43
+ for (let b = 0; b < 32; b++) {
44
+ votes1[b] += (h1 >>> b) & 1 ? 1 : -1;
45
+ votes2[b] += (h2 >>> b) & 1 ? 1 : -1;
46
+ }
47
+ }
48
+ let out = '';
49
+ for (let b = 0; b < 32; b++)
50
+ out += votes1[b] >= 0 ? '1' : '0';
51
+ for (let b = 0; b < 32; b++)
52
+ out += votes2[b] >= 0 ? '1' : '0';
53
+ return out;
54
+ }
55
+ /**
56
+ * Count distinct simhash groups. No early exit — the count also feeds
57
+ * the diversity ratio, which needs the true cardinality.
58
+ */
59
+ function countUniqueSimhash(items) {
60
+ const seen = new Set();
61
+ for (const item of items)
62
+ seen.add(simhash(item));
63
+ return seen.size;
64
+ }
65
+ /**
66
+ * Cumulative unique word-bigram coverage: curve[i] = distinct bigrams
67
+ * seen across items[0..=i]. Single-word items emit `(word, "")`;
68
+ * empty items emit `("", "")` — mirrors the Python/Rust cardinality.
69
+ */
70
+ function computeUniqueBigramCurve(items) {
71
+ const seen = new Set();
72
+ const curve = [];
73
+ for (const item of items) {
74
+ const words = item.split(/\s+/).filter((w) => w.length > 0);
75
+ if (words.length === 0) {
76
+ seen.add(' ');
77
+ }
78
+ else if (words.length === 1) {
79
+ seen.add(words[0] + ' ');
80
+ }
81
+ else {
82
+ for (let i = 0; i + 1 < words.length; i++) {
83
+ seen.add(words[i] + ' ' + words[i + 1]);
84
+ }
85
+ }
86
+ curve.push(seen.size);
87
+ }
88
+ return curve;
89
+ }
90
+ /**
91
+ * Kneedle knee finder on a monotonically-increasing curve. Returns the
92
+ * 1-indexed keep-count, or null when no knee clears the 0.05 deviation
93
+ * threshold. Flat curve (all items identical) -> 1.
94
+ */
95
+ function findKnee(curve) {
96
+ const n = curve.length;
97
+ if (n < 3)
98
+ return null;
99
+ const yMin = curve[0];
100
+ const yMax = curve[n - 1];
101
+ if (Math.abs(yMax - yMin) < Number.EPSILON)
102
+ return 1;
103
+ const xRange = n - 1;
104
+ const yRange = yMax - yMin;
105
+ let maxDiff = -1;
106
+ let kneeIdx = null;
107
+ for (let i = 0; i < n; i++) {
108
+ const xNorm = i / xRange;
109
+ const yNorm = (curve[i] - yMin) / yRange;
110
+ const diff = yNorm - xNorm;
111
+ if (diff > maxDiff) {
112
+ maxDiff = diff;
113
+ kneeIdx = i;
114
+ }
115
+ }
116
+ if (maxDiff < 0.05)
117
+ return null;
118
+ return kneeIdx === null ? null : kneeIdx + 1;
119
+ }
120
+ /**
121
+ * Compute the optimal number of items to keep.
122
+ *
123
+ * @param items string representations of items in importance order
124
+ * @param bias multiplier on the knee (>1 keep more, <1 compress harder)
125
+ * @param minK lower bound
126
+ * @param maxK upper bound (undefined = items.length)
127
+ */
128
+ function computeOptimalK(items, bias, minK, maxK) {
129
+ const n = items.length;
130
+ const effectiveMax = maxK ?? n;
131
+ // Tier 1: trivial.
132
+ if (n <= 8)
133
+ return n;
134
+ // Near-total redundancy: <=3 unique groups -> keep that many.
135
+ const uniqueCount = countUniqueSimhash(items);
136
+ if (uniqueCount <= 3) {
137
+ return Math.min(Math.max(minK, uniqueCount), effectiveMax);
138
+ }
139
+ // Tier 2: Kneedle on the bigram coverage curve.
140
+ const curve = computeUniqueBigramCurve(items);
141
+ let knee = findKnee(curve);
142
+ const diversityRatio = uniqueCount / n;
143
+ if (knee === null) {
144
+ // No saturation — scale keep-fraction with diversity.
145
+ const keepFraction = 0.3 + 0.7 * diversityRatio;
146
+ knee = Math.max(minK, Math.floor(n * keepFraction));
147
+ }
148
+ else if (diversityRatio > 0.7) {
149
+ const floor = Math.max(minK, Math.floor(n * (0.3 + 0.7 * diversityRatio)));
150
+ knee = Math.max(knee, floor);
151
+ }
152
+ let k = Math.max(minK, Math.floor(knee * bias));
153
+ k = Math.min(k, effectiveMax);
154
+ return Math.max(minK, Math.min(k, effectiveMax));
155
+ }
156
+ //# sourceMappingURL=adaptive-sizer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"adaptive-sizer.js","sourceRoot":"","sources":["../../src/crush/adaptive-sizer.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,40 @@
1
+ /**
2
+ * MIRRORED FILE — canonical source: packages/core/src/crush/crush-keywords.ts.
3
+ * Byte-identical copy lives at packages/cli/src/crush/crush-keywords.ts (the CLI is a
4
+ * zero-dep artifact and cannot import @greprag/core). KEEP IN SYNC —
5
+ * the sync guard in tests/test-crush.cjs fails the build on drift.
6
+ *
7
+ * Keyword registries + word-boundary classification shared by the crush
8
+ * compressors. Port of Headroom's signals/keyword_detector.rs +
9
+ * smart_crusher/error_keywords.rs.
10
+ *
11
+ * Carries Headroom's documented fixes:
12
+ * - the error set includes abort/timeout/denied/rejected (the Python
13
+ * regex omitted them while the keyword list had them);
14
+ * - `token` is NOT in the security set (false-positives on every LLM
15
+ * token count in agent logs).
16
+ */
17
+ /** Error/failure keywords used for line scoring and JSON item preservation. */
18
+ export declare const ERROR_KEYWORDS: readonly string[];
19
+ /**
20
+ * The 12-keyword preservation set for JSON items (smart_crusher's
21
+ * fallback signal — intentionally broad; over-preserving beats dropping
22
+ * a real error). Differs from ERROR_KEYWORDS by omitting bare 'fail'
23
+ * (too noisy inside serialized JSON, where 'failed'/'failure' cover it).
24
+ */
25
+ export declare const JSON_ERROR_KEYWORDS: readonly string[];
26
+ export declare const WARNING_KEYWORDS: readonly string[];
27
+ export declare const IMPORTANCE_KEYWORDS: readonly string[];
28
+ /**
29
+ * Case-insensitive whole-word containment check ("errorless" does not
30
+ * match "error"; "ERROR:" does).
31
+ */
32
+ export declare function containsKeyword(line: string, keyword: string): boolean;
33
+ export declare function containsAnyKeyword(line: string, keywords: readonly string[]): boolean;
34
+ export type ImportanceCategory = 'error' | 'warning' | 'importance';
35
+ /**
36
+ * Classify a line's importance category for search-match scoring.
37
+ * Error outranks warning outranks importance (matches Headroom's
38
+ * priority-pattern ordering: 0.5 / 0.4 / 0.3 boosts).
39
+ */
40
+ export declare function classifyImportance(line: string): ImportanceCategory | null;
@@ -0,0 +1,110 @@
1
+ "use strict";
2
+ /**
3
+ * MIRRORED FILE — canonical source: packages/core/src/crush/crush-keywords.ts.
4
+ * Byte-identical copy lives at packages/cli/src/crush/crush-keywords.ts (the CLI is a
5
+ * zero-dep artifact and cannot import @greprag/core). KEEP IN SYNC —
6
+ * the sync guard in tests/test-crush.cjs fails the build on drift.
7
+ *
8
+ * Keyword registries + word-boundary classification shared by the crush
9
+ * compressors. Port of Headroom's signals/keyword_detector.rs +
10
+ * smart_crusher/error_keywords.rs.
11
+ *
12
+ * Carries Headroom's documented fixes:
13
+ * - the error set includes abort/timeout/denied/rejected (the Python
14
+ * regex omitted them while the keyword list had them);
15
+ * - `token` is NOT in the security set (false-positives on every LLM
16
+ * token count in agent logs).
17
+ */
18
+ Object.defineProperty(exports, "__esModule", { value: true });
19
+ exports.IMPORTANCE_KEYWORDS = exports.WARNING_KEYWORDS = exports.JSON_ERROR_KEYWORDS = exports.ERROR_KEYWORDS = void 0;
20
+ exports.containsKeyword = containsKeyword;
21
+ exports.containsAnyKeyword = containsAnyKeyword;
22
+ exports.classifyImportance = classifyImportance;
23
+ /** Error/failure keywords used for line scoring and JSON item preservation. */
24
+ exports.ERROR_KEYWORDS = [
25
+ 'error',
26
+ 'exception',
27
+ 'fail',
28
+ 'failed',
29
+ 'failure',
30
+ 'fatal',
31
+ 'critical',
32
+ 'crash',
33
+ 'panic',
34
+ 'abort',
35
+ 'timeout',
36
+ 'denied',
37
+ 'rejected',
38
+ ];
39
+ /**
40
+ * The 12-keyword preservation set for JSON items (smart_crusher's
41
+ * fallback signal — intentionally broad; over-preserving beats dropping
42
+ * a real error). Differs from ERROR_KEYWORDS by omitting bare 'fail'
43
+ * (too noisy inside serialized JSON, where 'failed'/'failure' cover it).
44
+ */
45
+ exports.JSON_ERROR_KEYWORDS = [
46
+ 'error',
47
+ 'exception',
48
+ 'failed',
49
+ 'failure',
50
+ 'critical',
51
+ 'fatal',
52
+ 'crash',
53
+ 'panic',
54
+ 'abort',
55
+ 'timeout',
56
+ 'denied',
57
+ 'rejected',
58
+ ];
59
+ exports.WARNING_KEYWORDS = ['warn', 'warning'];
60
+ exports.IMPORTANCE_KEYWORDS = [
61
+ 'important',
62
+ 'note',
63
+ 'todo',
64
+ 'fixme',
65
+ 'hack',
66
+ 'xxx',
67
+ 'bug',
68
+ 'fix',
69
+ ];
70
+ function isWordChar(ch) {
71
+ return /[A-Za-z0-9_]/.test(ch);
72
+ }
73
+ /**
74
+ * Case-insensitive whole-word containment check ("errorless" does not
75
+ * match "error"; "ERROR:" does).
76
+ */
77
+ function containsKeyword(line, keyword) {
78
+ const haystack = line.toLowerCase();
79
+ const needle = keyword.toLowerCase();
80
+ let from = 0;
81
+ for (;;) {
82
+ const idx = haystack.indexOf(needle, from);
83
+ if (idx === -1)
84
+ return false;
85
+ const leftOk = idx === 0 || !isWordChar(haystack[idx - 1]);
86
+ const right = idx + needle.length;
87
+ const rightOk = right === haystack.length || !isWordChar(haystack[right]);
88
+ if (leftOk && rightOk)
89
+ return true;
90
+ from = idx + 1;
91
+ }
92
+ }
93
+ function containsAnyKeyword(line, keywords) {
94
+ return keywords.some((kw) => containsKeyword(line, kw));
95
+ }
96
+ /**
97
+ * Classify a line's importance category for search-match scoring.
98
+ * Error outranks warning outranks importance (matches Headroom's
99
+ * priority-pattern ordering: 0.5 / 0.4 / 0.3 boosts).
100
+ */
101
+ function classifyImportance(line) {
102
+ if (containsAnyKeyword(line, exports.ERROR_KEYWORDS))
103
+ return 'error';
104
+ if (containsAnyKeyword(line, exports.WARNING_KEYWORDS))
105
+ return 'warning';
106
+ if (containsAnyKeyword(line, exports.IMPORTANCE_KEYWORDS))
107
+ return 'importance';
108
+ return null;
109
+ }
110
+ //# sourceMappingURL=crush-keywords.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"crush-keywords.js","sourceRoot":"","sources":["../../src/crush/crush-keywords.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;GAeG;;;AA6DH,0CAaC;AAED,gDAEC;AASD,gDAKC;AA1FD,+EAA+E;AAClE,QAAA,cAAc,GAAsB;IAC/C,OAAO;IACP,WAAW;IACX,MAAM;IACN,QAAQ;IACR,SAAS;IACT,OAAO;IACP,UAAU;IACV,OAAO;IACP,OAAO;IACP,OAAO;IACP,SAAS;IACT,QAAQ;IACR,UAAU;CACX,CAAC;AAEF;;;;;GAKG;AACU,QAAA,mBAAmB,GAAsB;IACpD,OAAO;IACP,WAAW;IACX,QAAQ;IACR,SAAS;IACT,UAAU;IACV,OAAO;IACP,OAAO;IACP,OAAO;IACP,OAAO;IACP,SAAS;IACT,QAAQ;IACR,UAAU;CACX,CAAC;AAEW,QAAA,gBAAgB,GAAsB,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;AAE1D,QAAA,mBAAmB,GAAsB;IACpD,WAAW;IACX,MAAM;IACN,MAAM;IACN,OAAO;IACP,MAAM;IACN,KAAK;IACL,KAAK;IACL,KAAK;CACN,CAAC;AAEF,SAAS,UAAU,CAAC,EAAU;IAC5B,OAAO,cAAc,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;AACjC,CAAC;AAED;;;GAGG;AACH,SAAgB,eAAe,CAAC,IAAY,EAAE,OAAe;IAC3D,MAAM,QAAQ,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC;IACpC,MAAM,MAAM,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC;IACrC,IAAI,IAAI,GAAG,CAAC,CAAC;IACb,SAAS,CAAC;QACR,MAAM,GAAG,GAAG,QAAQ,CAAC,OAAO,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;QAC3C,IAAI,GAAG,KAAK,CAAC,CAAC;YAAE,OAAO,KAAK,CAAC;QAC7B,MAAM,MAAM,GAAG,GAAG,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC;QAC3D,MAAM,KAAK,GAAG,GAAG,GAAG,MAAM,CAAC,MAAM,CAAC;QAClC,MAAM,OAAO,GAAG,KAAK,KAAK,QAAQ,CAAC,MAAM,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC;QAC1E,IAAI,MAAM,IAAI,OAAO;YAAE,OAAO,IAAI,CAAC;QACnC,IAAI,GAAG,GAAG,GAAG,CAAC,CAAC;IACjB,CAAC;AACH,CAAC;AAED,SAAgB,kBAAkB,CAAC,IAAY,EAAE,QAA2B;IAC1E,OAAO,QAAQ,CAAC,IAAI,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,eAAe,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,CAAC;AAC1D,CAAC;AAID;;;;GAIG;AACH,SAAgB,kBAAkB,CAAC,IAAY;IAC7C,IAAI,kBAAkB,CAAC,IAAI,EAAE,sBAAc,CAAC;QAAE,OAAO,OAAO,CAAC;IAC7D,IAAI,kBAAkB,CAAC,IAAI,EAAE,wBAAgB,CAAC;QAAE,OAAO,SAAS,CAAC;IACjE,IAAI,kBAAkB,CAAC,IAAI,EAAE,2BAAmB,CAAC;QAAE,OAAO,YAAY,CAAC;IACvE,OAAO,IAAI,CAAC;AACd,CAAC"}
@@ -0,0 +1,38 @@
1
+ /**
2
+ * MIRRORED FILE — canonical source: packages/core/src/crush/crush-types.ts.
3
+ * Byte-identical copy lives at packages/cli/src/crush/crush-types.ts (the CLI is a
4
+ * zero-dep artifact and cannot import @greprag/core). KEEP IN SYNC —
5
+ * the sync guard in tests/test-crush.cjs fails the build on drift.
6
+ *
7
+ * Shared types for the crush engine — pure tool-output compressors
8
+ * (TypeScript ports of Headroom's search/log/smart-crusher transforms).
9
+ *
10
+ * Every compressor is a pure function: string in → { output, stats } out.
11
+ * No I/O, no deps. CCR storage and CLI plumbing live in packages/cli.
12
+ */
13
+ export type CrushSourceType = 'search' | 'log' | 'json';
14
+ export interface CrushStats {
15
+ /** Source type the compressor handled. */
16
+ sourceType: CrushSourceType;
17
+ /** Input size in characters. */
18
+ originalChars: number;
19
+ /** Output size in characters. */
20
+ compressedChars: number;
21
+ /** compressedChars / originalChars (1.0 = no compression). */
22
+ compressionRatio: number;
23
+ /** Units the compressor reasons in (matches/lines/items) before selection. */
24
+ originalUnits: number;
25
+ /** Units surviving selection. */
26
+ keptUnits: number;
27
+ /** True when the compressor passed input through unchanged. */
28
+ passthrough: boolean;
29
+ /** Why passthrough happened (when it did). */
30
+ passthroughReason?: string;
31
+ }
32
+ export interface CrushResult {
33
+ output: string;
34
+ stats: CrushStats;
35
+ }
36
+ /** Rough token estimate shared by validate-or-revert checks: 1 token ≈ 4 chars. */
37
+ export declare function estimateTokens(text: string): number;
38
+ export declare function makePassthrough(content: string, sourceType: CrushSourceType, reason: string, units?: number): CrushResult;
@@ -0,0 +1,36 @@
1
+ "use strict";
2
+ /**
3
+ * MIRRORED FILE — canonical source: packages/core/src/crush/crush-types.ts.
4
+ * Byte-identical copy lives at packages/cli/src/crush/crush-types.ts (the CLI is a
5
+ * zero-dep artifact and cannot import @greprag/core). KEEP IN SYNC —
6
+ * the sync guard in tests/test-crush.cjs fails the build on drift.
7
+ *
8
+ * Shared types for the crush engine — pure tool-output compressors
9
+ * (TypeScript ports of Headroom's search/log/smart-crusher transforms).
10
+ *
11
+ * Every compressor is a pure function: string in → { output, stats } out.
12
+ * No I/O, no deps. CCR storage and CLI plumbing live in packages/cli.
13
+ */
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ exports.estimateTokens = estimateTokens;
16
+ exports.makePassthrough = makePassthrough;
17
+ /** Rough token estimate shared by validate-or-revert checks: 1 token ≈ 4 chars. */
18
+ function estimateTokens(text) {
19
+ return Math.ceil(text.length / 4);
20
+ }
21
+ function makePassthrough(content, sourceType, reason, units = 0) {
22
+ return {
23
+ output: content,
24
+ stats: {
25
+ sourceType,
26
+ originalChars: content.length,
27
+ compressedChars: content.length,
28
+ compressionRatio: 1.0,
29
+ originalUnits: units,
30
+ keptUnits: units,
31
+ passthrough: true,
32
+ passthroughReason: reason,
33
+ },
34
+ };
35
+ }
36
+ //# sourceMappingURL=crush-types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"crush-types.js","sourceRoot":"","sources":["../../src/crush/crush-types.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;GAWG;;AA6BH,wCAEC;AAED,0CAmBC;AAxBD,mFAAmF;AACnF,SAAgB,cAAc,CAAC,IAAY;IACzC,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;AACpC,CAAC;AAED,SAAgB,eAAe,CAC7B,OAAe,EACf,UAA2B,EAC3B,MAAc,EACd,KAAK,GAAG,CAAC;IAET,OAAO;QACL,MAAM,EAAE,OAAO;QACf,KAAK,EAAE;YACL,UAAU;YACV,aAAa,EAAE,OAAO,CAAC,MAAM;YAC7B,eAAe,EAAE,OAAO,CAAC,MAAM;YAC/B,gBAAgB,EAAE,GAAG;YACrB,aAAa,EAAE,KAAK;YACpB,SAAS,EAAE,KAAK;YAChB,WAAW,EAAE,IAAI;YACjB,iBAAiB,EAAE,MAAM;SAC1B;KACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,16 @@
1
+ /**
2
+ * MIRRORED FILE — canonical source: packages/core/src/crush/index.ts.
3
+ * Byte-identical copy lives at packages/cli/src/crush/index.ts (the CLI is a
4
+ * zero-dep artifact and cannot import @greprag/core). KEEP IN SYNC —
5
+ * the sync guard in tests/test-crush.cjs fails the build on drift.
6
+ *
7
+ * Crush engine — pure tool-output compressors (Headroom ports).
8
+ * String in -> { output, stats } out. Zero deps, no I/O.
9
+ */
10
+ export { CrushResult, CrushStats, CrushSourceType, estimateTokens, makePassthrough } from './crush-types';
11
+ export { crushSearch, parseMatchLine, DEFAULT_SEARCH_CONFIG, SearchCompressorConfig } from './search-compressor';
12
+ export { crushLog, detectFormat, classifyLevel, isSummaryLine, parseLogLines, normalizeForDedupe, DEFAULT_LOG_CONFIG, LogCompressorConfig, LogFormat, LogLevel, LogLine, } from './log-compressor';
13
+ export { crushJson, computeKSplit, DEFAULT_JSON_CONFIG, JsonCrusherConfig } from './json-crusher';
14
+ export { classifyArray, detectErrorItems, detectRareStatusValues, detectSequentialPattern, detectStructuralOutliers, ArrayType, JsonValue, } from './json-detectors';
15
+ export { computeOptimalK, computeUniqueBigramCurve, findKnee } from './adaptive-sizer';
16
+ export { ERROR_KEYWORDS, JSON_ERROR_KEYWORDS, containsKeyword, containsAnyKeyword, classifyImportance, } from './crush-keywords';
@@ -0,0 +1,48 @@
1
+ "use strict";
2
+ /**
3
+ * MIRRORED FILE — canonical source: packages/core/src/crush/index.ts.
4
+ * Byte-identical copy lives at packages/cli/src/crush/index.ts (the CLI is a
5
+ * zero-dep artifact and cannot import @greprag/core). KEEP IN SYNC —
6
+ * the sync guard in tests/test-crush.cjs fails the build on drift.
7
+ *
8
+ * Crush engine — pure tool-output compressors (Headroom ports).
9
+ * String in -> { output, stats } out. Zero deps, no I/O.
10
+ */
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.classifyImportance = exports.containsAnyKeyword = exports.containsKeyword = exports.JSON_ERROR_KEYWORDS = exports.ERROR_KEYWORDS = exports.findKnee = exports.computeUniqueBigramCurve = exports.computeOptimalK = exports.detectStructuralOutliers = exports.detectSequentialPattern = exports.detectRareStatusValues = exports.detectErrorItems = exports.classifyArray = exports.DEFAULT_JSON_CONFIG = exports.computeKSplit = exports.crushJson = exports.DEFAULT_LOG_CONFIG = exports.normalizeForDedupe = exports.parseLogLines = exports.isSummaryLine = exports.classifyLevel = exports.detectFormat = exports.crushLog = exports.DEFAULT_SEARCH_CONFIG = exports.parseMatchLine = exports.crushSearch = exports.makePassthrough = exports.estimateTokens = void 0;
13
+ var crush_types_1 = require("./crush-types");
14
+ Object.defineProperty(exports, "estimateTokens", { enumerable: true, get: function () { return crush_types_1.estimateTokens; } });
15
+ Object.defineProperty(exports, "makePassthrough", { enumerable: true, get: function () { return crush_types_1.makePassthrough; } });
16
+ var search_compressor_1 = require("./search-compressor");
17
+ Object.defineProperty(exports, "crushSearch", { enumerable: true, get: function () { return search_compressor_1.crushSearch; } });
18
+ Object.defineProperty(exports, "parseMatchLine", { enumerable: true, get: function () { return search_compressor_1.parseMatchLine; } });
19
+ Object.defineProperty(exports, "DEFAULT_SEARCH_CONFIG", { enumerable: true, get: function () { return search_compressor_1.DEFAULT_SEARCH_CONFIG; } });
20
+ var log_compressor_1 = require("./log-compressor");
21
+ Object.defineProperty(exports, "crushLog", { enumerable: true, get: function () { return log_compressor_1.crushLog; } });
22
+ Object.defineProperty(exports, "detectFormat", { enumerable: true, get: function () { return log_compressor_1.detectFormat; } });
23
+ Object.defineProperty(exports, "classifyLevel", { enumerable: true, get: function () { return log_compressor_1.classifyLevel; } });
24
+ Object.defineProperty(exports, "isSummaryLine", { enumerable: true, get: function () { return log_compressor_1.isSummaryLine; } });
25
+ Object.defineProperty(exports, "parseLogLines", { enumerable: true, get: function () { return log_compressor_1.parseLogLines; } });
26
+ Object.defineProperty(exports, "normalizeForDedupe", { enumerable: true, get: function () { return log_compressor_1.normalizeForDedupe; } });
27
+ Object.defineProperty(exports, "DEFAULT_LOG_CONFIG", { enumerable: true, get: function () { return log_compressor_1.DEFAULT_LOG_CONFIG; } });
28
+ var json_crusher_1 = require("./json-crusher");
29
+ Object.defineProperty(exports, "crushJson", { enumerable: true, get: function () { return json_crusher_1.crushJson; } });
30
+ Object.defineProperty(exports, "computeKSplit", { enumerable: true, get: function () { return json_crusher_1.computeKSplit; } });
31
+ Object.defineProperty(exports, "DEFAULT_JSON_CONFIG", { enumerable: true, get: function () { return json_crusher_1.DEFAULT_JSON_CONFIG; } });
32
+ var json_detectors_1 = require("./json-detectors");
33
+ Object.defineProperty(exports, "classifyArray", { enumerable: true, get: function () { return json_detectors_1.classifyArray; } });
34
+ Object.defineProperty(exports, "detectErrorItems", { enumerable: true, get: function () { return json_detectors_1.detectErrorItems; } });
35
+ Object.defineProperty(exports, "detectRareStatusValues", { enumerable: true, get: function () { return json_detectors_1.detectRareStatusValues; } });
36
+ Object.defineProperty(exports, "detectSequentialPattern", { enumerable: true, get: function () { return json_detectors_1.detectSequentialPattern; } });
37
+ Object.defineProperty(exports, "detectStructuralOutliers", { enumerable: true, get: function () { return json_detectors_1.detectStructuralOutliers; } });
38
+ var adaptive_sizer_1 = require("./adaptive-sizer");
39
+ Object.defineProperty(exports, "computeOptimalK", { enumerable: true, get: function () { return adaptive_sizer_1.computeOptimalK; } });
40
+ Object.defineProperty(exports, "computeUniqueBigramCurve", { enumerable: true, get: function () { return adaptive_sizer_1.computeUniqueBigramCurve; } });
41
+ Object.defineProperty(exports, "findKnee", { enumerable: true, get: function () { return adaptive_sizer_1.findKnee; } });
42
+ var crush_keywords_1 = require("./crush-keywords");
43
+ Object.defineProperty(exports, "ERROR_KEYWORDS", { enumerable: true, get: function () { return crush_keywords_1.ERROR_KEYWORDS; } });
44
+ Object.defineProperty(exports, "JSON_ERROR_KEYWORDS", { enumerable: true, get: function () { return crush_keywords_1.JSON_ERROR_KEYWORDS; } });
45
+ Object.defineProperty(exports, "containsKeyword", { enumerable: true, get: function () { return crush_keywords_1.containsKeyword; } });
46
+ Object.defineProperty(exports, "containsAnyKeyword", { enumerable: true, get: function () { return crush_keywords_1.containsAnyKeyword; } });
47
+ Object.defineProperty(exports, "classifyImportance", { enumerable: true, get: function () { return crush_keywords_1.classifyImportance; } });
48
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/crush/index.ts"],"names":[],"mappings":";AAAA;;;;;;;;GAQG;;;AAEH,6CAA0G;AAAvD,6GAAA,cAAc,OAAA;AAAE,8GAAA,eAAe,OAAA;AAClF,yDAAiH;AAAxG,gHAAA,WAAW,OAAA;AAAE,mHAAA,cAAc,OAAA;AAAE,0HAAA,qBAAqB,OAAA;AAC3D,mDAY0B;AAXxB,0GAAA,QAAQ,OAAA;AACR,8GAAA,YAAY,OAAA;AACZ,+GAAA,aAAa,OAAA;AACb,+GAAA,aAAa,OAAA;AACb,+GAAA,aAAa,OAAA;AACb,oHAAA,kBAAkB,OAAA;AAClB,oHAAA,kBAAkB,OAAA;AAMpB,+CAAkG;AAAzF,yGAAA,SAAS,OAAA;AAAE,6GAAA,aAAa,OAAA;AAAE,mHAAA,mBAAmB,OAAA;AACtD,mDAQ0B;AAPxB,+GAAA,aAAa,OAAA;AACb,kHAAA,gBAAgB,OAAA;AAChB,wHAAA,sBAAsB,OAAA;AACtB,yHAAA,uBAAuB,OAAA;AACvB,0HAAA,wBAAwB,OAAA;AAI1B,mDAAuF;AAA9E,iHAAA,eAAe,OAAA;AAAE,0HAAA,wBAAwB,OAAA;AAAE,0GAAA,QAAQ,OAAA;AAC5D,mDAM0B;AALxB,gHAAA,cAAc,OAAA;AACd,qHAAA,mBAAmB,OAAA;AACnB,iHAAA,eAAe,OAAA;AACf,oHAAA,kBAAkB,OAAA;AAClB,oHAAA,kBAAkB,OAAA"}
@@ -0,0 +1,38 @@
1
+ /**
2
+ * MIRRORED FILE — canonical source: packages/core/src/crush/json-crusher.ts.
3
+ * Byte-identical copy lives at packages/cli/src/crush/json-crusher.ts (the CLI is a
4
+ * zero-dep artifact and cannot import @greprag/core). KEEP IN SYNC —
5
+ * the sync guard in tests/test-crush.cjs fails the build on drift.
6
+ *
7
+ * JSON-array crusher — TypeScript port of the SIMPLE core of Headroom's
8
+ * smart_crusher: statistical sampling + error preservation. Classifies
9
+ * each array, keeps errors / structural outliers / rare statuses /
10
+ * first+last blocks, and replaces the dropped bulk with a count marker
11
+ * string (`"[... N items omitted ...]"`).
12
+ *
13
+ * The full Headroom orchestration (TOIN semantics, relevance planning,
14
+ * lossless compaction, change points) is intentionally not ported.
15
+ */
16
+ import { CrushResult } from './crush-types';
17
+ export interface JsonCrusherConfig {
18
+ /** Arrays smaller than this are left alone. */
19
+ minItemsToAnalyze: number;
20
+ /** Target maximum items kept per crushed array. */
21
+ maxItemsAfterCrush: number;
22
+ /** Fraction of the budget pinned to the array head. */
23
+ firstFraction: number;
24
+ /** Fraction of the budget pinned to the array tail. */
25
+ lastFraction: number;
26
+ bias: number;
27
+ }
28
+ export declare const DEFAULT_JSON_CONFIG: JsonCrusherConfig;
29
+ /** First/last slot split for a keep-budget. Never exceeds kTotal. */
30
+ export declare function computeKSplit(kTotal: number, firstFraction: number, lastFraction: number): {
31
+ first: number;
32
+ last: number;
33
+ };
34
+ /**
35
+ * Compress JSON containing large arrays. Non-JSON input, or JSON with
36
+ * no qualifying arrays, passes through unchanged.
37
+ */
38
+ export declare function crushJson(content: string, config?: Partial<JsonCrusherConfig>): CrushResult;