thumbgate 1.27.11 → 1.27.13

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 (131) hide show
  1. package/.claude-plugin/plugin.json +1 -1
  2. package/.well-known/llms.txt +2 -1
  3. package/.well-known/mcp/server-card.json +1 -1
  4. package/README.md +2 -4
  5. package/adapters/claude/.mcp.json +2 -2
  6. package/adapters/mcp/server-stdio.js +1 -1
  7. package/adapters/opencode/opencode.json +1 -1
  8. package/adapters/policy-engine/ethicore-guardian-client.js +68 -0
  9. package/adapters/policy-engine/thumbgate-policy-engine-adapter.js +260 -0
  10. package/bin/cli.js +78 -259
  11. package/config/builtin-lessons.json +23 -0
  12. package/config/gate-templates.json +0 -228
  13. package/config/gates/claim-verification.json +0 -18
  14. package/package.json +35 -25
  15. package/public/assets/brand/thumbgate-logo-transparent.svg +22 -0
  16. package/public/assets/brand/thumbgate-mark-inline-v3.svg +19 -0
  17. package/public/assets/brand/thumbgate-mark.svg +11 -5
  18. package/public/blog.html +0 -30
  19. package/public/brand/thumbgate-mark.svg +9 -5
  20. package/public/chatgpt-app.html +2 -2
  21. package/public/compare.html +2 -1
  22. package/public/dashboard.html +1 -1
  23. package/public/federal.html +1 -1
  24. package/public/index.html +95 -216
  25. package/public/learn.html +59 -35
  26. package/public/lessons.html +1 -1
  27. package/public/numbers.html +2 -2
  28. package/public/pro.html +7 -7
  29. package/scripts/aws-blocks-guardrails.js +228 -0
  30. package/scripts/cli-schema.js +22 -10
  31. package/scripts/dashboard-chat.js +2 -1
  32. package/scripts/document-intake.js +1 -49
  33. package/scripts/durability/step.js +3 -3
  34. package/scripts/gate-stats.js +5 -11
  35. package/scripts/gemini-embedding-policy.js +2 -1
  36. package/scripts/hook-stop-anti-claim.js +116 -184
  37. package/scripts/hosted-config.js +0 -12
  38. package/scripts/llm-client.js +187 -5
  39. package/scripts/plausible-domain-config.js +3 -1
  40. package/scripts/seo-gsd.js +240 -1
  41. package/scripts/tool-registry.js +2 -2
  42. package/scripts/vector-store.js +44 -0
  43. package/scripts/workspace-evolver.js +62 -2
  44. package/src/api/server.js +340 -131
  45. package/public/assets/brand/thumbgate-mark-inline.svg +0 -15
  46. package/public/compare/adopt-ai.html +0 -219
  47. package/public/compare/agentix-labs.html +0 -197
  48. package/public/compare/ai-experience-orchestration.html +0 -216
  49. package/public/compare/anthropic-claude-for-legal.html +0 -260
  50. package/public/compare/anthropic-containment.html +0 -280
  51. package/public/compare/arcade.html +0 -175
  52. package/public/compare/arcjet.html +0 -239
  53. package/public/compare/bumblebee.html +0 -307
  54. package/public/compare/claude-code-hooks.html +0 -294
  55. package/public/compare/databricks-unity-ai-gateway.html +0 -215
  56. package/public/compare/fallow.html +0 -351
  57. package/public/compare/heidi.html +0 -233
  58. package/public/compare/mem0.html +0 -342
  59. package/public/compare/oak-and-sparrow-gatekeeper.html +0 -289
  60. package/public/compare/rein.html +0 -236
  61. package/public/compare/sigmashake.html +0 -256
  62. package/public/compare/speclock.html +0 -342
  63. package/public/guides/agent-harness-optimization.html +0 -342
  64. package/public/guides/agentic-web-governance.html +0 -406
  65. package/public/guides/ai-agent-governance-sprint.html +0 -415
  66. package/public/guides/ai-agent-pre-action-approval-gates.html +0 -401
  67. package/public/guides/ai-agent-workflow-migration-checklist.html +0 -392
  68. package/public/guides/ai-deployment-readiness.html +0 -415
  69. package/public/guides/ai-mode-ads-agent-governance.html +0 -401
  70. package/public/guides/ai-search-topical-presence.html +0 -342
  71. package/public/guides/autoresearch-agent-safety.html +0 -342
  72. package/public/guides/background-agent-governance.html +0 -358
  73. package/public/guides/best-tools-stop-ai-agents-breaking-production.html +0 -363
  74. package/public/guides/browser-automation-safety.html +0 -342
  75. package/public/guides/chatgpt-ads-trust.html +0 -353
  76. package/public/guides/claude-code-feedback.html +0 -339
  77. package/public/guides/claude-code-prevent-repeated-mistakes.html +0 -161
  78. package/public/guides/claude-code-skills-guardrails.html +0 -343
  79. package/public/guides/claude-desktop.html +0 -356
  80. package/public/guides/code-knowledge-graph-guardrails.html +0 -365
  81. package/public/guides/codex-cli-guardrails.html +0 -339
  82. package/public/guides/cursor-agent-guardrails.html +0 -339
  83. package/public/guides/cursor-prevent-repeated-mistakes.html +0 -161
  84. package/public/guides/database-agent-safety.html +0 -406
  85. package/public/guides/deepseek-v4-runtime-guardrails.html +0 -346
  86. package/public/guides/developer-machine-supply-chain-guardrails.html +0 -358
  87. package/public/guides/gcp-mcp-guardrails.html +0 -147
  88. package/public/guides/gemini-cli-feedback-memory.html +0 -339
  89. package/public/guides/gpt-5-5-model-evaluation.html +0 -358
  90. package/public/guides/internal-ai-engineering-stack-guardrails.html +0 -348
  91. package/public/guides/long-running-agent-context-management.html +0 -346
  92. package/public/guides/mcp-tool-governance.html +0 -401
  93. package/public/guides/multica-thumbgate-setup.html +0 -134
  94. package/public/guides/native-messaging-host-security.html +0 -342
  95. package/public/guides/policy-engine-pre-action-gates.html +0 -346
  96. package/public/guides/pre-action-checks.html +0 -342
  97. package/public/guides/pretooluse-hooks-vs-advisory-prompt-rules.html +0 -342
  98. package/public/guides/prompt-tricks-to-workflow-rules.html +0 -365
  99. package/public/guides/proxy-pointer-rag-guardrails.html +0 -352
  100. package/public/guides/rag-precision-tuning-guardrails.html +0 -352
  101. package/public/guides/reasoning-compression-guardrails.html +0 -346
  102. package/public/guides/relational-knowledge-ai-recommendations.html +0 -342
  103. package/public/guides/roo-code-alternative-cline.html +0 -339
  104. package/public/guides/semantic-programmatic-seo-guardrails.html +0 -352
  105. package/public/guides/seo-agent-skills-guardrails.html +0 -344
  106. package/public/guides/stop-repeated-ai-agent-mistakes.html +0 -342
  107. package/public/learn/ac-dc-runtime-enforcement.html +0 -277
  108. package/public/learn/agent-harness-pattern.html +0 -181
  109. package/public/learn/agent-identity-connector-governance.html +0 -146
  110. package/public/learn/agent-swarms-shared-gates.html +0 -173
  111. package/public/learn/agentic-enterprise-context-brain.html +0 -117
  112. package/public/learn/agentic-os-team-governance.html +0 -146
  113. package/public/learn/ai-agent-governance.html +0 -158
  114. package/public/learn/ai-agent-persistent-memory.html +0 -211
  115. package/public/learn/anthropomorphic-claim-gates.html +0 -180
  116. package/public/learn/background-agent-control-layer.html +0 -184
  117. package/public/learn/claude-code-goal-with-rubrics.html +0 -205
  118. package/public/learn/codex-role-plugins-need-governance.html +0 -125
  119. package/public/learn/cost-aware-agent-gate-routing.html +0 -173
  120. package/public/learn/databricks-unity-ai-gateway-runtime-governance.html +0 -157
  121. package/public/learn/deterministic-agent-workflows.html +0 -185
  122. package/public/learn/feedback-loop-vs-decision-layer.html +0 -283
  123. package/public/learn/from-prototype-to-production.html +0 -223
  124. package/public/learn/learn.css +0 -51
  125. package/public/learn/mcp-pre-action-checks-explained.html +0 -172
  126. package/public/learn/pretix-stripe-connect-marketplaces.html +0 -161
  127. package/public/learn/regulated-agent-execution-boundary.html +0 -196
  128. package/public/learn/spec-driven-development.html +0 -168
  129. package/public/learn/stop-ai-agent-force-push.html +0 -134
  130. package/public/learn/vibe-coding-safety-net.html +0 -142
  131. package/scripts/reddit-browser-notification-watch.js +0 -230
