specmem-hardwicksoftware 3.7.34 → 3.7.36

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 (56) hide show
  1. package/CHANGELOG.md +34 -0
  2. package/README.md +11 -15
  3. package/bin/specmem-console.cjs +839 -51
  4. package/claude-hooks/agent-chooser-hook.js +6 -6
  5. package/claude-hooks/agent-loading-hook.cjs +16 -16
  6. package/claude-hooks/agent-loading-hook.js +18 -18
  7. package/claude-hooks/agent-type-matcher.js +1 -1
  8. package/claude-hooks/background-completion-silencer.js +1 -1
  9. package/claude-hooks/file-claim-enforcer.cjs +37 -36
  10. package/claude-hooks/output-cleaner.cjs +1 -1
  11. package/claude-hooks/settings.json +27 -3
  12. package/claude-hooks/specmem-search-enforcer.cjs +2 -11
  13. package/claude-hooks/specmem-team-member-inject.js +1 -1
  14. package/claude-hooks/specmem-unified-hook.py +1 -1
  15. package/claude-hooks/subagent-loading-hook.cjs +1 -1
  16. package/claude-hooks/task-progress-hook.cjs +7 -7
  17. package/claude-hooks/task-progress-hook.js +3 -3
  18. package/claude-hooks/team-comms-enforcer.cjs +49 -47
  19. package/dist/claude-sessions/sessionParser.js +5 -0
  20. package/dist/codebase/codebaseIndexer.js +48 -17
  21. package/dist/codebase/exclusions.js +3 -4
  22. package/dist/codebase/index.js +4 -0
  23. package/dist/codebase/pdfExtractor.js +298 -0
  24. package/dist/dashboard/api/taskTeamMembers.js +2 -2
  25. package/dist/db/bigBrainMigrations.js +29 -0
  26. package/dist/hooks/hookManager.js +4 -4
  27. package/dist/hooks/teamFramingCli.js +1 -1
  28. package/dist/hooks/teamMemberPrepromptHook.js +5 -5
  29. package/dist/init/claudeConfigInjector.js +2 -2
  30. package/dist/mcp/compactionProxy.js +834 -186
  31. package/dist/mcp/compactionProxyDaemon.js +112 -37
  32. package/dist/mcp/contextVault.js +439 -0
  33. package/dist/mcp/embeddingServerManager.js +61 -1
  34. package/dist/mcp/mcpProtocolHandler.js +6 -1
  35. package/dist/mcp/miniCOTServerManager.js +82 -8
  36. package/dist/mcp/specMemServer.js +45 -10
  37. package/dist/mcp/toolRegistry.js +6 -0
  38. package/dist/startup/startupIndexing.js +14 -0
  39. package/dist/team-members/taskOrchestrator.js +3 -3
  40. package/dist/team-members/taskTeamMemberLogger.js +2 -2
  41. package/dist/tools/goofy/deployTeamMember.js +3 -3
  42. package/dist/tools/goofy/digInTheVault.js +81 -0
  43. package/dist/tools/goofy/stashTheGoods.js +56 -0
  44. package/dist/tools/teamMemberDeployer.js +2 -2
  45. package/dist/watcher/changeHandler.js +65 -8
  46. package/dist/watcher/changeQueue.js +20 -1
  47. package/dist/watcher/index.js +37 -2
  48. package/embedding-sandbox/mini-cot-service.py +11 -13
  49. package/embedding-sandbox/pdf-text-extract.py +208 -0
  50. package/package.json +1 -1
  51. package/scripts/deploy-hooks.cjs +2 -2
  52. package/scripts/global-postinstall.cjs +2 -2
  53. package/scripts/specmem-init.cjs +130 -36
  54. package/specmem/model-config.json +6 -6
  55. package/specmem/supervisord.conf +1 -1
  56. package/svg-sections/readme-token-compaction.svg +246 -0
@@ -1291,49 +1291,126 @@ fi
1291
1291
  }
1292
1292
  }
1293
1293
 
1294
- // ── Step 3b: Add ANTHROPIC_BASE_URL proxy routing to bashrc ─────────────
1295
- // Always routes Claude Code API calls through the compaction proxy.
1296
- // Proxy runs in passthrough mode when disabled seamless on/off toggling.
1297
- // Does NOT touch ANTHROPIC_API_KEY only sets the base URL.
1298
- const proxyMarker = '# specmem-proxy-env';
1294
+ // ── Step 3b: Start compaction proxy daemon ─────────────────────────────
1295
+ // CRITICAL: Proxy MUST be confirmed alive BEFORE setting ANTHROPIC_BASE_URL.
1296
+ // If we set the env var pointing at a dead proxy, Claude gets ECONNREFUSED
1297
+ // on every API call and is completely bricked. Daemon first, env var second.
1299
1298
  const defaultProxyPort = process.env.COMPACTION_PROXY_PORT || '4080';
