thumbgate 1.27.18 → 1.27.20

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (170) hide show
  1. package/.claude/commands/dashboard.md +15 -0
  2. package/.claude/commands/thumbgate-blocked.md +27 -0
  3. package/.claude/commands/thumbgate-dashboard.md +15 -0
  4. package/.claude/commands/thumbgate-doctor.md +30 -0
  5. package/.claude/commands/thumbgate-guard.md +36 -0
  6. package/.claude/commands/thumbgate-protect.md +30 -0
  7. package/.claude/commands/thumbgate-rules.md +30 -0
  8. package/.claude-plugin/plugin.json +4 -3
  9. package/.well-known/agentic-verify.txt +1 -0
  10. package/.well-known/llms.txt +33 -12
  11. package/.well-known/mcp/server-card.json +8 -8
  12. package/README.md +246 -30
  13. package/adapters/claude/.mcp.json +2 -2
  14. package/adapters/codex/config.toml +2 -2
  15. package/adapters/gcp/dfcx-webhook-gate.js +295 -0
  16. package/adapters/gemini/function-declarations.json +1 -0
  17. package/adapters/letta/README.md +41 -0
  18. package/adapters/letta/thumbgate-letta-adapter.js +133 -0
  19. package/adapters/mcp/server-stdio.js +263 -11
  20. package/adapters/opencode/opencode.json +1 -1
  21. package/adapters/policy-engine/ethicore-guardian-client.js +68 -0
  22. package/adapters/policy-engine/thumbgate-policy-engine-adapter.js +260 -0
  23. package/bench/observability-eval-suite.json +26 -0
  24. package/bench/thumbgate-bench.json +2 -2
  25. package/bin/cli.js +1456 -122
  26. package/bin/dashboard-cli.js +7 -0
  27. package/bin/postinstall.js +11 -27
  28. package/commands/dashboard.md +15 -0
  29. package/commands/thumbgate-dashboard.md +15 -0
  30. package/config/gate-classifier-routing.json +98 -0
  31. package/config/gate-templates.json +216 -0
  32. package/config/gates/claim-verification.json +12 -0
  33. package/config/gates/default.json +31 -2
  34. package/config/github-about.json +2 -2
  35. package/config/mcp-allowlists.json +23 -13
  36. package/config/merge-quality-checks.json +0 -1
  37. package/config/model-candidates.json +121 -6
  38. package/config/post-deploy-marketing-pages.json +80 -0
  39. package/config/tessl-tiles.json +1 -3
  40. package/openapi/openapi.yaml +12 -0
  41. package/package.json +225 -100
  42. package/public/about.html +162 -0
  43. package/public/agent-manager.html +179 -0
  44. package/public/agents-cost-savings.html +153 -0
  45. package/public/ai-malpractice-prevention.html +818 -0
  46. package/public/assets/brand/github-social-preview.png +0 -0
  47. package/public/assets/brand/thumbgate-icon-512.png +0 -0
  48. package/public/assets/brand/thumbgate-icon-pro-512.png +0 -0
  49. package/public/assets/brand/thumbgate-icon-team-512.png +0 -0
  50. package/public/assets/brand/thumbgate-logo-1200x360.png +0 -0
  51. package/public/assets/brand/thumbgate-logo-transparent.svg +28 -0
  52. package/public/assets/brand/thumbgate-mark-inline-v3.svg +18 -0
  53. package/public/assets/brand/thumbgate-mark-pro.svg +23 -0
  54. package/public/assets/brand/thumbgate-mark-team.svg +26 -0
  55. package/public/assets/brand/thumbgate-mark.svg +21 -0
  56. package/public/assets/brand/thumbgate-wordmark.svg +20 -0
  57. package/public/assets/claude-thumbgate-statusbar.svg +8 -0
  58. package/public/assets/codex-thumbgate-statusbar-test.svg +9 -0
  59. package/public/assets/legal-intake-control-flow.svg +66 -0
  60. package/public/blog.html +4 -4
  61. package/public/brand/thumbgate-mark.svg +19 -0
  62. package/public/brand/thumbgate-og.svg +16 -0
  63. package/public/chatgpt-app.html +330 -0
  64. package/public/codex-enterprise.html +123 -0
  65. package/public/codex-plugin.html +72 -20
  66. package/public/compare.html +31 -8
  67. package/public/dashboard.html +930 -166
  68. package/public/diagnostic.html +345 -0
  69. package/public/federal.html +2 -2
  70. package/public/guide.html +33 -13
  71. package/public/index.html +469 -111
  72. package/public/install.html +193 -0
  73. package/public/js/buyer-intent.js +672 -0
  74. package/public/learn.html +183 -18
  75. package/public/lessons.html +168 -10
  76. package/public/numbers.html +7 -7
  77. package/public/pricing.html +399 -0
  78. package/public/pro.html +34 -11
  79. package/scripts/action-receipts.js +324 -0
  80. package/scripts/activation-quickstart.js +187 -0
  81. package/scripts/agent-memory-lifecycle.js +211 -0
  82. package/scripts/agent-operations-planner.js +621 -0
  83. package/scripts/agent-readiness.js +20 -3
  84. package/scripts/agent-reward-model.js +53 -1
  85. package/scripts/ai-component-inventory.js +367 -0
  86. package/scripts/async-eval-observability.js +236 -0
  87. package/scripts/audit.js +65 -0
  88. package/scripts/auto-promote-gates.js +82 -10
  89. package/scripts/auto-wire-hooks.js +14 -0
  90. package/scripts/aws-blocks-guardrails.js +272 -0
  91. package/scripts/billing.js +93 -1
  92. package/scripts/bot-detection.js +61 -3
  93. package/scripts/build-metadata.js +50 -10
  94. package/scripts/classifier-routing.js +130 -0
  95. package/scripts/cli-feedback.js +4 -2
  96. package/scripts/cli-schema.js +97 -0
  97. package/scripts/cli-telemetry.js +6 -1
  98. package/scripts/commercial-offer.js +82 -2
  99. package/scripts/context-manager.js +74 -6
  100. package/scripts/dashboard-chat.js +332 -0
  101. package/scripts/dashboard.js +68 -2
  102. package/scripts/export-databricks-bundle.js +5 -1
  103. package/scripts/export-dpo-pairs.js +7 -2
  104. package/scripts/feedback-aggregate.js +281 -0
  105. package/scripts/feedback-loop.js +123 -1
  106. package/scripts/feedback-quality.js +87 -0
  107. package/scripts/feedback-sanitizer.js +105 -0
  108. package/scripts/filesystem-search.js +35 -10
  109. package/scripts/gate-stats.js +89 -0
  110. package/scripts/gates-engine.js +1176 -85
  111. package/scripts/gemini-embedding-policy.js +2 -1
  112. package/scripts/hook-runtime.js +20 -14
  113. package/scripts/hook-stop-anti-claim.js +301 -0
  114. package/scripts/hook-thumbgate-cache-updater.js +18 -2
  115. package/scripts/hybrid-feedback-context.js +142 -7
  116. package/scripts/install-shim.js +87 -0
  117. package/scripts/lesson-inference.js +8 -3
  118. package/scripts/lesson-search.js +17 -1
  119. package/scripts/license.js +10 -10
  120. package/scripts/llm-client.js +169 -4
  121. package/scripts/local-model-profile.js +15 -8
  122. package/scripts/mcp-config.js +7 -1
  123. package/scripts/mcp-oauth.js +293 -0
  124. package/scripts/memory-scope-readiness.js +159 -0
  125. package/scripts/meta-agent-loop.js +36 -0
  126. package/scripts/noop-detect.js +285 -0
  127. package/scripts/operational-integrity.js +39 -5
  128. package/scripts/oss-pr-opportunity-scout.js +35 -5
  129. package/scripts/parallel-workflow-orchestrator.js +293 -0
  130. package/scripts/plan-gate.js +243 -0
  131. package/scripts/plausible-domain-config.js +99 -0
  132. package/scripts/plausible-server-events.js +9 -6
  133. package/scripts/pro-local-dashboard.js +4 -4
  134. package/scripts/proxy-pointer-rag-guardrails.js +42 -1
  135. package/scripts/published-cli.js +0 -8
  136. package/scripts/qa-scenario-planner.js +136 -0
  137. package/scripts/rate-limiter.js +64 -13
  138. package/scripts/repeat-metric.js +137 -0
  139. package/scripts/secret-fixture-tokens.js +61 -0
  140. package/scripts/secret-redaction.js +166 -0
  141. package/scripts/secret-scanner.js +44 -5
  142. package/scripts/security-scanner.js +260 -10
  143. package/scripts/self-distill-agent.js +3 -1
  144. package/scripts/self-harness-optimizer.js +141 -0
  145. package/scripts/self-healing-check.js +193 -0
  146. package/scripts/self-protection.js +90 -0
  147. package/scripts/seo-gsd.js +916 -7
  148. package/scripts/silent-failure-cluster.js +531 -0
  149. package/scripts/statusline-cache-path.js +17 -2
  150. package/scripts/statusline-cache-read.js +57 -0
  151. package/scripts/statusline-local-stats.js +9 -1
  152. package/scripts/statusline-meta.js +28 -2
  153. package/scripts/statusline.sh +20 -4
  154. package/scripts/sync-telemetry-from-prod.js +374 -0
  155. package/scripts/telemetry-analytics.js +357 -0
  156. package/scripts/thompson-sampling.js +31 -10
  157. package/scripts/thumbgate-bench.js +16 -1
  158. package/scripts/thumbgate-search.js +85 -19
  159. package/scripts/tool-contract-validator.js +76 -0
  160. package/scripts/tool-registry.js +169 -1
  161. package/scripts/trajectory-scorer.js +63 -0
  162. package/scripts/vector-store.js +45 -0
  163. package/scripts/verify-marketing-pages-deployed.js +212 -0
  164. package/scripts/visitor-journey.js +172 -0
  165. package/scripts/workflow-sentinel.js +286 -53
  166. package/scripts/workspace-evolver.js +62 -2
  167. package/src/api/server.js +2683 -319
  168. package/.claude-plugin/marketplace.json +0 -85
  169. package/adapters/chatgpt/openapi.yaml +0 -1695
  170. package/scripts/bot-detector.js +0 -50
