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
|
@@ -1,68 +0,0 @@
|
|
|
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
|
-
};
|
|
@@ -1,260 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
'use strict';
|
|
3
|
-
|
|
4
|
-
const { normalizeProviderAction } = require('../../scripts/provider-action-normalizer');
|
|
5
|
-
|
|
6
|
-
const BLOCK_DECISIONS = new Set([
|
|
7
|
-
'block',
|
|
8
|
-
'blocked',
|
|
9
|
-
'deny',
|
|
10
|
-
'denied',
|
|
11
|
-
'disallow',
|
|
12
|
-
'disallowed',
|
|
13
|
-
'fail',
|
|
14
|
-
'failed',
|
|
15
|
-
'forbid',
|
|
16
|
-
'forbidden',
|
|
17
|
-
'reject',
|
|
18
|
-
'rejected',
|
|
19
|
-
'unsafe',
|
|
20
|
-
'violation',
|
|
21
|
-
]);
|
|
22
|
-
|
|
23
|
-
const REVIEW_DECISIONS = new Set([
|
|
24
|
-
'approval',
|
|
25
|
-
'approval-required',
|
|
26
|
-
'approval_required',
|
|
27
|
-
'approve',
|
|
28
|
-
'human-review',
|
|
29
|
-
'human_review',
|
|
30
|
-
'manual-review',
|
|
31
|
-
'manual_review',
|
|
32
|
-
'review',
|
|
33
|
-
'requires-approval',
|
|
34
|
-
'requires_approval',
|
|
35
|
-
'requires-review',
|
|
36
|
-
'requires_review',
|
|
37
|
-
]);
|
|
38
|
-
|
|
39
|
-
const ALLOW_DECISIONS = new Set([
|
|
40
|
-
'accept',
|
|
41
|
-
'accepted',
|
|
42
|
-
'allow',
|
|
43
|
-
'allowed',
|
|
44
|
-
'ok',
|
|
45
|
-
'pass',
|
|
46
|
-
'passed',
|
|
47
|
-
'permit',
|
|
48
|
-
'permitted',
|
|
49
|
-
'safe',
|
|
50
|
-
]);
|
|
51
|
-
|
|
52
|
-
function asObject(value) {
|
|
53
|
-
return value && typeof value === 'object' && !Array.isArray(value) ? value : {};
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
function asArray(value) {
|
|
57
|
-
return Array.isArray(value) ? value : [];
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
function firstString(...values) {
|
|
61
|
-
for (const value of values) {
|
|
62
|
-
const text = String(value || '').trim();
|
|
63
|
-
if (text) return text;
|
|
64
|
-
}
|
|
65
|
-
return '';
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
function normalizeDecisionToken(value) {
|
|
69
|
-
return String(value || '')
|
|
70
|
-
.trim()
|
|
71
|
-
.toLowerCase()
|
|
72
|
-
.replace(/\s+/g, '-');
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
function normalizeEvidence(value) {
|
|
76
|
-
const direct = asArray(value.evidence);
|
|
77
|
-
const citations = asArray(value.citations);
|
|
78
|
-
const violations = asArray(value.violations);
|
|
79
|
-
const reasons = asArray(value.reasons);
|
|
80
|
-
const reasoning = asArray(value.reasoning);
|
|
81
|
-
const threatTypes = asArray(value.threat_types || value.threatTypes)
|
|
82
|
-
.map((threatType) => ({
|
|
83
|
-
code: String(threatType || '').trim(),
|
|
84
|
-
message: `Threat type: ${String(threatType || '').trim()}`,
|
|
85
|
-
source: 'guardian',
|
|
86
|
-
severity: firstString(value.threat_level, value.threatLevel),
|
|
87
|
-
}));
|
|
88
|
-
return [...direct, ...citations, ...violations, ...reasons, ...reasoning, ...threatTypes]
|
|
89
|
-
.map((entry) => {
|
|
90
|
-
if (typeof entry === 'string') return { text: entry };
|
|
91
|
-
const object = asObject(entry);
|
|
92
|
-
if (!Object.keys(object).length) return null;
|
|
93
|
-
return {
|
|
94
|
-
id: firstString(object.id, object.ruleId, object.rule_id, object.code),
|
|
95
|
-
text: firstString(object.text, object.reason, object.message, object.description, object.title),
|
|
96
|
-
source: firstString(object.source, object.provider, object.policy),
|
|
97
|
-
severity: firstString(object.severity, object.level),
|
|
98
|
-
raw: object,
|
|
99
|
-
};
|
|
100
|
-
})
|
|
101
|
-
.filter(Boolean);
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
function extractPolicyDecision(input = {}) {
|
|
105
|
-
const event = asObject(input);
|
|
106
|
-
for (const candidate of [
|
|
107
|
-
event.policyDecision,
|
|
108
|
-
event.policy_decision,
|
|
109
|
-
event.guardrailResult,
|
|
110
|
-
event.guardrail_result,
|
|
111
|
-
event.result,
|
|
112
|
-
]) {
|
|
113
|
-
const object = asObject(candidate);
|
|
114
|
-
if (Object.keys(object).length) return object;
|
|
115
|
-
}
|
|
116
|
-
return event;
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
function classifyPolicyDecision(input = {}) {
|
|
120
|
-
const value = extractPolicyDecision(input);
|
|
121
|
-
const token = normalizeDecisionToken(firstString(
|
|
122
|
-
value.decision,
|
|
123
|
-
value.action,
|
|
124
|
-
value.status,
|
|
125
|
-
value.result,
|
|
126
|
-
value.verdict,
|
|
127
|
-
value.outcome,
|
|
128
|
-
value.effect,
|
|
129
|
-
value.recommended_action,
|
|
130
|
-
value.recommendedAction,
|
|
131
|
-
));
|
|
132
|
-
|
|
133
|
-
if (
|
|
134
|
-
value.allowed === false
|
|
135
|
-
|| value.is_safe === false
|
|
136
|
-
|| value.isSafe === false
|
|
137
|
-
|| value.accepted === false
|
|
138
|
-
|| value.blocked === true
|
|
139
|
-
|| value.denied === true
|
|
140
|
-
|| BLOCK_DECISIONS.has(token)
|
|
141
|
-
) {
|
|
142
|
-
return 'block';
|
|
143
|
-
}
|
|
144
|
-
if (
|
|
145
|
-
value.requiresApproval === true
|
|
146
|
-
|| value.requires_approval === true
|
|
147
|
-
|| value.reviewRequired === true
|
|
148
|
-
|| value.review_required === true
|
|
149
|
-
|| REVIEW_DECISIONS.has(token)
|
|
150
|
-
) {
|
|
151
|
-
return 'approval_required';
|
|
152
|
-
}
|
|
153
|
-
if (
|
|
154
|
-
value.allowed === true
|
|
155
|
-
|| value.is_safe === true
|
|
156
|
-
|| value.isSafe === true
|
|
157
|
-
|| value.accepted === true
|
|
158
|
-
|| ALLOW_DECISIONS.has(token)
|
|
159
|
-
) {
|
|
160
|
-
return 'allow';
|
|
161
|
-
}
|
|
162
|
-
return 'unknown';
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
function normalizePolicyDecision(input = {}, options = {}) {
|
|
166
|
-
const value = extractPolicyDecision(input);
|
|
167
|
-
const decision = classifyPolicyDecision(value);
|
|
168
|
-
const source = firstString(
|
|
169
|
-
options.source,
|
|
170
|
-
value.source,
|
|
171
|
-
value.provider,
|
|
172
|
-
value.engine,
|
|
173
|
-
value.policyEngine,
|
|
174
|
-
value.policy_engine,
|
|
175
|
-
'policy-engine'
|
|
176
|
-
);
|
|
177
|
-
const reason = firstString(
|
|
178
|
-
value.reason,
|
|
179
|
-
value.message,
|
|
180
|
-
value.explanation,
|
|
181
|
-
value.summary,
|
|
182
|
-
asArray(value.reasoning).join('; '),
|
|
183
|
-
asArray(value.reasons).join('; '),
|
|
184
|
-
decision === 'unknown' ? 'Policy engine returned an unknown decision; approval required before execution.' : ''
|
|
185
|
-
);
|
|
186
|
-
|
|
187
|
-
return {
|
|
188
|
-
allowed: decision === 'allow',
|
|
189
|
-
blocked: decision === 'block',
|
|
190
|
-
approvalRequired: decision === 'approval_required' || decision === 'unknown',
|
|
191
|
-
decision,
|
|
192
|
-
reason,
|
|
193
|
-
source,
|
|
194
|
-
confidence: Number.isFinite(Number(value.confidence)) ? Number(value.confidence) : null,
|
|
195
|
-
policyId: firstString(value.policyId, value.policy_id, value.ruleId, value.rule_id, value.id),
|
|
196
|
-
severity: firstString(value.severity, value.level, value.threat_level, value.threatLevel),
|
|
197
|
-
score: Number.isFinite(Number(value.score))
|
|
198
|
-
? Number(value.score)
|
|
199
|
-
: (Number.isFinite(Number(value.threat_score)) ? Number(value.threat_score) : null),
|
|
200
|
-
evidence: normalizeEvidence(value),
|
|
201
|
-
raw: value,
|
|
202
|
-
};
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
function normalizePolicyAction(input = {}) {
|
|
206
|
-
const event = asObject(input);
|
|
207
|
-
return {
|
|
208
|
-
...normalizeProviderAction({
|
|
209
|
-
...event,
|
|
210
|
-
provider: firstString(event.provider, event.agentRuntime, event.runtime, 'policy-engine'),
|
|
211
|
-
toolName: firstString(event.toolName, event.tool_name, event.name),
|
|
212
|
-
input: asObject(event.toolInput || event.input || event.arguments || event.args),
|
|
213
|
-
}),
|
|
214
|
-
policyContext: asObject(event.policyContext || event.policy_context),
|
|
215
|
-
};
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
function createPolicyEngineGuard({
|
|
219
|
-
policyCheck,
|
|
220
|
-
executeTool,
|
|
221
|
-
gateCheck,
|
|
222
|
-
onDecision,
|
|
223
|
-
source = 'policy-engine',
|
|
224
|
-
} = {}) {
|
|
225
|
-
if (typeof policyCheck !== 'function') {
|
|
226
|
-
throw new TypeError('createPolicyEngineGuard requires a policyCheck function');
|
|
227
|
-
}
|
|
228
|
-
if (typeof executeTool !== 'function') {
|
|
229
|
-
throw new TypeError('createPolicyEngineGuard requires an executeTool function');
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
return async function guardedPolicyTool(input = {}) {
|
|
233
|
-
const normalizedAction = normalizePolicyAction(input);
|
|
234
|
-
const policyDecision = normalizePolicyDecision(await policyCheck(normalizedAction), { source });
|
|
235
|
-
const gateDecision = typeof gateCheck === 'function'
|
|
236
|
-
? normalizePolicyDecision(await gateCheck({ normalizedAction, policyDecision }), { source: 'thumbgate' })
|
|
237
|
-
: null;
|
|
238
|
-
const effectiveDecision = gateDecision && !gateDecision.allowed ? gateDecision : policyDecision;
|
|
239
|
-
|
|
240
|
-
if (typeof onDecision === 'function') {
|
|
241
|
-
await onDecision({ normalizedAction, policyDecision, gateDecision, effectiveDecision });
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
if (!effectiveDecision.allowed) {
|
|
245
|
-
const error = new Error(effectiveDecision.reason || 'ThumbGate blocked this action before execution.');
|
|
246
|
-
error.code = effectiveDecision.approvalRequired ? 'THUMBGATE_APPROVAL_REQUIRED' : 'THUMBGATE_BLOCKED';
|
|
247
|
-
error.thumbgate = { normalizedAction, policyDecision, gateDecision, effectiveDecision };
|
|
248
|
-
throw error;
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
return executeTool(input, { normalizedAction, policyDecision, gateDecision, effectiveDecision });
|
|
252
|
-
};
|
|
253
|
-
}
|
|
254
|
-
|
|
255
|
-
module.exports = {
|
|
256
|
-
createPolicyEngineGuard,
|
|
257
|
-
extractPolicyDecision,
|
|
258
|
-
normalizePolicyAction,
|
|
259
|
-
normalizePolicyDecision,
|
|
260
|
-
};
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"cases": [
|
|
3
|
-
{
|
|
4
|
-
"id": "checkout-link-grounding",
|
|
5
|
-
"traceId": "trace_checkout_001",
|
|
6
|
-
"question": "Is the Pro checkout link working?",
|
|
7
|
-
"response": "The Pro checkout link is working because the checkout diagnostic confirms Stripe Pro checkout is reachable.",
|
|
8
|
-
"retrievedContexts": [
|
|
9
|
-
"Stripe Pro checkout diagnostic confirms the Pro checkout link is reachable and returns a valid checkout target.",
|
|
10
|
-
"The workflow sprint checkout is intake-led and should not expose a stale payment link."
|
|
11
|
-
],
|
|
12
|
-
"reference": "The Pro checkout link is reachable when the Stripe diagnostic passes."
|
|
13
|
-
},
|
|
14
|
-
{
|
|
15
|
-
"id": "letta-tool-gate",
|
|
16
|
-
"traceId": "trace_letta_001",
|
|
17
|
-
"question": "Should Letta execute a force push tool call?",
|
|
18
|
-
"response": "ThumbGate blocks force push before execution for Letta tool calls.",
|
|
19
|
-
"retrievedContexts": [
|
|
20
|
-
"ThumbGate's Letta adapter wraps Letta tool calls and runs gate-check before the executor is called.",
|
|
21
|
-
"Force push to main is a blocked high-risk git action."
|
|
22
|
-
],
|
|
23
|
-
"reference": "ThumbGate blocks high-risk Letta tool calls before execution."
|
|
24
|
-
}
|
|
25
|
-
]
|
|
26
|
-
}
|
package/bin/dashboard-cli.js
DELETED
package/commands/dashboard.md
DELETED
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: dashboard
|
|
3
|
-
description: Open the local HTTP dashboard for the current project in your web browser.
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# Open Dashboard
|
|
7
|
-
|
|
8
|
-
Open the local HTTP dashboard for the current project in your web browser.
|
|
9
|
-
|
|
10
|
-
## Instructions
|
|
11
|
-
Execute the following command in the project directory to open the browser dashboard scoped to the current repository:
|
|
12
|
-
```bash
|
|
13
|
-
thumbgate-dashboard
|
|
14
|
-
```
|
|
15
|
-
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: thumbgate-dashboard
|
|
3
|
-
description: Open the local HTTP dashboard for the current project in your web browser.
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# Open Scoped ThumbGate Dashboard
|
|
7
|
-
|
|
8
|
-
Open the local HTTP dashboard for the current project in your web browser.
|
|
9
|
-
|
|
10
|
-
## Instructions
|
|
11
|
-
Execute the following command in the project directory to open the browser dashboard:
|
|
12
|
-
```bash
|
|
13
|
-
thumbgate-dashboard
|
|
14
|
-
```
|
|
15
|
-
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 1,
|
|
3
|
-
"lessons": [
|
|
4
|
-
{
|
|
5
|
-
"id": "builtin-response-quality-shallow-positive-closeout",
|
|
6
|
-
"title": "MISTAKE: Assistant gave shallow acknowledgement after user said thumbs up",
|
|
7
|
-
"content": "What went wrong: Assistant gave shallow acknowledgement after positive feedback, such as thumbs up, perfect, good, or thank you, instead of staying quiet or giving an evidence checkpoint.\nHow to avoid: If the previous user message is positive feedback and the proposed final response is a low-value social closeout, block it and require either silence-level brevity or a compact evidence checkpoint with proof, result, residual risk, and next state.\nAction needed: Enforce this at the final-response boundary, not only as PreToolUse context.\nReasoning: Stored lessons and retrieval are not enough when the model can still ignore the lesson at generation time.",
|
|
8
|
-
"category": "error",
|
|
9
|
-
"importance": "high",
|
|
10
|
-
"tags": [
|
|
11
|
-
"feedback",
|
|
12
|
-
"negative",
|
|
13
|
-
"response-quality",
|
|
14
|
-
"final-response",
|
|
15
|
-
"positive-feedback",
|
|
16
|
-
"shallow-closeout",
|
|
17
|
-
"enforcement"
|
|
18
|
-
],
|
|
19
|
-
"timestamp": "2026-06-20T19:01:58.000Z",
|
|
20
|
-
"source": "packaged-builtin"
|
|
21
|
-
}
|
|
22
|
-
]
|
|
23
|
-
}
|
|
@@ -1,98 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 1,
|
|
3
|
-
"defaultLane": "local_classical",
|
|
4
|
-
"lanes": {
|
|
5
|
-
"deterministic": {
|
|
6
|
-
"description": "Regex, allow/deny lists, protected paths, branch rules, and exact policy checks. Always runs first.",
|
|
7
|
-
"maxLatencyMs": 25,
|
|
8
|
-
"cloudAllowed": false,
|
|
9
|
-
"useFor": [
|
|
10
|
-
"secret patterns",
|
|
11
|
-
"force-push",
|
|
12
|
-
"destructive SQL",
|
|
13
|
-
"protected operating files",
|
|
14
|
-
"known repeated command signatures"
|
|
15
|
-
]
|
|
16
|
-
},
|
|
17
|
-
"semantic_cache": {
|
|
18
|
-
"description": "Cached decision for semantically equivalent repeats where wording or PII changed but action meaning did not.",
|
|
19
|
-
"maxLatencyMs": 50,
|
|
20
|
-
"cloudAllowed": false,
|
|
21
|
-
"requiresProvenance": true,
|
|
22
|
-
"useFor": [
|
|
23
|
-
"semantic repeat blocks",
|
|
24
|
-
"cached approvals",
|
|
25
|
-
"prompt variants with same action meaning",
|
|
26
|
-
"PII-normalized duplicate checks"
|
|
27
|
-
]
|
|
28
|
-
},
|
|
29
|
-
"local_classical": {
|
|
30
|
-
"description": "Fast local text routing for high-volume, low-ambiguity feedback and gate labels.",
|
|
31
|
-
"maxLatencyMs": 250,
|
|
32
|
-
"cloudAllowed": false,
|
|
33
|
-
"minExamples": 40,
|
|
34
|
-
"useFor": [
|
|
35
|
-
"routine feedback triage",
|
|
36
|
-
"known error classes",
|
|
37
|
-
"low-risk support labels",
|
|
38
|
-
"bulk import classification"
|
|
39
|
-
]
|
|
40
|
-
},
|
|
41
|
-
"local_semantic": {
|
|
42
|
-
"description": "Local semantic/FTS recall for near-miss lessons, fuzzy duplicates, and low-data labels.",
|
|
43
|
-
"maxLatencyMs": 750,
|
|
44
|
-
"cloudAllowed": false,
|
|
45
|
-
"useFor": [
|
|
46
|
-
"near-duplicate lessons",
|
|
47
|
-
"sparse labels",
|
|
48
|
-
"cross-session recurrence",
|
|
49
|
-
"similar command intent"
|
|
50
|
-
]
|
|
51
|
-
},
|
|
52
|
-
"llm_judge": {
|
|
53
|
-
"description": "Budget-capped LLM review for ambiguous, high-value decisions where semantics matter.",
|
|
54
|
-
"maxLatencyMs": 10000,
|
|
55
|
-
"cloudAllowed": true,
|
|
56
|
-
"requiresEvidence": true,
|
|
57
|
-
"useFor": [
|
|
58
|
-
"ambiguous policy mapping",
|
|
59
|
-
"multi-document evidence review",
|
|
60
|
-
"rubric critique",
|
|
61
|
-
"structured dataset provenance review"
|
|
62
|
-
]
|
|
63
|
-
},
|
|
64
|
-
"rubric_gate": {
|
|
65
|
-
"description": "Completion blocker for failed rubrics, missing evidence, and loop-until-done harness caps.",
|
|
66
|
-
"maxLatencyMs": 500,
|
|
67
|
-
"cloudAllowed": false,
|
|
68
|
-
"requiresEvidence": true,
|
|
69
|
-
"useFor": [
|
|
70
|
-
"failed rubric criteria",
|
|
71
|
-
"missing done evidence",
|
|
72
|
-
"critic review failure",
|
|
73
|
-
"workflow completion claims"
|
|
74
|
-
]
|
|
75
|
-
},
|
|
76
|
-
"human_review": {
|
|
77
|
-
"description": "Stop and ask for approval when the action is high-risk, private, or too ambiguous for automated routing.",
|
|
78
|
-
"maxLatencyMs": null,
|
|
79
|
-
"cloudAllowed": false,
|
|
80
|
-
"requiresEvidence": true,
|
|
81
|
-
"useFor": [
|
|
82
|
-
"production credentials",
|
|
83
|
-
"customer data",
|
|
84
|
-
"regulated workflows",
|
|
85
|
-
"unbounded external posting",
|
|
86
|
-
"payment or refund changes"
|
|
87
|
-
]
|
|
88
|
-
}
|
|
89
|
-
},
|
|
90
|
-
"thresholds": {
|
|
91
|
-
"classicalMinExamples": 40,
|
|
92
|
-
"lowLatencyBudgetMs": 300,
|
|
93
|
-
"llmMinLatencyBudgetMs": 2000,
|
|
94
|
-
"highRiskAmbiguity": 0.65,
|
|
95
|
-
"mediumAmbiguity": 0.35,
|
|
96
|
-
"largeBatchRows": 50
|
|
97
|
-
}
|
|
98
|
-
}
|
|
@@ -1,61 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"$comment": "Sentinel manifest for post-deploy verification of top-level marketing pages. Each entry is curled against the live production URL after every push to main; if the sentinel string is missing from the response body, the deploy is flagged as broken and the workflow comments on the associated PR. Adding a new top-level marketing page? Add it here so the deploy-verify workflow catches a route regression before a real visitor does. Keep sentinel strings short and stable (visible body copy, not styling classes or hashed assets).",
|
|
3
|
-
"version": 1,
|
|
4
|
-
"pages": [
|
|
5
|
-
{
|
|
6
|
-
"route": "/",
|
|
7
|
-
"sentinel": "Stop paying for the same AI mistake twice",
|
|
8
|
-
"description": "Home page hero (lifeblood — never regress)"
|
|
9
|
-
},
|
|
10
|
-
{
|
|
11
|
-
"route": "/pro",
|
|
12
|
-
"sentinel": "ThumbGate Pro",
|
|
13
|
-
"description": "Pro landing page"
|
|
14
|
-
},
|
|
15
|
-
{
|
|
16
|
-
"route": "/dashboard",
|
|
17
|
-
"sentinel": "ThumbGate Dashboard",
|
|
18
|
-
"description": "Dashboard demo (already enforced by /dashboard step; included here for symmetry with PR comment surface)"
|
|
19
|
-
},
|
|
20
|
-
{
|
|
21
|
-
"route": "/federal",
|
|
22
|
-
"sentinel": "ThumbGate",
|
|
23
|
-
"description": "Federal lead-gen page (SBIR / GSA arrivals)"
|
|
24
|
-
},
|
|
25
|
-
{
|
|
26
|
-
"route": "/numbers",
|
|
27
|
-
"sentinel": "ThumbGate",
|
|
28
|
-
"description": "First-party numbers / data transparency page"
|
|
29
|
-
},
|
|
30
|
-
{
|
|
31
|
-
"route": "/ai-malpractice-prevention",
|
|
32
|
-
"sentinel": "Pre-Execution Controls for Legal AI Agents",
|
|
33
|
-
"description": "Legal AI intake risk-controls page for law-firm pilot conversations"
|
|
34
|
-
},
|
|
35
|
-
{
|
|
36
|
-
"route": "/learn/background-agent-control-layer",
|
|
37
|
-
"sentinel": "Background agents need a control layer outside the model",
|
|
38
|
-
"description": "Background-agent AI-SDLC control-layer positioning page"
|
|
39
|
-
},
|
|
40
|
-
{
|
|
41
|
-
"route": "/llm-context.md",
|
|
42
|
-
"sentinel": "## What ThumbGate Is",
|
|
43
|
-
"description": "Canonical declarative summary AI crawlers read"
|
|
44
|
-
},
|
|
45
|
-
{
|
|
46
|
-
"route": "/robots.txt",
|
|
47
|
-
"sentinel": "User-agent",
|
|
48
|
-
"description": "Crawl directives (mandatory per Google's 2026-05-15 AI features guide)"
|
|
49
|
-
},
|
|
50
|
-
{
|
|
51
|
-
"route": "/sitemap.xml",
|
|
52
|
-
"sentinel": "<urlset",
|
|
53
|
-
"description": "XML sitemap for search-engine discoverability"
|
|
54
|
-
},
|
|
55
|
-
{
|
|
56
|
-
"route": "/about",
|
|
57
|
-
"sentinel": "Igor Ganapolsky",
|
|
58
|
-
"description": "About page for GEO discoverability"
|
|
59
|
-
}
|
|
60
|
-
]
|
|
61
|
-
}
|