vektor-slipstream 1.4.4 → 2.0.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 (56) hide show
  1. package/README.md +67 -306
  2. package/package.json +14 -146
  3. package/CHANGELOG.md +0 -139
  4. package/LICENSE +0 -33
  5. package/TENETS.md +0 -189
  6. package/audn-log.js +0 -143
  7. package/axon.js +0 -389
  8. package/boot-patch.js +0 -33
  9. package/boot-screen.html +0 -210
  10. package/briefing.js +0 -150
  11. package/cerebellum.js +0 -439
  12. package/cloak-behaviour.js +0 -596
  13. package/cloak-captcha.js +0 -541
  14. package/cloak-core.js +0 -499
  15. package/cloak-identity.js +0 -484
  16. package/cloak-index.js +0 -261
  17. package/cloak-llms.js +0 -163
  18. package/cloak-pattern-store.js +0 -471
  19. package/cloak-recorder-auto.js +0 -297
  20. package/cloak-recorder-snippet.js +0 -119
  21. package/cloak-turbo-quant.js +0 -357
  22. package/cloak-warmup.js +0 -240
  23. package/cortex.js +0 -221
  24. package/detect-hardware.js +0 -181
  25. package/entity-resolver.js +0 -298
  26. package/errors.js +0 -66
  27. package/examples/example-claude-mcp.js +0 -220
  28. package/examples/example-langchain-researcher.js +0 -82
  29. package/examples/example-openai-assistant.js +0 -84
  30. package/examples/examples-README.md +0 -161
  31. package/export-import.js +0 -221
  32. package/forget.js +0 -148
  33. package/inspect.js +0 -199
  34. package/mistral/README-mistral.md +0 -123
  35. package/mistral/mistral-bridge.js +0 -218
  36. package/mistral/mistral-setup.js +0 -220
  37. package/mistral/vektor-tool-manifest.json +0 -41
  38. package/models/model_quantized.onnx +0 -0
  39. package/models/vocab.json +0 -1
  40. package/namespace.js +0 -186
  41. package/pin.js +0 -91
  42. package/slipstream-core-extended.js +0 -134
  43. package/slipstream-core.js +0 -1
  44. package/slipstream-db.js +0 -140
  45. package/slipstream-embedder.js +0 -338
  46. package/sovereign.js +0 -142
  47. package/token.js +0 -322
  48. package/types/index.d.ts +0 -269
  49. package/vektor-banner-loader.js +0 -109
  50. package/vektor-cli.js +0 -259
  51. package/vektor-licence-prompt.js +0 -128
  52. package/vektor-licence.js +0 -192
  53. package/vektor-setup.js +0 -270
  54. package/vektor-slipstream.dxt +0 -0
  55. package/vektor-tui.js +0 -373
  56. package/visualize.js +0 -235
