thumbgate 1.21.1 → 1.22.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.
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "thumbgate-marketplace",
3
- "version": "1.21.1",
3
+ "version": "1.22.0",
4
4
  "owner": {
5
5
  "name": "Igor Ganapolsky",
6
6
  "email": "ig5973700@gmail.com"
@@ -14,7 +14,7 @@
14
14
  "source": "npm",
15
15
  "package": "thumbgate"
16
16
  },
17
- "version": "1.21.1",
17
+ "version": "1.22.0",
18
18
  "author": {
19
19
  "name": "Igor Ganapolsky",
20
20
  "email": "ig5973700@gmail.com",
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "thumbgate",
3
3
  "description": "One 👎 becomes a hard rule the agent cannot bypass. Captures thumbs-down feedback, distills it into PreToolUse Pre-Action Checks, enforced across every future Claude Code session.",
4
- "version": "1.21.1",
4
+ "version": "1.22.0",
5
5
  "author": {
6
6
  "name": "Igor Ganapolsky",
7
7
  "email": "ig5973700@gmail.com",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "thumbgate",
3
- "version": "1.21.1",
3
+ "version": "1.22.0",
4
4
  "description": "ThumbGate — 👍👎 feedback that teaches your AI agent. Thumbs down a mistake, it never happens again.",
5
5
  "homepage": "https://thumbgate-production.up.railway.app",
6
6
  "transport": "stdio",
@@ -2,13 +2,13 @@
2
2
  "mcpServers": {
3
3
  "thumbgate": {
4
4
  "command": "npx",
5
- "args": ["--yes", "--package", "thumbgate@1.21.1", "thumbgate", "serve"]
5
+ "args": ["--yes", "--package", "thumbgate@1.22.0", "thumbgate", "serve"]
6
6
  }
7
7
  },
8
8
  "hooks": {
9
9
  "preToolUse": {
10
10
  "command": "npx",
11
- "args": ["--yes", "--package", "thumbgate@1.21.1", "thumbgate", "gate-check"]
11
+ "args": ["--yes", "--package", "thumbgate@1.22.0", "thumbgate", "gate-check"]
12
12
  }
13
13
  }
14
14
  }
@@ -216,7 +216,7 @@ const {
216
216
  finalizeSession: finalizeFeedbackSession,
217
217
  } = require('../../scripts/feedback-session');
218
218
 
219
- const SERVER_INFO = { name: 'thumbgate-mcp', version: '1.21.1' };
219
+ const SERVER_INFO = { name: 'thumbgate-mcp', version: '1.22.0' };
220
220
  const COMMERCE_CATEGORIES = [
221
221
  'product_recommendation',
222
222
  'brand_compliance',
@@ -368,6 +368,111 @@ function buildRecallResponse(args = {}) {
368
368
  return toTextResult(text);
369
369
  }
370
370
 
371
+ function buildSuggestFixResponse(args = {}) {
372
+ const context = String(args.context || '').trim();
373
+ const rawLimit = Number(args.limit);
374
+ const limit = Number.isFinite(rawLimit) && rawLimit > 0 ? Math.min(rawLimit, 5) : 3;
375
+
376
+ // If no context provided, return generic suggestion
377
+ if (!context) {
378
+ return toTextResult({
379
+ suggestions: [
380
+ {
381
+ action: 'Capture feedback about what went wrong so ThumbGate can learn and prevent recurrence.',
382
+ source: 'generic',
383
+ },
384
+ ],
385
+ query: '',
386
+ totalFound: 0,
387
+ });
388
+ }
389
+
390
+ // Search lessons via lesson-search module
391
+ const lessonModule = loadPrivateMcpModule('lessonSearch');
392
+ let lessonActions = [];
393
+ if (lessonModule) {
394
+ try {
395
+ const searchResult = lessonModule.searchLessons(context, { limit: 10 });
396
+ const results = Array.isArray(searchResult && searchResult.results) ? searchResult.results : [];
397
+ for (const result of results) {
398
+ const correctiveActions = (result.systemResponse && Array.isArray(result.systemResponse.correctiveActions))
399
+ ? result.systemResponse.correctiveActions
400
+ : [];
401
+ for (const action of correctiveActions) {
402
+ const text = String(action.text || '').trim();
403
+ if (text) {
404
+ lessonActions.push({
405
+ action: text,
406
+ source: action.source || `lesson:${result.id || 'unknown'}`,
407
+ score: result.score || 0,
408
+ });
409
+ }
410
+ }
411
+ // Also pick up lesson-level howToAvoid / actionNeeded when no explicit correctiveActions
412
+ if (correctiveActions.length === 0 && result.lesson) {
413
+ const text = result.lesson.howToAvoid || result.lesson.actionNeeded || '';
414
+ if (text) {
415
+ lessonActions.push({
416
+ action: String(text).trim(),
417
+ source: `lesson:${result.id || 'unknown'}`,
418
+ score: result.score || 0,
419
+ });
420
+ }
421
+ }
422
+ }
423
+ } catch {
424
+ // lesson search failure is non-fatal
425
+ }
426
+ }
427
+
428
+ // Search prevention rules directly via lesson-search module's helper
429
+ let ruleActions = [];
430
+ try {
431
+ const { readPreventionRuleMatches } = require('../../scripts/lesson-search');
432
+ const ruleMatches = readPreventionRuleMatches(context, limit);
433
+ for (const rule of ruleMatches) {
434
+ const text = rule.summary || rule.title || '';
435
+ if (text) {
436
+ ruleActions.push({
437
+ action: String(text).trim(),
438
+ source: `rule:${String(rule.title || 'prevention_rules').trim()}`,
439
+ score: rule.score || 0,
440
+ });
441
+ }
442
+ }
443
+ } catch {
444
+ // rule search failure is non-fatal
445
+ }
446
+
447
+ // Merge, deduplicate, sort by score, and take top `limit`
448
+ const seen = new Set();
449
+ const all = [...lessonActions, ...ruleActions]
450
+ .filter((item) => {
451
+ if (!item.action) return false;
452
+ const key = item.action.toLowerCase();
453
+ if (seen.has(key)) return false;
454
+ seen.add(key);
455
+ return true;
456
+ })
457
+ .sort((a, b) => (b.score || 0) - (a.score || 0))
458
+ .slice(0, limit)
459
+ .map(({ action, source }) => ({ action, source }));
460
+
461
+ // If nothing matched, add generic fallback
462
+ if (all.length === 0) {
463
+ all.push({
464
+ action: 'No matching lessons or rules found. Capture feedback via capture_feedback so ThumbGate can learn from this failure.',
465
+ source: 'generic',
466
+ });
467
+ }
468
+
469
+ return toTextResult({
470
+ suggestions: all,
471
+ query: context,
472
+ totalFound: all.length,
473
+ });
474
+ }
475
+
371
476
  function buildDiagnoseFailureResponse(args = {}) {
372
477
  let intentPlan = null;
373
478
  const requestedProfile = args.mcpProfile || getActiveMcpProfile();
@@ -579,6 +684,8 @@ async function callToolInner(name, args) {
579
684
  tags: Array.isArray(args.tags) ? args.tags : [],
580
685
  }));
581
686
  }