@@ -2,6 +2,40 @@
2
2
  'use strict';
3
3
 
4
4
  const MEMORY_TYPES = new Set(['episodic', 'semantic', 'procedural', 'preference', 'working']);
5
+ const MEMORY_SCOPES = new Set(['task', 'session', 'user', 'project', 'org']);
6
+ const HIGH_RISK_TERMS = new Set([
7
+ 'billing',
8
+ 'checkout',
9
+ 'compliance',
10
+ 'credential',
11
+ 'data-loss',
12
+ 'deploy',
13
+ 'deployment',
14
+ 'git',
15
+ 'payment',
16
+ 'production',
17
+ 'release',
18
+ 'secret',
19
+ 'security',
20
+ 'stripe',
21
+ 'verification',
22
+ ]);
23
+ const KNOWN_ENTITY_PATTERNS = [
24
+ ['Claude Code', /\bclaude\s+code\b/i, 'agent'],
25
+ ['Codex', /\bcodex\b/i, 'agent'],
26
+ ['Cursor', /\bcursor\b/i, 'agent'],
27
+ ['Gemini CLI', /\bgemini\s+cli\b/i, 'agent'],
28
+ ['MCP', /\bmcp\b/i, 'protocol'],
29
+ ['Stripe', /\bstripe\b/i, 'service'],
30
+ ['GitHub', /\bgithub\b|\bgh\s+/i, 'service'],
31
+ ['Railway', /\brailway\b/i, 'service'],
32
+ ['Plausible', /\bplausible\b/i, 'service'],
33
+ ['PostHog', /\bposthog\b/i, 'service'],
34
+ ['SQLite', /\bsqlite\b|\bfts5\b/i, 'storage'],
35
+ ['LanceDB', /\blancedb\b/i, 'storage'],
36
+ ['Docker', /\bdocker\b/i, 'runtime'],
37
+ ['npm', /\bnpm\b|\bnpx\b/i, 'runtime'],
38
+ ];
5
39
 
