thumbgate 1.4.1 → 1.4.3

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 (60) hide show
  1. package/.claude-plugin/README.md +45 -34
  2. package/.claude-plugin/marketplace.json +3 -3
  3. package/.claude-plugin/plugin.json +3 -3
  4. package/.well-known/llms.txt +1 -1
  5. package/.well-known/mcp/server-card.json +1 -1
  6. package/README.md +26 -2
  7. package/adapters/README.md +4 -1
  8. package/adapters/chatgpt/INSTALL.md +39 -19
  9. package/adapters/claude/.mcp.json +2 -2
  10. package/adapters/codex/config.toml +2 -2
  11. package/adapters/mcp/server-stdio.js +10 -4
  12. package/adapters/opencode/opencode.json +1 -1
  13. package/adapters/perplexity/.mcp.json +36 -0
  14. package/adapters/perplexity/config.toml +16 -0
  15. package/adapters/perplexity/opencode.json +29 -0
  16. package/bin/cli.js +246 -90
  17. package/config/mcp-allowlists.json +11 -3
  18. package/package.json +28 -13
  19. package/plugins/claude-codex-bridge/.claude-plugin/plugin.json +1 -1
  20. package/plugins/claude-codex-bridge/.mcp.json +1 -1
  21. package/plugins/codex-profile/.codex-plugin/plugin.json +1 -1
  22. package/plugins/codex-profile/.mcp.json +1 -1
  23. package/plugins/codex-profile/INSTALL.md +1 -1
  24. package/plugins/codex-profile/README.md +1 -1
  25. package/plugins/cursor-marketplace/.cursor-plugin/plugin.json +1 -1
  26. package/plugins/opencode-profile/INSTALL.md +1 -1
  27. package/public/index.html +121 -24
  28. package/public/llm-context.md +17 -1
  29. package/scripts/ai-search-visibility.js +10 -36
  30. package/scripts/audit-trail.js +25 -15
  31. package/scripts/auto-wire-hooks.js +127 -0
  32. package/scripts/cli-demo.js +102 -0
  33. package/scripts/cli-schema.js +285 -0
  34. package/scripts/cli-status.js +166 -0
  35. package/scripts/cross-encoder-reranker.js +235 -0
  36. package/scripts/explore-subcommands.js +277 -0
  37. package/scripts/explore.js +569 -0
  38. package/scripts/feedback-loop.js +20 -6
  39. package/scripts/lesson-inference.js +27 -2
  40. package/scripts/lesson-reranker.js +263 -0
  41. package/scripts/lesson-retrieval.js +34 -17
  42. package/scripts/lesson-search.js +69 -0
  43. package/scripts/perplexity-client.js +210 -0
  44. package/scripts/perplexity-command-center.js +644 -0
  45. package/scripts/perplexity-marketing.js +17 -29
  46. package/scripts/prove-packaged-runtime.js +5 -4
  47. package/scripts/ralph-mode-ci.js +122 -19
  48. package/scripts/reflector-agent.js +2 -2
  49. package/scripts/session-analyzer.js +533 -0
  50. package/scripts/social-analytics/db/marketing-db.js +179 -0
  51. package/scripts/social-analytics/db/schema.sql +23 -0
  52. package/scripts/social-analytics/generate-instagram-card.js +31 -5
  53. package/scripts/social-analytics/generate-slides.js +268 -0
  54. package/scripts/social-analytics/post-video.js +316 -0
  55. package/scripts/social-analytics/publishers/zernio.js +52 -23
  56. package/scripts/statusline-local-stats.js +3 -1
  57. package/scripts/statusline.sh +15 -10
  58. package/scripts/thumbgate-bench.js +494 -0
  59. package/src/api/server.js +65 -1
  60. package/scripts/social-analytics/db/analytics.sqlite +0 -0
