thumbgate 1.27.6 → 1.27.7
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/commands/thumbgate-blocked.md +27 -0
- package/.claude/commands/thumbgate-doctor.md +30 -0
- package/.claude/commands/thumbgate-guard.md +36 -0
- package/.claude/commands/thumbgate-protect.md +30 -0
- package/.claude/commands/thumbgate-rules.md +30 -0
- package/.claude-plugin/plugin.json +1 -1
- package/.well-known/llms.txt +6 -2
- package/.well-known/mcp/server-card.json +1 -1
- package/README.md +49 -5
- package/adapters/claude/.mcp.json +2 -2
- package/adapters/letta/README.md +41 -0
- package/adapters/letta/thumbgate-letta-adapter.js +133 -0
- package/adapters/mcp/server-stdio.js +16 -1
- package/adapters/opencode/opencode.json +1 -1
- package/adapters/policy-engine/ethicore-guardian-client.js +68 -0
- package/adapters/policy-engine/thumbgate-policy-engine-adapter.js +260 -0
- package/bench/observability-eval-suite.json +26 -0
- package/bin/cli.js +180 -2
- package/bin/postinstall.js +1 -1
- package/config/gate-templates.json +84 -0
- package/config/gates/claim-verification.json +6 -0
- package/config/gates/default.json +20 -0
- package/config/github-about.json +1 -1
- package/config/model-candidates.json +50 -0
- package/package.json +65 -25
- package/public/agent-manager.html +41 -1
- package/public/agents-cost-savings.html +1 -1
- package/public/ai-malpractice-prevention.html +2 -1
- 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-mark-inline.svg +15 -0
- package/public/assets/brand/thumbgate-mark-pro.svg +23 -0
- package/public/assets/brand/thumbgate-mark-team.svg +26 -0
- package/public/assets/brand/thumbgate-mark.svg +15 -0
- package/public/assets/brand/thumbgate-wordmark.svg +20 -0
- package/public/assets/claude-thumbgate-statusbar.svg +8 -0
- package/public/assets/codex-thumbgate-statusbar-test.svg +9 -0
- package/public/assets/legal-intake-control-flow.svg +66 -0
- package/public/blog.html +1 -1
- package/public/brand/thumbgate-mark.svg +15 -0
- package/public/brand/thumbgate-og.svg +16 -0
- package/public/codex-enterprise.html +1 -1
- package/public/codex-plugin.html +1 -1
- package/public/compare.html +23 -3
- package/public/dashboard.html +312 -30
- package/public/federal.html +1 -1
- package/public/guide.html +5 -4
- package/public/index.html +167 -49
- package/public/js/buyer-intent.js +672 -0
- package/public/learn.html +74 -7
- package/public/lessons.html +2 -1
- package/public/numbers.html +3 -3
- package/public/pricing.html +63 -15
- package/public/pro.html +7 -7
- package/scripts/activation-quickstart.js +187 -0
- package/scripts/agent-memory-lifecycle.js +211 -0
- package/scripts/async-eval-observability.js +236 -0
- package/scripts/auto-promote-gates.js +75 -4
- package/scripts/build-metadata.js +24 -3
- package/scripts/cli-schema.js +22 -0
- package/scripts/dashboard-chat.js +2 -1
- package/scripts/dashboard.js +8 -0
- package/scripts/export-databricks-bundle.js +5 -1
- package/scripts/export-dpo-pairs.js +7 -2
- package/scripts/feedback-aggregate.js +281 -0
- package/scripts/feedback-loop.js +34 -0
- package/scripts/filesystem-search.js +35 -10
- package/scripts/gates-engine.js +198 -6
- package/scripts/gemini-embedding-policy.js +2 -1
- package/scripts/hook-stop-anti-claim.js +227 -0
- package/scripts/hook-thumbgate-cache-updater.js +18 -2
- package/scripts/lesson-inference.js +8 -3
- package/scripts/lesson-search.js +17 -1
- package/scripts/operational-integrity.js +39 -5
- package/scripts/plausible-domain-config.js +4 -2
- package/scripts/rate-limiter.js +12 -6
- package/scripts/secret-redaction.js +166 -0
- package/scripts/security-scanner.js +100 -0
- package/scripts/self-distill-agent.js +3 -1
- package/scripts/self-harness-optimizer.js +141 -0
- package/scripts/seo-gsd.js +635 -0
- package/scripts/statusline-cache-path.js +17 -2
- package/scripts/statusline-cache-read.js +57 -0
- package/scripts/statusline-local-stats.js +9 -1
- package/scripts/statusline-meta.js +5 -2
- package/scripts/statusline.sh +13 -1
- package/scripts/sync-telemetry-from-prod.js +374 -0
- package/scripts/telemetry-analytics.js +9 -0
- package/scripts/thumbgate-search.js +85 -19
- package/scripts/tool-contract-validator.js +76 -0
- package/scripts/vector-store.js +44 -0
- package/scripts/workspace-evolver.js +62 -2
- package/src/api/server.js +715 -86
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: thumbgate-blocked
|
|
3
|
+
description: Show what ThumbGate has actually blocked — gate enforcement stats and the full enforcement matrix. Use for "what has ThumbGate blocked", "show gate stats", "is enforcement working", "how many tokens did we save", "enforcement matrix".
|
|
4
|
+
allowed-tools: mcp__thumbgate__gate_stats, mcp__thumbgate__enforcement_matrix, Bash(npx thumbgate gate-stats:*)
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# ThumbGate Blocked
|
|
8
|
+
|
|
9
|
+
Show the enforcement record: how many risky actions were blocked vs warned, which gates fire most, and the full feedback → check → rejection pipeline.
|
|
10
|
+
|
|
11
|
+
This command wraps existing ThumbGate capability — **no new logic**. It reads the live enforcement counters.
|
|
12
|
+
|
|
13
|
+
## Steps
|
|
14
|
+
|
|
15
|
+
1. Call the `gate_stats` MCP tool for the headline numbers: blocked count, warned count, and the top gates by hits. (CLI fallback: `npx thumbgate gate-stats`.)
|
|
16
|
+
2. Call the `enforcement_matrix` MCP tool for the full picture: feedback pipeline stats, active pre-action checks, and the rejection ledger with revival conditions.
|
|
17
|
+
3. Summarize for the user:
|
|
18
|
+
- Total blocks (each block = a repeat mistake stopped before it spent tokens or did damage).
|
|
19
|
+
- Most-triggered gates.
|
|
20
|
+
- Anything in the rejection ledger that is close to revival.
|
|
21
|
+
4. If counts are all zero, note that enforcement is wired but hasn't fired yet, and point to `/thumbgate-guard` to promote a rule.
|
|
22
|
+
|
|
23
|
+
## Example
|
|
24
|
+
|
|
25
|
+
```
|
|
26
|
+
/thumbgate-blocked
|
|
27
|
+
```
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: thumbgate-doctor
|
|
3
|
+
description: Health-check the ThumbGate wiring for this project — hooks, MCP server, and agent-readiness — and report what's broken. Use for "is ThumbGate wired up", "thumbgate doctor", "check my guardrails are installed", "why aren't my gates firing", "agent readiness".
|
|
4
|
+
allowed-tools: Bash(npx thumbgate doctor:*), mcp__thumbgate__check_operational_integrity
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# ThumbGate Doctor
|
|
8
|
+
|
|
9
|
+
Audit whether ThumbGate is actually wired into this agent: PreToolUse / SessionStart hooks installed, MCP server reachable, lesson store present, and overall agent-readiness — then tell the user exactly what to fix.
|
|
10
|
+
|
|
11
|
+
This command wraps existing ThumbGate capability — **no new logic**. It runs the existing doctor + integrity checks.
|
|
12
|
+
|
|
13
|
+
## Steps
|
|
14
|
+
|
|
15
|
+
1. Run the existing wiring/health audit:
|
|
16
|
+
```bash
|
|
17
|
+
npx thumbgate doctor
|
|
18
|
+
```
|
|
19
|
+
(Add `--json` for a machine-readable report.) It exits non-zero when the project is not `ready`.
|
|
20
|
+
2. For deeper runtime state, call the `check_operational_integrity` MCP tool to verify the server-side enforcement path is live, not just the local config.
|
|
21
|
+
3. Summarize:
|
|
22
|
+
- ✅ what's wired (hooks, MCP, store, statusline).
|
|
23
|
+
- ❌ what's missing, with the exact fix command (usually `npx thumbgate init`).
|
|
24
|
+
4. If everything is green, say so plainly with the readiness status; if not, lead with the single highest-impact fix.
|
|
25
|
+
|
|
26
|
+
## Example
|
|
27
|
+
|
|
28
|
+
```
|
|
29
|
+
/thumbgate-doctor
|
|
30
|
+
```
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: thumbgate-guard
|
|
3
|
+
description: Turn the last agent mistake into a hard prevention rule the agent cannot bypass. Use after a bad tool call, a wrong action, or a thumbs-down — "guard against this", "block this from happening again", "never do that again", "promote this to a rule".
|
|
4
|
+
allowed-tools: mcp__thumbgate__capture_feedback, Bash(npx thumbgate force-gate:*), Bash(npx thumbgate quickstart:*)
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# ThumbGate Guard
|
|
8
|
+
|
|
9
|
+
Capture the mistake the agent just made and promote it into a Pre-Action Check (a `block` gate) so the same tool-call shape is intercepted before it runs again — in this and every future session, across Claude Code, Cursor, Codex, Gemini, Amp, and Cline.
|
|
10
|
+
|
|
11
|
+
This command wraps existing ThumbGate capability. It adds **no new logic** — it routes to the real capture + force-promote path.
|
|
12
|
+
|
|
13
|
+
## Steps
|
|
14
|
+
|
|
15
|
+
1. Identify the specific bad action from the recent conversation (e.g. `git push --force origin main`, `DROP TABLE users`, deploy without tests). State it in one sentence.
|
|
16
|
+
2. Record the signal with the `capture_feedback` MCP tool:
|
|
17
|
+
- `signal: "down"`
|
|
18
|
+
- `context`: one sentence describing what went wrong
|
|
19
|
+
- `whatWentWrong`: the concrete failure
|
|
20
|
+
- `whatToChange`: the prevention action
|
|
21
|
+
- `tags`: the domain (e.g. `git`, `database`, `deploy`)
|
|
22
|
+
- If the user only gave a vague signal, pass the recent turns through `conversationWindow` / `chatHistory` for history-aware distillation instead of refusing.
|
|
23
|
+
3. Promote it to an enforced block gate using the existing force-promote path:
|
|
24
|
+
```bash
|
|
25
|
+
npx thumbgate force-gate "<one-sentence context of the mistake>"
|
|
26
|
+
```
|
|
27
|
+
This prints the new `gateId` and the total active gate count.
|
|
28
|
+
4. Show the user the promoted rule and confirm it is now enforced as a PreToolUse block.
|
|
29
|
+
|
|
30
|
+
> First rule of the project and want the guided walkthrough (capture → promote → watch it block once)? Run `npx thumbgate quickstart` instead.
|
|
31
|
+
|
|
32
|
+
## Example
|
|
33
|
+
|
|
34
|
+
```
|
|
35
|
+
/thumbgate-guard the agent force-pushed to main and overwrote a teammate's commit
|
|
36
|
+
```
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: thumbgate-protect
|
|
3
|
+
description: Show this repo's branch/release governance and grant a scoped, time-limited approval for an action that touches protected files. Use for "protect this branch", "is main protected", "approve this protected change", "branch governance", "let me edit a protected file".
|
|
4
|
+
allowed-tools: mcp__thumbgate__get_branch_governance, mcp__thumbgate__approve_protected_action
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# ThumbGate Protect
|
|
8
|
+
|
|
9
|
+
Inspect the protected-action posture for this project and, when the user explicitly approves, grant a scoped, expiring exception so a protected-file edit or publish can proceed under audit.
|
|
10
|
+
|
|
11
|
+
This command wraps existing ThumbGate capability — **no new logic**. It reads governance state and records a time-boxed approval.
|
|
12
|
+
|
|
13
|
+
## Steps
|
|
14
|
+
|
|
15
|
+
1. Read the current posture with the `get_branch_governance` MCP tool: which branches are protected, release rules, and the protected-file globs in effect.
|
|
16
|
+
2. Report it plainly: what is protected, and what the agent is currently blocked from touching without approval.
|
|
17
|
+
3. **Only if the user explicitly asks to proceed**, grant a scoped approval with `approve_protected_action`:
|
|
18
|
+
- `pathGlobs`: the smallest set of protected globs the action needs.
|
|
19
|
+
- `reason`: why this is approved (one sentence).
|
|
20
|
+
- `evidence`: supporting note (tests passing, owner sign-off, etc.) when available.
|
|
21
|
+
- `ttlMs`: keep it short — default is 1 hour, never exceed what the task needs.
|
|
22
|
+
4. Confirm the approval id, covered globs, and expiry. Approvals are deliberately temporary and audited; re-run for the next task.
|
|
23
|
+
|
|
24
|
+
> This is for granting *narrow, temporary* exceptions, not for disabling protection. Never use it to bypass branch governance wholesale.
|
|
25
|
+
|
|
26
|
+
## Example
|
|
27
|
+
|
|
28
|
+
```
|
|
29
|
+
/thumbgate-protect
|
|
30
|
+
```
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: thumbgate-rules
|
|
3
|
+
description: List the active prevention rules and learned lessons guarding this project. Use to answer "what is ThumbGate protecting me from", "show my gates/rules", "what has the agent learned", "what's blocked here".
|
|
4
|
+
allowed-tools: mcp__thumbgate__prevention_rules, mcp__thumbgate__get_reliability_rules, mcp__thumbgate__search_lessons, Bash(npx thumbgate rules:*)
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# ThumbGate Rules
|
|
8
|
+
|
|
9
|
+
Show the guardrails currently in force for this project: the auto-promoted prevention rules, the reliability rules, and the promoted lessons behind them.
|
|
10
|
+
|
|
11
|
+
This command wraps existing ThumbGate capability — **no new logic**. It reads the live rule + lesson stores.
|
|
12
|
+
|
|
13
|
+
## Steps
|
|
14
|
+
|
|
15
|
+
1. List the active prevention rules with the `prevention_rules` MCP tool (or the CLI fallback `npx thumbgate rules`).
|
|
16
|
+
2. Pull the reliability rules with `get_reliability_rules` to show which tool-call shapes are gated.
|
|
17
|
+
3. For each rule, surface the lesson it came from with `search_lessons` so the user sees *why* the rule exists, not just *what* it blocks.
|
|
18
|
+
4. Present a compact table:
|
|
19
|
+
|
|
20
|
+
| Rule / Gate | Blocks | From lesson | State |
|
|
21
|
+
|-------------|--------|-------------|-------|
|
|
22
|
+
| … | … | … | active / archived |
|
|
23
|
+
|
|
24
|
+
5. If there are zero active rules, point the user to `/thumbgate-guard` to promote their first one.
|
|
25
|
+
|
|
26
|
+
## Example
|
|
27
|
+
|
|
28
|
+
```
|
|
29
|
+
/thumbgate-rules
|
|
30
|
+
```
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "thumbgate",
|
|
3
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.27.
|
|
4
|
+
"version": "1.27.7",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Igor Ganapolsky",
|
|
7
7
|
"email": "ig5973700@gmail.com",
|
package/.well-known/llms.txt
CHANGED
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
- CLAUDE.md and .cursorrules files are suggestions agents can ignore
|
|
16
16
|
- No memory between sessions means no learning from corrections
|
|
17
17
|
- Teams have no shared safety rules across developers
|
|
18
|
+
- AI crawlers and agents create machine traffic without proving buyer intent; teams need AI-discoverable proof plus runtime gates before internal agents act
|
|
18
19
|
|
|
19
20
|
## How it works
|
|
20
21
|
|
|
@@ -51,9 +52,9 @@ npx thumbgate init --agent claude-code
|
|
|
51
52
|
- ChatGPT App / GPT Action: https://thumbgate.ai/chatgpt-app
|
|
52
53
|
- Free GPT: advice, checkpointing, and setup help in ChatGPT
|
|
53
54
|
- Codex Plugin: https://thumbgate.ai/codex-plugin
|
|
54
|
-
- Free local CLI:
|
|
55
|
+
- Free local CLI: 2 captures/day, 10 total captures, up to 3 active auto-promoted prevention rules, and local Pre-Action Checks after install (recall and lesson search are Pro-only)
|
|
55
56
|
- Pro: $19/mo or $149/yr — personal enforcement proof, local dashboard, check debugger, DPO export, synced lessons/rules across machines, and review-ready exports
|
|
56
|
-
-
|
|
57
|
+
- Enterprise: custom pricing, scoped after intake — shared hosted lesson database, org-wide dashboard, GCP/DFCX guardrails, VPC gating, and white-glove workflow hardening sprints
|
|
57
58
|
|
|
58
59
|
## Links
|
|
59
60
|
|
|
@@ -63,6 +64,9 @@ npx thumbgate init --agent claude-code
|
|
|
63
64
|
- Agent discovery: https://thumbgate.ai/.well-known/mcp.json
|
|
64
65
|
- Progressive tool index: https://thumbgate.ai/.well-known/mcp/tools.json
|
|
65
66
|
- Context footprint report: https://thumbgate.ai/.well-known/mcp/footprint.json
|
|
67
|
+
- Headroom context compression guardrails: https://thumbgate.ai/guides/headroom-context-compression-guardrails
|
|
68
|
+
- Sovereign coding model guardrails: https://thumbgate.ai/guides/sovereign-coding-model-guardrails
|
|
69
|
+
- Agentic web governance: https://thumbgate.ai/guides/agentic-web-governance
|
|
66
70
|
- AI Mode ads and agent governance: https://thumbgate.ai/guides/ai-mode-ads-agent-governance
|
|
67
71
|
- MCP tool governance: https://thumbgate.ai/guides/mcp-tool-governance
|
|
68
72
|
- AI agent pre-action approval gates: https://thumbgate.ai/guides/ai-agent-pre-action-approval-gates
|
package/README.md
CHANGED
|
@@ -12,6 +12,10 @@ ThumbGate is the local-first firewall for AI coding agents. It runs in the PreTo
|
|
|
12
12
|
|
|
13
13
|
The product is a self-improving enforcement layer: thumbs-down feedback, prompt evaluation, and proof from prior runs become prevention rules that permanently stop repeated failures before the next tool call.
|
|
14
14
|
|
|
15
|
+
<p align="center">
|
|
16
|
+
<img src="docs/media/thumbgate-demo.gif" alt="ThumbGate blocking an AI agent's dangerous commands (rm -rf, force-push, chmod 777) in real time, while letting safe commands through" width="820" />
|
|
17
|
+
</p>
|
|
18
|
+
|
|
15
19
|
```
|
|
16
20
|
Agent tries: rm -rf tests/
|
|
17
21
|
ThumbGate: ⛔ BLOCKED — "Never delete test directories"
|
|
@@ -24,7 +28,7 @@ The product is a self-improving enforcement layer: thumbs-down feedback, prompt
|
|
|
24
28
|
npx thumbgate init # auto-detects your agent, wires hooks, 30 seconds
|
|
25
29
|
```
|
|
26
30
|
|
|
27
|
-
Works with **Claude Code, Cursor, Codex, Gemini CLI, Amp, Cline, OpenCode** and any MCP-compatible agent. Free tier:
|
|
31
|
+
Works with **Claude Code, Cursor, Codex, Gemini CLI, Amp, Cline, OpenCode** and any MCP-compatible agent. Free tier: 2 feedback captures/day (10 total) and up to 3 active auto-promoted prevention rules. [Pro: $19/mo or $149/yr](https://thumbgate.ai/checkout/pro?utm_source=github&utm_medium=readme) — unlimited rules, history-aware lessons, feedback sessions, dashboard, DPO export. Enterprise (custom pricing, scoped after intake) adds a shared hosted lesson DB, org dashboard, and shared org-wide enforcement.
|
|
28
32
|
|
|
29
33
|
[](https://github.com/IgorGanapolsky/ThumbGate/actions/workflows/ci.yml)
|
|
30
34
|
[](https://www.npmjs.com/package/thumbgate)
|
|
@@ -53,6 +57,24 @@ In that stack, ThumbGate is the pre-action gate between generated intent and exe
|
|
|
53
57
|
|
|
54
58
|
---
|
|
55
59
|
|
|
60
|
+
## Discoverable slash-commands — the guardrail layer for spec-driven agents
|
|
61
|
+
|
|
62
|
+
Spec-driven agent frameworks like **GSD** (get-shit-done) and **GitHub Spec Kit** are great at *planning and generating* work — they expose dozens of discoverable `/gsd-*` / `/specify` commands in the agent command palette. ThumbGate is the **guardrail layer for spec-driven agents**: it sits *after* the plan, on the boundary between a generated tool call and its execution. It works **alongside GSD / Spec-Kit, not instead of them** — they decide *what* to build; ThumbGate enforces *what the agent must never do while building it*.
|
|
63
|
+
|
|
64
|
+
`npx thumbgate init` installs these commands into your agent's palette (`.claude/commands/`, `.gemini/commands/`, `.antigravitycli/commands/`) so the enforcement layer is as browsable as the planning layer:
|
|
65
|
+
|
|
66
|
+
| Command | What it does | Wraps (existing capability) |
|
|
67
|
+
|---------|--------------|------------------------------|
|
|
68
|
+
| `/thumbgate-guard` | Turn the last agent mistake into a hard prevention rule | `capture_feedback` + `thumbgate force-gate` |
|
|
69
|
+
| `/thumbgate-rules` | List the active prevention rules + lessons guarding this repo | `prevention_rules`, `get_reliability_rules`, `search_lessons` |
|
|
70
|
+
| `/thumbgate-blocked` | Show what's actually been blocked — gate stats + enforcement matrix | `gate_stats`, `enforcement_matrix` |
|
|
71
|
+
| `/thumbgate-protect` | Show branch/release governance; grant a scoped, expiring approval | `get_branch_governance`, `approve_protected_action` |
|
|
72
|
+
| `/thumbgate-doctor` | Health-check the wiring (hooks, MCP, agent-readiness) | `thumbgate doctor` |
|
|
73
|
+
|
|
74
|
+
Each is a thin wrapper over an existing MCP tool or CLI command — **no new enforcement logic, just discoverability**.
|
|
75
|
+
|
|
76
|
+
---
|
|
77
|
+
|
|
56
78
|
## 🎬 90-second demo
|
|
57
79
|
|
|
58
80
|
Watch the force-push scenario: agent tries to `git push --force`, one thumbs-down, next session it's blocked — zero tokens spent on the repeat.
|
|
@@ -185,6 +207,26 @@ Hand-rolled hooks are the right tool for a small, static denylist you maintain b
|
|
|
185
207
|
|
|
186
208
|
Prompt engineering still matters, but it is only the starting point. ThumbGate adds prompt evaluation on top: proof lanes, benchmarks, and self-heal checks tell you whether your prompt and workflow actually held up under execution instead of leaving you to guess from vibes. Run `npx thumbgate eval --from-feedback --write-report=.thumbgate/prompt-eval-proof.md` to turn real thumbs-up/down feedback into reusable eval cases and a buyer-ready proof report.
|
|
187
209
|
|
|
210
|
+
### Retrieval & latency: local-first, zero network hops
|
|
211
|
+
|
|
212
|
+
ThumbGate's latency advantage is structural, not a tuned cloud cluster: there is no retrieval service and no model on the enforcement path, so the gate decision never leaves your machine.
|
|
213
|
+
|
|
214
|
+
```mermaid
|
|
215
|
+
flowchart LR
|
|
216
|
+
A["Agent about to run<br/>a tool call"] --> B{"Literal / AST match<br/>on an active rule?"}
|
|
217
|
+
B -- "exact match" --> D["Deterministic gate decision<br/>(no model, on-device)"]
|
|
218
|
+
B -- "no exact match, but<br/>semantically near a<br/>blocked pattern" --> C["Local CPU embeddings<br/>bge-small via LanceDB<br/>(no external API)"]
|
|
219
|
+
C --> D
|
|
220
|
+
D -- "known-bad" --> E["⛔ BLOCK before execution"]
|
|
221
|
+
D -- "safe" --> F["✓ Allow"]
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
- **Deterministic first.** Most decisions are a literal or AST pattern match against your active rules — sub-millisecond, on-device, no embeddings.
|
|
225
|
+
- **Local semantic fallback.** When an action isn't on the literal block list but is semantically near one you've blocked before, ThumbGate searches the rule corpus with CPU-only `bge-small` embeddings via LanceDB — still local, still no external API call.
|
|
226
|
+
- **No LLM on the enforcement path.** The gate never calls a model to decide block/allow. Thompson Sampling only tunes soft-rule confidence weights; hard rules always fire deterministically (see Layer 2).
|
|
227
|
+
|
|
228
|
+
The fastest network round-trip is the one you never make: enforcement is fully local, so it adds negligible latency to the agent loop — no cloud retrieval, no inference hop, no data leaving the machine.
|
|
229
|
+
|
|
188
230
|
### Managed model benchmark lane
|
|
189
231
|
|
|
190
232
|
When a new managed model drops, do not swap ThumbGate over on vendor claims alone. Rank it against the actual ThumbGate workload first:
|
|
@@ -342,6 +384,8 @@ npx thumbgate model-candidates --workload=dashboard-analysis --provider=openai -
|
|
|
342
384
|
npx thumbgate native-messaging-audit # inspect local browser bridges and extension hosts
|
|
343
385
|
npx thumbgate dashboard --open # open local project-scoped dashboard in browser
|
|
344
386
|
thumbgate-dashboard # standalone browser dashboard shortcut (run '/project:thumbgate-dashboard' in Claude/Grok)
|
|
387
|
+
npx thumbgate check-update # check if a new version is available on npm/GitHub
|
|
388
|
+
npx thumbgate self-update # update ThumbGate to the latest version globally
|
|
345
389
|
npx thumbgate serve # start MCP server on stdio
|
|
346
390
|
npx thumbgate bench # run reliability benchmark
|
|
347
391
|
npx thumbgate bench --programbench-smoke # include cleanroom whole-repo proof lane
|
|
@@ -382,7 +426,7 @@ If you change MCP or hook settings, restart the affected agent session so Claude
|
|
|
382
426
|
| | Free | Pro ($19/mo) | Enterprise |
|
|
383
427
|
|---|---|---|---|
|
|
384
428
|
| Local CLI + enforced checks | ✅ | ✅ | ✅ |
|
|
385
|
-
| Feedback captures |
|
|
429
|
+
| Feedback captures | 2/day (10 total) | Unlimited | Unlimited |
|
|
386
430
|
| Active auto-promoted prevention rules | 3 | Unlimited | Unlimited |
|
|
387
431
|
| MCP agent integrations | All | All | All |
|
|
388
432
|
| Personal dashboard | — | ✅ | ✅ |
|
|
@@ -396,7 +440,7 @@ If you change MCP or hook settings, restart the affected agent session so Claude
|
|
|
396
440
|
| Compliance audit export | — | — | ✅ |
|
|
397
441
|
| Dedicated onboarding + SLA | — | — | ✅ |
|
|
398
442
|
|
|
399
|
-
The free tier gives you
|
|
443
|
+
The free tier gives you 2 feedback captures/day (10 total) and up to 3 active auto-promoted prevention rules — enough to make ThumbGate part of your daily flow before you upgrade. MCP integrations for all agents (Claude Code, Cursor, Codex, Gemini, Amp, Cline, OpenCode) ship free.
|
|
400
444
|
|
|
401
445
|
Pro ($19/mo or $149/yr) removes the rule cap and adds history-aware lesson recall, lesson search, DPO export, and a personal dashboard. Enterprise (custom pricing, scoped after intake) adds a shared hosted lesson DB, org dashboard, and shared enforcement across the org, plus regulatory gate templates (legal intake, financial compliance, healthcare), custom policy layers scoped to firm/practice-area, compliance audit export, and dedicated onboarding with SLA.
|
|
402
446
|
|
|
@@ -487,7 +531,7 @@ curl -X POST http://localhost:3456/v1/dpo/export \
|
|
|
487
531
|
| Layer | Technology |
|
|
488
532
|
|-------|-----------|
|
|
489
533
|
| **Storage** | SQLite + FTS5, LanceDB vectors, JSONL logs |
|
|
490
|
-
| **Capture** |
|
|
534
|
+
| **Capture** | 2/day, 10 total on Free; unlimited on Pro, Team, and Enterprise |
|
|
491
535
|
| **Intelligence** | MemAlign dual recall, Thompson Sampling |
|
|
492
536
|
| **Enforcement** | PreToolUse hook engine, Checks config |
|
|
493
537
|
| **Interfaces** | MCP stdio, HTTP API, CLI (Node.js >=18) |
|
|
@@ -575,7 +619,7 @@ Those are suggestions the agent can ignore. ThumbGate checks are enforced — th
|
|
|
575
619
|
If it supports MCP or pre-action hooks, yes. Claude Code, Claude Desktop, Cursor, Codex, Gemini CLI, Amp, Cline, OpenCode all work out of the box.
|
|
576
620
|
|
|
577
621
|
**Is it free?**
|
|
578
|
-
The free tier gives you
|
|
622
|
+
The free tier gives you 2 feedback captures/day, 10 total captures, and up to 3 active auto-promoted prevention rules — enough for solo devs to prove a blocked repeat before upgrading. MCP integrations ship free for every agent.
|
|
579
623
|
|
|
580
624
|
Pro ($19/mo or $149/yr) removes the rule cap and adds history-aware lesson recall, lesson search, and a personal dashboard. Enterprise (custom pricing, scoped after intake) adds a shared hosted lesson DB, org dashboard, and shared enforcement.
|
|
581
625
|
|
|
@@ -2,13 +2,13 @@
|
|
|
2
2
|
"mcpServers": {
|
|
3
3
|
"thumbgate": {
|
|
4
4
|
"command": "npx",
|
|
5
|
-
"args": ["--yes", "--package", "thumbgate@1.27.
|
|
5
|
+
"args": ["--yes", "--package", "thumbgate@1.27.7", "thumbgate", "serve"]
|
|
6
6
|
}
|
|
7
7
|
},
|
|
8
8
|
"hooks": {
|
|
9
9
|
"preToolUse": {
|
|
10
10
|
"command": "npx",
|
|
11
|
-
"args": ["--yes", "--package", "thumbgate@1.27.
|
|
11
|
+
"args": ["--yes", "--package", "thumbgate@1.27.7", "thumbgate", "gate-check"]
|
|
12
12
|
}
|
|
13
13
|
}
|
|
14
14
|
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# Letta Adapter
|
|
2
|
+
|
|
3
|
+
Letta is a stateful-agent runtime with persistent memory, MCP tools, custom server tools, and client-side tool execution. ThumbGate should not compete with that memory surface. ThumbGate should sit underneath it as the deterministic local enforcement layer.
|
|
4
|
+
|
|
5
|
+
## Integration Pattern
|
|
6
|
+
|
|
7
|
+
Use `thumbgate-letta-adapter.js` to wrap Letta tool execution:
|
|
8
|
+
|
|
9
|
+
1. Letta agent proposes a tool call.
|
|
10
|
+
2. The wrapper normalizes the Letta event into ThumbGate's provider-action schema.
|
|
11
|
+
3. Your app calls ThumbGate's local gate-check transport.
|
|
12
|
+
4. If ThumbGate blocks or requires approval, the tool executor is never called.
|
|
13
|
+
5. If allowed, the original Letta tool executes normally.
|
|
14
|
+
|
|
15
|
+
This works for the two practical Letta surfaces:
|
|
16
|
+
|
|
17
|
+
- **MCP tools**: Letta forwards the tool call through the Letta server to an MCP server. Wrap the forwarding boundary or expose the downstream tool through a ThumbGate-guarded MCP server.
|
|
18
|
+
- **Client tools**: Letta asks your client application to execute a tool locally. Wrap the client tool handler with `createLettaToolGuard`.
|
|
19
|
+
|
|
20
|
+
## Example
|
|
21
|
+
|
|
22
|
+
```js
|
|
23
|
+
const { createLettaToolGuard } = require('./thumbgate-letta-adapter');
|
|
24
|
+
|
|
25
|
+
const guardedTool = createLettaToolGuard({
|
|
26
|
+
gateCheck: async (normalizedAction) => thumbgateGateCheck(normalizedAction),
|
|
27
|
+
executeTool: async (lettaEvent) => runOriginalTool(lettaEvent),
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
await guardedTool({
|
|
31
|
+
agentId: 'agent-123',
|
|
32
|
+
clientTool: {
|
|
33
|
+
name: 'shell',
|
|
34
|
+
input: { command: 'git push --force origin main' },
|
|
35
|
+
},
|
|
36
|
+
});
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## Positioning
|
|
40
|
+
|
|
41
|
+
Letta helps agents remember and operate with state. ThumbGate helps teams decide what those agents are allowed to do next. The moat is adapter coverage: ThumbGate works under memory-first runtimes instead of asking buyers to replace them.
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
const { normalizeProviderAction } = require('../../scripts/provider-action-normalizer');
|
|
5
|
+
|
|
6
|
+
function asObject(value) {
|
|
7
|
+
return value && typeof value === 'object' && !Array.isArray(value) ? value : {};
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
function firstString(...values) {
|
|
11
|
+
for (const value of values) {
|
|
12
|
+
const text = String(value || '').trim();
|
|
13
|
+
if (text) return text;
|
|
14
|
+
}
|
|
15
|
+
return '';
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function extractLettaToolCall(input = {}) {
|
|
19
|
+
const event = asObject(input);
|
|
20
|
+
const toolCall = asObject(event.toolCall || event.tool_call || event.lettaToolCall);
|
|
21
|
+
const functionCall = asObject(toolCall.function || event.function);
|
|
22
|
+
const mcp = asObject(event.mcp || event.mcpToolCall);
|
|
23
|
+
const clientTool = asObject(event.clientTool || event.client_tool);
|
|
24
|
+
const params = asObject(event.params);
|
|
25
|
+
|
|
26
|
+
const name = firstString(
|
|
27
|
+
event.toolName,
|
|
28
|
+
event.name,
|
|
29
|
+
toolCall.name,
|
|
30
|
+
functionCall.name,
|
|
31
|
+
clientTool.name,
|
|
32
|
+
mcp.name,
|
|
33
|
+
params.name
|
|
34
|
+
);
|
|
35
|
+
const args = asObject(
|
|
36
|
+
event.arguments
|
|
37
|
+
|| event.args
|
|
38
|
+
|| event.input
|
|
39
|
+
|| toolCall.arguments
|
|
40
|
+
|| toolCall.input
|
|
41
|
+
|| functionCall.arguments
|
|
42
|
+
|| clientTool.arguments
|
|
43
|
+
|| clientTool.input
|
|
44
|
+
|| mcp.arguments
|
|
45
|
+
|| params.arguments
|
|
46
|
+
);
|
|
47
|
+
|
|
48
|
+
return {
|
|
49
|
+
id: firstString(event.id, event.toolCallId, event.tool_call_id, toolCall.id, clientTool.id),
|
|
50
|
+
name,
|
|
51
|
+
arguments: args,
|
|
52
|
+
server: firstString(event.mcpServer, mcp.server, params.server),
|
|
53
|
+
surface: firstString(event.surface, event.executionSurface, clientTool.name ? 'client-tool' : mcp.name || params.name ? 'mcp-tool' : 'server-tool'),
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function normalizeLettaAction(input = {}) {
|
|
58
|
+
const event = asObject(input);
|
|
59
|
+
const toolCall = extractLettaToolCall(event);
|
|
60
|
+
|
|
61
|
+
const normalized = normalizeProviderAction({
|
|
62
|
+
...event,
|
|
63
|
+
provider: 'letta',
|
|
64
|
+
toolCall: {
|
|
65
|
+
id: toolCall.id,
|
|
66
|
+
name: toolCall.name,
|
|
67
|
+
input: toolCall.arguments,
|
|
68
|
+
},
|
|
69
|
+
toolName: toolCall.name,
|
|
70
|
+
input: toolCall.arguments,
|
|
71
|
+
mcpServer: toolCall.server,
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
return {
|
|
75
|
+
...normalized,
|
|
76
|
+
provider: 'letta',
|
|
77
|
+
agentRuntime: 'letta',
|
|
78
|
+
letta: {
|
|
79
|
+
agentId: firstString(event.agentId, event.agent_id),
|
|
80
|
+
messageId: firstString(event.messageId, event.message_id),
|
|
81
|
+
surface: toolCall.surface,
|
|
82
|
+
toolCallId: toolCall.id,
|
|
83
|
+
},
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
function normalizeGateDecision(decision = {}) {
|
|
88
|
+
const value = asObject(decision);
|
|
89
|
+
const raw = firstString(value.decision, value.mode, value.action, value.status).toLowerCase();
|
|
90
|
+
const blocked = value.allowed === false
|
|
91
|
+
|| value.accepted === false
|
|
92
|
+
|| value.blocked === true
|
|
93
|
+
|| ['block', 'deny', 'denied', 'reject', 'rejected'].includes(raw);
|
|
94
|
+
const approvalRequired = value.requiresApproval === true || raw === 'approve';
|
|
95
|
+
return {
|
|
96
|
+
allowed: !blocked && !approvalRequired,
|
|
97
|
+
blocked,
|
|
98
|
+
approvalRequired,
|
|
99
|
+
reason: firstString(value.reason, value.message, Array.isArray(value.reasons) ? value.reasons.join('; ') : ''),
|
|
100
|
+
raw: value,
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
function createLettaToolGuard({ gateCheck, executeTool, onDecision } = {}) {
|
|
105
|
+
if (typeof gateCheck !== 'function') {
|
|
106
|
+
throw new TypeError('createLettaToolGuard requires a gateCheck function');
|
|
107
|
+
}
|
|
108
|
+
if (typeof executeTool !== 'function') {
|
|
109
|
+
throw new TypeError('createLettaToolGuard requires an executeTool function');
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
return async function guardedLettaTool(input = {}) {
|
|
113
|
+
const normalizedAction = normalizeLettaAction(input);
|
|
114
|
+
const decision = normalizeGateDecision(await gateCheck(normalizedAction));
|
|
115
|
+
if (typeof onDecision === 'function') {
|
|
116
|
+
await onDecision({ normalizedAction, decision });
|
|
117
|
+
}
|
|
118
|
+
if (!decision.allowed) {
|
|
119
|
+
const error = new Error(decision.reason || 'ThumbGate blocked this Letta tool call before execution.');
|
|
120
|
+
error.code = decision.approvalRequired ? 'THUMBGATE_APPROVAL_REQUIRED' : 'THUMBGATE_BLOCKED';
|
|
121
|
+
error.thumbgate = { normalizedAction, decision };
|
|
122
|
+
throw error;
|
|
123
|
+
}
|
|
124
|
+
return executeTool(input, { normalizedAction, decision });
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
module.exports = {
|
|
129
|
+
createLettaToolGuard,
|
|
130
|
+
extractLettaToolCall,
|
|
131
|
+
normalizeGateDecision,
|
|
132
|
+
normalizeLettaAction,
|
|
133
|
+
};
|
|
@@ -231,7 +231,7 @@ const {
|
|
|
231
231
|
finalizeSession: finalizeFeedbackSession,
|
|
232
232
|
} = require('../../scripts/feedback-session');
|
|
233
233
|
|
|
234
|
-
const SERVER_INFO = { name: 'thumbgate-mcp', version: '1.27.
|
|
234
|
+
const SERVER_INFO = { name: 'thumbgate-mcp', version: '1.27.7' };
|
|
235
235
|
const COMMERCE_CATEGORIES = [
|
|
236
236
|
'product_recommendation',
|
|
237
237
|
'brand_compliance',
|
|
@@ -674,6 +674,21 @@ function buildEstimateUncertaintyResponse(args = {}) {
|
|
|
674
674
|
|
|
675
675
|
async function callTool(name, args = {}) {
|
|
676
676
|
assertToolAllowed(name, getActiveMcpProfile());
|
|
677
|
+
|
|
678
|
+
// Validate tool input contract against schema
|
|
679
|
+
const { TOOLS } = require('../../scripts/tool-registry');
|
|
680
|
+
const toolDef = TOOLS.find(t => t.name === name);
|
|
681
|
+
if (toolDef && toolDef.inputSchema) {
|
|
682
|
+
const { validateToolContract } = require('../../scripts/tool-contract-validator');
|
|
683
|
+
const validation = validateToolContract(toolDef.inputSchema, args);
|
|
684
|
+
if (!validation.valid) {
|
|
685
|
+
const err = new Error(`Tool contract violation on '${name}': ${validation.errors.join('; ')}`);
|
|
686
|
+
err.errorCategory = 'contract';
|
|
687
|
+
err.isRetryable = false;
|
|
688
|
+
throw err;
|
|
689
|
+
}
|
|
690
|
+
}
|
|
691
|
+
|
|
677
692
|
if (name !== 'workflow_sentinel' && process.env.THUMBGATE_DISABLE_MCP_FIREWALL !== '1') {
|
|
678
693
|
const firewallResult = (await evaluateGatesAsync(name, args)) || evaluateSecretGuard({ tool_name: name, tool_input: args });
|
|
679
694
|
if (firewallResult && firewallResult.decision === 'deny') {
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
const DEFAULT_ENDPOINT = 'https://api.oraclestechnologies.com/v1/guardian/analyze';
|
|
5
|
+
|
|
6
|
+
function requireApiKey(env = process.env) {
|
|
7
|
+
const key = env.ETHICORE_API_KEY || env.GUARDIAN_API_KEY || env.ORACLES_GUARDIAN_API_KEY;
|
|
8
|
+
if (!key) {
|
|
9
|
+
throw new Error('ETHICORE_API_KEY env var is required');
|
|
10
|
+
}
|
|
11
|
+
return key;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
async function analyzeText(text, options = {}) {
|
|
15
|
+
if (!String(text || '').trim()) {
|
|
16
|
+
throw new Error('analyzeText requires text');
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const env = options.env || process.env;
|
|
20
|
+
const endpoint = options.endpoint || env.ETHICORE_GUARDIAN_ENDPOINT || DEFAULT_ENDPOINT;
|
|
21
|
+
const apiKey = options.apiKey || requireApiKey(env);
|
|
22
|
+
const fetchImpl = options.fetch || fetch;
|
|
23
|
+
|
|
24
|
+
const response = await fetchImpl(endpoint, {
|
|
25
|
+
method: 'POST',
|
|
26
|
+
headers: {
|
|
27
|
+
Authorization: `Bearer ${apiKey}`,
|
|
28
|
+
'Content-Type': 'application/json',
|
|
29
|
+
},
|
|
30
|
+
body: JSON.stringify({ text }),
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
const bodyText = await response.text();
|
|
34
|
+
let body = bodyText;
|
|
35
|
+
try {
|
|
36
|
+
body = bodyText ? JSON.parse(bodyText) : {};
|
|
37
|
+
} catch {
|
|
38
|
+
// Keep non-JSON body for diagnostics.
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
if (!response.ok) {
|
|
42
|
+
throw new Error(`Ethicore Guardian API ${response.status}: ${typeof body === 'string' ? body : JSON.stringify(body)}`);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
return body;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function createEthicorePolicyCheck(options = {}) {
|
|
49
|
+
return async function ethicorePolicyCheck(action = {}) {
|
|
50
|
+
const toolText = [
|
|
51
|
+
action.toolName,
|
|
52
|
+
action.actionType,
|
|
53
|
+
action.command,
|
|
54
|
+
action.path,
|
|
55
|
+
action.url,
|
|
56
|
+
action.input ? JSON.stringify(action.input) : '',
|
|
57
|
+
].filter(Boolean).join('\n');
|
|
58
|
+
|
|
59
|
+
return analyzeText(toolText || JSON.stringify(action), options);
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
module.exports = {
|
|
64
|
+
DEFAULT_ENDPOINT,
|
|
65
|
+
analyzeText,
|
|
66
|
+
createEthicorePolicyCheck,
|
|
67
|
+
requireApiKey,
|
|
68
|
+
};
|