6
40
  function normalizeText(value) {
7
41
  if (value === undefined || value === null) return '';
@@ -13,6 +47,178 @@ function normalizeMemoryType(value) {
13
47
  return MEMORY_TYPES.has(normalized) ? normalized : 'episodic';
14
48
  }
15
49
 
50
+ function tokenize(value) {
51
+ return normalizeText(value)
52
+ .toLowerCase()
53
+ .split(/[^a-z0-9_.:/-]+/)
54
+ .filter(Boolean);
55
+ }
56
+
57
+ function uniqueByName(entities) {
58
+ const seen = new Set();
59
+ return entities.filter((entity) => {
60
+ const key = normalizeText(entity.name).toLowerCase();
61
+ if (!key || seen.has(key)) return false;
62
+ seen.add(key);
63
+ return true;
64
+ });
65
+ }
66
+
67
+ function collectMemoryText(memory = {}) {
68
+ return [
69
+ memory.title,
70
+ memory.content,
71
+ memory.context,
72
+ memory.whatWentWrong,
73
+ memory.whatToChange,
74
+ memory.whatWorked,
75
+ memory.domain,
76
+ memory.skill,
77
+ Array.isArray(memory.tags) ? memory.tags.join(' ') : memory.tags,
78
+ ].filter(Boolean).join(' ');
79
+ }
80
+
81
+ function extractMemoryEntities(memory = {}) {
82
+ const text = collectMemoryText(memory);
83
+ const entities = [];
84
+
85
+ for (const [name, pattern, type] of KNOWN_ENTITY_PATTERNS) {
86
+ if (pattern.test(text)) entities.push({ name, type });
87
+ }
88
+
89
+ const commandMatches = text.match(/`([^`]+)`/g) || [];
90
+ for (const match of commandMatches) {
91
+ const command = match.slice(1, -1).trim();
92
+ if (/^(git|npm|npx|node|gh|curl|docker|python|pytest|stripe)\b/i.test(command)) {
93
+ entities.push({ name: command, type: 'command' });
94
+ } else if (/[./-]/.test(command)) {
95
+ entities.push({ name: command, type: 'path' });
96
+ }
97
+ }
98
+
99
+ const pathMatches = text.match(/\b(?:[a-z0-9_-]+\/)+[a-z0-9_.-]+\b/gi) || [];
100
+ for (const filePath of pathMatches.slice(0, 8)) {
101
+ entities.push({ name: filePath, type: 'path' });
102
+ }
103
+
104
+ return uniqueByName(entities).slice(0, 16);
105
+ }
106
+
107
+ function inferMemoryScope(memory = {}) {
108
+ const explicit = normalizeText(memory.scope || memory.memoryScope).toLowerCase();
109
+ if (MEMORY_SCOPES.has(explicit)) return explicit;
110
+
111
+ const text = collectMemoryText(memory).toLowerCase();
112
+ const tags = new Set(Array.isArray(memory.tags) ? memory.tags.map((tag) => normalizeText(tag).toLowerCase()) : []);
113
+
114
+ if (tags.has('preference') || /\b(prefer|style|tone|my preference|user preference)\b/.test(text)) return 'user';
115
+ if (tags.has('org') || tags.has('team') || /\b(enterprise|seat|team|shared|org|compliance|policy|approval)\b/.test(text)) return 'org';
116
+ if (tags.has('repo') || tags.has('project') || tags.has('release') || tags.has('deployment')
117
+ || /\b(repo|repository|branch|ci|pull request|github|deploy|production|release|publish)\b/.test(text)) return 'project';
118
+ if (tags.has('session') || /\b(this session|current session|today|right now)\b/.test(text)) return 'session';
119
+ return 'task';
120
+ }
121
+
122
+ function scoreMemoryDecay(memory = {}, options = {}) {
123
+ const nowMs = options.now ? new Date(options.now).getTime() : Date.now();
124
+ const timestampMs = memory.timestamp ? new Date(memory.timestamp).getTime() : NaN;
125
+ const ageDays = Number.isFinite(timestampMs)
126
+ ? Math.max(0, (nowMs - timestampMs) / (1000 * 60 * 60 * 24))
127
+ : null;
128
+ const textTokens = new Set(tokenize(collectMemoryText(memory)));
129
+ const tags = Array.isArray(memory.tags) ? memory.tags.map((tag) => normalizeText(tag).toLowerCase()) : [];
130
+ const highRisk = tags.some((tag) => HIGH_RISK_TERMS.has(tag))
131
+ || [...textTokens].some((token) => HIGH_RISK_TERMS.has(token))
132
+ || ['critical', 'high'].includes(normalizeText(memory.importance).toLowerCase());
133
+
134
+ if (highRisk) {
135
+ return {
136
+ state: 'sticky',
137
+ ageDays,
138
+ score: 1,
139
+ reason: 'high-risk memories stay retrievable until explicitly retired',
140
+ };
141
+ }
142
+ if (ageDays === null) {
143
+ return {
144
+ state: 'review',
145
+ ageDays,
146
+ score: 0.6,
147
+ reason: 'memory has no timestamp, so it needs review before durable promotion',
148
+ };
149
+ }
150
+ if (ageDays > 180) {
151
+ return {
152
+ state: 'archive_candidate',
153
+ ageDays,
154
+ score: 0.2,
155
+ reason: 'old low-risk memory should be consolidated or archived',
156
+ };
157
+ }
158
+ if (ageDays > 60) {
159
+ return {
160
+ state: 'review',
161
+ ageDays,
162
+ score: 0.55,
163
+ reason: 'older low-risk memory should be refreshed before it dominates recall',
164
+ };
165
+ }
166
+ return {
167
+ state: 'active',
168
+ ageDays,
169
+ score: 0.85,
170
+ reason: 'recent memory remains eligible for recall',
171
+ };
172
+ }
173
+
174
+ function scoreHybridMemoryMatch(query, memory = {}, options = {}) {
175
+ const queryTokens = new Set(tokenize(query));
176
+ const memoryTokens = new Set(tokenize(collectMemoryText(memory)));
177
+ const queryText = normalizeText(query).toLowerCase();
178
+ const memoryText = collectMemoryText(memory).toLowerCase();
179
+ const memoryEntities = extractMemoryEntities(memory);
180
+ const queryEntityNames = extractMemoryEntities({ content: query }).map((entity) => entity.name.toLowerCase());
181
+
182
+ let lexicalMatches = 0;
183
+ for (const token of queryTokens) {
184
+ if (memoryTokens.has(token)) lexicalMatches++;
185
+ }
186
+ const lexicalScore = queryTokens.size > 0 ? lexicalMatches / queryTokens.size : 0;
187
+ const phraseScore = queryText && memoryText.includes(queryText) ? 0.35 : 0;
188
+ const entityMatches = memoryEntities.filter((entity) => queryEntityNames.includes(entity.name.toLowerCase()));
189
+ const entityScore = queryEntityNames.length > 0 ? entityMatches.length / queryEntityNames.length : 0;
190
+ const decay = scoreMemoryDecay(memory, options);
191
+ const lifecycleScore = decay.state === 'archive_candidate' ? -0.15 : decay.state === 'sticky' ? 0.12 : 0;
192
+ const score = lexicalScore + phraseScore + (entityScore * 0.45) + lifecycleScore;
193
+
194
+ return {
195
+ score: Number(Math.max(0, score).toFixed(4)),
196
+ lexicalScore: Number(lexicalScore.toFixed(4)),
197
+ entityScore: Number(entityScore.toFixed(4)),
198
+ matchedEntities: entityMatches,
199
+ decayState: decay.state,
200
+ };
201
+ }
202
+
203
+ function buildMemoryLifecycleView(memory = {}, options = {}) {
204
+ const scope = inferMemoryScope(memory);
205
+ const entities = extractMemoryEntities(memory);
206
+ const decay = scoreMemoryDecay(memory, options);
207
+ const retrieval = scoreHybridMemoryMatch(options.query || '', memory, options);
208
+
209
+ return {
210
+ scope,
211
+ entities,
212
+ decay,
213
+ retrievalHints: {
214
+ hybridScore: retrieval.score,
215
+ lexicalScore: retrieval.lexicalScore,
216
+ entityScore: retrieval.entityScore,
217
+ matchedEntities: retrieval.matchedEntities,
218
+ },
219
+ };
220
+ }
221
+
16
222
  function buildMemoryLifecyclePolicy(input = {}) {
17
223
  return {
18
224
  generatedAt: normalizeText(input.generatedAt) || new Date().toISOString(),
@@ -91,6 +297,11 @@ function evaluateMemoryPromotion(memory = {}, policy = buildMemoryLifecyclePolic
91
297
 
92
298
  module.exports = {
93
299
  buildMemoryLifecyclePolicy,
300
+ buildMemoryLifecycleView,
94
301
  evaluateMemoryPromotion,
302
+ extractMemoryEntities,
303
+ inferMemoryScope,
95
304
  normalizeMemoryType,
305
+ scoreHybridMemoryMatch,
306
+ scoreMemoryDecay,
96
307
  };