thumbgate 1.27.17 → 1.27.18
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/marketplace.json +85 -0
- package/.claude-plugin/plugin.json +3 -4
- package/.well-known/llms.txt +12 -33
- package/.well-known/mcp/server-card.json +8 -8
- package/README.md +30 -221
- package/adapters/chatgpt/openapi.yaml +1695 -0
- package/adapters/claude/.mcp.json +2 -2
- package/adapters/gemini/function-declarations.json +0 -1
- package/adapters/mcp/server-stdio.js +11 -263
- package/adapters/opencode/opencode.json +1 -1
- package/bench/thumbgate-bench.json +2 -2
- package/bin/cli.js +122 -1421
- package/bin/postinstall.js +27 -11
- package/config/gate-templates.json +0 -216
- package/config/gates/claim-verification.json +0 -12
- package/config/gates/default.json +2 -31
- package/config/github-about.json +2 -2
- package/config/mcp-allowlists.json +13 -23
- package/config/merge-quality-checks.json +1 -0
- package/config/model-candidates.json +6 -121
- package/openapi/openapi.yaml +0 -12
- package/package.json +99 -229
- package/public/blog.html +4 -4
- package/public/codex-plugin.html +20 -72
- package/public/compare.html +8 -31
- package/public/dashboard.html +166 -930
- package/public/federal.html +2 -2
- package/public/guide.html +9 -33
- package/public/index.html +116 -495
- package/public/learn.html +18 -191
- package/public/lessons.html +10 -168
- package/public/numbers.html +7 -7
- package/public/pro.html +11 -34
- package/scripts/agent-memory-lifecycle.js +0 -211
- package/scripts/agent-readiness.js +3 -167
- package/scripts/agent-reward-model.js +1 -53
- package/scripts/auto-promote-gates.js +10 -82
- package/scripts/auto-wire-hooks.js +0 -14
- package/scripts/billing.js +1 -93
- package/scripts/build-metadata.js +10 -50
- package/scripts/cli-feedback.js +6 -18
- package/scripts/cli-schema.js +0 -90
- package/scripts/cli-telemetry.js +1 -6
- package/scripts/commercial-offer.js +2 -82
- package/scripts/context-manager.js +6 -74
- package/scripts/dashboard.js +2 -68
- package/scripts/durability/step.js +3 -3
- package/scripts/export-databricks-bundle.js +1 -5
- package/scripts/export-dpo-pairs.js +2 -7
- package/scripts/feedback-loop.js +1 -145
- package/scripts/feedback-quality.js +0 -87
- package/scripts/filesystem-search.js +10 -35
- package/scripts/gate-stats.js +0 -89
- package/scripts/gates-engine.js +85 -1105
- package/scripts/gemini-embedding-policy.js +1 -2
- package/scripts/hook-runtime.js +14 -20
- package/scripts/hook-thumbgate-cache-updater.js +2 -18
- package/scripts/hybrid-feedback-context.js +7 -142
- package/scripts/lesson-inference.js +3 -8
- package/scripts/lesson-search.js +1 -17
- package/scripts/license.js +1 -0
- package/scripts/llm-client.js +9 -390
- package/scripts/local-model-profile.js +8 -15
- package/scripts/memory-scope-readiness.js +0 -159
- package/scripts/meta-agent-loop.js +0 -36
- package/scripts/operational-integrity.js +5 -39
- package/scripts/oss-pr-opportunity-scout.js +5 -35
- package/scripts/plausible-server-events.js +6 -9
- package/scripts/pro-local-dashboard.js +4 -4
- package/scripts/proxy-pointer-rag-guardrails.js +1 -42
- package/scripts/rate-limiter.js +13 -64
- package/scripts/secret-scanner.js +5 -44
- package/scripts/security-scanner.js +10 -260
- package/scripts/self-distill-agent.js +1 -3
- package/scripts/seo-gsd.js +2 -916
- package/scripts/statusline-cache-path.js +2 -17
- package/scripts/statusline-local-stats.js +1 -9
- package/scripts/statusline-meta.js +2 -28
- package/scripts/statusline.sh +4 -20
- package/scripts/telemetry-analytics.js +0 -357
- package/scripts/thompson-sampling.js +10 -31
- package/scripts/thumbgate-bench.js +1 -16
- package/scripts/thumbgate-search.js +19 -85
- package/scripts/tool-registry.js +1 -169
- package/scripts/vector-store.js +0 -45
- package/scripts/workflow-sentinel.js +53 -286
- package/scripts/workspace-evolver.js +2 -62
- package/src/api/server.js +290 -2578
- package/.claude/commands/dashboard.md +0 -15
- package/.claude/commands/thumbgate-blocked.md +0 -27
- package/.claude/commands/thumbgate-dashboard.md +0 -15
- package/.claude/commands/thumbgate-doctor.md +0 -30
- package/.claude/commands/thumbgate-guard.md +0 -36
- package/.claude/commands/thumbgate-protect.md +0 -30
- package/.claude/commands/thumbgate-rules.md +0 -30
- package/.well-known/agentic-verify.txt +0 -1
- package/adapters/gcp/dfcx-webhook-gate.js +0 -295
- package/adapters/letta/README.md +0 -41
- package/adapters/letta/thumbgate-letta-adapter.js +0 -133
- package/adapters/policy-engine/ethicore-guardian-client.js +0 -68
- package/adapters/policy-engine/thumbgate-policy-engine-adapter.js +0 -260
- package/bench/observability-eval-suite.json +0 -26
- package/bin/dashboard-cli.js +0 -7
- package/commands/dashboard.md +0 -15
- package/commands/thumbgate-dashboard.md +0 -15
- package/config/builtin-lessons.json +0 -23
- package/config/gate-classifier-routing.json +0 -98
- package/config/post-deploy-marketing-pages.json +0 -61
- package/public/about.html +0 -162
- package/public/agent-manager.html +0 -179
- package/public/agents-cost-savings.html +0 -153
- package/public/ai-malpractice-prevention.html +0 -818
- package/public/assets/brand/github-social-preview.png +0 -0
- package/public/assets/brand/thumbgate-icon-512.png +0 -0
- package/public/assets/brand/thumbgate-icon-pro-512.png +0 -0
- package/public/assets/brand/thumbgate-icon-team-512.png +0 -0
- package/public/assets/brand/thumbgate-logo-1200x360.png +0 -0
- package/public/assets/brand/thumbgate-logo-transparent.svg +0 -22
- package/public/assets/brand/thumbgate-mark-inline-v3.svg +0 -19
- package/public/assets/brand/thumbgate-mark-pro.svg +0 -23
- package/public/assets/brand/thumbgate-mark-team.svg +0 -26
- package/public/assets/brand/thumbgate-mark.svg +0 -21
- package/public/assets/brand/thumbgate-wordmark.svg +0 -20
- package/public/assets/claude-thumbgate-statusbar.svg +0 -8
- package/public/assets/codex-thumbgate-statusbar-test.svg +0 -9
- package/public/assets/legal-intake-control-flow.svg +0 -66
- package/public/brand/thumbgate-mark.svg +0 -19
- package/public/brand/thumbgate-og.svg +0 -16
- package/public/chatgpt-app.html +0 -330
- package/public/codex-enterprise.html +0 -123
- package/public/js/buyer-intent.js +0 -672
- package/public/pricing.html +0 -399
- package/scripts/action-receipts.js +0 -324
- package/scripts/activation-quickstart.js +0 -187
- package/scripts/agent-operations-planner.js +0 -621
- package/scripts/ai-component-inventory.js +0 -367
- package/scripts/async-eval-observability.js +0 -236
- package/scripts/audit.js +0 -65
- package/scripts/aws-blocks-guardrails.js +0 -228
- package/scripts/classifier-routing.js +0 -130
- package/scripts/dashboard-chat.js +0 -332
- package/scripts/feedback-aggregate.js +0 -281
- package/scripts/feedback-sanitizer.js +0 -105
- package/scripts/hob-pack.js +0 -591
- package/scripts/hook-stop-anti-claim.js +0 -301
- package/scripts/install-shim.js +0 -87
- package/scripts/mcp-oauth.js +0 -293
- package/scripts/noop-detect.js +0 -285
- package/scripts/omlx-smoke.js +0 -192
- package/scripts/parallel-workflow-orchestrator.js +0 -293
- package/scripts/plan-gate.js +0 -243
- package/scripts/plausible-domain-config.js +0 -99
- package/scripts/qa-scenario-planner.js +0 -136
- package/scripts/repeat-metric.js +0 -137
- package/scripts/secret-fixture-tokens.js +0 -61
- package/scripts/secret-redaction.js +0 -166
- package/scripts/self-harness-optimizer.js +0 -141
- package/scripts/self-healing-check.js +0 -193
- package/scripts/silent-failure-cluster.js +0 -531
- package/scripts/statusline-cache-read.js +0 -57
- package/scripts/sync-telemetry-from-prod.js +0 -374
- package/scripts/tool-contract-validator.js +0 -76
- package/scripts/trajectory-scorer.js +0 -63
- package/scripts/verify-marketing-pages-deployed.js +0 -195
- package/scripts/visitor-journey.js +0 -172
package/public/learn.html
CHANGED
|
@@ -4,14 +4,14 @@
|
|
|
4
4
|
<meta charset="UTF-8">
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
6
|
<title>Learn — AI Agent Safety, Pre-Action Checks, and Vibe Coding Guardrails</title>
|
|
7
|
-
<script defer data-domain="thumbgate.
|
|
7
|
+
<script defer data-domain="thumbgate-production.up.railway.app" src="https://plausible.io/js/script.js"></script>
|
|
8
8
|
<meta name="description" content="Practical guides for stopping AI coding agent mistakes. Learn about pre-action checks, MCP guardrails, feedback-driven enforcement, and vibe coding safety for Claude Code, Cursor, Codex, and more.">
|
|
9
9
|
<meta name="keywords" content="AI agent safety, pre-action checks, vibe coding guardrails, Claude Code mistakes, Cursor agent memory, MCP server hooks, AI coding agent feedback, ThumbGate guides">
|
|
10
10
|
<meta property="og:title" content="Learn — AI Agent Safety Guides by ThumbGate">
|
|
11
11
|
<meta property="og:description" content="Practical guides for stopping AI coding agent mistakes with pre-action checks and feedback-driven enforcement.">
|
|
12
12
|
<meta property="og:type" content="website">
|
|
13
|
-
<meta property="og:url" content="https://thumbgate.
|
|
14
|
-
<link rel="canonical" href="https://thumbgate.
|
|
13
|
+
<meta property="og:url" content="https://thumbgate-production.up.railway.app/learn">
|
|
14
|
+
<link rel="canonical" href="https://thumbgate-production.up.railway.app/learn">
|
|
15
15
|
<link rel="icon" type="image/png" href="/thumbgate-icon.png">
|
|
16
16
|
<link rel="apple-touch-icon" href="/assets/brand/thumbgate-mark.svg">
|
|
17
17
|
|
|
@@ -21,8 +21,8 @@
|
|
|
21
21
|
"@type": "CollectionPage",
|
|
22
22
|
"name": "ThumbGate Learning Hub",
|
|
23
23
|
"description": "Practical guides for AI coding agent safety, pre-action checks, and vibe coding guardrails.",
|
|
24
|
-
"url": "https://thumbgate.
|
|
25
|
-
"dateModified": "2026-
|
|
24
|
+
"url": "https://thumbgate-production.up.railway.app/learn",
|
|
25
|
+
"dateModified": "2026-04-20",
|
|
26
26
|
"author": {
|
|
27
27
|
"@type": "Person",
|
|
28
28
|
"name": "Igor Ganapolsky",
|
|
@@ -35,7 +35,7 @@
|
|
|
35
35
|
"publisher": {
|
|
36
36
|
"@type": "Organization",
|
|
37
37
|
"name": "ThumbGate",
|
|
38
|
-
"url": "https://thumbgate.
|
|
38
|
+
"url": "https://thumbgate-production.up.railway.app"
|
|
39
39
|
},
|
|
40
40
|
"mainEntity": {
|
|
41
41
|
"@type": "ItemList",
|
|
@@ -43,81 +43,39 @@
|
|
|
43
43
|
{
|
|
44
44
|
"@type": "ListItem",
|
|
45
45
|
"position": 1,
|
|
46
|
-
"url": "https://thumbgate.
|
|
46
|
+
"url": "https://thumbgate-production.up.railway.app/learn/stop-ai-agent-force-push",
|
|
47
47
|
"name": "How to Stop AI Agents From Force-Pushing to Main"
|
|
48
48
|
},
|
|
49
49
|
{
|
|
50
50
|
"@type": "ListItem",
|
|
51
51
|
"position": 2,
|
|
52
|
-
"url": "https://thumbgate.
|
|
52
|
+
"url": "https://thumbgate-production.up.railway.app/learn/vibe-coding-safety-net",
|
|
53
53
|
"name": "The Vibe Coding Safety Net You Are Missing"
|
|
54
54
|
},
|
|
55
55
|
{
|
|
56
56
|
"@type": "ListItem",
|
|
57
57
|
"position": 3,
|
|
58
|
-
"url": "https://thumbgate.
|
|
58
|
+
"url": "https://thumbgate-production.up.railway.app/learn/mcp-pre-action-checks-explained",
|
|
59
59
|
"name": "MCP Pre-Action Checks Explained"
|
|
60
60
|
},
|
|
61
61
|
{
|
|
62
62
|
"@type": "ListItem",
|
|
63
63
|
"position": 4,
|
|
64
|
-
"url": "https://thumbgate.
|
|
64
|
+
"url": "https://thumbgate-production.up.railway.app/learn/agent-harness-pattern",
|
|
65
65
|
"name": "The Agent Harness Pattern: Why Your AI Needs a Seatbelt"
|
|
66
66
|
},
|
|
67
67
|
{
|
|
68
68
|
"@type": "ListItem",
|
|
69
69
|
"position": 5,
|
|
70
|
-
"url": "https://thumbgate.
|
|
71
|
-
"name": "Background Agents Need a Control Layer Outside the Model"
|
|
72
|
-
},
|
|
73
|
-
{
|
|
74
|
-
"@type": "ListItem",
|
|
75
|
-
"position": 6,
|
|
76
|
-
"url": "https://thumbgate.ai/learn/ai-agent-persistent-memory",
|
|
70
|
+
"url": "https://thumbgate-production.up.railway.app/learn/ai-agent-persistent-memory",
|
|
77
71
|
"name": "How to Give Your AI Coding Agent Persistent Memory Across Sessions"
|
|
78
72
|
},
|
|
79
73
|
{
|
|
80
74
|
"@type": "ListItem",
|
|
81
|
-
"position":
|
|
82
|
-
"url": "https://thumbgate.ai/learn/agentic-enterprise-context-brain",
|
|
83
|
-
"name": "Agentic Enterprise Context Brain: Memory Plus Enforcement"
|
|
84
|
-
},
|
|
85
|
-
{
|
|
86
|
-
"@type": "ListItem",
|
|
87
|
-
"position": 8,
|
|
88
|
-
"url": "https://thumbgate.ai/learn/deterministic-agent-workflows",
|
|
89
|
-
"name": "Deterministic Agent Workflows Need Runtime Gates"
|
|
90
|
-
},
|
|
91
|
-
{
|
|
92
|
-
"@type": "ListItem",
|
|
93
|
-
"position": 9,
|
|
94
|
-
"url": "https://thumbgate.ai/learn/codex-role-plugins-need-governance",
|
|
95
|
-
"name": "Codex Role Plugins Need Pre-Action Governance"
|
|
96
|
-
},
|
|
97
|
-
{
|
|
98
|
-
"@type": "ListItem",
|
|
99
|
-
"position": 10,
|
|
100
|
-
"url": "https://thumbgate.ai/learn/agentic-os-team-governance",
|
|
101
|
-
"name": "Agentic OS Team Governance: Three Tiers Plus Gates"
|
|
102
|
-
},
|
|
103
|
-
{
|
|
104
|
-
"@type": "ListItem",
|
|
105
|
-
"position": 11,
|
|
106
|
-
"url": "https://thumbgate.ai/learn/cost-aware-agent-gate-routing",
|
|
107
|
-
"name": "Cost-Aware Agent Gate Routing"
|
|
108
|
-
},
|
|
109
|
-
{
|
|
110
|
-
"@type": "ListItem",
|
|
111
|
-
"position": 12,
|
|
75
|
+
"position": 6,
|
|
112
76
|
"url": "https://thumbgate.ai/learn/from-prototype-to-production",
|
|
113
77
|
"name": "From git init to v1.17.0 in 70 days: an honest ThumbGate build log"
|
|
114
78
|
},
|
|
115
|
-
{
|
|
116
|
-
"@type": "ListItem",
|
|
117
|
-
"position": 13,
|
|
118
|
-
"url": "https://thumbgate.ai/learn/pretix-stripe-connect-marketplaces",
|
|
119
|
-
"name": "Building a Pretix + Stripe Connect Plugin for Live-Music Venues"
|
|
120
|
-
},
|
|
121
79
|
{
|
|
122
80
|
"@type": "ListItem",
|
|
123
81
|
"position": 7,
|
|
@@ -145,56 +103,38 @@
|
|
|
145
103
|
{
|
|
146
104
|
"@type": "ListItem",
|
|
147
105
|
"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
106
|
"url": "https://thumbgate.ai/guides/roo-code-alternative-cline",
|
|
161
107
|
"name": "Roo Code Alternative: Migrating to Cline with Portable Lesson Memory"
|
|
162
108
|
},
|
|
163
109
|
{
|
|
164
110
|
"@type": "ListItem",
|
|
165
|
-
"position":
|
|
111
|
+
"position": 11,
|
|
166
112
|
"url": "https://thumbgate.ai/guides/browser-automation-safety",
|
|
167
113
|
"name": "Browser Automation Safety for AI Agents"
|
|
168
114
|
},
|
|
169
115
|
{
|
|
170
116
|
"@type": "ListItem",
|
|
171
|
-
"position":
|
|
117
|
+
"position": 12,
|
|
172
118
|
"url": "https://thumbgate.ai/guides/native-messaging-host-security",
|
|
173
119
|
"name": "Native Messaging Host Security"
|
|
174
120
|
},
|
|
175
121
|
{
|
|
176
122
|
"@type": "ListItem",
|
|
177
|
-
"position":
|
|
123
|
+
"position": 13,
|
|
178
124
|
"url": "https://thumbgate.ai/guides/ai-search-topical-presence",
|
|
179
125
|
"name": "AI Search Topical Presence"
|
|
180
126
|
},
|
|
181
127
|
{
|
|
182
128
|
"@type": "ListItem",
|
|
183
|
-
"position":
|
|
129
|
+
"position": 14,
|
|
184
130
|
"url": "https://thumbgate.ai/guides/relational-knowledge-ai-recommendations",
|
|
185
131
|
"name": "Relational Knowledge in AI Recommendations"
|
|
186
132
|
},
|
|
187
133
|
{
|
|
188
134
|
"@type": "ListItem",
|
|
189
|
-
"position":
|
|
135
|
+
"position": 15,
|
|
190
136
|
"url": "https://thumbgate.ai/guides/ai-deployment-readiness",
|
|
191
137
|
"name": "AI Deployment Readiness Before Production Rollout"
|
|
192
|
-
},
|
|
193
|
-
{
|
|
194
|
-
"@type": "ListItem",
|
|
195
|
-
"position": 18,
|
|
196
|
-
"url": "https://thumbgate.ai/guides/database-agent-safety",
|
|
197
|
-
"name": "Database Safety for AI Agents"
|
|
198
138
|
}
|
|
199
139
|
]
|
|
200
140
|
}
|
|
@@ -290,7 +230,7 @@
|
|
|
290
230
|
<body>
|
|
291
231
|
|
|
292
232
|
<nav>
|
|
293
|
-
<a href="/" class="brand"><img src="/assets/brand/thumbgate-mark-inline
|
|
233
|
+
<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>
|
|
294
234
|
<a href="/guide">Setup Guide</a>
|
|
295
235
|
<a href="/learn">Learn</a>
|
|
296
236
|
<a href="/dashboard">Dashboard</a>
|
|
@@ -357,14 +297,6 @@
|
|
|
357
297
|
<span class="article-tag">Shared Memory</span>
|
|
358
298
|
</a>
|
|
359
299
|
|
|
360
|
-
<a href="/learn/background-agent-control-layer" class="article-card">
|
|
361
|
-
<h3>Background Agents Need a Control Layer Outside the Model</h3>
|
|
362
|
-
<p>Agents can produce work. Production teams still need triggers, isolated runs, context, visibility, and controls. This is where ThumbGate fits in the AI-SDLC stack.</p>
|
|
363
|
-
<span class="article-tag">Background Agents</span>
|
|
364
|
-
<span class="article-tag">AI-SDLC</span>
|
|
365
|
-
<span class="article-tag">Controls</span>
|
|
366
|
-
</a>
|
|
367
|
-
|
|
368
300
|
<a href="/learn/claude-code-goal-with-rubrics" class="article-card">
|
|
369
301
|
<h3>Claude Code /goal vs Todo: The 4-Field Pattern That Actually Holds</h3>
|
|
370
302
|
<p>Treating /goal like a todo wastes the command. The 4-field pattern (clear goal, measurable success, shown proof, hard limits) is the same shape as a ThumbGate rubric. Pair them and the agent cannot fake completion.</p>
|
|
@@ -381,46 +313,6 @@
|
|
|
381
313
|
<span class="article-tag">Session Persistence</span>
|
|
382
314
|
</a>
|
|
383
315
|
|
|
384
|
-
<a href="/learn/agentic-enterprise-context-brain" class="article-card">
|
|
385
|
-
<h3>Agentic Enterprise Context Brain: Memory Plus Enforcement</h3>
|
|
386
|
-
<p>Enterprise agents need a context brain, but memory alone does not stop a repeated bad action. This guide turns facts, trust scores, prior failures, approvals, and evidence into pre-action gates.</p>
|
|
387
|
-
<span class="article-tag">Agentic Enterprise</span>
|
|
388
|
-
<span class="article-tag">Memory OS</span>
|
|
389
|
-
<span class="article-tag">Enforcement</span>
|
|
390
|
-
</a>
|
|
391
|
-
|
|
392
|
-
<a href="/learn/deterministic-agent-workflows" class="article-card">
|
|
393
|
-
<h3>Deterministic Agent Workflows Need Runtime Gates</h3>
|
|
394
|
-
<p>Claude Code workflows make orchestration scriptable and reviewable. ThumbGate adds the missing trust layer: run contracts, proof gates, and repeat-failure blocks before each tool call executes.</p>
|
|
395
|
-
<span class="article-tag">Claude Code</span>
|
|
396
|
-
<span class="article-tag">Workflows</span>
|
|
397
|
-
<span class="article-tag">Proof Gates</span>
|
|
398
|
-
</a>
|
|
399
|
-
|
|
400
|
-
<a href="/learn/codex-role-plugins-need-governance" class="article-card">
|
|
401
|
-
<h3>Codex Role Plugins Need Pre-Action Governance</h3>
|
|
402
|
-
<p>Codex plugins, Sites, and annotations move agent work into sales, analytics, design, finance, and documents. ThumbGate gates role-specific writes before they publish, share, or update business systems.</p>
|
|
403
|
-
<span class="article-tag">Codex Plugins</span>
|
|
404
|
-
<span class="article-tag">Sites</span>
|
|
405
|
-
<span class="article-tag">Governance</span>
|
|
406
|
-
</a>
|
|
407
|
-
|
|
408
|
-
<a href="/learn/agentic-os-team-governance" class="article-card">
|
|
409
|
-
<h3>Agentic OS Team Governance: Three Tiers Plus Gates</h3>
|
|
410
|
-
<p>A team Agentic OS needs human-editable source of truth, agent-operating files, git backup, permission mirroring, and memory scope. ThumbGate turns that architecture into runtime checks.</p>
|
|
411
|
-
<span class="article-tag">Agentic OS</span>
|
|
412
|
-
<span class="article-tag">Team Memory</span>
|
|
413
|
-
<span class="article-tag">Enterprise</span>
|
|
414
|
-
</a>
|
|
415
|
-
|
|
416
|
-
<a href="/learn/cost-aware-agent-gate-routing" class="article-card">
|
|
417
|
-
<h3>Cost-Aware Agent Gate Routing</h3>
|
|
418
|
-
<p>Use deterministic rules, semantic cache, local classifiers, local semantic recall, LLM judges, and human review in the right order so governance stays fast enough to leave on.</p>
|
|
419
|
-
<span class="article-tag">Semantic Cache</span>
|
|
420
|
-
<span class="article-tag">Rubrics</span>
|
|
421
|
-
<span class="article-tag">Cost Control</span>
|
|
422
|
-
</a>
|
|
423
|
-
|
|
424
316
|
<a href="/learn/from-prototype-to-production" class="article-card">
|
|
425
317
|
<h3>From git init to v1.17.0 in 70 days: an honest ThumbGate build log</h3>
|
|
426
318
|
<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>
|
|
@@ -428,27 +320,11 @@
|
|
|
428
320
|
<span class="article-tag">Indie SaaS</span>
|
|
429
321
|
<span class="article-tag">Shipping in Public</span>
|
|
430
322
|
</a>
|
|
431
|
-
|
|
432
|
-
<a href="/learn/pretix-stripe-connect-marketplaces" class="article-card">
|
|
433
|
-
<h3>Building a Pretix + Stripe Connect Plugin for Live-Music Venues</h3>
|
|
434
|
-
<p>How to design a multi-venue Stripe Connect ticketing plugin on Pretix, keeping venues as Merchant of Record without messy platform-fee tax reporting.</p>
|
|
435
|
-
<span class="article-tag">Stripe Connect</span>
|
|
436
|
-
<span class="article-tag">Pretix</span>
|
|
437
|
-
<span class="article-tag">Case Study</span>
|
|
438
|
-
</a>
|
|
439
323
|
</div>
|
|
440
324
|
|
|
441
325
|
<h2>Popular buyer questions</h2>
|
|
442
326
|
<p class="section-intro">These are the high-intent guides for buyers who already know the pain and want to understand where ThumbGate fits fast.</p>
|
|
443
327
|
<div class="article-grid">
|
|
444
|
-
<a href="/guides/database-agent-safety" class="article-card">
|
|
445
|
-
<h3>Database Safety for AI Agents</h3>
|
|
446
|
-
<p>Block hallucinated SQL writes, migrations, role grants, and production database changes before an agent can touch live data.</p>
|
|
447
|
-
<span class="article-tag">Database</span>
|
|
448
|
-
<span class="article-tag">SQL</span>
|
|
449
|
-
<span class="article-tag">Production Safety</span>
|
|
450
|
-
</a>
|
|
451
|
-
|
|
452
328
|
<a href="/guides/ai-deployment-readiness" class="article-card">
|
|
453
329
|
<h3>AI Deployment Readiness Before Production Rollout</h3>
|
|
454
330
|
<p>Use one priority workflow to map tools, data, controls, pre-action gates, and proof before an AI deployment team ships into production.</p>
|
|
@@ -457,14 +333,6 @@
|
|
|
457
333
|
<span class="article-tag">Sprint</span>
|
|
458
334
|
</a>
|
|
459
335
|
|
|
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
|
-
|
|
468
336
|
<a href="/guides/ai-search-topical-presence" class="article-card">
|
|
469
337
|
<h3>AI Search Topical Presence</h3>
|
|
470
338
|
<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>
|
|
@@ -473,22 +341,6 @@
|
|
|
473
341
|
<span class="article-tag">Recommendation</span>
|
|
474
342
|
</a>
|
|
475
343
|
|
|
476
|
-
<a href="/guides/agentic-web-governance" class="article-card">
|
|
477
|
-
<h3>Agentic Web Governance</h3>
|
|
478
|
-
<p>Bots already outnumber humans in HTML requests. ThumbGate turns that agentic-web shift into pre-action governance before AI agents touch real systems.</p>
|
|
479
|
-
<span class="article-tag">Agentic Web</span>
|
|
480
|
-
<span class="article-tag">AI Search</span>
|
|
481
|
-
<span class="article-tag">Governance</span>
|
|
482
|
-
</a>
|
|
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
344
|
<a href="/guides/relational-knowledge-ai-recommendations" class="article-card">
|
|
493
345
|
<h3>Relational Knowledge in AI Recommendations</h3>
|
|
494
346
|
<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,30 +381,6 @@
|
|
|
529
381
|
<span class="article-tag">Enforcement</span>
|
|
530
382
|
</a>
|
|
531
383
|
|
|
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
|
-
|
|
556
384
|
<a href="/guides/roo-code-alternative-cline" class="article-card">
|
|
557
385
|
<h3>Roo Code Alternative: Migrate to Cline Without Losing Agent Memory</h3>
|
|
558
386
|
<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>
|
|
@@ -593,6 +421,5 @@
|
|
|
593
421
|
</div>
|
|
594
422
|
</div>
|
|
595
423
|
|
|
596
|
-
<script src="/js/buyer-intent.js"></script>
|
|
597
424
|
</body>
|
|
598
425
|
</html>
|
package/public/lessons.html
CHANGED
|
@@ -6,13 +6,13 @@
|
|
|
6
6
|
<title>ThumbGate — Lessons Learned</title>
|
|
7
7
|
<link rel="icon" type="image/png" href="/thumbgate-icon.png">
|
|
8
8
|
<link rel="apple-touch-icon" href="/assets/brand/thumbgate-mark.svg">
|
|
9
|
-
<script defer data-domain="thumbgate.
|
|
9
|
+
<script defer data-domain="thumbgate-production.up.railway.app" src="https://plausible.io/js/script.js"></script>
|
|
10
10
|
<script type="application/ld+json">
|
|
11
11
|
{
|
|
12
12
|
"@context": "https://schema.org",
|
|
13
13
|
"@type": "WebPage",
|
|
14
14
|
"name": "ThumbGate Lessons Learned",
|
|
15
|
-
"url": "https://thumbgate.
|
|
15
|
+
"url": "https://thumbgate-production.up.railway.app/lessons",
|
|
16
16
|
"dateModified": "2026-04-20",
|
|
17
17
|
"author": {
|
|
18
18
|
"@type": "Person",
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
"publisher": {
|
|
27
27
|
"@type": "Organization",
|
|
28
28
|
"name": "ThumbGate",
|
|
29
|
-
"url": "https://thumbgate.
|
|
29
|
+
"url": "https://thumbgate-production.up.railway.app"
|
|
30
30
|
}
|
|
31
31
|
}
|
|
32
32
|
</script>
|
|
@@ -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
|
|
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>
|
|
215
215
|
<div class="nav-links">
|
|
216
216
|
<a href="/dashboard">Dashboard</a>
|
|
217
217
|
<a href="/lessons" class="active">Lessons</a>
|
|
@@ -385,32 +385,8 @@ const LOCAL_PRO_BOOTSTRAP = __LESSONS_BOOTSTRAP_ENABLED__;
|
|
|
385
385
|
function escHtml(s) { var d = document.createElement('div'); d.textContent = s; return d.innerHTML; }
|
|
386
386
|
function escAttr(s) { return escHtml(String(s || '')).replace(/"/g, '"'); }
|
|
387
387
|
|
|
388
|
-
let ACTIVE_PROJECT_DIR = '';
|
|
389
|
-
try {
|
|
390
|
-
var urlParams = new URLSearchParams(window.location.search);
|
|
391
|
-
ACTIVE_PROJECT_DIR = urlParams.get('project') || '';
|
|
392
|
-
} catch (e) {}
|
|
393
|
-
|
|
394
|
-
function preserveProjectQueryParams() {
|
|
395
|
-
if (!ACTIVE_PROJECT_DIR) return;
|
|
396
|
-
var links = document.querySelectorAll('a[href^="/dashboard"], a[href^="/lessons"], a[href="/"]');
|
|
397
|
-
links.forEach(function(link) {
|
|
398
|
-
try {
|
|
399
|
-
var url = new URL(link.href, window.location.origin);
|
|
400
|
-
url.searchParams.set('project', ACTIVE_PROJECT_DIR);
|
|
401
|
-
link.href = url.pathname + url.search + url.hash;
|
|
402
|
-
} catch (e) {}
|
|
403
|
-
});
|
|
404
|
-
}
|
|
405
|
-
|
|
406
|
-
window.addEventListener('DOMContentLoaded', preserveProjectQueryParams);
|
|
407
|
-
|
|
408
388
|
function getHeaders() {
|
|
409
|
-
|
|
410
|
-
if (ACTIVE_PROJECT_DIR) {
|
|
411
|
-
headers['x-thumbgate-project-dir'] = ACTIVE_PROJECT_DIR;
|
|
412
|
-
}
|
|
413
|
-
return headers;
|
|
389
|
+
return { 'Authorization': 'Bearer ' + API_KEY, 'Content-Type': 'application/json' };
|
|
414
390
|
}
|
|
415
391
|
|
|
416
392
|
function hasBootstrapKey() {
|
|
@@ -473,18 +449,6 @@ function switchTab(name) {
|
|
|
473
449
|
// Highlight the corresponding stat card
|
|
474
450
|
var cardMap = { rules: 0, timeline: 2, insights: 3 };
|
|
475
451
|
highlightCard(cardMap[name] !== undefined ? cardMap[name] : -1);
|
|
476
|
-
// Scroll the active tab content into view so the click has a visible effect.
|
|
477
|
-
// Without this, clicking a stat card or tab header when its content is below
|
|
478
|
-
// the fold appears to do nothing — the tab changes silently and the user
|
|
479
|
-
// never sees the new content. The tab-strip itself stays visible so the
|
|
480
|
-
// selected-state is still observable.
|
|
481
|
-
if (content && typeof content.scrollIntoView === 'function') {
|
|
482
|
-
try {
|
|
483
|
-
content.scrollIntoView({ behavior: 'smooth', block: 'start' });
|
|
484
|
-
} catch (_err) {
|
|
485
|
-
content.scrollIntoView();
|
|
486
|
-
}
|
|
487
|
-
}
|
|
488
452
|
if (typeof plausible === 'function') plausible('lessons_tab', { props: { tab: name } });
|
|
489
453
|
}
|
|
490
454
|
|
|
@@ -815,107 +779,14 @@ function deriveSeverity(lesson) {
|
|
|
815
779
|
return 'info';
|
|
816
780
|
}
|
|
817
781
|
|
|
818
|
-
function cleanLiveTitle(titleText, contextText) {
|
|
819
|
-
if (!titleText) return 'Lesson';
|
|
820
|
-
var prefix = '';
|
|
821
|
-
var rest = titleText;
|
|
822
|
-
var match = titleText.match(/^(MISTAKE|SUCCESS|LEARNING|PREFERENCE):\s*(.*)/i);
|
|
823
|
-
if (match) {
|
|
824
|
-
prefix = match[1].toUpperCase() + ': ';
|
|
825
|
-
rest = match[2];
|
|
826
|
-
}
|
|
827
|
-
|
|
828
|
-
var trimmed = rest.trim();
|
|
829
|
-
var isJson = trimmed.indexOf('{') === 0;
|
|
830
|
-
|
|
831
|
-
if (isJson) {
|
|
832
|
-
try {
|
|
833
|
-
var parsed = JSON.parse(trimmed);
|
|
834
|
-
var promptVal = parsed.prompt;
|
|
835
|
-
var hookVal = parsed.hook_event_name || parsed.hookEventName;
|
|
836
|
-
if (promptVal) {
|
|
837
|
-
var dirName = parsed.cwd ? parsed.cwd.split('/').pop() : '';
|
|
838
|
-
return prefix + 'Prompt "' + promptVal + '"' + (dirName ? ' inside ' + dirName : '');
|
|
839
|
-
}
|
|
840
|
-
if (hookVal) {
|
|
841
|
-
var dirName = parsed.cwd ? parsed.cwd.split('/').pop() : '';
|
|
842
|
-
return prefix + 'Hook event ' + hookVal + (dirName ? ' inside ' + dirName : '');
|
|
843
|
-
}
|
|
844
|
-
if (parsed.signal) {
|
|
845
|
-
var dirName = parsed.cwd ? parsed.cwd.split('/').pop() : '';
|
|
846
|
-
return prefix + (parsed.signal === 'up' ? 'Thumbs Up' : 'Thumbs Down') + (dirName ? ' inside ' + dirName : '');
|
|
847
|
-
}
|
|
848
|
-
} catch (e) {
|
|
849
|
-
if (contextText) {
|
|
850
|
-
var ctxTrimmed = contextText.trim();
|
|
851
|
-
if (ctxTrimmed.indexOf('{') === 0) {
|
|
852
|
-
try {
|
|
853
|
-
var parsedCtx = JSON.parse(ctxTrimmed);
|
|
854
|
-
var promptValCtx = parsedCtx.prompt;
|
|
855
|
-
var hookValCtx = parsedCtx.hook_event_name || parsedCtx.hookEventName;
|
|
856
|
-
if (promptValCtx) {
|
|
857
|
-
var dirName = parsedCtx.cwd ? parsedCtx.cwd.split('/').pop() : '';
|
|
858
|
-
return prefix + 'Prompt "' + promptValCtx + '"' + (dirName ? ' inside ' + dirName : '');
|
|
859
|
-
}
|
|
860
|
-
if (hookValCtx) {
|
|
861
|
-
var dirName = parsedCtx.cwd ? parsedCtx.cwd.split('/').pop() : '';
|
|
862
|
-
return prefix + 'Hook event ' + hookValCtx + (dirName ? ' inside ' + dirName : '');
|
|
863
|
-
}
|
|
864
|
-
} catch (err) {
|
|
865
|
-
// ignore
|
|
866
|
-
}
|
|
867
|
-
}
|
|
868
|
-
}
|
|
869
|
-
}
|
|
870
|
-
|
|
871
|
-
var promptMatch = rest.match(/"prompt"\s*:\s*"([^"]+)"/) || (contextText && contextText.match(/"prompt"\s*:\s*"([^"]+)"/));
|
|
872
|
-
if (promptMatch) {
|
|
873
|
-
var cwdMatch = rest.match(/"cwd"\s*:\s*"([^"]+)"/) || (contextText && contextText.match(/"cwd"\s*:\s*"([^"]+)"/));
|
|
874
|
-
var dirName = cwdMatch ? cwdMatch[1].split('/').pop() : '';
|
|
875
|
-
return prefix + 'Prompt "' + promptMatch[1] + '"' + (dirName ? ' inside ' + dirName : '');
|
|
876
|
-
}
|
|
877
|
-
|
|
878
|
-
var hookMatch = rest.match(/"hook_?event_?name"\s*:\s*"([^"]+)"/i) || (contextText && contextText.match(/"hook_?event_?name"\s*:\s*"([^"]+)"/i));
|
|
879
|
-
if (hookMatch) {
|
|
880
|
-
var cwdMatch = rest.match(/"cwd"\s*:\s*"([^"]+)"/) || (contextText && contextText.match(/"cwd"\s*:\s*"([^"]+)"/));
|
|
881
|
-
var dirName = cwdMatch ? cwdMatch[1].split('/').pop() : '';
|
|
882
|
-
return prefix + 'Hook event ' + hookMatch[1] + (dirName ? ' inside ' + dirName : '');
|
|
883
|
-
}
|
|
884
|
-
}
|
|
885
|
-
return titleText;
|
|
886
|
-
}
|
|
887
|
-
|
|
888
|
-
function cleanLiveContext(contextText) {
|
|
889
|
-
if (!contextText) return '';
|
|
890
|
-
var trimmed = contextText.trim();
|
|
891
|
-
if (trimmed.indexOf('{') === 0 && trimmed.indexOf('}') === trimmed.length - 1) {
|
|
892
|
-
try {
|
|
893
|
-
var parsed = JSON.parse(trimmed);
|
|
894
|
-
if (parsed.prompt) {
|
|
895
|
-
var dirName = parsed.cwd ? parsed.cwd.split('/').pop() : '';
|
|
896
|
-
var parts = [];
|
|
897
|
-
parts.push('Prompt: "' + parsed.prompt + '"');
|
|
898
|
-
if (parsed.cwd) parts.push('Working dir: ' + parsed.cwd);
|
|
899
|
-
if (parsed.hook_event_name) parts.push('Hook event: ' + parsed.hook_event_name);
|
|
900
|
-
return parts.join(' · ');
|
|
901
|
-
}
|
|
902
|
-
} catch (e) {
|
|
903
|
-
// ignore
|
|
904
|
-
}
|
|
905
|
-
}
|
|
906
|
-
return contextText;
|
|
907
|
-
}
|
|
908
|
-
|
|
909
782
|
function mapLiveRules(payload) {
|
|
910
783
|
return (payload.results || []).map(function(result) {
|
|
911
784
|
var linkedGate = (((result.systemResponse || {}).linkedAutoGates) || [])[0] || null;
|
|
912
785
|
var sourceFeedback = ((result.systemResponse || {}).sourceFeedback) || null;
|
|
913
|
-
var rawTitle = result.title || ((result.lesson || {}).summary) || 'Lesson';
|
|
914
|
-
var rawContext = ((result.lesson || {}).howToAvoid) || ((result.lesson || {}).summary) || (sourceFeedback && sourceFeedback.context) || '';
|
|
915
786
|
return {
|
|
916
787
|
id: result.id,
|
|
917
|
-
title:
|
|
918
|
-
context:
|
|
788
|
+
title: result.title || ((result.lesson || {}).summary) || 'Lesson',
|
|
789
|
+
context: ((result.lesson || {}).howToAvoid) || ((result.lesson || {}).summary) || (sourceFeedback && sourceFeedback.context) || '',
|
|
919
790
|
occurrences: linkedGate && linkedGate.occurrences ? linkedGate.occurrences : 1,
|
|
920
791
|
severity: deriveSeverity(result),
|
|
921
792
|
tags: Array.isArray(result.tags) ? result.tags : [],
|
|
@@ -929,14 +800,13 @@ function mapTimelineItems(payload, lessonMap) {
|
|
|
929
800
|
return (payload.results || []).map(function(entry) {
|
|
930
801
|
var linkedLesson = lessonMap.get(entry.id) || null;
|
|
931
802
|
var timestamp = entry.timestamp || null;
|
|
932
|
-
var rawContext = entry.context || entry.title || '';
|
|
933
803
|
return {
|
|
934
804
|
signal: normalizeSignal(entry.signal || entry.feedback),
|
|
935
|
-
context:
|
|
805
|
+
context: entry.context || entry.title || '',
|
|
936
806
|
date: formatDate(entry.timestamp),
|
|
937
807
|
timestamp: timestamp,
|
|
938
808
|
dayKey: toDayKey(timestamp),
|
|
939
|
-
learned: linkedLesson ?
|
|
809
|
+
learned: linkedLesson ? linkedLesson.title : '',
|
|
940
810
|
feedbackId: entry.id || ''
|
|
941
811
|
};
|
|
942
812
|
});
|
|
@@ -1044,41 +914,14 @@ async function loadLive() {
|
|
|
1044
914
|
renderTimeline(allTimeline);
|
|
1045
915
|
renderInsights(dashboardSnapshot);
|
|
1046
916
|
renderImprovementMetrics(stats, dashboardSnapshot);
|
|
1047
|
-
var isEnterprise = API_KEY.startsWith('tg_op_') || API_KEY.startsWith('tg_creator_');
|
|
1048
|
-
if (stats.tier) {
|
|
1049
|
-
isEnterprise = (stats.tier === 'Enterprise');
|
|
1050
|
-
}
|
|
1051
|
-
const tierName = isEnterprise ? 'Enterprise' : 'Pro';
|
|
1052
917
|
document.getElementById('proBadge').style.display = 'none';
|
|
1053
|
-
setMode('Local
|
|
918
|
+
setMode('Local Pro connected — this lessons view is reading your live rules, feedback timeline, and insights.', false);
|
|
1054
919
|
} catch (_err) {
|
|
1055
920
|
loadDemo();
|
|
1056
921
|
}
|
|
1057
922
|
}
|
|
1058
923
|
|
|
1059
924
|
loadLive().then(function() {
|
|
1060
|
-
// Handle ?signal= query param from dashboard stat-card navigation.
|
|
1061
|
-
// Vocabulary: 'up' | 'down' | 'all' (canonical). Also accepts the legacy
|
|
1062
|
-
// 'positive' | 'negative' aliases the dashboard once emitted.
|
|
1063
|
-
var qsSignal = new URLSearchParams(window.location.search).get('signal');
|
|
1064
|
-
if (qsSignal) {
|
|
1065
|
-
var signalMap = { positive: 'up', negative: 'down', up: 'up', down: 'down', all: 'all' };
|
|
1066
|
-
var mapped = signalMap[qsSignal];
|
|
1067
|
-
if (mapped) {
|
|
1068
|
-
switchTab('timeline');
|
|
1069
|
-
filterTimeline(mapped, null);
|
|
1070
|
-
var filterBtns = document.querySelectorAll('#tab-timeline .filter-btn');
|
|
1071
|
-
filterBtns.forEach(function(b) {
|
|
1072
|
-
var label = b.textContent.trim().toLowerCase();
|
|
1073
|
-
var match = (mapped === 'all' && label === 'all') ||
|
|
1074
|
-
(mapped === 'up' && (label.indexOf('👍') !== -1 || label.indexOf('positive') !== -1 || label === 'up')) ||
|
|
1075
|
-
(mapped === 'down' && (label.indexOf('👎') !== -1 || label.indexOf('negative') !== -1 || label === 'down'));
|
|
1076
|
-
b.classList.toggle('active', match);
|
|
1077
|
-
});
|
|
1078
|
-
return;
|
|
1079
|
-
}
|
|
1080
|
-
}
|
|
1081
|
-
|
|
1082
925
|
// Default: highlight Active Rules card on page load
|
|
1083
926
|
highlightCard(0);
|
|
1084
927
|
|
|
@@ -1184,7 +1027,6 @@ async function submitFeedback() {
|
|
|
1184
1027
|
btn.disabled = false; btn.textContent = 'Submit';
|
|
1185
1028
|
}
|
|
1186
1029
|
</script>
|
|
1187
|
-
<script src="/js/buyer-intent.js"></script>
|
|
1188
1030
|
|
|
1189
1031
|
</body>
|
|
1190
1032
|
</html>
|