package/public/learn.html CHANGED
@@ -115,18 +115,6 @@
115
115
  {
116
116
  "@type": "ListItem",
117
117
  "position": 13,
118
- "url": "https://thumbgate.ai/learn/anthropomorphic-claim-gates",
119
- "name": "Anthropomorphic Claim Gates for AI Agents"
120
- },
121
- {
122
- "@type": "ListItem",
123
- "position": 14,
124
- "url": "https://thumbgate.ai/learn/agent-identity-connector-governance",
125
- "name": "Agent Identity and Connector Governance"
126
- },
127
- {
128
- "@type": "ListItem",
129
- "position": 15,
130
118
  "url": "https://thumbgate.ai/learn/pretix-stripe-connect-marketplaces",
131
119
  "name": "Building a Pretix + Stripe Connect Plugin for Live-Music Venues"
132
120
  },
@@ -157,42 +145,54 @@
157
145
  {
158
146
  "@type": "ListItem",
159
147
  "position": 10,
148
+ "url": "https://thumbgate.ai/guides/hermes-agent-guardrails",
149
+ "name": "Hermes Agent Guardrails for Self-Improving Agents"
150
+ },
151
+ {
152
+ "@type": "ListItem",
153
+ "position": 11,
154
+ "url": "https://thumbgate.ai/guides/agent-context-governance",
155
+ "name": "Agent Context Governance for Long-Running Agents"
156
+ },
157
+ {
158
+ "@type": "ListItem",
159
+ "position": 12,
160
160
  "url": "https://thumbgate.ai/guides/roo-code-alternative-cline",
161
161
  "name": "Roo Code Alternative: Migrating to Cline with Portable Lesson Memory"
162
162
  },
163
163
  {
164
164
  "@type": "ListItem",
165
- "position": 11,
165
+ "position": 13,
166
166
  "url": "https://thumbgate.ai/guides/browser-automation-safety",
167
167
  "name": "Browser Automation Safety for AI Agents"
168
168
  },
169
169
  {
170
170
  "@type": "ListItem",
171
- "position": 12,
171
+ "position": 14,
172
172
  "url": "https://thumbgate.ai/guides/native-messaging-host-security",
173
173
  "name": "Native Messaging Host Security"
174
174
  },
175
175
  {
176
176
  "@type": "ListItem",
177
- "position": 13,
177
+ "position": 15,
178
178
  "url": "https://thumbgate.ai/guides/ai-search-topical-presence",
179
179
  "name": "AI Search Topical Presence"
180
180
  },
181
181
  {
182
182
  "@type": "ListItem",
183
- "position": 14,
183
+ "position": 16,
184
184
  "url": "https://thumbgate.ai/guides/relational-knowledge-ai-recommendations",
185
185
  "name": "Relational Knowledge in AI Recommendations"
186
186
  },
187
187
  {
188
188
  "@type": "ListItem",
189
- "position": 15,
189
+ "position": 17,
190
190
  "url": "https://thumbgate.ai/guides/ai-deployment-readiness",
191
191
  "name": "AI Deployment Readiness Before Production Rollout"
192
192
  },
