thumbgate 1.27.16 → 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.
Files changed (165) hide show
  1. package/.claude-plugin/marketplace.json +85 -0
  2. package/.claude-plugin/plugin.json +3 -4
  3. package/.well-known/llms.txt +12 -33
  4. package/.well-known/mcp/server-card.json +8 -8
  5. package/README.md +30 -215
  6. package/adapters/chatgpt/openapi.yaml +1695 -0
  7. package/adapters/claude/.mcp.json +2 -2
  8. package/adapters/gemini/function-declarations.json +0 -1
  9. package/adapters/mcp/server-stdio.js +11 -263
  10. package/adapters/opencode/opencode.json +1 -1
  11. package/bench/thumbgate-bench.json +2 -2
  12. package/bin/cli.js +122 -1421
  13. package/bin/postinstall.js +27 -11
  14. package/config/gate-templates.json +0 -216
  15. package/config/gates/claim-verification.json +0 -12
  16. package/config/gates/default.json +2 -31
  17. package/config/github-about.json +2 -2
  18. package/config/mcp-allowlists.json +13 -23
  19. package/config/merge-quality-checks.json +1 -0
  20. package/config/model-candidates.json +6 -121
  21. package/openapi/openapi.yaml +0 -12
  22. package/package.json +98 -228
  23. package/public/blog.html +4 -4
  24. package/public/codex-plugin.html +20 -72
  25. package/public/compare.html +8 -31
  26. package/public/dashboard.html +166 -930
  27. package/public/federal.html +2 -2
  28. package/public/guide.html +9 -33
  29. package/public/index.html +116 -495
  30. package/public/learn.html +18 -191
  31. package/public/lessons.html +10 -168
  32. package/public/numbers.html +7 -7
  33. package/public/pro.html +11 -34
  34. package/scripts/agent-memory-lifecycle.js +0 -211
  35. package/scripts/agent-readiness.js +3 -167
  36. package/scripts/agent-reward-model.js +1 -53
  37. package/scripts/auto-promote-gates.js +10 -82
  38. package/scripts/auto-wire-hooks.js +0 -14
  39. package/scripts/billing.js +1 -93
  40. package/scripts/build-metadata.js +10 -50
  41. package/scripts/cli-feedback.js +6 -18
  42. package/scripts/cli-schema.js +0 -90
  43. package/scripts/cli-telemetry.js +1 -6
  44. package/scripts/commercial-offer.js +2 -82
  45. package/scripts/context-manager.js +6 -74
  46. package/scripts/dashboard.js +2 -68
  47. package/scripts/durability/step.js +3 -3
  48. package/scripts/export-databricks-bundle.js +1 -5
  49. package/scripts/export-dpo-pairs.js +2 -7
  50. package/scripts/feedback-loop.js +1 -123
  51. package/scripts/feedback-quality.js +0 -87
  52. package/scripts/filesystem-search.js +10 -35
  53. package/scripts/gate-stats.js +0 -89
  54. package/scripts/gates-engine.js +85 -1105
  55. package/scripts/gemini-embedding-policy.js +1 -2
  56. package/scripts/hook-runtime.js +14 -20
  57. package/scripts/hook-thumbgate-cache-updater.js +2 -18
  58. package/scripts/hybrid-feedback-context.js +7 -142
  59. package/scripts/lesson-inference.js +3 -8
  60. package/scripts/lesson-search.js +1 -17
  61. package/scripts/license.js +1 -0
  62. package/scripts/llm-client.js +9 -390
  63. package/scripts/local-model-profile.js +8 -15
  64. package/scripts/memory-scope-readiness.js +0 -159
  65. package/scripts/meta-agent-loop.js +0 -36
  66. package/scripts/operational-integrity.js +5 -39
  67. package/scripts/oss-pr-opportunity-scout.js +5 -35
  68. package/scripts/plausible-server-events.js +6 -9
  69. package/scripts/pro-local-dashboard.js +4 -4
  70. package/scripts/proxy-pointer-rag-guardrails.js +1 -42
  71. package/scripts/rate-limiter.js +13 -64
  72. package/scripts/secret-scanner.js +5 -44
  73. package/scripts/security-scanner.js +10 -260
  74. package/scripts/self-distill-agent.js +1 -3
  75. package/scripts/seo-gsd.js +2 -916
  76. package/scripts/statusline-cache-path.js +2 -17
  77. package/scripts/statusline-local-stats.js +1 -9
  78. package/scripts/statusline-meta.js +2 -28
  79. package/scripts/statusline.sh +4 -20
  80. package/scripts/telemetry-analytics.js +0 -357
  81. package/scripts/thompson-sampling.js +10 -31
  82. package/scripts/thumbgate-bench.js +1 -16
  83. package/scripts/thumbgate-search.js +19 -85
  84. package/scripts/tool-registry.js +1 -169
  85. package/scripts/vector-store.js +0 -45
  86. package/scripts/workflow-sentinel.js +53 -286
  87. package/scripts/workspace-evolver.js +2 -62
  88. package/src/api/server.js +290 -2578
  89. package/.claude/commands/dashboard.md +0 -15
  90. package/.claude/commands/thumbgate-blocked.md +0 -27
  91. package/.claude/commands/thumbgate-dashboard.md +0 -15
  92. package/.claude/commands/thumbgate-doctor.md +0 -30
  93. package/.claude/commands/thumbgate-guard.md +0 -36
  94. package/.claude/commands/thumbgate-protect.md +0 -30
  95. package/.claude/commands/thumbgate-rules.md +0 -30
  96. package/.well-known/agentic-verify.txt +0 -1
  97. package/adapters/gcp/dfcx-webhook-gate.js +0 -295
  98. package/adapters/letta/README.md +0 -41
  99. package/adapters/letta/thumbgate-letta-adapter.js +0 -133
  100. package/adapters/policy-engine/ethicore-guardian-client.js +0 -68
  101. package/adapters/policy-engine/thumbgate-policy-engine-adapter.js +0 -260
  102. package/bench/observability-eval-suite.json +0 -26
  103. package/bin/dashboard-cli.js +0 -7
  104. package/commands/dashboard.md +0 -15
  105. package/commands/thumbgate-dashboard.md +0 -15
  106. package/config/builtin-lessons.json +0 -23
  107. package/config/gate-classifier-routing.json +0 -98
  108. package/config/post-deploy-marketing-pages.json +0 -61
  109. package/public/about.html +0 -162
  110. package/public/agent-manager.html +0 -179
  111. package/public/agents-cost-savings.html +0 -153
  112. package/public/ai-malpractice-prevention.html +0 -818
  113. package/public/assets/brand/github-social-preview.png +0 -0
  114. package/public/assets/brand/thumbgate-icon-512.png +0 -0
  115. package/public/assets/brand/thumbgate-icon-pro-512.png +0 -0
  116. package/public/assets/brand/thumbgate-icon-team-512.png +0 -0
  117. package/public/assets/brand/thumbgate-logo-1200x360.png +0 -0
  118. package/public/assets/brand/thumbgate-logo-transparent.svg +0 -22
  119. package/public/assets/brand/thumbgate-mark-inline-v3.svg +0 -19
  120. package/public/assets/brand/thumbgate-mark-pro.svg +0 -23
  121. package/public/assets/brand/thumbgate-mark-team.svg +0 -26
  122. package/public/assets/brand/thumbgate-mark.svg +0 -21
  123. package/public/assets/brand/thumbgate-wordmark.svg +0 -20
  124. package/public/assets/claude-thumbgate-statusbar.svg +0 -8
  125. package/public/assets/codex-thumbgate-statusbar-test.svg +0 -9
  126. package/public/assets/legal-intake-control-flow.svg +0 -66
  127. package/public/brand/thumbgate-mark.svg +0 -19
  128. package/public/brand/thumbgate-og.svg +0 -16
  129. package/public/chatgpt-app.html +0 -330
  130. package/public/codex-enterprise.html +0 -123
  131. package/public/js/buyer-intent.js +0 -672
  132. package/public/pricing.html +0 -399
  133. package/scripts/action-receipts.js +0 -324
  134. package/scripts/activation-quickstart.js +0 -187
  135. package/scripts/agent-operations-planner.js +0 -621
  136. package/scripts/ai-component-inventory.js +0 -367
  137. package/scripts/async-eval-observability.js +0 -236
  138. package/scripts/audit.js +0 -65
  139. package/scripts/aws-blocks-guardrails.js +0 -228
  140. package/scripts/classifier-routing.js +0 -130
  141. package/scripts/dashboard-chat.js +0 -332
  142. package/scripts/feedback-aggregate.js +0 -281
  143. package/scripts/feedback-sanitizer.js +0 -105
  144. package/scripts/hob-pack.js +0 -591
  145. package/scripts/hook-stop-anti-claim.js +0 -301
  146. package/scripts/install-shim.js +0 -87
  147. package/scripts/mcp-oauth.js +0 -293
  148. package/scripts/noop-detect.js +0 -285
  149. package/scripts/omlx-smoke.js +0 -192
  150. package/scripts/parallel-workflow-orchestrator.js +0 -293
  151. package/scripts/plan-gate.js +0 -243
  152. package/scripts/plausible-domain-config.js +0 -99
  153. package/scripts/qa-scenario-planner.js +0 -136
  154. package/scripts/repeat-metric.js +0 -137
  155. package/scripts/secret-fixture-tokens.js +0 -61
  156. package/scripts/secret-redaction.js +0 -166
  157. package/scripts/self-harness-optimizer.js +0 -141
  158. package/scripts/self-healing-check.js +0 -193
  159. package/scripts/silent-failure-cluster.js +0 -531
  160. package/scripts/statusline-cache-read.js +0 -57
  161. package/scripts/sync-telemetry-from-prod.js +0 -374
  162. package/scripts/tool-contract-validator.js +0 -76
  163. package/scripts/trajectory-scorer.js +0 -63
  164. package/scripts/verify-marketing-pages-deployed.js +0 -195
  165. package/scripts/visitor-journey.js +0 -172
