thumbgate 1.4.0 → 1.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,11 +1,64 @@
1
1
  # ChatGPT GPT Actions: ThumbGate Install
2
2
 
3
- Import the OpenAPI spec into a Custom GPT in under 5 minutes. No coding required.
3
+ Use the published ThumbGate GPT from GPT Store when it is visible for your account, or import the OpenAPI spec into a Custom GPT in under 5 minutes. Regular users use it by replying with šŸ‘/šŸ‘Ž or "thumbs up/down" on ChatGPT answers so ThumbGate remembers lessons, prevents repeated bad answers, and reinforces the answers that worked.
4
+
5
+ ## GPT Store path
6
+
7
+ 1. Open ChatGPT.
8
+ 2. Open **Explore GPTs**.
9
+ 3. Search for `ThumbGate`.
10
+ 4. Choose the GPT by **Igor Ganapolsky** in the **Programming** category.
11
+
12
+ Direct store URL status: published by the operator on April 13, 2026, but the public `chatgpt.com/g/...` URL has not been captured in this repo yet. Do not invent a URL; add it here once the share link is available.
13
+
14
+ ## 30-second regular-user flow
15
+
16
+ 1. Ask the ThumbGate GPT any normal question.
17
+ 2. If the answer helped, reply with `šŸ‘` plus one sentence about what worked.
18
+ 3. If the answer missed, reply with `šŸ‘Ž` plus one sentence about what to change.
19
+ 4. Ask `What do you remember about how I like answers?` to verify the saved lessons.
20
+
21
+ The user should never need to know what MCP, OpenAPI, Actions, DPO, or prevention rules mean. The GPT should explain the loop as: "Reply šŸ‘ or šŸ‘Ž. I remember the lesson for next time."
22
+
23
+ ## Regular-user prompts
24
+
25
+ Use these as GPT conversation starters so regular users know how to teach ThumbGate:
26
+
27
+ 1. `šŸ‘Ž this answer was too vague. Next time give me exact steps.`
28
+ 2. `šŸ‘ this format worked. Remember to answer with short numbered steps.`
29
+ 3. `Thumbs down: you assumed I know technical terms. Next time explain it for a beginner first.`
30
+ 4. `Remember this lesson: I prefer direct answers with examples before theory.`
31
+ 5. `Search my ThumbGate lessons before answering this.`
32
+
33
+ Use typed chat replies. ChatGPT's native feedback buttons may send feedback to OpenAI, but they should not be described as the ThumbGate capture path unless OpenAI exposes them to GPT Actions.
34
+
35
+ ## Pre-action gate flow
36
+
37
+ Use this when the user asks whether an AI agent should run a proposed action, command, file edit, deployment, merge, or publish step:
38
+
39
+ 1. The GPT calls `evaluateDecision` (`POST /v1/decisions/evaluate`) before answering.
40
+ 2. If the response has `decisionControl.executionMode: "blocked"`, the GPT says the action is blocked and explains the returned reason.
41
+ 3. If the response has `decisionControl.executionMode: "checkpoint_required"`, the GPT asks for explicit confirmation before proceeding.
42
+ 4. If the response has `decisionControl.executionMode: "auto_execute"`, the GPT can say the action is allowed and summarize why.
43
+
44
+ Plain thumbs-up/down feedback is the memory loop. The decision endpoint is the gate loop. Do not claim hard blocking unless the decision endpoint, a saved lesson, or a prevention rule was actually applied.
45
+
46
+ ## Best first GPT message
47
+
48
+ Use this as the first response for regular users:
49
+
50
+ ```text
51
+ Ask me anything. After my answer, reply šŸ‘ if it helped or šŸ‘Ž plus one sentence if it missed. I will remember the lesson, avoid repeating bad answer patterns, and reuse the formats you like.
52
+ ```
4
53
 
5
54
  ## Prerequisites
6
55
 
7
56
  - A ChatGPT Plus or Team account (Custom GPTs require a paid plan)
8
- - ThumbGate API running at a public HTTPS URL (see [Deployment docs](../../docs/deployment.md))
57
+ - ThumbGate API running at `https://thumbgate-production.up.railway.app`
58
+ - Privacy policy URL: `https://thumbgate-production.up.railway.app/privacy`
59
+ - Owner-managed `THUMBGATE_API_KEY` for one-time GPT Builder Actions auth
60
+
61
+ Regular GPT users should not need an API key, JSON payload, OpenAPI knowledge, or developer setup. They should only see the thumbs-up/down memory loop.
9
62
 
10
63
  ## Step 1 — Open GPT Builder
11
64
 
@@ -19,7 +72,7 @@ Import the OpenAPI spec into a Custom GPT in under 5 minutes. No coding required
19
72
  2. Click **Create new action**
20
73
  3. Click **Import from URL** — paste your hosted spec URL:
21
74
  ```
22
- https://<your-railway-domain>/openapi.yaml
75
+ https://thumbgate-production.up.railway.app/openapi.yaml
23
76
  ```
24
77
  Or click **Upload file** and select:
25
78
  ```
@@ -34,13 +87,15 @@ In the Actions panel:
34
87
  2. **Auth type**: Bearer
35
88
  3. **API Key**: paste your `THUMBGATE_API_KEY` value
36
89
 
90
+ This is an owner setup field. Do not ask regular GPT users to provide an API key.
91
+
37
92
  ## Step 4 — Update the Server URL
38
93
 
39
94
  In the imported spec, confirm the `servers.url` points to your deployed API:
40
95
 
41
96
  ```yaml
42
97
  servers:
43
- - url: https://<your-railway-domain>
98
+ - url: https://thumbgate-production.up.railway.app
44
99
  ```
45
100
 
46
101
  If you uploaded the file, edit the server URL in the GPT Actions editor.
package/bin/cli.js CHANGED
@@ -1506,6 +1506,7 @@ function help() {
1506
1506
  console.log(' capture [flags] Capture feedback (--feedback=up|down --context="..." --tags="...")');
1507
1507
  console.log(' stats Show feedback analytics + Revenue-at-Risk');
1508
1508
  console.log(' cfo Show hosted billing summary when configured, else local fallback JSON');
1509
+ console.log(' billing:setup Generate operator key + print Railway setup instructions');
1509
1510
  console.log(' repair-github-marketplace Dry-run or apply legacy GitHub Marketplace amount repairs (--write)');
1510
1511
  console.log(' north-star Show proof-backed workflow-run progress toward the North Star');
1511
1512
  console.log(' summary Human-readable feedback summary');
@@ -1612,6 +1613,9 @@ switch (COMMAND) {
1612
1613
  case 'revenue':
1613
1614
  cfo();
1614
1615
  break;
1616
+ case 'billing:setup':
1617
+ require(path.join(PKG_ROOT, 'scripts', 'billing-setup'));
1618
+ break;
1615
1619
  case 'repair-github-marketplace':
1616
1620
  repairGithubMarketplace();
1617
1621
  break;
@@ -3,7 +3,7 @@
3
3
  "repositoryUrl": "https://github.com/IgorGanapolsky/ThumbGate",
4
4
  "homepageUrl": "https://thumbgate-production.up.railway.app",
5
5
  "githubDescription": "CLI-first agent governance for AI coding workflows: pre-action gates, shared lessons, and team safeguards that stop repeated agent mistakes.",
6
- "metaDescription": "CLI-first agent governance for teams shipping AI-generated changes. šŸ‘Ž Thumbs down distills history-aware lessons from up to 8 prior entries and stays linked to a 60-second feedback session. šŸ‘ Thumbs up reinforces safe patterns. Pre-action gates, workflow governance, shared lessons and org visibility, release confidence, and isolated execution guidance turn vibe coding mistakes into shared enforcement and proof-ready rollout.",
6
+ "metaDescription": "CLI-first agent governance for teams shipping AI-generated changes. \ud83d\udc4e Thumbs down distills history-aware lessons from up to 8 prior entries and stays linked to a 60-second feedback session. \ud83d\udc4d Thumbs up reinforces safe patterns. Pre-action gates, workflow governance, shared lessons and org visibility, release confidence, and isolated execution guidance turn vibe coding mistakes into shared enforcement and proof-ready rollout.",
7
7
  "topics": [
8
8
  "thumbgate",
9
9
  "pre-action-gates",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "thumbgate",
3
- "version": "1.4.0",
3
+ "version": "1.4.1",
4
4
  "description": "ThumbGate: self-improving agent governance for engineering teams. Three-tier approval routing (block/approve/log), shared enforcement, CI gates, and audit trails. Every mistake becomes a prevention rule. PreToolUse hooks, Thompson Sampling, SQLite+FTS5 lesson DB, and LanceDB vector search.",
5
5
  "homepage": "https://thumbgate-production.up.railway.app",
6
6
  "repository": {
@@ -37,6 +37,7 @@
37
37
  "changeset:status": "changeset status",
38
38
  "changeset:check": "node scripts/changeset-check.js",
39
39
  "build:claude-mcpb": "node scripts/build-claude-mcpb.js",
40
+ "build:claude-review-zip": "node scripts/build-claude-mcpb.js --review-zip",
40
41
  "build:codex-plugin": "node scripts/build-codex-plugin.js",
41
42
  "verify:quick": "node scripts/verify-run.js quick",
42
43
  "verify:full": "node scripts/verify-run.js full",
@@ -71,7 +72,7 @@
71
72
  "social:post-everywhere:dry": "node scripts/post-everywhere.js --dry-run",
72
73
  "social:reply-monitor": "node scripts/social-reply-monitor.js",
73
74
  "social:reply-monitor:dry": "node scripts/social-reply-monitor.js --dry-run",
74
- "test": "npm run test:schema && npm run test:loop && npm run test:dpo && npm run test:kto && npm run test:api && npm run test:proof && npm run test:e2e && npm run test:rlaif && npm run test:attribution && npm run test:quality && npm run test:intelligence && npm run test:training-export && npm run test:deployment && npm run test:operational-integrity && npm run test:workflow && npm run test:billing && npm run test:cli && npm run test:watcher && npm run test:autoresearch && npm run test:ops && npm run test:tessl && npm run test:gates && npm run test:evoskill && npm run test:gates-hardening && npm run test:workers && npm run test:social-analytics && npm run test:memalign && npm run test:xmemory-lite && npm run test:filesystem-search && npm run test:zernio && npm run test:obsidian-export && npm run test:lesson-db && npm run test:lesson-rotation && npm run test:memory-dedup && npm run test:feedback-quality && npm run test:sync-version && npm run test:check-congruence && npm run test:tool-registry && npm run test:feedback-to-rules && npm run test:memory-firewall && npm run test:belief-update && npm run test:hosted-config && npm run test:cloudflare-sandbox && npm run test:mcp-config && npm run test:plan-gate && npm run test:pulse && npm run test:semantic-layer && npm run test:data-pipeline && npm run test:optimize-context && npm run test:principle-extractor && npm run test:analytics-window && npm run test:funnel-analytics && npm run test:experiment-tracker && npm run test:build-metadata && npm run test:context-engine && npm run test:hf-papers && npm run test:marketing-experiment && npm run test:seo-gsd && npm run test:verify-run && npm run test:export-dpo-pairs && npm run test:export-hf-dataset && npm run test:license && npm run test:bot-detector && npm run test:postinstall && npm run test:funnel-invariants && npm run test:cli-telemetry && npm run test:pro-parity && npm run test:model-tier-router && npm run test:computer-use-firewall && npm run test:skill-exporter && npm run test:statusline && npm run test:evolution && npm run test:org-dashboard && npm run test:multi-hop-recall && npm run test:synthetic-dpo && npm run test:thumbgate-skill && npm run test:learn-hub && npm run test:feedback-fallback && npm run test:metaclaw && npm run test:server-lock && npm run test:control-tower && npm run test:pii-scanner && npm run test:data-governance && npm run test:lesson-inference && npm run test:semantic-dedup && npm run test:fs-utils && npm run test:lesson-retrieval && npm run test:reflector-agent && npm run test:feedback-session && npm run test:feedback-history-distiller && npm run test:hallucination-detector && npm run test:history-distiller && npm run test:predictive-insights && npm run test:prove-predictive-insights && npm run test:statusbar-cli && npm run test:generate-instagram-card && npm run test:instagram-thumbgate-post && npm run test:publish-instagram-thumbgate && npm run test:lesson-synthesis && npm run test:background-governance && npm run test:memory-migration && npm run test:prompt-dlp && npm run test:ephemeral-store && npm run test:agent-security && npm run test:skill-progressive && npm run test:per-step-scoring && npm run test:weekly-auto-post && npm run test:social-post-hourly && npm run test:social-quality-gate && npm run test:a2ui-engine && npm run test:gate-satisfy && npm run test:money-watcher && npm run test:budget && npm run test:quick-start && npm run test:utm && npm run test:product-feedback && npm run test:feedback-root-consolidator && npm run test:engagement-audit && npm run test:install-growth-automation && npm run test:publish-thumbgate-launch && npm run test:reconcile-thumbgate-campaign && npm run test:reddit-publisher && npm run test:schedule-thumbgate-campaign && npm run test:social-reply-monitor && npm run test:sync-launch-assets && npm run test:ai-search-visibility && npm run test:security-scanner && npm run test:llm-client && npm run test:managed-lesson-agent && npm run test:self-distill && npm run test:meta-agent && npm run test:harness-selector && npm run test:seo-guides",
75
+ "test": "npm run test:schema && npm run test:loop && npm run test:dpo && npm run test:kto && npm run test:api && npm run test:proof && npm run test:e2e && npm run test:rlaif && npm run test:attribution && npm run test:quality && npm run test:intelligence && npm run test:training-export && npm run test:deployment && npm run test:operational-integrity && npm run test:workflow && npm run test:billing && npm run test:cli && npm run test:watcher && npm run test:autoresearch && npm run test:ops && npm run test:tessl && npm run test:gates && npm run test:evoskill && npm run test:gates-hardening && npm run test:workers && npm run test:social-analytics && npm run test:memalign && npm run test:xmemory-lite && npm run test:filesystem-search && npm run test:zernio && npm run test:obsidian-export && npm run test:lesson-db && npm run test:lesson-rotation && npm run test:memory-dedup && npm run test:feedback-quality && npm run test:sync-version && npm run test:check-congruence && npm run test:tool-registry && npm run test:feedback-to-rules && npm run test:memory-firewall && npm run test:belief-update && npm run test:hosted-config && npm run test:operational-summary && npm run test:cloudflare-sandbox && npm run test:mcp-config && npm run test:plan-gate && npm run test:pulse && npm run test:semantic-layer && npm run test:data-pipeline && npm run test:optimize-context && npm run test:principle-extractor && npm run test:analytics-window && npm run test:funnel-analytics && npm run test:experiment-tracker && npm run test:build-metadata && npm run test:context-engine && npm run test:hf-papers && npm run test:marketing-experiment && npm run test:seo-gsd && npm run test:verify-run && npm run test:export-dpo-pairs && npm run test:export-hf-dataset && npm run test:license && npm run test:bot-detector && npm run test:postinstall && npm run test:funnel-invariants && npm run test:cli-telemetry && npm run test:pro-parity && npm run test:model-tier-router && npm run test:computer-use-firewall && npm run test:skill-exporter && npm run test:statusline && npm run test:evolution && npm run test:org-dashboard && npm run test:multi-hop-recall && npm run test:synthetic-dpo && npm run test:thumbgate-skill && npm run test:learn-hub && npm run test:feedback-fallback && npm run test:metaclaw && npm run test:server-lock && npm run test:control-tower && npm run test:pii-scanner && npm run test:data-governance && npm run test:lesson-inference && npm run test:semantic-dedup && npm run test:fs-utils && npm run test:lesson-retrieval && npm run test:reflector-agent && npm run test:feedback-session && npm run test:feedback-history-distiller && npm run test:hallucination-detector && npm run test:history-distiller && npm run test:predictive-insights && npm run test:prove-predictive-insights && npm run test:statusbar-cli && npm run test:generate-instagram-card && npm run test:instagram-thumbgate-post && npm run test:publish-instagram-thumbgate && npm run test:lesson-synthesis && npm run test:background-governance && npm run test:memory-migration && npm run test:prompt-dlp && npm run test:ephemeral-store && npm run test:agent-security && npm run test:skill-progressive && npm run test:per-step-scoring && npm run test:weekly-auto-post && npm run test:social-post-hourly && npm run test:social-quality-gate && npm run test:a2ui-engine && npm run test:gate-satisfy && npm run test:money-watcher && npm run test:budget && npm run test:quick-start && npm run test:utm && npm run test:product-feedback && npm run test:feedback-root-consolidator && npm run test:engagement-audit && npm run test:install-growth-automation && npm run test:publish-thumbgate-launch && npm run test:reconcile-thumbgate-campaign && npm run test:reddit-publisher && npm run test:schedule-thumbgate-campaign && npm run test:social-reply-monitor && npm run test:sync-launch-assets && npm run test:ai-search-visibility && npm run test:security-scanner && npm run test:llm-client && npm run test:managed-lesson-agent && npm run test:self-distill && npm run test:meta-agent && npm run test:harness-selector && npm run test:seo-guides && npm run test:enforcement-loop",
75
76
  "test:feedback-fallback": "node --test tests/feedback-fallback.test.js",
76
77
  "test:metaclaw": "node --test tests/metaclaw-features.test.js",
77
78
  "test:server-lock": "node --test tests/server-stdio-lock.test.js",
@@ -92,6 +93,7 @@
92
93
  "test:memory-firewall": "node --test tests/memory-firewall.test.js",
93
94
  "test:belief-update": "node --test tests/belief-update.test.js",
94
95
  "test:hosted-config": "node --test tests/hosted-config.test.js",
96
+ "test:operational-summary": "node --test tests/operational-summary.test.js",
95
97
  "test:cloudflare-sandbox": "node --test tests/cloudflare-dynamic-sandbox.test.js tests/cloudflare-sandbox-api.test.js",
96
98
  "test:mcp-config": "node --test tests/mcp-config.test.js",
97
99
  "test:plan-gate": "node --test tests/plan-gate.test.js",
@@ -132,13 +134,13 @@
132
134
  "test:training-export": "node --test tests/training-export.test.js tests/databricks-export.test.js",
133
135
  "test:deployment": "node --test tests/deployment.test.js tests/deploy-policy.test.js tests/publish-decision.test.js tests/changeset-check.test.js tests/sonarcloud-workflow.test.js",
134
136
  "test:operational-integrity": "node --test tests/operational-integrity.test.js tests/sync-branch-protection.test.js",
135
- "test:workflow": "node --test tests/workflow-contract.test.js tests/social-marketing-assets.test.js tests/social-pipeline.test.js tests/positioning-contract.test.js tests/docs-claim-hygiene.test.js tests/workflow-runs.test.js tests/workflow-sprint-intake.test.js tests/gtm-revenue-loop.test.js tests/enterprise-story.test.js",
137
+ "test:workflow": "node --test tests/workflow-contract.test.js tests/social-marketing-assets.test.js tests/social-pipeline.test.js tests/positioning-contract.test.js tests/docs-claim-hygiene.test.js tests/workflow-runs.test.js tests/workflow-sprint-intake.test.js tests/gtm-revenue-loop.test.js tests/enterprise-story.test.js tests/ralph-loop.test.js",
136
138
  "test:billing": "node --test tests/billing.test.js",
137
139
  "test:cli": "node --test tests/analytics-report.test.js tests/creator-campaigns.test.js tests/cli.test.js tests/codex-bridge-script.test.js tests/dispatch-brief.test.js tests/feedback-normalize.test.js tests/install-mcp.test.js tests/pr-manager.test.js tests/pro-local-dashboard.test.js tests/published-cli.test.js tests/revenue-status.test.js",
138
140
  "test:evolution": "node --test tests/workspace-evolver.test.js",
139
141
  "test:watcher": "node --test tests/jsonl-watcher.test.js",
140
142
  "test:autoresearch": "node --test tests/autoresearch.test.js",
141
- "test:ops": "node --test tests/adk-consolidator.test.js tests/anthropic-partner-strategy.test.js tests/auto-promote-gates.test.js tests/auto-wire-hooks.test.js tests/claude-skill.test.js tests/codegraph-context.test.js tests/commercial-signals.test.js tests/decision-journal.test.js tests/delegation-runtime.test.js tests/disagreement-mining.test.js tests/failure-diagnostics.test.js tests/gate-stats.test.js tests/github-billing.test.js tests/intervention-policy.test.js tests/markdown-escape.test.js tests/mcp-tools-gates.test.js tests/project-bayes-e2e.test.js tests/project-bayes.test.js tests/rate-limiter.test.js tests/schedule-manager.test.js tests/session-handoff.test.js tests/skill-generator.test.js tests/smart-learning.test.js tests/spike-and-sink.test.js tests/stripe-webhook-route.test.js tests/train-from-feedback.test.js tests/workflow-hardening-sprint.test.js tests/workflow-sentinel.test.js tests/test-suite-parity.test.js tests/a2ui-engine.test.js tests/webhook-delivery.test.js",
143
+ "test:ops": "node --test tests/adk-consolidator.test.js tests/anthropic-partner-strategy.test.js tests/auto-promote-gates.test.js tests/auto-wire-hooks.test.js tests/claude-skill.test.js tests/codegraph-context.test.js tests/commercial-signals.test.js tests/decision-journal.test.js tests/delegation-runtime.test.js tests/disagreement-mining.test.js tests/failure-diagnostics.test.js tests/gate-stats.test.js tests/github-billing.test.js tests/intervention-policy.test.js tests/markdown-escape.test.js tests/mcp-tools-gates.test.js tests/project-bayes-e2e.test.js tests/project-bayes.test.js tests/rate-limiter.test.js tests/schedule-manager.test.js tests/session-handoff.test.js tests/skill-generator.test.js tests/smart-learning.test.js tests/spike-and-sink.test.js tests/stripe-webhook-route.test.js tests/stripe-webhook-rotation.test.js tests/train-from-feedback.test.js tests/workflow-hardening-sprint.test.js tests/workflow-sentinel.test.js tests/test-suite-parity.test.js tests/a2ui-engine.test.js tests/webhook-delivery.test.js",
142
144
  "test:tessl": "node --test tests/tessl-export.test.js",
143
145
  "test:gates": "node --test tests/gate-templates.test.js tests/gates-engine.test.js tests/claim-verification.test.js tests/secret-scanner.test.js tests/prompt-guard.test.js tests/audit-trail.test.js tests/profile-router.test.js tests/workflow-sentinel.test.js tests/docker-sandbox-planner.test.js",
144
146
  "test:budget": "node --test tests/budget-enforcer.test.js",
@@ -248,6 +250,7 @@
248
250
  "test:sync-launch-assets": "node --test tests/sync-launch-assets.test.js",
249
251
  "test:reddit-publisher": "node --test tests/reddit-publisher.test.js",
250
252
  "test:engagement-audit": "node --test tests/engagement-audit.test.js",
253
+ "test:enforcement-loop": "node --test tests/enforcement-loop-fixes.test.js",
251
254
  "test:ai-search-visibility": "node --test tests/ai-search-visibility.test.js",
252
255
  "test:security-scanner": "node --test tests/security-scanner.test.js",
253
256
  "test:llm-client": "node --test tests/llm-client.test.js",
@@ -340,6 +343,7 @@
340
343
  "devDependencies": {
341
344
  "@changesets/changelog-github": "^0.5.1",
342
345
  "@changesets/cli": "^2.30.0",
343
- "c8": "^11.0.0"
346
+ "c8": "^11.0.0",
347
+ "undici": "^8.0.2"
344
348
  }
345
349
  }
package/public/index.html CHANGED
@@ -19,9 +19,9 @@
19
19
  <meta charset="UTF-8">
20
20
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
21
21
  __GOOGLE_SITE_VERIFICATION_META__
22
- <title>ThumbGate — Agent governance for AI coding workflows</title>
22
+ <title>ThumbGate — Your AI agent just made that mistake again. One thumbs-down. It never happens again.</title>
23
23
  <meta name="description" content="CLI-first agent governance for teams shipping AI-generated changes. šŸ‘Ž Thumbs down distills history-aware lessons from up to 8 prior entries and stays linked to a 60-second feedback session. šŸ‘ Thumbs up reinforces safe patterns. Pre-action gates, workflow governance, shared lessons and org visibility, release confidence, and isolated execution guidance turn vibe coding mistakes into shared enforcement and proof-ready rollout.">
24
- <meta property="og:title" content="ThumbGate — Agent governance for AI coding workflows">
24
+ <meta property="og:title" content="ThumbGate — Your AI agent just made that mistake again. One thumbs-down. It never happens again.">
25
25
  <meta property="og:description" content="CLI-first agent governance for teams shipping AI-generated changes. šŸ‘Ž Thumbs down distills history-aware lessons from up to 8 prior entries and stays linked to a 60-second feedback session. šŸ‘ Thumbs up reinforces safe patterns. Pre-action gates, workflow governance, shared lessons and org visibility, release confidence, and isolated execution guidance turn vibe coding mistakes into shared enforcement and proof-ready rollout.">
26
26
  <meta property="og:type" content="website">
27
27
  <meta name="keywords" content="ThumbGate, thumbgate, agent governance, AI coding workflow governance, workflow hardening sprint, pre-action gates, CLI-first agent safety, Claude Code, Cursor, Codex, Gemini, Amp, OpenCode, approval policies, audit trail, release confidence, Docker Sandboxes, feedback enforcement, context engineering, AI authenticity, prevent AI slop, human-led AI, AI agent standards enforcement, brand authenticity AI">
@@ -425,6 +425,14 @@ __GA_BOOTSTRAP__
425
425
  .proof-bar .dot { display: none; }
426
426
  }
427
427
  </style>
428
+ <!-- PostHog Analytics -->
429
+ <script>
430
+ !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
+ posthog.init('__POSTHOG_API_KEY__', {
432
+ api_host: 'https://us.i.posthog.com',
433
+ person_profiles: 'identified_only',
434
+ });
435
+ </script>
428
436
  </head>
429
437
  <body>
430
438
 
@@ -443,7 +451,7 @@ __GA_BOOTSTRAP__
443
451
  <a href="/learn">Learn</a>
444
452
  <a href="/compare">Compare</a>
445
453
  <a href="/dashboard">Dashboard Demo</a>
446
- <a href="#workflow-sprint-intake" class="nav-cta">Start Sprint</a>
454
+ <a href="#workflow-sprint-intake" onclick="posthog.capture('workflow_sprint')" class="nav-cta">Start Sprint</a>
447
455
  </div>
448
456
  </div>
449
457
  </nav>
@@ -452,31 +460,38 @@ __GA_BOOTSTRAP__
452
460
  <section class="hero">
453
461
  <div class="container">
454
462
  <div class="hero-thumbs">šŸ‘šŸ‘Ž</div>
455
- <div class="hero-badge">ā— Workflow Hardening Sprint for teams shipping AI-generated changes</div>
456
- <h1>Make one AI workflow<br>safe enough to ship team-wide.</h1>
463
+ <div class="hero-badge">ā— Your AI agent just made that mistake again</div>
464
+ <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>
457
466
  <div class="hero-signals">
458
467
  <div class="signal-pill signal-down">šŸ‘Ž Repeated failure becomes enforcement before the next run</div>
459
- <div class="signal-pill signal-up">šŸ‘ Safe pattern reinforced across the shared workflow</div>
460
- <div class="signal-pill">šŸ›”ļø Human judgment gates every AI action — your standards, not AI slop</div>
461
- </div>
462
- <p class="hero-persona">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>
463
- <p><strong>Best first paid motion:</strong> start with one repo, one workflow, and one repeat failure. ThumbGate turns the blocker into enforcement, routes risky runs toward isolated execution, and gives the buyer a proof-ready story around shared memory, approval boundaries, release confidence, and auditability.</p>
464
- <div class="hero-actions">
465
- <a href="#workflow-sprint-intake" class="btn-team">Start Workflow Hardening Sprint</a>
466
- <a href="https://github.com/IgorGanapolsky/ThumbGate/releases/latest/download/thumbgate-codex-plugin.zip" class="btn-install-link" target="_blank" rel="noopener">Install Codex plugin</a>
467
- <a href="/guide?utm_source=website&utm_medium=homepage_hero&utm_campaign=install_free" class="btn-pro-page btn-install-link">Install Free CLI</a>
468
- <a href="/dashboard?utm_source=website&utm_medium=homepage_hero&utm_campaign=demo" class="btn-demo-link">Open dashboard demo</a>
468
+ <div class="signal-pill signal-up">āœ… Safe pattern reinforced across the shared workflow</div>
469
+ <div class="signal-pill">šŸ” Works with Claude Code Ā· Cursor Ā· Codex Ā· Gemini Ā· Amp</div>
469
470
  </div>
470
- <p class="hero-paid-note"><strong>Running Codex?</strong> Download the published plugin bundle or open the <a href="https://github.com/IgorGanapolsky/ThumbGate/blob/main/plugins/codex-profile/INSTALL.md" target="_blank" rel="noopener">Codex install guide</a> for the repo-local profile and MCP path.</p>
471
- <p class="hero-paid-note"><strong>Start free as an individual.</strong> Pro stays the self-serve lane for personal dashboard and DPO export. Team pricing anchors at <strong>$99/seat/mo with a 3-seat minimum</strong>, but the team path starts intake-first with the Workflow Hardening Sprint so buyers see proof before a wider rollout.</p>
472
- <div class="hero-install" onclick="copyInstall(this)" title="Click to copy">
473
- <span class="prompt">$</span>
474
- <span class="cmd">npx thumbgate init</span>
475
- <span class="copy-hint">click to copy</span>
471
+ <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
+ <div class="hero-actions" style="margin-top:32px;">
473
+ <div class="hero-install" onclick="copyInstall(this)" title="Click to copy" style="margin-bottom:0;">
474
+ <span class="prompt">$</span>
475
+ <span class="cmd">npx thumbgate init</span>
476
+ <span class="copy-hint">click to copy</span>
477
+ </div>
478
+ <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
+ <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>
476
481
  </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>
477
484
  <div class="proof-bar">
478
485
  <a href="/guide" rel="noopener">CLI-first setup guide →</a>
479
486
  <span class="dot"></span>
487
+ <a href="https://github.com/IgorGanapolsky/ThumbGate/releases/latest/download/thumbgate-claude-desktop.mcpb" target="_blank" rel="noopener">Claude plugin bundle →</a>
488
+ <span class="dot"></span>
489
+ <a href="https://github.com/IgorGanapolsky/ThumbGate/blob/main/docs/CLAUDE_DESKTOP_EXTENSION.md" target="_blank" rel="noopener">Claude submission packet →</a>
490
+ <span class="dot"></span>
491
+ <a href="https://github.com/IgorGanapolsky/ThumbGate/blob/main/.claude-plugin/README.md" target="_blank" rel="noopener">Claude marketplace install →</a>
492
+ <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>
494
+ <span class="dot"></span>
480
495
  <a href="https://github.com/IgorGanapolsky/ThumbGate/releases/latest/download/thumbgate-codex-plugin.zip" target="_blank" rel="noopener">Codex plugin download →</a>
481
496
  <span class="dot"></span>
482
497
  <a href="https://github.com/IgorGanapolsky/ThumbGate/blob/main/docs/VERIFICATION_EVIDENCE.md" target="_blank" rel="noopener">Verification evidence →</a>
@@ -515,9 +530,14 @@ __GA_BOOTSTRAP__
515
530
  <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>
516
531
  <div class="card-arrow">Get the Codex plugin →</div>
517
532
  </a>
533
+ <a class="compat-card" href="https://github.com/IgorGanapolsky/ThumbGate/blob/main/adapters/chatgpt/INSTALL.md" target="_blank" rel="noopener">
534
+ <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>
537
+ </a>
518
538
  <a class="compat-card" href="/guides/claude-desktop">
519
539
  <h3>🧩 Claude Desktop plugin</h3>
520
- <p>One command install. No build step, no cloud account. Grab the <code>.mcpb</code> bundle or run <code>npx thumbgate init --claude-desktop</code>.</p>
540
+ <p>Install the published <code>.mcpb</code> bundle today, point buyers at the submission packet, and let Claude Code users add the repo marketplace while the official directory review is still pending.</p>
521
541
  <div class="card-arrow">Get the Claude plugin →</div>
522
542
  </a>
523
543
  <a class="compat-card" href="https://github.com/IgorGanapolsky/ThumbGate/tree/main/plugins" target="_blank" rel="noopener">
@@ -759,10 +779,11 @@ __GA_BOOTSTRAP__
759
779
  "mcpServers": {
760
780
  "thumbgate": {
761
781
  "command": "npx",
762
- "args": ["--yes", "thumbgate", "serve"]
782
+ "args": ["--yes", "--package", "thumbgate", "thumbgate", "serve"]
763
783
  }
764
784
  }
765
785
  }</pre>
786
+ <p style="color: #8b949e; max-width: 760px; margin: 16px auto 0;">Official directory review is separate. Claude Code users can install immediately with <code>/plugin marketplace add IgorGanapolsky/ThumbGate</code> and <code>/plugin install thumbgate@thumbgate-marketplace</code>.</p>
766
787
  </div>
767
788
  </section>
768
789
 
@@ -6,8 +6,8 @@ const path = require('path');
6
6
  const { resolveFeedbackDir } = require('./feedback-paths');
7
7
 
8
8
  const MAX_AUTO_GATES = 10;
9
- const WARN_THRESHOLD = 3; // 3+ repeated failures surface a warning gate
10
- const BLOCK_THRESHOLD = 5; // 5+ repeated failures hard-block the action
9
+ const WARN_THRESHOLD = 2; // 2+ repeated failures surface a warning gate
10
+ const BLOCK_THRESHOLD = 3; // 3+ repeated failures hard-block the action
11
11
  const WINDOW_DAYS = 30;
12
12
 
13
13
  const NEG_SIGNALS = new Set(['negative', 'negative_strong', 'down', 'thumbs_down']);
@@ -20,8 +20,10 @@ function getFeedbackLogPath() {
20
20
  const localClaude = path.join(process.cwd(), '.claude', 'memory', 'feedback', 'feedback-log.jsonl');
21
21
  if (fs.existsSync(localFallback)) return localFallback;
22
22
  if (fs.existsSync(localClaude)) return localClaude;
23
+ // Fall back to resolveFeedbackDir() for proper home-dir resolution
24
+ const resolved = path.join(resolveFeedbackDir(), 'feedback-log.jsonl');
25
+ if (fs.existsSync(resolved)) return resolved;
23
26
  return localFallback; // default even if doesn't exist
24
- return path.join(resolveFeedbackDir(), 'feedback-log.jsonl');
25
27
  }
26
28
 
27
29
  function getAutoGatesPath() {
@@ -0,0 +1,109 @@
1
+ #!/usr/bin/env node
2
+ 'use strict';
3
+
4
+ /**
5
+ * billing-setup.js — Wire up hosted billing for the CFO dashboard
6
+ *
7
+ * Generates a THUMBGATE_OPERATOR_KEY and stores it locally so that
8
+ * `node bin/cli.js cfo --today` pulls live revenue from the production server.
9
+ *
10
+ * Usage:
11
+ * node scripts/billing-setup.js
12
+ *
13
+ * After running, set the printed key on Railway:
14
+ * railway variables set THUMBGATE_OPERATOR_KEY=<key>
15
+ * Then redeploy (or let Railway auto-deploy).
16
+ */
17
+
18
+ const crypto = require('node:crypto');
19
+ const fs = require('node:fs');
20
+ const path = require('node:path');
21
+ const os = require('node:os');
22
+
23
+ const LOCAL_CONFIG_PATH = path.join(os.homedir(), '.config', 'thumbgate', 'operator.json');
24
+ const PROD_URL = 'https://thumbgate-production.up.railway.app';
25
+
26
+ function generateOperatorKey() {
27
+ return `tg_op_${crypto.randomBytes(20).toString('hex')}`;
28
+ }
29
+
30
+ function loadExistingConfig() {
31
+ try {
32
+ const raw = fs.readFileSync(LOCAL_CONFIG_PATH, 'utf8');
33
+ return JSON.parse(raw);
34
+ } catch {
35
+ return null;
36
+ }
37
+ }
38
+
39
+ function saveConfig(config) {
40
+ const dir = path.dirname(LOCAL_CONFIG_PATH);
41
+ fs.mkdirSync(dir, { recursive: true });
42
+ fs.writeFileSync(LOCAL_CONFIG_PATH, JSON.stringify(config, null, 2) + '\n', { mode: 0o600 });
43
+ }
44
+
45
+ async function verifyEndpoint(baseUrl, key) {
46
+ try {
47
+ const url = new URL('/v1/billing/summary?window=today', baseUrl);
48
+ const res = await fetch(url, {
49
+ method: 'GET',
50
+ headers: { authorization: `Bearer ${key}`, accept: 'application/json' },
51
+ });
52
+ return { status: res.status, ok: res.ok };
53
+ } catch (err) {
54
+ return { status: null, ok: false, error: err.message };
55
+ }
56
+ }
57
+
58
+ async function main() {
59
+ const existing = loadExistingConfig();
60
+
61
+ if (existing && existing.operatorKey && existing.baseUrl) {
62
+ console.log('\nāœ“ Operator config already exists at', LOCAL_CONFIG_PATH);
63
+ console.log(' Base URL :', existing.baseUrl);
64
+ console.log(' Operator key:', existing.operatorKey);
65
+ console.log('\nTo regenerate, delete the file and re-run this script.');
66
+
67
+ // Set env for this process so the verify check works
68
+ process.env.THUMBGATE_OPERATOR_KEY = existing.operatorKey;
69
+ process.env.THUMBGATE_BILLING_API_BASE_URL = existing.baseUrl;
70
+
71
+ const check = await verifyEndpoint(existing.baseUrl, existing.operatorKey);
72
+ if (check.ok) {
73
+ console.log('\nāœ“ Production endpoint responds OK — hosted billing is active.');
74
+ } else if (check.status === 403) {
75
+ console.log('\n⚠ Production endpoint returned 403 — the operator key is not yet set on Railway.');
76
+ console.log('\nSet it now:\n');
77
+ console.log(` railway variables set THUMBGATE_OPERATOR_KEY=${existing.operatorKey}`);
78
+ console.log('\nThen redeploy (Railway will pick it up automatically).');
79
+ } else {
80
+ console.log(`\n⚠ Endpoint check returned status ${check.status || 'error'}: ${check.error || ''}`);
81
+ }
82
+ return;
83
+ }
84
+
85
+ const key = generateOperatorKey();
86
+ const config = {
87
+ operatorKey: key,
88
+ baseUrl: process.env.THUMBGATE_BILLING_API_BASE_URL || PROD_URL,
89
+ createdAt: new Date().toISOString(),
90
+ };
91
+
92
+ saveConfig(config);
93
+
94
+ console.log('\nāœ“ Operator key generated and saved to', LOCAL_CONFIG_PATH);
95
+ console.log('\n──────────────────────────────────────────────────────');
96
+ console.log(' THUMBGATE_OPERATOR_KEY =', key);
97
+ console.log('──────────────────────────────────────────────────────');
98
+ console.log('\nSet this key on Railway (one-time):');
99
+ console.log('\n railway variables set THUMBGATE_OPERATOR_KEY=' + key);
100
+ console.log('\nOr paste it into the Railway dashboard under Variables.');
101
+ console.log('\nAfter Railway redeploys, run:\n');
102
+ console.log(' node bin/cli.js cfo --today\n');
103
+ console.log('The CFO dashboard will use live production billing data.');
104
+ }
105
+
106
+ main().catch((err) => {
107
+ console.error('billing-setup error:', err.message);
108
+ process.exit(1);
109
+ });
@@ -5,6 +5,7 @@ const fs = require('fs');
5
5
  const path = require('path');
6
6
  const { execFileSync } = require('child_process');
7
7
  const {
8
+ getClaudePluginReviewVersionedAssetName,
8
9
  getClaudePluginVersionedAssetName,
9
10
  } = require('./distribution-surfaces');
10
11
 
@@ -27,6 +28,14 @@ const RUNTIME_COPY_PATHS = [
27
28
  'SECURITY.md',
28
29
  'server.json',
29
30
  ];
31
+ const REVIEW_PACKET_COPY_PATHS = [
32
+ '.claude-plugin',
33
+ 'docs/CLAUDE_DESKTOP_EXTENSION.md',
34
+ 'README.md',
35
+ 'LICENSE',
36
+ 'SECURITY.md',
37
+ 'server.json',
38
+ ];
30
39
 
31
40
  function readJson(relativePath) {
32
41
  return JSON.parse(fs.readFileSync(path.join(PROJECT_ROOT, relativePath), 'utf8'));
@@ -173,17 +182,74 @@ function buildClaudeMcpb(outputDir = DEFAULT_OUTPUT_DIR) {
173
182
  };
174
183
  }
175
184
 
176
- if (require.main === module) {
177
- const outputDir = process.argv[2]
178
- ? path.resolve(process.cwd(), process.argv[2])
185
+ function buildClaudeReviewZip(outputDir = DEFAULT_OUTPUT_DIR) {
186
+ const packageJson = readJson('package.json');
187
+ const reviewRoot = path.join(outputDir, 'review');
188
+ const reviewDirName = 'thumbgate-claude-plugin-review';
189
+ const stageDir = path.join(reviewRoot, reviewDirName);
190
+ const outputFile = path.join(outputDir, getClaudePluginReviewVersionedAssetName(packageJson.version));
191
+
192
+ fs.rmSync(reviewRoot, { recursive: true, force: true });
193
+ fs.mkdirSync(stageDir, { recursive: true });
194
+
195
+ for (const relativePath of REVIEW_PACKET_COPY_PATHS) {
196
+ copyEntry(relativePath, stageDir);
197
+ }
198
+
199
+ fs.rmSync(outputFile, { force: true });
200
+ exec('zip', ['-qr', outputFile, reviewDirName], { cwd: reviewRoot });
201
+
202
+ return {
203
+ stageDir,
204
+ outputFile,
205
+ };
206
+ }
207
+
208
+ function resolveBuildRequest(args = [], cwd = process.cwd()) {
209
+ const mode = args.includes('--review-zip')
210
+ ? 'review-zip'
211
+ : args.includes('--all')
212
+ ? 'all'
213
+ : 'mcpb';
214
+ const outputArg = args.find((arg) => !arg.startsWith('--'));
215
+ const outputDir = outputArg
216
+ ? path.resolve(cwd, outputArg)
179
217
  : DEFAULT_OUTPUT_DIR;
180
- const { outputFile } = buildClaudeMcpb(outputDir);
181
- console.log(`Built Claude Desktop bundle: ${outputFile}`);
218
+
219
+ return { mode, outputDir };
220
+ }
221
+
222
+ function runBuildRequest({ mode, outputDir }, deps = { buildClaudeMcpb, buildClaudeReviewZip }) {
223
+ if (mode === 'review-zip') {
224
+ const { outputFile } = deps.buildClaudeReviewZip(outputDir);
225
+ return [`Built Claude plugin review zip: ${outputFile}`];
226
+ }
227
+
228
+ if (mode === 'all') {
229
+ const { outputFile } = deps.buildClaudeMcpb(outputDir);
230
+ const { outputFile: reviewOutputFile } = deps.buildClaudeReviewZip(outputDir);
231
+ return [
232
+ `Built Claude Desktop bundle: ${outputFile}`,
233
+ `Built Claude plugin review zip: ${reviewOutputFile}`,
234
+ ];
235
+ }
236
+
237
+ const { outputFile } = deps.buildClaudeMcpb(outputDir);
238
+ return [`Built Claude Desktop bundle: ${outputFile}`];
239
+ }
240
+
241
+ if (require.main === module) {
242
+ for (const line of runBuildRequest(resolveBuildRequest(process.argv.slice(2)))) {
243
+ console.log(line);
244
+ }
182
245
  }
183
246
 
184
247
  module.exports = {
185
248
  DEFAULT_OUTPUT_DIR,
186
249
  buildClaudeMcpbManifest,
250
+ buildClaudeReviewZip,
187
251
  stageClaudeMcpbBundle,
188
252
  buildClaudeMcpb,
253
+ resolveBuildRequest,
254
+ runBuildRequest,
189
255
  };