193
193
  {
194
194
  "@type": "ListItem",
195
- "position": 16,
195
+ "position": 18,
196
196
  "url": "https://thumbgate.ai/guides/database-agent-safety",
197
197
  "name": "Database Safety for AI Agents"
198
198
  }
@@ -290,7 +290,7 @@
290
290
  <body>
291
291
 
292
292
  <nav>
293
- <a href="/" class="brand"><img src="/assets/brand/thumbgate-mark-inline.svg" alt="ThumbGate" class="logo-mark" width="28" height="28"><span class="logo-text">ThumbGate</span></a>
293
+ <a href="/" class="brand"><img src="/assets/brand/thumbgate-mark-inline-v3.svg" alt="ThumbGate" class="logo-mark" width="28" height="28"><span class="logo-text">ThumbGate</span></a>
294
294
  <a href="/guide">Setup Guide</a>
295
295
  <a href="/learn">Learn</a>
296
296
  <a href="/dashboard">Dashboard</a>
@@ -421,22 +421,6 @@
421
421
  <span class="article-tag">Cost Control</span>
422
422
  </a>
423
423
 
424
- <a href="/learn/anthropomorphic-claim-gates" class="article-card">
425
- <h3>Anthropomorphic Claim Gates for AI Agents</h3>
426
- <p>Do not let an agent say a model understands, knows, decides, or behaves human-like unless it can show the measurement criteria and evidence behind that claim.</p>
427
- <span class="article-tag">Claim Verification</span>
428
- <span class="article-tag">Research</span>
429
- <span class="article-tag">Proof Gates</span>
430
- </a>
431
-
432
- <a href="/learn/agent-identity-connector-governance" class="article-card">
433
- <h3>Agent Identity and Connector Governance</h3>
434
- <p>Agents connected to Merge, Glean, MCP gateways, and enterprise apps are identities. Gate owner, credential, connector scope, DLP, audit, and purpose before they act.</p>
435
- <span class="article-tag">Agent Identity</span>
436
- <span class="article-tag">MCP Connectors</span>
437
- <span class="article-tag">Least Privilege</span>
438
- </a>
439
-
440
424
  <a href="/learn/from-prototype-to-production" class="article-card">
441
425
  <h3>From git init to v1.17.0 in 70 days: an honest ThumbGate build log</h3>
442
426
  <p>70 days, 112 commits, 17 minor releases, 6k npm downloads, $0 cold-traffic revenue. The unedited story of taking ThumbGate from a one-line repo init to live production — including the part that's still broken.</p>
@@ -473,6 +457,14 @@
473
457
  <span class="article-tag">Sprint</span>
474
458
  </a>
475
459
 
460
+ <a href="/guides/aws-blocks-agent-guardrails" class="article-card">
461
+ <h3>AWS Blocks Agent Guardrails</h3>
462
+ <p>Guard the local-to-cloud jump before AWS Blocks agents deploy, destroy resources, mutate data, expand IAM, or call Bedrock tools.</p>
463
+ <span class="article-tag">AWS Blocks</span>
464
+ <span class="article-tag">Cloud Safety</span>
465
+ <span class="article-tag">Pre-action Gates</span>
466
+ </a>
467
+
476
468
  <a href="/guides/ai-search-topical-presence" class="article-card">
477
469
  <h3>AI Search Topical Presence</h3>
478
470
  <p>Why AI assistants recommend the tools they repeatedly see tied to a buyer problem, and how ThumbGate builds that association with proof-backed pages.</p>
@@ -489,6 +481,14 @@
489
481
  <span class="article-tag">Governance</span>
490
482
  </a>
491
483
 
484
+ <a href="/guides/vllm-serving-guardrails" class="article-card">
485
+ <h3>vLLM Serving Guardrails</h3>
486
+ <p>Gate self-hosted inference changes before agents route production work through PagedAttention, batching, prefix-cache, or model-swap optimizations.</p>
487
+ <span class="article-tag">vLLM</span>
488
+ <span class="article-tag">LLM Serving</span>
489
+ <span class="article-tag">Runtime Safety</span>
490
+ </a>
491
+
492
492
  <a href="/guides/relational-knowledge-ai-recommendations" class="article-card">
493
493
  <h3>Relational Knowledge in AI Recommendations</h3>
494
494
  <p>How stored brand-to-problem associations shape AI answers, and why ThumbGate should own the pre-action-checks category in those retrieval paths.</p>
@@ -529,6 +529,30 @@
529
529
  <span class="article-tag">Enforcement</span>
530
530
  </a>
531
531
 
532
+ <a href="/guides/hermes-agent-guardrails" class="article-card">
533
+ <h3>Hermes Agent Guardrails for Self-Improving Agents</h3>
534
+ <p>Hermes-style agents bring persistent memory, generated skills, gateways, automations, and sandboxes. ThumbGate adds the pre-action firewall before those agents touch real systems.</p>
535
+ <span class="article-tag">Hermes Agent</span>
536
+ <span class="article-tag">Persistent Agents</span>
537
+ <span class="article-tag">Execution Firewall</span>
538
+ </a>
539
+
540
+ <a href="/guides/safe-self-evolution" class="article-card">
541
+ <h3>Safe Self-Evolution: Prompt Optimization without Regression</h3>
542
+ <p>Hermes-style autonomous agents learn by observing failures and rewriting skills. ThumbGate introduces Safe Self-Evolution: weakness mining, automated prompt optimization, verification suites, and atomic git rollbacks.</p>
543
+ <span class="article-tag">Self-Evolution</span>
544
+ <span class="article-tag">Harness Optimizer</span>
545
+ <span class="article-tag">Verification Gate</span>
546
+ </a>
547
+
548
+ <a href="/guides/agent-context-governance" class="article-card">
549
+ <h3>Agent Context Governance for Long-Running Agents</h3>
550
+ <p>AdaCoM, tokenmaxxing backlash, Managed Agents, lockdown modes, and model-provenance scares all point to one need: clean context and tool gates before agents act.</p>
551
+ <span class="article-tag">Context Governance</span>
552
+ <span class="article-tag">Tool Lockdown</span>
553
+ <span class="article-tag">Model Provenance</span>
554
+ </a>
555
+
532
556
  <a href="/guides/roo-code-alternative-cline" class="article-card">