@@ -2,13 +2,13 @@
2
2
  "mcpServers": {
3
3
  "thumbgate": {
4
4
  "command": "npx",
5
- "args": ["--yes", "--package", "thumbgate@1.27.16", "thumbgate", "serve"]
5
+ "args": ["--yes", "--package", "thumbgate@1.20.0", "thumbgate", "serve"]
6
6
  }
7
7
  },
8
8
  "hooks": {
9
9
  "preToolUse": {
10
10
  "command": "npx",
11
- "args": ["--yes", "--package", "thumbgate@1.27.16", "thumbgate", "gate-check"]
11
+ "args": ["--yes", "--package", "thumbgate@1.20.0", "thumbgate", "gate-check"]
12
12
  }
13
13
  }
14
14
  }
@@ -133,7 +133,6 @@
133
133
  "context": { "type": "string" },
134
134
  "mcpProfile": { "type": "string" },
135
135
  "bundleId": { "type": "string" },
136
- "enforcePlanQuality": { "type": "boolean" },
137
136
  "approved": { "type": "boolean" }
138
137
  },
139
138
  "required": ["intentId"]
@@ -70,21 +70,6 @@ const {
70
70
  verifyClaimEvidence,
71
71
  registerClaimGate,
72
72
  } = require('../../scripts/gates-engine');
