thumbgate 1.23.1 → 1.23.2

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 (40) hide show
  1. package/.claude-plugin/marketplace.json +5 -5
  2. package/.claude-plugin/plugin.json +2 -2
  3. package/.well-known/llms.txt +26 -11
  4. package/.well-known/mcp/server-card.json +8 -8
  5. package/README.md +69 -34
  6. package/adapters/claude/.mcp.json +2 -2
  7. package/adapters/mcp/server-stdio.js +1 -1
  8. package/adapters/opencode/opencode.json +1 -1
  9. package/bin/cli.js +39 -16
  10. package/bin/postinstall.js +11 -22
  11. package/config/gate-templates.json +72 -0
  12. package/config/github-about.json +1 -1
  13. package/config/post-deploy-marketing-pages.json +6 -1
  14. package/package.json +5 -5
  15. package/public/agent-manager.html +3 -3
  16. package/public/agents-cost-savings.html +3 -3
  17. package/public/ai-malpractice-prevention.html +278 -7
  18. package/public/blog.html +3 -3
  19. package/public/codex-enterprise.html +3 -3
  20. package/public/codex-plugin.html +4 -4
  21. package/public/compare.html +6 -6
  22. package/public/dashboard.html +211 -126
  23. package/public/guide.html +5 -5
  24. package/public/index.html +156 -47
  25. package/public/learn.html +24 -10
  26. package/public/lessons.html +2 -2
  27. package/public/numbers.html +6 -6
  28. package/public/pricing.html +6 -5
  29. package/public/pro.html +1 -0
  30. package/scripts/billing.js +17 -0
  31. package/scripts/commercial-offer.js +4 -1
  32. package/scripts/dashboard.js +53 -1
  33. package/scripts/gates-engine.js +3 -3
  34. package/scripts/plausible-server-events.js +2 -1
  35. package/scripts/rate-limiter.js +16 -12
  36. package/scripts/seo-gsd.js +167 -1
  37. package/scripts/telemetry-analytics.js +310 -0
  38. package/scripts/visitor-journey.js +172 -0
  39. package/src/api/server.js +65 -29
  40. package/adapters/chatgpt/openapi.yaml +0 -1705
@@ -10,9 +10,9 @@
10
10
  <meta property="og:title" content="ThumbGate — The Numbers">
11
11
  <meta property="og:description" content="Generated first-party operational snapshot: configured gates, recorded interventions, and explicit zero-evidence caveats.">
12
12
  <meta property="og:type" content="website">
13
- <meta property="og:url" content="https://thumbgate-production.up.railway.app/numbers">
13
+ <meta property="og:url" content="https://thumbgate.ai/numbers">
14
14
  <meta name="twitter:card" content="summary_large_image">
15
- <link rel="canonical" href="https://thumbgate-production.up.railway.app/numbers">
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
18
  <script defer data-domain="thumbgate-production.up.railway.app" src="https://plausible.io/js/script.js"></script>
@@ -25,8 +25,8 @@
25
25
  "alternateName": "thumbgate",
26
26
  "applicationCategory": "DeveloperApplication",
27
27
  "operatingSystem": "Cross-platform, Node.js >=18.18.0",
28
- "softwareVersion": "1.23.1",
29
- "url": "https://thumbgate-production.up.railway.app/numbers",
28
+ "softwareVersion": "1.23.2",
29
+ "url": "https://thumbgate.ai/numbers",
30
30
  "dateModified": "2026-05-07",
