thumbgate 1.4.1 → 1.4.3

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 (60) hide show
  1. package/.claude-plugin/README.md +45 -34
  2. package/.claude-plugin/marketplace.json +3 -3
  3. package/.claude-plugin/plugin.json +3 -3
  4. package/.well-known/llms.txt +1 -1
  5. package/.well-known/mcp/server-card.json +1 -1
  6. package/README.md +26 -2
  7. package/adapters/README.md +4 -1
  8. package/adapters/chatgpt/INSTALL.md +39 -19
  9. package/adapters/claude/.mcp.json +2 -2
  10. package/adapters/codex/config.toml +2 -2
  11. package/adapters/mcp/server-stdio.js +10 -4
  12. package/adapters/opencode/opencode.json +1 -1
  13. package/adapters/perplexity/.mcp.json +36 -0
  14. package/adapters/perplexity/config.toml +16 -0
  15. package/adapters/perplexity/opencode.json +29 -0
  16. package/bin/cli.js +246 -90
  17. package/config/mcp-allowlists.json +11 -3
  18. package/package.json +28 -13
  19. package/plugins/claude-codex-bridge/.claude-plugin/plugin.json +1 -1
  20. package/plugins/claude-codex-bridge/.mcp.json +1 -1
  21. package/plugins/codex-profile/.codex-plugin/plugin.json +1 -1
  22. package/plugins/codex-profile/.mcp.json +1 -1
  23. package/plugins/codex-profile/INSTALL.md +1 -1
  24. package/plugins/codex-profile/README.md +1 -1
  25. package/plugins/cursor-marketplace/.cursor-plugin/plugin.json +1 -1
  26. package/plugins/opencode-profile/INSTALL.md +1 -1
  27. package/public/index.html +121 -24
  28. package/public/llm-context.md +17 -1
  29. package/scripts/ai-search-visibility.js +10 -36
  30. package/scripts/audit-trail.js +25 -15
  31. package/scripts/auto-wire-hooks.js +127 -0
  32. package/scripts/cli-demo.js +102 -0
  33. package/scripts/cli-schema.js +285 -0
  34. package/scripts/cli-status.js +166 -0
  35. package/scripts/cross-encoder-reranker.js +235 -0
  36. package/scripts/explore-subcommands.js +277 -0
  37. package/scripts/explore.js +569 -0
  38. package/scripts/feedback-loop.js +20 -6
  39. package/scripts/lesson-inference.js +27 -2
  40. package/scripts/lesson-reranker.js +263 -0
  41. package/scripts/lesson-retrieval.js +34 -17
  42. package/scripts/lesson-search.js +69 -0
  43. package/scripts/perplexity-client.js +210 -0
  44. package/scripts/perplexity-command-center.js +644 -0
  45. package/scripts/perplexity-marketing.js +17 -29
  46. package/scripts/prove-packaged-runtime.js +5 -4
  47. package/scripts/ralph-mode-ci.js +122 -19
  48. package/scripts/reflector-agent.js +2 -2
  49. package/scripts/session-analyzer.js +533 -0
  50. package/scripts/social-analytics/db/marketing-db.js +179 -0
  51. package/scripts/social-analytics/db/schema.sql +23 -0
  52. package/scripts/social-analytics/generate-instagram-card.js +31 -5
  53. package/scripts/social-analytics/generate-slides.js +268 -0
  54. package/scripts/social-analytics/post-video.js +316 -0
  55. package/scripts/social-analytics/publishers/zernio.js +52 -23
  56. package/scripts/statusline-local-stats.js +3 -1
  57. package/scripts/statusline.sh +15 -10
  58. package/scripts/thumbgate-bench.js +494 -0
  59. package/src/api/server.js +65 -1
  60. package/scripts/social-analytics/db/analytics.sqlite +0 -0
@@ -45,7 +45,7 @@ That profile launches:
45
45
  ```toml
46
46
  [mcp_servers.thumbgate]
47
47
  command = "npx"
48
- args = ["--yes", "--package", "thumbgate@1.4.0", "thumbgate", "serve"]
48
+ args = ["--yes", "--package", "thumbgate@1.4.3", "thumbgate", "serve"]
49
49
  ```
50
50
 
51
51
  ### Build from source
@@ -2,7 +2,7 @@
2
2
  "name": "thumbgate",
3
3
  "displayName": "ThumbGate",
4
4
  "description": "👍👎 Thumbs down a mistake — your AI agent won't repeat it. Thumbs up good work — it remembers the pattern.",
5
- "version": "1.4.0",
5
+ "version": "1.4.3",
6
6
  "author": {
7
7
  "name": "Igor Ganapolsky"
8
8
  },
@@ -25,7 +25,7 @@ The portable profile adds this MCP server entry:
25
25
  "mcp": {
26
26
  "thumbgate": {
27
27
  "type": "local",
28
- "command": ["npx", "--yes", "--package", "thumbgate@1.4.0", "thumbgate", "serve"],
28
+ "command": ["npx", "--yes", "--package", "thumbgate@1.4.3", "thumbgate", "serve"],
29
29
  "enabled": true
30
30
  }
31
31
  }
package/public/index.html CHANGED
@@ -11,8 +11,8 @@
11
11
  Created with Perplexity Computer
12
12
  https://www.perplexity.ai/computer
13
13
  -->
14
- <meta name="generator" content="Perplexity Computer">
15
- <meta name="author" content="Perplexity Computer">
14
+ <meta name="generator" content="ThumbGate">
15
+ <meta name="author" content="Igor Ganapolsky">
16
16
  <meta property="og:see_also" content="https://www.perplexity.ai/computer">
17
17
  <link rel="author" href="https://www.perplexity.ai/computer">
18
18
 
@@ -59,6 +59,7 @@ __GA_BOOTSTRAP__
59
59
  },