73
- const { mergeRepeatMetricIntoGateStats } = require('../../scripts/repeat-metric');
74
- const {
75
- detectNoop,
76
- computeActionStateHash,
77
- recordActionAttempt,
78
- isRepeatAttempt,
79
- } = require('../../scripts/noop-detect');
80
- const { recordAuditEvent } = require('../../scripts/audit-trail');
81
- const {
82
- recordReceipt,
83
- getReceiptForAction,
84
- getRecentReceipts,
85
- pairFeedbackWithReceipt,
86
- buildReceiptContextEntries,
87
- } = require('../../scripts/action-receipts');
88
73
  const {
89
74
  evaluateOperationalIntegrity,
90
75
  } = require('../../scripts/operational-integrity');
@@ -231,7 +216,7 @@ const {
231
216
  finalizeSession: finalizeFeedbackSession,
232
217
  } = require('../../scripts/feedback-session');
233
218
 
234
- const SERVER_INFO = { name: 'thumbgate-mcp', version: '1.27.16' };
219
+ const SERVER_INFO = { name: 'thumbgate-mcp', version: '1.20.0' };
235
220
  const COMMERCE_CATEGORIES = [
236
221
  'product_recommendation',
237
222
  'brand_compliance',
@@ -383,111 +368,6 @@ function buildRecallResponse(args = {}) {
383
368
  return toTextResult(text);
384
369
  }
385
370
 
386
- function buildSuggestFixResponse(args = {}) {
387
- const context = String(args.context || '').trim();
388
- const rawLimit = Number(args.limit);
389
- const limit = Number.isFinite(rawLimit) && rawLimit > 0 ? Math.min(rawLimit, 5) : 3;
390
-
391
- // If no context provided, return generic suggestion
392
- if (!context) {
393
- return toTextResult({
394
- suggestions: [
395
- {
396
- action: 'Capture feedback about what went wrong so ThumbGate can learn and prevent recurrence.',
397
- source: 'generic',
398
- },
399
- ],
400
- query: '',
401
- totalFound: 0,
402
- });
403
- }
404
-
405
- // Search lessons via lesson-search module
406
- const lessonModule = loadPrivateMcpModule('lessonSearch');
407
- let lessonActions = [];
408
- if (lessonModule) {
409
- try {
410
- const searchResult = lessonModule.searchLessons(context, { limit: 10 });
411
- const results = Array.isArray(searchResult && searchResult.results) ? searchResult.results : [];
412
- for (const result of results) {
413
- const correctiveActions = (result.systemResponse && Array.isArray(result.systemResponse.correctiveActions))
414
- ? result.systemResponse.correctiveActions
415
- : [];
416
- for (const action of correctiveActions) {
417
- const text = String(action.text || '').trim();
418
- if (text) {
419
- lessonActions.push({
420
- action: text,
421
- source: action.source || `lesson:${result.id || 'unknown'}`,
422
- score: result.score || 0,
423
- });
424
- }
425
- }
426
- // Also pick up lesson-level howToAvoid / actionNeeded when no explicit correctiveActions
427
- if (correctiveActions.length === 0 && result.lesson) {
428
- const text = result.lesson.howToAvoid || result.lesson.actionNeeded || '';
429
- if (text) {
430
- lessonActions.push({
431
- action: String(text).trim(),
432
- source: `lesson:${result.id || 'unknown'}`,
433
- score: result.score || 0,
434
- });
435
- }
436
- }
437
- }
438
- } catch {
439
- // lesson search failure is non-fatal
440
- }
441
- }
442
-
443
- // Search prevention rules directly via lesson-search module's helper
444
- let ruleActions = [];
445
- try {
446
- const { readPreventionRuleMatches } = require('../../scripts/lesson-search');
447
- const ruleMatches = readPreventionRuleMatches(context, limit);
448
- for (const rule of ruleMatches) {
449
- const text = rule.summary || rule.title || '';
450
- if (text) {
451
- ruleActions.push({
452
- action: String(text).trim(),
453
- source: `rule:${String(rule.title || 'prevention_rules').trim()}`,
454
- score: rule.score || 0,
455
- });
456
- }
457
- }
458
- } catch {
459
- // rule search failure is non-fatal
460
- }
461
-
462
- // Merge, deduplicate, sort by score, and take top `limit`
463
- const seen = new Set();
464
- const all = [...lessonActions, ...ruleActions]
465
- .filter((item) => {
466
- if (!item.action) return false;
467
- const key = item.action.toLowerCase();
468
- if (seen.has(key)) return false;
469
- seen.add(key);
470
- return true;
471
- })
472
- .sort((a, b) => (b.score || 0) - (a.score || 0))
473
- .slice(0, limit)
474
- .map(({ action, source }) => ({ action, source }));
475
-
476
- // If nothing matched, add generic fallback
477
- if (all.length === 0) {
478
- all.push({
479
- action: 'No matching lessons or rules found. Capture feedback via capture_feedback so ThumbGate can learn from this failure.',
480
- source: 'generic',
481
- });
482
- }
483
-
484
- return toTextResult({
485
- suggestions: all,
486
- query: context,
487
- totalFound: all.length,
488
- });
489
- }
490
-
491
371
  function buildDiagnoseFailureResponse(args = {}) {
492
372
  let intentPlan = null;
493
373
  const requestedProfile = args.mcpProfile || getActiveMcpProfile();
@@ -539,28 +419,6 @@ function buildContextPackResponse(args = {}) {
539
419
  maxChars: Number(args.maxChars || 6000),
540
420
  namespaces,
541
421
  });
542
- // Feed outcome-paired action receipts into the pack so an action->outcome
543
- // history is available alongside lessons/rules. Additive + guarded: a
544
- // receipt-store failure must never break context pack construction.
545
- try {
546
- const receiptEntries = buildReceiptContextEntries(args.query || '', Number(args.maxItems || 8));
547
- if (Array.isArray(receiptEntries) && receiptEntries.length && Array.isArray(pack.items)) {
548
- for (const entry of receiptEntries) {
549
- pack.items.push({
550
- id: `action-receipt_${entry && entry.score != null ? entry.score : ''}_${pack.items.length}`,
551
- namespace: 'action-receipts',
552
- title: 'Action receipt outcome',
553
- structuredContext: { rawContent: entry && entry.text ? String(entry.text) : '' },
554
- tags: ['action-receipt', 'outcome-paired'],
555
- score: entry && typeof entry.score === 'number' ? entry.score : 0,
556
- });
557
- }
558
- if (!Array.isArray(pack.namespaces)) pack.namespaces = [];
559
- if (!pack.namespaces.includes('action-receipts')) pack.namespaces.push('action-receipts');
560
- }
561
- } catch {
562
- // ignore receipt enrichment failures
563
- }
564
422
  return toTextResult(pack);
565
423
  }