@@ -1,471 +0,0 @@
1
- 'use strict';
2
-
3
- /**
4
- * cloak-pattern-store.js — Tiered self-improving pattern library
5
- * ─────────────────────────────────────────────────────────────────────────────
6
- * Stores behaviour patterns in SQLite with win/loss scoring, tier management,
7
- * auto-pruning, and duplicate detection. Patterns get smarter over time.
8
- *
9
- * Tiers:
10
- * elite (max 10) — 3+ wins, 0 losses. Used 70% of sessions.
11
- * active (max 30) — Positive score, in rotation. Used 25% of sessions.
12
- * probation (max 20) — New or declining. Used 5% of sessions.
13
- * retired (deleted) — Score < -3, stale, or duplicate.
14
- *
15
- * Pruning rules:
16
- * - Score drops to -3 → immediate retirement
17
- * - No win in 30 days + score ≤ 0 → retirement
18
- * - Pattern age > 90 days + score < 5 → retirement (sites change)
19
- * - Active tier > 30 → prune lowest scored
20
- * - Duplicate (>92% similarity) → discard on arrival
21
- * - Elite tier full + new 3-win → bump lowest elite to active
22
- * ─────────────────────────────────────────────────────────────────────────────
23
- */
24
-
25
- const path = require('path');
26
- const os = require('os');
27
- const fs = require('fs');
28
- const crypto = require('crypto');
29
-
30
- const DB_PATH = process.env.VEKTOR_PATTERN_DB || path.join(os.homedir(), '.vektor', 'pattern-store.db');
31
-
32
- // Tier weights for random selection (elite gets most traffic)
33
- const TIER_WEIGHTS = { elite: 0.70, active: 0.25, probation: 0.05 };
34
-
35
- // Tier size caps
36
- const TIER_CAPS = { elite: 10, active: 30, probation: 20 };
37
-
38
- // Pruning thresholds
39
- const PRUNE = {
40
- minScore: -3, // retire immediately below this
41
- staleDays: 30, // retire if no win in this many days AND score ≤ 0
42
- ageDays: 90, // retire if older than this AND score < 5
43
- similarityThresh: 0.92, // discard new pattern if >92% similar to existing elite
44
- };
45
-
46
- let _db = null;
47
-
48
- // ── DB initialisation ─────────────────────────────────────────────────────────
49
-
50
- function getDB() {
51
- if (_db) return _db;
52
-
53
- const Database = require('better-sqlite3');
54
- fs.mkdirSync(path.dirname(DB_PATH), { recursive: true });
55
- _db = new Database(DB_PATH);
56
-
57
- _db.pragma('journal_mode = WAL');
58
- _db.pragma('synchronous = NORMAL');
59
-
60
- _db.exec(`
61
- CREATE TABLE IF NOT EXISTS patterns (
62
- id TEXT PRIMARY KEY,
63
- name TEXT NOT NULL,
64
- category TEXT NOT NULL DEFAULT 'custom',
65
- tier TEXT NOT NULL DEFAULT 'probation',
66
- score INTEGER NOT NULL DEFAULT 0,
67
- wins INTEGER NOT NULL DEFAULT 0,
68
- losses INTEGER NOT NULL DEFAULT 0,
69
- sessions INTEGER NOT NULL DEFAULT 0,
70
- created_at INTEGER NOT NULL,
71
- last_win_at INTEGER,
72
- last_used_at INTEGER,
73
- description TEXT,
74
- profile TEXT NOT NULL,
75
- fingerprint TEXT NOT NULL
76
- );
77
-
78
- CREATE TABLE IF NOT EXISTS pattern_log (
79
- id INTEGER PRIMARY KEY AUTOINCREMENT,
80
- pattern_id TEXT NOT NULL,
81
- outcome TEXT NOT NULL,
82
- site TEXT,
83
- score_delta INTEGER NOT NULL,
84
- logged_at INTEGER NOT NULL
85
- );
86
-
87
- CREATE INDEX IF NOT EXISTS idx_tier ON patterns(tier);
88
- CREATE INDEX IF NOT EXISTS idx_category ON patterns(category);
89
- CREATE INDEX IF NOT EXISTS idx_score ON patterns(score DESC);
90
- `);
91
-
92
- return _db;
93
- }
94
-
95
- // ── Fingerprint for duplicate detection ───────────────────────────────────────
96
- // Summarises a pattern's velocity/scroll profile as a compact vector
97
- // so we can detect near-duplicates before adding to the store.
98
-
99
- function _fingerprintPattern(events) {
100
- if (!events?.length) return '0'.repeat(32);
101
-
102
- // Build a 16-bucket histogram of: scroll velocity, move speed, pause frequency
103
- const buckets = new Float32Array(16);
104
- let prev = null;
105
- let scrollCount = 0, moveCount = 0, pauseCount = 0;
106
- let totalScrollDy = 0;
107
-
108
- for (const e of events) {
109
- if (e.type === 'scroll') {
110
- scrollCount++;
111
- totalScrollDy += Math.abs(e.dy || 0);
112
- // Bucket by scroll velocity (dy / dt)
113
- const vel = prev ? Math.abs(e.dy || 0) / Math.max(1, e.dt - (prev.dt || 0)) : 0;
114
- const b = Math.min(7, Math.floor(vel / 10));
115
- buckets[b]++;
116
- } else if (e.type === 'move') {
117
- moveCount++;
118
- buckets[8 + Math.min(7, Math.floor(Math.random() * 8))]++;
119
- } else if (e.type === 'pause') {
120
- pauseCount++;
121
- }
122
- prev = e;
123
- }
124
-
125
- // Normalise buckets
126
- const total = events.length || 1;
127
- for (let i = 0; i < 16; i++) buckets[i] /= total;
128
-
129
- // Pack into hex string
130
- return Buffer.from(buckets.buffer).toString('hex').slice(0, 32);
131
- }
132
-
133
- function _similarityScore(fpA, fpB) {
134
- if (fpA === fpB) return 1.0;
135
- // Simple hamming-based similarity on hex fingerprints
136
- let matches = 0;
137
- const len = Math.min(fpA.length, fpB.length);
138
- for (let i = 0; i < len; i++) {
139
- if (fpA[i] === fpB[i]) matches++;
140
- }
141
- return matches / len;
142
- }
143
-
144
- // ── Core operations ───────────────────────────────────────────────────────────
145
-
146
- /**
147
- * Add a new pattern to the store (starts in probation).
148
- * Runs duplicate check — returns null if too similar to existing elite.
149
- *
150
- * @param {object} pattern — { name, category, description, events, viewport }
151
- * @returns {{ id, tier, duplicate } | null}
152
- */
153
- function addPattern(pattern) {
154
- const db = getDB();
155
-
156
- const events = pattern.events || [];
157
- const fingerprint = _fingerprintPattern(events);
158
- const id = crypto.randomUUID();
159
-
160
- // Duplicate check against elite + active patterns
161
- const existing = db.prepare(
162
- `SELECT fingerprint FROM patterns WHERE tier IN ('elite','active')`
163
- ).all();
164
-
165
- for (const row of existing) {
166
- const sim = _similarityScore(fingerprint, row.fingerprint);
167
- if (sim >= PRUNE.similarityThresh) {
168
- return { id: null, tier: null, duplicate: true, similarity: sim };
169
- }
170
- }
171
-
172
- db.prepare(`
173
- INSERT INTO patterns
174
- (id, name, category, tier, score, wins, losses, sessions,
175
- created_at, last_win_at, last_used_at, description, profile, fingerprint)
176
- VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?)
177
- `).run(
178
- id,
179
- pattern.name || 'unnamed-' + Date.now(),
180
- pattern.category || 'custom',
181
- 'probation',
182
- 0, 0, 0, 0,
183
- Date.now(), null, null,
184
- pattern.description || '',
185
- JSON.stringify({ events, viewport: pattern.viewport }),
186
- fingerprint
187
- );
188
-
189
- _prune(db);
190
-
191
- return { id, tier: 'probation', duplicate: false };
192
- }
193
-
194
- /**
195
- * Record an outcome for a pattern after a session.
196
- * Updates score, tier, win/loss counts, triggers pruning.
197
- *
198
- * @param {string} patternId
199
- * @param {'pass'|'block'|'captcha'|'unknown'} outcome
200
- * @param {string} site — hostname of the target
201
- */
202
- function recordOutcome(patternId, outcome, site = '') {
203
- const db = getDB();
204
- const row = db.prepare('SELECT * FROM patterns WHERE id = ?').get(patternId);
205
- if (!row) return null;
206
-
207
- const delta = outcome === 'pass' ? 2 :
208
- outcome === 'block' ? -2 :
209
- outcome === 'captcha' ? -1 : 0;
210
-
211
- const newScore = row.score + delta;
212
- const newWins = outcome === 'pass' ? row.wins + 1 : row.wins;
213
- const newLosses = (outcome === 'block' || outcome === 'captcha') ? row.losses + 1 : row.losses;
214
- const lastWinAt = outcome === 'pass' ? Date.now() : row.last_win_at;
215
-
216
- // Determine new tier
217
- let tier = row.tier;
218
- if (newScore <= PRUNE.minScore) {
219
- tier = 'retired';
220
- } else if (newWins >= 3 && newLosses === 0 && tier === 'active') {
221
- // Promote to elite if elite has room
222
- const eliteCount = db.prepare(`SELECT COUNT(*) as n FROM patterns WHERE tier = 'elite'`).get().n;
223
- if (eliteCount < TIER_CAPS.elite) tier = 'elite';
224
- else {
225
- // Bump lowest-scored elite to active to make room
226
- const lowestElite = db.prepare(
227
- `SELECT id FROM patterns WHERE tier = 'elite' ORDER BY score ASC LIMIT 1`
228
- ).get();
229
- if (lowestElite && newScore > row.score) {
230
- db.prepare(`UPDATE patterns SET tier = 'active' WHERE id = ?`).run(lowestElite.id);
231
- tier = 'elite';
232
- }
233
- }
234
- } else if (tier === 'probation' && newScore > 0 && row.sessions >= 3) {
235
- tier = 'active';
236
- }
237
-
238
- db.prepare(`
239
- UPDATE patterns SET
240
- score = ?, wins = ?, losses = ?, sessions = sessions + 1,
241
- last_win_at = ?, last_used_at = ?, tier = ?
242
- WHERE id = ?
243
- `).run(newScore, newWins, newLosses, lastWinAt, Date.now(), tier, patternId);
244
-
245
- db.prepare(`
246
- INSERT INTO pattern_log (pattern_id, outcome, site, score_delta, logged_at)
247
- VALUES (?,?,?,?,?)
248
- `).run(patternId, outcome, site, delta, Date.now());
249
-
250
- // If retired, remove immediately
251
- if (tier === 'retired') {
252
- db.prepare('DELETE FROM patterns WHERE id = ?').run(patternId);
253
- }
254
-
255
- _prune(db);
256
-
257
- return { id: patternId, tier, score: newScore, wins: newWins, losses: newLosses };
258
- }
259
-
260
- /**
261
- * Pick a pattern for use, weighted by tier.
262
- * @param {string} category — filter by category (optional)
263
- * @returns {{ id, name, events, viewport, tier } | null}
264
- */
265
- function pickPattern(category = null) {
266
- const db = getDB();
267
-
268
- // Roll for tier
269
- const roll = Math.random();
270
- let tier;
271
- if (roll < TIER_WEIGHTS.elite) tier = 'elite';
272
- else if (roll < TIER_WEIGHTS.elite + TIER_WEIGHTS.active) tier = 'active';
273
- else tier = 'probation';
274
-
275
- // Try preferred tier first, fall back up if empty
276
- const tierOrder = tier === 'elite' ? ['elite', 'active', 'probation'] :
277
- tier === 'active' ? ['active', 'elite', 'probation'] :
278
- ['probation', 'active', 'elite'];
279
-
280
- for (const t of tierOrder) {
281
- const where = category
282
- ? `tier = '${t}' AND category = '${category.replace(/'/g,"''")}'`
283
- : `tier = '${t}'`;
284
-
285
- const rows = db.prepare(
286
- `SELECT * FROM patterns WHERE ${where} ORDER BY score DESC`
287
- ).all();
288
-
289
- if (!rows.length) continue;
290
-
291
- // Weighted random within tier — higher score = higher probability
292
- const minScore = Math.min(...rows.map(r => r.score));
293
- const weights = rows.map(r => Math.max(0.1, r.score - minScore + 1));
294
- const total = weights.reduce((a, b) => a + b, 0);
295
- let pick = Math.random() * total;
296
- for (let i = 0; i < rows.length; i++) {
297
- pick -= weights[i];
298
- if (pick <= 0) {
299
- const profile = JSON.parse(rows[i].profile);
300
- return {
301
- id: rows[i].id,
302
- name: rows[i].name,
303
- tier: rows[i].tier,
304
- score: rows[i].score,
305
- events: profile.events,
306
- viewport: profile.viewport,
307
- };
308
- }
309
- }
310
-
311
- // Fallback: return last row
312
- const last = rows[rows.length - 1];
313
- const profile = JSON.parse(last.profile);
314
- return { id: last.id, name: last.name, tier: last.tier, score: last.score,
315
- events: profile.events, viewport: profile.viewport };
316
- }
317
-
318
- return null; // no patterns in store
319
- }
320
-
321
- /**
322
- * Get all patterns summary (for MCP tool / stats).
323
- */
324
- function storeStats() {
325
- const db = getDB();
326
- const counts = db.prepare(`
327
- SELECT tier, COUNT(*) as n, AVG(score) as avg_score,
328
- SUM(wins) as total_wins, SUM(losses) as total_losses
329
- FROM patterns GROUP BY tier
330
- `).all();
331
-
332
- const total = db.prepare('SELECT COUNT(*) as n FROM patterns').get().n;
333
- const log = db.prepare(
334
- 'SELECT COUNT(*) as n FROM pattern_log WHERE logged_at > ?'
335
- ).get(Date.now() - 7 * 24 * 3600 * 1000).n;
336
-
337
- return {
338
- total,
339
- tiers: counts,
340
- sessionsLast7d: log,
341
- caps: TIER_CAPS,
342
- pruneRules: PRUNE,
343
- };
344
- }
345
-
346
- /**
347
- * List patterns with full stats.
348
- */
349
- function listPatterns(tier = null) {
350
- const db = getDB();
351
- const sql = tier
352
- ? `SELECT id,name,category,tier,score,wins,losses,sessions,created_at,last_win_at,description FROM patterns WHERE tier = ? ORDER BY score DESC`
353
- : `SELECT id,name,category,tier,score,wins,losses,sessions,created_at,last_win_at,description FROM patterns ORDER BY tier, score DESC`;
354
- return tier ? db.prepare(sql).all(tier) : db.prepare(sql).all();
355
- }
356
-
357
- // ── Auto-pruning ──────────────────────────────────────────────────────────────
358
-
359
- function _prune(db) {
360
- const now = Date.now();
361
-
362
- // 1. Retire stale: no win in 30 days AND score ≤ 0
363
- const staleThresh = now - PRUNE.staleDays * 24 * 3600 * 1000;
364
- db.prepare(`
365
- DELETE FROM patterns
366
- WHERE score <= 0
367
- AND tier != 'retired'
368
- AND (last_win_at IS NULL OR last_win_at < ?)
369
- AND created_at < ?
370
- `).run(staleThresh, staleThresh);
371
-
372
- // 2. Retire aged: > 90 days old AND score < 5
373
- const ageThresh = now - PRUNE.ageDays * 24 * 3600 * 1000;
374
- db.prepare(`
375
- DELETE FROM patterns WHERE created_at < ? AND score < 5
376
- `).run(ageThresh);
377
-
378
- // 3. Cap active tier — keep top 30 by score
379
- const activeCount = db.prepare(`SELECT COUNT(*) as n FROM patterns WHERE tier = 'active'`).get().n;
380
- if (activeCount > TIER_CAPS.active) {
381
- const toDelete = activeCount - TIER_CAPS.active;
382
- db.prepare(`
383
- DELETE FROM patterns WHERE id IN (
384
- SELECT id FROM patterns WHERE tier = 'active' ORDER BY score ASC LIMIT ?
385
- )
386
- `).run(toDelete);
387
- }
388
-
389
- // 4. Cap probation tier — keep top 20 by score, prefer newer
390
- const probCount = db.prepare(`SELECT COUNT(*) as n FROM patterns WHERE tier = 'probation'`).get().n;
391
- if (probCount > TIER_CAPS.probation) {
392
- const toDelete = probCount - TIER_CAPS.probation;
393
- db.prepare(`
394
- DELETE FROM patterns WHERE id IN (
395
- SELECT id FROM patterns WHERE tier = 'probation'
396
- ORDER BY score ASC, created_at ASC LIMIT ?
397
- )
398
- `).run(toDelete);
399
- }
400
-
401
- // 5. Prune log table — keep last 1000 entries
402
- const logCount = db.prepare('SELECT COUNT(*) as n FROM pattern_log').get().n;
403
- if (logCount > 1000) {
404
- db.prepare(`
405
- DELETE FROM pattern_log WHERE id IN (
406
- SELECT id FROM pattern_log ORDER BY logged_at ASC LIMIT ?
407
- )
408
- `).run(logCount - 1000);
409
- }
410
- }
411
-
412
- /**
413
- * Force a full prune pass (callable from MCP tool).
414
- */
415
- function pruneNow() {
416
- const db = getDB();
417
- const before = db.prepare('SELECT COUNT(*) as n FROM patterns').get().n;
418
- _prune(db);
419
- const after = db.prepare('SELECT COUNT(*) as n FROM patterns').get().n;
420
- return { removed: before - after, remaining: after };
421
- }
422
-
423
- /**
424
- * Seed the store with built-in patterns from cloak-behaviour.js.
425
- * Only seeds if store is empty. Built-ins start in 'active' tier with score 1.
426
- */
427
- function seedBuiltins() {
428
- const db = getDB();
429
- const existing = db.prepare('SELECT COUNT(*) as n FROM patterns').get().n;
430
- if (existing > 0) return { seeded: 0, reason: 'store already has patterns' };
431
-
432
- const { PATTERN_LIBRARY } = require('./cloak-behaviour');
433
- let seeded = 0;
434
-
435
- for (const [name, pattern] of Object.entries(PATTERN_LIBRARY)) {
436
- const fingerprint = _fingerprintPattern(pattern.events);
437
- const id = crypto.randomUUID();
438
- db.prepare(`
439
- INSERT INTO patterns
440
- (id, name, category, tier, score, wins, losses, sessions,
441
- created_at, last_win_at, last_used_at, description, profile, fingerprint)
442
- VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?)
443
- `).run(
444
- id, name, pattern.category,
445
- 'active', // built-ins start active, not probation
446
- 1, 0, 0, 0,
447
- Date.now(), null, null,
448
- pattern.description || '',
449
- JSON.stringify({ events: pattern.events, viewport: pattern.viewport }),
450
- fingerprint
451
- );
452
- seeded++;
453
- }
454
-
455
- return { seeded };
456
- }
457
-
458
- module.exports = {
459
- addPattern,
460
- recordOutcome,
461
- pickPattern,
462
- storeStats,
463
- listPatterns,
464
- pruneNow,
465
- seedBuiltins,
466
- };
467
-
468
- /** @internal — test use only. Resets the cached DB connection. */
469
- function _resetDB() { _db = null; }
470
-
471
- module.exports._resetDB = _resetDB;