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.
- package/dist/archive/glyph-font.d.ts +22 -0
- package/dist/archive/glyph-font.js +72 -0
- package/dist/archive/glyph-font.js.map +1 -0
- package/dist/archive/page-renderer.d.ts +67 -0
- package/dist/archive/page-renderer.js +197 -0
- package/dist/archive/page-renderer.js.map +1 -0
- package/dist/archive/png-codec.d.ts +21 -0
- package/dist/archive/png-codec.js +197 -0
- package/dist/archive/png-codec.js.map +1 -0
- package/dist/archive/transcript-extract.d.ts +39 -0
- package/dist/archive/transcript-extract.js +187 -0
- package/dist/archive/transcript-extract.js.map +1 -0
- package/dist/ccr-store.d.ts +49 -0
- package/dist/ccr-store.js +171 -0
- package/dist/ccr-store.js.map +1 -0
- package/dist/commands/archive.d.ts +81 -0
- package/dist/commands/archive.js +358 -0
- package/dist/commands/archive.js.map +1 -0
- package/dist/commands/context-governor.d.ts +82 -0
- package/dist/commands/context-governor.js +344 -0
- package/dist/commands/context-governor.js.map +1 -0
- package/dist/commands/crush-stats.d.ts +36 -0
- package/dist/commands/crush-stats.js +142 -0
- package/dist/commands/crush-stats.js.map +1 -0
- package/dist/commands/crush.d.ts +24 -0
- package/dist/commands/crush.js +183 -0
- package/dist/commands/crush.js.map +1 -0
- package/dist/commands/email.js +158 -9
- package/dist/commands/email.js.map +1 -1
- package/dist/commands/inbox-watch-supervisor.js +8 -65
- package/dist/commands/inbox-watch-supervisor.js.map +1 -1
- package/dist/commands/init.js +93 -0
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/pipe-wrap.d.ts +75 -0
- package/dist/commands/pipe-wrap.js +255 -0
- package/dist/commands/pipe-wrap.js.map +1 -0
- package/dist/commands/watcher-registry.d.ts +1 -8
- package/dist/commands/watcher-registry.js +10 -47
- package/dist/commands/watcher-registry.js.map +1 -1
- package/dist/crush/adaptive-sizer.d.ts +40 -0
- package/dist/crush/adaptive-sizer.js +156 -0
- package/dist/crush/adaptive-sizer.js.map +1 -0
- package/dist/crush/crush-keywords.d.ts +40 -0
- package/dist/crush/crush-keywords.js +110 -0
- package/dist/crush/crush-keywords.js.map +1 -0
- package/dist/crush/crush-types.d.ts +38 -0
- package/dist/crush/crush-types.js +36 -0
- package/dist/crush/crush-types.js.map +1 -0
- package/dist/crush/index.d.ts +16 -0
- package/dist/crush/index.js +48 -0
- package/dist/crush/index.js.map +1 -0
- package/dist/crush/json-crusher.d.ts +38 -0
- package/dist/crush/json-crusher.js +250 -0
- package/dist/crush/json-crusher.js.map +1 -0
- package/dist/crush/json-detectors.d.ts +48 -0
- package/dist/crush/json-detectors.js +211 -0
- package/dist/crush/json-detectors.js.map +1 -0
- package/dist/crush/log-compressor.d.ts +60 -0
- package/dist/crush/log-compressor.js +394 -0
- package/dist/crush/log-compressor.js.map +1 -0
- package/dist/crush/search-compressor.d.ts +60 -0
- package/dist/crush/search-compressor.js +210 -0
- package/dist/crush/search-compressor.js.map +1 -0
- package/dist/email-pull.d.ts +25 -3
- package/dist/email-pull.js +25 -5
- package/dist/email-pull.js.map +1 -1
- package/dist/email-send.d.ts +4 -0
- package/dist/email-send.js +2 -0
- package/dist/email-send.js.map +1 -1
- package/dist/hook.js +49 -1
- package/dist/hook.js.map +1 -1
- package/dist/index.js +487 -449
- package/dist/index.js.map +1 -1
- package/dist/session-id.js +7 -12
- package/dist/session-id.js.map +1 -1
- package/package.json +2 -2
- package/skill/greprag/SKILL.md +2 -2
- package/skill/greprag/docs/email.md +28 -4
- package/skill/mechanic/SKILL.md +1 -1
- package/skill/templates/chip-spawn.md +4 -2
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/** 8x8 monochrome bitmap font for the PNG archive renderer — printable
|
|
2
|
+
* ASCII 32..126 (95 glyphs), one row byte per pixel row, LSB = leftmost.
|
|
3
|
+
*
|
|
4
|
+
* Data: font8x8_basic by Daniel Hepper (public domain), itself based on
|
|
5
|
+
* Marcel Sondaar / IBM public-domain VGA fonts.
|
|
6
|
+
* https://github.com/dhepper/font8x8 — embedded as hex so the renderer
|
|
7
|
+
* has ZERO runtime deps (Node's built-in zlib does PNG compression).
|
|
8
|
+
*
|
|
9
|
+
* All 95 glyph bitmaps are pairwise distinct (verified at generation,
|
|
10
|
+
* re-verified by tests/test-governed-compact.cjs), so pixel-level decode
|
|
11
|
+
* back to text is unambiguous — the basis of the round-trip self-test.
|
|
12
|
+
*
|
|
13
|
+
* GENERATED from font8x8_basic.h — regenerate rather than hand-edit.
|
|
14
|
+
*/
|
|
15
|
+
export declare const GLYPH_W = 8;
|
|
16
|
+
export declare const GLYPH_H = 8;
|
|
17
|
+
export declare const FIRST_CODE = 32;
|
|
18
|
+
export declare const LAST_CODE = 126;
|
|
19
|
+
/** Glyph rows (8 bytes) for a char code; null when outside 32..126. */
|
|
20
|
+
export declare function glyphRows(code: number): number[] | null;
|
|
21
|
+
export declare function codeForSignature(sigHex: string): number | null;
|
|
22
|
+
export declare function signatureForRows(bytes: number[]): string;
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// adr: adr/governed-compact.md
|
|
3
|
+
/** 8x8 monochrome bitmap font for the PNG archive renderer — printable
|
|
4
|
+
* ASCII 32..126 (95 glyphs), one row byte per pixel row, LSB = leftmost.
|
|
5
|
+
*
|
|
6
|
+
* Data: font8x8_basic by Daniel Hepper (public domain), itself based on
|
|
7
|
+
* Marcel Sondaar / IBM public-domain VGA fonts.
|
|
8
|
+
* https://github.com/dhepper/font8x8 — embedded as hex so the renderer
|
|
9
|
+
* has ZERO runtime deps (Node's built-in zlib does PNG compression).
|
|
10
|
+
*
|
|
11
|
+
* All 95 glyph bitmaps are pairwise distinct (verified at generation,
|
|
12
|
+
* re-verified by tests/test-governed-compact.cjs), so pixel-level decode
|
|
13
|
+
* back to text is unambiguous — the basis of the round-trip self-test.
|
|
14
|
+
*
|
|
15
|
+
* GENERATED from font8x8_basic.h — regenerate rather than hand-edit.
|
|
16
|
+
*/
|
|
17
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
18
|
+
exports.LAST_CODE = exports.FIRST_CODE = exports.GLYPH_H = exports.GLYPH_W = void 0;
|
|
19
|
+
exports.glyphRows = glyphRows;
|
|
20
|
+
exports.codeForSignature = codeForSignature;
|
|
21
|
+
exports.signatureForRows = signatureForRows;
|
|
22
|
+
exports.GLYPH_W = 8;
|
|
23
|
+
exports.GLYPH_H = 8;
|
|
24
|
+
exports.FIRST_CODE = 32;
|
|
25
|
+
exports.LAST_CODE = 126;
|
|
26
|
+
/** 95 glyphs, index = charCode - 32. 16 hex chars = 8 row bytes, top row
|
|
27
|
+
* first; in each byte bit 0 (LSB) is the LEFTMOST pixel. */
|
|
28
|
+
const FONT_HEX = [
|
|
29
|
+
'0000000000000000', '183c3c1818001800', '3636000000000000', '36367f367f363600', '0c3e031e301f0c00',
|
|
30
|
+
'006333180c666300', '1c361c6e3b336e00', '0606030000000000', '180c0606060c1800', '060c1818180c0600',
|
|
31
|
+
'00663cff3c660000', '000c0c3f0c0c0000', '00000000000c0c06', '0000003f00000000', '00000000000c0c00',
|
|
32
|
+
'6030180c06030100', '3e63737b6f673e00', '0c0e0c0c0c0c3f00', '1e33301c06333f00', '1e33301c30331e00',
|
|
33
|
+
'383c36337f307800', '3f031f3030331e00', '1c06031f33331e00', '3f3330180c0c0c00', '1e33331e33331e00',
|
|
34
|
+
'1e33333e30180e00', '000c0c00000c0c00', '000c0c00000c0c06', '180c0603060c1800', '00003f00003f0000',
|
|
35
|
+
'060c1830180c0600', '1e3330180c000c00', '3e637b7b7b031e00', '0c1e33333f333300', '3f66663e66663f00',
|
|
36
|
+
'3c66030303663c00', '1f36666666361f00', '7f46161e16467f00', '7f46161e16060f00', '3c66030373667c00',
|
|
37
|
+
'3333333f33333300', '1e0c0c0c0c0c1e00', '7830303033331e00', '6766361e36666700', '0f06060646667f00',
|
|
38
|
+
'63777f7f6b636300', '63676f7b73636300', '1c36636363361c00', '3f66663e06060f00', '1e3333333b1e3800',
|
|
39
|
+
'3f66663e36666700', '1e33070e38331e00', '3f2d0c0c0c0c1e00', '3333333333333f00', '33333333331e0c00',
|
|
40
|
+
'6363636b7f776300', '6363361c1c366300', '3333331e0c0c1e00', '7f6331184c667f00', '1e06060606061e00',
|
|
41
|
+
'03060c1830604000', '1e18181818181e00', '081c366300000000', '00000000000000ff', '0c0c180000000000',
|
|
42
|
+
'00001e303e336e00', '0706063e66663b00', '00001e3303331e00', '3830303e33336e00', '00001e333f031e00',
|
|
43
|
+
'1c36060f06060f00', '00006e33333e301f', '0706366e66666700', '0c000e0c0c0c1e00', '300030303033331e',
|
|
44
|
+
'070666361e366700', '0e0c0c0c0c0c1e00', '0000337f7f6b6300', '00001f3333333300', '00001e3333331e00',
|
|
45
|
+
'00003b66663e060f', '00006e33333e3078', '00003b6e66060f00', '00003e031e301f00', '080c3e0c0c2c1800',
|
|
46
|
+
'0000333333336e00', '00003333331e0c00', '0000636b7f7f3600', '000063361c366300', '00003333333e301f',
|
|
47
|
+
'00003f190c263f00', '380c0c070c0c3800', '1818180018181800', '070c0c380c0c0700', '6e3b000000000000',
|
|
48
|
+
];
|
|
49
|
+
/** Glyph rows (8 bytes) for a char code; null when outside 32..126. */
|
|
50
|
+
function glyphRows(code) {
|
|
51
|
+
if (code < exports.FIRST_CODE || code > exports.LAST_CODE)
|
|
52
|
+
return null;
|
|
53
|
+
const hex = FONT_HEX[code - exports.FIRST_CODE];
|
|
54
|
+
const out = [];
|
|
55
|
+
for (let i = 0; i < 8; i++)
|
|
56
|
+
out.push(parseInt(hex.slice(i * 2, i * 2 + 2), 16));
|
|
57
|
+
return out;
|
|
58
|
+
}
|
|
59
|
+
/** Reverse map: 16-hex glyph signature -> char code. Built once, lazily. */
|
|
60
|
+
let reverse = null;
|
|
61
|
+
function codeForSignature(sigHex) {
|
|
62
|
+
if (!reverse) {
|
|
63
|
+
reverse = new Map();
|
|
64
|
+
for (let c = exports.FIRST_CODE; c <= exports.LAST_CODE; c++)
|
|
65
|
+
reverse.set(FONT_HEX[c - exports.FIRST_CODE], c);
|
|
66
|
+
}
|
|
67
|
+
return reverse.get(sigHex) ?? null;
|
|
68
|
+
}
|
|
69
|
+
function signatureForRows(bytes) {
|
|
70
|
+
return bytes.map((b) => (b & 0xff).toString(16).padStart(2, '0')).join('');
|
|
71
|
+
}
|
|
72
|
+
//# sourceMappingURL=glyph-font.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"glyph-font.js","sourceRoot":"","sources":["../../src/archive/glyph-font.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/** Page renderer — lays conversation text out on a fixed character grid and
|
|
2
|
+
* rasterizes it with the embedded 8x8 font into 1568x1568 grayscale PNGs
|
|
3
|
+
* (the Snapcompact pattern: text re-encoded as pixels reads back at ~3x
|
|
4
|
+
* the token density via the vision path).
|
|
5
|
+
*
|
|
6
|
+
* Geometry: 8x8 glyphs in 8x10 cells (2px leading for line separation) on
|
|
7
|
+
* a 1568x1568 canvas -> 196 cols x 156 rows = 30,576 chars/page. That is
|
|
8
|
+
* the deliberate middle of the Snapcompact reference range (6x10 ~40K
|
|
9
|
+
* chars max-density vs 8x12 ~25K safe): font8x8 is a battle-tested VGA
|
|
10
|
+
* face, far more legible to a vision model than a hand-authored 6x10.
|
|
11
|
+
*
|
|
12
|
+
* Losslessness: chars outside printable ASCII are escaped to \\uXXXX (or
|
|
13
|
+
* \\u{XXXXXX}) BEFORE layout, so every rendered char has a unique glyph and
|
|
14
|
+
* pixel-level decode (decodePageText) reconstructs the grid exactly. The
|
|
15
|
+
* round-trip self-test renders -> decodes -> compares grid text; it proves
|
|
16
|
+
* the pixels carry the text losslessly. Long lines wrap at the column
|
|
17
|
+
* boundary (wrap vs original-newline is not distinguished — acceptable for
|
|
18
|
+
* a vision reader, noted in the ADR).
|
|
19
|
+
*/
|
|
20
|
+
export declare const PAGE_SIZE = 1568;
|
|
21
|
+
export declare const CELL_W = 8;
|
|
22
|
+
export declare const CELL_H = 10;
|
|
23
|
+
export declare const COLS: number;
|
|
24
|
+
export declare const ROWS: number;
|
|
25
|
+
export declare const CHARS_PER_PAGE: number;
|
|
26
|
+
/** Make text grid-safe and reversible: CRLF -> LF, tab -> \\t escape, any
|
|
27
|
+
* char outside printable ASCII -> \\uXXXX / \\u{XXXXXX}. Output contains
|
|
28
|
+
* only chars 32..126 plus newlines. */
|
|
29
|
+
export declare function sanitizeForGrid(text: string): string;
|
|
30
|
+
/** Sanitize text while re-mapping char-offset marks (turn starts) into the
|
|
31
|
+
* sanitized offset space — escaping expands chars, so raw offsets drift. */
|
|
32
|
+
export declare function sanitizeWithMarks<T extends {
|
|
33
|
+
charStart: number;
|
|
34
|
+
}>(text: string, marks: T[]): {
|
|
35
|
+
sanitized: string;
|
|
36
|
+
marks: T[];
|
|
37
|
+
};
|
|
38
|
+
export interface GridRow {
|
|
39
|
+
/** Exactly COLS chars (space-padded). */
|
|
40
|
+
text: string;
|
|
41
|
+
/** Char offset of this row's first char in the sanitized source text. */
|
|
42
|
+
charStart: number;
|
|
43
|
+
}
|
|
44
|
+
/** Split sanitized text into grid rows: newline-separated lines, each
|
|
45
|
+
* hard-wrapped at COLS. Rows are space-padded to exactly COLS chars. */
|
|
46
|
+
export declare function layoutRows(sanitized: string, cols?: number): GridRow[];
|
|
47
|
+
export interface RenderedPage {
|
|
48
|
+
png: Buffer;
|
|
49
|
+
/** The exact grid text on this page: ROWS lines of COLS chars. */
|
|
50
|
+
gridText: string;
|
|
51
|
+
charStart: number;
|
|
52
|
+
charEnd: number;
|
|
53
|
+
}
|
|
54
|
+
/** Rasterize one page of grid rows (up to ROWS) into a PNG. A full page is
|
|
55
|
+
* 1568x1568; the final partial page is only as tall as its rows, so its
|
|
56
|
+
* grid text and its pixels stay in exact 1:1 correspondence (the round-trip
|
|
57
|
+
* gate compares them) and the file carries no blank padding. */
|
|
58
|
+
export declare function renderPage(pageRows: GridRow[], cols?: number, rows?: number): RenderedPage;
|
|
59
|
+
/** Paginate grid rows into page-sized groups. */
|
|
60
|
+
export declare function paginate(rowsIn: GridRow[], rowsPerPage?: number): GridRow[][];
|
|
61
|
+
/** Read the grid text back out of a rendered page PNG by matching each
|
|
62
|
+
* cell's 8x8 pixel block against the font table. Unknown signatures decode
|
|
63
|
+
* as the Unicode replacement char so a corruption is loud, not silent. */
|
|
64
|
+
export declare function decodePageText(png: Buffer, cols?: number): string;
|
|
65
|
+
/** Render -> decode -> compare. Returns null when lossless, else a
|
|
66
|
+
* description of the first mismatch. */
|
|
67
|
+
export declare function verifyRoundTrip(page: RenderedPage): string | null;
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// adr: adr/governed-compact.md
|
|
3
|
+
/** Page renderer — lays conversation text out on a fixed character grid and
|
|
4
|
+
* rasterizes it with the embedded 8x8 font into 1568x1568 grayscale PNGs
|
|
5
|
+
* (the Snapcompact pattern: text re-encoded as pixels reads back at ~3x
|
|
6
|
+
* the token density via the vision path).
|
|
7
|
+
*
|
|
8
|
+
* Geometry: 8x8 glyphs in 8x10 cells (2px leading for line separation) on
|
|
9
|
+
* a 1568x1568 canvas -> 196 cols x 156 rows = 30,576 chars/page. That is
|
|
10
|
+
* the deliberate middle of the Snapcompact reference range (6x10 ~40K
|
|
11
|
+
* chars max-density vs 8x12 ~25K safe): font8x8 is a battle-tested VGA
|
|
12
|
+
* face, far more legible to a vision model than a hand-authored 6x10.
|
|
13
|
+
*
|
|
14
|
+
* Losslessness: chars outside printable ASCII are escaped to \\uXXXX (or
|
|
15
|
+
* \\u{XXXXXX}) BEFORE layout, so every rendered char has a unique glyph and
|
|
16
|
+
* pixel-level decode (decodePageText) reconstructs the grid exactly. The
|
|
17
|
+
* round-trip self-test renders -> decodes -> compares grid text; it proves
|
|
18
|
+
* the pixels carry the text losslessly. Long lines wrap at the column
|
|
19
|
+
* boundary (wrap vs original-newline is not distinguished — acceptable for
|
|
20
|
+
* a vision reader, noted in the ADR).
|
|
21
|
+
*/
|
|
22
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
23
|
+
exports.CHARS_PER_PAGE = exports.ROWS = exports.COLS = exports.CELL_H = exports.CELL_W = exports.PAGE_SIZE = void 0;
|
|
24
|
+
exports.sanitizeForGrid = sanitizeForGrid;
|
|
25
|
+
exports.sanitizeWithMarks = sanitizeWithMarks;
|
|
26
|
+
exports.layoutRows = layoutRows;
|
|
27
|
+
exports.renderPage = renderPage;
|
|
28
|
+
exports.paginate = paginate;
|
|
29
|
+
exports.decodePageText = decodePageText;
|
|
30
|
+
exports.verifyRoundTrip = verifyRoundTrip;
|
|
31
|
+
const glyph_font_1 = require("./glyph-font");
|
|
32
|
+
const png_codec_1 = require("./png-codec");
|
|
33
|
+
exports.PAGE_SIZE = 1568;
|
|
34
|
+
exports.CELL_W = glyph_font_1.GLYPH_W; // 8
|
|
35
|
+
exports.CELL_H = 10; // 8px glyph + 2px leading
|
|
36
|
+
exports.COLS = Math.floor(exports.PAGE_SIZE / exports.CELL_W); // 196
|
|
37
|
+
exports.ROWS = Math.floor(exports.PAGE_SIZE / exports.CELL_H); // 156
|
|
38
|
+
exports.CHARS_PER_PAGE = exports.COLS * exports.ROWS; // 30,576
|
|
39
|
+
const BG = 255; // white
|
|
40
|
+
const FG = 0; // black
|
|
41
|
+
// ---------- Text sanitation ---------------------------------------------------
|
|
42
|
+
/** Make text grid-safe and reversible: CRLF -> LF, tab -> \\t escape, any
|
|
43
|
+
* char outside printable ASCII -> \\uXXXX / \\u{XXXXXX}. Output contains
|
|
44
|
+
* only chars 32..126 plus newlines. */
|
|
45
|
+
function sanitizeForGrid(text) {
|
|
46
|
+
const out = [];
|
|
47
|
+
for (const ch of text.replace(/\r\n/g, '\n').replace(/\r/g, '\n')) {
|
|
48
|
+
const code = ch.codePointAt(0);
|
|
49
|
+
if (ch === '\n') {
|
|
50
|
+
out.push('\n');
|
|
51
|
+
}
|
|
52
|
+
else if (ch === '\t') {
|
|
53
|
+
out.push('\\t');
|
|
54
|
+
}
|
|
55
|
+
else if (code >= 32 && code <= 126) {
|
|
56
|
+
out.push(ch);
|
|
57
|
+
}
|
|
58
|
+
else if (code <= 0xffff) {
|
|
59
|
+
out.push('\\u' + code.toString(16).padStart(4, '0'));
|
|
60
|
+
}
|
|
61
|
+
else {
|
|
62
|
+
out.push('\\u{' + code.toString(16) + '}');
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
return out.join('');
|
|
66
|
+
}
|
|
67
|
+
/** Sanitize text while re-mapping char-offset marks (turn starts) into the
|
|
68
|
+
* sanitized offset space — escaping expands chars, so raw offsets drift. */
|
|
69
|
+
function sanitizeWithMarks(text, marks) {
|
|
70
|
+
const sortedMarks = [...marks].sort((a, b) => a.charStart - b.charStart);
|
|
71
|
+
const pieces = [];
|
|
72
|
+
const remapped = [];
|
|
73
|
+
let prevRaw = 0;
|
|
74
|
+
let sanitizedLen = 0;
|
|
75
|
+
for (const mark of sortedMarks) {
|
|
76
|
+
const piece = sanitizeForGrid(text.slice(prevRaw, mark.charStart));
|
|
77
|
+
pieces.push(piece);
|
|
78
|
+
sanitizedLen += piece.length;
|
|
79
|
+
remapped.push({ ...mark, charStart: sanitizedLen });
|
|
80
|
+
prevRaw = mark.charStart;
|
|
81
|
+
}
|
|
82
|
+
pieces.push(sanitizeForGrid(text.slice(prevRaw)));
|
|
83
|
+
return { sanitized: pieces.join(''), marks: remapped };
|
|
84
|
+
}
|
|
85
|
+
/** Split sanitized text into grid rows: newline-separated lines, each
|
|
86
|
+
* hard-wrapped at COLS. Rows are space-padded to exactly COLS chars. */
|
|
87
|
+
function layoutRows(sanitized, cols = exports.COLS) {
|
|
88
|
+
const rows = [];
|
|
89
|
+
let offset = 0;
|
|
90
|
+
for (const line of sanitized.split('\n')) {
|
|
91
|
+
if (line.length === 0) {
|
|
92
|
+
rows.push({ text: ' '.repeat(cols), charStart: offset });
|
|
93
|
+
}
|
|
94
|
+
else {
|
|
95
|
+
for (let i = 0; i < line.length; i += cols) {
|
|
96
|
+
const slice = line.slice(i, i + cols);
|
|
97
|
+
rows.push({ text: slice.padEnd(cols, ' '), charStart: offset + i });
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
offset += line.length + 1; // + newline
|
|
101
|
+
}
|
|
102
|
+
return rows;
|
|
103
|
+
}
|
|
104
|
+
/** Rasterize one page of grid rows (up to ROWS) into a PNG. A full page is
|
|
105
|
+
* 1568x1568; the final partial page is only as tall as its rows, so its
|
|
106
|
+
* grid text and its pixels stay in exact 1:1 correspondence (the round-trip
|
|
107
|
+
* gate compares them) and the file carries no blank padding. */
|
|
108
|
+
function renderPage(pageRows, cols = exports.COLS, rows = exports.ROWS) {
|
|
109
|
+
const rowCount = Math.max(1, Math.min(pageRows.length, rows));
|
|
110
|
+
const width = cols * exports.CELL_W;
|
|
111
|
+
const height = rowCount * exports.CELL_H;
|
|
112
|
+
const pixels = Buffer.alloc(width * height, BG);
|
|
113
|
+
for (let r = 0; r < Math.min(pageRows.length, rowCount); r++) {
|
|
114
|
+
const row = pageRows[r];
|
|
115
|
+
for (let c = 0; c < cols; c++) {
|
|
116
|
+
const glyph = (0, glyph_font_1.glyphRows)(row.text.charCodeAt(c));
|
|
117
|
+
if (!glyph)
|
|
118
|
+
continue; // space stays background; out-of-range cannot occur post-sanitize
|
|
119
|
+
const px = c * exports.CELL_W;
|
|
120
|
+
const py = r * exports.CELL_H;
|
|
121
|
+
for (let gy = 0; gy < glyph_font_1.GLYPH_H; gy++) {
|
|
122
|
+
const bits = glyph[gy];
|
|
123
|
+
if (bits === 0)
|
|
124
|
+
continue;
|
|
125
|
+
const base = (py + gy) * width + px;
|
|
126
|
+
for (let gx = 0; gx < glyph_font_1.GLYPH_W; gx++) {
|
|
127
|
+
if (bits & (1 << gx))
|
|
128
|
+
pixels[base + gx] = FG;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
const img = { width, height, pixels };
|
|
134
|
+
const charStart = pageRows.length ? pageRows[0].charStart : 0;
|
|
135
|
+
const last = pageRows[pageRows.length - 1];
|
|
136
|
+
const charEnd = last ? last.charStart + last.text.trimEnd().length : charStart;
|
|
137
|
+
return {
|
|
138
|
+
png: (0, png_codec_1.encodePng)(img),
|
|
139
|
+
gridText: pageRows.map((r) => r.text).join('\n'),
|
|
140
|
+
charStart,
|
|
141
|
+
charEnd,
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
/** Paginate grid rows into page-sized groups. */
|
|
145
|
+
function paginate(rowsIn, rowsPerPage = exports.ROWS) {
|
|
146
|
+
const pages = [];
|
|
147
|
+
for (let i = 0; i < rowsIn.length; i += rowsPerPage) {
|
|
148
|
+
pages.push(rowsIn.slice(i, i + rowsPerPage));
|
|
149
|
+
}
|
|
150
|
+
return pages;
|
|
151
|
+
}
|
|
152
|
+
// ---------- Pixel-level decode (round-trip self-test) ---------------------------
|
|
153
|
+
/** Read the grid text back out of a rendered page PNG by matching each
|
|
154
|
+
* cell's 8x8 pixel block against the font table. Unknown signatures decode
|
|
155
|
+
* as the Unicode replacement char so a corruption is loud, not silent. */
|
|
156
|
+
function decodePageText(png, cols = exports.COLS) {
|
|
157
|
+
const img = (0, png_codec_1.decodePng)(png);
|
|
158
|
+
const rows = Math.floor(img.height / exports.CELL_H);
|
|
159
|
+
const usableCols = Math.min(cols, Math.floor(img.width / exports.CELL_W));
|
|
160
|
+
const lines = [];
|
|
161
|
+
for (let r = 0; r < rows; r++) {
|
|
162
|
+
const chars = [];
|
|
163
|
+
for (let c = 0; c < usableCols; c++) {
|
|
164
|
+
const bytes = [];
|
|
165
|
+
for (let gy = 0; gy < glyph_font_1.GLYPH_H; gy++) {
|
|
166
|
+
let b = 0;
|
|
167
|
+
const base = (r * exports.CELL_H + gy) * img.width + c * exports.CELL_W;
|
|
168
|
+
for (let gx = 0; gx < glyph_font_1.GLYPH_W; gx++) {
|
|
169
|
+
if (img.pixels[base + gx] < 128)
|
|
170
|
+
b |= 1 << gx;
|
|
171
|
+
}
|
|
172
|
+
bytes.push(b);
|
|
173
|
+
}
|
|
174
|
+
const code = (0, glyph_font_1.codeForSignature)((0, glyph_font_1.signatureForRows)(bytes));
|
|
175
|
+
chars.push(code === null ? '�' : String.fromCharCode(code));
|
|
176
|
+
}
|
|
177
|
+
lines.push(chars.join(''));
|
|
178
|
+
}
|
|
179
|
+
return lines.join('\n');
|
|
180
|
+
}
|
|
181
|
+
/** Render -> decode -> compare. Returns null when lossless, else a
|
|
182
|
+
* description of the first mismatch. */
|
|
183
|
+
function verifyRoundTrip(page) {
|
|
184
|
+
const decoded = decodePageText(page.png);
|
|
185
|
+
if (decoded === page.gridText)
|
|
186
|
+
return null;
|
|
187
|
+
const a = page.gridText;
|
|
188
|
+
const b = decoded;
|
|
189
|
+
const n = Math.min(a.length, b.length);
|
|
190
|
+
for (let i = 0; i < n; i++) {
|
|
191
|
+
if (a[i] !== b[i]) {
|
|
192
|
+
return `mismatch at char ${i}: rendered ${JSON.stringify(a[i])} decoded ${JSON.stringify(b[i])}`;
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
return `length mismatch: rendered ${a.length} decoded ${b.length}`;
|
|
196
|
+
}
|
|
197
|
+
//# sourceMappingURL=page-renderer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"page-renderer.js","sourceRoot":"","sources":["../../src/archive/page-renderer.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/** Minimal PNG encoder/decoder for the archive renderer — 8-bit grayscale
|
|
2
|
+
* only, zero dependencies (Node's built-in zlib supplies DEFLATE; PNG's
|
|
3
|
+
* IDAT is a zlib stream).
|
|
4
|
+
*
|
|
5
|
+
* Encode writes filter type 0 (None) on every scanline — glyph bitmaps
|
|
6
|
+
* deflate well without prediction and it keeps decode trivial. Decode
|
|
7
|
+
* handles all five standard filters anyway, so files re-saved by other
|
|
8
|
+
* tools still round-trip.
|
|
9
|
+
*/
|
|
10
|
+
export interface GrayImage {
|
|
11
|
+
width: number;
|
|
12
|
+
height: number;
|
|
13
|
+
/** Row-major, one byte per pixel, 0 = black .. 255 = white. */
|
|
14
|
+
pixels: Buffer;
|
|
15
|
+
}
|
|
16
|
+
export declare function crc32(buf: Buffer): number;
|
|
17
|
+
/** Encode an 8-bit grayscale image as a PNG buffer. */
|
|
18
|
+
export declare function encodePng(img: GrayImage): Buffer;
|
|
19
|
+
/** Decode an 8-bit grayscale PNG produced by encodePng (or equivalent).
|
|
20
|
+
* Throws on anything that isn't a non-interlaced 8-bit grayscale PNG. */
|
|
21
|
+
export declare function decodePng(buf: Buffer): GrayImage;
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// adr: adr/governed-compact.md
|
|
3
|
+
/** Minimal PNG encoder/decoder for the archive renderer — 8-bit grayscale
|
|
4
|
+
* only, zero dependencies (Node's built-in zlib supplies DEFLATE; PNG's
|
|
5
|
+
* IDAT is a zlib stream).
|
|
6
|
+
*
|
|
7
|
+
* Encode writes filter type 0 (None) on every scanline — glyph bitmaps
|
|
8
|
+
* deflate well without prediction and it keeps decode trivial. Decode
|
|
9
|
+
* handles all five standard filters anyway, so files re-saved by other
|
|
10
|
+
* tools still round-trip.
|
|
11
|
+
*/
|
|
12
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
13
|
+
if (k2 === undefined) k2 = k;
|
|
14
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
15
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
16
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
17
|
+
}
|
|
18
|
+
Object.defineProperty(o, k2, desc);
|
|
19
|
+
}) : (function(o, m, k, k2) {
|
|
20
|
+
if (k2 === undefined) k2 = k;
|
|
21
|
+
o[k2] = m[k];
|
|
22
|
+
}));
|
|
23
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
24
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
25
|
+
}) : function(o, v) {
|
|
26
|
+
o["default"] = v;
|
|
27
|
+
});
|
|
28
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
29
|
+
var ownKeys = function(o) {
|
|
30
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
31
|
+
var ar = [];
|
|
32
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
33
|
+
return ar;
|
|
34
|
+
};
|
|
35
|
+
return ownKeys(o);
|
|
36
|
+
};
|
|
37
|
+
return function (mod) {
|
|
38
|
+
if (mod && mod.__esModule) return mod;
|
|
39
|
+
var result = {};
|
|
40
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
41
|
+
__setModuleDefault(result, mod);
|
|
42
|
+
return result;
|
|
43
|
+
};
|
|
44
|
+
})();
|
|
45
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
46
|
+
exports.crc32 = crc32;
|
|
47
|
+
exports.encodePng = encodePng;
|
|
48
|
+
exports.decodePng = decodePng;
|
|
49
|
+
const zlib = __importStar(require("zlib"));
|
|
50
|
+
const PNG_SIGNATURE = Buffer.from([0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a]);
|
|
51
|
+
// ---------- CRC32 (PNG polynomial) ------------------------------------------
|
|
52
|
+
let crcTable = null;
|
|
53
|
+
function getCrcTable() {
|
|
54
|
+
if (crcTable)
|
|
55
|
+
return crcTable;
|
|
56
|
+
crcTable = new Uint32Array(256);
|
|
57
|
+
for (let n = 0; n < 256; n++) {
|
|
58
|
+
let c = n;
|
|
59
|
+
for (let k = 0; k < 8; k++) {
|
|
60
|
+
c = c & 1 ? 0xedb88320 ^ (c >>> 1) : c >>> 1;
|
|
61
|
+
}
|
|
62
|
+
crcTable[n] = c >>> 0;
|
|
63
|
+
}
|
|
64
|
+
return crcTable;
|
|
65
|
+
}
|
|
66
|
+
function crc32(buf) {
|
|
67
|
+
const table = getCrcTable();
|
|
68
|
+
let c = 0xffffffff;
|
|
69
|
+
for (let i = 0; i < buf.length; i++) {
|
|
70
|
+
c = table[(c ^ buf[i]) & 0xff] ^ (c >>> 8);
|
|
71
|
+
}
|
|
72
|
+
return (c ^ 0xffffffff) >>> 0;
|
|
73
|
+
}
|
|
74
|
+
// ---------- Encode -----------------------------------------------------------
|
|
75
|
+
function chunk(type, data) {
|
|
76
|
+
const len = Buffer.alloc(4);
|
|
77
|
+
len.writeUInt32BE(data.length, 0);
|
|
78
|
+
const typeAndData = Buffer.concat([Buffer.from(type, 'ascii'), data]);
|
|
79
|
+
const crc = Buffer.alloc(4);
|
|
80
|
+
crc.writeUInt32BE(crc32(typeAndData), 0);
|
|
81
|
+
return Buffer.concat([len, typeAndData, crc]);
|
|
82
|
+
}
|
|
83
|
+
/** Encode an 8-bit grayscale image as a PNG buffer. */
|
|
84
|
+
function encodePng(img) {
|
|
85
|
+
const { width, height, pixels } = img;
|
|
86
|
+
if (pixels.length !== width * height) {
|
|
87
|
+
throw new Error(`pixel buffer ${pixels.length} != ${width}x${height}`);
|
|
88
|
+
}
|
|
89
|
+
const ihdr = Buffer.alloc(13);
|
|
90
|
+
ihdr.writeUInt32BE(width, 0);
|
|
91
|
+
ihdr.writeUInt32BE(height, 4);
|
|
92
|
+
ihdr[8] = 8; // bit depth
|
|
93
|
+
ihdr[9] = 0; // color type: grayscale
|
|
94
|
+
ihdr[10] = 0; // compression
|
|
95
|
+
ihdr[11] = 0; // filter method
|
|
96
|
+
ihdr[12] = 0; // no interlace
|
|
97
|
+
// Raw scanlines: filter byte 0 + row pixels.
|
|
98
|
+
const raw = Buffer.alloc(height * (width + 1));
|
|
99
|
+
for (let y = 0; y < height; y++) {
|
|
100
|
+
raw[y * (width + 1)] = 0;
|
|
101
|
+
pixels.copy(raw, y * (width + 1) + 1, y * width, (y + 1) * width);
|
|
102
|
+
}
|
|
103
|
+
const idat = zlib.deflateSync(raw, { level: 9 });
|
|
104
|
+
return Buffer.concat([
|
|
105
|
+
PNG_SIGNATURE,
|
|
106
|
+
chunk('IHDR', ihdr),
|
|
107
|
+
chunk('IDAT', idat),
|
|
108
|
+
chunk('IEND', Buffer.alloc(0)),
|
|
109
|
+
]);
|
|
110
|
+
}
|
|
111
|
+
// ---------- Decode -----------------------------------------------------------
|
|
112
|
+
function paeth(a, b, c) {
|
|
113
|
+
const p = a + b - c;
|
|
114
|
+
const pa = Math.abs(p - a);
|
|
115
|
+
const pb = Math.abs(p - b);
|
|
116
|
+
const pc = Math.abs(p - c);
|
|
117
|
+
if (pa <= pb && pa <= pc)
|
|
118
|
+
return a;
|
|
119
|
+
if (pb <= pc)
|
|
120
|
+
return b;
|
|
121
|
+
return c;
|
|
122
|
+
}
|
|
123
|
+
/** Decode an 8-bit grayscale PNG produced by encodePng (or equivalent).
|
|
124
|
+
* Throws on anything that isn't a non-interlaced 8-bit grayscale PNG. */
|
|
125
|
+
function decodePng(buf) {
|
|
126
|
+
if (buf.length < 8 || !buf.subarray(0, 8).equals(PNG_SIGNATURE)) {
|
|
127
|
+
throw new Error('not a PNG (bad signature)');
|
|
128
|
+
}
|
|
129
|
+
let width = 0;
|
|
130
|
+
let height = 0;
|
|
131
|
+
const idatParts = [];
|
|
132
|
+
let off = 8;
|
|
133
|
+
while (off + 8 <= buf.length) {
|
|
134
|
+
const len = buf.readUInt32BE(off);
|
|
135
|
+
const type = buf.toString('ascii', off + 4, off + 8);
|
|
136
|
+
const data = buf.subarray(off + 8, off + 8 + len);
|
|
137
|
+
if (type === 'IHDR') {
|
|
138
|
+
width = data.readUInt32BE(0);
|
|
139
|
+
height = data.readUInt32BE(4);
|
|
140
|
+
const bitDepth = data[8];
|
|
141
|
+
const colorType = data[9];
|
|
142
|
+
const interlace = data[12];
|
|
143
|
+
if (bitDepth !== 8 || colorType !== 0 || interlace !== 0) {
|
|
144
|
+
throw new Error(`unsupported PNG (bitDepth=${bitDepth} colorType=${colorType} interlace=${interlace})`);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
else if (type === 'IDAT') {
|
|
148
|
+
idatParts.push(data);
|
|
149
|
+
}
|
|
150
|
+
else if (type === 'IEND') {
|
|
151
|
+
break;
|
|
152
|
+
}
|
|
153
|
+
off += 8 + len + 4; // len + type + data + crc
|
|
154
|
+
}
|
|
155
|
+
if (!width || !height)
|
|
156
|
+
throw new Error('PNG missing IHDR');
|
|
157
|
+
if (idatParts.length === 0)
|
|
158
|
+
throw new Error('PNG missing IDAT');
|
|
159
|
+
const raw = zlib.inflateSync(Buffer.concat(idatParts));
|
|
160
|
+
const stride = width + 1;
|
|
161
|
+
if (raw.length < height * stride) {
|
|
162
|
+
throw new Error(`PNG data short: ${raw.length} < ${height * stride}`);
|
|
163
|
+
}
|
|
164
|
+
const pixels = Buffer.alloc(width * height);
|
|
165
|
+
for (let y = 0; y < height; y++) {
|
|
166
|
+
const filter = raw[y * stride];
|
|
167
|
+
const rowIn = raw.subarray(y * stride + 1, y * stride + 1 + width);
|
|
168
|
+
const rowOut = pixels.subarray(y * width, (y + 1) * width);
|
|
169
|
+
for (let x = 0; x < width; x++) {
|
|
170
|
+
const a = x > 0 ? rowOut[x - 1] : 0; // left
|
|
171
|
+
const b = y > 0 ? pixels[(y - 1) * width + x] : 0; // up
|
|
172
|
+
const c = x > 0 && y > 0 ? pixels[(y - 1) * width + x - 1] : 0; // up-left
|
|
173
|
+
let v;
|
|
174
|
+
switch (filter) {
|
|
175
|
+
case 0:
|
|
176
|
+
v = rowIn[x];
|
|
177
|
+
break;
|
|
178
|
+
case 1:
|
|
179
|
+
v = rowIn[x] + a;
|
|
180
|
+
break;
|
|
181
|
+
case 2:
|
|
182
|
+
v = rowIn[x] + b;
|
|
183
|
+
break;
|
|
184
|
+
case 3:
|
|
185
|
+
v = rowIn[x] + ((a + b) >> 1);
|
|
186
|
+
break;
|
|
187
|
+
case 4:
|
|
188
|
+
v = rowIn[x] + paeth(a, b, c);
|
|
189
|
+
break;
|
|
190
|
+
default: throw new Error(`unsupported PNG filter ${filter} on row ${y}`);
|
|
191
|
+
}
|
|
192
|
+
rowOut[x] = v & 0xff;
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
return { width, height, pixels };
|
|
196
|
+
}
|
|
197
|
+
//# sourceMappingURL=png-codec.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"png-codec.js","sourceRoot":"","sources":["../../src/archive/png-codec.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/** Transcript extraction for the PNG archive — JSONL -> flat conversation
|
|
2
|
+
* text with turn-numbered section headers.
|
|
3
|
+
*
|
|
4
|
+
* Main chain only: sidechain (subagent) entries are skipped — the archive
|
|
5
|
+
* is the record of THIS conversation, which is what compaction is about to
|
|
6
|
+
* summarize away. A "turn" increments on each real user message (one with
|
|
7
|
+
* text content, not a tool_result carrier), matching the turn notion used
|
|
8
|
+
* across the hook layer.
|
|
9
|
+
*
|
|
10
|
+
* Section headers (`=== T<n> USER ===` etc.) give the vision model anchors
|
|
11
|
+
* to scan for, and give the indexer the char offsets it needs to stamp a
|
|
12
|
+
* turn range onto every rendered page.
|
|
13
|
+
*/
|
|
14
|
+
export interface TurnMark {
|
|
15
|
+
turn: number;
|
|
16
|
+
/** Char offset of the turn's first section header in the extracted text. */
|
|
17
|
+
charStart: number;
|
|
18
|
+
}
|
|
19
|
+
export interface ExtractedTranscript {
|
|
20
|
+
/** Flat conversation text (pre-sanitize — may contain any unicode). */
|
|
21
|
+
text: string;
|
|
22
|
+
/** Ascending char offsets where each turn begins. */
|
|
23
|
+
turnMarks: TurnMark[];
|
|
24
|
+
/** Total turns seen (= turnMarks.length). */
|
|
25
|
+
turns: number;
|
|
26
|
+
}
|
|
27
|
+
/** Extract the main-chain conversation from a transcript JSONL string. */
|
|
28
|
+
export declare function extractConversation(jsonl: string): ExtractedTranscript;
|
|
29
|
+
/** File wrapper. Returns null when the transcript can't be read. */
|
|
30
|
+
export declare function extractTranscriptFile(transcriptPath: string): ExtractedTranscript | null;
|
|
31
|
+
/** Turn range [first, last] overlapping a char window. turnMarks must be
|
|
32
|
+
* ascending and in the SAME offset space as the window (callers re-map
|
|
33
|
+
* marks through sanitizeWithMarks before paginating). A turn spans from
|
|
34
|
+
* its mark to the next mark (the last turn runs to infinity). Content
|
|
35
|
+
* before the first mark (rare T0 preamble) reports as turn 0. */
|
|
36
|
+
export declare function turnRangeForWindow(marks: TurnMark[], charStart: number, charEnd: number): {
|
|
37
|
+
turnStart: number;
|
|
38
|
+
turnEnd: number;
|
|
39
|
+
};
|