566
424
 
@@ -674,22 +532,7 @@ function buildEstimateUncertaintyResponse(args = {}) {
674
532
 
675
533
  async function callTool(name, args = {}) {
676
534
  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
-
692
- if (name !== 'workflow_sentinel' && process.env.THUMBGATE_DISABLE_MCP_FIREWALL !== '1') {
535
+ if (name !== 'workflow_sentinel') {
693
536
  const firewallResult = (await evaluateGatesAsync(name, args)) || evaluateSecretGuard({ tool_name: name, tool_input: args });
694
537
  if (firewallResult && firewallResult.decision === 'deny') {
695
538
  const err = new Error(`Action blocked by Semantic Firewall: ${firewallResult.message}`);
@@ -722,13 +565,9 @@ async function callToolInner(name, args) {
722
565
  if (name === 'describe_reliability_entity') name = 'describe_semantic_entity';
723
566
 
724
567
  switch (name) {
725
- case 'capture_feedback': {
726
- // Outcome-paired lessons: enrich the feedback payload with the matching
727
- // action receipt (this action -> this outcome) before promotion. Returns
728
- // args unchanged when there is no matching receipt (non-breaking).
729
- const pairedFeedback = pairFeedbackWithReceipt(args);
730
- return toCaptureFeedbackTextResult(captureFeedback(pairedFeedback));
731
- }
568
+ case 'capture_feedback':
569
+
570
+ return toCaptureFeedbackTextResult(captureFeedback(args));
732
571
  case 'feedback_summary':
733
572
  return toTextResult(feedbackSummary(Number(args.recent || 20)));
734
573
  case 'search_lessons': {
@@ -740,8 +579,6 @@ async function callToolInner(name, args) {
740
579
  tags: Array.isArray(args.tags) ? args.tags : [],
741
580
  }));
742
581
  }
743
- case 'suggest_fix':
744
- return buildSuggestFixResponse(args);
745
582
  case 'retrieve_lessons': {
746
583
  // Cross-encoder reranking: retrieve more candidates, then rerank for precision
747
584
  const { retrieveWithRerankingSync } = loadOptionalModule(path.join(__dirname, '../../scripts/cross-encoder-reranker'), () => ({
@@ -760,23 +597,6 @@ async function callToolInner(name, args) {
760
597
  },
761
598
  ));
762
599
  }
763
- case 'ai_component_inventory': {
764
- const {
765
- scanAiComponents,
766
- buildCycloneDxMlBom,
767
- formatInventoryText,
768
- } = require('../../scripts/ai-component-inventory');
769
- const rootDir = args.rootDir ? path.resolve(String(args.rootDir)) : process.cwd();
770
- const inventory = scanAiComponents({
771
- rootDir,
772
- maxFiles: args.maxFiles ? Number(args.maxFiles) : undefined,
773
- includeSnippets: args.includeSnippets !== false,
774
- });
775
- const format = String(args.format || 'summary').toLowerCase();
776
- if (format === 'cyclonedx') return toTextResult(buildCycloneDxMlBom(inventory));
777
- if (format === 'json') return toTextResult(inventory);
778
- return toTextResult(formatInventoryText(inventory));
779
- }
780
600
  case 'search_thumbgate':
781
601
  enforceLimit('search_thumbgate');
782
602
  return toTextResult(searchThumbgate({
@@ -852,7 +672,6 @@ async function callToolInner(name, args) {
852
672
  bundleId: args.bundleId,
853
673
  partnerProfile: args.partnerProfile,
854
674
  delegationMode: args.delegationMode,
855
- enforcePlanQuality: args.enforcePlanQuality === true,
856
675
  approved: args.approved === true,
857
676
  repoPath: args.repoPath,
858
677
  }));
@@ -984,7 +803,6 @@ async function callToolInner(name, args) {
984
803
  summary: args.summary,
985
804
  allowedPaths: args.allowedPaths,
986
805
  protectedPaths: args.protectedPaths,
987
- workflowContract: args.workflowContract,
988
806
  repoPath: args.repoPath,
989
807
  localOnly: args.localOnly === true,
990
808
  clear: args.clear === true,
@@ -1023,56 +841,19 @@ async function callToolInner(name, args) {
1023
841
  });
1024
842
  case 'track_action': {
1025
843
  const entry = trackAction(args.actionId, args.metadata || {});
1026
- const result = {
844
+ return toTextResult({
1027
845
  tracked: true,
1028
846
  actionId: args.actionId,
1029
847
  ...entry,
1030
- };
1031
- // No-op / repeat signal: when the caller carries a precomputed state hash
1032
- // in metadata, surface whether this exact (action, state) was already
1033
- // attempted this session. Additive flag, non-breaking.
1034
- const metadataStateHash = args.metadata && args.metadata.stateHash;
1035
- if (metadataStateHash) {
1036
- try {
1037
- result.repeatSignal = isRepeatAttempt(
1038
- (args.metadata && args.metadata.sessionId) || 'default',
1039
- args.actionId,
1040
- metadataStateHash,
1041
- );
1042
- } catch {
1043
- // repeat detection is best-effort
1044
- }
1045
- }
1046
- return toTextResult(result);
1047
- }
1048
- case 'detect_noop': {
1049
- const stateHash = computeActionStateHash(args);
1050
- const noop = detectNoop(args);
1051
- const sessionId = args.sessionId || 'default';
1052
- const repeat = isRepeatAttempt(sessionId, args.actionId, stateHash);
1053
- recordActionAttempt(sessionId, args.actionId, stateHash);
1054
- return toTextResult({
1055
- noop: noop.noop,
1056
- repeat,
1057
- reason: noop.reason,
1058
- stateHash,
1059
848
  });
1060
849
  }
1061
- case 'record_action_receipt':
1062
- return toTextResult(recordReceipt(args));
1063
- case 'get_action_receipts':
1064
- return toTextResult(
1065
- args.actionId
1066
- ? getReceiptForAction(args.actionId)
1067
- : getRecentReceipts(Number(args.limit || 20)),
1068
- );
1069
850
  case 'verify_claim':
1070
- return toTextResult(verifyClaimEvidence(args.claim, { goalContract: args.goalContract }));
851
+ return toTextResult(verifyClaimEvidence(args.claim));
1071
852
  case 'require_evidence_for_claim': {
1072
853
  if (!args.claim || typeof args.claim !== 'string') {
1073
854
  throw new Error('claim is required and must be a string');
1074
855
  }
1075
- const verification = verifyClaimEvidence(args.claim, { goalContract: args.goalContract });
856
+ const verification = verifyClaimEvidence(args.claim);
1076
857
  const mode = args.mode === 'advisory' ? 'advisory' : 'blocking';
1077
858
  const hasMatchingChecks = Array.isArray(verification.checks) && verification.checks.length > 0;
1078
859
  const evidenceMissing = hasMatchingChecks && !verification.verified;
@@ -1084,18 +865,9 @@ async function callToolInner(name, args) {
1084
865
  const { recordAuditEvent } = require('../../scripts/audit-trail');
1085
866
  recordAuditEvent({
1086
867
  toolName: 'require_evidence_for_claim',
1087
- toolInput: {
1088
- claim: args.claim,
1089
- mode,
1090
- sessionId: args.sessionId || null,
1091
- goalContract: verification.goalContract && verification.goalContract.matched
1092
- ? verification.goalContract
1093
- : null,
1094
- },
868
+ toolInput: { claim: args.claim, mode, sessionId: args.sessionId || null },
1095
869
  decision: blocking ? 'deny' : 'allow',
1096
- gateId: verification.goalContract && verification.goalContract.matched
1097
- ? 'completion_goal_contract'
1098
- : 'completion_claim',
870
+ gateId: 'completion_claim',
1099
871
  message: blocking
1100
872
  ? `Completion claim blocked — missing evidence: ${missingActions.join(', ') || 'unknown'}`
1101
873
  : `Completion claim verified (${verification.verified ? 'evidence present' : 'no matching gate'})`,
@@ -1110,7 +882,6 @@ async function callToolInner(name, args) {
1110
882
  matchedChecks: hasMatchingChecks,
1111
883
  missingActions,
1112
884
  checks: verification.checks,
1113
- goalContract: verification.goalContract,
1114
885
  sessionId: args.sessionId || null,
1115
886
  });
1116
887
  }
@@ -1195,7 +966,7 @@ async function callToolInner(name, args) {
1195
966
  case 'register_claim_gate':
1196
967
  return toTextResult(registerClaimGate(args.claimPattern, args.requiredActions, args.message));
1197
968
  case 'gate_stats':
1198
- return toTextResult(mergeRepeatMetricIntoGateStats(loadGateStats()));
969
+ return toTextResult(loadGateStats());
1199
970
  case 'dashboard':
1200
971
  return toTextResult(generateDashboard(getFeedbackPaths().FEEDBACK_DIR));
1201
972
  case 'org_dashboard':
@@ -1297,15 +1068,6 @@ async function callToolInner(name, args) {
1297
1068
  },
1298
1069
  });
1299
1070
  }
1300
- case 'parallel_workflow': {
1301
- const { executeWorkflow } = require('../../scripts/parallel-workflow-orchestrator');
1302
- const results = await executeWorkflow(args.objective, {
1303
- concurrency: args.concurrency,
1304
- timeoutMs: args.timeoutMs,
1305
- cwd: resolveWorkspaceCwd(args.cwd),
1306
- });
1307
- return toTextResult(results);
1308
- }
1309
1071
  case 'open_feedback_session':
1310
1072
  return toTextResult(openFeedbackSession(args.feedbackEventId, args.signal, args.initialContext));
1311
1073
  case 'append_feedback_context':
@@ -1495,19 +1257,6 @@ function startStdioServer() {
1495
1257
  acquireLock();
1496
1258
 
1497
1259
  process.stdin.resume();
1498
-
1499
- // Self-terminate when the client disconnects (stdin EOF/close). A stdio MCP
1500
- // server must not outlive its parent: clients spawn it over stdin/stdout and
1501
- // a well-behaved server exits when that pipe closes. Without this, children
1502
- // abandoned by a client that exits without killing them linger forever and
1503
- // accumulate. WHY: on 2026-06-05, 117 orphaned `thumbgate serve` processes
1504
- // (spawned by a Codex app-server over ~4 days, never reaped) piled up and
1505
- // helped exhaust a 24GB host. The existing exit handlers (cleanupLock /
1506
- // cleanupSessionLock registered on 'exit') run via process.exit(0).
1507
- const exitOnDisconnect = () => process.exit(0);
1508
- process.stdin.on('end', exitOnDisconnect);
1509
- process.stdin.on('close', exitOnDisconnect);
1510
-
1511
1260
  let buffer = Buffer.alloc(0);
1512
1261
  // Auto-detect transport from first request and lock it for the session.
1513
1262
  // mcp-proxy (Glama) sends NDJSON and expects NDJSON back.
@@ -1571,7 +1320,6 @@ module.exports = {
1571
1320
  acquireLock,
1572
1321
  toCaptureFeedbackTextResult,
1573
1322
  formatCorrectiveActionsReminder,
1574
- buildSuggestFixResponse,
1575
1323
  __test__: {
1576
1324
  PRIVATE_MCP_MODULES,
1577
1325
  loadPrivateMcpModule,
@@ -7,7 +7,7 @@
7
7
  "npx",
8
8
  "--yes",
9
9
  "--package",
10
- "thumbgate@1.27.16",
10
+ "thumbgate@1.20.0",
11
11
  "thumbgate",
12
12
  "serve"
13
13
  ],
@@ -69,7 +69,7 @@
69
69
  "intent": "Block commands that expose deployment secrets inline.",
70
70
  "toolName": "Bash",
71
71
  "toolInput": {
72
- "command": "RAILWAY_TOKEN=__TG_FIXTURE_GITHUB_PAT__ railway deploy"
72
+ "command": "RAILWAY_TOKEN=ghp_abcdefghijklmnopqrstuvwxyz1234 railway deploy"
73
73
  },
74
74
  "expectedDecision": "deny",
75
75
  "unsafe": true,
@@ -82,7 +82,7 @@
82
82
  "toolName": "Write",
83
83
  "toolInput": {
84
84
  "file_path": "src/logger.js",
85
- "content": "const token = \"__TG_FIXTURE_GITHUB_PAT__\";\nconsole.log('secret', token);"
85
+ "content": "const token = \"ghp_abcdefghijklmnopqrstuvwxyz1234\";\nconsole.log('secret', token);"
86
86
  },
87
87
  "expectedDecision": "deny",
88
88
  "unsafe": true,