@blackwell-systems/gcf 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.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Blackwell Systems
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,177 @@
1
+ <p align="center">
2
+ <a href="https://github.com/blackwell-systems"><img src="https://raw.githubusercontent.com/blackwell-systems/blackwell-docs-theme/main/badge-trademark.svg" alt="Blackwell Systems"></a>
3
+ <a href="https://github.com/blackwell-systems/gcf-typescript/actions"><img src="https://github.com/blackwell-systems/gcf-typescript/actions/workflows/ci.yml/badge.svg" alt="CI"></a>
4
+ <a href="LICENSE"><img src="https://img.shields.io/badge/license-MIT-blue.svg" alt="License"></a>
5
+ </p>
6
+
7
+ # gcf-typescript
8
+
9
+ TypeScript implementation of [GCF (Graph Compact Format)](https://github.com/blackwell-systems/gcf).
10
+
11
+ **84% fewer tokens than JSON. 32% fewer than TOON. 100% LLM comprehension accuracy at 500 symbols, where JSON fails.**
12
+
13
+ ## Install
14
+
15
+ ```
16
+ npm install @blackwell-systems/gcf
17
+ ```
18
+
19
+ Zero dependencies. TypeScript-first. Includes CLI.
20
+
21
+ ## CLI
22
+
23
+ ```bash
24
+ npx @blackwell-systems/gcf encode < payload.json # JSON to GCF
25
+ npx @blackwell-systems/gcf decode < payload.gcf # GCF to JSON
26
+ npx @blackwell-systems/gcf stats < payload.json # token comparison
27
+ ```
28
+
29
+ ```
30
+ Payload: 50 symbols, 20 edges
31
+
32
+ JSON ██████████████████████████████ 4,200 tokens
33
+ GCF ████████░░░░░░░░░░░░░░░░░░░░░░ 1,150 tokens
34
+
35
+ Savings: 73% fewer tokens with GCF
36
+ ```
37
+
38
+ Or install globally: `npm install -g @blackwell-systems/gcf` then use `gcf` directly.
39
+
40
+ ## Library
41
+
42
+ ### Quick Start
43
+
44
+ ```typescript
45
+ import { encode, type Payload } from '@blackwell-systems/gcf';
46
+
47
+ const p: Payload = {
48
+ tool: 'context_for_task',
49
+ tokenBudget: 5000,
50
+ tokensUsed: 1847,
51
+ symbols: [
52
+ { qualifiedName: 'pkg.AuthMiddleware', kind: 'function', score: 0.78, provenance: 'lsp_resolved', distance: 0 },
53
+ { qualifiedName: 'pkg.NewServer', kind: 'function', score: 0.54, provenance: 'lsp_resolved', distance: 1 },
54
+ ],
55
+ edges: [
56
+ { source: 'pkg.NewServer', target: 'pkg.AuthMiddleware', edgeType: 'calls' },
57
+ ],
58
+ };
59
+
60
+ const output = encode(p);
61
+ ```
62
+
63
+ Output:
64
+ ```
65
+ GCF tool=context_for_task budget=5000 tokens=1847 symbols=2
66
+ ## targets
67
+ @0 fn pkg.AuthMiddleware 0.78 lsp_resolved
68
+ ## related
69
+ @1 fn pkg.NewServer 0.54 lsp_resolved
70
+ ## edges
71
+ @0<@1 calls
72
+ ```
73
+
74
+ ## Decode
75
+
76
+ ```typescript
77
+ import { decode } from '@blackwell-systems/gcf';
78
+
79
+ const p = decode(input);
80
+ console.log(p.tool, p.symbols.length, 'symbols', p.edges.length, 'edges');
81
+ ```
82
+
83
+ ## Session Deduplication
84
+
85
+ Track transmitted symbols across multiple tool responses. Previously-sent symbols become bare references instead of full declarations:
86
+
87
+ ```typescript
88
+ import { Session, encodeWithSession } from '@blackwell-systems/gcf';
89
+
90
+ const sess = new Session();
91
+
92
+ const out1 = encodeWithSession(payload1, sess); // full declarations
93
+ const out2 = encodeWithSession(payload2, sess); // reused symbols as "@N # previously transmitted"
94
+ ```
95
+
96
+ By the 5th call in a session: 92.7% token savings vs JSON.
97
+
98
+ ## Delta Encoding
99
+
100
+ When the consumer already has a prior context pack, send only what changed:
101
+
102
+ ```typescript
103
+ import { encodeDelta, type DeltaPayload } from '@blackwell-systems/gcf';
104
+
105
+ const delta: DeltaPayload = {
106
+ tool: 'context_for_task',
107
+ baseRoot: 'aaa111',
108
+ newRoot: 'bbb222',
109
+ removed: [{ qualifiedName: 'pkg.OldFunc', kind: 'function', score: 0, provenance: '', distance: 0 }],
110
+ added: [{ qualifiedName: 'pkg.NewFunc', kind: 'function', score: 0.85, provenance: 'rwr', distance: 0 }],
111
+ removedEdges: [],
112
+ addedEdges: [],
113
+ deltaTokens: 30,
114
+ fullTokens: 200,
115
+ };
116
+
117
+ const output = encodeDelta(delta);
118
+ ```
119
+
120
+ 81.2% savings on re-queries where the pack changed slightly.
121
+
122
+ ## API
123
+
124
+ | Function | Description |
125
+ |----------|-------------|
126
+ | `encode(p: Payload): string` | Encode a payload to GCF text |
127
+ | `decode(input: string): Payload` | Parse GCF text back to a Payload |
128
+ | `encodeWithSession(p: Payload, s: Session): string` | Encode with session deduplication |
129
+ | `encodeDelta(d: DeltaPayload): string` | Encode a delta (added/removed only) |
130
+ | `new Session()` | Create a new session tracker |
131
+
132
+ ## Types
133
+
134
+ | Type | Purpose |
135
+ |------|---------|
136
+ | `Payload` | Full GCF payload: tool, budget, symbols, edges, pack root |
137
+ | `Symbol` | Graph node: qualified name, kind, score, provenance, distance |
138
+ | `Edge` | Directed relationship: source, target, edge type |
139
+ | `DeltaPayload` | Diff between two packs: added/removed symbols and edges |
140
+ | `Session` | Tracker for multi-call deduplication |
141
+ | `KIND_ABBREV` / `KIND_EXPAND` | Bidirectional kind abbreviation maps |
142
+
143
+ ## Comprehension Eval
144
+
145
+ A rigorous 3-way benchmark (GCF vs TOON vs JSON) at 500 symbols, 200 edges. Six structured extraction questions sent to an LLM:
146
+
147
+ | Format | Accuracy | Tokens | vs JSON |
148
+ |--------|----------|--------|---------|
149
+ | **GCF** | **100%** (6/6) | **11,090** | **79% fewer** |
150
+ | TOON | 100% (6/6) | 16,378 | 69% fewer |
151
+ | JSON | 66.7% (4/6) | 53,341 | baseline |
152
+
153
+ JSON failed on counting tasks. GCF and TOON both achieved perfect accuracy. GCF does it in 32% fewer tokens.
154
+
155
+ ## Token Efficiency (TOON's Own Benchmark)
156
+
157
+ Running [TOON's benchmark harness](https://github.com/blackwell-systems/toon/tree/gcf-comparison) with GCF inserted (their datasets, their tokenizer):
158
+
159
+ | Track | GCF | TOON | Result |
160
+ |-------|-----|------|--------|
161
+ | Mixed-structure (nested, semi-uniform) | 169,554 | 227,896 | **GCF 34% smaller** |
162
+ | Flat-only (tabular) | 66,026 | 67,837 | **GCF 3% smaller** |
163
+ | Semi-uniform event logs | 107,269 | 154,032 | **GCF 44% smaller** |
164
+
165
+ GCF wins on every dataset except deeply nested config (75 tokens on a 618-token payload). On semi-uniform data, GCF uses 44% fewer tokens than TOON.
166
+
167
+ Reproducible: [blackwell-systems/toon@gcf-comparison](https://github.com/blackwell-systems/toon/tree/gcf-comparison)
168
+
169
+ ## Related
170
+
171
+ - [Specification](https://github.com/blackwell-systems/gcf) (grammar, encoding rules, design constraints)
172
+ - [gcf-go](https://github.com/blackwell-systems/gcf-go) (Go implementation)
173
+ - [TOON benchmark fork](https://github.com/blackwell-systems/toon/tree/gcf-comparison) (reproducible token counts)
174
+
175
+ ## License
176
+
177
+ MIT
package/dist/cli.d.ts ADDED
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * GCF command-line interface: encode, decode, stats.
4
+ */
5
+ export {};
6
+ //# sourceMappingURL=cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AACA;;GAEG"}
package/dist/cli.js ADDED
@@ -0,0 +1,122 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * GCF command-line interface: encode, decode, stats.
4
+ */
5
+ import { readFileSync } from 'node:fs';
6
+ import { encode } from './encode.js';
7
+ import { decode } from './decode.js';
8
+ const USAGE = `gcf - token-optimized wire format for LLM tool responses
9
+
10
+ Usage:
11
+ gcf encode [file] Encode JSON payload to GCF (stdin if no file)
12
+ gcf decode [file] Decode GCF text to JSON (stdin if no file)
13
+ gcf stats [file] Compare token counts: JSON vs GCF (stdin if no file)
14
+ gcf version Print version
15
+
16
+ Examples:
17
+ gcf encode < payload.json
18
+ gcf decode < payload.gcf
19
+ gcf stats payload.json
20
+ `;
21
+ function readInput(args) {
22
+ if (args.length > 0 && args[0] !== '-') {
23
+ return readFileSync(args[0], 'utf-8');
24
+ }
25
+ return readFileSync(0, 'utf-8');
26
+ }
27
+ function payloadFromJSON(data) {
28
+ const obj = JSON.parse(data);
29
+ return {
30
+ tool: obj.tool ?? '',
31
+ tokenBudget: obj.tokenBudget ?? 0,
32
+ tokensUsed: obj.tokensUsed ?? 0,
33
+ packRoot: obj.packRoot ?? '',
34
+ symbols: (obj.symbols ?? []).map((s) => ({
35
+ qualifiedName: s.qualifiedName,
36
+ kind: s.kind,
37
+ score: s.score,
38
+ provenance: s.provenance,
39
+ distance: s.distance ?? 0,
40
+ })),
41
+ edges: (obj.edges ?? []).map((e) => ({
42
+ source: e.source,
43
+ target: e.target,
44
+ edgeType: e.edgeType,
45
+ status: e.status ?? '',
46
+ })),
47
+ };
48
+ }
49
+ function payloadToJSON(p) {
50
+ return JSON.stringify({
51
+ tool: p.tool,
52
+ tokensUsed: p.tokensUsed,
53
+ tokenBudget: p.tokenBudget,
54
+ packRoot: p.packRoot ?? '',
55
+ symbols: p.symbols.map(s => ({
56
+ qualifiedName: s.qualifiedName,
57
+ kind: s.kind,
58
+ score: s.score,
59
+ provenance: s.provenance,
60
+ distance: s.distance,
61
+ })),
62
+ edges: p.edges.map(e => ({
63
+ source: e.source,
64
+ target: e.target,
65
+ edgeType: e.edgeType,
66
+ ...(e.status ? { status: e.status } : {}),
67
+ })),
68
+ }, null, 2);
69
+ }
70
+ function doEncode(data) {
71
+ const p = payloadFromJSON(data);
72
+ process.stdout.write(encode(p));
73
+ }
74
+ function doDecode(data) {
75
+ const p = decode(data);
76
+ console.log(payloadToJSON(p));
77
+ }
78
+ function doStats(data) {
79
+ const p = payloadFromJSON(data);
80
+ const gcfOutput = encode(p);
81
+ const jsonTokens = Math.floor(data.trim().length / 4);
82
+ const gcfTokens = Math.floor(gcfOutput.trim().length / 4);
83
+ const savings = jsonTokens > 0 ? 100 * (1 - gcfTokens / jsonTokens) : 0;
84
+ const barWidth = 30;
85
+ const jsonBar = '█'.repeat(barWidth);
86
+ const gcfFilled = jsonTokens > 0 ? Math.round((gcfTokens * barWidth) / jsonTokens) : 0;
87
+ const gcfBar = '█'.repeat(gcfFilled) + '░'.repeat(barWidth - gcfFilled);
88
+ console.log(`Payload: ${p.symbols.length} symbols, ${p.edges.length} edges\n`);
89
+ console.log(` JSON ${jsonBar} ${jsonTokens} tokens`);
90
+ console.log(` GCF ${gcfBar} ${gcfTokens} tokens`);
91
+ console.log(`\n Savings: ${Math.round(savings)}% fewer tokens with GCF`);
92
+ }
93
+ const args = process.argv.slice(2);
94
+ const cmd = args[0];
95
+ switch (cmd) {
96
+ case 'encode':
97
+ doEncode(readInput(args.slice(1)));
98
+ break;
99
+ case 'decode':
100
+ doDecode(readInput(args.slice(1)));
101
+ break;
102
+ case 'stats':
103
+ doStats(readInput(args.slice(1)));
104
+ break;
105
+ case 'version':
106
+ console.log('gcf 0.1.0');
107
+ break;
108
+ case '-h':
109
+ case '--help':
110
+ case 'help':
111
+ process.stdout.write(USAGE);
112
+ break;
113
+ default:
114
+ if (!cmd) {
115
+ process.stderr.write(USAGE);
116
+ process.exit(1);
117
+ }
118
+ process.stderr.write(`unknown command: ${cmd}\n\n`);
119
+ process.stderr.write(USAGE);
120
+ process.exit(1);
121
+ }
122
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * KindAbbrev maps full kind names to short GCF abbreviations.
3
+ */
4
+ export declare const KIND_ABBREV: Record<string, string>;
5
+ /**
6
+ * KindExpand is the reverse of KindAbbrev: maps abbreviations back to full kind names.
7
+ */
8
+ export declare const KIND_EXPAND: Record<string, string>;
9
+ //# sourceMappingURL=constants.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,eAAO,MAAM,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAiB9C,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAiB9C,CAAC"}
@@ -0,0 +1,43 @@
1
+ /**
2
+ * KindAbbrev maps full kind names to short GCF abbreviations.
3
+ */
4
+ export const KIND_ABBREV = {
5
+ function: 'fn',
6
+ type: 'type',
7
+ method: 'method',
8
+ interface: 'iface',
9
+ var: 'var',
10
+ const: 'const',
11
+ resource: 'resource',
12
+ table: 'table',
13
+ class: 'class',
14
+ selector: 'selector',
15
+ field: 'field',
16
+ route_handler: 'route',
17
+ external: 'ext',
18
+ file: 'file',
19
+ package: 'pkg',
20
+ service: 'svc',
21
+ };
22
+ /**
23
+ * KindExpand is the reverse of KindAbbrev: maps abbreviations back to full kind names.
24
+ */
25
+ export const KIND_EXPAND = {
26
+ fn: 'function',
27
+ type: 'type',
28
+ method: 'method',
29
+ iface: 'interface',
30
+ var: 'var',
31
+ const: 'const',
32
+ resource: 'resource',
33
+ table: 'table',
34
+ class: 'class',
35
+ selector: 'selector',
36
+ field: 'field',
37
+ route: 'route_handler',
38
+ ext: 'external',
39
+ file: 'file',
40
+ pkg: 'package',
41
+ svc: 'service',
42
+ };
43
+ //# sourceMappingURL=constants.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"constants.js","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,CAAC,MAAM,WAAW,GAA2B;IACjD,QAAQ,EAAE,IAAI;IACd,IAAI,EAAE,MAAM;IACZ,MAAM,EAAE,QAAQ;IAChB,SAAS,EAAE,OAAO;IAClB,GAAG,EAAE,KAAK;IACV,KAAK,EAAE,OAAO;IACd,QAAQ,EAAE,UAAU;IACpB,KAAK,EAAE,OAAO;IACd,KAAK,EAAE,OAAO;IACd,QAAQ,EAAE,UAAU;IACpB,KAAK,EAAE,OAAO;IACd,aAAa,EAAE,OAAO;IACtB,QAAQ,EAAE,KAAK;IACf,IAAI,EAAE,MAAM;IACZ,OAAO,EAAE,KAAK;IACd,OAAO,EAAE,KAAK;CACf,CAAC;AAEF;;GAEG;AACH,MAAM,CAAC,MAAM,WAAW,GAA2B;IACjD,EAAE,EAAE,UAAU;IACd,IAAI,EAAE,MAAM;IACZ,MAAM,EAAE,QAAQ;IAChB,KAAK,EAAE,WAAW;IAClB,GAAG,EAAE,KAAK;IACV,KAAK,EAAE,OAAO;IACd,QAAQ,EAAE,UAAU;IACpB,KAAK,EAAE,OAAO;IACd,KAAK,EAAE,OAAO;IACd,QAAQ,EAAE,UAAU;IACpB,KAAK,EAAE,OAAO;IACd,KAAK,EAAE,eAAe;IACtB,GAAG,EAAE,UAAU;IACf,IAAI,EAAE,MAAM;IACZ,GAAG,EAAE,SAAS;IACd,GAAG,EAAE,SAAS;CACf,CAAC"}
@@ -0,0 +1,6 @@
1
+ import type { Payload } from './types.js';
2
+ /**
3
+ * Decode parses GCF text back into a Payload.
4
+ */
5
+ export declare function decode(input: string): Payload;
6
+ //# sourceMappingURL=decode.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"decode.d.ts","sourceRoot":"","sources":["../src/decode.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAQ,OAAO,EAAU,MAAM,YAAY,CAAC;AAGxD;;GAEG;AACH,wBAAgB,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CA6E7C"}
package/dist/decode.js ADDED
@@ -0,0 +1,179 @@
1
+ import { KIND_EXPAND } from './constants.js';
2
+ /**
3
+ * Decode parses GCF text back into a Payload.
4
+ */
5
+ export function decode(input) {
6
+ const lines = input.split('\n');
7
+ if (lines.length === 0) {
8
+ throw new Error('gcf: empty input');
9
+ }
10
+ const header = lines[0];
11
+ if (!header.startsWith('GCF ')) {
12
+ throw new Error(`gcf: invalid header, expected 'GCF ...' got "${header}"`);
13
+ }
14
+ const p = {
15
+ tool: '',
16
+ tokenBudget: 0,
17
+ tokensUsed: 0,
18
+ symbols: [],
19
+ edges: [],
20
+ };
21
+ // Parse header fields.
22
+ parseHeader(header.slice(4), p);
23
+ // Parse body: symbols and edges.
24
+ const symbols = [];
25
+ const symByID = new Map();
26
+ let currentDistance = 0;
27
+ let inEdges = false;
28
+ for (let i = 1; i < lines.length; i++) {
29
+ let line = lines[i].replace(/\r$/, '');
30
+ if (line === '')
31
+ continue;
32
+ // Group header.
33
+ if (line.startsWith('## ')) {
34
+ const group = line.slice(3);
35
+ inEdges = group === 'edges';
36
+ if (!inEdges) {
37
+ switch (group) {
38
+ case 'targets':
39
+ currentDistance = 0;
40
+ break;
41
+ case 'related':
42
+ currentDistance = 1;
43
+ break;
44
+ case 'extended':
45
+ currentDistance = 2;
46
+ break;
47
+ default:
48
+ if (group.startsWith('distance_')) {
49
+ const d = parseInt(group.slice(9), 10);
50
+ if (!isNaN(d)) {
51
+ currentDistance = d;
52
+ }
53
+ }
54
+ break;
55
+ }
56
+ }
57
+ continue;
58
+ }
59
+ // Comment.
60
+ if (line.startsWith('# ')) {
61
+ continue;
62
+ }
63
+ if (inEdges) {
64
+ const edge = parseEdgeLine(line, symByID);
65
+ p.edges.push(edge);
66
+ }
67
+ else {
68
+ const { symbol, id } = parseSymbolLine(line, currentDistance);
69
+ symbols.push(symbol);
70
+ symByID.set(id, symbol);
71
+ }
72
+ }
73
+ p.symbols = symbols;
74
+ return p;
75
+ }
76
+ function parseHeader(fields, p) {
77
+ const parts = fields.split(/\s+/);
78
+ for (const part of parts) {
79
+ const eqIdx = part.indexOf('=');
80
+ if (eqIdx < 0)
81
+ continue;
82
+ const key = part.slice(0, eqIdx);
83
+ const value = part.slice(eqIdx + 1);
84
+ switch (key) {
85
+ case 'tool':
86
+ p.tool = value;
87
+ break;
88
+ case 'budget': {
89
+ const v = parseInt(value, 10);
90
+ if (isNaN(v))
91
+ throw new Error(`gcf: invalid budget "${value}"`);
92
+ p.tokenBudget = v;
93
+ break;
94
+ }
95
+ case 'tokens': {
96
+ const v = parseInt(value, 10);
97
+ if (isNaN(v))
98
+ throw new Error(`gcf: invalid tokens "${value}"`);
99
+ p.tokensUsed = v;
100
+ break;
101
+ }
102
+ case 'pack_root':
103
+ p.packRoot = value;
104
+ break;
105
+ case 'symbols':
106
+ // Informational, reconstructed from parsed symbols.
107
+ break;
108
+ }
109
+ }
110
+ }
111
+ function parseSymbolLine(line, distance) {
112
+ if (!line.startsWith('@')) {
113
+ throw new Error(`gcf: expected symbol line starting with @, got "${line}"`);
114
+ }
115
+ const parts = line.split(/\s+/);
116
+ if (parts.length < 5) {
117
+ throw new Error(`gcf: symbol line needs at least 5 fields, got ${parts.length} in "${line}"`);
118
+ }
119
+ const idStr = parts[0].slice(1); // strip @
120
+ const id = parseInt(idStr, 10);
121
+ if (isNaN(id)) {
122
+ throw new Error(`gcf: invalid symbol id "${idStr}"`);
123
+ }
124
+ let kind = parts[1];
125
+ if (KIND_EXPAND[kind]) {
126
+ kind = KIND_EXPAND[kind];
127
+ }
128
+ const qname = parts[2];
129
+ const score = parseFloat(parts[3]);
130
+ if (isNaN(score)) {
131
+ throw new Error(`gcf: invalid score "${parts[3]}"`);
132
+ }
133
+ const provenance = parts[4];
134
+ return {
135
+ symbol: {
136
+ qualifiedName: qname,
137
+ kind,
138
+ score,
139
+ provenance,
140
+ distance,
141
+ },
142
+ id,
143
+ };
144
+ }
145
+ function parseEdgeLine(line, symByID) {
146
+ const parts = line.split(/\s+/);
147
+ if (parts.length < 2) {
148
+ throw new Error(`gcf: edge line needs at least 2 fields, got "${line}"`);
149
+ }
150
+ const ref = parts[0];
151
+ const ltIdx = ref.indexOf('<');
152
+ if (ltIdx < 0) {
153
+ throw new Error(`gcf: edge line missing '<' separator in "${ref}"`);
154
+ }
155
+ const targetIDStr = ref.slice(1, ltIdx); // strip leading @
156
+ const sourceIDStr = ref.slice(ltIdx + 2); // strip <@
157
+ const targetID = parseInt(targetIDStr, 10);
158
+ if (isNaN(targetID)) {
159
+ throw new Error(`gcf: invalid target id "${targetIDStr}"`);
160
+ }
161
+ const sourceID = parseInt(sourceIDStr, 10);
162
+ if (isNaN(sourceID)) {
163
+ throw new Error(`gcf: invalid source id "${sourceIDStr}"`);
164
+ }
165
+ const targetSym = symByID.get(targetID);
166
+ const sourceSym = symByID.get(sourceID);
167
+ if (!targetSym || !sourceSym) {
168
+ throw new Error(`gcf: edge references unknown symbol id(s): target=${targetID} source=${sourceID}`);
169
+ }
170
+ const edgeType = parts[1];
171
+ const status = parts.length >= 3 ? parts[2] : undefined;
172
+ return {
173
+ source: sourceSym.qualifiedName,
174
+ target: targetSym.qualifiedName,
175
+ edgeType,
176
+ status,
177
+ };
178
+ }
179
+ //# sourceMappingURL=decode.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"decode.js","sourceRoot":"","sources":["../src/decode.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ import type { DeltaPayload } from './types.js';
2
+ /**
3
+ * EncodeDelta serializes a DeltaPayload into GCF delta format.
4
+ */
5
+ export declare function encodeDelta(d: DeltaPayload): string;
6
+ //# sourceMappingURL=delta.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"delta.d.ts","sourceRoot":"","sources":["../src/delta.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAG/C;;GAEG;AACH,wBAAgB,WAAW,CAAC,CAAC,EAAE,YAAY,GAAG,MAAM,CAgDnD"}
package/dist/delta.js ADDED
@@ -0,0 +1,46 @@
1
+ import { KIND_ABBREV } from './constants.js';
2
+ /**
3
+ * EncodeDelta serializes a DeltaPayload into GCF delta format.
4
+ */
5
+ export function encodeDelta(d) {
6
+ const lines = [];
7
+ // Header.
8
+ let savings = 0;
9
+ if (d.fullTokens > 0) {
10
+ savings = Math.round(100 * (1 - d.deltaTokens / d.fullTokens));
11
+ }
12
+ lines.push(`GCF tool=${d.tool} delta=true base_root=${d.baseRoot} new_root=${d.newRoot} tokens=${d.deltaTokens} savings=${savings}%`);
13
+ // Removed symbols: short references (consumer already has the full declaration).
14
+ if (d.removed.length > 0) {
15
+ lines.push('## removed');
16
+ for (const s of d.removed) {
17
+ const kind = KIND_ABBREV[s.kind] || s.kind;
18
+ lines.push(`${kind} ${s.qualifiedName}`);
19
+ }
20
+ }
21
+ // Added symbols: full declarations (consumer doesn't have these).
22
+ if (d.added.length > 0) {
23
+ lines.push('## added');
24
+ for (let i = 0; i < d.added.length; i++) {
25
+ const s = d.added[i];
26
+ const kind = KIND_ABBREV[s.kind] || s.kind;
27
+ lines.push(`@${i} ${kind} ${s.qualifiedName} ${s.score.toFixed(2)} ${s.provenance}`);
28
+ }
29
+ }
30
+ // Removed edges.
31
+ if (d.removedEdges.length > 0) {
32
+ lines.push('## edges_removed');
33
+ for (const e of d.removedEdges) {
34
+ lines.push(`${e.source} -> ${e.target} ${e.edgeType}`);
35
+ }
36
+ }
37
+ // Added edges.
38
+ if (d.addedEdges.length > 0) {
39
+ lines.push('## edges_added');
40
+ for (const e of d.addedEdges) {
41
+ lines.push(`${e.source} -> ${e.target} ${e.edgeType}`);
42
+ }
43
+ }
44
+ return lines.join('\n') + '\n';
45
+ }
46
+ //# sourceMappingURL=delta.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"delta.js","sourceRoot":"","sources":["../src/delta.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAE7C;;GAEG;AACH,MAAM,UAAU,WAAW,CAAC,CAAe;IACzC,MAAM,KAAK,GAAa,EAAE,CAAC;IAE3B,UAAU;IACV,IAAI,OAAO,GAAG,CAAC,CAAC;IAChB,IAAI,CAAC,CAAC,UAAU,GAAG,CAAC,EAAE,CAAC;QACrB,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,WAAW,GAAG,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC;IACjE,CAAC;IACD,KAAK,CAAC,IAAI,CACR,YAAY,CAAC,CAAC,IAAI,yBAAyB,CAAC,CAAC,QAAQ,aAAa,CAAC,CAAC,OAAO,WAAW,CAAC,CAAC,WAAW,YAAY,OAAO,GAAG,CAC1H,CAAC;IAEF,iFAAiF;IACjF,IAAI,CAAC,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACzB,KAAK,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;QACzB,KAAK,MAAM,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,CAAC;YAC1B,MAAM,IAAI,GAAG,WAAW,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC;YAC3C,KAAK,CAAC,IAAI,CAAC,GAAG,IAAI,IAAI,CAAC,CAAC,aAAa,EAAE,CAAC,CAAC;QAC3C,CAAC;IACH,CAAC;IAED,kEAAkE;IAClE,IAAI,CAAC,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACvB,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QACvB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YACxC,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;YACrB,MAAM,IAAI,GAAG,WAAW,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC;YAC3C,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,CAAC,aAAa,IAAI,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,UAAU,EAAE,CAAC,CAAC;QACvF,CAAC;IACH,CAAC;IAED,iBAAiB;IACjB,IAAI,CAAC,CAAC,YAAY,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC9B,KAAK,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC;QAC/B,KAAK,MAAM,CAAC,IAAI,CAAC,CAAC,YAAY,EAAE,CAAC;YAC/B,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,MAAM,OAAO,CAAC,CAAC,MAAM,IAAI,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC;QACzD,CAAC;IACH,CAAC;IAED,eAAe;IACf,IAAI,CAAC,CAAC,UAAU,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC5B,KAAK,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC;QAC7B,KAAK,MAAM,CAAC,IAAI,CAAC,CAAC,UAAU,EAAE,CAAC;YAC7B,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,MAAM,OAAO,CAAC,CAAC,MAAM,IAAI,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC;QACzD,CAAC;IACH,CAAC;IAED,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;AACjC,CAAC"}