thumbgate 1.20.0 → 1.21.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,6 +1,6 @@
1
1
  {
2
2
  "name": "thumbgate-marketplace",
3
- "version": "1.20.0",
3
+ "version": "1.21.1",
4
4
  "owner": {
5
5
  "name": "Igor Ganapolsky",
6
6
  "email": "ig5973700@gmail.com"
@@ -8,47 +8,75 @@
8
8
  "plugins": [
9
9
  {
10
10
  "name": "thumbgate",
11
- "description": "Type 👍 or 👎 on any agent action. ThumbGate captures it, distills a lesson, and blocks the pattern from repeating. One thumbs-down = the agent physically cannot make that mistake again. 33 pre-action checks, budget enforcement, self-protection, and NIST/SOC2 compliance tags.",
11
+ "description": "One 👎 becomes a hard rule the agent cannot bypass. Captures thumbs-down feedback, distills it into PreToolUse Pre-Action Checks, enforced across every future Claude Code session.",
12
+ "longDescription": "ThumbGate is a tripwire, not a memory layer. When you thumbs-down an agent action — a force-push that overwrote a teammate's commit, a destructive SQL drop, a refactor you already rejected — ThumbGate captures the pattern, distills a one-sentence lesson, and installs it as a PreToolUse block. The next time the agent reaches for the same tool call shape, the hook fires before execution and Claude sees your own words back as the reason.\n\nThe enforcement lives in the hook, not in the model's context, so the agent cannot bypass it by forgetting, by being prompted around it, or by switching sessions. Same rule works in Claude Code, Cursor, Codex, Gemini CLI, Amp, Cline, and OpenCode.\n\n33 pre-action checks shipped (force-push, destructive SQL, mass-delete, npm publish from wrong branch, deploy without verification). Budget enforcement (action count + time limits) prevents runaway agent sessions. NIST / SOC2 / OWASP / CWE compliance tags on every rule for enterprise teams. DPO training-pair export for teams running their own fine-tunes.\n\nFree tier: unlimited local rules, fully offline. Pro ($19/mo): cloud sync across team, dashboard, audit export.",
12
13
  "source": {
13
14
  "source": "npm",
14
15
  "package": "thumbgate"
15
16
  },
16
- "version": "1.20.0",
17
+ "version": "1.21.1",
17
18
  "author": {
18
- "name": "Igor Ganapolsky"
19
+ "name": "Igor Ganapolsky",
20
+ "email": "ig5973700@gmail.com",
21
+ "url": "https://thumbgate.ai"
19
22
  },
20
23
  "homepage": "https://thumbgate-production.up.railway.app",
21
24
  "repository": "https://github.com/IgorGanapolsky/ThumbGate",
22
25
  "license": "MIT",
23
26
  "category": "developer-tools",
24
27
  "tags": [
25
- "pre-action-checks",
26
- "ai-agent-safety",
27
- "mcp",
28
- "memory",
28
+ "guardrails",
29
+ "pretooluse",
30
+ "hooks",
31
+ "feedback",
32
+ "rlhf",
33
+ "dpo",
34
+ "agent-safety",
29
35
  "workflow-hardening"
30
36
  ],
31
37
  "keywords": [
38
+ "guardrails",
39
+ "pretooluse",
40
+ "hooks",
41
+ "feedback",
42
+ "rlhf",
43
+ "dpo",
44
+ "agent-safety",
45
+ "workflow-hardening",
32
46
  "claude-desktop",
33
47
  "desktop-extension",
34
48
  "pre-action-checks",
35
49
  "ai-agent-safety",
36
50
  "mcp",
37
- "memory",
38
- "workflow-hardening"
51
+ "memory"
39
52
  ],
53
+ "capabilities": {
54
+ "skills": 2,
55
+ "commands": 5,
56
+ "agents": 1,
57
+ "hooks": 3,
58
+ "mcpServer": "thumbgate serve"
59
+ },
60
+ "installCommand": "/plugin install thumbgate@claude-plugins-official",
40
61
  "metadata": {
41
62
  "author": "Igor Ganapolsky",
42
63
  "homepage": "https://thumbgate-production.up.railway.app",
43
64
  "license": "MIT",
44
65
  "keywords": [
66
+ "guardrails",
67
+ "pretooluse",
68
+ "hooks",
69
+ "feedback",
70
+ "rlhf",
71
+ "dpo",
72
+ "agent-safety",
73
+ "workflow-hardening",
45
74
  "claude-desktop",
46
75
  "desktop-extension",
47
76
  "pre-action-checks",
48
77
  "ai-agent-safety",
49
78
  "mcp",
50
- "memory",
51
- "workflow-hardening"
79
+ "memory"
52
80
  ],
53
81
  "category": "developer-tools"
54
82
  }
@@ -1,22 +1,31 @@
1
1
  {
2
2
  "name": "thumbgate",
3
- "description": "Type 👍 or 👎 on any agent action. ThumbGate captures it, distills a lesson, and blocks the pattern from repeating. One thumbs-down = the agent physically cannot make that mistake again. 33 pre-action checks, budget enforcement, self-protection, and NIST/SOC2 compliance tags.",
4
- "version": "1.20.0",
3
+ "description": "One 👎 becomes a hard rule the agent cannot bypass. Captures thumbs-down feedback, distills it into PreToolUse Pre-Action Checks, enforced across every future Claude Code session.",
4
+ "version": "1.21.1",
5
5
  "author": {
6
- "name": "Igor Ganapolsky"
6
+ "name": "Igor Ganapolsky",
7
+ "email": "ig5973700@gmail.com",
8
+ "url": "https://thumbgate.ai"
7
9
  },
8
10
  "homepage": "https://thumbgate-production.up.railway.app",
9
11
  "repository": "https://github.com/IgorGanapolsky/ThumbGate",
10
12
  "license": "MIT",
13
+ "category": "developer-tools",
11
14
  "keywords": [
15
+ "guardrails",
16
+ "pretooluse",
17
+ "hooks",
18
+ "feedback",
19
+ "rlhf",
20
+ "dpo",
21
+ "agent-safety",
22
+ "workflow-hardening",
12
23
  "claude-desktop",
13
24
  "desktop-extension",
14
25
  "mcp",
15
26
  "pre-action-checks",
16
27
  "ai-agent-safety",
17
- "memory",
18
- "guardrails",
19
- "workflow-hardening"
28
+ "memory"
20
29
  ],
21
30
  "skills": "./skills/",
22
31
  "mcpServers": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "thumbgate",
3
- "version": "1.20.0",
3
+ "version": "1.21.1",
4
4
  "description": "ThumbGate — 👍👎 feedback that teaches your AI agent. Thumbs down a mistake, it never happens again.",
5
5
  "homepage": "https://thumbgate-production.up.railway.app",
6
6
  "transport": "stdio",
package/README.md CHANGED
@@ -6,17 +6,23 @@
6
6
  </a>
7
7
  </p>
8
8
 
9
- **Your AI coding bill has a leak.**
9
+ **AI agents repeat mistakes. You pay for every retry.**
10
10
 
11
- **Stop paying for the same AI mistake twice.**
11
+ ThumbGate remembers what went wrong and permanently blocks it before it happens again. One thumbs-down becomes a prevention rule that fires across every session, every agent, every model — before a single token is spent on the repeat.
12
12
 
13
- Every retry loop, every hallucinated import, every *"let me try a different approach"* — those are billable tokens on every LLM vendor's bill. Thumbs-down once; ThumbGate blocks that exact mistake on every future call. Across Claude Code, Cursor, Codex, Gemini, Amp, Cline, OpenCode — any MCP-compatible agent, forever.
14
-
15
- Under the hood: your thumbs-down becomes one of your **Pre-Action Checks** that physically blocks the pattern **permanently** on every future call across every session, every model, every agent. It is **self-improving agent governance**: every correction promotes a fresh prevention rule, and your library of prevention rules grows stronger with every lesson. Works with Claude Code, Cursor, Codex, Gemini CLI, Amp, Cline, OpenCode, and any MCP-compatible agent. The monthly Anthropic / OpenAI bill stops paying for the same lesson over and over — local-first enforcement, zero tokens spent on repeats.
13
+ ```
14
+ Agent tries: rm -rf tests/
15
+ ThumbGate: BLOCKED"Never delete test directories"
16
+ Pattern matched: rm.*-rf.*tests
17
+ Source: your thumbs-down from last Tuesday
18
+ Tokens spent on this repeat: 0
19
+ ```
16
20
 
17
- > **Prevent expensive AI mistakes. Make AI stop repeating mistakes. Turn a smart assistant into a reliable operator.**
21
+ ```bash
22
+ npx thumbgate init # auto-detects your agent, wires hooks, 30 seconds
23
+ ```
18
24
 
19
- > **Mission:** make AI coding affordable by making sure you never pay for the same mistake twice.
25
+ Works with **Claude Code, Cursor, Codex, Gemini CLI, Amp, Cline, OpenCode** and any MCP-compatible agent. Free tier: 5 active prevention rules. [Pro: $19/mo](https://thumbgate-production.up.railway.app/checkout/pro?utm_source=github&utm_medium=readme) — unlimited rules, dashboard, DPO export.
20
26
 
21
27
  [![CI](https://github.com/IgorGanapolsky/ThumbGate/actions/workflows/ci.yml/badge.svg)](https://github.com/IgorGanapolsky/ThumbGate/actions/workflows/ci.yml)
22
28
  [![npm](https://img.shields.io/npm/v/thumbgate)](https://www.npmjs.com/package/thumbgate)
@@ -48,7 +54,7 @@ If someone is not already bought into ThumbGate, do not lead with architecture.
48
54
 
49
55
  1. **Show the pain:** open the **[ThumbGate GPT](https://thumbgate-production.up.railway.app/go/gpt?utm_source=github&utm_medium=readme&utm_campaign=first_dollar_activation&cta_id=readme_first_dollar_open_gpt&cta_placement=readme_first_dollar)** and paste the bad answer, risky command, deploy, PR action, or agent plan before it runs again.
50
56
  2. **Capture the lesson:** type `thumbs down:` or `thumbs up:` with one concrete sentence. Native ChatGPT rating buttons are not the ThumbGate capture path; typed feedback is.
51
- 3. **Enforce the repeat:** run `npx thumbgate init` where the agent executes so the lesson can become a Pre-Action Check instead of another reminder.
57
+ 3. **Enforce the repeat:** run `npx thumbgate init` where the agent executes so the lesson can become one of your Pre-Action Checks instead of another reminder.
52
58
  4. **Upgrade only after proof:** Solo Pro is for the dashboard, DPO export, proof-ready evidence, and higher capture limits after one real blocked repeat. Team starts with the Workflow Hardening Sprint around one repeated failure, one owner, and one proof review.
53
59
 
54
60
  The buying question is simple: **what repeated AI mistake would be worth blocking before the next tool call?**
@@ -179,6 +185,19 @@ Each recommendation ships with the benchmark commands to run next: feedback-deri
179
185
 
180
186
  Works with **Claude Code, Cursor, Codex, Gemini CLI, Amp, Cline, OpenCode**, and any MCP-compatible agent. Migrating from Roo Code (sunsetting 2026-05-15)? See [`adapters/cline/INSTALL.md`](./adapters/cline/INSTALL.md).
181
187
 
188
+ ### Install scope: machine-wide vs per-project
189
+
190
+ ThumbGate supports two install scopes. Pick once when you install — you can switch later by re-running with the other flag.
191
+
192
+ | Scope | Command | Settings file | Lesson DB + dashboard live in | When to use |
193
+ |-------|---------|---------------|--------------------------------|-------------|
194
+ | **Machine-wide** (default) | `npx thumbgate init` | `~/.claude/settings.json` | `~/.claude/memory/feedback/` | Solo dev — **one shared dashboard across every repo on this machine**. A lesson learned in `repo-A` blocks the same mistake in `repo-B` automatically. |
195
+ | **Per-project** | `npx thumbgate init --project` (in the repo root) | `<repo>/.claude/settings.json` | `<repo>/.claude/memory/feedback/` | Client work, compliance, or multi-tenant — **separate dashboard per repo**, lessons stay isolated, audit trail belongs to the repo. |
196
+
197
+ Both scopes write `mcpServers.thumbgate` + the PreToolUse / UserPromptSubmit / PostToolUse / SessionStart hooks; the only difference is *where*. Machine-wide is the right default for most developers. Switch to `--project` only when you have a reason to keep lessons from bleeding between repos.
198
+
199
+ > Per-project lesson DBs live under each repo's `.claude/memory/feedback/` and **must stay gitignored** — they're a runtime store, not source. ThumbGate's bundled `.gitignore` template handles this.
200
+
182
201
  ### Status bar proof
183
202
 
184
203
  ![Claude Code ThumbGate footer](public/assets/claude-thumbgate-statusbar.svg)
@@ -447,6 +466,7 @@ Pro ($19/mo or $149/yr) removes the rule cap and adds history-aware lesson recal
447
466
  - [**ThumbGate for Federal Agencies**](docs/FEDERAL.md) — pilot-ready posture, NIST 800-53 control mapping, OMB M-24-10 / EO 14110 alignment, ThumbGate-Core gov deployment mode, public/Core boundary invariants. Landing page: [thumbgate.ai/federal](https://thumbgate-production.up.railway.app/federal).
448
467
  - [First Dollar Playbook](docs/FIRST_DOLLAR_PLAYBOOK.md) — turning one painful workflow into the next booked pilot
449
468
  - [Commercial Truth](docs/COMMERCIAL_TRUTH.md) — pricing, claims, what we don't say
469
+ - [Goal Contracts](docs/GOAL_CONTRACTS.md) — evidence-before-done contracts for multi-agent handoffs
450
470
  - [Changeset Strategy](docs/CHANGESET_STRATEGY.md) — release notes and version bump enforcement
451
471
  - [Release Confidence](docs/RELEASE_CONFIDENCE.md) — changesets, version checks, proof lanes
452
472
  - [Verification Evidence](docs/VERIFICATION_EVIDENCE.md) — proof artifacts
@@ -2,13 +2,13 @@
2
2
  "mcpServers": {
3
3
  "thumbgate": {
4
4
  "command": "npx",
5
- "args": ["--yes", "--package", "thumbgate@1.20.0", "thumbgate", "serve"]
5
+ "args": ["--yes", "--package", "thumbgate@1.21.1", "thumbgate", "serve"]
6
6
  }
7
7
  },
8
8
  "hooks": {
9
9
  "preToolUse": {
10
10
  "command": "npx",
11
- "args": ["--yes", "--package", "thumbgate@1.20.0", "thumbgate", "gate-check"]
11
+ "args": ["--yes", "--package", "thumbgate@1.21.1", "thumbgate", "gate-check"]
12
12
  }
13
13
  }
14
14
  }
@@ -216,7 +216,7 @@ const {
216
216
  finalizeSession: finalizeFeedbackSession,
217
217
  } = require('../../scripts/feedback-session');
218
218
 
219
- const SERVER_INFO = { name: 'thumbgate-mcp', version: '1.20.0' };
219
+ const SERVER_INFO = { name: 'thumbgate-mcp', version: '1.21.1' };
220
220
  const COMMERCE_CATEGORIES = [
221
221
  'product_recommendation',
222
222
  'brand_compliance',
@@ -848,12 +848,12 @@ async function callToolInner(name, args) {
848
848
  });
849
849
  }
850
850
  case 'verify_claim':
851
- return toTextResult(verifyClaimEvidence(args.claim));
851
+ return toTextResult(verifyClaimEvidence(args.claim, { goalContract: args.goalContract }));
852
852
  case 'require_evidence_for_claim': {
853
853
  if (!args.claim || typeof args.claim !== 'string') {
854
854
  throw new Error('claim is required and must be a string');
855
855
  }
856
- const verification = verifyClaimEvidence(args.claim);
856
+ const verification = verifyClaimEvidence(args.claim, { goalContract: args.goalContract });
857
857
  const mode = args.mode === 'advisory' ? 'advisory' : 'blocking';
858
858
  const hasMatchingChecks = Array.isArray(verification.checks) && verification.checks.length > 0;
859
859
  const evidenceMissing = hasMatchingChecks && !verification.verified;
@@ -865,9 +865,18 @@ async function callToolInner(name, args) {
865
865
  const { recordAuditEvent } = require('../../scripts/audit-trail');
866
866
  recordAuditEvent({
867
867
  toolName: 'require_evidence_for_claim',
868
- toolInput: { claim: args.claim, mode, sessionId: args.sessionId || null },
868
+ toolInput: {
869
+ claim: args.claim,
870
+ mode,
871
+ sessionId: args.sessionId || null,
872
+ goalContract: verification.goalContract && verification.goalContract.matched
873
+ ? verification.goalContract
874
+ : null,
875
+ },
869
876
  decision: blocking ? 'deny' : 'allow',
870
- gateId: 'completion_claim',
877
+ gateId: verification.goalContract && verification.goalContract.matched
878
+ ? 'completion_goal_contract'
879
+ : 'completion_claim',
871
880
  message: blocking
872
881
  ? `Completion claim blocked — missing evidence: ${missingActions.join(', ') || 'unknown'}`
873
882
  : `Completion claim verified (${verification.verified ? 'evidence present' : 'no matching gate'})`,
@@ -882,6 +891,7 @@ async function callToolInner(name, args) {
882
891
  matchedChecks: hasMatchingChecks,
883
892
  missingActions,
884
893
  checks: verification.checks,
894
+ goalContract: verification.goalContract,
885
895
  sessionId: args.sessionId || null,
886
896
  });
887
897
  }
@@ -7,7 +7,7 @@
7
7
  "npx",
8
8
  "--yes",
9
9
  "--package",
10
- "thumbgate@1.20.0",
10
+ "thumbgate@1.21.1",
11
11
  "thumbgate",
12
12
  "serve"
13
13
  ],
package/bin/cli.js CHANGED
@@ -396,6 +396,26 @@ function whichExists(cmd) {
396
396
  function setupClaude() {
397
397
  const mcpChanged = mergeMcpJson(path.join(CWD, '.mcp.json'), 'Claude Code', 'project');
398
398
 
399
+ // Wire the canonical ThumbGate gate hooks (PreToolUse pre-action check,
400
+ // UserPromptSubmit, PostToolUse, SessionStart) through the shared wiring
401
+ // path so `init`, `init --agent claude-code`, and `install` all produce the
402
+ // same hook set. Before this, `install` shipped a Claude config with no
403
+ // PreToolUse gate — the core ThumbGate feature was silently missing.
404
+ let wireChanged = false;
405
+ try {
406
+ const { wireHooks } = require(path.join(PKG_ROOT, 'scripts', 'auto-wire-hooks'));
407
+ const wireResult = wireHooks({ agent: 'claude-code' });
408
+ if (wireResult.error) {
409
+ console.log(` Claude Code: ${wireResult.error}`);
410
+ } else if (wireResult.changed) {
411
+ wireChanged = true;
412
+ const lifecycles = [...new Set(wireResult.added.map((h) => h.lifecycle))].join(', ');
413
+ console.log(` Claude Code: wired gate hooks (${lifecycles})`);
414
+ }
415
+ } catch (err) {
416
+ console.log(` Claude Code: hook wiring skipped (${err.message})`);
417
+ }
418
+
399
419
  // Upsert Stop hook into .claude/settings.json for autonomous self-scoring
400
420
  const settingsPath = path.join(CWD, '.claude', 'settings.json');
401
421
  const stopHookCommand = 'bash scripts/hook-stop-self-score.sh';
@@ -452,7 +472,7 @@ function setupClaude() {
452
472
  fs.writeFileSync(settingsPath, JSON.stringify(settings, null, 2) + '\n');
453
473
  }
454
474
 
455
- return mcpChanged || hooksChanged;
475
+ return mcpChanged || hooksChanged || wireChanged;
456
476
  }
457
477
 
458
478
  function setupCodex() {
@@ -724,6 +744,7 @@ function init(cliArgs = parseArgs(process.argv.slice(3))) {
724
744
  let configured = 0;
725
745
 
726
746
  const platforms = [
747
+ { name: 'Claude Code', detect: [() => whichExists('claude'), () => fs.existsSync(path.join(HOME, '.claude'))], setup: setupClaude },
727
748
  { name: 'Codex', detect: [() => whichExists('codex'), () => fs.existsSync(path.join(HOME, '.codex'))], setup: setupCodex },
728
749
  { name: 'Gemini', detect: [() => whichExists('gemini'), () => fs.existsSync(path.join(HOME, '.gemini'))], setup: setupGemini },
729
750
  { name: 'Amp', detect: [() => whichExists('amp'), () => fs.existsSync(path.join(HOME, '.amp'))], setup: setupAmp },
@@ -851,6 +872,12 @@ function capture() {
851
872
  process.exit(1);
852
873
  }
853
874
 
875
+ const gateAction = (args.action || '').toLowerCase();
876
+ if (gateAction && !['block', 'approve', 'warn'].includes(gateAction)) {
877
+ console.error('Unrecognized --action. Use: block (default), approve, or warn');
878
+ process.exit(1);
879
+ }
880
+
854
881
  const result = captureFeedback({
855
882
  signal: normalized,
856
883
  context: args.context || '',
@@ -858,6 +885,7 @@ function capture() {
858
885
  whatToChange: args['what-to-change'],
859
886
  whatWorked: args['what-worked'],
860
887
  tags: args.tags,
888
+ gateAction: gateAction || undefined,
861
889
  });
862
890
 
863
891
  if (result.accepted) {
@@ -2326,6 +2354,7 @@ function help() {
2326
2354
  console.log(' dashboard Open the local ThumbGate dashboard');
2327
2355
  console.log(' doctor Audit runtime isolation + bootstrap context');
2328
2356
  console.log(' pro ThumbGate Pro (dashboard, exports, sync)');
2357
+ console.log(' subscribe <email> Get the 5-min setup guide + weekly tips by email');
2329
2358
  console.log('');
2330
2359
  console.log('More:');
2331
2360
  console.log(' thumbgate help all Full subcommand surface (~70 commands)');
@@ -2371,7 +2400,10 @@ function help() {
2371
2400
 
2372
2401
  // Legacy and specialist commands kept visible until they graduate into the schema.
2373
2402
  console.log('Also available:');
2374
- console.log(' install-mcp Install MCP server into Claude Code settings (--project for local)');
2403
+ console.log(' install-mcp Install MCP server + PreToolUse hooks into Claude Code settings');
2404
+ console.log(' default: machine-wide (~/.claude/settings.json — shared dashboard)');
2405
+ console.log(' --project: per-repo (<cwd>/.claude/settings.json — isolated dashboard)');
2406
+ console.log(' --no-hooks: MCP only, skip hook wiring');
2375
2407
  console.log(' cfo Hosted billing summary (local fallback JSON)');
2376
2408
  console.log(' billing:setup Generate operator key + print Railway setup instructions');
2377
2409
  console.log(' repair-github-marketplace Repair legacy GitHub Marketplace amount mappings');
@@ -2447,6 +2479,11 @@ if (COMMAND === 'daemon' || COMMAND === 'serve-daemon') {
2447
2479
  }
2448
2480
 
2449
2481
  switch (COMMAND) {
2482
+ case '--version':
2483
+ case '-v':
2484
+ case 'version':
2485
+ console.log(pkgVersion());
2486
+ break;
2450
2487
  case 'init':
2451
2488
  init();
2452
2489
  upgradeNudge();
@@ -2870,6 +2907,86 @@ switch (COMMAND) {
2870
2907
  case 'compact':
2871
2908
  compact();
2872
2909
  break;
2910
+ case 'subscribe': {
2911
+ // Capture an installer's email so we can send the 5-minute setup
2912
+ // guide + weekly tips. Drops to /v1/marketing/install-email on the
2913
+ // hosted endpoint; the server fires sendNewsletterWelcomeEmail via
2914
+ // Resend and persists the address for follow-up.
2915
+ //
2916
+ // Usage:
2917
+ // npx thumbgate subscribe you@company.com
2918
+ // npx thumbgate subscribe --email=you@company.com
2919
+ //
2920
+ // Never prompts interactively — postinstall must stay non-interactive
2921
+ // for CI safety. This is the deliberate opt-in path the banner points
2922
+ // at; if the operator runs it, they want the email.
2923
+ const args = process.argv.slice(3);
2924
+ let email = '';
2925
+ for (const arg of args) {
2926
+ if (arg.startsWith('--email=')) email = arg.slice('--email='.length).trim();
2927
+ else if (!arg.startsWith('--')) email = arg.trim();
2928
+ }
2929
+ if (!email || !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email)) {
2930
+ console.error('Usage: npx thumbgate subscribe <email>');
2931
+ console.error(' npx thumbgate subscribe --email=you@company.com');
2932
+ console.error('');
2933
+ console.error('We send a 5-minute setup guide + weekly tips. One-click unsubscribe.');
2934
+ process.exit(1);
2935
+ }
2936
+ const endpoint = process.env.THUMBGATE_INSTALL_EMAIL_ENDPOINT
2937
+ || 'https://thumbgate.ai/v1/marketing/install-email';
2938
+ const payload = JSON.stringify({
2939
+ email,
2940
+ source: 'cli_subscribe',
2941
+ installId: (() => {
2942
+ try {
2943
+ const configPath = path.join(CWD, '.thumbgate', 'config.json');
2944
+ if (!fs.existsSync(configPath)) return null;
2945
+ return (JSON.parse(fs.readFileSync(configPath, 'utf8')).installId) || null;
2946
+ } catch { return null; }
2947
+ })(),
2948
+ cliVersion: pkgVersion(),
2949
+ });
2950
+ const url = new URL(endpoint);
2951
+ const transport = url.protocol === 'https:' ? require('node:https') : require('node:http');
2952
+ const req = transport.request({
2953
+ method: 'POST',
2954
+ hostname: url.hostname,
2955
+ port: url.port || (url.protocol === 'https:' ? 443 : 80),
2956
+ path: url.pathname + url.search,
2957
+ headers: {
2958
+ 'Content-Type': 'application/json',
2959
+ 'Content-Length': Buffer.byteLength(payload),
2960
+ 'User-Agent': `thumbgate-cli/${pkgVersion()}`,
2961
+ },
2962
+ timeout: 8000,
2963
+ }, (res) => {
2964
+ let body = '';
2965
+ res.on('data', (chunk) => { body += chunk; });
2966
+ res.on('end', () => {
2967
+ if (res.statusCode >= 200 && res.statusCode < 300) {
2968
+ console.log(`✓ Subscribed ${email}.`);
2969
+ console.log(' Check your inbox in ~30 seconds for the setup guide.');
2970
+ console.log(' Unsubscribe link is in every email.');
2971
+ process.exit(0);
2972
+ } else {
2973
+ console.error(`✗ Subscribe failed: HTTP ${res.statusCode}${body ? ` — ${body.slice(0, 200)}` : ''}`);
2974
+ process.exit(2);
2975
+ }
2976
+ });
2977
+ });
2978
+ req.on('error', (err) => {
2979
+ console.error(`✗ Subscribe failed: ${err.message}`);
2980
+ console.error(' Network issue? Try again, or email igor.ganapolsky@gmail.com directly.');
2981
+ process.exit(3);
2982
+ });
2983
+ req.on('timeout', () => {
2984
+ req.destroy(new Error('timeout after 8000ms'));
2985
+ });
2986
+ req.write(payload);
2987
+ req.end();
2988
+ break;
2989
+ }
2873
2990
  case 'checkin': {
2874
2991
  // User check-in command — asks how it's going after install
2875
2992
  const thumbgateDir = path.join(CWD, '.thumbgate');
@@ -22,29 +22,35 @@ const {
22
22
  // This captures UTM attribution in our funnel before handing off to Stripe.
23
23
  const PRO_CTA_URL = 'https://thumbgate.ai/go/pro?utm_source=npm&utm_medium=postinstall&utm_campaign=first_dollar';
24
24
  const WORKFLOW_SPRINT_URL = 'https://thumbgate.ai/#workflow-sprint-intake';
25
+ const DASHBOARD_URL = 'https://thumbgate.ai/dashboard?utm_source=npm&utm_medium=postinstall&utm_campaign=dashboard_nudge';
25
26
 
26
27
  process.stderr.write(`
27
28
  ╭─────────────────────────────────────────────────────╮
28
- │ ThumbGate installed.
29
+ │ ThumbGate installed — 14-day Pro trial active.
29
30
  │ │
30
- │ Every repeat-mistake your agent makes costs
31
- tokens. ThumbGate blocks known-bad tool calls
32
- BEFORE the model sees them zero tokens spent
33
- │ on mistakes you've already corrected. │
31
+ │ Every feature unlocked. No limits. No card needed.
32
+ After 14 days, you keep the free tier (5 rules,
33
+ unlimited captures) or upgrade to keep Pro.
34
34
  │ │
35
- │ Start free:
35
+ │ Start now:
36
36
  │ npx thumbgate init │
37
37
  │ npx thumbgate stats │
38
+ │ │
39
+ │ Get the 5-min setup guide + weekly tips: │
40
+ │ npx thumbgate subscribe you@company.com │
41
+ │ │
42
+ │ See your gates firing live: │
43
+ │ ${DASHBOARD_URL.slice(0, 47).padEnd(47, ' ')} │
38
44
  ╰─────────────────────────────────────────────────────╯
39
45
 
40
- Pro ${PRO_PRICE_LABEL}
41
- personal local dashboard, DPO export
42
- Upgrade: ${PRO_CTA_URL}
43
- Direct: ${PRO_MONTHLY_PAYMENT_LINK}
46
+ Your 14-day Pro trial includes:
47
+ Unlimited prevention rules (free caps at 5)
48
+ Lesson search + recall across sessions
49
+ DPO export for preference fine-tuning
50
+ Hosted dashboard — no self-hosting needed
44
51
 
45
- Team: ${TEAM_PRICE_LABEL}
46
- Workflow Hardening Sprint intake:
47
- ${WORKFLOW_SPRINT_URL}
52
+ After the trial: ${PRO_PRICE_LABEL}
53
+ Upgrade: ${PRO_CTA_URL}
48
54
 
49
55
  Or run: npx thumbgate pro
50
56
 
@@ -4,7 +4,6 @@
4
4
  "CodeQL",
5
5
  "Analyze JavaScript (javascript-typescript)",
6
6
  "Verify changeset",
7
- "SonarCloud Code Analysis",
8
7
  "GitGuardian Security Checks",
9
8
  "Socket Security: Project Report",
10
9
  "Socket Security: Pull Request Alerts"
@@ -0,0 +1,46 @@
1
+ {
2
+ "$comment": "Sentinel manifest for post-deploy verification of top-level marketing pages. Each entry is curled against the live production URL after every push to main; if the sentinel string is missing from the response body, the deploy is flagged as broken and the workflow comments on the associated PR. Adding a new top-level marketing page? Add it here so the deploy-verify workflow catches a route regression before a real visitor does. Keep sentinel strings short and stable (visible body copy, not styling classes or hashed assets).",
3
+ "version": 1,
4
+ "pages": [
5
+ {
6
+ "route": "/",
7
+ "sentinel": "Stop paying for the same AI mistake twice",
8
+ "description": "Home page hero (lifeblood — never regress)"
9
+ },
10
+ {
11
+ "route": "/pro",
12
+ "sentinel": "ThumbGate Pro",
13
+ "description": "Pro landing page"
14
+ },
15
+ {
16
+ "route": "/dashboard",
17
+ "sentinel": "ThumbGate Dashboard",
18
+ "description": "Dashboard demo (already enforced by /dashboard step; included here for symmetry with PR comment surface)"
19
+ },
20
+ {
21
+ "route": "/federal",
22
+ "sentinel": "ThumbGate",
23
+ "description": "Federal lead-gen page (SBIR / GSA arrivals)"
24
+ },
25
+ {
26
+ "route": "/numbers",
27
+ "sentinel": "ThumbGate",
28
+ "description": "First-party numbers / data transparency page"
29
+ },
30
+ {
31
+ "route": "/llm-context.md",
32
+ "sentinel": "## What ThumbGate Is",
33
+ "description": "Canonical declarative summary AI crawlers read"
34
+ },
35
+ {
36
+ "route": "/robots.txt",
37
+ "sentinel": "User-agent",
38
+ "description": "Crawl directives (mandatory per Google's 2026-05-15 AI features guide)"
39
+ },
40
+ {
41
+ "route": "/sitemap.xml",
42
+ "sentinel": "<urlset",
43
+ "description": "XML sitemap for search-engine discoverability"
44
+ }
45
+ ]
46
+ }