package/bin/cli.js CHANGED
@@ -726,6 +726,18 @@ function capture() {
726
726
  if (result.accepted) {
727
727
  const ev = result.feedbackEvent;
728
728
  const mem = result.memoryRecord;
729
+
730
+ if (args.json) {
731
+ console.log(JSON.stringify({
732
+ ok: true,
733
+ signal: normalized,
734
+ feedbackId: ev.id,
735
+ memoryId: mem.id,
736
+ actionType: ev.actionType,
737
+ }, null, 2));
738
+ return;
739
+ }
740
+
729
741
  console.log(`\nFeedback Captured [${normalized.toUpperCase()}]`);
730
742
  console.log('─'.repeat(50));
731
743
  console.log(` Feedback ID : ${ev.id}`);
@@ -742,6 +754,14 @@ function capture() {
742
754
  console.log('');
743
755
  proNudge();
744
756
  } else {
757
+ if (args.json) {
758
+ console.log(JSON.stringify({
759
+ ok: false,
760
+ signal: normalized,
761
+ reason: result.reason,
762
+ }, null, 2));
763
+ process.exit(2);
764
+ }
745
765
  console.log(`\nFeedback Recorded [${normalized.toUpperCase()}] — not promoted`);
746
766
  console.log('─'.repeat(50));
747
767
  console.log(` Reason : ${result.reason}\n`);
@@ -751,23 +771,37 @@ function capture() {
751
771
 
752
772
  function stats() {
753
773
  trackEvent('cli_stats', { command: 'stats' });
774
+ const args = parseArgs(process.argv.slice(3));
754
775
  const { analyzeFeedback } = require(path.join(PKG_ROOT, 'scripts', 'feedback-loop'));
755
776
  const data = analyzeFeedback();
756
-
777
+
778
+ const avgCostOfMistake = 2.50;
779
+ const payload = {
780
+ total: data.total,
781
+ positives: data.totalPositive,
782
+ negatives: data.totalNegative,
783
+ approvalRate: Math.round(data.approvalRate * 100),
784
+ recentTrend: Math.round(data.recentRate * 100),
785
+ revenueAtRisk: Number((data.totalNegative * avgCostOfMistake).toFixed(2)),
786
+ topTags: data.topTags || [],
787
+ recentActivity: data.recentActivity || [],
788
+ };
789
+
790
+ if (args.json) {
791
+ console.log(JSON.stringify(payload, null, 2));
792
+ return;
793
+ }
794
+
757
795
  console.log('\n📊 ThumbGate Performance Metrics');
758
796
  console.log('─'.repeat(50));
759
- console.log(` Total Signals : ${data.total}`);
760
- console.log(` Approval Rate : ${Math.round(data.approvalRate * 100)}%`);
761
- console.log(` Recent Trend : ${Math.round(data.recentRate * 100)}%`);
762
-
763
- // The Pitch: Revenue-at-Risk
764
- const avgCostOfMistake = 2.50; // $2.50 per agent turn/fix
765
- const revenueAtRisk = (data.totalNegative * avgCostOfMistake).toFixed(2);
766
-
767
- if (data.totalNegative > 0) {
797
+ console.log(` Total Signals : ${payload.total}`);
798
+ console.log(` Approval Rate : ${payload.approvalRate}%`);
799
+ console.log(` Recent Trend : ${payload.recentTrend}%`);
800
+
801
+ if (payload.negatives > 0) {
768
802
  console.log('\n⚠️ REVENUE-AT-RISK ANALYSIS');
769
- console.log(` Repeated Failures detected: ${data.totalNegative}`);
770
- console.log(` Estimated Operational Loss: $${revenueAtRisk}`);
803
+ console.log(` Repeated Failures detected: ${payload.negatives}`);
804
+ console.log(` Estimated Operational Loss: $${payload.revenueAtRisk}`);
771
805
  console.log(' Action Required: Run "npx thumbgate rules" to generate guardrails.');
772
806
  console.log(' Strategic Recommendation: if this is a shared workflow problem, start the Workflow Hardening Sprint.');
773
807
  console.log(' Team intake: https://thumbgate-production.up.railway.app/#workflow-sprint-intake');
@@ -779,9 +813,15 @@ function stats() {
779
813
  }
780
814
 
781
815
  function compact() {
816
+ const args = parseArgs(process.argv.slice(3));
782
817
  const { compactMemories } = require(path.join(PKG_ROOT, 'scripts', 'feedback-loop'));
783
818
  const result = compactMemories();
784
819
 
820
+ if (args.json) {
821
+ console.log(JSON.stringify({ before: result.before, after: result.after, removed: result.removed }, null, 2));
822
+ return;
823
+ }
824
+
785
825
  console.log('\n🧹 Memory Compaction Complete');
786
826
  console.log('─'.repeat(50));
787
827
  console.log(` Before : ${result.before} memories`);
@@ -980,24 +1020,66 @@ function pro() {
980
1020
 
981
1021
  function summary() {
982
1022
  const args = parseArgs(process.argv.slice(3));
983
- const { feedbackSummary } = require(path.join(PKG_ROOT, 'scripts', 'feedback-loop'));
1023
+ const { feedbackSummary, analyzeFeedback } = require(path.join(PKG_ROOT, 'scripts', 'feedback-loop'));
1024
+ if (args.json) {
1025
+ const data = analyzeFeedback();
1026
+ console.log(JSON.stringify({
1027
+ total: data.total,
1028
+ positives: data.totalPositive,
1029
+ negatives: data.totalNegative,
1030
+ approvalRate: Math.round(data.approvalRate * 100),
1031
+ recentTrend: Math.round(data.recentRate * 100),
1032
+ }, null, 2));
1033
+ return;
1034
+ }
984
1035
  console.log(feedbackSummary(Number(args.recent || 20)));
985
1036
  }
986
1037
 
987
1038
  function lessons() {
988
1039
  trackEvent('cli_recall', { command: 'lessons' });
989
1040
  const args = parseArgs(process.argv.slice(3));
1041
+ const tags = String(args.tags || '').split(',').map((t) => t.trim()).filter(Boolean);
1042
+ const query = args.query || process.argv.slice(3).find((a) => !a.startsWith('--')) || '';
1043
+ const limit = Number(args.limit || 10);
1044
+
1045
+ // --remote: fetch from hosted Railway instance
1046
+ if (args.remote) {
1047
+ const apiBase = process.env.THUMBGATE_API_URL || PRO_URL;
1048
+ const params = new URLSearchParams({ q: query, limit: String(limit) });
1049
+ if (args.category) params.set('category', args.category);
1050
+ if (tags.length) params.set('tags', tags.join(','));
1051
+ const url = `${apiBase}/v1/lessons/search?${params}`;
1052
+ const mod = url.startsWith('https') ? require('https') : require('http');
1053
+ let body = '';
1054
+ const req = mod.get(url, { timeout: 8000 }, (res) => {
1055
+ res.on('data', (chunk) => { body += chunk; });
1056
+ res.on('end', () => {
1057
+ try {
1058
+ const result = JSON.parse(body);
1059
+ if (args.json) {
1060
+ console.log(JSON.stringify(result, null, 2));
1061
+ } else {
1062
+ const { formatLessonSearchResults } = require(path.join(PKG_ROOT, 'scripts', 'lesson-search'));
1063
+ process.stdout.write(`[remote: ${apiBase}]\n`);
1064
+ process.stdout.write(formatLessonSearchResults(result));
1065
+ }
1066
+ } catch {
1067
+ process.stderr.write(`Error parsing remote response: ${body.slice(0, 200)}\n`);
1068
+ process.exit(1);
1069
+ }
1070
+ });
1071
+ });
1072
+ req.on('error', (err) => {
1073
+ process.stderr.write(`Remote fetch failed: ${err.message}\n`);
1074
+ process.exit(1);
1075
+ });
1076
+ req.on('timeout', () => { req.destroy(); process.stderr.write('Remote fetch timed out\n'); process.exit(1); });
1077
+ return;
1078
+ }
1079
+
1080
+ // --local (default)
990
1081
  const { searchLessons, formatLessonSearchResults } = require(path.join(PKG_ROOT, 'scripts', 'lesson-search'));
991
- const tags = String(args.tags || '')
992
- .split(',')
993
- .map((tag) => tag.trim())
994
- .filter(Boolean);
995
- const query = args.query || process.argv.slice(3).find((arg) => !arg.startsWith('--')) || '';
996
- const result = searchLessons(query, {
997
- limit: Number(args.limit || 10),
998
- category: args.category,
999
- tags,
1000
- });
1082
+ const result = searchLessons(query, { limit, category: args.category, tags });
1001
1083
 
1002
1084
  if (args.json) {
1003
1085
  console.log(JSON.stringify(result, null, 2));
@@ -1214,6 +1296,16 @@ function rules() {
1214
1296
  const { writePreventionRules } = require(path.join(PKG_ROOT, 'scripts', 'feedback-loop'));
1215
1297
  const outPath = args.output || path.join(CWD, '.thumbgate', 'prevention-rules.md');
1216
1298
  const result = writePreventionRules(outPath, Number(args.min || 2));
1299
+ if (args.json) {
1300
+ // Count rule sections (## headers) from the generated markdown
1301
+ const ruleHeaders = (result.markdown || '').match(/^## /gm);
1302
+ console.log(JSON.stringify({
1303
+ ok: true,
1304
+ path: result.path,
1305
+ rulesWritten: ruleHeaders ? ruleHeaders.length : 0,
1306
+ }, null, 2));
1307
+ return;
1308
+ }
1217
1309
  console.log(`Wrote prevention rules to ${result.path}`);
1218
1310
  }
1219
1311
 
@@ -1256,15 +1348,14 @@ function watchCmd() {
1256
1348
  }
1257
1349
 
1258
1350
  function status() {
1259
- const statusDashboard = require(path.join(PKG_ROOT, 'scripts', 'status-dashboard'));
1260
- const { getFeedbackPaths } = require(path.join(PKG_ROOT, 'scripts', 'feedback-loop'));
1261
- const { FEEDBACK_DIR } = getFeedbackPaths();
1262
- const data = statusDashboard.generateStatus(FEEDBACK_DIR);
1263
- // printDashboard writes directly to stdout when run as main;
1264
- // for CLI we call the same renderer
1265
- statusDashboard.printDashboard
1266
- ? statusDashboard.printDashboard(data)
1267
- : console.log(JSON.stringify(data, null, 2));
1351
+ const args = parseArgs(process.argv.slice(3));
1352
+ const { generateAgentStatus, formatStatus } = require(path.join(PKG_ROOT, 'scripts', 'cli-status'));
1353
+ const data = generateAgentStatus({ pkgRoot: PKG_ROOT, projectDir: CWD });
1354
+ if (args.json) {
1355
+ console.log(JSON.stringify(data, null, 2));
1356
+ return;
1357
+ }
1358
+ process.stdout.write(formatStatus(data));
1268
1359
  }
1269
1360
 
1270
1361
  function funnel() {
@@ -1473,8 +1564,14 @@ function dashboard() {
1473
1564
  }
1474
1565
 
1475
1566
  function gateStats() {
1567
+ const args = parseArgs(process.argv.slice(3));
1476
1568
  const { calculateStats, formatStats } = require(path.join(PKG_ROOT, 'scripts', 'gate-stats'));
1477
1569
  const stats = calculateStats();
1570
+ if (args.json) {
1571
+ const { gates, ...summary } = stats;
1572
+ console.log(JSON.stringify(args.verbose ? stats : summary, null, 2));
1573
+ return;
1574
+ }
1478
1575
  console.log('\n' + formatStats(stats) + '\n');
1479
1576
  }
1480
1577
 
@@ -1489,71 +1586,83 @@ function startApi() {
1489
1586
 
1490
1587
  function help() {
1491
1588
  const v = pkgVersion();
1492
- console.log(`thumbgate v${v}`);
1589
+ const { groupedCommands, commandHelpLine } = require(path.join(PKG_ROOT, 'scripts', 'cli-schema'));
1590
+ const groups = groupedCommands();
1591
+ const GROUP_LABELS = {
1592
+ capture: 'Feedback capture',
1593
+ discovery: 'Discovery & inspection',
1594
+ gates: 'Gates & rules',
1595
+ export: 'Export',
1596
+ ops: 'Operations',
1597
+ advanced: 'Advanced',
1598
+ };
1599
+
1600
+ console.log(`thumbgate v${v} — pre-action gates for AI coding agents`);
1601
+ console.log('');
1602
+
1603
+ for (const [groupKey, label] of Object.entries(GROUP_LABELS)) {
1604
+ const cmds = groups[groupKey];
1605
+ if (!cmds || cmds.length === 0) continue;
1606
+ console.log(`${label}:`);
1607
+ for (const cmd of cmds) {
1608
+ console.log(commandHelpLine(cmd));
1609
+ }
1610
+ console.log('');
1611
+ }
1612
+
1613
+ // Internal / hook commands (called by agent runtime, not operator-facing schema).
1614
+ console.log('Internal hooks (called by agent runtime):');
1615
+ console.log(' gate-check Evaluate PreToolUse payload from stdin -> ALLOW/BLOCK');
1616
+ console.log(' cache-update Refresh Claude statusline cache from stdin');
1617
+ console.log(' statusline-render Render ThumbGate Claude status line');
1618
+ console.log(' hook-auto-capture Process Claude UserPromptSubmit inline feedback');
1619
+ console.log(' session-start Refresh local ThumbGate session cache');
1493
1620
  console.log('');
1494
- console.log('Commands:');
1495
- console.log(' init Scaffold .thumbgate/ config + MCP server in current project');
1496
- console.log(' --agent=NAME Wire PreToolUse hooks for agent (claude-code|codex|gemini|forge)');
1497
- console.log(' --wire-hooks Wire hooks only (auto-detect agent, skip scaffolding)');
1498
- console.log(' --dry-run Preview hook changes without writing');
1499
- console.log(' install-mcp Install ThumbGate MCP server into Claude Code settings (--project for local)');
1500
- console.log(' serve Start MCP server (stdio) — for claude/codex/gemini/forge mcp add');
1501
- console.log(' gate-check Internal: evaluate a PreToolUse payload from stdin');
1502
- console.log(' cache-update Internal: refresh the Claude statusline cache from stdin');
1503
- console.log(' statusline-render Internal: render the ThumbGate Claude status line');
1504
- console.log(' hook-auto-capture Internal: process Claude UserPromptSubmit feedback');
1505
- console.log(' session-start Internal: refresh local ThumbGate session cache');
1506
- console.log(' capture [flags] Capture feedback (--feedback=up|down --context="..." --tags="...")');
1507
- console.log(' stats Show feedback analytics + Revenue-at-Risk');
1508
- console.log(' cfo Show hosted billing summary when configured, else local fallback JSON');
1621
+
1622
+ // Legacy and specialist commands kept visible until they graduate into the schema.
1623
+ console.log('Also available:');
1624
+ console.log(' install-mcp Install MCP server into Claude Code settings (--project for local)');
1625
+ console.log(' cfo Hosted billing summary (local fallback JSON)');
1509
1626
  console.log(' billing:setup Generate operator key + print Railway setup instructions');
1510
- console.log(' repair-github-marketplace Dry-run or apply legacy GitHub Marketplace amount repairs (--write)');
1627
+ console.log(' repair-github-marketplace Repair legacy GitHub Marketplace amount mappings');
1511
1628
  console.log(' north-star Show proof-backed workflow-run progress toward the North Star');
1512
- console.log(' summary Human-readable feedback summary');
1513
- console.log(' lessons [flags] Search promoted lessons and show linked corrective actions');
1514
- console.log(' model-fit Detect the current local embedding profile and write evidence report');
1515
- console.log(' risk [flags] Train or query the boosted local risk scorer');
1516
- console.log(' doctor Audit runtime isolation, bootstrap context, and permission tier');
1517
- console.log(' dispatch Print a Dispatch-safe remote ops brief for phone-driven review sessions');
1518
- console.log(' import-doc Import a local policy/runbook and propose reviewable gate candidates');
1519
- console.log(' export-dpo Export DPO training pairs (prompt/chosen/rejected JSONL)');
1520
- console.log(' export-databricks Export feedback logs + proof artifacts as a Databricks-ready analytics bundle');
1521
- console.log(' obsidian-export Export all feedback data as interlinked Obsidian markdown notes');
1522
- console.log(' --vault-path=PATH Obsidian vault path (or set THUMBGATE_OBSIDIAN_VAULT_PATH)');
1523
- console.log(' --output-dir=DIR Output subdirectory (default: AI-Memories/thumbgate)');
1524
- console.log(' rules Generate prevention rules from repeated failures');
1525
- console.log(' optimize [PRO] Prune CLAUDE.md and migrate manual rules to Pre-Action Gates');
1526
- console.log(' force-gate <PATTERN> Immediately create a blocking gate from a pattern');
1527
- console.log(' meta-agent Run meta-agent loop: generate + evaluate + promote prevention rules');
1528
- console.log(' --dry-run Preview rules without writing');
1529
- console.log(' --status Show last run summary');
1530
- console.log(' self-heal Run self-healing check and auto-fix');
1531
- console.log(' activate <KEY> Activate a Pro license key (from Stripe checkout)');
1532
- console.log(' pro Show Pro plan ($19/mo) + hosted pilot info');
1533
- console.log(' --upgrade Install Pro configs into .thumbgate/');
1534
- console.log(' prove [--target=X] Run proof harness (adapters|automation|attribution|lancedb|local-intelligence|...)');
1535
- console.log(' watch [flags] Watch .thumbgate/ for external signals and ingest through pipeline (--once, --source=X)');
1536
- console.log(' status Show feedback tracking dashboard — approval trend + failure domains');
1537
- console.log(' dashboard Full ThumbGate dashboard — approval rate, gate stats, prevention impact');
1538
- console.log(' funnel Show marketing & revenue conversion funnel analytics');
1539
- console.log(' pulse Show real-time GTM velocity and Mission Control summary');
1540
- console.log(' dispatch Dispatch-safe brief — metrics, gates, and read-only prompt templates');
1541
- console.log(' gate-check PreToolUse hook: reads tool JSON from stdin, outputs gate verdict');
1542
- console.log(' gate-stats Show gate statistics — active gates, blocks, warns, time saved');
1543
- console.log(' analytics Unified ThumbGate analytics snapshot (npm, GitHub, landing page)');
1629
+ console.log(' model-fit Detect local embedding profile and write evidence report');
1630
+ console.log(' risk Train or query the boosted local risk scorer');
1631
+ console.log(' optimize [PRO] Prune CLAUDE.md and migrate rules to Pre-Action Gates');
1632
+ console.log(' prove [--target=X] Run proof harness (adapters|automation|...)');
1633
+ console.log(' watch Watch .thumbgate/ for external signals');
1634
+ console.log(' status Approval trend + failure domain dashboard');
1635
+ console.log(' funnel Marketing and revenue conversion funnel analytics');
1636
+ console.log(' pulse Real-time GTM velocity and Mission Control summary');
1637
+ console.log(' dispatch Dispatch-safe brief for phone-driven review sessions');
1638
+ console.log(' analytics Unified analytics snapshot (npm, GitHub, landing)');
1544
1639
  console.log(' start-api Start the ThumbGate HTTPS API server');
1545
- console.log(' help Show this help message');
1546
1640
  console.log('');
1641
+
1642
+ console.log('Global flags (all commands):');
1643
+ console.log(' --json Output as machine-readable JSON');
1644
+ console.log(' --local Use local storage (default for most commands)');
1645
+ console.log(' --remote Fetch from hosted Railway instance');
1646
+ console.log('');
1647
+
1648
+ console.log('Explore subcommands (non-interactive):');
1649
+ console.log(' explore lessons [--json] [--limit=N] List lessons with confidence badges');
1650
+ console.log(' explore rules [--json] List prevention rules');
1651
+ console.log(' explore gates [--json] List gates with action badges');
1652
+ console.log(' explore firings [--json] [--limit=N] List recent gate firings');
1653
+ console.log('');
1654
+
1547
1655
  console.log('Examples:');
1548
1656
  console.log(' npx thumbgate init');
1549
- console.log(' npx thumbgate stats');
1550
- console.log(' npx thumbgate cfo');
1551
- console.log(' npx thumbgate import-doc docs/release-policy.md --json');
1552
- console.log(' npx thumbgate repair-github-marketplace --write');
1553
- console.log(' npx thumbgate lessons --query="verification" --limit=5');
1554
- console.log(' npx thumbgate model-fit');
1555
- console.log(' npx thumbgate risk');
1556
- console.log(' npx thumbgate pro');
1657
+ console.log(' npx thumbgate status --json');
1658
+ console.log(' npx thumbgate explore lessons --json');
1659
+ console.log(' npx thumbgate explore gates --json');
1660
+ console.log(' npx thumbgate demo');
1661
+ console.log(' npx thumbgate stats --json');
1662
+ console.log(' npx thumbgate lessons "force push" --json');
1663
+ console.log(' npx thumbgate lessons --query="deploy" --remote');
1664
+ console.log(' npx thumbgate gate-stats --json');
1665
+ console.log(' npx thumbgate capture --feedback=down --context="agent broke deploy" --json');
1557
1666
  proNudge();
1558
1667
  }
1559
1668
 
@@ -1822,6 +1931,53 @@ switch (COMMAND) {
1822
1931
  case 'gate-stats':
1823
1932
  gateStats();
1824
1933
  break;
1934
+ case 'explore': {
1935
+ const subCmd = process.argv[3];
1936
+ const exploreArgs = parseArgs(process.argv.slice(3));
1937
+ // If a known subcommand is given (or --json), use non-interactive mode
1938
+ const knownSubs = ['lessons', 'rules', 'gates', 'firings'];
1939
+ if (knownSubs.includes(subCmd) || exploreArgs.json) {
1940
+ const { exploreLessons, exploreRules, exploreGates, exploreGateFirings } = require(path.join(PKG_ROOT, 'scripts', 'explore-subcommands'));
1941
+ const { getFeedbackPaths } = require(path.join(PKG_ROOT, 'scripts', 'feedback-loop'));
1942
+ const { FEEDBACK_DIR } = getFeedbackPaths();
1943
+ const subOptions = {
1944
+ feedbackDir: FEEDBACK_DIR,
1945
+ pkgRoot: PKG_ROOT,
1946
+ limit: Number(exploreArgs.limit || 20),
1947
+ json: Boolean(exploreArgs.json),
1948
+ };
1949
+ const effectiveSub = knownSubs.includes(subCmd) ? subCmd : 'lessons';
1950
+ let output;
1951
+ switch (effectiveSub) {
1952
+ case 'lessons': output = exploreLessons(subOptions); break;
1953
+ case 'rules': output = exploreRules(subOptions); break;
1954
+ case 'gates': output = exploreGates(subOptions); break;
1955
+ case 'firings': output = exploreGateFirings(subOptions); break;
1956
+ default: output = exploreLessons(subOptions); break;
1957
+ }
1958
+ if (exploreArgs.json) {
1959
+ console.log(JSON.stringify(output, null, 2));
1960
+ } else {
1961
+ process.stdout.write(output);
1962
+ }
1963
+ } else {
1964
+ // No subcommand and no --json → launch interactive TUI
1965
+ const { run: runExplore } = require(path.join(PKG_ROOT, 'scripts', 'explore'));
1966
+ runExplore();
1967
+ }
1968
+ break;
1969
+ }
1970
+ case 'demo': {
1971
+ const demoArgs = parseArgs(process.argv.slice(3));
1972
+ const { runDemo } = require(path.join(PKG_ROOT, 'scripts', 'cli-demo'));
1973
+ const demoOutput = runDemo({ json: Boolean(demoArgs.json) });
1974
+ if (demoArgs.json) {
1975
+ console.log(JSON.stringify(demoOutput, null, 2));
1976
+ } else {
1977
+ process.stdout.write(demoOutput);
1978
+ }
1979
+ break;
1980
+ }
1825
1981
  case 'dashboard':
1826
1982
  dashboard();
1827
1983
  break;
@@ -51,7 +51,11 @@
51
51
  "capture_memory_feedback",
52
52
  "get_reliability_rules",
53
53
  "describe_reliability_entity",
54
- "report_product_issue"
54
+ "report_product_issue",
55
+ "perplexity_search",
56
+ "perplexity_ask",
57
+ "perplexity_research",
58
+ "perplexity_reason"
55
59
  ],
56
60
  "essential": [
57
61
  "capture_feedback",
@@ -124,7 +128,9 @@
124
128
  "get_business_metrics",
125
129
  "describe_semantic_entity",
126
130
  "get_reliability_rules",
127
- "describe_reliability_entity"
131
+ "describe_reliability_entity",
132
+ "perplexity_search",
133
+ "perplexity_ask"
128
134
  ],
129
135
  "dispatch": [
130
136
  "recall",
@@ -151,7 +157,9 @@
151
157
  "get_business_metrics",
152
158
  "describe_semantic_entity",
153
159
  "get_reliability_rules",
154
- "describe_reliability_entity"
160
+ "describe_reliability_entity",
161
+ "perplexity_search",
162
+ "perplexity_ask"
155
163
  ],
156
164
  "locked": [
157
165
  "feedback_summary",
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "thumbgate",
3
- "version": "1.4.1",
4
- "description": "ThumbGate: self-improving agent governance for engineering teams. Three-tier approval routing (block/approve/log), shared enforcement, CI gates, and audit trails. Every mistake becomes a prevention rule. PreToolUse hooks, Thompson Sampling, SQLite+FTS5 lesson DB, and LanceDB vector search.",
3
+ "version": "1.4.3",
4
+ "description": "Self-improving agent governance: type thumbs-up or thumbs-down on any AI agent action. ThumbGate turns every mistake into a prevention rule and blocks the pattern from repeating. One thumbs-down, never again. 33 pre-action gates, budget enforcement, and self-protection for Claude Code, Cursor, Codex, Gemini CLI, and Amp.",
5
5
  "homepage": "https://thumbgate-production.up.railway.app",
6
6
  "repository": {
7
7
  "type": "git",
@@ -72,7 +72,7 @@
72
72
  "social:post-everywhere:dry": "node scripts/post-everywhere.js --dry-run",
73
73
  "social:reply-monitor": "node scripts/social-reply-monitor.js",
74
74
  "social:reply-monitor:dry": "node scripts/social-reply-monitor.js --dry-run",
75
- "test": "npm run test:schema && npm run test:loop && npm run test:dpo && npm run test:kto && npm run test:api && npm run test:proof && npm run test:e2e && npm run test:rlaif && npm run test:attribution && npm run test:quality && npm run test:intelligence && npm run test:training-export && npm run test:deployment && npm run test:operational-integrity && npm run test:workflow && npm run test:billing && npm run test:cli && npm run test:watcher && npm run test:autoresearch && npm run test:ops && npm run test:tessl && npm run test:gates && npm run test:evoskill && npm run test:gates-hardening && npm run test:workers && npm run test:social-analytics && npm run test:memalign && npm run test:xmemory-lite && npm run test:filesystem-search && npm run test:zernio && npm run test:obsidian-export && npm run test:lesson-db && npm run test:lesson-rotation && npm run test:memory-dedup && npm run test:feedback-quality && npm run test:sync-version && npm run test:check-congruence && npm run test:tool-registry && npm run test:feedback-to-rules && npm run test:memory-firewall && npm run test:belief-update && npm run test:hosted-config && npm run test:operational-summary && npm run test:cloudflare-sandbox && npm run test:mcp-config && npm run test:plan-gate && npm run test:pulse && npm run test:semantic-layer && npm run test:data-pipeline && npm run test:optimize-context && npm run test:principle-extractor && npm run test:analytics-window && npm run test:funnel-analytics && npm run test:experiment-tracker && npm run test:build-metadata && npm run test:context-engine && npm run test:hf-papers && npm run test:marketing-experiment && npm run test:seo-gsd && npm run test:verify-run && npm run test:export-dpo-pairs && npm run test:export-hf-dataset && npm run test:license && npm run test:bot-detector && npm run test:postinstall && npm run test:funnel-invariants && npm run test:cli-telemetry && npm run test:pro-parity && npm run test:model-tier-router && npm run test:computer-use-firewall && npm run test:skill-exporter && npm run test:statusline && npm run test:evolution && npm run test:org-dashboard && npm run test:multi-hop-recall && npm run test:synthetic-dpo && npm run test:thumbgate-skill && npm run test:learn-hub && npm run test:feedback-fallback && npm run test:metaclaw && npm run test:server-lock && npm run test:control-tower && npm run test:pii-scanner && npm run test:data-governance && npm run test:lesson-inference && npm run test:semantic-dedup && npm run test:fs-utils && npm run test:lesson-retrieval && npm run test:reflector-agent && npm run test:feedback-session && npm run test:feedback-history-distiller && npm run test:hallucination-detector && npm run test:history-distiller && npm run test:predictive-insights && npm run test:prove-predictive-insights && npm run test:statusbar-cli && npm run test:generate-instagram-card && npm run test:instagram-thumbgate-post && npm run test:publish-instagram-thumbgate && npm run test:lesson-synthesis && npm run test:background-governance && npm run test:memory-migration && npm run test:prompt-dlp && npm run test:ephemeral-store && npm run test:agent-security && npm run test:skill-progressive && npm run test:per-step-scoring && npm run test:weekly-auto-post && npm run test:social-post-hourly && npm run test:social-quality-gate && npm run test:a2ui-engine && npm run test:gate-satisfy && npm run test:money-watcher && npm run test:budget && npm run test:quick-start && npm run test:utm && npm run test:product-feedback && npm run test:feedback-root-consolidator && npm run test:engagement-audit && npm run test:install-growth-automation && npm run test:publish-thumbgate-launch && npm run test:reconcile-thumbgate-campaign && npm run test:reddit-publisher && npm run test:schedule-thumbgate-campaign && npm run test:social-reply-monitor && npm run test:sync-launch-assets && npm run test:ai-search-visibility && npm run test:security-scanner && npm run test:llm-client && npm run test:managed-lesson-agent && npm run test:self-distill && npm run test:meta-agent && npm run test:harness-selector && npm run test:seo-guides && npm run test:enforcement-loop",
75
+ "test": "npm run test:schema && npm run test:loop && npm run test:dpo && npm run test:kto && npm run test:api && npm run test:proof && npm run test:e2e && npm run test:rlaif && npm run test:attribution && npm run test:quality && npm run test:intelligence && npm run test:training-export && npm run test:deployment && npm run test:operational-integrity && npm run test:workflow && npm run test:billing && npm run test:cli && npm run test:watcher && npm run test:autoresearch && npm run test:ops && npm run test:session-analyzer && npm run test:tessl && npm run test:gates && npm run test:evoskill && npm run test:gates-hardening && npm run test:workers && npm run test:social-analytics && npm run test:memalign && npm run test:xmemory-lite && npm run test:filesystem-search && npm run test:zernio && npm run test:obsidian-export && npm run test:lesson-db && npm run test:lesson-rotation && npm run test:memory-dedup && npm run test:feedback-quality && npm run test:sync-version && npm run test:check-congruence && npm run test:tool-registry && npm run test:feedback-to-rules && npm run test:memory-firewall && npm run test:belief-update && npm run test:hosted-config && npm run test:operational-summary && npm run test:operator-key-auth && npm run test:cloudflare-sandbox && npm run test:mcp-config && npm run test:plan-gate && npm run test:pulse && npm run test:semantic-layer && npm run test:data-pipeline && npm run test:optimize-context && npm run test:principle-extractor && npm run test:analytics-window && npm run test:funnel-analytics && npm run test:experiment-tracker && npm run test:build-metadata && npm run test:context-engine && npm run test:hf-papers && npm run test:marketing-experiment && npm run test:seo-gsd && npm run test:verify-run && npm run test:export-dpo-pairs && npm run test:export-hf-dataset && npm run test:license && npm run test:bot-detector && npm run test:postinstall && npm run test:funnel-invariants && npm run test:cli-telemetry && npm run test:pro-parity && npm run test:model-tier-router && npm run test:computer-use-firewall && npm run test:skill-exporter && npm run test:statusline && npm run test:evolution && npm run test:org-dashboard && npm run test:multi-hop-recall && npm run test:synthetic-dpo && npm run test:thumbgate-skill && npm run test:learn-hub && npm run test:feedback-fallback && npm run test:metaclaw && npm run test:server-lock && npm run test:control-tower && npm run test:pii-scanner && npm run test:data-governance && npm run test:lesson-inference && npm run test:semantic-dedup && npm run test:fs-utils && npm run test:cli-schema && npm run test:explore && npm run test:lesson-reranker && npm run test:lesson-retrieval && npm run test:cross-encoder && npm run test:reflector-agent && npm run test:feedback-session && npm run test:feedback-history-distiller && npm run test:hallucination-detector && npm run test:history-distiller && npm run test:predictive-insights && npm run test:prove-predictive-insights && npm run test:statusbar-cli && npm run test:generate-instagram-card && npm run test:instagram-thumbgate-post && npm run test:publish-instagram-thumbgate && npm run test:lesson-synthesis && npm run test:background-governance && npm run test:memory-migration && npm run test:prompt-dlp && npm run test:ephemeral-store && npm run test:agent-security && npm run test:skill-progressive && npm run test:per-step-scoring && npm run test:weekly-auto-post && npm run test:social-post-hourly && npm run test:social-quality-gate && npm run test:a2ui-engine && npm run test:gate-satisfy && npm run test:money-watcher && npm run test:budget && npm run test:quick-start && npm run test:utm && npm run test:product-feedback && npm run test:feedback-root-consolidator && npm run test:engagement-audit && npm run test:install-growth-automation && npm run test:publish-thumbgate-launch && npm run test:reconcile-thumbgate-campaign && npm run test:reddit-publisher && npm run test:schedule-thumbgate-campaign && npm run test:social-reply-monitor && npm run test:sync-launch-assets && npm run test:ai-search-visibility && npm run test:perplexity && npm run test:security-scanner && npm run test:llm-client && npm run test:managed-lesson-agent && npm run test:self-distill && npm run test:meta-agent && npm run test:harness-selector && npm run test:thumbgate-bench && npm run test:seo-guides && npm run test:enforcement-loop && npm run test:cli-agent-experience",
76
76
  "test:feedback-fallback": "node --test tests/feedback-fallback.test.js",
77
77
  "test:metaclaw": "node --test tests/metaclaw-features.test.js",
78
78
  "test:server-lock": "node --test tests/server-stdio-lock.test.js",
@@ -94,6 +94,7 @@
94
94
  "test:belief-update": "node --test tests/belief-update.test.js",
95
95
  "test:hosted-config": "node --test tests/hosted-config.test.js",
96
96
  "test:operational-summary": "node --test tests/operational-summary.test.js",
97
+ "test:operator-key-auth": "node --test tests/api-operator-key-auth.test.js",
97
98
  "test:cloudflare-sandbox": "node --test tests/cloudflare-dynamic-sandbox.test.js tests/cloudflare-sandbox-api.test.js",
98
99
  "test:mcp-config": "node --test tests/mcp-config.test.js",
99
100
  "test:plan-gate": "node --test tests/plan-gate.test.js",
@@ -132,15 +133,16 @@
132
133
  "test:quality": "node --test tests/validate-feedback.test.js",
133
134
  "test:intelligence": "node --test tests/intelligence.test.js",
134
135
  "test:training-export": "node --test tests/training-export.test.js tests/databricks-export.test.js",
135
- "test:deployment": "node --test tests/deployment.test.js tests/deploy-policy.test.js tests/publish-decision.test.js tests/changeset-check.test.js tests/sonarcloud-workflow.test.js",
136
+ "test:deployment": "node --test tests/deployment.test.js tests/deploy-policy.test.js tests/publish-decision.test.js tests/changeset-check.test.js tests/sonarcloud-workflow.test.js tests/package-boundary.test.js",
136
137
  "test:operational-integrity": "node --test tests/operational-integrity.test.js tests/sync-branch-protection.test.js",
137
- "test:workflow": "node --test tests/workflow-contract.test.js tests/social-marketing-assets.test.js tests/social-pipeline.test.js tests/positioning-contract.test.js tests/docs-claim-hygiene.test.js tests/workflow-runs.test.js tests/workflow-sprint-intake.test.js tests/gtm-revenue-loop.test.js tests/enterprise-story.test.js tests/ralph-loop.test.js",
138
+ "test:workflow": "node --test tests/workflow-contract.test.js tests/social-marketing-assets.test.js tests/social-pipeline.test.js tests/positioning-contract.test.js tests/docs-claim-hygiene.test.js tests/workflow-runs.test.js tests/workflow-sprint-intake.test.js tests/gtm-revenue-loop.test.js tests/enterprise-story.test.js tests/ralph-loop.test.js tests/ralph-mode-ci.test.js",
138
139
  "test:billing": "node --test tests/billing.test.js",
139
140
  "test:cli": "node --test tests/analytics-report.test.js tests/creator-campaigns.test.js tests/cli.test.js tests/codex-bridge-script.test.js tests/dispatch-brief.test.js tests/feedback-normalize.test.js tests/install-mcp.test.js tests/pr-manager.test.js tests/pro-local-dashboard.test.js tests/published-cli.test.js tests/revenue-status.test.js",
140
141
  "test:evolution": "node --test tests/workspace-evolver.test.js",
141
142
  "test:watcher": "node --test tests/jsonl-watcher.test.js",
142
143
  "test:autoresearch": "node --test tests/autoresearch.test.js",
143
144
  "test:ops": "node --test tests/adk-consolidator.test.js tests/anthropic-partner-strategy.test.js tests/auto-promote-gates.test.js tests/auto-wire-hooks.test.js tests/claude-skill.test.js tests/codegraph-context.test.js tests/commercial-signals.test.js tests/decision-journal.test.js tests/delegation-runtime.test.js tests/disagreement-mining.test.js tests/failure-diagnostics.test.js tests/gate-stats.test.js tests/github-billing.test.js tests/intervention-policy.test.js tests/markdown-escape.test.js tests/mcp-tools-gates.test.js tests/project-bayes-e2e.test.js tests/project-bayes.test.js tests/rate-limiter.test.js tests/schedule-manager.test.js tests/session-handoff.test.js tests/skill-generator.test.js tests/smart-learning.test.js tests/spike-and-sink.test.js tests/stripe-webhook-route.test.js tests/stripe-webhook-rotation.test.js tests/train-from-feedback.test.js tests/workflow-hardening-sprint.test.js tests/workflow-sentinel.test.js tests/test-suite-parity.test.js tests/a2ui-engine.test.js tests/webhook-delivery.test.js",
145
+ "test:session-analyzer": "node --test tests/session-analyzer.test.js",
144
146
  "test:tessl": "node --test tests/tessl-export.test.js",
145
147
  "test:gates": "node --test tests/gate-templates.test.js tests/gates-engine.test.js tests/claim-verification.test.js tests/secret-scanner.test.js tests/prompt-guard.test.js tests/audit-trail.test.js tests/profile-router.test.js tests/workflow-sentinel.test.js tests/docker-sandbox-planner.test.js",
146
148
  "test:budget": "node --test tests/budget-enforcer.test.js",
@@ -206,6 +208,7 @@
206
208
  "test:data-governance": "node --test tests/data-governance.test.js",
207
209
  "test:lesson-inference": "node --test tests/conversation-context.test.js tests/lesson-inference.test.js",
208
210
  "test:lesson-retrieval": "node --test tests/lesson-retrieval.test.js",
211
+ "test:cross-encoder": "node --test tests/cross-encoder-reranker.test.js",
209
212
  "test:reflector-agent": "node --test tests/reflector-agent.test.js",
210
213
  "test:feedback-session": "node --test tests/feedback-session.test.js",
211
214
  "test:feedback-history-distiller": "node --test tests/feedback-history-distiller.test.js",
@@ -269,7 +272,19 @@
269
272
  "test:meta-agent": "node --test tests/meta-agent-loop.test.js",
270
273
  "test:semantic-dedup": "node --test tests/semantic-dedup.test.js",
271
274
  "test:fs-utils": "node --test tests/fs-utils.test.js",
272
- "test:harness-selector": "node --test tests/harness-selector.test.js"
275
+ "test:lesson-reranker": "node --test tests/lesson-reranker.test.js",
276
+ "test:harness-selector": "node --test tests/harness-selector.test.js",
277
+ "test:thumbgate-bench": "node --test tests/thumbgate-bench.test.js",
278
+ "thumbgate:bench": "node scripts/thumbgate-bench.js",
279
+ "test:perplexity": "node --test tests/perplexity-client.test.js tests/perplexity-command-center.test.js tests/perplexity-adapter.test.js",
280
+ "perplexity:visibility": "node scripts/perplexity-command-center.js visibility",
281
+ "perplexity:leads": "node scripts/perplexity-command-center.js leads",
282
+ "perplexity:brief": "node scripts/perplexity-command-center.js brief",
283
+ "perplexity:full": "node scripts/perplexity-command-center.js full",
284
+ "perplexity:mcp-config": "node scripts/perplexity-command-center.js mcp-config",
285
+ "test:explore": "node --test tests/explore.test.js",
286
+ "test:cli-schema": "node --test tests/cli-schema.test.js",
287
+ "test:cli-agent-experience": "node --test tests/cli-agent-experience.test.js"
273
288
  },
274
289
  "keywords": [
275
290
  "mcp",
@@ -324,15 +339,15 @@
324
339
  "node": ">=18.18.0"
325
340
  },
326
341
  "dependencies": {
327
- "@anthropic-ai/sdk": "^0.24.0",
328
- "@google/genai": "^1.48.0",
342
+ "@anthropic-ai/sdk": "^0.88.0",
343
+ "@google/genai": "^1.49.0",
329
344
  "@huggingface/transformers": "^4.0.1",
330
345
  "@lancedb/lancedb": "^0.27.2",
331
346
  "apache-arrow": "^18.1.0",
332
- "better-sqlite3": "^12.8.0",
333
- "dotenv": "^17.4.1",
347
+ "better-sqlite3": "^12.9.0",
348
+ "dotenv": "^17.4.2",
334
349
  "playwright-core": "^1.59.1",
335
- "stripe": "^22.0.0"
350
+ "stripe": "^22.0.1"
336
351
  },
337
352
  "overrides": {
338
353
  "express@4.22.1": {
@@ -341,9 +356,9 @@
341
356
  },
342
357
  "mcpName": "io.github.IgorGanapolsky/thumbgate",
343
358
  "devDependencies": {
344
- "@changesets/changelog-github": "^0.5.1",
359
+ "@changesets/changelog-github": "^0.6.0",
345
360
  "@changesets/cli": "^2.30.0",
346
361
  "c8": "^11.0.0",
347
- "undici": "^8.0.2"
362
+ "undici": "^8.1.0"
348
363
  }
349
364
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "codex-bridge",
3
- "version": "1.4.0",
3
+ "version": "1.4.3",
4
4
  "description": "Run Codex review, adversarial review, and second-pass handoffs from Claude Code while keeping ThumbGate reliability memory in the loop.",
5
5
  "author": {
6
6
  "name": "Igor Ganapolsky",
@@ -5,7 +5,7 @@
5
5
  "args": [
6
6
  "--yes",
7
7
  "--package",
8
- "thumbgate@1.4.0",
8
+ "thumbgate@1.4.3",
9
9
  "thumbgate",
10
10
  "serve"
11
11
  ]
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "codex-profile",
3
- "version": "1.4.0",
3
+ "version": "1.4.3",
4
4
  "description": "ThumbGate for Codex: pre-action gates, skill packs, hallucination detection, PII scanning, progressive disclosure (82% token savings), and MCP-backed reliability memory.",
5
5
  "author": {
6
6
  "name": "Igor Ganapolsky",
@@ -5,7 +5,7 @@
5
5
  "args": [
6
6
  "--yes",
7
7
  "--package",
8
- "thumbgate@1.4.0",
8
+ "thumbgate@1.4.3",
9
9
  "thumbgate",
10
10
  "serve"
11
11
  ]
@@ -54,7 +54,7 @@ The following block is appended to `~/.codex/config.toml`:
54
54
  ```toml
55
55
  [mcp_servers.thumbgate]
56
56
  command = "npx"
57
- args = ["--yes", "--package", "thumbgate@1.4.0", "thumbgate", "serve"]
57
+ args = ["--yes", "--package", "thumbgate@1.4.3", "thumbgate", "serve"]
58
58
  ```
59
59
 
60
60
  The repo-local Codex app plugin ships the same runtime path through `plugins/codex-profile/.mcp.json`, so the manual config and plugin metadata stay aligned.