1300
- let hasProxyFix = false;
1301
- try {
1302
- if (fs.existsSync(bashrcPath)) {
1303
- const currentBashrc = fs.readFileSync(bashrcPath, 'utf8');
1304
- hasProxyFix = currentBashrc.includes(proxyMarker);
1305
- // If old conditional version exists, replace it with the unconditional one
1306
- if (hasProxyFix && currentBashrc.includes('.compaction-proxy-port')) {
1307
- const cleaned = currentBashrc.replace(/\n?# specmem-proxy-env\n(?:# [^\n]*\n)*if \[ -f "\$HOME\/\.claude\/\.compaction-proxy-port" \];[\s\S]*?fi\n?/g, '');
1308
- fs.writeFileSync(bashrcPath, cleaned);
1309
- hasProxyFix = false; // Will re-add the new version below
1310
- initLog('Replaced old conditional proxy bashrc block with unconditional version');
1299
+ let proxyAlive = false;
1300
+ let proxyPort = defaultProxyPort;
1301
+ {
1302
+ const pidFile = path.join(os.homedir(), '.claude', '.compaction-proxy.pid');
1303
+ const portFile = path.join(os.homedir(), '.claude', '.compaction-proxy-port');
1304
+ // Kill any existing proxy daemon
1305
+ try {
1306
+ if (fs.existsSync(pidFile)) {
1307
+ let pid;
1308
+ try {
1309
+ const pidData = JSON.parse(fs.readFileSync(pidFile, 'utf8'));
1310
+ pid = pidData.pid || parseInt(pidData);
1311
+ } catch { pid = parseInt(fs.readFileSync(pidFile, 'utf8').trim()); }
1312
+ if (pid > 0) {
1313
+ try { process.kill(pid, 0); process.kill(pid, 'SIGTERM'); initLog(`Killed stale proxy daemon PID ${pid}`); } catch {}
1314
+ }
1315
+ try { fs.unlinkSync(pidFile); } catch {}
1311
1316
  }
1312
- }
1313
- } catch (e) { /* no .bashrc */ }
1314
-
1315
- if (!hasProxyFix) {
1316
- const proxyFix = `
1317
- ${proxyMarker}
1318
- # SpecMem: Always route API calls through compaction proxy (passthrough when disabled)
1319
- export ANTHROPIC_BASE_URL="http://127.0.0.1:\${COMPACTION_PROXY_PORT:-${defaultProxyPort}}"
1320
- `;
1317
+ if (fs.existsSync(portFile)) try { fs.unlinkSync(portFile); } catch {}
1318
+ } catch {}
1319
+ // Spawn fresh proxy daemon
1321
1320
  try {
1322
- fs.appendFileSync(bashrcPath, proxyFix);
1323
- result.proxyEnvFixed = true;
1324
- result.fixed = true;
1325
- initLog('Added unconditional ANTHROPIC_BASE_URL proxy routing to .bashrc');
1321
+ const daemonPath = require.resolve('specmem-hardwicksoftware/dist/mcp/compactionProxyDaemon.js');
1322
+ const { spawn } = require('child_process');
1323
+ const child = spawn(process.execPath, [daemonPath], {
1324
+ detached: true, stdio: 'ignore', env: { ...process.env, SPECMEM_DAEMON: '1' }
1325
+ });
1326
+ child.unref();
1327
+ // Wait for daemon to write port file (up to 5s)
1328
+ const portWaitFile = path.join(os.homedir(), '.claude', '.compaction-proxy-port');
1329
+ for (let i = 0; i < 50; i++) {
1330
+ if (fs.existsSync(portWaitFile)) {
1331
+ const p = fs.readFileSync(portWaitFile, 'utf8').trim();
1332
+ if (p && parseInt(p) > 0) {
1333
+ proxyPort = p;
1334
+ // Verify the daemon process is still alive (signal 0 = existence check)
1335
+ try { process.kill(child.pid, 0); proxyAlive = true; } catch {}
1336
+ initLog(`Proxy daemon port file appeared (port ${p}, PID ${child.pid}, alive=${proxyAlive})`);
1337
+ break;
1338
+ }
1339
+ }
1340
+ const { execSync: _es } = require('child_process');
1341
+ _es('sleep 0.1', { stdio: 'ignore' });
1342
+ }
1343
+ if (proxyAlive) {
1344
+ console.log(`${c.green}✓ Compaction proxy daemon started (port ${proxyPort})${c.reset}`);
1345
+ } else {
1346
+ console.log(`${c.yellow}⚠ Compaction proxy daemon failed to start — Claude will connect directly to Anthropic${c.reset}`);
1347
+ }
1326
1348
  } catch (e) {
1327
- initLog('Failed to write .bashrc proxy fix', e);
1349
+ initLog(`Failed to spawn proxy daemon: ${e.message}`);
1350
+ console.log(`${c.yellow}⚠ Could not start proxy daemon: ${e.message}${c.reset}`);
1328
1351
  }
1329
1352
  }
1330
1353
 
1331
- // Always set for current session proxy is always in the path
1354
+ // ── Step 3c: Configure ANTHROPIC_BASE_URL routing ─────────────────────
1355
+ // .bashrc: conditional on port file (safe for future shells — no routing to dead proxy)
1356
+ // process.env: only set if proxy confirmed alive (safe for THIS session)
1357
+ // Respects `specmem proxy enable/disable` — disabled proxy still runs in passthrough,
1358
+ // port file still exists, so traffic still routes through it (just uncompressed).
1332
1359
  {
1333
- const proxyUrl = `http://127.0.0.1:${defaultProxyPort}`;
1334
- if (process.env.ANTHROPIC_BASE_URL !== proxyUrl) {
1360
+ const proxyMarker = '# specmem-proxy-env';
1361
+ let hasProxyFix = false;
1362
+ let needsUpgrade = false;
1363
+ try {
1364
+ if (fs.existsSync(bashrcPath)) {
1365
+ const bashrc = fs.readFileSync(bashrcPath, 'utf8');
1366
+ hasProxyFix = bashrc.includes(proxyMarker);
1367
+ // Detect old unconditional version (no port file check) — needs upgrade to conditional
1368
+ if (hasProxyFix && !bashrc.includes('.compaction-proxy-port')) {
1369
+ needsUpgrade = true;
1370
+ }
1371
+ }
1372
+ } catch {}
1373
+
1374
+ // Replace unconditional with safe conditional version
1375
+ if (needsUpgrade) {
1376
+ try {
1377
+ const bashrc = fs.readFileSync(bashrcPath, 'utf8');
1378
+ const cleaned = bashrc.replace(/\n?# specmem-proxy-env\n(?:[^\n]+\n)+/, '\n');
1379
+ fs.writeFileSync(bashrcPath, cleaned);
1380
+ hasProxyFix = false;
1381
+ initLog('Removed unconditional proxy block from .bashrc (upgrading to conditional)');
1382
+ } catch {}
1383
+ }
1384
+
1385
+ // Write conditional .bashrc block — only routes when port file exists
1386
+ // This means: proxy running (enabled OR disabled/passthrough) → routes through proxy
1387
+ // proxy not running (dead/never started) → Claude talks directly to Anthropic
1388
+ if (!hasProxyFix) {
1389
+ const proxyFix = `
1390
+ ${proxyMarker}
1391
+ # SpecMem: Route API calls through compaction proxy when it's running
1392
+ if [ -f "\$HOME/.claude/.compaction-proxy-port" ]; then
1393
+ export ANTHROPIC_BASE_URL="http://127.0.0.1:\$(cat "\$HOME/.claude/.compaction-proxy-port")"
1394
+ fi
1395
+ `;
1396
+ try {
1397
+ fs.appendFileSync(bashrcPath, proxyFix);
1398
+ result.proxyEnvFixed = true;
1399
+ result.fixed = true;
1400
+ initLog('Added conditional ANTHROPIC_BASE_URL proxy routing to .bashrc');
1401
+ } catch (e) {
1402
+ initLog('Failed to write .bashrc proxy fix', e);
1403
+ }
1404
+ }
1405
+
1406
+ // Current session: only set if proxy is confirmed alive RIGHT NOW
1407
+ if (proxyAlive) {
1408
+ const proxyUrl = `http://127.0.0.1:${proxyPort}`;
1335
1409
  process.env.ANTHROPIC_BASE_URL = proxyUrl;
1336
1410
  initLog(`Set ANTHROPIC_BASE_URL=${proxyUrl} for current session`);
1411
+ } else {
1412
+ delete process.env.ANTHROPIC_BASE_URL;
1413
+ initLog('Proxy not alive — ANTHROPIC_BASE_URL not set, Claude connects directly to Anthropic');
1337
1414
  }
1338
1415
  }
1339
1416
 
@@ -7190,6 +7267,11 @@ async function launchScreenSessions(projectPath, ui) {
7190
7267
  return result;
7191
7268
  }
7192
7269
 
7270
+ // Ensure xclip is available for TUI clipboard support
7271
+ try { execSync('which xclip', { stdio: 'ignore' }); } catch {
7272
+ try { execSync('apt-get install -y xclip 2>/dev/null', { stdio: 'ignore', timeout: 30000 }); } catch {}
7273
+ }
7274
+
7193
7275
  // Get current running screens (wipe dead ones first)
7194
7276
  ui.setStatus('Detecting running sessions...');
7195
7277
  try { execSync('screen -wipe 2>/dev/null || true', { stdio: 'ignore' }); } catch {}
@@ -7263,9 +7345,21 @@ async function launchScreenSessions(projectPath, ui) {
7263
7345
  // Uses screen hardcopy to tmpfs on-demand instead of continuous logging
7264
7346
  // -h 5000 sets scrollback buffer to 5000 lines for hardcopy capture
7265
7347
  const claudeBin = getClaudeBinary();
7266
- // Always set ANTHROPIC_BASE_URL proxy runs in passthrough mode when disabled
7267
- const proxyPort = process.env.COMPACTION_PROXY_PORT || '4080';
7268
- const proxyEnv = `ANTHROPIC_BASE_URL="http://127.0.0.1:${proxyPort}" `;
7348
+ // Only route through proxy if it's confirmed alive (port file exists)
7349
+ // Prevents launching Claude pointed at a dead proxy (ECONNREFUSED on all API calls)
7350
+ const proxyPortFile = path.join(os.homedir(), '.claude', '.compaction-proxy-port');
7351
+ let proxyEnv = '';
7352
+ try {
7353
+ if (fs.existsSync(proxyPortFile)) {
7354
+ const pPort = fs.readFileSync(proxyPortFile, 'utf8').trim();
7355
+ if (pPort && parseInt(pPort) > 0) {
7356
+ proxyEnv = `ANTHROPIC_BASE_URL="http://127.0.0.1:${pPort}" `;
7357
+ }
7358
+ }
7359
+ } catch {}
7360
+ if (!proxyEnv) {
7361
+ initLog('Proxy port file not found at screen launch — Claude will connect directly to Anthropic');
7362
+ }
7269
7363
  execSync(`screen -h 5000 -dmS ${claudeSession} bash -c 'cd "${projectPath}" && ${proxyEnv}SPECMEM_DASHBOARD=1 "${claudeBin}" 2>&1; exec bash'`, { stdio: 'ignore' });
7270
7364
  await sleep(300);
7271
7365
 
@@ -35,12 +35,12 @@
35
35
  },
36
36
  "resources": {
37
37
  "cpuMin": 10,
38
- "cpuMax": 30,
38
+ "cpuMax": 50,
39
39
  "cpuCoreMin": 1,
40
- "cpuCoreMax": 4,
41
- "ramMinMb": 4000,
42
- "ramMaxMb": 15000,
43
- "updatedAt": "2026-02-24T20:01:48.721Z"
40
+ "cpuCoreMax": 5,
41
+ "ramMinMb": 6000,
42
+ "ramMaxMb": 19500,
43
+ "updatedAt": "2026-03-01T19:38:15.430Z"
44
44
  },
45
45
  "resourcePool": {
46
46
  "embedding": {
@@ -95,7 +95,7 @@
95
95
  },
96
96
  "heavyOps": {
97
97
  "enabled": true,
98
- "enabledAt": "2026-02-26T14:18:50.747Z",
98
+ "enabledAt": "2026-03-01T13:41:50.330Z",
99
99
  "originalBatchSize": 32,
100
100
  "batchSizeMultiplier": 2,
101
101
  "throttleReduction": 0.2
@@ -1,6 +1,6 @@
1
1
  ; ============================================
2
2
  ; SPECMEM BRAIN CONTAINER - DYNAMIC SUPERVISORD CONFIG
3
- ; Generated by specmem-init at 2026-02-26T20:07:11.788Z
3
+ ; Generated by specmem-init at 2026-03-02T00:36:22.804Z
4
4
  ; Thread counts from model-config.json resourcePool
5
5
  ; ============================================
6
6
 
@@ -0,0 +1,246 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 800 1020" width="800" height="1020">
2
+ <defs>
3
+ <linearGradient id="bgGrad" x1="0%" y1="0%" x2="100%" y2="100%">
4
+ <stop offset="0%" style="stop-color:#0d1117"/>
5
+ <stop offset="100%" style="stop-color:#161b22"/>
6
+ </linearGradient>
7
+ <linearGradient id="cardGrad" x1="0%" y1="0%" x2="100%" y2="100%">
8
+ <stop offset="0%" style="stop-color:#1c2128;stop-opacity:0.9"/>
9
+ <stop offset="100%" style="stop-color:#21262d;stop-opacity:0.85"/>
10
+ </linearGradient>
11
+ <linearGradient id="titleGrad" x1="0%" y1="0%" x2="100%" y2="0%">
12
+ <stop offset="0%" style="stop-color:#00bfff"/>
13
+ <stop offset="50%" style="stop-color:#a855f7"/>
14
+ <stop offset="100%" style="stop-color:#00bfff"/>
15
+ </linearGradient>
16
+ <linearGradient id="cyanPurple" x1="0%" y1="0%" x2="100%" y2="0%">
17
+ <stop offset="0%" style="stop-color:#00bfff"/>
18
+ <stop offset="100%" style="stop-color:#a855f7"/>
19
+ </linearGradient>
20
+ <linearGradient id="greenGrad" x1="0%" y1="0%" x2="100%" y2="0%">
21
+ <stop offset="0%" style="stop-color:#22c55e"/>
22
+ <stop offset="100%" style="stop-color:#4ade80"/>
23
+ </linearGradient>
24
+ <linearGradient id="orangeGrad" x1="0%" y1="0%" x2="100%" y2="0%">
25
+ <stop offset="0%" style="stop-color:#f59e0b"/>
26
+ <stop offset="100%" style="stop-color:#f78534"/>
27
+ </linearGradient>
28
+ <filter id="glow" x="-20%" y="-20%" width="140%" height="140%">
29
+ <feGaussianBlur in="SourceAlpha" stdDeviation="3" result="blur"/>
30
+ <feFlood flood-color="#00bfff" flood-opacity="0.3"/>
31
+ <feComposite in2="blur" operator="in"/>
32
+ <feMerge><feMergeNode/><feMergeNode in="SourceGraphic"/></feMerge>
33
+ </filter>
34
+ <filter id="glowGreen" x="-20%" y="-20%" width="140%" height="140%">
35
+ <feGaussianBlur in="SourceAlpha" stdDeviation="4" result="blur"/>
36
+ <feFlood flood-color="#22c55e" flood-opacity="0.4"/>
37
+ <feComposite in2="blur" operator="in"/>
38
+ <feMerge><feMergeNode/><feMergeNode in="SourceGraphic"/></feMerge>
39
+ </filter>
40
+ </defs>
41
+
42
+ <!-- Background -->
43
+ <rect width="800" height="1020" rx="16" ry="16" fill="url(#bgGrad)"/>
44
+ <rect width="800" height="1020" rx="16" ry="16" fill="none" stroke="url(#cyanPurple)" stroke-width="1" stroke-opacity="0.2"/>
45
+
46
+ <!-- Title Section -->
47
+ <text x="400" y="36" text-anchor="middle" font-family="system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif" font-size="20" font-weight="700" fill="url(#titleGrad)">Token Compaction Pipeline</text>
48
+ <text x="400" y="56" text-anchor="middle" font-family="system-ui, sans-serif" font-size="11" fill="#6e7681">5-layer MITM proxy between Claude Code and Anthropic API. Every request gets optimized.</text>
49
+
50
+ <!-- Big stat banner -->
51
+ <rect x="40" y="72" width="720" height="70" rx="12" fill="url(#cardGrad)" stroke="#22c55e" stroke-width="1.5" filter="url(#glowGreen)"/>
52
+ <text x="200" y="103" text-anchor="middle" font-family="system-ui, sans-serif" font-size="36" font-weight="800" fill="#22c55e">~60%</text>
53
+ <text x="200" y="125" text-anchor="middle" font-family="system-ui, sans-serif" font-size="11" fill="#6e7681">input token reduction</text>
54
+ <text x="400" y="103" text-anchor="middle" font-family="system-ui, sans-serif" font-size="36" font-weight="800" fill="#00bfff">5</text>
55
+ <text x="400" y="125" text-anchor="middle" font-family="system-ui, sans-serif" font-size="11" fill="#6e7681">compression layers</text>
56
+ <text x="600" y="103" text-anchor="middle" font-family="system-ui, sans-serif" font-size="36" font-weight="800" fill="#a855f7">0ms</text>
57
+ <text x="600" y="125" text-anchor="middle" font-family="system-ui, sans-serif" font-size="11" fill="#6e7681">added latency (async)</text>
58
+
59
+ <!-- Pipeline flow label -->
60
+ <text x="400" y="170" text-anchor="middle" font-family="system-ui, sans-serif" font-size="14" font-weight="600" fill="#e6edf3">Request Flow: Claude Code &#x2192; Compaction Proxy &#x2192; Anthropic API</text>
61
+
62
+ <!-- ═══════════════════════════════════════════════════════ -->
63
+ <!-- LAYER 1: Context Vault (y=188, h=126) -->
64
+ <!-- ═══════════════════════════════════════════════════════ -->
65
+ <g transform="translate(30, 188)">
66
+ <rect width="740" height="126" rx="12" fill="url(#cardGrad)" stroke="#22c55e" stroke-width="1.5"/>
67
+ <rect width="740" height="3" rx="1.5" fill="url(#greenGrad)"/>
68
+
69
+ <circle cx="36" cy="30" r="14" fill="none" stroke="#22c55e" stroke-width="1.5" stroke-opacity="0.7"/>
70
+ <text x="36" y="35" text-anchor="middle" font-family="system-ui, sans-serif" font-size="13" font-weight="700" fill="#22c55e">1</text>
71
+
72
+ <text x="60" y="34" font-family="system-ui, sans-serif" font-size="14" font-weight="700" fill="#4ade80">&#x1F3E6; Context Vault</text>
73
+ <rect x="210" y="20" width="90" height="20" rx="10" fill="#22c55e" fill-opacity="0.15" stroke="#22c55e" stroke-width="0.8" stroke-opacity="0.4"/>
74
+ <text x="255" y="34" text-anchor="middle" font-family="'SF Mono', 'Fira Code', Consolas, monospace" font-size="10" font-weight="600" fill="#4ade80">99% savings</text>
75
+
76
+ <text font-family="system-ui, sans-serif" font-size="11" fill="#8b949e">
77
+ <tspan x="24" y="58">Tool results larger than 5KB are auto-stashed to PostgreSQL with full-text indexing (tsvector).</tspan>
78
+ <tspan x="24" dy="15">Claude receives a compact receipt (~800 bytes) with preview, vocabulary, and retrieval commands.</tspan>
79
+ <tspan x="24" dy="15">On-demand retrieval via BM25-ranked search. 24h TTL with automatic expiry.</tspan>
80
+ </text>
81
+
82
+ <rect x="24" y="106" width="80" height="14" rx="3" fill="#ef4444" fill-opacity="0.2" stroke="#ef4444" stroke-width="0.8" stroke-opacity="0.4"/>
83
+ <text x="64" y="117" text-anchor="middle" font-family="'SF Mono', monospace" font-size="8" fill="#f87171">315KB result</text>
84
+ <text x="118" y="117" font-family="system-ui, sans-serif" font-size="11" fill="#484f58">&#x2192;</text>
85
+ <rect x="138" y="106" width="68" height="14" rx="3" fill="#22c55e" fill-opacity="0.2" stroke="#22c55e" stroke-width="0.8" stroke-opacity="0.4"/>
86
+ <text x="172" y="117" text-anchor="middle" font-family="'SF Mono', monospace" font-size="8" fill="#4ade80">800B receipt</text>
87
+ <text x="225" y="117" font-family="'SF Mono', monospace" font-size="8" fill="#484f58">stash_the_goods() / dig_in_the_vault()</text>
88
+ </g>
89
+
90
+ <!-- Connector 1→2 -->
91
+ <line x1="66" y1="314" x2="66" y2="330" stroke="#30363d" stroke-width="2" stroke-dasharray="3,3"/>
92
+ <polygon points="62,328 66,336 70,328" fill="#30363d"/>
93
+
94
+ <!-- ═══════════════════════════════════════════════════════ -->
95
+ <!-- LAYER 2: Steno + YCC (y=336, h=180) -->
96
+ <!-- ═══════════════════════════════════════════════════════ -->
97
+ <g transform="translate(30, 336)">
98
+ <rect width="740" height="180" rx="12" fill="url(#cardGrad)" stroke="#00bfff" stroke-width="1.5"/>
99
+ <rect width="740" height="3" rx="1.5" fill="#00bfff"/>
100
+
101
+ <circle cx="36" cy="30" r="14" fill="none" stroke="#00bfff" stroke-width="1.5" stroke-opacity="0.7"/>
102
+ <text x="36" y="35" text-anchor="middle" font-family="system-ui, sans-serif" font-size="13" font-weight="700" fill="#00bfff">2</text>
103
+
104
+ <text x="60" y="34" font-family="system-ui, sans-serif" font-size="14" font-weight="700" fill="#00bfff">&#x1F916; Steno Compression</text>
105
+ <rect x="240" y="20" width="90" height="20" rx="10" fill="#00bfff" fill-opacity="0.12" stroke="#00bfff" stroke-width="0.8" stroke-opacity="0.4"/>
106
+ <text x="285" y="34" text-anchor="middle" font-family="'SF Mono', 'Fira Code', Consolas, monospace" font-size="10" font-weight="600" fill="#00bfff">~40% savings</text>
107
+
108
+ <text font-family="system-ui, sans-serif" font-size="11" fill="#8b949e">
109
+ <tspan x="24" y="58">Strips ~80 filler words (the, a, is, are, was, were, of, to, in, for ...) that carry minimal semantic</tspan>
110
+ <tspan x="24" dy="15">meaning. Applies ~100 programming abbreviations: function&#x2192;fn, configuration&#x2192;cfg, database&#x2192;db,</tspan>
111
+ <tspan x="24" dy="15">implementation&#x2192;impl, authentication&#x2192;auth, environment&#x2192;env, repository&#x2192;repo, and more.</tspan>
112
+ </text>
113
+
114
+ <!-- Before/after example -->
115
+ <rect x="24" y="104" width="340" height="14" rx="3" fill="#1a1f26" stroke="#21262d" stroke-width="0.8"/>
116
+ <text x="30" y="115" font-family="'SF Mono', monospace" font-size="8" fill="#6e7681">"the function configuration is required"</text>
117
+ <text x="372" y="115" font-family="system-ui, sans-serif" font-size="11" fill="#484f58">&#x2192;</text>
118
+ <rect x="390" y="104" width="130" height="14" rx="3" fill="#00bfff" fill-opacity="0.1" stroke="#00bfff" stroke-width="0.8" stroke-opacity="0.3"/>
119
+ <text x="396" y="115" font-family="'SF Mono', monospace" font-size="8" fill="#58a6ff">"fn cfg reqd"</text>
120
+ <text x="540" y="115" font-family="system-ui, sans-serif" font-size="8" fill="#484f58">KEEP_WORDS: not, no, never, must, all</text>
121
+
122
+ <!-- ── YCC Sub-layer ── -->
123
+ <line x1="24" y1="128" x2="716" y2="128" stroke="#30363d" stroke-width="0.8" stroke-dasharray="4,3"/>
124
+
125
+ <!-- YC Logo -->
126
+ <rect x="24" y="137" width="36" height="36" rx="8" fill="#a855f7" fill-opacity="0.2" stroke="#a855f7" stroke-width="1.5" stroke-opacity="0.6"/>
127
+ <text x="42" y="161" text-anchor="middle" font-family="system-ui, sans-serif" font-size="16" font-weight="900" fill="#c084fc">YC</text>
128
+
129
+ <!-- Yung Cracka Compress title + badge -->
130
+ <text x="72" y="152" font-family="system-ui, sans-serif" font-size="13" font-weight="700" fill="#c084fc">&#x1F977;&#x1F3FB; Yung Cracka Compress</text>
131
+ <rect x="260" y="140" width="68" height="18" rx="9" fill="#a855f7" fill-opacity="0.12" stroke="#a855f7" stroke-width="0.8" stroke-opacity="0.4"/>
132
+ <text x="294" y="153" text-anchor="middle" font-family="'SF Mono', monospace" font-size="9" font-weight="600" fill="#c084fc">opt-in</text>
133
+ <text x="340" y="153" font-family="'SF Mono', monospace" font-size="8" fill="#484f58">SLANG_ENABLED: false</text>
134
+
135
+ <!-- YCC description -->
136
+ <text x="72" y="172" font-family="system-ui, sans-serif" font-size="10" fill="#6e7681">DMV x Florida slang layer. 90+ entries LLMs already understand. definitely&#x2192;def, probably&#x2192;prolly, through&#x2192;thru</text>
137
+ </g>
138
+
139
+ <!-- Connector 2→3 -->
140
+ <line x1="66" y1="516" x2="66" y2="532" stroke="#30363d" stroke-width="2" stroke-dasharray="3,3"/>
141
+ <polygon points="62,530 66,538 70,530" fill="#30363d"/>
142
+
143
+ <!-- ═══════════════════════════════════════════════════════ -->
144
+ <!-- LAYER 3: Neural MT (y=538, h=142) -->
145
+ <!-- ═══════════════════════════════════════════════════════ -->
146
+ <g transform="translate(30, 538)">
147
+ <rect width="740" height="142" rx="12" fill="url(#cardGrad)" stroke="#a855f7" stroke-width="1.5"/>
148
+ <rect width="740" height="3" rx="1.5" fill="#a855f7"/>
149
+
150
+ <circle cx="36" cy="30" r="14" fill="none" stroke="#a855f7" stroke-width="1.5" stroke-opacity="0.7"/>
151
+ <text x="36" y="35" text-anchor="middle" font-family="system-ui, sans-serif" font-size="13" font-weight="700" fill="#a855f7">3</text>
152
+
153
+ <text x="60" y="34" font-family="system-ui, sans-serif" font-size="14" font-weight="700" fill="#a855f7">&#x1F9D1;&#x200D;&#x1F4BB; Neural MT (EN&#x2192;ZH)</text>
154
+ <rect x="270" y="20" width="105" height="20" rx="10" fill="#a855f7" fill-opacity="0.12" stroke="#a855f7" stroke-width="0.8" stroke-opacity="0.4"/>
155
+ <text x="322" y="34" text-anchor="middle" font-family="'SF Mono', 'Fira Code', Consolas, monospace" font-size="10" font-weight="600" fill="#a855f7">+30% on top</text>
156
+
157
+ <text font-family="system-ui, sans-serif" font-size="11" fill="#8b949e">
158
+ <tspan x="24" y="58">Steno'd tool_result text is translated EN&#x2192;ZH via local Argos Translate (air-gapped, no API calls).</tspan>
159
+ <tspan x="24" dy="15">Loop-back verification: ZH&#x2192;EN back-translation compared via LCS Dice + Jaccard (threshold 0.65).</tspan>
160
+ <tspan x="24" dy="15">Failed verifications fall back to steno-only. Passthrough vocab for untranslatable tech terms (webpack,</tspan>
161
+ <tspan x="24" dy="15">nginx, docker, etc). Word-level TM cache grows over time &#x2014; repeated words skip the socket entirely.</tspan>
162
+ </text>
163
+
164
+ <!-- Verification flow diagram -->
165
+ <rect x="24" y="120" width="58" height="14" rx="3" fill="#00bfff" fill-opacity="0.1" stroke="#00bfff" stroke-width="0.8" stroke-opacity="0.3"/>
166
+ <text x="53" y="131" text-anchor="middle" font-family="'SF Mono', monospace" font-size="8" fill="#58a6ff">steno'd</text>
167
+ <text x="90" y="131" font-family="system-ui, sans-serif" font-size="9" fill="#484f58">&#x2192;</text>
168
+ <rect x="102" y="120" width="34" height="14" rx="3" fill="#a855f7" fill-opacity="0.15" stroke="#a855f7" stroke-width="0.8" stroke-opacity="0.4"/>
169
+ <text x="119" y="131" text-anchor="middle" font-family="'SF Mono', monospace" font-size="8" fill="#c084fc">ZH</text>
170
+ <text x="144" y="131" font-family="system-ui, sans-serif" font-size="9" fill="#484f58">&#x2192;</text>
171
+ <rect x="156" y="120" width="64" height="14" rx="3" fill="#f59e0b" fill-opacity="0.12" stroke="#f59e0b" stroke-width="0.8" stroke-opacity="0.3"/>
172
+ <text x="188" y="131" text-anchor="middle" font-family="'SF Mono', monospace" font-size="8" fill="#fbbf24">back-EN</text>
173
+ <text x="228" y="131" font-family="system-ui, sans-serif" font-size="9" fill="#484f58">&#x2192;</text>
174
+ <rect x="242" y="120" width="48" height="14" rx="3" fill="#22c55e" fill-opacity="0.15" stroke="#22c55e" stroke-width="0.8" stroke-opacity="0.4"/>
175
+ <text x="266" y="131" text-anchor="middle" font-family="'SF Mono', monospace" font-size="8" fill="#4ade80">&gt;=0.65</text>
176
+ <text x="298" y="131" font-family="system-ui, sans-serif" font-size="9" fill="#4ade80">use ZH</text>
177
+ <text x="350" y="131" font-family="system-ui, sans-serif" font-size="9" fill="#484f58">|</text>
178
+ <rect x="364" y="120" width="48" height="14" rx="3" fill="#ef4444" fill-opacity="0.15" stroke="#ef4444" stroke-width="0.8" stroke-opacity="0.4"/>
179
+ <text x="388" y="131" text-anchor="middle" font-family="'SF Mono', monospace" font-size="8" fill="#f87171">&lt;0.65</text>
180
+ <text x="420" y="131" font-family="system-ui, sans-serif" font-size="9" fill="#f87171">keep steno</text>
181
+ <text x="490" y="131" font-family="system-ui, sans-serif" font-size="8" fill="#484f58">TM cache + synonym learning from failures</text>
182
+ </g>
183
+
184
+ <!-- Connector 3→4 -->
185
+ <line x1="66" y1="680" x2="66" y2="696" stroke="#30363d" stroke-width="2" stroke-dasharray="3,3"/>
186
+ <polygon points="62,694 66,702 70,694" fill="#30363d"/>
187
+
188
+ <!-- ═══════════════════════════════════════════════════════ -->
189
+ <!-- LAYER 4: Old-Message Stripping (y=702, h=114) -->
190
+ <!-- ═══════════════════════════════════════════════════════ -->
191
+ <g transform="translate(30, 702)">
192
+ <rect width="740" height="114" rx="12" fill="url(#cardGrad)" stroke="#f59e0b" stroke-width="1.5"/>
193
+ <rect width="740" height="3" rx="1.5" fill="url(#orangeGrad)"/>
194
+
195
+ <circle cx="36" cy="30" r="14" fill="none" stroke="#f59e0b" stroke-width="1.5" stroke-opacity="0.7"/>
196
+ <text x="36" y="35" text-anchor="middle" font-family="system-ui, sans-serif" font-size="13" font-weight="700" fill="#f59e0b">4</text>
197
+
198
+ <text x="60" y="34" font-family="system-ui, sans-serif" font-size="14" font-weight="700" fill="#fbbf24">&#x1F5D1;&#xFE0F; Old-Message Stripping</text>
199
+ <rect x="272" y="20" width="100" height="20" rx="10" fill="#f59e0b" fill-opacity="0.12" stroke="#f59e0b" stroke-width="0.8" stroke-opacity="0.4"/>
200
+ <text x="322" y="34" text-anchor="middle" font-family="'SF Mono', 'Fira Code', Consolas, monospace" font-size="10" font-weight="600" fill="#fbbf24">85%+ savings</text>
201
+
202
+ <text font-family="system-ui, sans-serif" font-size="11" fill="#8b949e">
203
+ <tspan x="24" y="58">tool_result content from messages outside the recent window (last 3 messages preserved) gets</tspan>
204
+ <tspan x="24" dy="15">replaced with a 200-char preview summary. Stale file reads, grep outputs, and old assistant text</tspan>
205
+ <tspan x="24" dy="15">blocks are trimmed to first-line anchors. SpecMem hook injections (SM-* markers) also stripped.</tspan>
206
+ </text>
207
+
208
+ <text x="24" y="106" font-family="'SF Mono', monospace" font-size="8" fill="#484f58">threshold: 100 chars | preview: 200 chars | preserves: tool_use_id, is_error, cache_control</text>
209
+ </g>
210
+
211
+ <!-- Connector 4→5 -->
212
+ <line x1="66" y1="816" x2="66" y2="832" stroke="#30363d" stroke-width="2" stroke-dasharray="3,3"/>
213
+ <polygon points="62,830 66,838 70,830" fill="#30363d"/>
214
+
215
+ <!-- ═══════════════════════════════════════════════════════ -->
216
+ <!-- LAYER 5: System-Reminder Stripping (y=838, h=114) -->
217
+ <!-- ═══════════════════════════════════════════════════════ -->
218
+ <g transform="translate(30, 838)">
219
+ <rect width="740" height="114" rx="12" fill="url(#cardGrad)" stroke="#ef4444" stroke-width="1.5"/>
220
+ <rect width="740" height="3" rx="1.5" fill="#ef4444"/>
221
+
222
+ <circle cx="36" cy="30" r="14" fill="none" stroke="#ef4444" stroke-width="1.5" stroke-opacity="0.7"/>
223
+ <text x="36" y="35" text-anchor="middle" font-family="system-ui, sans-serif" font-size="13" font-weight="700" fill="#ef4444">5</text>
224
+
225
+ <text x="60" y="34" font-family="system-ui, sans-serif" font-size="14" font-weight="700" fill="#f87171">&#x1F9F9; System-Reminder Stripping</text>
226
+ <rect x="298" y="20" width="100" height="20" rx="10" fill="#ef4444" fill-opacity="0.12" stroke="#ef4444" stroke-width="0.8" stroke-opacity="0.4"/>
227
+ <text x="348" y="34" text-anchor="middle" font-family="'SF Mono', 'Fira Code', Consolas, monospace" font-size="10" font-weight="600" fill="#f87171">variable</text>
228
+
229
+ <text font-family="system-ui, sans-serif" font-size="11" fill="#8b949e">
230
+ <tspan x="24" y="58">Duplicate &lt;system-reminder&gt; tags stripped from messages. First instance is preserved (sets up</tspan>
231
+ <tspan x="24" dy="15">context/style), all subsequent identical reminders removed. System prompt dedup tracks content</tspan>
232
+ <tspan x="24" dy="15">hash &#x2014; same prompt across requests is sent once, then stripped on repeat.</tspan>
233
+ </text>
234
+
235
+ <text x="24" y="106" font-family="'SF Mono', monospace" font-size="8" fill="#484f58">regex: /&lt;system-reminder&gt;[\s\S]*?&lt;\/system-reminder&gt;/g | keeps first, strips rest</text>
236
+ </g>
237
+
238
+ <!-- ═══════════════════════════════════════════════════════ -->
239
+ <!-- Result bar (y=970, h=44) -->
240
+ <!-- ═══════════════════════════════════════════════════════ -->
241
+ <rect x="30" y="968" width="740" height="44" rx="12" fill="#22c55e" fill-opacity="0.08" stroke="#22c55e" stroke-width="1.5" stroke-opacity="0.4"/>
242
+ <circle cx="66" cy="990" r="12" fill="none" stroke="#22c55e" stroke-width="2"/>
243
+ <path d="M60 990 L64 995 L74 984" fill="none" stroke="#4ade80" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"/>
244
+ <text x="88" y="986" font-family="system-ui, sans-serif" font-size="13" font-weight="600" fill="#4ade80">Combined: ~57-60% total input token reduction.</text>
245
+ <text x="88" y="1003" font-family="system-ui, sans-serif" font-size="10" fill="#6e7681">All layers run on every request. Falls back gracefully &#x2014; proxy never breaks the API call. Toggle via /config.</text>
246
+ </svg>