533
557
  <h3>Roo Code Alternative: Migrate to Cline Without Losing Agent Memory</h3>
534
558
  <p>Use the Roo shutdown window to pitch portable lesson memory and local-first enforcement instead of making operators re-teach the same failures after they switch.</p>
@@ -211,7 +211,7 @@
211
211
 
212
212
  <nav>
213
213
  <div class="container">
214
- <a href="/dashboard" class="nav-logo"><img src="/assets/brand/thumbgate-mark-inline.svg" alt="ThumbGate" class="logo-mark" width="28" height="28"><span class="logo-text">ThumbGate</span></a>
214
+ <a href="/dashboard" class="nav-logo"><img src="/assets/brand/thumbgate-mark-inline-v3.svg" alt="ThumbGate" class="logo-mark" width="28" height="28"><span class="logo-text">ThumbGate</span></a>
215
215
  <div class="nav-links">
216
216
  <a href="/dashboard">Dashboard</a>
217
217
  <a href="/lessons" class="active">Lessons</a>
@@ -25,7 +25,7 @@
25
25
  "alternateName": "thumbgate",
26
26
  "applicationCategory": "DeveloperApplication",
27
27
  "operatingSystem": "Cross-platform, Node.js >=18.18.0",
28
- "softwareVersion": "1.27.7",
28
+ "softwareVersion": "1.27.8",
29
29
  "url": "https://thumbgate.ai/numbers",
30
30
  "dateModified": "2026-05-07",