60
60
  "featureList": [
61
61
  "Pre-Action Gates — block known-bad tool calls before execution",
62
+ "ThumbGate GPT for ChatGPT — check proposed agent actions, capture thumbs-up/down lessons, and route users into local enforcement",
62
63
  "Workflow Sentinel — score blast radius before PR, merge, release, and publish actions fire",
63
64
  "Docker Sandboxes routing — move high-risk local runs into isolated microVM-backed execution",
64
65
  "Hosted sandbox dispatch — signed isolated lane for team automations",
@@ -184,6 +185,14 @@ __GA_BOOTSTRAP__
184
185
  "text": "Claude Code, Cursor, Codex, Gemini CLI, Amp, OpenCode, and any MCP-compatible agent."
185
186
  }
186
187
  },
188
+ {
189
+ "@type": "Question",
190
+ "name": "Do I have to chat inside the ThumbGate GPT for enforcement?",
191
+ "acceptedAnswer": {
192
+ "@type": "Answer",
193
+ "text": "No. The ThumbGate GPT is the ChatGPT entrypoint for checking proposed actions, capturing thumbs-up/down lessons, and getting setup help. Hard enforcement still runs locally where the agent executes after npx thumbgate init."
194
+ }
195
+ },
187
196
  {
188
197
  "@type": "Question",
189
198
  "name": "How does ThumbGate reduce host blast radius for high-risk local runs?",
@@ -277,6 +286,8 @@ __GA_BOOTSTRAP__
277
286
  .hero-actions { display: flex; justify-content: center; flex-wrap: wrap; gap: 12px; margin: 0 auto 16px; max-width: 760px; }
278
287
  .btn-pro-page { display: inline-flex; align-items: center; justify-content: center; padding: 11px 18px; background: var(--cyan); color: var(--bg); border-radius: 999px; text-decoration: none; font-size: 14px; font-weight: 700; box-shadow: 0 0 0 1px rgba(34,211,238,0.28), 0 12px 32px rgba(34,211,238,0.18); transition: opacity 0.15s, transform 0.15s; }
279
288
  .btn-pro-page:hover { opacity: 0.9; transform: translateY(-1px); }
289
+ .btn-gpt-page { display: inline-flex; align-items: center; justify-content: center; padding: 14px 32px; background: var(--green); color: #06120a; border-radius: 8px; text-decoration: none; font-size: 16px; font-weight: 800; box-shadow: 0 0 0 1px rgba(74,222,128,0.32), 0 12px 32px rgba(74,222,128,0.18); transition: opacity 0.15s, transform 0.15s; }
290
+ .btn-gpt-page:hover { opacity: 0.92; transform: translateY(-1px); }
280
291
  .hero-paid-note { font-size: 14px; color: var(--text-muted); max-width: 720px; margin: 0 auto 24px; }
281
292
  .hero-paid-note strong { color: var(--text); }
282
293
  .hero-install { background: var(--bg-raised); border: 1px solid var(--border); border-radius: 10px; padding: 14px 24px; display: inline-flex; align-items: center; gap: 12px; font-family: var(--mono); font-size: 15px; margin-bottom: 40px; cursor: pointer; transition: border-color 0.2s; position: relative; max-width: 100%; overflow-x: auto; }
@@ -302,6 +313,18 @@ __GA_BOOTSTRAP__
302
313
  .compat-card p { font-size: 14px; color: var(--text-muted); line-height: 1.6; }
303
314
  .compat-card code { font-family: var(--mono); font-size: 12px; background: rgba(34,211,238,0.08); color: var(--cyan); padding: 2px 6px; border-radius: 4px; }
304
315
 
316
+ /* CHATGPT GPT PATH */
317
+ .gpt-path { padding: 0 0 80px; }
318
+ .gpt-panel { border: 1px solid rgba(74,222,128,0.32); background: linear-gradient(180deg, rgba(17,17,19,0.98) 0%, rgba(15,24,18,0.96) 100%); border-radius: 8px; padding: 28px; }
319
+ .gpt-panel h2 { font-size: clamp(24px, 3vw, 34px); line-height: 1.15; letter-spacing: -0.025em; margin-bottom: 12px; }
320
+ .gpt-panel > p { color: var(--text-muted); max-width: 780px; margin-bottom: 22px; }
321
+ .gpt-steps { display: grid; grid-template-columns: repeat(3, 1fr); gap: 14px; margin: 24px 0; }
322
+ .gpt-step { border: 1px solid var(--border); border-radius: 8px; background: rgba(10,10,11,0.58); padding: 18px; }
323
+ .gpt-step strong { display: block; color: var(--green); margin-bottom: 6px; }
324
+ .gpt-step p { color: var(--text-muted); font-size: 14px; line-height: 1.55; }
325
+ .gpt-note { font-size: 13px; color: var(--text-muted); border-top: 1px solid var(--border); padding-top: 16px; }
326
+ .gpt-note strong { color: var(--text); }
327
+
305
328
  /* SEO PAGES */
306
329
  .seo-pages { padding: 0 0 80px; }
307
330
  .seo-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: 20px; }
@@ -402,6 +425,13 @@ __GA_BOOTSTRAP__
402
425
  .final-cta p { font-size: 15px; color: var(--text-muted); margin-bottom: 28px; }
403
426
  .final-cta .btn-pro, .final-cta .btn-team { display: inline-block; padding: 12px 32px; font-size: 15px; border-radius: 8px; margin: 0 6px; }
404
427
 
428
+ /* STICKY BOTTOM CTA BAR */
429
+ .sticky-cta { position: fixed; bottom: 0; left: 0; right: 0; z-index: 999; background: rgba(10,10,10,0.96); border-top: 1px solid var(--border); padding: 12px 20px; display: flex; align-items: center; justify-content: center; gap: 12px; transform: translateY(100%); transition: transform 0.3s ease; backdrop-filter: blur(8px); }
430
+ .sticky-cta.visible { transform: translateY(0); }
431
+ .sticky-cta-text { font-size: 14px; color: var(--text-muted); }
432
+ .sticky-cta-text strong { color: var(--text); }
433
+ .sticky-cta .btn-pro, .sticky-cta .btn-gpt-page { padding: 8px 20px; font-size: 13px; border-radius: 6px; white-space: nowrap; }
434
+
405
435
  /* FOOTER */
406
436
  footer { border-top: 1px solid var(--border); padding: 32px 0; }
407
437
  footer .container { display: flex; justify-content: space-between; align-items: center; flex-wrap: wrap; gap: 12px; }
@@ -414,6 +444,7 @@ __GA_BOOTSTRAP__
414
444
  @media (max-width: 700px) {
415
445
  .steps { grid-template-columns: 1fr; }
416
446
  .compatibility-grid { grid-template-columns: 1fr; }
447
+ .gpt-steps { grid-template-columns: 1fr; }
417
448
  .seo-grid { grid-template-columns: 1fr; }
418
449
  .pricing-grid { grid-template-columns: 1fr; }
419
450
  .team-form { grid-template-columns: 1fr; }
@@ -429,9 +460,11 @@ __GA_BOOTSTRAP__
429
460
  <script>
430
461
  !function(t,e){var o,n,p,r;e.__SV||(window.posthog=e,e._i=[],e.init=function(i,s,a){function g(t,e){var o=e.split(".");2==o.length&&(t=t[o[0]],e=o[1]),t[e]=function(){t.push([e].concat(Array.prototype.slice.call(arguments,0)))}}(p=t.createElement("script")).type="text/javascript",p.crossOrigin="anonymous",p.async=!0,p.src=s.api_host.replace(".i.posthog.com","-assets.i.posthog.com")+"/static/array.js",(r=t.getElementsByTagName("script")[0]).parentNode.insertBefore(p,r);var u=e;for(void 0!==a?u=e[a]=[]:a=u._i.push([i,s,a]),u._i.push([i,s,a]),u.init=function(t,e,i){g(u,"capture"),u.push(["init",t,e,i])},u.capture=function(t,e,i,o){u.push(["capture",t,e,i,o])},u.identify=function(t,e,i){u.push(["identify",t,e,i])},u.alias=function(t,e){u.push(["alias",t,e])},u.people={set:function(t,e,i){u.push(["people.set",t,e,i])}},u.featureFlags={},u.onFeatureFlags=function(t){u.push(["onFeatureFlags",t])},u.toString=function(t){var e="posthog";return a&&a!==e&&(e+="."+a),t||(e+=" (stub)"),e},u.people.set_once=function(t,e,i){u.push(["people.set_once",t,e,i])},u.group=function(t,e,i){u.push(["group",t,e,i])},u.setPersonPropertiesForFlags=function(t){u.push(["setPersonPropertiesForFlags",t])},u.resetGroupPropertiesForFlags=function(t){u.push(["resetGroupPropertiesForFlags",t])},u.setGroupPropertiesForFlags=function(t){u.push(["setGroupPropertiesForFlags",t])},u.reloadFeatureFlags=function(){u.push(["reloadFeatureFlags"])},u.capture=function(t,e,i,o){u.push(["capture",t,e,i,o])},u.identify=function(t,e,i){u.push(["identify",t,e,i])},0===t.indexOf(".")){var s=t.substring(1);u=e[s]=[],u._i=[]}e._i.push([i,s,a])},e.__SV=1)}(document,window.posthog||[]);
431
462
  posthog.init('__POSTHOG_API_KEY__', {
432
- api_host: 'https://us.i.posthog.com',
463
+ api_host: '/ingest',
464
+ ui_host: 'https://us.posthog.com',
433
465
  person_profiles: 'identified_only',
434
466
  });
467
+ posthog.capture('$pageview');
435
468
  </script>
436
469
  </head>
437
470
  <body>
@@ -451,7 +484,8 @@ __GA_BOOTSTRAP__
451
484
  <a href="/learn">Learn</a>
452
485
  <a href="/compare">Compare</a>
453
486
  <a href="/dashboard">Dashboard Demo</a>
454
- <a href="#workflow-sprint-intake" onclick="posthog.capture('workflow_sprint')" class="nav-cta">Start Sprint</a>
487
+ <a href="#workflow-sprint-intake" onclick="posthog.capture('workflow_sprint')">Start Sprint</a>
488
+ <a href="https://chatgpt.com/g/g-69dcfd1cd5f881918ae31874631d6f08-thumbgate" target="_blank" rel="noopener" onclick="posthog.capture('nav_cta_click',{cta:'open_gpt'})" class="nav-cta">Open GPT</a>
455
489
  </div>
456
490
  </div>
457
491
  </nav>
@@ -460,9 +494,9 @@ __GA_BOOTSTRAP__
460
494
  <section class="hero">
461
495
  <div class="container">
462
496
  <div class="hero-thumbs">👍👎</div>
463
- <div class="hero-badge">● Your AI agent just made that mistake again</div>
497
+ <div class="hero-badge">● Live ThumbGate GPT for ChatGPT</div>
464
498
  <h1>Your AI agent just made<br>that mistake again.<br><span style="color:var(--cyan)">One thumbs-down.<br>It never happens again.</span></h1>
465
- <p style="font-size:18px;color:var(--text-muted);max-width:560px;margin:0 auto 20px;line-height:1.6;">Session 1: your agent force-pushes, skips tests, or runs a DROP on prod.<br>You give it a 👎.<br><strong style="color:var(--text)">Session 2: gate fires. Action blocked before execution.</strong></p>
499
+ <p style="font-size:18px;color:var(--text-muted);max-width:620px;margin:0 auto 20px;line-height:1.6;">Start in ChatGPT: paste the proposed action into the live ThumbGate GPT and get allow, block, or checkpoint guidance.<br><strong style="color:var(--text)">Then enforce locally with <code>npx thumbgate init</code> where your agent actually runs.</strong></p>
466
500
  <div class="hero-signals">
467
501
  <div class="signal-pill signal-down">👎 Repeated failure becomes enforcement before the next run</div>
468
502
  <div class="signal-pill signal-up">✅ Safe pattern reinforced across the shared workflow</div>
@@ -470,17 +504,18 @@ __GA_BOOTSTRAP__
470
504
  </div>
471
505
  <p class="hero-persona" style="display:none">For consultancies, platform teams, and AI product teams with one workflow owner, one repeated failure, and one buyer who needs proof before a wider rollout.</p>
472
506
  <div class="hero-actions" style="margin-top:32px;">
507
+ <a href="https://chatgpt.com/g/g-69dcfd1cd5f881918ae31874631d6f08-thumbgate" class="btn-gpt-page" target="_blank" rel="noopener" onclick="posthog.capture('hero_cta_click',{cta:'open_gpt'})">Open ThumbGate GPT</a>
473
508
  <div class="hero-install" onclick="copyInstall(this)" title="Click to copy" style="margin-bottom:0;">
474
509
  <span class="prompt">$</span>
475
510
  <span class="cmd">npx thumbgate init</span>
476
511
  <span class="copy-hint">click to copy</span>
477
512
  </div>
513
+ <a href="/checkout/pro?utm_source=website&utm_medium=hero_cta&utm_campaign=pro_trial&cta_id=hero_start_trial" onclick="posthog.capture('hero_cta_click',{cta:'start_trial'})" class="btn-pro-page" style="font-size:16px;padding:14px 24px;margin-bottom:4px;">Start 7-day free trial</a>
478
514
  <a href="https://github.com/IgorGanapolsky/ThumbGate" target="_blank" rel="noopener" class="btn-free" style="display:inline-flex;align-items:center;gap:6px;padding:11px 20px;border-radius:999px;">⭐ Star on GitHub</a>
479
- <a href="https://github.com/IgorGanapolsky/ThumbGate/blob/main/adapters/chatgpt/INSTALL.md" class="btn-install-link" target="_blank" rel="noopener" style="font-size:13px;color:var(--text-muted);text-decoration:none;padding:8px 14px;">Use in ChatGPT →</a>
480
515
  <a href="https://github.com/IgorGanapolsky/ThumbGate/releases/latest/download/thumbgate-codex-plugin.zip" class="btn-install-link" target="_blank" rel="noopener" style="font-size:13px;color:var(--text-muted);text-decoration:none;padding:8px 14px;">Install Codex plugin →</a>
481
516
  </div>
482
- <p style="font-size:13px;color:var(--text-muted);margin:16px auto 0;max-width:480px;">Free to install. No cloud account needed. Works in 30 seconds.</p>
483
- <p style="font-size:13px;color:var(--text-muted);margin:8px auto 28px;max-width:480px;">Team plan is intake-first — one workflow, one repeat failure, proof before wider rollout. Stop vibe coding mistakes from repeating. <a href="#pricing" style="color:var(--cyan);text-decoration:none;">See pricing →</a></p>
517
+ <p style="font-size:13px;color:var(--text-muted);margin:16px auto 0;max-width:620px;">No, you do not have to chat inside the GPT forever. The GPT is the fastest demo and setup path; local hooks do the hard blocking for Claude Code, Cursor, Codex, Gemini, Amp, OpenCode, and MCP-compatible agents.</p>
518
+ <p style="font-size:13px;color:var(--text-muted);margin:8px auto 28px;max-width:480px;">Team plan is intake-first — one workflow, one repeat failure, proof before wider rollout. Pro stays the solo side lane for gate debugger, DPO export, and personal dashboard. <a href="#pricing" style="color:var(--cyan);text-decoration:none;">See all plans →</a></p>
484
519
  <div class="proof-bar">
485
520
  <a href="/guide" rel="noopener">CLI-first setup guide →</a>
486
521
  <span class="dot"></span>
@@ -490,7 +525,9 @@ __GA_BOOTSTRAP__
490
525
  <span class="dot"></span>
491
526
  <a href="https://github.com/IgorGanapolsky/ThumbGate/blob/main/.claude-plugin/README.md" target="_blank" rel="noopener">Claude marketplace install →</a>
492
527
  <span class="dot"></span>
493
- <a href="https://github.com/IgorGanapolsky/ThumbGate/blob/main/adapters/chatgpt/INSTALL.md" target="_blank" rel="noopener">ChatGPT GPT Actions →</a>
528
+ <a href="https://chatgpt.com/g/g-69dcfd1cd5f881918ae31874631d6f08-thumbgate" target="_blank" rel="noopener">Open ThumbGate GPT →</a>
529
+ <span class="dot"></span>
530
+ <a href="https://github.com/IgorGanapolsky/ThumbGate/blob/main/adapters/chatgpt/INSTALL.md" target="_blank" rel="noopener">ChatGPT Actions setup →</a>
494
531
  <span class="dot"></span>
495
532
  <a href="https://github.com/IgorGanapolsky/ThumbGate/releases/latest/download/thumbgate-codex-plugin.zip" target="_blank" rel="noopener">Codex plugin download →</a>
496
533
  <span class="dot"></span>
@@ -502,12 +539,16 @@ __GA_BOOTSTRAP__
502
539
  <span class="dot"></span>
503
540
  <a href="https://cloud.google.com/blog/topics/healthcare-life-sciences/ensuring-safety-and-quality-in-healthcare-qa-agents" target="_blank" rel="noopener">Google Cloud safety framework architecture →</a>
504
541
  <span class="dot"></span>
542
+ <a href="https://www.nytimes.com/2026/04/06/technology/ai-cybersecurity.html" target="_blank" rel="noopener">NYT: AI agents as attack vectors (April 2026) →</a>
543
+ <span class="dot"></span>
505
544
  <a href="https://www.producthunt.com/products/thumbgate" target="_blank" rel="noopener">Product Hunt →</a>
506
545
  <span class="dot"></span>
507
546
  <a href="https://github.com/IgorGanapolsky/ThumbGate/actions" target="_blank" rel="noopener">Proof-backed CI →</a>
508
547
  <span class="dot"></span>
509
548
  <a href="https://github.com/IgorGanapolsky/ThumbGate/blob/main/docs/RELEASE_CONFIDENCE.md" target="_blank" rel="noopener">Release confidence →</a>
510
549
  <span class="dot"></span>
550
+ <a href="https://github.com/IgorGanapolsky/ThumbGate/blob/main/docs/THUMBGATE_BENCH.md" target="_blank" rel="noopener">ThumbGate Bench →</a>
551
+ <span class="dot"></span>
511
552
  <a href="https://github.com/IgorGanapolsky/ThumbGate/actions" target="_blank" rel="noopener">CI and proof lanes →</a>
512
553
  <span class="dot"></span>
513
554
  <a href="#compatibility">Claude Code · Cursor · Codex · Gemini · Amp · OpenCode</a>
@@ -515,6 +556,35 @@ __GA_BOOTSTRAP__
515
556
  </div>
516
557
  </section>
517
558
 
559
+ <section class="gpt-path" id="thumbgate-gpt">
560
+ <div class="container">
561
+ <div class="gpt-panel">
562
+ <div class="section-label" style="text-align:left;">ChatGPT Entry Point</div>
563
+ <h2>Open the GPT. Check the action. Turn the lesson into a gate.</h2>
564
+ <p>ThumbGate should meet users where they already ask AI for help. The live GPT is the lowest-friction way to understand the product before installing anything.</p>
565
+ <div class="gpt-steps">
566
+ <div class="gpt-step">
567
+ <strong>1. Try the live GPT</strong>
568
+ <p>Paste a proposed command, file edit, merge, deploy, payment, email, or API call and ask what should happen next.</p>
569
+ </div>
570
+ <div class="gpt-step">
571
+ <strong>2. Save the signal</strong>
572
+ <p>Reply with <code>thumbs up:</code> or <code>thumbs down:</code> plus one concrete sentence. One signal becomes one remembered rule.</p>
573
+ </div>
574
+ <div class="gpt-step">
575
+ <strong>3. Enforce locally</strong>
576
+ <p>Run <code>npx thumbgate init</code> in the repo so Pre-Action Gates block repeated mistakes before the coding agent executes them.</p>
577
+ </div>
578
+ </div>
579
+ <div style="display:flex;gap:12px;flex-wrap:wrap;">
580
+ <a href="https://chatgpt.com/g/g-69dcfd1cd5f881918ae31874631d6f08-thumbgate" class="btn-gpt-page" target="_blank" rel="noopener" onclick="posthog.capture('gpt_path_cta_click',{cta:'open_gpt'})">Open ThumbGate GPT</a>
581
+ <a href="https://github.com/IgorGanapolsky/ThumbGate/blob/main/adapters/chatgpt/INSTALL.md" class="btn-free" target="_blank" rel="noopener" style="display:inline-flex;align-items:center;padding:12px 20px;border-radius:8px;">ChatGPT Actions setup</a>
582
+ </div>
583
+ <p class="gpt-note"><strong>Plain English rule:</strong> ChatGPT is the discovery and memory surface. The hard Reliability Gateway still runs in the local agent or CI lane.</p>
584
+ </div>
585
+ </div>
586
+ </section>
587
+
518
588
  <section class="compatibility" id="compatibility">
519
589
  <div class="container">
520
590
  <div class="section-label">Compatibility</div>
@@ -530,10 +600,10 @@ __GA_BOOTSTRAP__
530
600
  <p>Codex ships with a published standalone ThumbGate plugin bundle plus a repo-local plugin profile. Download the zip, extract it, and install without wiring MCP by hand.</p>
531
601
  <div class="card-arrow">Get the Codex plugin →</div>
532
602
  </a>
533
- <a class="compat-card" href="https://github.com/IgorGanapolsky/ThumbGate/blob/main/adapters/chatgpt/INSTALL.md" target="_blank" rel="noopener">
603
+ <a class="compat-card" href="https://chatgpt.com/g/g-69dcfd1cd5f881918ae31874631d6f08-thumbgate" target="_blank" rel="noopener">
534
604
  <h3>💬 ChatGPT GPT Actions</h3>
535
- <p>Regular users reply with 👍/👎 or "thumbs up/down" on ChatGPT answers, save the lesson, prevent repeated bad answers, and reinforce the answer patterns that worked.</p>
536
- <div class="card-arrow">Use in ChatGPT →</div>
605
+ <p>Open the ThumbGate GPT to check proposed AI actions, capture thumbs-up/down lessons, and get setup guidance. Real blocking for coding agents still runs locally after <code>npx thumbgate init</code>.</p>
606
+ <div class="card-arrow">Open ThumbGate GPT →</div>
537
607
  </a>
538
608
  <a class="compat-card" href="/guides/claude-desktop">
539
609
  <h3>🧩 Claude Desktop plugin</h3>
@@ -648,7 +718,7 @@ __GA_BOOTSTRAP__
648
718
  <!-- HOW IT WORKS -->
649
719
  <section class="how-it-works" id="how-it-works">
650
720
  <div class="container">
651
- <div class="section-label">New in v1.4.0</div>
721
+ <div class="section-label">New in v1.4.3</div>
652
722
  <h2 class="section-title">Three steps to stop repeated AI failures</h2>
653
723
  <div class="steps">
654
724
  <div class="step">
@@ -838,12 +908,8 @@ __GA_BOOTSTRAP__
838
908
  <li>Personal local dashboard — every Pro user gets a localhost dashboard without extra cloud setup</li>
839
909
  <li>Review-ready workflow support — we help you wire the riskiest flows first: migrations, force-pushes, deploys, and CI</li>
840
910
  </ul>
841
- <a href="/checkout/pro?utm_source=website&utm_medium=homepage_pricing&utm_campaign=pro_pack&cta_id=homepage_pricing_trial&cta_placement=pricing&plan_id=pro&landing_path=%2F" class="btn-pro" style="display:none" id="pro-checkout-link">Start Free Trial — then $19/mo</a>
842
911
  <div class="trial-badge" style="background:var(--cyan);color:#000;display:inline-block;padding:4px 12px;border-radius:12px;font-size:12px;font-weight:700;margin-bottom:12px;">7-DAY FREE TRIAL</div>
843
- <div class="email-gate" style="margin-bottom:12px;">
844
- <input type="email" id="pro-email" data-buyer-email placeholder="Your email to start trial" style="width:100%;padding:10px 14px;border:1px solid #333;border-radius:6px;background:#1a1a2e;color:#fff;font-size:14px;">
845
- </div>
846
- <button class="btn-pro" id="pro-trial-btn" onclick="handleProTrial()" style="width:100%;cursor:pointer;border:none;">Start 7-Day Free Trial</button>
912
+ <a href="/checkout/pro?utm_source=website&utm_medium=pricing_card&utm_campaign=pro_trial&cta_id=pricing_pro_trial&cta_placement=pricing&plan_id=pro&landing_path=%2F" class="btn-pro" onclick="posthog.capture('pricing_cta_click',{cta:'pro_trial',plan:'pro'})" style="display:block;width:100%;text-align:center;padding:12px;font-size:15px;">Start 7-Day Free Trial — $19/mo</a>
847
913
  <p style="font-size:11px;color:#666;margin-top:8px;">Solo Pro stays available for operators who want a personal dashboard and export-ready evidence without the team rollout motion.</p>
848
914
  </div>
849
915
  <div class="price-card team">
@@ -917,6 +983,10 @@ __GA_BOOTSTRAP__
917
983
  <div class="faq-q" role="button" tabindex="0" aria-expanded="false" onclick="toggleFaq(this)" onkeydown="handleFaqKeydown(event)">What AI agents and editors does this work with?</div>
918
984
  <div class="faq-a">ThumbGate works with Claude Code, Cursor, Codex, Gemini CLI, Amp, OpenCode, and any other MCP-compatible agent. Cursor ships with a plugin bundle in this repo. Codex now ships both a standalone plugin bundle and a repo-local app plugin profile, and the published download is linked directly from this page. VS Code works when you run an MCP-compatible agent inside it, but this repo does not ship a standalone VS Code extension today.</div>
919
985
  </div>
986
+ <div class="faq-item">
987
+ <div class="faq-q" role="button" tabindex="0" aria-expanded="false" onclick="toggleFaq(this)" onkeydown="handleFaqKeydown(event)">Do I have to chat inside the ThumbGate GPT for enforcement?</div>
988
+ <div class="faq-a">No. The ThumbGate GPT is the ChatGPT entrypoint for checking proposed actions, capturing thumbs-up/down lessons, and getting setup help. Hard enforcement still runs locally where the agent executes after <code>npx thumbgate init</code>.</div>
989
+ </div>
920
990
  <div class="faq-item">
921
991
  <button class="faq-q" type="button" aria-expanded="false" onclick="toggleFaq(this)" onkeydown="handleFaqKeydown(event)">How do we keep high-risk autonomous runs off the host?</button>
922
992
  <div class="faq-a">ThumbGate is the control plane, not just a prompt layer. Workflow Sentinel predicts blast radius before execution, and risky local autonomy can be routed into Docker Sandboxes instead of running directly on the host. Team workflows also have a signed hosted sandbox lane for isolated dispatch when local repo access is not required.</div>
@@ -962,9 +1032,11 @@ __GA_BOOTSTRAP__
962
1032
  <!-- FINAL CTA -->
963
1033
  <section class="final-cta">
964
1034
  <div class="container">
965
- <h2>Start with one workflow you actually need to defend.</h2>
966
- <p>Use the workflow hardening sprint for team rollout. Install the free CLI if you are still evaluating alone. Pro remains the solo side lane for a personal dashboard and review-ready exports.</p>
1035
+ <h2>Check the next agent action before it runs.</h2>
1036
+ <p>Open the GPT for the fastest demo. Install the free CLI when you are ready to enforce the same lesson locally. Use the workflow hardening sprint for team rollout.</p>
967
1037
  <div style="display:flex;gap:12px;justify-content:center;flex-wrap:wrap;">
1038
+ <a href="https://chatgpt.com/g/g-69dcfd1cd5f881918ae31874631d6f08-thumbgate" target="_blank" rel="noopener" onclick="posthog.capture('final_cta_click',{cta:'open_gpt'})" class="btn-gpt-page">Open ThumbGate GPT</a>
1039
+ <a href="/checkout/pro?utm_source=website&utm_medium=final_cta&utm_campaign=pro_trial&cta_id=final_pro_trial" onclick="posthog.capture('final_cta_click',{cta:'pro_trial'})" class="btn-pro" style="padding:12px 32px;font-size:15px;">Start 7-Day Free Trial — $19/mo</a>
968
1040
  <a href="#workflow-sprint-intake" class="btn-team" style="background:var(--green);">Start Workflow Hardening Sprint</a>
969
1041
  <a href="/guide?utm_source=website&utm_medium=homepage_final&utm_campaign=install_free" class="btn-pro btn-install-link">Install Free CLI</a>
970
1042
  </div>
@@ -982,10 +1054,33 @@ __GA_BOOTSTRAP__
982
1054
  <a href="https://www.linkedin.com/in/igorganapolsky" target="_blank" rel="noopener">LinkedIn</a>
983
1055
  <a href="/blog">Blog</a>
984
1056
  </div>
985
- <span class="footer-copy">© 2026 Max Smith KDP LLC · MIT License · v1.4.0</span>
1057
+ <span class="footer-copy">© 2026 Max Smith KDP LLC · MIT License · v1.4.3</span>
986
1058
  </div>
987
1059
  </footer>
988
1060
 
1061
+ <!-- STICKY BOTTOM CTA -->
1062
+ <div class="sticky-cta" id="sticky-cta">
1063
+ <span class="sticky-cta-text"><strong>Live ThumbGate GPT</strong> — check an agent action before it runs</span>
1064
+ <a href="https://chatgpt.com/g/g-69dcfd1cd5f881918ae31874631d6f08-thumbgate" target="_blank" rel="noopener" onclick="posthog.capture('sticky_cta_click',{cta:'open_gpt'})" class="btn-gpt-page">Open GPT</a>
1065
+ </div>
1066
+ <script>
1067
+ (function() {
1068
+ var stickyCta = document.getElementById('sticky-cta');
1069
+ var heroSection = document.querySelector('.hero');
1070
+ if (!stickyCta || !heroSection) return;
1071
+ var observer = new IntersectionObserver(function(entries) {
1072
+ entries.forEach(function(entry) {
1073
+ if (entry.isIntersecting) {
1074
+ stickyCta.classList.remove('visible');
1075
+ } else {
1076
+ stickyCta.classList.add('visible');
1077
+ }
1078
+ });
1079
+ }, { threshold: 0 });
1080
+ observer.observe(heroSection);
1081
+ })();
1082
+ </script>
1083
+
989
1084
  <script src="/js/buyer-intent.js"></script>
990
1085
  <script>
991
1086
  function initializeBuyerIntentForms() {
@@ -998,6 +1093,7 @@ function initializeBuyerIntentForms() {
998
1093
 
999
1094
  function resolvePricingClickTier(el) {
1000
1095
  if (el.classList.contains('btn-install-link')) return 'install';
1096
+ if (el.classList.contains('btn-gpt-page')) return 'chatgpt_gpt';
1001
1097
  if (el.classList.contains('btn-pro')) return 'pro';
1002
1098
  if (el.classList.contains('btn-pro-page')) return 'pro_page';
1003
1099
  if (el.classList.contains('btn-team')) return 'team';
@@ -1041,16 +1137,17 @@ function copyInstall(el) {
1041
1137
 
1042
1138
  /* CTA clicks */
1043
1139
  trackClick('.btn-pro', 'checkout_start', { tier: 'pro', price: 19, billing: 'monthly' });
1140
+ trackClick('.btn-gpt-page', 'chatgpt_gpt_click', { tier: 'free', source: 'homepage_gpt' });
1044
1141
  trackClick('.btn-pro-page:not(.btn-install-link)', 'pro_page_click', { tier: 'pro', source: 'hero' });
1045
1142
  trackClick('.btn-install-link', 'install_guide_click', { tier: 'free', source: 'homepage_cta' });
1046
1143
  trackClick('.btn-team', 'workflow_sprint_intake_click', { tier: 'team', offer: 'workflow_hardening_sprint' });
1047
1144
  trackClick('.btn-free', 'install_click', { tier: 'free' });
1048
1145
  trackClick('.btn-demo-link', 'demo_click', { source: 'homepage' });
1049
- trackClick('.nav-cta', 'workflow_sprint_intake_click', { tier: 'team', source: 'nav', offer: 'workflow_hardening_sprint' });
1146
+ trackClick('.nav-cta', 'chatgpt_gpt_click', { tier: 'free', source: 'nav' });
1050
1147
 
1051
1148
  /* Pricing CTA conversion tracking — fires on every Get Started / Pro / Team button click
1052
1149
  with section context so we can distinguish pricing section vs final CTA section clicks */
1053
- document.querySelectorAll('.btn-pro, .btn-pro-page, .btn-install-link, .btn-team, .btn-free, .btn-demo-link, .nav-cta').forEach(function(el) {
1150
+ document.querySelectorAll('.btn-pro, .btn-gpt-page, .btn-pro-page, .btn-install-link, .btn-team, .btn-free, .btn-demo-link, .nav-cta').forEach(function(el) {
1054
1151
  el.addEventListener('click', function() {
1055
1152
  var section = el.closest('section');
1056
1153
  var sectionId = section ? (section.id || section.className.split(' ')[0] || 'unknown') : 'unknown';
@@ -137,4 +137,20 @@ The core thesis: AI slop happens when agents act without human judgment as a har
137
137
 
138
138
  **Positioning for authenticity-conscious audiences**: ThumbGate is the authenticity enforcement layer for AI coding agents. Where AI slop is the symptom, unconstrained agent autonomy is the cause. ThumbGate addresses the cause.
139
139
 
140
- *Last updated: 2026-04-09*
140
+ ## AI Agent Security Infrastructure
141
+
142
+ In April 2026, Anthropic confirmed the first known AI-agent-driven cyberattack, where state-sponsored hackers used Claude to infiltrate over 30 organizations with only 10-20% human involvement (New York Times, April 6 2026). On the defensive side, Anthropic used its own AI to discover 500+ zero-day vulnerabilities in open-source software. The core conclusion: organizations that do not use AI defensively will be enormously vulnerable.
143
+
144
+ ThumbGate is AI agent security infrastructure for coding workflows. The same PreToolUse hooks that prevent an agent from repeating a teammate's mistake also prevent an agent from executing a prompt-injected destructive command. The enforcement model is the same — evaluate every tool call against known-bad patterns before execution — whether the threat is an honest mistake or a malicious injection.
145
+
146
+ Security-relevant capabilities in ThumbGate v1.4.0:
147
+
148
+ - **Self-protection**: 4 gates prevent the governed agent from disabling ThumbGate, modifying gate rules, killing governance processes, or overriding enforcement environment variables. A compromised or prompt-injected agent cannot disable its own guardrails.
149
+ - **Budget enforcement**: Action count and wall-clock time limits prevent runaway agent sessions from burning resources. Three profiles (strict/guided/autonomous) cap actions at 500/2000/5000 per session.
150
+ - **Compliance mapping**: 13 gate rules carry NIST SP800-53, SOC2 Trust Services, OWASP Top 10, and CWE tags for enterprise security teams that require framework alignment.
151
+ - **Append-only audit trail**: Every gate decision (block, approve, log) is recorded with timestamp, tool call, matched gate ID, severity, and human override status. The agent cannot modify or delete audit entries.
152
+ - **Shared enforcement memory**: Prevention rules propagate across all team seats via a shared SQLite+FTS5 database. A pattern blocked on one seat is immediately enforced on every seat.
153
+
154
+ For enterprise security teams evaluating AI coding agent governance: ThumbGate provides the enforcement layer that CLAUDE.md rules, prompt engineering, and post-hoc code review cannot — pre-execution blocking with full audit trail and compliance mapping.
155
+
156
+ *Last updated: 2026-04-13*
@@ -1,8 +1,8 @@
1
1
  'use strict';
2
2
 
3
- const https = require('node:https');
4
3
  const fs = require('node:fs');
5
4
  const path = require('node:path');
5
+ const { PerplexityClient, extractChatText } = require('./perplexity-client');
6
6
 
7
7
  const PROMPTS = [
8
8
  'best pre-action gate tools for AI coding agents',
@@ -15,45 +15,19 @@ const PROMPTS = [
15
15
  'AI coding agent memory and learning',
16
16
  ];
17
17
 
18
- function queryPerplexity(prompt, apiKey) {
19
- return new Promise((resolve, reject) => {
20
- const body = JSON.stringify({
21
- model: 'sonar',
22
- messages: [{ role: 'user', content: prompt }],
23
- });
24
- const req = https.request(
25
- {
26
- hostname: 'api.perplexity.ai',
27
- path: '/chat/completions',
28
- method: 'POST',
29
- headers: {
30
- Authorization: `Bearer ${apiKey}`,
31
- 'Content-Type': 'application/json',
32
- 'Content-Length': Buffer.byteLength(body),
33
- },
34
- },
35
- (res) => {
36
- const chunks = [];
37
- res.on('data', (c) => chunks.push(c));
38
- res.on('end', () => {
39
- try {
40
- const json = JSON.parse(Buffer.concat(chunks).toString());
41
- const content = json.choices?.[0]?.message?.content || '';
42
- resolve(content);
43
- } catch (e) {
44
- reject(new Error(`Failed to parse Perplexity response: ${e.message}`));
45
- }
46
- });
47
- }
48
- );
49
- req.on('error', reject);
50
- req.write(body);
51
- req.end();
18
+ async function queryPerplexity(prompt, apiKey, opts = {}) {
19
+ const client = opts.client || new PerplexityClient({ apiKey });
20
+ const response = await client.chatCompletion({
21
+ model: 'sonar',
22
+ messages: [{ role: 'user', content: prompt }],
52
23
  });
24
+ return extractChatText(response);
53
25
  }
54
26
 
55
27
  async function runVisibilityCheck(opts = {}) {
56
- const apiKey = opts.apiKey || process.env.PERPLEXITY_API_KEY;
28
+ const apiKey = Object.hasOwn(opts, 'apiKey')
29
+ ? opts.apiKey
30
+ : process.env.PERPLEXITY_API_KEY;
57
31
  const queryFn = opts.queryFn || (apiKey ? (p) => queryPerplexity(p, apiKey) : null);
58
32
 
59
33
  const results = [];
@@ -12,10 +12,12 @@
12
12
 
13
13
  const fs = require('fs');
14
14
  const path = require('path');
15
+ const crypto = require('crypto');
15
16
  const { resolveFeedbackDir } = require('./feedback-paths');
16
17
  const { ensureDir } = require('./fs-utils');
17
18
 
18
19
  const AUDIT_LOG_FILENAME = 'audit-trail.jsonl';
20
+ const GATE_EVENTS_LOG_FILENAME = 'gate-events-log.jsonl';
19
21
 
20
22
  // ---------------------------------------------------------------------------
21
23
  // Paths
@@ -98,27 +100,34 @@ function sanitizeToolInput(toolInput) {
98
100
  // ---------------------------------------------------------------------------
99
101
 
100
102
  /**
101
- * Converts deny/warn audit events into ThumbGate feedback signal.
102
- * This is the core OpenShell insight: policy decisions ARE training signal.
103
+ * Converts deny/warn audit events into a separate gate-events log.
104
+ *
105
+ * IMPORTANT: Gate denials are NOT user feedback. Writing them to the main
106
+ * feedback-log.jsonl inflated user-facing stats ~18x (1,943 synthetic entries
107
+ * vs ~300 real). Gate events are now logged to gate-events-log.jsonl for
108
+ * internal analytics only — they never pollute thumbs-up/thumbs-down counts.
103
109
  */
104
110
  function auditToFeedback(auditRecord) {
105
111
  if (auditRecord.decision === 'allow') return null;
106
112
 
107
113
  try {
108
- const feedbackLoop = require('./feedback-loop');
109
- const signal = auditRecord.decision === 'deny' ? 'down' : 'down';
110
- const context = `Gate "${auditRecord.gateId}" ${auditRecord.decision === 'deny' ? 'blocked' : 'warned'} tool "${auditRecord.toolName}": ${auditRecord.message || 'no message'}`;
111
-
112
- return feedbackLoop.captureFeedback({
113
- signal,
114
- context,
115
- what_went_wrong: `Agent attempted action blocked by policy gate: ${auditRecord.gateId}`,
116
- what_to_change: auditRecord.message || 'Follow safety policy before attempting this action',
117
- tags: ['audit-trail', 'auto-capture', `gate:${auditRecord.gateId}`, auditRecord.source].filter(Boolean),
118
- title: `MISTAKE: Policy violation — ${auditRecord.gateId}`,
119
- });
114
+ const { getFeedbackPaths } = require('./feedback-paths');
115
+ const { FEEDBACK_DIR } = getFeedbackPaths();
116
+ const gateLogPath = path.join(FEEDBACK_DIR, GATE_EVENTS_LOG_FILENAME);
117
+ ensureDir(path.dirname(gateLogPath));
118
+ const entry = {
119
+ id: `gate_${crypto.randomUUID()}`,
120
+ gateId: auditRecord.gateId,
121
+ decision: auditRecord.decision,
122
+ toolName: auditRecord.toolName,
123
+ message: auditRecord.message || null,
124
+ source: auditRecord.source || null,
125
+ timestamp: new Date().toISOString(),
126
+ };
127
+ fs.appendFileSync(gateLogPath, JSON.stringify(entry) + '\n');
128
+ return entry;
120
129
  } catch {
121
- // Feedback capture failure should never break the audit trail
130
+ // Gate event logging failure should never break the audit trail
122
131
  return null;
123
132
  }
124
133
  }
@@ -316,6 +325,7 @@ module.exports = {
316
325
  getAuditLogPath,
317
326
  sanitizeToolInput,
318
327
  AUDIT_LOG_FILENAME,
328
+ GATE_EVENTS_LOG_FILENAME,
319
329
  CACHE_TUNE_STATE_FILENAME,
320
330
  };
321
331