@madkid/relay-ctx 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. package/dist/commands/checkpoint.d.ts +18 -0
  2. package/dist/commands/checkpoint.d.ts.map +1 -0
  3. package/dist/commands/checkpoint.js +130 -0
  4. package/dist/commands/checkpoint.js.map +1 -0
  5. package/dist/commands/hooks.d.ts +36 -0
  6. package/dist/commands/hooks.d.ts.map +1 -0
  7. package/dist/commands/hooks.js +226 -0
  8. package/dist/commands/hooks.js.map +1 -0
  9. package/dist/commands/init.d.ts +14 -0
  10. package/dist/commands/init.d.ts.map +1 -0
  11. package/dist/commands/init.js +228 -0
  12. package/dist/commands/init.js.map +1 -0
  13. package/dist/commands/inject.d.ts +20 -0
  14. package/dist/commands/inject.d.ts.map +1 -0
  15. package/dist/commands/inject.js +209 -0
  16. package/dist/commands/inject.js.map +1 -0
  17. package/dist/commands/list.d.ts +2 -0
  18. package/dist/commands/list.d.ts.map +1 -0
  19. package/dist/commands/list.js +174 -0
  20. package/dist/commands/list.js.map +1 -0
  21. package/dist/commands/sync.d.ts +17 -0
  22. package/dist/commands/sync.d.ts.map +1 -0
  23. package/dist/commands/sync.js +239 -0
  24. package/dist/commands/sync.js.map +1 -0
  25. package/dist/core/compressor.d.ts +16 -0
  26. package/dist/core/compressor.d.ts.map +1 -0
  27. package/dist/core/compressor.js +354 -0
  28. package/dist/core/compressor.js.map +1 -0
  29. package/dist/core/scanner.d.ts +40 -0
  30. package/dist/core/scanner.d.ts.map +1 -0
  31. package/dist/core/scanner.js +366 -0
  32. package/dist/core/scanner.js.map +1 -0
  33. package/dist/core/storage.d.ts +39 -0
  34. package/dist/core/storage.d.ts.map +1 -0
  35. package/dist/core/storage.js +122 -0
  36. package/dist/core/storage.js.map +1 -0
  37. package/dist/index.d.ts +3 -0
  38. package/dist/index.d.ts.map +1 -0
  39. package/dist/index.js +57 -0
  40. package/dist/index.js.map +1 -0
  41. package/dist/test-relay.d.ts +2 -0
  42. package/dist/test-relay.d.ts.map +1 -0
  43. package/dist/test-relay.js +433 -0
  44. package/dist/test-relay.js.map +1 -0
  45. package/package.json +32 -0