31
31
  "creator": {
@@ -202,7 +202,7 @@
202
202
  <main class="container">
203
203
  <h1>The Numbers</h1>
204
204
  <p class="subtitle">Generated first-party operational snapshot from the ThumbGate runtime. This is not customer traction, install volume, revenue, or proof that a configured gate has fired.</p>
205
- <div class="freshness">Updated: 2026-05-07 · Version 1.27.7</div>
205
+ <div class="freshness">Updated: 2026-05-07 · Version 1.27.8</div>
206
206
  <div class="truth-note"><strong>Read this first:</strong> configured checks are inventory. Recorded blocks and warnings are usage evidence. This snapshot currently reports 0 recorded hard-block event(s) and 0 recorded warning event(s).</div>
207
207
 
208
208
  <h2>Gate enforcement</h2>
package/public/pro.html CHANGED
@@ -37,7 +37,7 @@ __GA_BOOTSTRAP__
37
37
  <script type="application/ld+json">
38
38
  {
39
39
  "@context": "https://schema.org",
40
- "@type": "FAQPage", "mainEntity": [{ "@type": "Question", "name": "How is Pro different from the free install?", "acceptedAnswer": { "@type": "Answer", "text": "Free keeps local recall, checks, and MCP. Pro adds the personal dashboard, DPO export, auto-connect, and founder support." } }, { "@type": "Question", "name": "Does Pro require a cloud account?", "acceptedAnswer": { "@type": "Answer", "text": "No. Pro stays local-first; Team is the hosted rollout lane for shared lessons, org visibility, and reviews." } }, { "@type": "Question", "name": "What happens after checkout?", "acceptedAnswer": { "@type": "Answer", "text": "You activate Pro, connect the local dashboard, and inspect blocked actions, lessons, and exports." } }, { "@type": "Question", "name": "When should I choose Team instead of Pro?", "acceptedAnswer": { "@type": "Answer", "text": "Choose Team when one correction needs to protect multiple developers or agents across shared repositories." } }]
40
+ "@type": "FAQPage", "mainEntity": [{ "@type": "Question", "name": "How is Pro different from the free install?", "acceptedAnswer": { "@type": "Answer", "text": "Free keeps local recall, checks, and MCP. Pro adds the personal dashboard, DPO export, auto-connect, and founder support." } }, { "@type": "Question", "name": "Does Pro require a cloud account?", "acceptedAnswer": { "@type": "Answer", "text": "No. Pro stays local-first; Enterprise is the hosted rollout lane for shared lessons, org visibility, and reviews." } }, { "@type": "Question", "name": "What happens after checkout?", "acceptedAnswer": { "@type": "Answer", "text": "You activate Pro, connect the local dashboard, and inspect blocked actions, lessons, and exports." } }, { "@type": "Question", "name": "When should I choose Enterprise instead of Pro?", "acceptedAnswer": { "@type": "Answer", "text": "Choose Enterprise when one correction needs to protect multiple developers or agents across shared repositories." } }]
41
41
  }
42
42
  </script>
43
43
 
@@ -712,7 +712,7 @@ __GA_BOOTSTRAP__
712
712
  <body>
713
713
  <nav>
714
714
  <div class="container">
715
- <a href="/" class="nav-logo"><img src="/assets/brand/thumbgate-mark-inline.svg" alt="ThumbGate" class="logo-mark" width="28" height="28"><span class="logo-text">ThumbGate Pro</span></a>
715
+ <a href="/" class="nav-logo"><img src="/assets/brand/thumbgate-mark-inline-v3.svg" alt="ThumbGate" class="logo-mark" width="28" height="28"><span class="logo-text">ThumbGate Pro</span></a>
716
716
  <div class="nav-links">
717
717
  <a href="#why-pay">Why Pro</a>
718
718
  <a href="#proof">Proof</a>
@@ -731,7 +731,7 @@ __GA_BOOTSTRAP__
731
731
  <h1>Buy the operator loop that proves your AI agent stopped repeating the mistake.</h1>
732
732
  <p style="font-size:13px;opacity:0.8;margin-bottom:0.5rem;">Updated: <time datetime="2026-04-20">2026-04-20</time> · by <a href="https://github.com/IgorGanapolsky" style="color:inherit;">Igor Ganapolsky</a></p>
733
733
  <p>ThumbGate Pro is for one operator who already hit a repeated AI-agent failure and now needs proof: what was blocked, why it was blocked, and what changed before the next risky run.</p>
734
- <p>Start Pro when you want the local dashboard, DPO export, and a single proof lane for the repeated mistake you need to stop. Team diagnostics and custom services are handled through intake, not this buyer path.</p>
734
+ <p>Start Pro when you want the local dashboard, DPO export, and a single proof lane for the repeated mistake you need to stop. Enterprise diagnostics and custom services are handled through intake, not this buyer path.</p>
735
735
  <div class="hero-proof">
736
736
  <div class="proof-pill">Personal local dashboard</div>
737
737
  <div class="proof-pill">DPO export from real corrections</div>
@@ -951,15 +951,15 @@ __GA_BOOTSTRAP__
951
951
  </div>
952
952
  <div class="faq-item">
953
953
  <button class="faq-q" type="button" onclick="toggleFaq(this)" onkeydown="handleFaqKeydown(event)" aria-expanded="false">Does Pro require a cloud account?</button>
954
- <div class="faq-a">No. Pro is still local-first for the individual operator lane. Team is the hosted rollout lane for shared lessons, org visibility, and hosted review views.</div>
954
+ <div class="faq-a">No. Pro is still local-first for the individual operator lane. Enterprise is the hosted rollout lane for shared lessons, org visibility, and hosted review views.</div>
955
955
  </div>
956
956
  <div class="faq-item">
957
957
  <button class="faq-q" type="button" onclick="toggleFaq(this)" onkeydown="handleFaqKeydown(event)" aria-expanded="false">What happens after checkout?</button>
958
958
  <div class="faq-a">You activate Pro, connect the personal local dashboard, and your running agents can appear automatically so you can inspect blocked actions, active lessons, and exportable DPO pairs without adding a separate cloud dashboard dependency.</div>
959
959
  </div>
960
960
  <div class="faq-item">
961
- <button class="faq-q" type="button" onclick="toggleFaq(this)" onkeydown="handleFaqKeydown(event)" aria-expanded="false">When should I choose Team instead of Pro?</button>
962
- <div class="faq-a">Choose Team when one thumbs-down should protect multiple people or agents across shared repositories, or when you need shared hosted lessons, org dashboard visibility, and a workflow hardening pilot with rollout review views.</div>
961
+ <button class="faq-q" type="button" onclick="toggleFaq(this)" onkeydown="handleFaqKeydown(event)" aria-expanded="false">When should I choose Enterprise instead of Pro?</button>
962
+ <div class="faq-a">Choose Enterprise when one thumbs-down should protect multiple people or agents across shared repositories, or when you need shared hosted lessons, org dashboard visibility, and a workflow hardening pilot with rollout review views.</div>
963
963
  </div>
964
964
  </div>
965
965
  </div>
@@ -987,7 +987,7 @@ __GA_BOOTSTRAP__
987
987
  <a href="__VERIFICATION_URL__" target="_blank" rel="noopener">Verification Evidence</a>
988
988
  <a href="https://github.com/IgorGanapolsky/ThumbGate" target="_blank" rel="noopener">GitHub</a>
989
989
  </div>
990
- <div class="footer-copy">ThumbGate Pro for individual operators. Team stays intake-first.</div>
990
+ <div class="footer-copy">ThumbGate Pro for individual operators. Enterprise stays intake-first.</div>
991
991
  </div>
992
992
  </footer>
993
993
 
@@ -0,0 +1,228 @@
1
+ #!/usr/bin/env node
2
+ 'use strict';
3
+
4
+ const fs = require('node:fs');
5
+ const path = require('node:path');
6
+
7
+ const AWS_BLOCKS_DEPENDENCY_PATTERN = /(^|\/)@aws-blocks\/(?:blocks|[^/\s"']+)/;
8
+
9
+ function toList(value) {
10
+ if (Array.isArray(value)) return value.map(String).map((entry) => entry.trim()).filter(Boolean);
11
+ if (typeof value === 'string') return value.split(',').map((entry) => entry.trim()).filter(Boolean);
12
+ return [];
13
+ }
14
+
15
+ function normalizeText(value) {
16
+ if (value == null) return '';
17
+ if (typeof value === 'string') return value;
18
+ try {
19
+ return JSON.stringify(value);
20
+ } catch {
21
+ return String(value);
22
+ }
23
+ }
24
+
25
+ function readPackageJson(projectDir) {
26
+ try {
27
+ return JSON.parse(fs.readFileSync(path.join(projectDir, 'package.json'), 'utf8'));
28
+ } catch {
29
+ return null;
30
+ }
31
+ }
32
+
33
+ function packageUsesAwsBlocks(pkg) {
34
+ if (!pkg || typeof pkg !== 'object') return false;
35
+ const dependencyText = JSON.stringify({
36
+ dependencies: pkg.dependencies || {},
37
+ devDependencies: pkg.devDependencies || {},
38
+ peerDependencies: pkg.peerDependencies || {},
39
+ optionalDependencies: pkg.optionalDependencies || {},
40
+ });
41
+ const scriptsText = JSON.stringify(pkg.scripts || {});
42
+ return AWS_BLOCKS_DEPENDENCY_PATTERN.test(dependencyText) || /aws-blocks|blocks-app|cdk|sandbox/i.test(scriptsText);
43
+ }
44
+
45
+ function detectAwsBlocksProject(projectDir = process.cwd()) {
46
+ const pkg = readPackageJson(projectDir);
47
+ if (packageUsesAwsBlocks(pkg)) return true;
48
+ return fs.existsSync(path.join(projectDir, 'aws-blocks', 'index.ts'))
49
+ || fs.existsSync(path.join(projectDir, 'aws-blocks', 'index.js'))
50
+ || fs.existsSync(path.join(projectDir, 'blocks.spec.json'));
51
+ }
52
+
53
+ function detectAction(input = {}) {
54
+ const command = normalizeText(input.command || input.args || input.shell || input.toolInput);
55
+ const toolName = normalizeText(input.toolName || input.tool || input.name);
56
+ const code = normalizeText(input.code || input.file || input.diff || input.body);
57
+ const combined = `${toolName}\n${command}\n${code}`;
58
+ const lower = combined.toLowerCase();
59
+
60
+ const signals = [];
61
+ const add = (id, label, severity = 'medium') => signals.push({ id, label, severity });
62
+
63
+ if (/\b(cdk\s+deploy|npm\s+run\s+deploy|pnpm\s+deploy|yarn\s+deploy|sst\s+deploy|blocks?\s+deploy)\b/i.test(combined)) {
64
+ add('aws-blocks-production-deploy', 'production deploy from an AWS Blocks workflow', 'high');
65
+ }
66
+
67
+ if (/\b(cdk\s+destroy|npm\s+run\s+destroy|pnpm\s+destroy|yarn\s+destroy|sandbox\b.*--destroy|--destroy\b|aws\s+cloudformation\s+delete-stack)\b/i.test(combined)) {
68
+ add('aws-blocks-destroy', 'destroy command can remove AWS resources created from local Blocks code', 'critical');
69
+ }
70
+
71
+ if (/\b(drop\s+(table|database|schema|index|column)|truncate\s+table|delete\s+from\s+[\w".-]+(?:\s*;|\s*$)|update\s+[\w".-]+\s+set\b(?![\s\S]{0,160}\bwhere\b))/i.test(combined)) {
72
+ add('destructive-sql-or-ddl', 'destructive or unscoped SQL mutation', 'critical');
73
+ }
74
+
75
+ if (/\b(aws\s+dynamodb\s+delete-table|aws\s+rds\s+delete-db-instance|aws\s+s3\s+rm\b[\s\S]*--recursive|aws\s+lambda\s+delete-function|aws\s+bedrock-agent\s+delete-|aws\s+bedrock-agent-runtime\b)/i.test(combined)) {
76
+ add('destructive-aws-cli', 'destructive AWS CLI or Bedrock agent action', 'critical');
77
+ }
78
+
79
+ if (/\b(gcloud|aws)\b[\s\S]{0,220}\b(add-iam-policy-binding|put-role-policy|attach-role-policy|create-policy-version)\b/i.test(combined)
80
+ || /\b(AdministratorAccess|roles\/owner|iam:PassRole|serviceAccountTokenCreator)\b/i.test(combined)) {
81
+ add('iam-escalation', 'agent session attempts to grant broad IAM authority', 'critical');
82
+ }
83
+
84
+ if (/\b(new\s+Agent\s*\(|@aws-blocks\/(?:agent|blocks)|\bAgent\b[\s\S]{0,120}\btools?\b)/.test(combined)) {
85
+ add('blocks-agent-tool-call', 'AWS Blocks Agent or Bedrock-style tool action needs a tool boundary', 'medium');
86
+ }
87
+
88
+ if (/\b(npm\s+run\s+dev|npm\s+start|pnpm\s+dev|yarn\s+dev|create-blocks-app)\b/i.test(combined)) {
89
+ add('local-dev', 'local AWS Blocks development loop', 'low');
90
+ }
91
+
92
+ return {
93
+ command,
94
+ toolName,
95
+ code,
96
+ signals,
97
+ highRisk: signals.some((signal) => ['high', 'critical'].includes(signal.severity)),
98
+ localOnly: signals.some((signal) => signal.id === 'local-dev') && signals.every((signal) => signal.severity === 'low'),
99
+ lower,
100
+ };
101
+ }
102
+
103
+ function evaluateAwsBlocksAction(input = {}) {
104
+ const projectDir = input.projectDir || input.cwd || process.cwd();
105
+ const projectUsesAwsBlocks = Boolean(
106
+ input.projectUsesAwsBlocks
107
+ || input.awsBlocks
108
+ || input.blocksProject
109
+ || detectAwsBlocksProject(projectDir)
110
+ );
111
+ const evidence = new Set(toList(input.evidence || input.proof || input.receipts));
112
+ const action = detectAction(input);
113
+ const requiredEvidence = [];
114
+
115
+ const requireEvidence = (id, label) => {
116
+ if (!evidence.has(id)) requiredEvidence.push({ id, label });
117
+ };
118
+
119
+ if (projectUsesAwsBlocks && action.signals.some((signal) => signal.id === 'aws-blocks-production-deploy')) {
120
+ requireEvidence('local-tests-pass', 'local AWS Blocks tests pass against local implementations');
121
+ requireEvidence('cdk-diff-reviewed', 'CDK diff or synthesized CloudFormation change set reviewed');
122
+ requireEvidence('cost-blast-radius-reviewed', 'AWS cost and resource blast radius reviewed');
123
+ }
124
+
125
+ if (action.signals.some((signal) => signal.id === 'aws-blocks-destroy')) {
126
+ requireEvidence('resource-inventory-exported', 'resource inventory exported before destroy');
127
+ requireEvidence('human-destroy-approval', 'named human approval for destroy');
128
+ }
129
+
130
+ if (action.signals.some((signal) => signal.id === 'destructive-sql-or-ddl')) {
131
+ requireEvidence('backup-or-rollback-ready', 'backup, rollback, or restore point exists');
132
+ requireEvidence('bounded-row-count-reviewed', 'row/table impact was previewed before mutation');
133
+ }
134
+
135
+ if (action.signals.some((signal) => signal.id === 'destructive-aws-cli')) {
136
+ requireEvidence('aws-account-and-region-confirmed', 'target AWS account and region confirmed');
137
+ requireEvidence('rollback-plan-attached', 'rollback or recovery plan attached');
138
+ }
139
+
140
+ if (action.signals.some((signal) => signal.id === 'iam-escalation')) {
141
+ requireEvidence('least-privilege-review', 'least-privilege review completed');
142
+ requireEvidence('security-owner-approval', 'security owner approval captured');
143
+ }
144
+
145
+ if (action.signals.some((signal) => signal.id === 'blocks-agent-tool-call')) {
146
+ requireEvidence('agent-tool-allowlist', 'agent tool allowlist and data boundary declared');
147
+ }
148
+
149
+ const shouldBlock = projectUsesAwsBlocks && requiredEvidence.length > 0;
150
+ const status = shouldBlock ? 'blocked' : (action.highRisk ? 'needs-review' : 'allowed');
151
+
152
+ return {
153
+ name: 'thumbgate-aws-blocks-guardrails',
154
+ status,
155
+ projectUsesAwsBlocks,
156
+ signals: action.signals,
157
+ requiredEvidence,
158
+ enforcementBoundary: 'local AWS Blocks confidence must not automatically become production AWS authority',
159
+ gates: [
160
+ 'allow local AWS Blocks dev loops without AWS credentials',
161
+ 'require local test proof plus CDK diff before production deploy',
162
+ 'block destroy and destructive data mutations until backup, blast-radius, and human approval evidence exists',
163
+ 'block IAM escalation and Bedrock/Agent tool expansion until an owner approves the tool boundary',
164
+ 'write a ThumbGate receipt for every allowed high-risk cloud action',
165
+ ],
166
+ nextActions: shouldBlock
167
+ ? requiredEvidence.map((item) => `Provide ${item.id}: ${item.label}`)
168
+ : ['Record an allow receipt when this action touches real AWS resources'],
169
+ };
170
+ }
171
+
172
+ function buildAwsBlocksHardeningOffer(input = {}) {
173
+ const workflow = String(input.workflow || input.name || 'AWS Blocks backend').trim();
174
+ const buyer = String(input.buyer || input.owner || 'platform owner').trim();
175
+ return {
176
+ name: 'thumbgate-aws-blocks-hardening-offer',
177
+ status: 'ready-for-positioning',
178
+ buyer,
179
+ workflow,
180
+ headline: 'AWS Blocks helps agents build the backend. ThumbGate stops them before unsafe cloud actions run.',
181
+ offer: 'AWS Blocks Agent Safety Review',
182
+ diagnosticPrice: '$499',
183
+ proofPlan: [
184
+ 'map one AWS Blocks local-to-cloud workflow',
185
+ 'install ThumbGate against the agent running that workflow',
186
+ 'add gates for deploy, destroy, data mutation, IAM, Bedrock Agent, and cost-blast-radius actions',
187
+ 'produce a receipt showing the first blocked repeat and the evidence required to allow it',
188
+ ],
189
+ cta: 'Send one AWS Blocks workflow that is about to deploy, mutate data, or call Bedrock tools.',
190
+ };
191
+ }
192
+
193
+ function parseArgs(argv = process.argv.slice(2)) {
194
+ const args = {};
195
+ for (const arg of argv) {
196
+ if (arg === '--json') args.json = true;
197
+ else if (arg === '--aws-blocks' || arg === '--project-uses-aws-blocks') args.projectUsesAwsBlocks = true;
198
+ else if (arg.startsWith('--command=')) args.command = arg.slice('--command='.length);
199
+ else if (arg.startsWith('--tool=')) args.toolName = arg.slice('--tool='.length);
200
+ else if (arg.startsWith('--code=')) args.code = arg.slice('--code='.length);
201
+ else if (arg.startsWith('--cwd=')) args.projectDir = arg.slice('--cwd='.length);
202
+ else if (arg.startsWith('--evidence=')) args.evidence = arg.slice('--evidence='.length);
203
+ else if (arg.startsWith('--workflow=')) args.workflow = arg.slice('--workflow='.length);
204
+ else if (arg.startsWith('--buyer=')) args.buyer = arg.slice('--buyer='.length);
205
+ else if (arg === 'offer') args.commandName = 'offer';
206
+ }
207
+ return args;
208
+ }
209
+
210
+ function runCli(args = parseArgs()) {
211
+ const report = args.commandName === 'offer'
212
+ ? buildAwsBlocksHardeningOffer(args)
213
+ : evaluateAwsBlocksAction(args);
214
+ if (args.json) console.log(JSON.stringify(report, null, 2));
215
+ else {
216
+ console.log(`${report.name}: ${report.status}`);
217
+ for (const action of report.nextActions || report.proofPlan || []) console.log(`- ${action}`);
218
+ }
219
+ }
220
+
221
+ if (require.main === module) runCli();
222
+
223
+ module.exports = {
224
+ detectAwsBlocksProject,
225
+ detectAction,
226
+ evaluateAwsBlocksAction,
227
+ buildAwsBlocksHardeningOffer,
228
+ };
@@ -123,16 +123,6 @@ const CLI_COMMANDS = [
123
123
  { name: 'remote', type: 'boolean', description: 'Fetch from hosted Railway instance' },
124
124
  ],
125
125
  },
126
- {
127
- name: 'community',
128
- aliases: ['registry'],
129
- description: 'Query or share verified prevention rules with the community knowledge registry',
130
- group: 'discovery',
131
- flags: [
132
- { name: 'json', type: 'boolean', description: 'Output as JSON' },
133
- { name: 'remote', type: 'boolean', description: 'Fetch from community remote API' },
134
- ],
135
- },
136
126
  {
137
127
  name: 'gate-stats',
138
128
  description: 'Check engine statistics — active checks, blocks, warns, time saved',
@@ -515,6 +505,12 @@ const CLI_COMMANDS = [
515
505
  group: 'gates',
516
506
  flags: [],
517
507
  },
508
+ {
509
+ name: 'hermes-gate',
510
+ description: 'Hermes Agent pre_tool_call hook: gate runtime tool calls (incl. skill_manage) before they run',
511
+ group: 'gates',
512
+ flags: [],
513
+ },
518
514
  {
519
515
  name: 'force-gate',
520
516
  description: 'Immediately create a blocking gate from a pattern string',
@@ -660,6 +656,22 @@ const CLI_COMMANDS = [
660
656
  { name: 'json', type: 'boolean', description: 'Output results as JSON' },
661
657
  ],
662
658
  },
659
+ {
660
+ name: 'check-update',
661
+ aliases: ['upgrade-check'],
662
+ description: 'Check for newer versions of ThumbGate from npm or GitHub',
663
+ group: 'ops',
664
+ flags: [
665
+ { name: 'json', type: 'boolean', description: 'Output results as JSON' },
666
+ ],
667
+ },
668
+ {
669
+ name: 'self-update',
670
+ aliases: ['upgrade-cli'],
671
+ description: 'Automatically install the latest version of ThumbGate globally',
672
+ group: 'ops',
673
+ flags: [],
674
+ },
663
675
  ];
664
676
 
665
677
  /**
@@ -317,7 +317,8 @@ async function answerDataQuestion(question, opts = {}) {
317
317
  if (isPerplexity) return await callPerplexityEndpoint({ apiKey, prompt, fetchImpl, sources });
318
318
  return await callGeminiEndpoint({ apiKey, model, prompt, fetchImpl, sources });
319
319
  } catch (err) {
320
- return { ok: false, error: 'network', message: err?.message || String(err), sources };
320
+ const safeMessage = (err && err.message) ? String(err.message).split('\n')[0].slice(0, 100) : 'An unexpected error occurred.';
321
+ return { ok: false, error: 'network', message: safeMessage, sources };
321
322
  }
322
323
  }
323
324
 
@@ -708,7 +708,6 @@ function buildDocumentSummary(document) {
708
708
  sourcePath: document.sourcePath || null,
709
709
  sourceName: document.sourceName || null,
710
710
  sourceFormat: document.sourceFormat,
711
- sourceUrl: document.sourceUrl || null,
712
711
  importedAt: document.importedAt,
713
712
  tags: normalizeTags(document.tags),
714
713
  excerpt: document.excerpt,
@@ -769,11 +768,7 @@ function persistDocument(document, options = {}) {
769
768
  const summaries = listImportedDocuments({
770
769
  ...options,
771
770
  limit: MAX_SEARCH_SCAN,
772
- }).documents.filter((entry) => {
773
- if (entry.documentId === document.documentId) return false;
774
- if (document.sourceUrl && entry.sourceUrl === document.sourceUrl) return false;
775
- return true;
776
- });
771
+ }).documents.filter((entry) => entry.documentId !== document.documentId);
777
772
  const nextSummaries = [
778
773
  buildDocumentSummary(document),
779
774
  ...summaries,
@@ -887,48 +882,6 @@ function importDocument(options = {}) {
887
882
  sourceFormat,
888
883
  });
889
884
  const fingerprint = sha256(`${title}\n${normalizedContent}`);
890
-
891
- // -- deduplication and RAG drift tracking ----------------------------------
892
- const paths = getDocumentStorePaths(options);
893
- let duplicate = null;
894
- if (fs.existsSync(paths.catalogPath)) {
895
- try {
896
- const catalog = readJsonl(paths.catalogPath);
897
- const urlMatch = options.sourceUrl ? String(options.sourceUrl).trim() : null;
898
- const matchedSummary = catalog.find((summary) =>
899
- (urlMatch && summary.sourceUrl === urlMatch) ||
900
- (summary.fingerprint === fingerprint)
901
- );
902
- if (matchedSummary) {
903
- const fullDoc = readImportedDocument(matchedSummary.documentId, options);
904
- if (fullDoc) {
905
- if (fullDoc.fingerprint === fingerprint) {
906
- // Case A: Content is identical
907
- const dedupReason = urlMatch && fullDoc.sourceUrl === urlMatch
908
- ? 'url-and-content-unchanged'
909
- : 'content-identical';
910
- return {
911
- ...fullDoc,
912
- duplicate: true,
913
- updated: false,
914
- dedupReason,
915
- };
916
- } else {
917
- // Case B: URL matches but content changed (RAG Drift!)
918
- duplicate = {
919
- previousDocumentId: fullDoc.documentId,
920
- previousFingerprint: fullDoc.fingerprint,
921
- updated: true,
922
- dedupReason: 'url-content-updated',
923
- };
924
- }
925
- }
926
- }
927
- } catch (err) {
928
- // best-effort
929
- }
930
- }
931
-
932
885
  const importedAt = nowIso();
933
886
  const sourceName = sourcePath ? path.basename(sourcePath) : null;
934
887
  const documentId = `doc_${slugify(title || sourceName || 'document').slice(0, 24) || 'document'}_${fingerprint.slice(0, 12)}`;
@@ -948,7 +901,6 @@ function importDocument(options = {}) {
948
901
  contentBytes: Buffer.byteLength(normalizedContent, 'utf8'),
949
902
  lineCount: normalizedContent.split('\n').filter(Boolean).length,
950
903
  headings: extractHeadings(normalizedContent),
951
- ...(duplicate || {}),
952
904
  };
953
905
  document.proposals = options.proposeGates === false
954
906
  ? []
@@ -7,11 +7,11 @@
7
7
  * the full durable-execution runtime. Gives each external call (HTTP,
8
8
  * LanceDB, LLM) a uniform retry + idempotency wrapper:
9
9
  *
10
- * const result = await runStep('zernio.publishPost', {
10
+ * const result = await runStep('directSocial.publishPost', {
11
11
  * retries: 3,
12
12
  * idempotencyKey: idempotencyKey(content, platforms),
13
13
  * }, async ({ attempt }) => {
14
- * return zernioFetch('POST', '/posts', body, { idempotencyKey: ... });
14
+ * return directSocialFetch('POST', '/posts', body, { idempotencyKey: ... });
15
15
  * });
16
16
  *
17
17
  * Why a custom helper instead of Vercel Workflows / Temporal / Inngest?
@@ -98,7 +98,7 @@ function idempotencyKey(...parts) {
98
98
  * `fn` resolves to, or throws the last error after exhausting retries /
99
99
  * hitting a non-retryable verdict.
100
100
  *
101
- * @param {string} name Step name, used in logs. e.g. 'zernio.publishPost'.
101
+ * @param {string} name Step name, used in logs. e.g. 'directSocial.publishPost'.
102
102
  * @param {object|function} options { retries, backoffMs, classify, onRetry, onFail, logger }
103
103
  * (may be passed directly as the callback shorthand)
104
104
  * @param {function({attempt:number}):Promise} fn The actual work.