31
31
  "creator": {
32
32
  "@type": "Person",
@@ -46,7 +46,7 @@
46
46
  "@type": "Dataset",
47
47
  "name": "ThumbGate Operational Snapshot",
48
48
  "description": "First-party operational snapshot from the ThumbGate pre-action check runtime: configured checks, recorded block/warn events, estimated token savings from recorded blocks, and Bayes error rate when the sample supports it.",
49
- "url": "https://thumbgate-production.up.railway.app/numbers",
49
+ "url": "https://thumbgate.ai/numbers",
50
50
  "license": "https://opensource.org/licenses/MIT",
51
51
  "creator": {
52
52
  "@type": "Person",
@@ -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.23.1</div>
205
+ <div class="freshness">Updated: 2026-05-07 · Version 1.23.2</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>
@@ -12,6 +12,7 @@ __GOOGLE_SITE_VERIFICATION_META__
12
12
  <meta property="og:url" content="__APP_ORIGIN__/pricing">
13
13
  <meta property="og:image" content="/og.png">
14
14
  <link rel="canonical" href="__APP_ORIGIN__/pricing">
15
+ <link rel="alternate" type="text/markdown" title="ThumbGate LLM context" href="__APP_ORIGIN__/llm-context.md">
15
16
  <link rel="icon" type="image/png" href="/thumbgate-icon.png">
16
17
  <link rel="apple-touch-icon" href="/assets/brand/thumbgate-mark.svg">
17
18
 
@@ -49,7 +50,7 @@ __GA_BOOTSTRAP__
49
50
  "@context": "https://schema.org",
50
51
  "@type": "FAQPage",
51
52
  "mainEntity": [
52
- { "@type": "Question", "name": "What does Pro add over the free CLI?", "acceptedAnswer": { "@type": "Answer", "text": "Free gives you unlimited captures and 5 active rules, running entirely on your machine. Pro is the hosted layer: lesson sync across machines, a dashboard without self-hosting, managed adapter updates, unlimited rules, and DPO export. You're paying for infrastructure we run, not features we hide." } },
53
+ { "@type": "Question", "name": "What does Pro add over the free CLI?", "acceptedAnswer": { "@type": "Answer", "text": "Free gives you 5 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." } },
53
54
  { "@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 Team add hosted sync for dashboards and shared lessons, but your source code stays local." } },
54
55
  { "@type": "Question", "name": "When should I pick Team over Pro?", "acceptedAnswer": { "@type": "Answer", "text": "When one engineer's correction should protect the whole team. Team shares the lesson database across seats so a fix in one repo prevents the same mistake in every repo." } },
55
56
  { "@type": "Question", "name": "Can I cancel anytime?", "acceptedAnswer": { "@type": "Answer", "text": "Yes. Pro and Team 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." } }
@@ -237,8 +238,8 @@ __GA_BOOTSTRAP__
237
238
  <div class="price">$0</div>
238
239
  <div class="price-sub">Block repeated mistakes daily. Forever free for solo devs.</div>
239
240
  <ul>
240
- <li>Unlimited feedback captures — every thumbs-down, every session</li>
241
- <li>Up to 5 active prevention rules</li>
241
+ <li>5 feedback captures/day (25 total) enough to see the value</li>
242
+ <li>Up to 3 active prevention rules</li>
242
243
  <li>All MCP integrations (Claude Code, Cursor, Codex, Gemini, Amp)</li>
243
244
  <li>PreToolUse hook blocking with built-in safety checks</li>
244
245
  <li>Runs 100% local — no account, no signup, no data leaves your machine</li>
@@ -257,7 +258,7 @@ __GA_BOOTSTRAP__
257
258
  <li><strong>Hosted lesson sync</strong> — corrections follow you across machines, no manual export</li>
258
259
  <li><strong>Managed adapter matrix</strong> — we track runtime changes in Claude Code, Cursor, Codex, Gemini, Amp so you don't</li>
259
260
  <li><strong>Hosted dashboard</strong> — see every blocked action, every rule that fired, without running your own server</li>
260
- <li><strong>Unlimited prevention rules</strong> — free caps at 5 auto-promoted rules</li>
261
+ <li><strong>Unlimited prevention rules</strong> — free caps at 3 auto-promoted rules</li>
261
262
  <li><strong>DPO + HuggingFace export</strong> — training data from your real corrections</li>
262
263
  <li><strong>Auto-connect</strong> — new agent surfaces appear automatically after setup</li>
263
264
  <li>7-day refund window. Cancel anytime.</li>
@@ -296,7 +297,7 @@ __GA_BOOTSTRAP__
296
297
  <div class="faq-list">
297
298
  <div class="faq-item">
298
299
  <div class="faq-q">What does Pro add over the free CLI?</div>
299
- <div class="faq-a">Free gives you unlimited captures and 5 active rules, running entirely on your machine. Pro is the hosted layer: lesson sync across machines, a dashboard without self-hosting, managed adapter updates, unlimited rules, and DPO export. You're paying for infrastructure we run, not features we hide.</div>
300
+ <div class="faq-a">Free gives you 5 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>
300
301
  </div>
301
302
  <div class="faq-item">
302
303
  <div class="faq-q">Does ThumbGate send my code to the cloud?</div>
package/public/pro.html CHANGED
@@ -11,6 +11,7 @@ __GOOGLE_SITE_VERIFICATION_META__
11
11
  <meta property="og:type" content="website">
12
12
  <meta property="og:url" content="__APP_ORIGIN__/pro">
13
13
  <link rel="canonical" href="__APP_ORIGIN__/pro">
14
+ <link rel="alternate" type="text/markdown" title="ThumbGate LLM context" href="__APP_ORIGIN__/llm-context.md">
14
15
  <link rel="icon" type="image/png" href="/thumbgate-icon.png">
15
16
  <link rel="apple-touch-icon" href="/assets/brand/thumbgate-mark.svg">
16
17
  <meta property="og:image" content="/og.png">
@@ -51,6 +51,7 @@ const {
51
51
  } = require('./analytics-window');
52
52
  const { ensureParentDir } = require('./fs-utils');
53
53
  const mailer = require('./mailer');
54
+ const { recordCheckoutFunnelEvent } = require('./plausible-server-events');
54
55
 
55
56
  function loadWorkflowSprintIntakeModule() {
56
57
  const modulePath = path.resolve(__dirname, 'workflow-sprint-intake.js');
@@ -3038,6 +3039,22 @@ async function handleWebhook(rawBody, signature) {
3038
3039
  attribution,
3039
3040
  });
3040
3041
  }
3042
+ // Fire Plausible purchase event so the funnel poller can measure
3043
+ // end-to-end conversion: visitor → CTA → checkout → email → Stripe → purchase.
3044
+ // Fire-and-forget (never blocks the webhook response).
3045
+ void recordCheckoutFunnelEvent('purchase', {
3046
+ page: '/success',
3047
+ props: {
3048
+ sessionId: session.id,
3049
+ customerId,
3050
+ traceId: traceId || '',
3051
+ packId: packId || '',
3052
+ amount: session.amount_total != null ? String(session.amount_total) : '',
3053
+ currency: session.currency || '',
3054
+ ...attribution,
3055
+ },
3056
+ });
3057
+
3041
3058
  return {
3042
3059
  handled: true,
3043
3060
  action: 'provisioned_api_key',
@@ -61,10 +61,12 @@ function buildCaptureReceipt({ signal, feedbackId, memoryId, actionType } = {})
61
61
  ` Stored proof : ${normalizedSignal} feedback${feedbackId ? ` (${feedbackId})` : ''}`,
62
62
  memoryId ? ` Local memory : ${memoryId}` : ' Local memory : saved locally',
63
63
  actionType ? ` Rule pressure : ${actionType}` : ' Rule pressure : available for promotion',
64
+ ' Free today : this proof protects this local machine',
65
+ ' Pro sync : keep this lesson, rule, and dashboard synced across machines and agent runtimes',
64
66
  ' Next proof : npx thumbgate stats',
65
67
  ' Cost proof : npx thumbgate cost',
66
68
  '',
67
- ` Solo Pro : ${PRO_PRICE_LABEL} for dashboard, search, exports, sync`,
69
+ ` Solo Pro : ${PRO_PRICE_LABEL} for hosted sync, search, dashboard, and exports`,
68
70
  ` Upgrade : ${trackedProUrl('cli_capture_receipt', actionType || normalizedSignal.toLowerCase())}`,
69
71
  ` Team path : ${TEAM_PRICE_LABEL}; start with one repeated workflow failure`,
70
72
  ' https://thumbgate.ai/#workflow-sprint-intake',
@@ -98,6 +100,7 @@ function buildStatsReceipt(stats = {}) {
98
100
  lines.push(` Failure pressure : ${negatives} negative ${pluralize(negatives, 'signal')}`);
99
101
  }
100
102
  lines.push(' Show the buyer : npx thumbgate cost');
103
+ lines.push(' Pro sync value : keep these lessons/rules visible across laptops, CI, containers, and agent runtimes');
101
104
  lines.push(` Solo Pro : ${trackedProUrl('cli_stats_receipt', 'proof_seen')}`);
102
105
  lines.push(' Team workflow : https://thumbgate.ai/#workflow-sprint-intake');
103
106
  lines.push('');
@@ -967,6 +967,20 @@ function computeAnalyticsSummary(feedbackDir, options = {}) {
967
967
  return {
968
968
  window: telemetry.window || analyticsWindow,
969
969
  telemetry,
970
+ firstPartyTrafficQuality: telemetry.trafficQuality || {
971
+ rawEvents: telemetry.totalEvents || 0,
972
+ externalEvents: 0,
973
+ excludedEvents: 0,
974
+ exclusionRate: 0,
975
+ byAudience: {},
976
+ byExclusionReason: {},
977
+ external: {
978
+ uniqueVisitors: 0,
979
+ pageViews: 0,
980
+ checkoutStarts: 0,
981
+ },
982
+ verdict: 'missing',
983
+ },
970
984
  funnel: {
971
985
  visitors: uniqueVisitors,
972
986
  sessions: telemetry.visitors ? telemetry.visitors.uniqueSessions || 0 : 0,
@@ -1149,16 +1163,42 @@ function computeInstrumentationReadiness(analytics, billing) {
1149
1163
  const coverage = billing && billing.coverage ? billing.coverage : {};
1150
1164
  const telemetry = analytics.telemetry || {};
1151
1165
  const visitors = telemetry.visitors || {};
1166
+ const quality = telemetry.trafficQuality || analytics.firstPartyTrafficQuality || {};
1167
+ const external = quality.external || {};
1152
1168
  const cli = telemetry.cli || {};
1169
+ const plausibleExportConfigured = Boolean(
1170
+ process.env.PLAUSIBLE_API_KEY && (process.env.PLAUSIBLE_SITE_ID || process.env.PLAUSIBLE_DOMAIN)
1171
+ );
1172
+ const posthogExportConfigured = Boolean(
1173
+ (process.env.POSTHOG_PERSONAL_API_KEY || process.env.POSTHOG_API_KEY) && process.env.POSTHOG_PROJECT_ID
1174
+ );
1175
+ const ga4ExportConfigured = Boolean(
1176
+ process.env.GA4_PROPERTY_ID && (process.env.GOOGLE_APPLICATION_CREDENTIALS || process.env.GOOGLE_CLIENT_EMAIL)
1177
+ );
1178
+ const dashboardGradeExportReady = plausibleExportConfigured || posthogExportConfigured || ga4ExportConfigured;
1153
1179
 
1154
1180
  return {
1155
- plausibleConfigured: /plausible\.io\/js\/script\.js|\/js\/analytics\.js/.test(landingPage),
1181
+ plausibleConfigured: /plausible\.io\/js\/script(?:\.tagged-events)?\.js|\/js\/analytics\.js/.test(landingPage),
1156
1182
  ga4Configured: Boolean(runtimeConfig.gaMeasurementId),
1157
1183
  googleSearchConsoleConfigured: Boolean(runtimeConfig.googleSiteVerification),
1158
1184
  softwareApplicationSchemaPresent: /"@type": "SoftwareApplication"/.test(landingPage),
1159
1185
  faqSchemaPresent: /"@type": "FAQPage"/.test(landingPage),
1160
1186
  telemetryEventsPresent: (telemetry.totalEvents || 0) > 0,
1161
1187
  uniqueVisitorsTracked: visitors.uniqueVisitors || 0,
1188
+ rawTelemetryEvents: quality.rawEvents || telemetry.totalEvents || 0,
1189
+ externalTelemetryEvents: quality.externalEvents || 0,
1190
+ excludedTelemetryEvents: quality.excludedEvents || 0,
1191
+ externalVisitorsTracked: external.uniqueVisitors || 0,
1192
+ externalPageViewsTracked: external.pageViews || 0,
1193
+ externalCheckoutStartsTracked: external.checkoutStarts || 0,
1194
+ externalVisitorPathsTracked: Array.isArray(external.visitorPaths) ? external.visitorPaths.length : 0,
1195
+ internalTestPollutionRate: quality.exclusionRate || 0,
1196
+ trafficQualityVerdict: quality.verdict || 'missing',
1197
+ topExcludedTrafficReason: quality.topExclusionReason || null,
1198
+ plausibleExportConfigured,
1199
+ posthogExportConfigured,
1200
+ ga4ExportConfigured,
1201
+ dashboardGradeExportReady,
1162
1202
  cliInstallsTracked: cli.uniqueInstalls || 0,
1163
1203
  funnelEventsPresent: (analytics.reconciliation.telemetryCheckoutStarts || 0) > 0,
1164
1204
  seoSignalsPresent: (analytics.seo.landingViews || 0) > 0,
@@ -1865,8 +1905,10 @@ function printDashboard(data) {
1865
1905
  console.log('');
1866
1906
  console.log('\uD83D\uDCBC Growth Analytics');
1867
1907
  console.log(` Unique Visitors : ${analytics.trafficMetrics.visitors}`);
1908
+ console.log(` External Visitors: ${instrumentation.externalVisitorsTracked}`);
1868
1909
  console.log(` Sessions : ${analytics.trafficMetrics.sessions}`);
1869
1910
  console.log(` Page Views : ${analytics.trafficMetrics.pageViews}`);
1911
+ console.log(` External Views : ${instrumentation.externalPageViewsTracked}`);
1870
1912
  console.log(` CTA Clicks : ${analytics.trafficMetrics.ctaClicks}`);
1871
1913
  console.log(` Leads : ${analytics.funnel.acquisitionLeads}`);
1872
1914
  console.log(` Sprint Leads : ${analytics.pipeline.workflowSprintLeads.total}`);
@@ -1877,6 +1919,7 @@ function printDashboard(data) {
1877
1919
  console.log(` Booked Revenue : $${(analytics.revenue.bookedRevenueCents / 100).toFixed(2)}`);
1878
1920
  console.log(` Matched Journeys : ${analytics.reconciliation.matchedPaidOrders}/${analytics.reconciliation.telemetryCheckoutStarts}`);
1879
1921
  console.log(` Buyer Loss : ${analytics.buyerLoss.totalSignals}`);
1922
+ console.log(` Data Quality : ${analytics.firstPartyTrafficQuality.verdict} (${instrumentation.excludedTelemetryEvents}/${instrumentation.rawTelemetryEvents} excluded)`);
1880
1923
  if (analytics.telemetry.visitors.topSource) {
1881
1924
  console.log(` Top Source : ${analytics.telemetry.visitors.topSource.key} (${analytics.telemetry.visitors.topSource.count}\u00D7)`);
1882
1925
  }
@@ -1896,6 +1939,15 @@ function printDashboard(data) {
1896
1939
  console.log(` GA4 : ${instrumentation.ga4Configured ? 'configured' : 'missing'}`);
1897
1940
  console.log(` Search Console : ${instrumentation.googleSearchConsoleConfigured ? 'configured' : 'missing'}`);
1898
1941
  console.log(` Telemetry Events : ${instrumentation.telemetryEventsPresent ? instrumentation.uniqueVisitorsTracked : 0} visitors`);
1942
+ console.log(` Clean Visitors : ${instrumentation.externalVisitorsTracked} external (${Math.round((instrumentation.internalTestPollutionRate || 0) * 100)}% internal/test/bot events)`);
1943
+ console.log(` Clean Paths : ${instrumentation.externalVisitorPathsTracked} first-party paths`);
1944
+ if (instrumentation.topExcludedTrafficReason) {
1945
+ console.log(` Top Exclusion : ${instrumentation.topExcludedTrafficReason.key} (${instrumentation.topExcludedTrafficReason.count}\u00D7)`);
1946
+ }
1947
+ console.log(` Plausible Export : ${instrumentation.plausibleExportConfigured ? 'configured' : 'missing API credentials'}`);
1948
+ console.log(` PostHog Export : ${instrumentation.posthogExportConfigured ? 'configured' : 'missing API credentials'}`);
1949
+ console.log(` GA4 Export : ${instrumentation.ga4ExportConfigured ? 'configured' : 'missing API credentials'}`);
1950
+ console.log(` Visitor Paths : ${instrumentation.dashboardGradeExportReady ? 'export-ready' : 'not dashboard-grade in repo'}`);
1899
1951
  console.log(` SEO Signals : ${instrumentation.seoSignalsPresent ? analytics.seo.landingViews : 0}`);
1900
1952
  console.log(` Buyer Loss : ${instrumentation.buyerLossSignalsPresent ? analytics.buyerLoss.totalSignals : 0}`);
1901
1953
  console.log(` Attribution : ${Math.round((instrumentation.trafficAttributionCoverage || 0) * 100)}% page-view coverage`);
@@ -1953,12 +1953,12 @@ function buildBlockActionProCta() {
1953
1953
  if (totalBlocks < 5) return null; // Too early — let them experience the product
1954
1954
 
1955
1955
  if (totalBlocks < 25) {
1956
- return '\n\n💡 Pro: sync rules across machines + dashboard analytics → thumbgate.ai/go/pro';
1956
+ return '\n\n💡 Pro: keep this rule synced across laptops, CI, containers, and agent runtimes → thumbgate.ai/go/pro';
1957
1957
  }
1958
1958
  if (totalBlocks < 100) {
1959
- return `\n\n💡 ${totalBlocks} actions blocked. Pro keeps rules in sync everywhere → thumbgate.ai/go/pro ($19/mo)`;
1959
+ return `\n\n💡 ${totalBlocks} actions blocked. Pro keeps these lessons/rules synced everywhere → thumbgate.ai/go/pro ($19/mo)`;
1960
1960
  }
1961
- return `\n\n💡 ${totalBlocks} mistakes caught. Your team could use this → thumbgate.ai/go/pro`;
1961
+ return `\n\n💡 ${totalBlocks} mistakes caught. Your team could use shared hosted enforcement → thumbgate.ai/go/pro`;
1962
1962
  } catch (_) {
1963
1963
  return null;
1964
1964
  }
@@ -25,7 +25,7 @@
25
25
 
26
26
  const https = require('node:https');
27
27
 
28
- const DEFAULT_PLAUSIBLE_DOMAIN = 'thumbgate-production.up.railway.app';
28
+ const DEFAULT_PLAUSIBLE_DOMAIN = 'thumbgate.ai';
29
29
  const PLAUSIBLE_ENDPOINT = 'https://plausible.io/api/event';
30
30
  const REQUEST_TIMEOUT_MS = 2_000;
31
31
 
@@ -142,6 +142,7 @@ const CHECKOUT_EVENT_NAMES = Object.freeze({
142
142
  view: 'Checkout Pro Viewed',
143
143
  emailSubmitted: 'Checkout Pro Email Submitted',
144
144
  stripeRedirect: 'Checkout Pro Stripe Redirect Started',
145
+ purchase: 'Checkout Pro Purchase Completed',
145
146
  });
146
147
 
147
148
  function recordCheckoutFunnelEvent(stage, options = {}) {
@@ -12,35 +12,37 @@ const {
12
12
  const USAGE_FILE = path.join(process.env.HOME || '/tmp', '.thumbgate', 'usage-limits.json');
13
13
 
14
14
  // ──────────────────────────────────────────────────────────
15
- // Free tier: generous on captures (habit formation) and rules
16
- // (5 active gates), gated on Pro-only features (recall, search,
17
- // exports). Dashboard, exports, and unlimited rules drive Pro.
15
+ // Free tier: tight enough to create upgrade pressure after
16
+ // real usage. Captures and rules are capped so heavy users
17
+ // hit the wall within the first week, not the first quarter.
18
18
  // ──────────────────────────────────────────────────────────
19
19
  const FREE_TIER_LIMITS = {
20
- capture_feedback: { daily: Infinity, lifetime: Infinity, label: 'feedback captures' },
21
- prevention_rules: { daily: Infinity, lifetime: Infinity, label: 'prevention rules generated' },
20
+ capture_feedback: { daily: 5, lifetime: 25, label: 'feedback captures (5/day, 25 total on free)' },
21
+ prevention_rules: { daily: 2, lifetime: 6, label: 'prevention rules generated (2/day on free)' },
22
22
  recall: { daily: 0, lifetime: 0, label: 'recall queries (Pro only)' },
23
23
  search_lessons: { daily: 0, lifetime: 0, label: 'lesson searches (Pro only)' },
24
24
  search_thumbgate: { daily: 0, lifetime: 0, label: 'ThumbGate searches (Pro only)' },
25
25
  commerce_recall: { daily: 0, lifetime: 0, label: 'commerce recalls (Pro only)' },
26
26
  export_dpo: { daily: 0, lifetime: 0, label: 'DPO exports (Pro only)' },
27
27
  export_databricks: { daily: 0, lifetime: 0, label: 'Databricks exports (Pro only)' },
28
- construct_context_pack: { daily: Infinity, lifetime: Infinity, label: 'context packs' },
28
+ construct_context_pack: { daily: 3, lifetime: Infinity, label: 'context packs (3/day on free)' },
29
29
  };
30
30
 
31
- const FREE_TIER_MAX_GATES = 5; // 5 active prevention rules on free; Pro is unlimited
32
- const FREE_TIER_DAILY_BLOCKS = 10; // 10 gate blocks/day on free; after limit, deny → warn + upgrade CTA
31
+ const FREE_TIER_MAX_GATES = 3; // 3 active prevention rules on free; Pro is unlimited
32
+ const FREE_TIER_DAILY_BLOCKS = 3; // 3 gate blocks/day on free; after limit, deny → warn + upgrade CTA
33
33
 
34
34
  const UPGRADE_MESSAGE = `Pro: ${PRO_PRICE_LABEL} — unlimited rules, recall, lesson search, dashboard, and exports: ${PRO_MONTHLY_PAYMENT_LINK}\n Team: ${TEAM_PRICE_LABEL} after workflow qualification.`;
35
35
 
36
36
  const PAYWALL_MESSAGES = {
37
- prevention_rules: 'Free tier includes 5 active prevention rules. Promote more or unlock unlimited rules with Pro.',
37
+ capture_feedback: 'Free tier: 5 captures/day (25 total). Your feedback is stored locally upgrade to capture unlimited.',
38
+ prevention_rules: 'Free tier includes 3 active prevention rules and 2 rule generations/day. Upgrade to Pro for unlimited rules.',
38
39
  recall: 'Recall is a Pro feature. Your past feedback is stored locally — upgrade to search and reuse it.',
39
40
  search_lessons: 'Lesson search is a Pro feature. Upgrade to find patterns in your agent\'s mistakes.',
41
+ construct_context_pack: 'Free tier: 3 context packs/day. Upgrade to Pro for unlimited.',
40
42
  default: 'This feature requires Pro. Start Pro — card required; billed today.',
41
43
  };
42
44
 
43
- const TRIAL_DAYS = 14;
45
+ const TRIAL_DAYS = 7;
44
46
 
45
47
  function getInstallAgeDays() {
46
48
  try {
@@ -91,7 +93,8 @@ function isProTier(authContext) {
91
93
  const { isProLicensed } = require('./license');
92
94
  if (isProLicensed()) return true;
93
95
  } catch (_) {}
94
- // 14-day reverse trial: new installs get full Pro access
96
+ // 7-day reverse trial: new installs get full Pro access, then hit a clear
97
+ // hosted-sync/unlimited-rules pay moment while the product is still fresh.
95
98
  if (isInTrialPeriod()) return true;
96
99
  return false;
97
100
  }
@@ -164,9 +167,10 @@ function checkLimit(action, authContext) {
164
167
 
165
168
  // Check daily limit
166
169
  if (dailyLimit !== Infinity && dailyCurrent >= dailyLimit) {
170
+ const paywallMsg = PAYWALL_MESSAGES[action] || PAYWALL_MESSAGES.default;
167
171
  return {
168
172
  allowed: false,
169
- message: `Daily limit reached. ${UPGRADE_MESSAGE}`,
173
+ message: `Daily limit reached. ${paywallMsg}\n\n${UPGRADE_MESSAGE}`,
170
174
  used: dailyCurrent,
171
175
  limit: dailyLimit,
172
176
  limitType: 'daily',
@@ -155,6 +155,21 @@ const HIGH_ROI_QUERY_SEEDS = [
155
155
  91,
156
156
  'Captures research-led interest in how AI systems decide which brands and tools to recommend.',
157
157
  ),
158
+ querySeed(
159
+ 'ai mode ads agent governance',
160
+ 94,
161
+ 'Conversational Google AI Mode ad demand where ThumbGate can become the cited answer for teams asking how to govern AI-agent actions, not just buy clicks.',
162
+ ),
163
+ querySeed(
164
+ 'mcp tool governance',
165
+ 95,
166
+ 'High-intent MCP buyer query where teams need approval boundaries and audit proof before exposing tools to agents.',
167
+ ),
168
+ querySeed(
169
+ 'ai agent pre action approval gates',
170
+ 95,
171
+ 'Bottom-of-funnel query for teams ready to add human approval and evidence requirements before AI agents touch risky tools.',
172
+ ),
158
173
  {
159
174
  query: 'thumbs up thumbs down feedback for ai coding agents',
160
175
  businessValue: 95,
@@ -1362,6 +1377,51 @@ const AI_RECOMMENDATION_VISIBILITY_GUIDE_SPECS = Object.freeze([
1362
1377
  ],
1363
1378
  relatedPaths: ['/guides/ai-search-topical-presence', '/compare/mem0'],
1364
1379
  },
1380
+ {
1381
+ slug: 'ai-mode-ads-agent-governance',
1382
+ meta: {
1383
+ query: 'ai mode ads agent governance',
1384
+ title: 'AI Mode Ads for Agent Governance | Turn Buyer Prompts Into ThumbGate Demand',
1385
+ heroTitle: 'AI Mode ads make agent-governance promotion conversational',
1386
+ heroSummary: 'Google AI Mode and conversational ad formats shift promotion from click-chasing to answer ownership. ThumbGate should show up when buyers ask how to govern Claude Code, Cursor, Codex, Gemini, MCP tools, and risky agent actions.',
1387
+ },
1388
+ takeaways: [
1389
+ 'Conversational ads reward brands that answer the buyer question directly before the click.',
1390
+ 'ThumbGate should own prompts about pre-action gates, MCP tool governance, repeated AI-agent mistakes, and audit proof.',
1391
+ 'The best paid-search asset is an answer page with schema, proof links, and a checkout or workflow-intake path.',
1392
+ ],
1393
+ sections: [
1394
+ ['paragraphs', 'Why conversational ads change the promotion plan', [
1395
+ 'Search ads are moving toward generated answers and product recommendations inside the search conversation. A buyer may not click ten blue links before forming an opinion; the assistant-like surface may summarize the category, compare options, and mention a vendor in one flow.',
1396
+ 'That means ThumbGate promotion has to be answer-shaped. The page must say exactly what ThumbGate is, which agent-risk problem it solves, which tools it supports, and what proof a buyer can verify before starting checkout or a Workflow Hardening Sprint.',
1397
+ ]],
1398
+ ['bullets', 'Buyer prompts ThumbGate should target', [
1399
+ 'How do I stop Claude Code or Cursor from repeating risky mistakes?',
1400
+ 'What is the pre-action approval layer for AI coding agents?',
1401
+ 'How do teams govern MCP tools before agents call them?',
1402
+ 'How do I audit AI-agent actions before production deploys, payments, or database writes?',
1403
+ 'What tool turns thumbs-down feedback into enforceable rules?',
1404
+ ]],
1405
+ ['paragraphs', 'How this page should be used', [
1406
+ 'Use this page as the landing asset for AI Mode, Gemini, and high-intent search experiments. Do not send conversational-ad traffic to a generic homepage first. Send it to the answer that mirrors the buyer prompt, then route warm readers to Pro checkout, the install guide, or workflow intake depending on intent.',
1407
+ ]],
1408
+ ],
1409
+ faq: [
1410
+ [
1411
+ 'How do AI Mode ads help ThumbGate?',
1412
+ 'They favor direct, conversational answers. ThumbGate benefits when it has pages that answer specific buyer prompts about AI-agent governance, MCP tool risk, pre-action approval gates, and repeated failure prevention.',
1413
+ ],
1414
+ [
1415
+ 'Should ThumbGate run broad Google Ads immediately?',
1416
+ 'No. The high-ROI path is to build answer assets first, then test narrow paid search or AI Mode campaigns against exact buyer prompts where the page, schema, proof links, and checkout route all match the question.',
1417
+ ],
1418
+ [
1419
+ 'What is the one-sentence ad answer?',
1420
+ 'ThumbGate is the pre-action execution gate for AI agents: it checks risky tool calls before they run, turns feedback into rules, and gives teams audit proof.',
1421
+ ],
1422
+ ],
1423
+ relatedPaths: ['/guides/ai-search-topical-presence', '/guides/pre-action-checks', '/guides/mcp-tool-governance'],
1424
+ },
1365
1425
  ]);
1366
1426
 
1367
1427
  function buildAiRecommendationVisibilityGuide(spec) {
@@ -1952,6 +2012,112 @@ const PAGE_BLUEPRINTS = [
1952
2012
  },
1953
2013
  ...BROWSER_BRIDGE_GUIDE_SPECS.map(buildBrowserBridgeGuide),
1954
2014
  ...AI_RECOMMENDATION_VISIBILITY_GUIDE_SPECS.map(buildAiRecommendationVisibilityGuide),
2015
+ {
2016
+ query: 'mcp tool governance',
2017
+ path: '/guides/mcp-tool-governance',
2018
+ pageType: 'guide',
2019
+ pillar: 'pre-action-checks',
2020
+ title: 'MCP Tool Governance | Pre-Action Gates Before Agents Call Tools',
2021
+ heroTitle: 'MCP tool governance before agents call real systems',
2022
+ heroSummary: 'MCP makes tools easy for agents to discover and call. ThumbGate adds the missing governance layer: approval boundaries, evidence requirements, and audit logs before high-risk MCP tool calls execute.',
2023
+ takeaways: [
2024
+ 'MCP adoption expands what agents can touch, so teams need a tool-call control plane.',
2025
+ 'Governance belongs before execution, not only in post-run logs or prompt rules.',
2026
+ 'ThumbGate turns feedback, policies, and evidence requirements into enforceable pre-action gates for MCP-compatible agent workflows.',
2027
+ ],
2028
+ sections: [
2029
+ {
2030
+ heading: 'Why MCP changes the risk model',
2031
+ paragraphs: [
2032
+ 'MCP turns databases, file systems, browsers, ticketing systems, cloud APIs, and internal tools into surfaces an agent can call. That is useful, but it also means a bad plan can become a real action faster than a human reviewer can notice.',
2033
+ 'The governance question is no longer only which tools exist. It is which agent, workflow, branch, file path, command, customer record, or environment is allowed to use each tool under which proof requirements.',
2034
+ ],
2035
+ },
2036
+ {
2037
+ heading: 'What MCP tool governance needs',
2038
+ bullets: [
2039
+ 'Tool inventory: know which tools are exposed to which agents and runtimes.',
2040
+ 'Risk tiers: classify destructive, customer-facing, production, payment, and data-export tools differently from read-only tools.',
2041
+ 'Pre-action checks: require evidence or approval before risky calls execute.',
2042
+ 'Feedback loops: turn thumbs-down reviews and incidents into reusable prevention rules.',
2043
+ 'Audit proof: log allowed, blocked, and approved tool calls with enough context for review.',
2044
+ ],
2045
+ },
2046
+ {
2047
+ heading: 'Where ThumbGate fits',
2048
+ paragraphs: [
2049
+ 'ThumbGate sits between generated intent and executed action. The agent can still plan and propose MCP tool calls, but ThumbGate checks the call against learned lessons, policy boundaries, evidence requirements, and workflow risk before the tool runs.',
2050
+ ],
2051
+ },
2052
+ ],
2053
+ faq: [
2054
+ {
2055
+ question: 'What is MCP tool governance?',
2056
+ answer: 'MCP tool governance is the policy, approval, evidence, and audit layer around tools exposed through Model Context Protocol so agents do not call high-risk systems without the right checks.',
2057
+ },
2058
+ {
2059
+ question: 'How is this different from an MCP server allowlist?',
2060
+ answer: 'An allowlist says a tool exists or is available. ThumbGate adds runtime context: tool arguments, branch, path, environment, prior feedback, evidence requirements, and whether this exact action should be allowed now.',
2061
+ },
2062
+ {
2063
+ question: 'Can ThumbGate work across multiple MCP-compatible agents?',
2064
+ answer: 'Yes. The same local-first lesson and pre-action gate pattern is designed for Claude Code, Cursor, Codex, Gemini, Amp, Cline, OpenCode, and MCP-compatible workflows.',
2065
+ },
2066
+ ],
2067
+ relatedPaths: ['/guides/pre-action-checks', '/guides/ai-mode-ads-agent-governance', '/guides/background-agent-governance'],
2068
+ },
2069
+ {
2070
+ query: 'ai agent pre action approval gates',
2071
+ path: '/guides/ai-agent-pre-action-approval-gates',
2072
+ pageType: 'guide',
2073
+ pillar: 'pre-action-checks',
2074
+ title: 'AI Agent Pre-Action Approval Gates | Human Review Before Risky Tool Calls',
2075
+ heroTitle: 'AI agent pre-action approval gates for risky tool calls',
2076
+ heroSummary: 'Human review after the damage lands is too late. ThumbGate adds pre-action approval gates so risky AI-agent commands, deploys, file edits, API calls, and MCP tool calls can require evidence or explicit approval before execution.',
2077
+ takeaways: [
2078
+ 'Approval gates matter most at the action boundary, where the agent is about to touch files, terminals, APIs, CI, payments, or production systems.',
2079
+ 'The right gate can block, pause for approval, or log-and-continue depending on risk.',
2080
+ 'ThumbGate converts prior thumbs-downs, workflow policies, and verification expectations into reusable approval rules.',
2081
+ ],
2082
+ sections: [
2083
+ {
2084
+ heading: 'Why approval must happen before execution',
2085
+ paragraphs: [
2086
+ 'Many agent failures are irreversible or expensive by the time a post-run reviewer sees them: force-pushes, destructive SQL, unsafe deploys, leaked secrets, customer-facing messages, and runaway API calls.',
2087
+ 'A pre-action approval gate pauses the action while there is still something to decide. The agent keeps its speed on safe work, but risky work requires proof, policy match, or a human yes.',
2088
+ ],
2089
+ },
2090
+ {
2091
+ heading: 'Three practical gate outcomes',
2092
+ bullets: [
2093
+ 'Block: deny known-bad actions such as force-pushing protected branches or touching secret files.',
2094
+ 'Approve: pause production deploys, schema migrations, payment actions, or customer-facing sends until a human approves.',
2095
+ 'Log: allow lower-risk actions while preserving audit evidence for review and future lessons.',
2096
+ ],
2097
+ },
2098
+ {
2099
+ heading: 'How ThumbGate turns approvals into learning',
2100
+ paragraphs: [
2101
+ 'Every approval, block, and thumbs-down gives the system better operating context. Repeated failures become prevention rules, accepted safe paths become reinforced lessons, and the audit trail gives teams evidence that the boundary fired before execution.',
2102
+ ],
2103
+ },
2104
+ ],
2105
+ faq: [
2106
+ {
2107
+ question: 'What should require a pre-action approval gate?',
2108
+ answer: 'Production deploys, destructive database actions, protected-branch writes, payment or refund actions, customer-facing sends, secret or PII access, high-cost API calls, and any repeated failure pattern the team has already corrected once.',
2109
+ },
2110
+ {
2111
+ question: 'Do approval gates slow every agent action down?',
2112
+ answer: 'No. Good gates are risk-tiered. Safe actions can continue, uncertain actions can be logged, risky actions can pause for approval, and known-bad actions can be blocked.',
2113
+ },
2114
+ {
2115
+ question: 'How does ThumbGate know what to block?',
2116
+ answer: 'ThumbGate uses explicit feedback, learned lessons, policy templates, command and path context, evidence requirements, and prior gate outcomes to decide whether the proposed action should proceed.',
2117
+ },
2118
+ ],
2119
+ relatedPaths: ['/guides/pre-action-checks', '/guides/mcp-tool-governance', '/guides/ai-agent-governance-sprint'],
2120
+ },
1955
2121
  guideBlueprint({
1956
2122
  query: 'autoresearch agent safety',
1957
2123
  path: '/guides/autoresearch-agent-safety',
@@ -2756,7 +2922,7 @@ function renderSeoPageHtml(page, runtimeConfig = {}) {
2756
2922
  <meta property="og:type" content="article" />
2757
2923
  <meta property="og:url" content="${escapeHtml(canonicalUrl)}" />
2758
2924
  <link rel="canonical" href="${escapeHtml(canonicalUrl)}" />
2759
- <link rel="llm-context" href="/public/llm-context.md" type="text/markdown" />
2925
+ <link rel="llm-context" href="/llm-context.md" type="text/markdown" />
2760
2926
  <link rel="icon" type="image/svg+xml" href="/thumbgate-icon.png" />
2761
2927
  <link rel="apple-touch-icon" href="/assets/brand/thumbgate-mark.svg" />
2762
2928
  <meta property="og:image" content="/og.png" />