687
+ case 'suggest_fix':
688
+ return buildSuggestFixResponse(args);
582
689
  case 'retrieve_lessons': {
583
690
  // Cross-encoder reranking: retrieve more candidates, then rerank for precision
584
691
  const { retrieveWithRerankingSync } = loadOptionalModule(path.join(__dirname, '../../scripts/cross-encoder-reranker'), () => ({
@@ -1330,6 +1437,7 @@ module.exports = {
1330
1437
  acquireLock,
1331
1438
  toCaptureFeedbackTextResult,
1332
1439
  formatCorrectiveActionsReminder,
1440
+ buildSuggestFixResponse,
1333
1441
  __test__: {
1334
1442
  PRIVATE_MCP_MODULES,
1335
1443
  loadPrivateMcpModule,
@@ -7,7 +7,7 @@
7
7
  "npx",
8
8
  "--yes",
9
9
  "--package",
10
- "thumbgate@1.21.1",
10
+ "thumbgate@1.22.0",
11
11
  "thumbgate",
12
12
  "serve"
13
13
  ],
package/bin/cli.js CHANGED
@@ -23,6 +23,7 @@
23
23
  * npx thumbgate background-governance # background-agent run report + risk check
24
24
  * npx thumbgate cfo # local operational billing summary
25
25
  * npx thumbgate pro # solo dashboard + exports side lane
26
+ * npx thumbgate audit <file> # audit an agent transcript for repeat-mistake token waste
26
27
  */
27
28
 
28
29
  'use strict';
@@ -40,13 +41,6 @@ const {
40
41
  resolveMcpEntry,
41
42
  } = require(path.join(__dirname, '..', 'scripts', 'mcp-config'));
42
43
  const { trackEvent } = require(path.join(__dirname, '..', 'scripts', 'cli-telemetry'));
43
- const {
44
- cacheUpdateHookCommand,
45
- preToolHookCommand,
46
- sessionStartHookCommand,
47
- statuslineCommand,
48
- userPromptHookCommand,
49
- } = require(path.join(__dirname, '..', 'scripts', 'hook-runtime'));
50
44
  const {
51
45
  PRO_MONTHLY_PAYMENT_LINK,
52
46
  PRO_PRICE_LABEL,
@@ -395,84 +389,24 @@ function whichExists(cmd) {
395
389
 
396
390
  function setupClaude() {
397
391
  const mcpChanged = mergeMcpJson(path.join(CWD, '.mcp.json'), 'Claude Code', 'project');
392
+ const { wireHooks } = require(path.join(PKG_ROOT, 'scripts', 'auto-wire-hooks'));
393
+ const hookResult = wireHooks({ agent: 'claude-code' });
398
394
 
399
- // Wire the canonical ThumbGate gate hooks (PreToolUse pre-action check,
400
- // UserPromptSubmit, PostToolUse, SessionStart) through the shared wiring
401
- // path so `init`, `init --agent claude-code`, and `install` all produce the
402
- // same hook set. Before this, `install` shipped a Claude config with no
403
- // PreToolUse gate — the core ThumbGate feature was silently missing.
404
- let wireChanged = false;
405
- try {
406
- const { wireHooks } = require(path.join(PKG_ROOT, 'scripts', 'auto-wire-hooks'));
407
- const wireResult = wireHooks({ agent: 'claude-code' });
408
- if (wireResult.error) {
409
- console.log(` Claude Code: ${wireResult.error}`);
410
- } else if (wireResult.changed) {
411
- wireChanged = true;
412
- const lifecycles = [...new Set(wireResult.added.map((h) => h.lifecycle))].join(', ');
413
- console.log(` Claude Code: wired gate hooks (${lifecycles})`);
414
- }
415
- } catch (err) {
416
- console.log(` Claude Code: hook wiring skipped (${err.message})`);
417
- }
418
-
419
- // Upsert Stop hook into .claude/settings.json for autonomous self-scoring
420
- const settingsPath = path.join(CWD, '.claude', 'settings.json');
421
- const stopHookCommand = 'bash scripts/hook-stop-self-score.sh';
422
-
423
- let settings = { hooks: {} };
424
- if (fs.existsSync(settingsPath)) {
425
- try { settings = JSON.parse(fs.readFileSync(settingsPath, 'utf8')); } catch (_) { /* fresh */ }
426
- }
427
- settings.hooks = settings.hooks || {};
428
-
429
- const stopAlreadyPresent = (settings.hooks.Stop || [])
430
- .some(entry => (entry.hooks || []).some(h => h.command === stopHookCommand));
431
-
432
- let hooksChanged = false;
433
- if (!stopAlreadyPresent) {
434
- settings.hooks.Stop = settings.hooks.Stop || [];
435
- settings.hooks.Stop.push({ hooks: [{ type: 'command', command: stopHookCommand }] });
436
- hooksChanged = true;
437
- console.log(' Claude Code: installed Stop hook');
395
+ if (hookResult.error) {
396
+ console.log(` Claude Code hooks: ${hookResult.error}`);
397
+ return mcpChanged;
438
398
  }
439
399
 
440
- // Upsert PostToolUse hook for ThumbGate statusline cache updates
441
- const cacheHookCommand = cacheUpdateHookCommand();
442
- const originalPostToolUseCount = (settings.hooks.PostToolUse || []).length;
443
- settings.hooks.PostToolUse = (settings.hooks.PostToolUse || []).filter(
444
- (entry) => !(entry.hooks || []).some((h) => h.command && h.command !== cacheHookCommand && /(hook-thumbgate-cache-updater|cache-update\b)/.test(h.command))
445
- );
446
- if (settings.hooks.PostToolUse.length !== originalPostToolUseCount) {
447
- hooksChanged = true;
448
- }
449
- const cacheAlreadyPresent = (settings.hooks.PostToolUse || [])
450
- .some(entry => (entry.hooks || []).some(h => h.command === cacheHookCommand || (h.command && h.command.includes('cache-update'))));
451
-
452
- if (!cacheAlreadyPresent) {
453
- settings.hooks.PostToolUse = settings.hooks.PostToolUse || [];
454
- settings.hooks.PostToolUse.push({
455
- matcher: 'mcp__thumbgate__feedback_stats|mcp__thumbgate__dashboard',
456
- hooks: [{ type: 'command', command: cacheHookCommand }]
457
- });
458
- hooksChanged = true;
459
- console.log(' Claude Code: installed ThumbGate cache updater hook');
460
- }
461
-
462
- // Upsert statusLine for ThumbGate feedback display
463
- const statuslineScript = statuslineCommand();
464
- if (!settings.statusLine || settings.statusLine.command !== statuslineScript) {
465
- settings.statusLine = { type: 'command', command: statuslineScript };
466
- hooksChanged = true;
467
- console.log(' Claude Code: installed ThumbGate status line');
468
- }
469
-
470
- if (hooksChanged) {
471
- fs.mkdirSync(path.dirname(settingsPath), { recursive: true });
472
- fs.writeFileSync(settingsPath, JSON.stringify(settings, null, 2) + '\n');
400
+ if (!hookResult.changed) {
401
+ console.log(` Claude Code hooks: already configured at ${hookResult.settingsPath}`);
402
+ } else {
403
+ for (const h of hookResult.added) {
404
+ console.log(` Claude Code: wired ${h.lifecycle} hook`);
405
+ }
406
+ console.log(` Claude Code settings: ${hookResult.settingsPath}`);
473
407
  }
474
408
 
475
- return mcpChanged || hooksChanged || wireChanged;
409
+ return mcpChanged || hookResult.changed;
476
410
  }
477
411
 
478
412
  function setupCodex() {
@@ -744,7 +678,11 @@ function init(cliArgs = parseArgs(process.argv.slice(3))) {
744
678
  let configured = 0;
745
679
 
746
680
  const platforms = [
747
- { name: 'Claude Code', detect: [() => whichExists('claude'), () => fs.existsSync(path.join(HOME, '.claude'))], setup: setupClaude },
681
+ { name: 'Claude Code', detect: [
682
+ () => whichExists('claude'),
683
+ () => fs.existsSync(path.join(HOME, '.claude')),
684
+ () => fs.existsSync(path.join(CWD, '.claude')),
685
+ ], setup: setupClaude },
748
686
  { name: 'Codex', detect: [() => whichExists('codex'), () => fs.existsSync(path.join(HOME, '.codex'))], setup: setupCodex },
749
687
  { name: 'Gemini', detect: [() => whichExists('gemini'), () => fs.existsSync(path.join(HOME, '.gemini'))], setup: setupGemini },
750
688
  { name: 'Amp', detect: [() => whichExists('amp'), () => fs.existsSync(path.join(HOME, '.amp'))], setup: setupAmp },
@@ -940,7 +878,14 @@ function stats() {
940
878
  const { analyzeFeedback } = require(path.join(PKG_ROOT, 'scripts', 'feedback-loop'));
941
879
  const data = analyzeFeedback();
942
880
 
881
+ // Gate enforcement stats — runtime intercepts + configured gates
882
+ let gateData = { blocked: 0, warned: 0, passed: 0, byGate: {} };
883
+ try { gateData = require(path.join(PKG_ROOT, 'scripts', 'gates-engine')).loadStats(); } catch {}
884
+ let gateConfigData = { totalGates: 0, autoPromotedGates: 0, estimatedHoursSaved: '0.0', topBlocked: null, firstTimeFixRate: null };
885
+ try { gateConfigData = require(path.join(PKG_ROOT, 'scripts', 'gate-stats')).calculateStats(); } catch {}
886
+
943
887
  const avgCostOfMistake = 2.50;
888
+ const totalInterceptions = gateData.blocked + gateData.warned;
944
889
  const payload = {
945
890
  total: data.total,
946
891
  positives: data.totalPositive,
@@ -950,6 +895,13 @@ function stats() {
950
895
  revenueAtRisk: Number((data.totalNegative * avgCostOfMistake).toFixed(2)),
951
896
  topTags: data.topTags || [],
952
897
  recentActivity: data.recentActivity || [],
898
+ gatesBlocked: gateData.blocked,
899
+ gatesWarned: gateData.warned,
900
+ totalGates: gateConfigData.totalGates,
901
+ autoPromotedGates: gateConfigData.autoPromotedGates,
902
+ estimatedHoursSaved: gateConfigData.estimatedHoursSaved,
903
+ topBlockedGate: gateConfigData.topBlocked ? gateConfigData.topBlocked.id : null,
904
+ firstTimeFixRate: gateConfigData.firstTimeFixRate,
953
905
  };
954
906
 
955
907
  if (args.json) {
@@ -963,6 +915,18 @@ function stats() {
963
915
  console.log(` Approval Rate : ${payload.approvalRate}%`);
964
916
  console.log(` Recent Trend : ${payload.recentTrend}%`);
965
917
 
918
+ // Gate enforcement — the high-ROI section
919
+ if (totalInterceptions > 0 || payload.totalGates > 0) {
920
+ console.log('\n🛡️ PRE-ACTION GATE ENFORCEMENT');
921
+ console.log(` Actions blocked : ${payload.gatesBlocked}`);
922
+ console.log(` Actions warned : ${payload.gatesWarned}`);
923
+ console.log(` Active gates : ${payload.totalGates} (${payload.autoPromotedGates} auto-promoted)`);
924
+ if (payload.topBlockedGate) console.log(` Top blocker : ${payload.topBlockedGate}`);
925
+ console.log(` Est. time saved : ~${payload.estimatedHoursSaved} hours`);
926
+ const { formatFirstTimeFixRate } = require(path.join(PKG_ROOT, 'scripts', 'gate-stats'));
927
+ console.log(` First-time fix : ${formatFirstTimeFixRate(payload.firstTimeFixRate)}`);
928
+ }
929
+
966
930
  if (payload.negatives > 0) {
967
931
  console.log('\n⚠️ REVENUE-AT-RISK ANALYSIS');
968
932
  console.log(` Repeated Failures detected: ${payload.negatives}`);
@@ -1746,6 +1710,25 @@ function gateStats() {
1746
1710
  console.log('\n' + formatStats(stats) + '\n');
1747
1711
  }
1748
1712
 
1713
+ function contextPacks() {
1714
+ const args = parseArgs(process.argv.slice(3));
1715
+ const { generateAutoContextPacks } = require(path.join(PKG_ROOT, 'scripts', 'auto-context-packs'));
1716
+ const result = generateAutoContextPacks();
1717
+ if (args.json) {
1718
+ console.log(JSON.stringify(result, null, 2));
1719
+ return;
1720
+ }
1721
+ console.log(`\nGenerated ${result.packCount} context pack(s):`);
1722
+ for (const p of result.packs) {
1723
+ console.log(` [${p.type}] ${p.name}`);
1724
+ console.log(` -> ${p.filePath}`);
1725
+ }
1726
+ if (result.packCount === 0) {
1727
+ console.log(' (No failure patterns found yet — capture some feedback first.)');
1728
+ }
1729
+ console.log('');
1730
+ }
1731
+
1749
1732
  function harnessAudit() {
1750
1733
  const args = parseArgs(process.argv.slice(3));
1751
1734
  const {
@@ -2548,6 +2531,11 @@ switch (COMMAND) {
2548
2531
  case 'search-lessons':
2549
2532
  lessons();
2550
2533
  break;
2534
+ case 'notes': {
2535
+ const { cli: notesCli } = require(path.join(PKG_ROOT, 'scripts', 'implementation-notes'));
2536
+ notesCli(process.argv.slice(3));
2537
+ break;
2538
+ }
2551
2539
  case 'lesson-health':
2552
2540
  case 'stale': {
2553
2541
  const { initDB } = require(path.join(PKG_ROOT, 'scripts', 'lesson-db'));
@@ -2689,6 +2677,9 @@ switch (COMMAND) {
2689
2677
  case 'rules':
2690
2678
  rules();
2691
2679
  break;
2680
+ case 'context-packs':
2681
+ contextPacks();
2682
+ break;
2692
2683
  case 'harness-audit':
2693
2684
  case 'harness':
2694
2685
  harnessAudit();
@@ -2884,6 +2875,29 @@ switch (COMMAND) {
2884
2875
  }
2885
2876
  break;
2886
2877
  }
2878
+ case 'audit': {
2879
+ const auditFile = process.argv[3];
2880
+ if (!auditFile) {
2881
+ console.error('Usage: npx thumbgate audit <path-to-transcript.txt>');
2882
+ process.exit(1);
2883
+ }
2884
+ const { runAudit } = require(path.join(PKG_ROOT, 'scripts', 'audit'));
2885
+ const { results, totalWaste, error } = runAudit(auditFile);
2886
+ if (error) {
2887
+ console.error(error);
2888
+ process.exit(1);
2889
+ }
2890
+ console.log('\n🔍 AI Bill Audit Results\n');
2891
+ if (results.length === 0) {
2892
+ console.log('✅ No repeat-offender patterns found. Your sessions are efficient!');
2893
+ } else {
2894
+ console.table(results);
2895
+ console.log('\n💰 Total estimated monthly waste: $' + totalWaste);
2896
+ console.log('\nBlock these mistakes permanently with ThumbGate Pro:');
2897
+ console.log(PRO_CHECKOUT_URL);
2898
+ }
2899
+ break;
2900
+ }
2887
2901
  case 'dashboard':
2888
2902
  dashboard();
2889
2903
  break;
@@ -68,7 +68,8 @@
68
68
  "perplexity_search",
69
69
  "perplexity_ask",
70
70
  "perplexity_research",
71
- "perplexity_reason"
71
+ "perplexity_reason",
72
+ "suggest_fix"
72
73
  ],
73
74
  "essential": [
74
75
  "capture_feedback",
@@ -104,7 +105,8 @@
104
105
  "report_product_issue",
105
106
  "require_evidence_for_claim",
106
107
  "session_report",
107
- "generate_operator_artifact"
108
+ "generate_operator_artifact",
109
+ "suggest_fix"
108
110
  ],
109
111
  "commerce": [
110
112
  "capture_feedback",
@@ -123,7 +125,8 @@
123
125
  "workflow_sentinel",
124
126
  "prevention_rules",
125
127
  "feedback_stats",
126
- "feedback_summary"
128
+ "feedback_summary",
129
+ "suggest_fix"
127
130
  ],
128
131
  "readonly": [
129
132
  "recall",
@@ -164,7 +167,8 @@
164
167
  "session_report",
165
168
  "generate_operator_artifact",
166
169
  "perplexity_search",
167
- "perplexity_ask"
170
+ "perplexity_ask",
171
+ "suggest_fix"
168
172
  ],
169
173
  "dispatch": [
170
174
  "recall",
@@ -204,7 +208,8 @@
204
208
  "session_report",
205
209
  "generate_operator_artifact",
206
210
  "perplexity_search",
207
- "perplexity_ask"
211
+ "perplexity_ask",
212
+ "suggest_fix"
208
213
  ],
209
214
  "locked": [
210
215
  "feedback_summary",
@@ -228,7 +233,8 @@
228
233
  "workflow_sentinel",
229
234
  "settings_status",
230
235
  "native_messaging_audit",
231
- "generate_operator_artifact"
236
+ "generate_operator_artifact",
237
+ "suggest_fix"
232
238
  ]
233
239
  }
234
240
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "thumbgate",
3
- "version": "1.21.1",
3
+ "version": "1.22.0",
4
4
  "description": "ThumbGate self-improving agent governance: thumbs-up/down turns every mistake into a prevention rule and blocks repeat patterns. 33 pre-action checks, budget enforcement, and self-protection for Claude Code, Cursor, Codex, Gemini CLI, and Amp.",
5
5
  "homepage": "https://thumbgate-production.up.railway.app",
6
6
  "repository": {
@@ -31,6 +31,7 @@
31
31
  "scripts/analytics-window.js",
32
32
  "scripts/async-job-runner.js",
33
33
  "scripts/audit-trail.js",
34
+ "scripts/audit.js",
34
35
  "scripts/auto-promote-gates.js",
35
36
  "scripts/auto-wire-hooks.js",
36
37
  "scripts/autoresearch-runner.js",
@@ -222,6 +223,7 @@
222
223
  "openapi/",
223
224
  "public/agent-manager.html",
224
225
  "public/blog.html",
226
+ "public/codex-enterprise.html",
225
227
  "public/codex-plugin.html",
226
228
  "public/compare.html",
227
229
  "public/dashboard.html",
@@ -332,7 +334,7 @@
332
334
  "social:prospect:bluesky:dry": "node scripts/social-bluesky-prospecting.js --dry-run",
333
335
  "social:reply-publish:bluesky:dry": "node scripts/social-reply-monitor-bluesky.js --publish-approved --dry-run",
334
336
  "test:python": "python3 -m pytest tests/*.py",
335
- "test": "npm run test:python && npm run test:schema && npm run test:loop && npm run test:dpo && npm run test:kto && npm run test:api && npm run test:proof && npm run test:e2e && npm run test:rlaif && npm run test:attribution && npm run test:quality && npm run test:intelligence && npm run test:training-export && npm run test:deployment && npm run test:operational-integrity && npm run test:workflow && npm run test:billing && npm run test:cli && npm run test:watcher && npm run test:autoresearch && npm run test:ops && npm run test:session-analyzer && npm run test:tessl && npm run test:gates && npm run test:evoskill && npm run test:gates-hardening && npm run test:workers && npm run test:social-analytics && npm run test:memalign && npm run test:xmemory-lite && npm run test:filesystem-search && npm run test:zernio && npm run test:platform-limits && npm run test:post-video && npm run test:post-everywhere-instagram && npm run test:post-everywhere-channels && npm run test:post-everywhere-zernio-default && npm run test:zernio-canonical-pollers && npm run test:zernio-status && npm run test:obsidian-export && npm run test:lesson-db && npm run test:lesson-rotation && npm run test:memory-dedup && npm run test:feedback-quality && npm run test:sync-version && npm run test:check-congruence && npm run test:tool-registry && npm run test:feedback-to-rules && npm run test:memory-firewall && npm run test:memory-scope-readiness && npm run test:belief-update && npm run test:hosted-config && npm run test:operational-summary && npm run test:operational-dashboard && npm run test:operator-artifacts && npm run test:operator-key-auth && npm run test:cloudflare-sandbox && npm run test:mcp-config && npm run test:plan-gate && npm run test:pulse && npm run test:semantic-layer && npm run test:data-pipeline && npm run test:optimize-context && npm run test:principle-extractor && npm run test:analytics-window && npm run test:funnel-analytics && npm run test:experiment-tracker && npm run test:build-metadata && npm run test:context-engine && npm run test:hf-papers && npm run test:marketing-experiment && npm run test:seo-gsd && npm run test:verify-run && npm run test:export-dpo-pairs && npm run test:export-hf-dataset && npm run test:license && npm run test:bot-detector && npm run test:audit-pr-bot-contamination && npm run test:stripe-bootstrap-saas-catalog && npm run test:postinstall && npm run test:funnel-invariants && npm run test:cli-telemetry && npm run test:pro-parity && npm run test:model-tier-router && npm run test:computer-use-firewall && npm run test:skill-exporter && npm run test:statusline && npm run test:evolution && npm run test:org-dashboard && npm run test:multi-hop-recall && npm run test:synthetic-dpo && npm run test:thumbgate-skill && npm run test:learn-hub && npm run test:feedback-fallback && npm run test:metaclaw && npm run test:server-lock && npm run test:control-tower && npm run test:pii-scanner && npm run test:data-governance && npm run test:lesson-inference && npm run test:semantic-dedup && npm run test:fs-utils && npm run test:cli-schema && npm run test:explore && npm run test:lesson-reranker && npm run test:lesson-retrieval && npm run test:cross-encoder && npm run test:reflector-agent && npm run test:feedback-session && npm run test:feedback-history-distiller && npm run test:hallucination-detector && npm run test:history-distiller && npm run test:predictive-insights && npm run test:prove-predictive-insights && npm run test:statusbar-cli && npm run test:generate-instagram-card && npm run test:instagram-thumbgate-post && npm run test:publish-instagram-thumbgate && npm run test:lesson-synthesis && npm run test:lesson-canonical && npm run test:background-governance && npm run test:memory-migration && npm run test:prompt-dlp && npm run test:ephemeral-store && npm run test:agent-security && npm run test:skill-progressive && npm run test:per-step-scoring && npm run test:weekly-auto-post && npm run test:social-post-hourly && npm run test:social-quality-gate && npm run test:a2ui-engine && npm run test:gate-satisfy && npm run test:money-watcher && npm run test:budget && npm run test:quick-start && npm run test:utm && npm run test:product-feedback && npm run test:feedback-root-consolidator && npm run test:engagement-audit && npm run test:install-growth-automation && npm run test:publish-thumbgate-launch && npm run test:community-course-platform-launch-kit && npm run test:reconcile-thumbgate-campaign && npm run test:reddit-publisher && npm run test:schedule-thumbgate-campaign && npm run test:social-reply-monitor && npm run test:social-dedupe-cleanup && npm run test:sync-launch-assets && npm run test:ai-search-visibility && npm run test:perplexity && npm run test:security-scanner && npm run test:llm-client && npm run test:managed-lesson-agent && npm run test:self-distill && npm run test:meta-agent && npm run test:harness-selector && npm run test:thumbgate-bench && npm run test:seo-guides && npm run test:enforcement-loop && npm run test:cli-agent-experience && npm run test:bot-detection && npm run test:checkout-archived-product-guard && npm run test:postgres-guard && npm run test:checkout-bot-guard && npm run test:checkout-pro-confirmation-gate && npm run test:session-health && npm run test:session-episodes && npm run test:spec-gate && npm run test:decision-trace && npm run test:dashboard-insights && npm run test:telemetry-tracked-link-slug && npm run test:prompt-eval && npm run test:demo-voiceover && npm run test:gate-coherence && npm run test:gate-eval && npm run test:high-roi && npm run test:public-static-assets && npm run test:token-savings && npm run test:numbers-page && npm run test:workflow-gate-checkpoint && npm run test:lesson-export-import && npm run test:landing-page-claims && npm run test:competitive-positioning-marketing && npm run test:medium-weekly && npm run test:dashboard-deeplink-e2e && npm run test:public-package-parity && npm run test:token-savings-dashboard && npm run test:cursor-wiring && npm run test:pretooluse-injection && npm run test:recent-corrective-context && npm run test:durability-step && npm run test:mailer && npm run test:brand-assets && npm run test:enforcement-teeth && npm run test:bayes-optimal-gate && npm run test:swarm-coordinator && npm run test:session-report && npm run test:agent-reasoning-traces && npm run test:judge-reward && npm run test:llm-behavior-monitor && npm run test:prompting-os && npm run test:single-use-credential-gate && npm run test:structured-prompt-driven && npm run test:require-evidence-gate && npm run test:rule-validator && npm run test:bluesky-atproto && npm run test:social-reply-monitor-bluesky && npm run test:bluesky-delete-replies && npm run test:architect-kit-memory-bridge && npm run test:sonar-review-hotspots && npm run test:actionable-remediations && npm run test:gemini-embedding-policy && npm run test:agent-design-governance && npm run test:public-core-boundary && npm run test:hook-stop-verify-deploy && npm run test:hook-stop-anti-claim && npm run test:plausible-server-events && npm run test:activation-tracker && npm run test:unified-revenue-rollup && npm run test:conversion-rate-stats && npm run test:external-customer-audit && npm run test:telemetry-export && npm run test:stripe-checkout-diagnostic && npm run test:stripe-business-identity-probe && npm run test:revenue-observability-doctor && npm run test:public-bundle-ratchet && npm run test:stripe-payment-link-update && npm run test:ci-cd-hygiene-audit && npm run test:verify-marketing-pages-deployed && npm run test:install-email-capture",
337
+ "test": "npm run test:python && npm run test:schema && npm run test:loop && npm run test:dpo && npm run test:kto && npm run test:api && npm run test:proof && npm run test:e2e && npm run test:rlaif && npm run test:attribution && npm run test:quality && npm run test:intelligence && npm run test:training-export && npm run test:deployment && npm run test:operational-integrity && npm run test:workflow && npm run test:billing && npm run test:cli && npm run test:watcher && npm run test:autoresearch && npm run test:ops && npm run test:session-analyzer && npm run test:tessl && npm run test:gates && npm run test:evoskill && npm run test:gates-hardening && npm run test:workers && npm run test:social-analytics && npm run test:memalign && npm run test:xmemory-lite && npm run test:filesystem-search && npm run test:zernio && npm run test:platform-limits && npm run test:post-video && npm run test:post-everywhere-instagram && npm run test:post-everywhere-channels && npm run test:post-everywhere-zernio-default && npm run test:zernio-canonical-pollers && npm run test:zernio-status && npm run test:obsidian-export && npm run test:lesson-db && npm run test:lesson-rotation && npm run test:memory-dedup && npm run test:feedback-quality && npm run test:sync-version && npm run test:check-congruence && npm run test:tool-registry && npm run test:feedback-to-rules && npm run test:memory-firewall && npm run test:memory-scope-readiness && npm run test:belief-update && npm run test:hosted-config && npm run test:operational-summary && npm run test:operational-dashboard && npm run test:operator-artifacts && npm run test:operator-key-auth && npm run test:cloudflare-sandbox && npm run test:mcp-config && npm run test:plan-gate && npm run test:pulse && npm run test:semantic-layer && npm run test:data-pipeline && npm run test:optimize-context && npm run test:principle-extractor && npm run test:analytics-window && npm run test:funnel-analytics && npm run test:experiment-tracker && npm run test:build-metadata && npm run test:context-engine && npm run test:hf-papers && npm run test:marketing-experiment && npm run test:seo-gsd && npm run test:verify-run && npm run test:export-dpo-pairs && npm run test:export-hf-dataset && npm run test:license && npm run test:bot-detector && npm run test:audit-pr-bot-contamination && npm run test:stripe-bootstrap-saas-catalog && npm run test:postinstall && npm run test:funnel-invariants && npm run test:cli-telemetry && npm run test:pro-parity && npm run test:model-tier-router && npm run test:computer-use-firewall && npm run test:skill-exporter && npm run test:statusline && npm run test:evolution && npm run test:org-dashboard && npm run test:multi-hop-recall && npm run test:synthetic-dpo && npm run test:thumbgate-skill && npm run test:learn-hub && npm run test:feedback-fallback && npm run test:metaclaw && npm run test:server-lock && npm run test:control-tower && npm run test:pii-scanner && npm run test:data-governance && npm run test:lesson-inference && npm run test:semantic-dedup && npm run test:fs-utils && npm run test:cli-schema && npm run test:explore && npm run test:lesson-reranker && npm run test:lesson-retrieval && npm run test:cross-encoder && npm run test:reflector-agent && npm run test:feedback-session && npm run test:feedback-history-distiller && npm run test:hallucination-detector && npm run test:history-distiller && npm run test:predictive-insights && npm run test:prove-predictive-insights && npm run test:statusbar-cli && npm run test:generate-instagram-card && npm run test:instagram-thumbgate-post && npm run test:publish-instagram-thumbgate && npm run test:lesson-synthesis && npm run test:lesson-canonical && npm run test:background-governance && npm run test:memory-migration && npm run test:prompt-dlp && npm run test:ephemeral-store && npm run test:agent-security && npm run test:skill-progressive && npm run test:per-step-scoring && npm run test:weekly-auto-post && npm run test:social-post-hourly && npm run test:social-quality-gate && npm run test:a2ui-engine && npm run test:gate-satisfy && npm run test:money-watcher && npm run test:budget && npm run test:quick-start && npm run test:utm && npm run test:product-feedback && npm run test:feedback-root-consolidator && npm run test:engagement-audit && npm run test:install-growth-automation && npm run test:publish-thumbgate-launch && npm run test:community-course-platform-launch-kit && npm run test:reconcile-thumbgate-campaign && npm run test:reddit-publisher && npm run test:schedule-thumbgate-campaign && npm run test:social-reply-monitor && npm run test:social-dedupe-cleanup && npm run test:sync-launch-assets && npm run test:ai-search-visibility && npm run test:perplexity && npm run test:security-scanner && npm run test:llm-client && npm run test:managed-lesson-agent && npm run test:self-distill && npm run test:meta-agent && npm run test:harness-selector && npm run test:thumbgate-bench && npm run test:seo-guides && npm run test:enforcement-loop && npm run test:cli-agent-experience && npm run test:bot-detection && npm run test:checkout-archived-product-guard && npm run test:postgres-guard && npm run test:checkout-bot-guard && npm run test:checkout-pro-confirmation-gate && npm run test:session-health && npm run test:session-episodes && npm run test:spec-gate && npm run test:decision-trace && npm run test:dashboard-insights && npm run test:telemetry-tracked-link-slug && npm run test:prompt-eval && npm run test:demo-voiceover && npm run test:gate-coherence && npm run test:gate-eval && npm run test:high-roi && npm run test:public-static-assets && npm run test:token-savings && npm run test:numbers-page && npm run test:workflow-gate-checkpoint && npm run test:lesson-export-import && npm run test:landing-page-claims && npm run test:competitive-positioning-marketing && npm run test:medium-weekly && npm run test:dashboard-deeplink-e2e && npm run test:public-package-parity && npm run test:token-savings-dashboard && npm run test:cursor-wiring && npm run test:pretooluse-injection && npm run test:recent-corrective-context && npm run test:durability-step && npm run test:mailer && npm run test:brand-assets && npm run test:enforcement-teeth && npm run test:bayes-optimal-gate && npm run test:swarm-coordinator && npm run test:session-report && npm run test:agent-reasoning-traces && npm run test:judge-reward && npm run test:llm-behavior-monitor && npm run test:prompting-os && npm run test:single-use-credential-gate && npm run test:structured-prompt-driven && npm run test:require-evidence-gate && npm run test:rule-validator && npm run test:bluesky-atproto && npm run test:social-reply-monitor-bluesky && npm run test:bluesky-delete-replies && npm run test:architect-kit-memory-bridge && npm run test:sonar-review-hotspots && npm run test:actionable-remediations && npm run test:gemini-embedding-policy && npm run test:agent-design-governance && npm run test:public-core-boundary && npm run test:hook-stop-verify-deploy && npm run test:hook-stop-anti-claim && npm run test:plausible-server-events && npm run test:activation-tracker && npm run test:unified-revenue-rollup && npm run test:conversion-rate-stats && npm run test:external-customer-audit && npm run test:telemetry-export && npm run test:stripe-checkout-diagnostic && npm run test:stripe-business-identity-probe && npm run test:revenue-observability-doctor && npm run test:public-bundle-ratchet && npm run test:stripe-payment-link-update && npm run test:ci-cd-hygiene-audit && npm run test:verify-marketing-pages-deployed && npm run test:install-email-capture && npm run test:install-shim && npm run test:hook-runtime-subcommands && npm run test:implementation-notes",
336
338
  "test:hook-stop-verify-deploy": "node --test tests/hook-stop-verify-deploy.test.js",
337
339
  "test:hook-stop-anti-claim": "node --test tests/hook-stop-anti-claim.test.js",
338
340
  "test:plausible-server-events": "node --test tests/plausible-server-events.test.js",
@@ -442,10 +444,10 @@
442
444
  "test:evolution": "node --test tests/workspace-evolver.test.js",
443
445
  "test:watcher": "node --test tests/jsonl-watcher.test.js",
444
446
  "test:autoresearch": "node --test tests/autoresearch.test.js",
445
- "test:ops": "node --test tests/adk-consolidator.test.js tests/anthropic-partner-strategy.test.js tests/auto-promote-gates.test.js tests/auto-wire-hooks.test.js tests/claude-skill.test.js tests/codegraph-context.test.js tests/commercial-signals.test.js tests/decision-journal.test.js tests/delegation-runtime.test.js tests/disagreement-mining.test.js tests/failure-diagnostics.test.js tests/gate-stats.test.js tests/git-hook-installer.test.js tests/github-billing.test.js tests/intervention-policy.test.js tests/markdown-escape.test.js tests/mcp-tools-gates.test.js tests/native-messaging-audit.test.js tests/project-bayes-e2e.test.js tests/project-bayes.test.js tests/rate-limiter.test.js tests/schedule-manager.test.js tests/session-handoff.test.js tests/skill-generator.test.js tests/smart-learning.test.js tests/spike-and-sink.test.js tests/stripe-revenue.test.js tests/stripe-webhook-route.test.js tests/stripe-webhook-rotation.test.js tests/train-from-feedback.test.js tests/workflow-hardening-sprint.test.js tests/workflow-sentinel.test.js tests/test-suite-parity.test.js tests/a2ui-engine.test.js tests/webhook-delivery.test.js",
447
+ "test:ops": "node --test tests/adk-consolidator.test.js tests/anthropic-partner-strategy.test.js tests/auto-promote-gates.test.js tests/auto-wire-hooks.test.js tests/claude-skill.test.js tests/codegraph-context.test.js tests/commercial-signals.test.js tests/decision-journal.test.js tests/delegation-runtime.test.js tests/disagreement-mining.test.js tests/failure-diagnostics.test.js tests/gate-stats.test.js tests/git-hook-installer.test.js tests/github-billing.test.js tests/intervention-policy.test.js tests/markdown-escape.test.js tests/mcp-tools-gates.test.js tests/native-messaging-audit.test.js tests/project-bayes-e2e.test.js tests/project-bayes.test.js tests/rate-limiter.test.js tests/schedule-manager.test.js tests/session-handoff.test.js tests/skill-generator.test.js tests/smart-learning.test.js tests/spike-and-sink.test.js tests/stripe-revenue.test.js tests/stripe-webhook-route.test.js tests/stripe-webhook-rotation.test.js tests/train-from-feedback.test.js tests/workflow-hardening-sprint.test.js tests/workflow-sentinel.test.js tests/test-suite-parity.test.js tests/a2ui-engine.test.js tests/webhook-delivery.test.js tests/auto-context-packs.test.js",
446
448
  "test:session-analyzer": "node --test tests/session-analyzer.test.js",
447
449
  "test:tessl": "node --test tests/tessl-export.test.js",
448
- "test:gates": "node --test tests/gate-templates.test.js tests/gates-engine.test.js tests/claim-verification.test.js tests/secret-scanner.test.js tests/secret-fixture-safety.test.js tests/prompt-guard.test.js tests/audit-trail.test.js tests/profile-router.test.js tests/workflow-sentinel.test.js tests/docker-sandbox-planner.test.js",
450
+ "test:gates": "node --test tests/gate-templates.test.js tests/gates-engine.test.js tests/claim-verification.test.js tests/secret-scanner.test.js tests/secret-fixture-safety.test.js tests/prompt-guard.test.js tests/audit-trail.test.js tests/profile-router.test.js tests/workflow-sentinel.test.js tests/docker-sandbox-planner.test.js tests/mcp-tools-suggest-fix.test.js",
449
451
  "test:budget": "node --test tests/budget-enforcer.test.js",
450
452
  "test:workers": "npm --prefix workers ci && npm --prefix workers test",
451
453
  "test:evoskill": "node --test tests/evoskill.test.js",
@@ -659,7 +661,15 @@
659
661
  "test:stripe-payment-link-update": "node --test tests/stripe-payment-link-update.test.js",
660
662
  "test:verify-marketing-pages-deployed": "node --test tests/verify-marketing-pages-deployed.test.js",
661
663
  "verify:marketing-pages": "node scripts/verify-marketing-pages-deployed.js",
662
- "test:install-email-capture": "node --test tests/install-email-capture.test.js"
664
+ "test:install-email-capture": "node --test tests/install-email-capture.test.js",
665
+ "test:install-shim": "node --test tests/install-shim.test.js",
666
+ "test:hook-runtime-subcommands": "node --test tests/hook-runtime-subcommands.test.js",
667
+ "test:implementation-notes": "node --test tests/implementation-notes.test.js",
668
+ "test:lessons-page-clickability": "playwright test tests/e2e/lessons-page-clickability.spec.js",
669
+ "test:index-page-clickability": "playwright test tests/e2e/index-page-clickability.spec.js",
670
+ "test:dashboard-page-clickability": "playwright test tests/e2e/dashboard-page-clickability.spec.js",
671
+ "test:agent-manager-page-clickability": "playwright test tests/e2e/agent-manager-page-clickability.spec.js",
672
+ "test:pricing-page-clickability": "playwright test tests/e2e/pricing-page-clickability.spec.js"
663
673
  },
664
674
  "keywords": [
665
675
  "mcp",
@@ -76,7 +76,7 @@
76
76
  </tr>
77
77
  <tr>
78
78
  <td><strong>Plugin marketplace</strong><br>Deciding which Claude Code / Cursor / Codex plugins are blessed and which are not.</td>
79
- <td>ThumbGate ships as a Claude Code plugin, a Cursor extension, a Codex plugin, and a Gemini CLI hook. One install, every supported agent. Adapter compatibility matrix kept current as runtimes change.</td>
79
+ <td>ThumbGate ships as a Claude Code plugin, a Cursor extension (Marketplace listing pending Cursor's review since 2026-05-19; runtime install works today via <code>npx thumbgate init --agent cursor</code>), a Codex plugin, and a Gemini CLI hook. One install, every supported agent. Adapter compatibility matrix kept current as runtimes change.</td>
80
80
  </tr>
81
81
  <tr>
82
82
  <td><strong>Permissions policy</strong><br>What an agent is allowed to execute, against which surfaces, with which evidence required.</td>