thumbgate 1.27.6 → 1.27.8
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.
- package/.claude/commands/thumbgate-blocked.md +27 -0
- package/.claude/commands/thumbgate-doctor.md +30 -0
- package/.claude/commands/thumbgate-guard.md +36 -0
- package/.claude/commands/thumbgate-protect.md +30 -0
- package/.claude/commands/thumbgate-rules.md +30 -0
- package/.claude-plugin/plugin.json +1 -1
- package/.well-known/llms.txt +6 -2
- package/.well-known/mcp/server-card.json +1 -1
- package/README.md +49 -5
- package/adapters/claude/.mcp.json +2 -2
- package/adapters/letta/README.md +41 -0
- package/adapters/letta/thumbgate-letta-adapter.js +133 -0
- package/adapters/mcp/server-stdio.js +16 -1
- package/adapters/opencode/opencode.json +1 -1
- package/adapters/policy-engine/ethicore-guardian-client.js +68 -0
- package/adapters/policy-engine/thumbgate-policy-engine-adapter.js +260 -0
- package/bench/observability-eval-suite.json +26 -0
- package/bin/cli.js +180 -2
- package/bin/postinstall.js +1 -1
- package/config/gate-templates.json +84 -0
- package/config/gates/claim-verification.json +6 -0
- package/config/gates/default.json +20 -0
- package/config/github-about.json +1 -1
- package/config/model-candidates.json +50 -0
- package/package.json +66 -25
- package/public/agent-manager.html +41 -1
- package/public/agents-cost-savings.html +1 -1
- package/public/ai-malpractice-prevention.html +2 -1
- package/public/assets/brand/github-social-preview.png +0 -0
- package/public/assets/brand/thumbgate-icon-512.png +0 -0
- package/public/assets/brand/thumbgate-icon-pro-512.png +0 -0
- package/public/assets/brand/thumbgate-icon-team-512.png +0 -0
- package/public/assets/brand/thumbgate-logo-1200x360.png +0 -0
- package/public/assets/brand/thumbgate-mark-inline.svg +15 -0
- package/public/assets/brand/thumbgate-mark-pro.svg +23 -0
- package/public/assets/brand/thumbgate-mark-team.svg +26 -0
- package/public/assets/brand/thumbgate-mark.svg +15 -0
- package/public/assets/brand/thumbgate-wordmark.svg +20 -0
- package/public/assets/claude-thumbgate-statusbar.svg +8 -0
- package/public/assets/codex-thumbgate-statusbar-test.svg +9 -0
- package/public/assets/legal-intake-control-flow.svg +66 -0
- package/public/blog.html +1 -1
- package/public/brand/thumbgate-mark.svg +15 -0
- package/public/brand/thumbgate-og.svg +16 -0
- package/public/codex-enterprise.html +1 -1
- package/public/codex-plugin.html +1 -1
- package/public/compare.html +23 -3
- package/public/dashboard.html +312 -30
- package/public/federal.html +1 -1
- package/public/guide.html +5 -4
- package/public/index.html +167 -49
- package/public/js/buyer-intent.js +672 -0
- package/public/learn.html +74 -7
- package/public/lessons.html +2 -1
- package/public/numbers.html +3 -3
- package/public/pricing.html +63 -15
- package/public/pro.html +7 -7
- package/scripts/activation-quickstart.js +187 -0
- package/scripts/agent-memory-lifecycle.js +211 -0
- package/scripts/async-eval-observability.js +236 -0
- package/scripts/auto-promote-gates.js +75 -4
- package/scripts/build-metadata.js +24 -3
- package/scripts/cli-schema.js +22 -0
- package/scripts/dashboard-chat.js +2 -1
- package/scripts/dashboard.js +8 -0
- package/scripts/export-databricks-bundle.js +5 -1
- package/scripts/export-dpo-pairs.js +7 -2
- package/scripts/feedback-aggregate.js +281 -0
- package/scripts/feedback-loop.js +34 -0
- package/scripts/filesystem-search.js +35 -10
- package/scripts/gates-engine.js +198 -6
- package/scripts/gemini-embedding-policy.js +2 -1
- package/scripts/hook-stop-anti-claim.js +227 -0
- package/scripts/hook-thumbgate-cache-updater.js +18 -2
- package/scripts/lesson-inference.js +8 -3
- package/scripts/lesson-search.js +17 -1
- package/scripts/operational-integrity.js +39 -5
- package/scripts/plausible-domain-config.js +4 -2
- package/scripts/rate-limiter.js +12 -6
- package/scripts/secret-redaction.js +166 -0
- package/scripts/security-scanner.js +100 -0
- package/scripts/self-distill-agent.js +3 -1
- package/scripts/self-harness-optimizer.js +141 -0
- package/scripts/seo-gsd.js +635 -0
- package/scripts/statusline-cache-path.js +17 -2
- package/scripts/statusline-cache-read.js +57 -0
- package/scripts/statusline-local-stats.js +9 -1
- package/scripts/statusline-meta.js +5 -2
- package/scripts/statusline.sh +13 -1
- package/scripts/sync-telemetry-from-prod.js +374 -0
- package/scripts/telemetry-analytics.js +9 -0
- package/scripts/thumbgate-search.js +85 -19
- package/scripts/tool-contract-validator.js +76 -0
- package/scripts/vector-store.js +44 -0
- package/scripts/workspace-evolver.js +62 -2
- package/src/api/server.js +715 -86
package/public/learn.html
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
<meta charset="UTF-8">
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
6
|
<title>Learn — AI Agent Safety, Pre-Action Checks, and Vibe Coding Guardrails</title>
|
|
7
|
-
<script defer data-domain="thumbgate
|
|
7
|
+
<script defer data-domain="thumbgate.ai" src="https://plausible.io/js/script.js"></script>
|
|
8
8
|
<meta name="description" content="Practical guides for stopping AI coding agent mistakes. Learn about pre-action checks, MCP guardrails, feedback-driven enforcement, and vibe coding safety for Claude Code, Cursor, Codex, and more.">
|
|
9
9
|
<meta name="keywords" content="AI agent safety, pre-action checks, vibe coding guardrails, Claude Code mistakes, Cursor agent memory, MCP server hooks, AI coding agent feedback, ThumbGate guides">
|
|
10
10
|
<meta property="og:title" content="Learn — AI Agent Safety Guides by ThumbGate">
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
"name": "ThumbGate Learning Hub",
|
|
23
23
|
"description": "Practical guides for AI coding agent safety, pre-action checks, and vibe coding guardrails.",
|
|
24
24
|
"url": "https://thumbgate.ai/learn",
|
|
25
|
-
"dateModified": "2026-
|
|
25
|
+
"dateModified": "2026-06-06",
|
|
26
26
|
"author": {
|
|
27
27
|
"@type": "Person",
|
|
28
28
|
"name": "Igor Ganapolsky",
|
|
@@ -145,38 +145,56 @@
|
|
|
145
145
|
{
|
|
146
146
|
"@type": "ListItem",
|
|
147
147
|
"position": 10,
|
|
148
|
+
"url": "https://thumbgate.ai/guides/hermes-agent-guardrails",
|
|
149
|
+
"name": "Hermes Agent Guardrails for Self-Improving Agents"
|
|
150
|
+
},
|
|
151
|
+
{
|
|
152
|
+
"@type": "ListItem",
|
|
153
|
+
"position": 11,
|
|
154
|
+
"url": "https://thumbgate.ai/guides/agent-context-governance",
|
|
155
|
+
"name": "Agent Context Governance for Long-Running Agents"
|
|
156
|
+
},
|
|
157
|
+
{
|
|
158
|
+
"@type": "ListItem",
|
|
159
|
+
"position": 12,
|
|
148
160
|
"url": "https://thumbgate.ai/guides/roo-code-alternative-cline",
|
|
149
161
|
"name": "Roo Code Alternative: Migrating to Cline with Portable Lesson Memory"
|
|
150
162
|
},
|
|
151
163
|
{
|
|
152
164
|
"@type": "ListItem",
|
|
153
|
-
"position":
|
|
165
|
+
"position": 13,
|
|
154
166
|
"url": "https://thumbgate.ai/guides/browser-automation-safety",
|
|
155
167
|
"name": "Browser Automation Safety for AI Agents"
|
|
156
168
|
},
|
|
157
169
|
{
|
|
158
170
|
"@type": "ListItem",
|
|
159
|
-
"position":
|
|
171
|
+
"position": 14,
|
|
160
172
|
"url": "https://thumbgate.ai/guides/native-messaging-host-security",
|
|
161
173
|
"name": "Native Messaging Host Security"
|
|
162
174
|
},
|
|
163
175
|
{
|
|
164
176
|
"@type": "ListItem",
|
|
165
|
-
"position":
|
|
177
|
+
"position": 15,
|
|
166
178
|
"url": "https://thumbgate.ai/guides/ai-search-topical-presence",
|
|
167
179
|
"name": "AI Search Topical Presence"
|
|
168
180
|
},
|
|
169
181
|
{
|
|
170
182
|
"@type": "ListItem",
|
|
171
|
-
"position":
|
|
183
|
+
"position": 16,
|
|
172
184
|
"url": "https://thumbgate.ai/guides/relational-knowledge-ai-recommendations",
|
|
173
185
|
"name": "Relational Knowledge in AI Recommendations"
|
|
174
186
|
},
|
|
175
187
|
{
|
|
176
188
|
"@type": "ListItem",
|
|
177
|
-
"position":
|
|
189
|
+
"position": 17,
|
|
178
190
|
"url": "https://thumbgate.ai/guides/ai-deployment-readiness",
|
|
179
191
|
"name": "AI Deployment Readiness Before Production Rollout"
|
|
192
|
+
},
|
|
193
|
+
{
|
|
194
|
+
"@type": "ListItem",
|
|
195
|
+
"position": 18,
|
|
196
|
+
"url": "https://thumbgate.ai/guides/database-agent-safety",
|
|
197
|
+
"name": "Database Safety for AI Agents"
|
|
180
198
|
}
|
|
181
199
|
]
|
|
182
200
|
}
|
|
@@ -423,6 +441,14 @@
|
|
|
423
441
|
<h2>Popular buyer questions</h2>
|
|
424
442
|
<p class="section-intro">These are the high-intent guides for buyers who already know the pain and want to understand where ThumbGate fits fast.</p>
|
|
425
443
|
<div class="article-grid">
|
|
444
|
+
<a href="/guides/database-agent-safety" class="article-card">
|
|
445
|
+
<h3>Database Safety for AI Agents</h3>
|
|
446
|
+
<p>Block hallucinated SQL writes, migrations, role grants, and production database changes before an agent can touch live data.</p>
|
|
447
|
+
<span class="article-tag">Database</span>
|
|
448
|
+
<span class="article-tag">SQL</span>
|
|
449
|
+
<span class="article-tag">Production Safety</span>
|
|
450
|
+
</a>
|
|
451
|
+
|
|
426
452
|
<a href="/guides/ai-deployment-readiness" class="article-card">
|
|
427
453
|
<h3>AI Deployment Readiness Before Production Rollout</h3>
|
|
428
454
|
<p>Use one priority workflow to map tools, data, controls, pre-action gates, and proof before an AI deployment team ships into production.</p>
|
|
@@ -439,6 +465,22 @@
|
|
|
439
465
|
<span class="article-tag">Recommendation</span>
|
|
440
466
|
</a>
|
|
441
467
|
|
|
468
|
+
<a href="/guides/agentic-web-governance" class="article-card">
|
|
469
|
+
<h3>Agentic Web Governance</h3>
|
|
470
|
+
<p>Bots already outnumber humans in HTML requests. ThumbGate turns that agentic-web shift into pre-action governance before AI agents touch real systems.</p>
|
|
471
|
+
<span class="article-tag">Agentic Web</span>
|
|
472
|
+
<span class="article-tag">AI Search</span>
|
|
473
|
+
<span class="article-tag">Governance</span>
|
|
474
|
+
</a>
|
|
475
|
+
|
|
476
|
+
<a href="/guides/vllm-serving-guardrails" class="article-card">
|
|
477
|
+
<h3>vLLM Serving Guardrails</h3>
|
|
478
|
+
<p>Gate self-hosted inference changes before agents route production work through PagedAttention, batching, prefix-cache, or model-swap optimizations.</p>
|
|
479
|
+
<span class="article-tag">vLLM</span>
|
|
480
|
+
<span class="article-tag">LLM Serving</span>
|
|
481
|
+
<span class="article-tag">Runtime Safety</span>
|
|
482
|
+
</a>
|
|
483
|
+
|
|
442
484
|
<a href="/guides/relational-knowledge-ai-recommendations" class="article-card">
|
|
443
485
|
<h3>Relational Knowledge in AI Recommendations</h3>
|
|
444
486
|
<p>How stored brand-to-problem associations shape AI answers, and why ThumbGate should own the pre-action-checks category in those retrieval paths.</p>
|
|
@@ -479,6 +521,30 @@
|
|
|
479
521
|
<span class="article-tag">Enforcement</span>
|
|
480
522
|
</a>
|
|
481
523
|
|
|
524
|
+
<a href="/guides/hermes-agent-guardrails" class="article-card">
|
|
525
|
+
<h3>Hermes Agent Guardrails for Self-Improving Agents</h3>
|
|
526
|
+
<p>Hermes-style agents bring persistent memory, generated skills, gateways, automations, and sandboxes. ThumbGate adds the pre-action firewall before those agents touch real systems.</p>
|
|
527
|
+
<span class="article-tag">Hermes Agent</span>
|
|
528
|
+
<span class="article-tag">Persistent Agents</span>
|
|
529
|
+
<span class="article-tag">Execution Firewall</span>
|
|
530
|
+
</a>
|
|
531
|
+
|
|
532
|
+
<a href="/guides/safe-self-evolution" class="article-card">
|
|
533
|
+
<h3>Safe Self-Evolution: Prompt Optimization without Regression</h3>
|
|
534
|
+
<p>Hermes-style autonomous agents learn by observing failures and rewriting skills. ThumbGate introduces Safe Self-Evolution: weakness mining, automated prompt optimization, verification suites, and atomic git rollbacks.</p>
|
|
535
|
+
<span class="article-tag">Self-Evolution</span>
|
|
536
|
+
<span class="article-tag">Harness Optimizer</span>
|
|
537
|
+
<span class="article-tag">Verification Gate</span>
|
|
538
|
+
</a>
|
|
539
|
+
|
|
540
|
+
<a href="/guides/agent-context-governance" class="article-card">
|
|
541
|
+
<h3>Agent Context Governance for Long-Running Agents</h3>
|
|
542
|
+
<p>AdaCoM, tokenmaxxing backlash, Managed Agents, lockdown modes, and model-provenance scares all point to one need: clean context and tool gates before agents act.</p>
|
|
543
|
+
<span class="article-tag">Context Governance</span>
|
|
544
|
+
<span class="article-tag">Tool Lockdown</span>
|
|
545
|
+
<span class="article-tag">Model Provenance</span>
|
|
546
|
+
</a>
|
|
547
|
+
|
|
482
548
|
<a href="/guides/roo-code-alternative-cline" class="article-card">
|
|
483
549
|
<h3>Roo Code Alternative: Migrate to Cline Without Losing Agent Memory</h3>
|
|
484
550
|
<p>Use the Roo shutdown window to pitch portable lesson memory and local-first enforcement instead of making operators re-teach the same failures after they switch.</p>
|
|
@@ -519,5 +585,6 @@
|
|
|
519
585
|
</div>
|
|
520
586
|
</div>
|
|
521
587
|
|
|
588
|
+
<script src="/js/buyer-intent.js"></script>
|
|
522
589
|
</body>
|
|
523
590
|
</html>
|
package/public/lessons.html
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
<title>ThumbGate — Lessons Learned</title>
|
|
7
7
|
<link rel="icon" type="image/png" href="/thumbgate-icon.png">
|
|
8
8
|
<link rel="apple-touch-icon" href="/assets/brand/thumbgate-mark.svg">
|
|
9
|
-
<script defer data-domain="thumbgate
|
|
9
|
+
<script defer data-domain="thumbgate.ai" src="https://plausible.io/js/script.js"></script>
|
|
10
10
|
<script type="application/ld+json">
|
|
11
11
|
{
|
|
12
12
|
"@context": "https://schema.org",
|
|
@@ -1184,6 +1184,7 @@ async function submitFeedback() {
|
|
|
1184
1184
|
btn.disabled = false; btn.textContent = 'Submit';
|
|
1185
1185
|
}
|
|
1186
1186
|
</script>
|
|
1187
|
+
<script src="/js/buyer-intent.js"></script>
|
|
1187
1188
|
|
|
1188
1189
|
</body>
|
|
1189
1190
|
</html>
|
package/public/numbers.html
CHANGED
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
<link rel="canonical" href="https://thumbgate.ai/numbers">
|
|
16
16
|
<link rel="icon" type="image/png" href="/thumbgate-icon.png">
|
|
17
17
|
<link rel="apple-touch-icon" href="/apple-touch-icon.png">
|
|
18
|
-
<script defer data-domain="thumbgate
|
|
18
|
+
<script defer data-domain="thumbgate.ai" src="https://plausible.io/js/script.js"></script>
|
|
19
19
|
|
|
20
20
|
<script type="application/ld+json">
|
|
21
21
|
{
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
"alternateName": "thumbgate",
|
|
26
26
|
"applicationCategory": "DeveloperApplication",
|
|
27
27
|
"operatingSystem": "Cross-platform, Node.js >=18.18.0",
|
|
28
|
-
"softwareVersion": "1.27.
|
|
28
|
+
"softwareVersion": "1.27.8",
|
|
29
29
|
"url": "https://thumbgate.ai/numbers",
|
|
30
30
|
"dateModified": "2026-05-07",
|
|
31
31
|
"creator": {
|
|
@@ -202,7 +202,7 @@
|
|
|
202
202
|
<main class="container">
|
|
203
203
|
<h1>The Numbers</h1>
|
|
204
204
|
<p class="subtitle">Generated first-party operational snapshot from the ThumbGate runtime. This is not customer traction, install volume, revenue, or proof that a configured gate has fired.</p>
|
|
205
|
-
<div class="freshness">Updated: 2026-05-07 · Version 1.27.
|
|
205
|
+
<div class="freshness">Updated: 2026-05-07 · Version 1.27.8</div>
|
|
206
206
|
<div class="truth-note"><strong>Read this first:</strong> configured checks are inventory. Recorded blocks and warnings are usage evidence. This snapshot currently reports 0 recorded hard-block event(s) and 0 recorded warning event(s).</div>
|
|
207
207
|
|
|
208
208
|
<h2>Gate enforcement</h2>
|
package/public/pricing.html
CHANGED
|
@@ -16,7 +16,7 @@ __GOOGLE_SITE_VERIFICATION_META__
|
|
|
16
16
|
<link rel="icon" type="image/png" href="/thumbgate-icon.png">
|
|
17
17
|
<link rel="apple-touch-icon" href="/assets/brand/thumbgate-mark.svg">
|
|
18
18
|
|
|
19
|
-
<script defer data-domain="thumbgate
|
|
19
|
+
<script defer data-domain="thumbgate.ai" src="https://plausible.io/js/script.tagged-events.js"></script>
|
|
20
20
|
__GA_BOOTSTRAP__
|
|
21
21
|
|
|
22
22
|
<script>
|
|
@@ -28,6 +28,57 @@ __GA_BOOTSTRAP__
|
|
|
28
28
|
const proPriceDollars = Number('__PRO_PRICE_DOLLARS__') || 19;
|
|
29
29
|
</script>
|
|
30
30
|
|
|
31
|
+
<script>
|
|
32
|
+
window.thumbgatePricingTelemetry = window.thumbgatePricingTelemetry || {};
|
|
33
|
+
window.trackPricingTelemetry = function(eventType, data) {
|
|
34
|
+
const params = new URLSearchParams(window.location.search);
|
|
35
|
+
const payload = Object.assign({
|
|
36
|
+
eventType,
|
|
37
|
+
clientType: 'web',
|
|
38
|
+
page: '/pricing',
|
|
39
|
+
source: params.get('utm_source') || 'pricing',
|
|
40
|
+
utmSource: params.get('utm_source') || 'pricing',
|
|
41
|
+
utmMedium: params.get('utm_medium') || 'pricing_page',
|
|
42
|
+
utmCampaign: params.get('utm_campaign') || 'pricing_page',
|
|
43
|
+
utmContent: params.get('utm_content') || null,
|
|
44
|
+
utmTerm: params.get('utm_term') || null,
|
|
45
|
+
traceId: params.get('trace_id') || null,
|
|
46
|
+
acquisitionId: params.get('acquisition_id') || serverAcquisitionId || null,
|
|
47
|
+
visitorId: params.get('visitor_id') || serverVisitorId || null,
|
|
48
|
+
sessionId: params.get('visitor_session_id') || params.get('session_id') || serverSessionId || null,
|
|
49
|
+
referrer: document.referrer || null,
|
|
50
|
+
landingPath: '/pricing'
|
|
51
|
+
}, data || {});
|
|
52
|
+
const body = JSON.stringify(payload);
|
|
53
|
+
if (navigator.sendBeacon) {
|
|
54
|
+
navigator.sendBeacon('/v1/telemetry/ping', new Blob([body], { type: 'application/json' }));
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
fetch('/v1/telemetry/ping', {
|
|
58
|
+
method: 'POST',
|
|
59
|
+
headers: { 'content-type': 'application/json' },
|
|
60
|
+
body,
|
|
61
|
+
keepalive: true
|
|
62
|
+
}).catch(function(){});
|
|
63
|
+
};
|
|
64
|
+
document.addEventListener('DOMContentLoaded', function() {
|
|
65
|
+
trackPricingTelemetry('pricing_page_view', { serverTelemetryCaptured });
|
|
66
|
+
document.querySelectorAll('[data-pricing-cta]').forEach(function(link) {
|
|
67
|
+
link.addEventListener('click', function() {
|
|
68
|
+
trackPricingTelemetry('pricing_cta_click', {
|
|
69
|
+
ctaId: link.getAttribute('data-cta-id') || null,
|
|
70
|
+
ctaPlacement: link.getAttribute('data-cta-placement') || 'pricing',
|
|
71
|
+
tier: link.getAttribute('data-tier') || null,
|
|
72
|
+
planId: link.getAttribute('data-plan-id') || null,
|
|
73
|
+
billingCycle: link.getAttribute('data-billing-cycle') || null,
|
|
74
|
+
price: link.getAttribute('data-price') || null,
|
|
75
|
+
href: link.getAttribute('href') || null
|
|
76
|
+
});
|
|
77
|
+
});
|
|
78
|
+
});
|
|
79
|
+
});
|
|
80
|
+
</script>
|
|
81
|
+
|
|
31
82
|
<script type="application/ld+json">
|
|
32
83
|
{
|
|
33
84
|
"@context": "https://schema.org",
|
|
@@ -38,8 +89,8 @@ __GA_BOOTSTRAP__
|
|
|
38
89
|
"url": "__APP_ORIGIN__/pricing",
|
|
39
90
|
"offers": [
|
|
40
91
|
{ "@type": "Offer", "name": "ThumbGate CLI (Free)", "price": "0", "priceCurrency": "USD" },
|
|
41
|
-
{ "@type": "Offer", "name": "ThumbGate Pro Monthly", "price": "__PRO_PRICE_DOLLARS__", "priceCurrency": "USD", "url": "__APP_ORIGIN__/checkout/pro?plan_id=pro&billing_cycle=monthly&landing_path=%2Fpricing" },
|
|
42
|
-
{ "@type": "Offer", "name": "ThumbGate Pro Annual", "price": "149", "priceCurrency": "USD", "url": "__APP_ORIGIN__/checkout/pro?plan_id=pro&billing_cycle=annual&landing_path=%2Fpricing" },
|
|
92
|
+
{ "@type": "Offer", "name": "ThumbGate Pro Monthly", "price": "__PRO_PRICE_DOLLARS__", "priceCurrency": "USD", "url": "__APP_ORIGIN__/checkout/pro?confirm=1&plan_id=pro&billing_cycle=monthly&landing_path=%2Fpricing" },
|
|
93
|
+
{ "@type": "Offer", "name": "ThumbGate Pro Annual", "price": "149", "priceCurrency": "USD", "url": "__APP_ORIGIN__/checkout/pro?confirm=1&plan_id=pro&billing_cycle=annual&landing_path=%2Fpricing" },
|
|
43
94
|
{ "@type": "Offer", "name": "ThumbGate Enterprise", "priceCurrency": "USD", "url": "__APP_ORIGIN__/#workflow-sprint-intake" }
|
|
44
95
|
]
|
|
45
96
|
}
|
|
@@ -50,7 +101,7 @@ __GA_BOOTSTRAP__
|
|
|
50
101
|
"@context": "https://schema.org",
|
|
51
102
|
"@type": "FAQPage",
|
|
52
103
|
"mainEntity": [
|
|
53
|
-
{ "@type": "Question", "name": "What does Pro add over the free CLI?", "acceptedAnswer": { "@type": "Answer", "text": "Free gives you
|
|
104
|
+
{ "@type": "Question", "name": "What does Pro add over the free CLI?", "acceptedAnswer": { "@type": "Answer", "text": "Free gives you 2 captures/day and 3 active rules, running entirely on your machine. Pro is the hosted layer: unlimited captures, unlimited rules, lesson sync across machines, a dashboard without self-hosting, managed adapter updates, and DPO export. You're paying for infrastructure we run, not features we hide." } },
|
|
54
105
|
{ "@type": "Question", "name": "Does ThumbGate send my code to the cloud?", "acceptedAnswer": { "@type": "Answer", "text": "No. The CLI is local-first — no data leaves your machine. Pro and Enterprise add hosted sync for dashboards and shared lessons, but your source code stays local." } },
|
|
55
106
|
{ "@type": "Question", "name": "When should I pick Enterprise over Pro?", "acceptedAnswer": { "@type": "Answer", "text": "When one engineer's correction should protect the whole team. Enterprise shares the lesson database across the org so a fix in one repo prevents the same mistake in every repo." } },
|
|
56
107
|
{ "@type": "Question", "name": "Can I cancel anytime?", "acceptedAnswer": { "@type": "Answer", "text": "Yes. Pro and Enterprise are month-to-month with a 7-day refund window on the first charge. Cancel from the billing portal and your subscription ends at the period close." } }
|
|
@@ -134,11 +185,9 @@ __GA_BOOTSTRAP__
|
|
|
134
185
|
padding: 3px 12px; border-radius: 6px;
|
|
135
186
|
font-size: 11px; font-weight: 700; letter-spacing: 0.5px; text-transform: uppercase;
|
|
136
187
|
}
|
|
137
|
-
.price-card.team-card { border-color: rgba(74, 222, 128, 0.45); box-shadow: inset 0 1px 0 rgba(74, 222, 128, 0.16); }
|
|
138
188
|
|
|
139
189
|
.tier { font-size: 13px; text-transform: uppercase; letter-spacing: 0.08em; color: var(--text-muted); font-weight: 600; margin-bottom: 8px; }
|
|
140
190
|
.price-card.highlight .tier { color: var(--cyan); }
|
|
141
|
-
.price-card.team-card .tier { color: var(--green); }
|
|
142
191
|
|
|
143
192
|
.price { font-size: 40px; font-weight: 700; letter-spacing: -0.03em; margin-bottom: 4px; }
|
|
144
193
|
.price span { font-size: 16px; color: var(--text-dim); }
|
|
@@ -147,7 +196,6 @@ __GA_BOOTSTRAP__
|
|
|
147
196
|
.price-card ul { list-style: none; padding: 0; margin: 0 0 28px; }
|
|
148
197
|
.price-card li { font-size: 14px; color: var(--text-muted); padding: 6px 0; display: flex; align-items: flex-start; gap: 8px; }
|
|
149
198
|
.price-card li::before { content: "\2713"; color: var(--cyan); font-weight: 700; flex-shrink: 0; }
|
|
150
|
-
.price-card.team-card li::before { color: var(--green); }
|
|
151
199
|
|
|
152
200
|
/* BUTTONS */
|
|
153
201
|
.btn-install {
|
|
@@ -218,7 +266,7 @@ __GA_BOOTSTRAP__
|
|
|
218
266
|
<a href="/pricing" style="color:var(--text);">Pricing</a>
|
|
219
267
|
<a href="/guide">Guide</a>
|
|
220
268
|
<a href="/dashboard">Dashboard</a>
|
|
221
|
-
<a class="nav-cta" href="/checkout/pro?utm_source=pricing&utm_medium=nav&utm_campaign=pricing_page&plan_id=pro&landing_path=%2Fpricing">Start Pro</a>
|
|
269
|
+
<a class="nav-cta" href="/checkout/pro?confirm=1&utm_source=pricing&utm_medium=nav&utm_campaign=pricing_page&cta_id=pricing_nav_start_pro&cta_placement=nav&plan_id=pro&landing_path=%2Fpricing" data-pricing-cta data-cta-id="pricing_nav_start_pro" data-cta-placement="nav" data-tier="pro" data-plan-id="pro" data-billing-cycle="monthly" data-price="19">Start Pro</a>
|
|
222
270
|
</div>
|
|
223
271
|
</div>
|
|
224
272
|
</nav>
|
|
@@ -238,13 +286,13 @@ __GA_BOOTSTRAP__
|
|
|
238
286
|
<div class="price">$0</div>
|
|
239
287
|
<div class="price-sub">Block repeated mistakes daily. Forever free for solo devs.</div>
|
|
240
288
|
<ul>
|
|
241
|
-
<li>
|
|
289
|
+
<li>2 feedback captures/day (10 total) — enough to see the value</li>
|
|
242
290
|
<li>Up to 3 active prevention rules</li>
|
|
243
291
|
<li>All MCP integrations (Claude Code, Cursor, Codex, Gemini, Amp)</li>
|
|
244
292
|
<li>PreToolUse hook blocking with built-in safety checks</li>
|
|
245
293
|
<li>Runs 100% local — no account, no signup, no data leaves your machine</li>
|
|
246
294
|
</ul>
|
|
247
|
-
<a class="btn-install" href="/go/install?utm_source=pricing&utm_medium=free_card" onclick="try{posthog.capture('pricing_cta_click',{cta:'install_free',tier:'free',placement:'pricing_page'})}catch(_){};try{plausible('pricing_cta_click',{props:{cta:'install_free',tier:'free'}})}catch(_){}">Install free</a>
|
|
295
|
+
<a class="btn-install" href="/go/install?utm_source=pricing&utm_medium=free_card&cta_id=pricing_install_free&cta_placement=free_card" data-pricing-cta data-cta-id="pricing_install_free" data-cta-placement="free_card" data-tier="free" data-plan-id="free" data-price="0" onclick="try{posthog.capture('pricing_cta_click',{cta:'install_free',tier:'free',placement:'pricing_page'})}catch(_){};try{plausible('pricing_cta_click',{props:{cta:'install_free',tier:'free'}})}catch(_){}">Install free</a>
|
|
248
296
|
</div>
|
|
249
297
|
|
|
250
298
|
<div class="price-card highlight" id="pro">
|
|
@@ -262,8 +310,8 @@ __GA_BOOTSTRAP__
|
|
|
262
310
|
<li><strong>Auto-connect</strong> — new agent surfaces appear automatically after setup</li>
|
|
263
311
|
<li>7-day refund window. Cancel anytime.</li>
|
|
264
312
|
</ul>
|
|
265
|
-
<a class="btn-pro" href="/checkout/pro?utm_source=pricing&utm_medium=hero_card&utm_campaign=pricing_page&plan_id=pro&landing_path=%2Fpricing" onclick="try{posthog.capture('pricing_cta_click',{cta:'start_pro',tier:'pro',placement:'pricing_page',price:19})}catch(_){};try{plausible('pricing_cta_click',{props:{cta:'start_pro',tier:'pro'}})}catch(_){}">Start Pro — $19/mo</a>
|
|
266
|
-
<p class="btn-sub">or
|
|
313
|
+
<a class="btn-pro" href="/checkout/pro?confirm=1&utm_source=pricing&utm_medium=hero_card&utm_campaign=pricing_page&cta_id=pricing_pro&cta_placement=pricing&plan_id=pro&billing_cycle=monthly&landing_path=%2Fpricing" data-pricing-cta data-cta-id="pricing_pro" data-cta-placement="pricing" data-tier="pro" data-plan-id="pro" data-billing-cycle="monthly" data-price="19" onclick="try{posthog.capture('pricing_cta_click',{cta:'start_pro',tier:'pro',placement:'pricing_page',price:19})}catch(_){};try{plausible('pricing_cta_click',{props:{cta:'start_pro',tier:'pro'}})}catch(_){}">Start Pro — $19/mo</a>
|
|
314
|
+
<p class="btn-sub">or <a href="/checkout/pro?confirm=1&utm_source=pricing&utm_medium=hero_card_annual&utm_campaign=pricing_page&cta_id=pricing_pro_annual&cta_placement=pricing&plan_id=pro&billing_cycle=annual&landing_path=%2Fpricing" data-pricing-cta data-cta-id="pricing_pro_annual" data-cta-placement="pricing" data-tier="pro" data-plan-id="pro" data-billing-cycle="annual" data-price="149" onclick="try{posthog.capture('pricing_cta_click',{cta:'start_pro_annual',tier:'pro',placement:'pricing_page',price:149})}catch(_){};try{plausible('pricing_cta_click',{props:{cta:'start_pro_annual',tier:'pro'}})}catch(_){}" style="color:var(--cyan);text-decoration:none;font-weight:600;">$149/year (save 35%) →</a></p>
|
|
267
315
|
</div>
|
|
268
316
|
|
|
269
317
|
<div class="price-card enterprise-card" id="enterprise">
|
|
@@ -280,7 +328,7 @@ __GA_BOOTSTRAP__
|
|
|
280
328
|
<li>Custom policy layers, compliance audit export, approval boundaries, SSO, and dedicated onboarding with SLA</li>
|
|
281
329
|
<li>Rollout starts only after workflow and proof review are explicit</li>
|
|
282
330
|
</ul>
|
|
283
|
-
<a class="btn-team" href="/?utm_source=pricing&utm_medium=enterprise_card&utm_campaign=enterprise_intake&cta_id=pricing_enterprise_intake&cta_placement=pricing&plan_id=enterprise#workflow-sprint-intake" onclick="try{posthog.capture('pricing_cta_click',{cta:'enterprise_intake',tier:'enterprise',placement:'pricing_page',price:0})}catch(_){};try{plausible('pricing_cta_click',{props:{cta:'enterprise_intake',tier:'enterprise'}})}catch(_){}">Talk to us</a>
|
|
331
|
+
<a class="btn-team" href="/?utm_source=pricing&utm_medium=enterprise_card&utm_campaign=enterprise_intake&cta_id=pricing_enterprise_intake&cta_placement=pricing&plan_id=enterprise#workflow-sprint-intake" data-pricing-cta data-cta-id="pricing_enterprise_intake" data-cta-placement="pricing" data-tier="enterprise" data-plan-id="enterprise" data-price="0" onclick="try{posthog.capture('pricing_cta_click',{cta:'enterprise_intake',tier:'enterprise',placement:'pricing_page',price:0})}catch(_){};try{plausible('pricing_cta_click',{props:{cta:'enterprise_intake',tier:'enterprise'}})}catch(_){}">Talk to us</a>
|
|
284
332
|
<p class="btn-sub">Custom pricing, scoped through intake so the workflow is explicit before checkout.</p>
|
|
285
333
|
</div>
|
|
286
334
|
|
|
@@ -288,7 +336,7 @@ __GA_BOOTSTRAP__
|
|
|
288
336
|
|
|
289
337
|
<div style="text-align:center;margin:32px 0;color:var(--text-muted);font-size:14px;">
|
|
290
338
|
Need founder help? Do not buy a blind diagnostic from a pricing table.
|
|
291
|
-
<a href="/?utm_source=pricing&utm_medium=scope_first&utm_campaign=enterprise_intake&cta_id=pricing_scope_first&cta_placement=pricing_note&plan_id=enterprise#workflow-sprint-intake" style="color:var(--cyan);text-decoration:none;font-weight:600;" onclick="try{posthog.capture('pricing_cta_click',{cta:'scope_first',tier:'enterprise',price:0})}catch(_){};try{plausible('pricing_cta_click',{props:{cta:'scope_first',tier:'enterprise'}})}catch(_){}">Send the workflow first</a> — then we scope the smallest paid rollout that can prove one repeated failure is blocked.
|
|
339
|
+
<a href="/?utm_source=pricing&utm_medium=scope_first&utm_campaign=enterprise_intake&cta_id=pricing_scope_first&cta_placement=pricing_note&plan_id=enterprise#workflow-sprint-intake" data-pricing-cta data-cta-id="pricing_scope_first" data-cta-placement="pricing_note" data-tier="enterprise" data-plan-id="enterprise" data-price="0" style="color:var(--cyan);text-decoration:none;font-weight:600;" onclick="try{posthog.capture('pricing_cta_click',{cta:'scope_first',tier:'enterprise',price:0})}catch(_){};try{plausible('pricing_cta_click',{props:{cta:'scope_first',tier:'enterprise'}})}catch(_){}">Send the workflow first</a> — then we scope the smallest paid rollout that can prove one repeated failure is blocked.
|
|
292
340
|
</div>
|
|
293
341
|
</section>
|
|
294
342
|
|
|
@@ -298,7 +346,7 @@ __GA_BOOTSTRAP__
|
|
|
298
346
|
<div class="faq-list">
|
|
299
347
|
<div class="faq-item">
|
|
300
348
|
<div class="faq-q">What does Pro add over the free CLI?</div>
|
|
301
|
-
<div class="faq-a">Free gives you
|
|
349
|
+
<div class="faq-a">Free gives you 2 captures/day and 3 active rules, running entirely on your machine. Pro is the hosted layer: unlimited captures, unlimited rules, lesson sync across machines, a dashboard without self-hosting, managed adapter updates, and DPO export. You're paying for infrastructure we run, not features we hide.</div>
|
|
302
350
|
</div>
|
|
303
351
|
<div class="faq-item">
|
|
304
352
|
<div class="faq-q">Why not just use an enterprise AI control plane?</div>
|
package/public/pro.html
CHANGED
|
@@ -16,7 +16,7 @@ __GOOGLE_SITE_VERIFICATION_META__
|
|
|
16
16
|
<link rel="apple-touch-icon" href="/assets/brand/thumbgate-mark.svg">
|
|
17
17
|
<meta property="og:image" content="/og.png">
|
|
18
18
|
|
|
19
|
-
<script defer data-domain="thumbgate
|
|
19
|
+
<script defer data-domain="thumbgate.ai" src="https://plausible.io/js/script.js"></script>
|
|
20
20
|
__GA_BOOTSTRAP__
|
|
21
21
|
|
|
22
22
|
<script>
|
|
@@ -37,7 +37,7 @@ __GA_BOOTSTRAP__
|
|
|
37
37
|
<script type="application/ld+json">
|
|
38
38
|
{
|
|
39
39
|
"@context": "https://schema.org",
|
|
40
|
-
"@type": "FAQPage", "mainEntity": [{ "@type": "Question", "name": "How is Pro different from the free install?", "acceptedAnswer": { "@type": "Answer", "text": "Free keeps local recall, checks, and MCP. Pro adds the personal dashboard, DPO export, auto-connect, and founder support." } }, { "@type": "Question", "name": "Does Pro require a cloud account?", "acceptedAnswer": { "@type": "Answer", "text": "No. Pro stays local-first;
|
|
40
|
+
"@type": "FAQPage", "mainEntity": [{ "@type": "Question", "name": "How is Pro different from the free install?", "acceptedAnswer": { "@type": "Answer", "text": "Free keeps local recall, checks, and MCP. Pro adds the personal dashboard, DPO export, auto-connect, and founder support." } }, { "@type": "Question", "name": "Does Pro require a cloud account?", "acceptedAnswer": { "@type": "Answer", "text": "No. Pro stays local-first; Enterprise is the hosted rollout lane for shared lessons, org visibility, and reviews." } }, { "@type": "Question", "name": "What happens after checkout?", "acceptedAnswer": { "@type": "Answer", "text": "You activate Pro, connect the local dashboard, and inspect blocked actions, lessons, and exports." } }, { "@type": "Question", "name": "When should I choose Enterprise instead of Pro?", "acceptedAnswer": { "@type": "Answer", "text": "Choose Enterprise when one correction needs to protect multiple developers or agents across shared repositories." } }]
|
|
41
41
|
}
|
|
42
42
|
</script>
|
|
43
43
|
|
|
@@ -731,7 +731,7 @@ __GA_BOOTSTRAP__
|
|
|
731
731
|
<h1>Buy the operator loop that proves your AI agent stopped repeating the mistake.</h1>
|
|
732
732
|
<p style="font-size:13px;opacity:0.8;margin-bottom:0.5rem;">Updated: <time datetime="2026-04-20">2026-04-20</time> · by <a href="https://github.com/IgorGanapolsky" style="color:inherit;">Igor Ganapolsky</a></p>
|
|
733
733
|
<p>ThumbGate Pro is for one operator who already hit a repeated AI-agent failure and now needs proof: what was blocked, why it was blocked, and what changed before the next risky run.</p>
|
|
734
|
-
<p>Start Pro when you want the local dashboard, DPO export, and a single proof lane for the repeated mistake you need to stop.
|
|
734
|
+
<p>Start Pro when you want the local dashboard, DPO export, and a single proof lane for the repeated mistake you need to stop. Enterprise diagnostics and custom services are handled through intake, not this buyer path.</p>
|
|
735
735
|
<div class="hero-proof">
|
|
736
736
|
<div class="proof-pill">Personal local dashboard</div>
|
|
737
737
|
<div class="proof-pill">DPO export from real corrections</div>
|
|
@@ -951,15 +951,15 @@ __GA_BOOTSTRAP__
|
|
|
951
951
|
</div>
|
|
952
952
|
<div class="faq-item">
|
|
953
953
|
<button class="faq-q" type="button" onclick="toggleFaq(this)" onkeydown="handleFaqKeydown(event)" aria-expanded="false">Does Pro require a cloud account?</button>
|
|
954
|
-
<div class="faq-a">No. Pro is still local-first for the individual operator lane.
|
|
954
|
+
<div class="faq-a">No. Pro is still local-first for the individual operator lane. Enterprise is the hosted rollout lane for shared lessons, org visibility, and hosted review views.</div>
|
|
955
955
|
</div>
|
|
956
956
|
<div class="faq-item">
|
|
957
957
|
<button class="faq-q" type="button" onclick="toggleFaq(this)" onkeydown="handleFaqKeydown(event)" aria-expanded="false">What happens after checkout?</button>
|
|
958
958
|
<div class="faq-a">You activate Pro, connect the personal local dashboard, and your running agents can appear automatically so you can inspect blocked actions, active lessons, and exportable DPO pairs without adding a separate cloud dashboard dependency.</div>
|
|
959
959
|
</div>
|
|
960
960
|
<div class="faq-item">
|
|
961
|
-
<button class="faq-q" type="button" onclick="toggleFaq(this)" onkeydown="handleFaqKeydown(event)" aria-expanded="false">When should I choose
|
|
962
|
-
<div class="faq-a">Choose
|
|
961
|
+
<button class="faq-q" type="button" onclick="toggleFaq(this)" onkeydown="handleFaqKeydown(event)" aria-expanded="false">When should I choose Enterprise instead of Pro?</button>
|
|
962
|
+
<div class="faq-a">Choose Enterprise when one thumbs-down should protect multiple people or agents across shared repositories, or when you need shared hosted lessons, org dashboard visibility, and a workflow hardening pilot with rollout review views.</div>
|
|
963
963
|
</div>
|
|
964
964
|
</div>
|
|
965
965
|
</div>
|
|
@@ -987,7 +987,7 @@ __GA_BOOTSTRAP__
|
|
|
987
987
|
<a href="__VERIFICATION_URL__" target="_blank" rel="noopener">Verification Evidence</a>
|
|
988
988
|
<a href="https://github.com/IgorGanapolsky/ThumbGate" target="_blank" rel="noopener">GitHub</a>
|
|
989
989
|
</div>
|
|
990
|
-
<div class="footer-copy">ThumbGate Pro for individual operators.
|
|
990
|
+
<div class="footer-copy">ThumbGate Pro for individual operators. Enterprise stays intake-first.</div>
|
|
991
991
|
</div>
|
|
992
992
|
</footer>
|
|
993
993
|
|
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
// ---------------------------------------------------------------------------
|
|
4
|
+
// Activation: guided first prevention rule + a live demonstrated block.
|
|
5
|
+
//
|
|
6
|
+
// ~98.5% of `init` users never promote their first rule, so they never see
|
|
7
|
+
// "ThumbGate just blocked a repeat mistake" — the aha moment that drives
|
|
8
|
+
// activation (and, downstream, conversion). `quickstart` walks a new user
|
|
9
|
+
// through capturing one real example, promoting it to a block rule, and then
|
|
10
|
+
// firing that rule against the exact action so they watch it get blocked.
|
|
11
|
+
//
|
|
12
|
+
// SAFETY: this is additive and lives in its own module. `init` is untouched.
|
|
13
|
+
// The interactive flow ONLY runs in a real TTY. Non-interactive / piped / CI
|
|
14
|
+
// invocations print a one-line hint and exit 0 without prompting or hanging.
|
|
15
|
+
// ---------------------------------------------------------------------------
|
|
16
|
+
|
|
17
|
+
const path = require('node:path');
|
|
18
|
+
|
|
19
|
+
const PKG_ROOT = path.join(__dirname, '..');
|
|
20
|
+
const PRO_URL = 'https://thumbgate.ai';
|
|
21
|
+
|
|
22
|
+
// Turn a free-text mistake description into a safe, literal gate pattern. We
|
|
23
|
+
// escape regex metacharacters so arbitrary user input can never produce an
|
|
24
|
+
// invalid or runaway regex inside the gates engine.
|
|
25
|
+
function escapeRegex(text) {
|
|
26
|
+
return String(text).replace(/[.*+?^${}()|[\]\\]/g, String.raw`\$&`);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function pkgVersion() {
|
|
30
|
+
try {
|
|
31
|
+
return require(path.join(PKG_ROOT, 'package.json')).version;
|
|
32
|
+
} catch {
|
|
33
|
+
// Version is cosmetic in the banner; fall back if package.json is unreadable.
|
|
34
|
+
return '0.0.0';
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// Core, dependency-injected activation flow so it is testable without a real
|
|
39
|
+
// TTY. Callers provide ask() (returns a Promise<string>), out() (line writer),
|
|
40
|
+
// and isTTY. Returns a structured result describing what was promoted/blocked.
|
|
41
|
+
//
|
|
42
|
+
// Optional injectables (deps) keep the test hermetic and let the CLI pass the
|
|
43
|
+
// real modules:
|
|
44
|
+
// deps.forcePromote(pattern, action) -> { gateId, totalGates }
|
|
45
|
+
// deps.runGate(input) -> Promise<rawJsonString>
|
|
46
|
+
// deps.captureFeedback(params)
|
|
47
|
+
// deps.trackEvent(name, props)
|
|
48
|
+
async function runActivationFlow({ ask, out, isTTY, deps = {} }) {
|
|
49
|
+
// Hard safety gate: never prompt or hang in non-interactive contexts.
|
|
50
|
+
if (!isTTY) {
|
|
51
|
+
out('thumbgate quickstart is an interactive walkthrough — run it in a terminal.');
|
|
52
|
+
out('Non-interactive setup: npx thumbgate init (or: npx thumbgate quick-start)');
|
|
53
|
+
return { interactive: false, promoted: false, blocked: false };
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
const forcePromote = deps.forcePromote
|
|
57
|
+
|| require(path.join(PKG_ROOT, 'scripts', 'auto-promote-gates')).forcePromote;
|
|
58
|
+
const runGate = deps.runGate
|
|
59
|
+
|| ((input) => require(path.join(PKG_ROOT, 'scripts', 'gates-engine')).runAsync(input));
|
|
60
|
+
let captureFeedback = deps.captureFeedback;
|
|
61
|
+
if (captureFeedback === undefined) {
|
|
62
|
+
try {
|
|
63
|
+
({ captureFeedback } = require(path.join(PKG_ROOT, 'scripts', 'feedback-loop')));
|
|
64
|
+
} catch {
|
|
65
|
+
// Feedback capture is a nice-to-have here; the rule + block is the aha.
|
|
66
|
+
captureFeedback = null;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
const trackEvent = deps.trackEvent || (() => {});
|
|
70
|
+
|
|
71
|
+
out('');
|
|
72
|
+
out(`thumbgate quickstart v${pkgVersion()}`);
|
|
73
|
+
out('');
|
|
74
|
+
out("Let's set up your first prevention rule and watch it block a repeat mistake.");
|
|
75
|
+
out('');
|
|
76
|
+
out('Think of one thing an AI agent did that you never want it to do again.');
|
|
77
|
+
out('Examples: "git push --force to main", "rm -rf node_modules", "edit .env directly".');
|
|
78
|
+
out('');
|
|
79
|
+
|
|
80
|
+
let mistake = String(await ask('The mistake to block: ') || '').trim();
|
|
81
|
+
if (!mistake) {
|
|
82
|
+
mistake = 'git push --force to main';
|
|
83
|
+
out(`(using a starter example: ${mistake})`);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// 1. Capture it as a real thumbs-down example (best-effort).
|
|
87
|
+
if (typeof captureFeedback === 'function') {
|
|
88
|
+
try {
|
|
89
|
+
captureFeedback({
|
|
90
|
+
signal: 'down',
|
|
91
|
+
context: mistake,
|
|
92
|
+
whatWentWrong: mistake,
|
|
93
|
+
whatToChange: `Block this action: ${mistake}`,
|
|
94
|
+
tags: 'quickstart,activation,first-rule',
|
|
95
|
+
gateAction: 'block',
|
|
96
|
+
});
|
|
97
|
+
} catch {
|
|
98
|
+
// Capture failure should not abort the activation aha.
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// 2. Promote it into a hard block rule using the existing primitive.
|
|
103
|
+
const pattern = escapeRegex(mistake);
|
|
104
|
+
const promotion = forcePromote(pattern, 'block');
|
|
105
|
+
out('');
|
|
106
|
+
out(` Rule promoted: ${promotion.gateId} [block]`);
|
|
107
|
+
out(` Active rules now: ${promotion.totalGates}`);
|
|
108
|
+
|
|
109
|
+
// 3. Demonstrate the block. Force strict enforcement for the demo so the
|
|
110
|
+
// user's brand-new rule hard-blocks (default posture is warn-by-default).
|
|
111
|
+
// We restore the prior value so we never mutate the user's environment.
|
|
112
|
+
const priorStrict = process.env.THUMBGATE_STRICT_ENFORCEMENT;
|
|
113
|
+
process.env.THUMBGATE_STRICT_ENFORCEMENT = '1';
|
|
114
|
+
let verdict;
|
|
115
|
+
try {
|
|
116
|
+
const demoInput = { tool_name: 'Bash', tool_input: { command: mistake } };
|
|
117
|
+
const raw = await runGate(demoInput);
|
|
118
|
+
verdict = JSON.parse(raw);
|
|
119
|
+
} finally {
|
|
120
|
+
if (priorStrict === undefined) delete process.env.THUMBGATE_STRICT_ENFORCEMENT;
|
|
121
|
+
else process.env.THUMBGATE_STRICT_ENFORCEMENT = priorStrict;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
const decision = verdict?.decision
|
|
125
|
+
|| verdict?.hookSpecificOutput?.permissionDecision;
|
|
126
|
+
const blocked = decision === 'block' || decision === 'deny';
|
|
127
|
+
|
|
128
|
+
out('');
|
|
129
|
+
if (blocked) {
|
|
130
|
+
out(' | ThumbGate just blocked it.');
|
|
131
|
+
out(` | Action attempted: ${mistake}`);
|
|
132
|
+
out(' | Verdict: BLOCKED — the agent cannot repeat this mistake.');
|
|
133
|
+
} else {
|
|
134
|
+
// Even in warn posture the action is flagged + logged. Be honest about it.
|
|
135
|
+
out(' | ThumbGate flagged it.');
|
|
136
|
+
out(` | Action attempted: ${mistake}`);
|
|
137
|
+
out(' | Verdict: flagged and logged. Set THUMBGATE_STRICT_ENFORCEMENT=1 to hard-block.');
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
// 4. Tie the value the user just saw to what Pro keeps working.
|
|
141
|
+
out('');
|
|
142
|
+
out(' That rule lives in this project. Pro keeps your rules — and the mistakes');
|
|
143
|
+
out(' you teach it — synced across every machine and agent runtime you work in,');
|
|
144
|
+
out(` so the block you just saw follows your whole team. ${PRO_URL}/pricing`);
|
|
145
|
+
out('');
|
|
146
|
+
|
|
147
|
+
try { trackEvent('cli_quickstart_activated', { command: 'quickstart', blocked }); } catch { /* telemetry best-effort */ }
|
|
148
|
+
|
|
149
|
+
return {
|
|
150
|
+
interactive: true,
|
|
151
|
+
promoted: true,
|
|
152
|
+
blocked,
|
|
153
|
+
gateId: promotion.gateId,
|
|
154
|
+
pattern,
|
|
155
|
+
mistake,
|
|
156
|
+
verdict,
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
// CLI entrypoint: wires runActivationFlow to a real readline prompt + stdout.
|
|
161
|
+
function quickstart() {
|
|
162
|
+
const isTTY = Boolean(process.stdout.isTTY && process.stdin.isTTY);
|
|
163
|
+
const out = (line = '') => console.log(line);
|
|
164
|
+
|
|
165
|
+
const trackEvent = (() => {
|
|
166
|
+
try { return require(path.join(PKG_ROOT, 'scripts', 'cli-telemetry')).trackEvent; } catch { return () => {}; }
|
|
167
|
+
})();
|
|
168
|
+
|
|
169
|
+
if (!isTTY) {
|
|
170
|
+
// Mirror the non-interactive branch without opening readline (which would
|
|
171
|
+
// otherwise keep the process alive waiting for input that never comes).
|
|
172
|
+
return runActivationFlow({ ask: async () => '', out, isTTY: false, deps: { trackEvent } });
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
const readline = require('node:readline');
|
|
176
|
+
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
177
|
+
const ask = (q) => new Promise((resolve) => rl.question(q, resolve));
|
|
178
|
+
|
|
179
|
+
return runActivationFlow({ ask, out, isTTY: true, deps: { trackEvent } })
|
|
180
|
+
.catch((err) => {
|
|
181
|
+
console.error(`quickstart error: ${err?.message ?? err}`);
|
|
182
|
+
process.exitCode = 1;
|
|
183
|
+
})
|
|
184
|
+
.finally(() => rl.close());
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
module.exports = { runActivationFlow, quickstart, escapeRegex };
|