package/dist/index.js ADDED
@@ -0,0 +1,57 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ const commander_1 = require("commander");
5
+ const init_1 = require("./commands/init");
6
+ const sync_1 = require("./commands/sync");
7
+ const inject_1 = require("./commands/inject");
8
+ const checkpoint_1 = require("./commands/checkpoint");
9
+ const list_1 = require("./commands/list");
10
+ const hooks_1 = require("./commands/hooks");
11
+ const program = new commander_1.Command();
12
+ program
13
+ .name('relay')
14
+ .description('Persistent AI context across sessions and tools')
15
+ .version('0.1.0');
16
+ program
17
+ .command('init')
18
+ .description('Initialize Relay for the current project')
19
+ .action(init_1.initCommand);
20
+ program
21
+ .command('sync')
22
+ .description('Scan project and update context')
23
+ .option('--silent', 'Suppress all output (used by git hooks)')
24
+ .action(sync_1.syncCommand);
25
+ program
26
+ .command('inject')
27
+ .description('Output compressed context ready to paste into any AI')
28
+ .option('--raw', 'Skip compression, output full PROJECT.md')
29
+ .option('--ai', 'Force AI compression mode using Anthropic Haiku')
30
+ .option('--bug', 'Debug mode: include git diff + prompt for error message')
31
+ .action(inject_1.injectCommand);
32
+ program
33
+ .command('checkpoint')
34
+ .description('Save a named snapshot of current context, or list checkpoints')
35
+ .argument('[message]', 'Checkpoint message')
36
+ .option('-l, --list', 'List all saved checkpoints')
37
+ .option('--silent', 'Suppress all output (used by git hooks)')
38
+ .action(async (message, options) => {
39
+ await (0, checkpoint_1.checkpointCommand)(message, options);
40
+ });
41
+ program
42
+ .command('list')
43
+ .description('Show all projects tracked by Relay')
44
+ .action(async () => {
45
+ await (0, list_1.listCommand)();
46
+ });
47
+ program
48
+ .command('hooks')
49
+ .description('Manage git hooks for automatic context tracking')
50
+ .option('--install', 'Install git hooks into this project')
51
+ .option('--uninstall', 'Remove git hooks from this project')
52
+ .option('--status', 'Show current hook installation status')
53
+ .action(async (options) => {
54
+ await (0, hooks_1.hooksCommand)(options);
55
+ });
56
+ program.parse();
57
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AACA,yCAAoC;AACpC,0CAA8C;AAC9C,0CAA8C;AAC9C,8CAAkD;AAClD,sDAA0D;AAC1D,0CAA8C;AAC9C,4CAAgD;AAEhD,MAAM,OAAO,GAAG,IAAI,mBAAO,EAAE,CAAC;AAE9B,OAAO;KACJ,IAAI,CAAC,OAAO,CAAC;KACb,WAAW,CAAC,iDAAiD,CAAC;KAC9D,OAAO,CAAC,OAAO,CAAC,CAAC;AAEpB,OAAO;KACJ,OAAO,CAAC,MAAM,CAAC;KACf,WAAW,CAAC,0CAA0C,CAAC;KACvD,MAAM,CAAC,kBAAW,CAAC,CAAC;AAEvB,OAAO;KACJ,OAAO,CAAC,MAAM,CAAC;KACf,WAAW,CAAC,iCAAiC,CAAC;KAC9C,MAAM,CAAC,UAAU,EAAE,yCAAyC,CAAC;KAC7D,MAAM,CAAC,kBAAW,CAAC,CAAC;AAEvB,OAAO;KACJ,OAAO,CAAC,QAAQ,CAAC;KACjB,WAAW,CAAC,sDAAsD,CAAC;KACnE,MAAM,CAAC,OAAO,EAAE,0CAA0C,CAAC;KAC3D,MAAM,CAAC,MAAM,EAAE,iDAAiD,CAAC;KACjE,MAAM,CAAC,OAAO,EAAE,yDAAyD,CAAC;KAC1E,MAAM,CAAC,sBAAa,CAAC,CAAC;AAEzB,OAAO;KACJ,OAAO,CAAC,YAAY,CAAC;KACrB,WAAW,CAAC,+DAA+D,CAAC;KAC5E,QAAQ,CAAC,WAAW,EAAE,oBAAoB,CAAC;KAC3C,MAAM,CAAC,YAAY,EAAE,4BAA4B,CAAC;KAClD,MAAM,CAAC,UAAU,EAAE,yCAAyC,CAAC;KAC7D,MAAM,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,EAAE;IACjC,MAAM,IAAA,8BAAiB,EAAC,OAAO,EAAE,OAAO,CAAC,CAAC;AAC5C,CAAC,CAAC,CAAC;AAEL,OAAO;KACJ,OAAO,CAAC,MAAM,CAAC;KACf,WAAW,CAAC,oCAAoC,CAAC;KACjD,MAAM,CAAC,KAAK,IAAI,EAAE;IACjB,MAAM,IAAA,kBAAW,GAAE,CAAC;AACtB,CAAC,CAAC,CAAC;AAEL,OAAO;KACJ,OAAO,CAAC,OAAO,CAAC;KAChB,WAAW,CAAC,iDAAiD,CAAC;KAC9D,MAAM,CAAC,WAAW,EAAE,qCAAqC,CAAC;KAC1D,MAAM,CAAC,aAAa,EAAE,oCAAoC,CAAC;KAC3D,MAAM,CAAC,UAAU,EAAE,uCAAuC,CAAC;KAC3D,MAAM,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE;IACxB,MAAM,IAAA,oBAAY,EAAC,OAAO,CAAC,CAAC;AAC9B,CAAC,CAAC,CAAC;AAEL,OAAO,CAAC,KAAK,EAAE,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=test-relay.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"test-relay.d.ts","sourceRoot":"","sources":["../src/test-relay.ts"],"names":[],"mappings":""}
@@ -0,0 +1,433 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ var __importDefault = (this && this.__importDefault) || function (mod) {
36
+ return (mod && mod.__esModule) ? mod : { "default": mod };
37
+ };
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ /**
40
+ * End-to-end test for Relay CLI core modules.
41
+ * Tests storage, scanner, compressor, and all 4 commands (non-interactive).
42
+ */
43
+ const fs_1 = __importDefault(require("fs"));
44
+ const path_1 = __importDefault(require("path"));
45
+ const os_1 = __importDefault(require("os"));
46
+ const storage_1 = require("./core/storage");
47
+ const scanner_1 = require("./core/scanner");
48
+ const compressor_1 = require("./core/compressor");
49
+ const hooks_1 = require("./commands/hooks");
50
+ // ── Helpers ───────────────────────────────────────────────────────
51
+ let passed = 0;
52
+ let failed = 0;
53
+ function assert(label, condition, detail) {
54
+ if (condition) {
55
+ console.log(` ✅ ${label}`);
56
+ passed++;
57
+ }
58
+ else {
59
+ console.log(` ❌ ${label}${detail ? ' — ' + detail : ''}`);
60
+ failed++;
61
+ }
62
+ }
63
+ function section(name) {
64
+ console.log(`\n━━━ ${name} ━━━`);
65
+ }
66
+ // ── Test: Storage ─────────────────────────────────────────────────
67
+ function testStorage() {
68
+ section('Storage Module');
69
+ // getRelayRoot
70
+ const root = (0, storage_1.getRelayRoot)();
71
+ const expected = path_1.default.join(process.env.APPDATA || os_1.default.homedir(), 'relay');
72
+ assert('getRelayRoot() returns OS-aware path', root === expected, `got "${root}"`);
73
+ console.log(` → root = ${root}`);
74
+ // getProjectName (running from e:\relay, should detect "relay" from root package.json)
75
+ const name = (0, storage_1.getProjectName)();
76
+ assert('getProjectName() detects name from package.json or folder', name.length > 0, `got "${name}"`);
77
+ console.log(` → name = ${name}`);
78
+ // getProjectPath
79
+ const projPath = (0, storage_1.getProjectPath)();
80
+ assert('getProjectPath() builds correct path', projPath.includes('projects') && projPath.includes(name));
81
+ console.log(` → path = ${projPath}`);
82
+ // writeProjectMd + readProjectMd
83
+ const testContent = '# Test Project\n\nThis is a test.\n';
84
+ (0, storage_1.writeProjectMd)(testContent);
85
+ const read = (0, storage_1.readProjectMd)();
86
+ assert('writeProjectMd + readProjectMd roundtrip', read === testContent);
87
+ // getProjectMdPath
88
+ const mdPath = (0, storage_1.getProjectMdPath)();
89
+ assert('PROJECT.md file exists on disk', fs_1.default.existsSync(mdPath));
90
+ console.log(` → PROJECT.md at ${mdPath}`);
91
+ // writeConfig + readConfig
92
+ const testConfig = { anthropicApiKey: 'sk-test-key-12345', testFlag: 'hello' };
93
+ (0, storage_1.writeConfig)(testConfig);
94
+ const readConf = (0, storage_1.readConfig)();
95
+ assert('writeConfig + readConfig roundtrip', readConf.anthropicApiKey === 'sk-test-key-12345');
96
+ assert('readConfig preserves all keys', readConf.testFlag === 'hello');
97
+ // Config file exists
98
+ const configPath = path_1.default.join((0, storage_1.getRelayRoot)(), 'config.json');
99
+ assert('config.json exists on disk', fs_1.default.existsSync(configPath));
100
+ }
101
+ // ── Test: Scanner ─────────────────────────────────────────────────
102
+ async function testScanner() {
103
+ section('Scanner Module');
104
+ const cwd = path_1.default.resolve(__dirname, '../../../'); // monorepo root (e:\relay)
105
+ console.log(` → scanning: ${cwd}`);
106
+ const scan = await (0, scanner_1.scanProject)(cwd);
107
+ assert('scan.name is detected', scan.name.length > 0, `got "${scan.name}"`);
108
+ assert('scan.structure is non-empty', scan.structure.length > 50, `${scan.structure.length} chars`);
109
+ assert('scan.dependencies is array', Array.isArray(scan.dependencies));
110
+ assert('scan.dependencies has items', scan.dependencies.length > 0, `found ${scan.dependencies.length} deps`);
111
+ assert('scan.techStack inferred', scan.techStack.length > 0, `[${scan.techStack.join(', ')}]`);
112
+ assert('scan.recentlyModified has files', scan.recentlyModified.length > 0, `${scan.recentlyModified.length} files`);
113
+ assert('scan.fileCount has extensions', Object.keys(scan.fileCount).length > 0);
114
+ // Check .gitignore / skip list is working
115
+ assert('node_modules excluded from structure', !scan.structure.includes('node_modules'));
116
+ assert('.git excluded from structure', !scan.structure.includes('.git/'));
117
+ // Print a sample of what was found
118
+ console.log(`\n 📁 Structure (first 10 lines):`);
119
+ scan.structure.split('\n').slice(0, 10).forEach((l) => console.log(` ${l}`));
120
+ console.log(`\n 📦 Dependencies (first 5):`);
121
+ scan.dependencies.slice(0, 5).forEach((d) => console.log(` - ${d}`));
122
+ console.log(`\n 🔧 Tech Stack: ${scan.techStack.join(', ')}`);
123
+ console.log(`\n 📝 Recently Modified:`);
124
+ scan.recentlyModified.forEach((f) => console.log(` - ${f}`));
125
+ console.log(`\n 📊 File Counts:`);
126
+ Object.entries(scan.fileCount)
127
+ .sort((a, b) => b[1] - a[1])
128
+ .slice(0, 8)
129
+ .forEach(([ext, count]) => console.log(` ${ext}: ${count}`));
130
+ }
131
+ // ── Test: Compressor (fallback only, no API key needed) ───────────
132
+ function testCompressor() {
133
+ section('Compressor Module (fallback truncation)');
134
+ const sampleMd = `# My Project
135
+
136
+ > Relay context
137
+
138
+ ## What we're building
139
+
140
+ A CLI tool for persistent AI context management.
141
+
142
+ ## Tech stack
143
+
144
+ - TypeScript
145
+ - Node.js
146
+ - Commander
147
+
148
+ ## What's in progress
149
+
150
+ Working on the scanner module.
151
+
152
+ ## What's next
153
+
154
+ - Add tests
155
+ - Polish the VS Code extension
156
+
157
+ ## Conventions
158
+
159
+ - Use functional style
160
+ - Keep modules small
161
+ - Use descriptive variable names
162
+
163
+ ## File structure
164
+
165
+ \`\`\`
166
+ relay/
167
+ ├── packages/
168
+ │ ├── cli/
169
+ │ │ ├── src/
170
+ │ │ │ ├── commands/
171
+ │ │ │ └── core/
172
+ │ │ └── package.json
173
+ │ └── vscode-extension/
174
+ └── package.json
175
+ \`\`\`
176
+
177
+ ## What's working
178
+
179
+ - Init command
180
+ - Storage module
181
+
182
+ ## Checkpoints
183
+
184
+ - [2024-01-15 14:32] "initial scaffold"
185
+ - [2024-01-16 10:00] "scanner done"
186
+ `;
187
+ const truncated = (0, compressor_1.truncateContext)(sampleMd);
188
+ assert('truncateContext returns non-empty string', truncated.length > 0);
189
+ assert('truncated is shorter than original', truncated.length <= sampleMd.length, `${truncated.length} vs ${sampleMd.length}`);
190
+ assert('truncated keeps "What we\'re building"', truncated.includes("What we're building"));
191
+ assert('truncated keeps "Tech stack"', truncated.includes('Tech stack'));
192
+ assert('truncated keeps "What\'s in progress"', truncated.includes("What's in progress"));
193
+ assert('truncated keeps "What\'s next"', truncated.includes("What's next"));
194
+ assert('Checkpoints section is dropped', !truncated.includes('Checkpoints'));
195
+ console.log(`\n Truncated output (${truncated.length} chars):`);
196
+ console.log(' ─'.repeat(30));
197
+ truncated.split('\n').forEach((l) => console.log(` ${l}`));
198
+ }
199
+ // ── Test: Checkpoint Command (programmatic) ───────────────────────
200
+ async function testCheckpoint() {
201
+ section('Checkpoint Command');
202
+ // First write a proper PROJECT.md
203
+ const projectMd = `# relay
204
+
205
+ > Relay context
206
+
207
+ ## What we're building
208
+
209
+ A CLI tool for persistent AI context.
210
+
211
+ ## Tech stack
212
+
213
+ - TypeScript
214
+ - Node.js
215
+
216
+ ## What's in progress
217
+
218
+ Working on tests.
219
+ `;
220
+ (0, storage_1.writeProjectMd)(projectMd);
221
+ // Import and run checkpoint
222
+ const { checkpointCommand } = await Promise.resolve().then(() => __importStar(require('./commands/checkpoint')));
223
+ await checkpointCommand('test-checkpoint-alpha');
224
+ // Verify snapshot was created
225
+ const snapshotsDir = path_1.default.join((0, storage_1.getProjectPath)(), 'snapshots');
226
+ assert('snapshots directory exists', fs_1.default.existsSync(snapshotsDir));
227
+ const snapshots = fs_1.default.readdirSync(snapshotsDir);
228
+ const testSnapshot = snapshots.find((f) => f.includes('test-checkpoint-alpha'));
229
+ assert('snapshot file created', !!testSnapshot, testSnapshot || 'not found');
230
+ if (testSnapshot) {
231
+ const snapshotContent = fs_1.default.readFileSync(path_1.default.join(snapshotsDir, testSnapshot), 'utf-8');
232
+ assert('snapshot contains checkpoint header', snapshotContent.includes('# Checkpoint: test-checkpoint-alpha'));
233
+ assert('snapshot contains original PROJECT.md', snapshotContent.includes("What we're building"));
234
+ }
235
+ // Verify PROJECT.md was updated with checkpoint entry
236
+ const updatedMd = (0, storage_1.readProjectMd)();
237
+ assert('PROJECT.md has Checkpoints section', updatedMd.includes('## Checkpoints'));
238
+ assert('PROJECT.md has checkpoint entry', updatedMd.includes('"test-checkpoint-alpha"'));
239
+ }
240
+ // ── Test: Sync Command (programmatic) ─────────────────────────────
241
+ async function testSync() {
242
+ section('Sync Command');
243
+ // Write a base PROJECT.md first
244
+ const baseMd = `# relay
245
+
246
+ > Relay context
247
+
248
+ ## What we're building
249
+
250
+ A CLI tool for persistent AI context. This should NOT be overwritten by sync.
251
+
252
+ ## Tech stack
253
+
254
+ - TypeScript
255
+
256
+ ## What's in progress
257
+
258
+ Manual notes here.
259
+
260
+ ## What's next
261
+
262
+ - Ship V1
263
+
264
+ ## Conventions
265
+
266
+ - Keep it simple
267
+
268
+ ## File structure
269
+
270
+ _(will be populated by sync)_
271
+
272
+ ## What's working
273
+
274
+ - Everything
275
+
276
+ ## What we're NOT building
277
+
278
+ - Cloud sync
279
+ `;
280
+ (0, storage_1.writeProjectMd)(baseMd);
281
+ // Run sync from the monorepo root
282
+ const origCwd = process.cwd();
283
+ process.chdir(path_1.default.resolve(__dirname, '../../../'));
284
+ const { syncCommand } = await Promise.resolve().then(() => __importStar(require('./commands/sync')));
285
+ await syncCommand();
286
+ process.chdir(origCwd);
287
+ // Verify
288
+ const synced = (0, storage_1.readProjectMd)();
289
+ assert('Synced PROJECT.md is non-empty', synced.length > 0);
290
+ assert('Preserved "What we\'re building" content', synced.includes('This should NOT be overwritten by sync'));
291
+ assert('Preserved "Conventions"', synced.includes('Keep it simple'));
292
+ assert('Preserved "What\'s next"', synced.includes('Ship V1'));
293
+ assert('Preserved "What we\'re NOT building"', synced.includes('Cloud sync'));
294
+ assert('File structure was updated', !synced.includes('will be populated by sync'));
295
+ assert('Tech stack was updated', synced.includes('TypeScript'));
296
+ assert('Recently modified section present', synced.includes('Recently modified'));
297
+ assert('Last synced timestamp added', synced.includes('Last synced'));
298
+ console.log(`\n Synced PROJECT.md (first 30 lines):`);
299
+ console.log(' ─'.repeat(30));
300
+ synced.split('\n').slice(0, 30).forEach((l) => console.log(` ${l}`));
301
+ }
302
+ // ── Test: Inject Command (raw mode, programmatic) ─────────────────
303
+ async function testInject() {
304
+ section('Inject Command (--raw mode)');
305
+ // Capture console.log output
306
+ const logs = [];
307
+ const origLog = console.log;
308
+ console.log = (...args) => {
309
+ logs.push(args.map(String).join(' '));
310
+ };
311
+ const { injectCommand } = await Promise.resolve().then(() => __importStar(require('./commands/inject')));
312
+ await injectCommand({ raw: true });
313
+ console.log = origLog;
314
+ const output = logs.join('\n');
315
+ assert('Output contains RELAY CONTEXT header', output.includes('--- RELAY CONTEXT:'));
316
+ assert('Output contains END RELAY CONTEXT', output.includes('--- END RELAY CONTEXT ---'));
317
+ assert('Output contains project content', output.includes("What we're building"));
318
+ console.log(`\n Inject output (first 10 lines):`);
319
+ console.log(' ─'.repeat(30));
320
+ output.split('\n').slice(0, 10).forEach((l) => console.log(` ${l}`));
321
+ }
322
+ // ── Test: Hooks (install, status, overwrite, uninstall) ────────────
323
+ async function testHooks() {
324
+ section('Hooks Module');
325
+ const origCwd = process.cwd();
326
+ const tmpDir = path_1.default.join(os_1.default.tmpdir(), `relay-hooks-test-${Date.now()}`);
327
+ const gitHooksDir = path_1.default.join(tmpDir, '.git', 'hooks');
328
+ // Set up temp git repo
329
+ fs_1.default.mkdirSync(gitHooksDir, { recursive: true });
330
+ process.chdir(tmpDir);
331
+ try {
332
+ // ── Test 1: status shows nothing installed ─────────────────────
333
+ const statusBefore = (0, hooks_1.getHooksStatus)();
334
+ assert('status: 3 hooks returned', statusBefore.length === 3, `got ${statusBefore.length}`);
335
+ assert('status: none installed initially', statusBefore.every(s => !s.exists));
336
+ // ── Test 2: install writes all 3 hooks ────────────────────────
337
+ const { installed, skipped } = (0, hooks_1.installHooks)();
338
+ assert('install: all 3 installed', installed.length === 3, `installed: [${installed.join(', ')}]`);
339
+ assert('install: none skipped', skipped.length === 0, `skipped: [${skipped.join(', ')}]`);
340
+ // Verify files on disk
341
+ for (const hookName of ['post-commit', 'post-checkout', 'post-merge']) {
342
+ const hookPath = path_1.default.join(gitHooksDir, hookName);
343
+ assert(`install: ${hookName} file exists`, fs_1.default.existsSync(hookPath));
344
+ const content = fs_1.default.readFileSync(hookPath, 'utf-8');
345
+ assert(`install: ${hookName} has relay marker`, content.includes('# relay-managed'));
346
+ }
347
+ // ── Test 3: status shows relay-managed ─────────────────────────
348
+ const statusAfterInstall = (0, hooks_1.getHooksStatus)();
349
+ assert('status: all 3 exist after install', statusAfterInstall.every(s => s.exists));
350
+ assert('status: all 3 relay-managed', statusAfterInstall.every(s => s.relayManaged));
351
+ // ── Test 4: re-install overwrites relay-managed hooks ──────────
352
+ // Corrupt a hook to verify it gets replaced
353
+ const postCommitPath = path_1.default.join(gitHooksDir, 'post-commit');
354
+ fs_1.default.writeFileSync(postCommitPath, '# relay-managed\nOLD CONTENT\n', 'utf-8');
355
+ const reinstall = (0, hooks_1.installHooks)();
356
+ assert('reinstall: post-commit re-installed', reinstall.installed.includes('post-commit'));
357
+ assert('reinstall: still 0 skipped', reinstall.skipped.length === 0);
358
+ const freshContent = fs_1.default.readFileSync(postCommitPath, 'utf-8');
359
+ assert('reinstall: old content replaced', !freshContent.includes('OLD CONTENT'));
360
+ assert('reinstall: new content has checkpoint', freshContent.includes('relay checkpoint'));
361
+ // ── Test 5: install skips non-relay-managed hooks ───────────────
362
+ fs_1.default.writeFileSync(postCommitPath, '#!/bin/sh\necho "custom hook"\n', 'utf-8');
363
+ const installWithConflict = (0, hooks_1.installHooks)();
364
+ assert('conflict: post-commit skipped', installWithConflict.skipped.includes('post-commit'));
365
+ assert('conflict: other 2 installed', installWithConflict.installed.length === 2);
366
+ // Status should show it as not relay-managed
367
+ const statusWithConflict = (0, hooks_1.getHooksStatus)();
368
+ const postCommitStatus = statusWithConflict.find(s => s.name === 'post-commit');
369
+ assert('status: post-commit exists but not relay-managed', postCommitStatus.exists && !postCommitStatus.relayManaged);
370
+ // ── Test 6: uninstall removes only relay-managed hooks ─────────
371
+ const removed = (0, hooks_1.uninstallHooks)();
372
+ assert('uninstall: 2 hooks removed (not post-commit)', removed.length === 2, `removed: [${removed.join(', ')}]`);
373
+ assert('uninstall: post-commit NOT removed', !removed.includes('post-commit'));
374
+ // post-commit still exists on disk
375
+ assert('uninstall: non-relay hook file remains', fs_1.default.existsSync(postCommitPath));
376
+ // post-checkout and post-merge are gone
377
+ assert('uninstall: post-checkout removed', !fs_1.default.existsSync(path_1.default.join(gitHooksDir, 'post-checkout')));
378
+ assert('uninstall: post-merge removed', !fs_1.default.existsSync(path_1.default.join(gitHooksDir, 'post-merge')));
379
+ // ── Test 7: status reflects partial state ──────────────────────
380
+ const statusPartial = (0, hooks_1.getHooksStatus)();
381
+ const existing = statusPartial.filter(s => s.exists);
382
+ assert('status: only 1 hook remains', existing.length === 1);
383
+ assert('status: remaining is post-commit', existing[0].name === 'post-commit');
384
+ // ── Test 8: double-uninstall is safe ───────────────────────────
385
+ const removedAgain = (0, hooks_1.uninstallHooks)();
386
+ assert('double-uninstall: nothing removed', removedAgain.length === 0);
387
+ // ── Test 9: hook content correctness ─────────────────────────────
388
+ // Clean up the custom hook and re-install to verify content
389
+ fs_1.default.unlinkSync(postCommitPath);
390
+ (0, hooks_1.installHooks)();
391
+ const postCheckoutContent = fs_1.default.readFileSync(path_1.default.join(gitHooksDir, 'post-checkout'), 'utf-8');
392
+ assert('content: post-checkout has BRANCH_SWITCH check', postCheckoutContent.includes('BRANCH_SWITCH'));
393
+ assert('content: post-checkout calls relay sync', postCheckoutContent.includes('relay sync'));
394
+ const postMergeContent = fs_1.default.readFileSync(path_1.default.join(gitHooksDir, 'post-merge'), 'utf-8');
395
+ assert('content: post-merge calls relay sync', postMergeContent.includes('relay sync'));
396
+ assert('content: post-merge calls relay checkpoint', postMergeContent.includes('relay checkpoint'));
397
+ // Final cleanup
398
+ (0, hooks_1.uninstallHooks)();
399
+ }
400
+ finally {
401
+ // Restore cwd and clean up temp dir
402
+ process.chdir(origCwd);
403
+ fs_1.default.rmSync(tmpDir, { recursive: true, force: true });
404
+ }
405
+ }
406
+ // ── Run All Tests ─────────────────────────────────────────────────
407
+ async function main() {
408
+ console.log('╔══════════════════════════════════════╗');
409
+ console.log('║ RELAY CLI — End-to-End Tests ║');
410
+ console.log('╚══════════════════════════════════════╝');
411
+ try {
412
+ testStorage();
413
+ await testScanner();
414
+ testCompressor();
415
+ await testCheckpoint();
416
+ await testSync();
417
+ await testInject();
418
+ await testHooks();
419
+ }
420
+ catch (err) {
421
+ console.log(`\n💥 Unexpected error: ${err}`);
422
+ if (err instanceof Error) {
423
+ console.log(err.stack);
424
+ }
425
+ failed++;
426
+ }
427
+ console.log('\n╔══════════════════════════════════════╗');
428
+ console.log(`║ Results: ${passed} passed, ${failed} failed${' '.repeat(Math.max(0, 13 - String(passed).length - String(failed).length))}║`);
429
+ console.log('╚══════════════════════════════════════╝\n');
430
+ process.exit(failed > 0 ? 1 : 0);
431
+ }
432
+ main();
433
+ //# sourceMappingURL=test-relay.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"test-relay.js","sourceRoot":"","sources":["../src/test-relay.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,32 @@
1
+ {
2
+ "name": "@madkid/relay-ctx",
3
+ "version": "0.1.0",
4
+ "description": "Persistent AI context across sessions and tools",
5
+ "main": "dist/index.js",
6
+ "bin": {
7
+ "relay": "dist/index.js"
8
+ },
9
+ "files": [
10
+ "dist"
11
+ ],
12
+ "scripts": {
13
+ "build": "tsc",
14
+ "dev": "tsc --watch",
15
+ "start": "node dist/index.js",
16
+ "prepublishOnly": "npm run build"
17
+ },
18
+ "dependencies": {
19
+ "commander": "^11.0.0",
20
+ "chalk": "^5.3.0",
21
+ "inquirer": "^9.2.0",
22
+ "@anthropic-ai/sdk": "^0.20.0",
23
+ "glob": "^10.3.0",
24
+ "ignore": "^5.3.0",
25
+ "ora": "^8.0.0"
26
+ },
27
+ "devDependencies": {
28
+ "@types/node": "^20.0.0",
29
+ "@types/inquirer": "^9.0.0",
30
+ "typescript": "^5.3.0"
31
+ }
32
+ }