thumbgate 1.27.11 → 1.27.13

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 (131) hide show
  1. package/.claude-plugin/plugin.json +1 -1
  2. package/.well-known/llms.txt +2 -1
  3. package/.well-known/mcp/server-card.json +1 -1
  4. package/README.md +2 -4
  5. package/adapters/claude/.mcp.json +2 -2
  6. package/adapters/mcp/server-stdio.js +1 -1
  7. package/adapters/opencode/opencode.json +1 -1
  8. package/adapters/policy-engine/ethicore-guardian-client.js +68 -0
  9. package/adapters/policy-engine/thumbgate-policy-engine-adapter.js +260 -0
  10. package/bin/cli.js +78 -259
  11. package/config/builtin-lessons.json +23 -0
  12. package/config/gate-templates.json +0 -228
  13. package/config/gates/claim-verification.json +0 -18
  14. package/package.json +35 -25
  15. package/public/assets/brand/thumbgate-logo-transparent.svg +22 -0
  16. package/public/assets/brand/thumbgate-mark-inline-v3.svg +19 -0
  17. package/public/assets/brand/thumbgate-mark.svg +11 -5
  18. package/public/blog.html +0 -30
  19. package/public/brand/thumbgate-mark.svg +9 -5
  20. package/public/chatgpt-app.html +2 -2
  21. package/public/compare.html +2 -1
  22. package/public/dashboard.html +1 -1
  23. package/public/federal.html +1 -1
  24. package/public/index.html +95 -216
  25. package/public/learn.html +59 -35
  26. package/public/lessons.html +1 -1
  27. package/public/numbers.html +2 -2
  28. package/public/pro.html +7 -7
  29. package/scripts/aws-blocks-guardrails.js +228 -0
  30. package/scripts/cli-schema.js +22 -10
  31. package/scripts/dashboard-chat.js +2 -1
  32. package/scripts/document-intake.js +1 -49
  33. package/scripts/durability/step.js +3 -3
  34. package/scripts/gate-stats.js +5 -11
  35. package/scripts/gemini-embedding-policy.js +2 -1
  36. package/scripts/hook-stop-anti-claim.js +116 -184
  37. package/scripts/hosted-config.js +0 -12
  38. package/scripts/llm-client.js +187 -5
  39. package/scripts/plausible-domain-config.js +3 -1
  40. package/scripts/seo-gsd.js +240 -1
  41. package/scripts/tool-registry.js +2 -2
  42. package/scripts/vector-store.js +44 -0
  43. package/scripts/workspace-evolver.js +62 -2
  44. package/src/api/server.js +340 -131
  45. package/public/assets/brand/thumbgate-mark-inline.svg +0 -15
  46. package/public/compare/adopt-ai.html +0 -219
  47. package/public/compare/agentix-labs.html +0 -197
  48. package/public/compare/ai-experience-orchestration.html +0 -216
  49. package/public/compare/anthropic-claude-for-legal.html +0 -260
  50. package/public/compare/anthropic-containment.html +0 -280
  51. package/public/compare/arcade.html +0 -175
  52. package/public/compare/arcjet.html +0 -239
  53. package/public/compare/bumblebee.html +0 -307
  54. package/public/compare/claude-code-hooks.html +0 -294
  55. package/public/compare/databricks-unity-ai-gateway.html +0 -215
  56. package/public/compare/fallow.html +0 -351
  57. package/public/compare/heidi.html +0 -233
  58. package/public/compare/mem0.html +0 -342
  59. package/public/compare/oak-and-sparrow-gatekeeper.html +0 -289
  60. package/public/compare/rein.html +0 -236
  61. package/public/compare/sigmashake.html +0 -256
  62. package/public/compare/speclock.html +0 -342
  63. package/public/guides/agent-harness-optimization.html +0 -342
  64. package/public/guides/agentic-web-governance.html +0 -406
  65. package/public/guides/ai-agent-governance-sprint.html +0 -415
  66. package/public/guides/ai-agent-pre-action-approval-gates.html +0 -401
  67. package/public/guides/ai-agent-workflow-migration-checklist.html +0 -392
  68. package/public/guides/ai-deployment-readiness.html +0 -415
  69. package/public/guides/ai-mode-ads-agent-governance.html +0 -401
  70. package/public/guides/ai-search-topical-presence.html +0 -342
  71. package/public/guides/autoresearch-agent-safety.html +0 -342
  72. package/public/guides/background-agent-governance.html +0 -358
  73. package/public/guides/best-tools-stop-ai-agents-breaking-production.html +0 -363
  74. package/public/guides/browser-automation-safety.html +0 -342
  75. package/public/guides/chatgpt-ads-trust.html +0 -353
  76. package/public/guides/claude-code-feedback.html +0 -339
  77. package/public/guides/claude-code-prevent-repeated-mistakes.html +0 -161
  78. package/public/guides/claude-code-skills-guardrails.html +0 -343
  79. package/public/guides/claude-desktop.html +0 -356
  80. package/public/guides/code-knowledge-graph-guardrails.html +0 -365
  81. package/public/guides/codex-cli-guardrails.html +0 -339
  82. package/public/guides/cursor-agent-guardrails.html +0 -339
  83. package/public/guides/cursor-prevent-repeated-mistakes.html +0 -161
  84. package/public/guides/database-agent-safety.html +0 -406
  85. package/public/guides/deepseek-v4-runtime-guardrails.html +0 -346
  86. package/public/guides/developer-machine-supply-chain-guardrails.html +0 -358
  87. package/public/guides/gcp-mcp-guardrails.html +0 -147
  88. package/public/guides/gemini-cli-feedback-memory.html +0 -339
  89. package/public/guides/gpt-5-5-model-evaluation.html +0 -358
  90. package/public/guides/internal-ai-engineering-stack-guardrails.html +0 -348
  91. package/public/guides/long-running-agent-context-management.html +0 -346
  92. package/public/guides/mcp-tool-governance.html +0 -401
  93. package/public/guides/multica-thumbgate-setup.html +0 -134
  94. package/public/guides/native-messaging-host-security.html +0 -342
  95. package/public/guides/policy-engine-pre-action-gates.html +0 -346
  96. package/public/guides/pre-action-checks.html +0 -342
  97. package/public/guides/pretooluse-hooks-vs-advisory-prompt-rules.html +0 -342
  98. package/public/guides/prompt-tricks-to-workflow-rules.html +0 -365
  99. package/public/guides/proxy-pointer-rag-guardrails.html +0 -352
  100. package/public/guides/rag-precision-tuning-guardrails.html +0 -352
  101. package/public/guides/reasoning-compression-guardrails.html +0 -346
  102. package/public/guides/relational-knowledge-ai-recommendations.html +0 -342
  103. package/public/guides/roo-code-alternative-cline.html +0 -339
  104. package/public/guides/semantic-programmatic-seo-guardrails.html +0 -352
  105. package/public/guides/seo-agent-skills-guardrails.html +0 -344
  106. package/public/guides/stop-repeated-ai-agent-mistakes.html +0 -342
  107. package/public/learn/ac-dc-runtime-enforcement.html +0 -277
  108. package/public/learn/agent-harness-pattern.html +0 -181
  109. package/public/learn/agent-identity-connector-governance.html +0 -146
  110. package/public/learn/agent-swarms-shared-gates.html +0 -173
  111. package/public/learn/agentic-enterprise-context-brain.html +0 -117
  112. package/public/learn/agentic-os-team-governance.html +0 -146
  113. package/public/learn/ai-agent-governance.html +0 -158
  114. package/public/learn/ai-agent-persistent-memory.html +0 -211
  115. package/public/learn/anthropomorphic-claim-gates.html +0 -180
  116. package/public/learn/background-agent-control-layer.html +0 -184
  117. package/public/learn/claude-code-goal-with-rubrics.html +0 -205
  118. package/public/learn/codex-role-plugins-need-governance.html +0 -125
  119. package/public/learn/cost-aware-agent-gate-routing.html +0 -173
  120. package/public/learn/databricks-unity-ai-gateway-runtime-governance.html +0 -157
  121. package/public/learn/deterministic-agent-workflows.html +0 -185
  122. package/public/learn/feedback-loop-vs-decision-layer.html +0 -283
  123. package/public/learn/from-prototype-to-production.html +0 -223
  124. package/public/learn/learn.css +0 -51
  125. package/public/learn/mcp-pre-action-checks-explained.html +0 -172
  126. package/public/learn/pretix-stripe-connect-marketplaces.html +0 -161
  127. package/public/learn/regulated-agent-execution-boundary.html +0 -196
  128. package/public/learn/spec-driven-development.html +0 -168
  129. package/public/learn/stop-ai-agent-force-push.html +0 -134
  130. package/public/learn/vibe-coding-safety-net.html +0 -142
  131. package/scripts/reddit-browser-notification-watch.js +0 -230
package/bin/cli.js CHANGED
@@ -2188,6 +2188,26 @@ function pulse() {
2188
2188
  });
2189
2189
  }
2190
2190
 
2191
+ function checkUpdateCmd() {
2192
+ const { checkUpdate } = require(path.join(PKG_ROOT, 'scripts', 'check-update'));
2193
+ const args = parseArgs(process.argv.slice(3));
2194
+ checkUpdate({ verbose: !args.json, force: args.force }).then((res) => {
2195
+ if (args.json) {
2196
+ console.log(JSON.stringify(res, null, 2));
2197
+ }
2198
+ process.exit(0);
2199
+ }).catch((err) => {
2200
+ console.error(err && err.message ? err.message : err);
2201
+ process.exit(1);
2202
+ });
2203
+ }
2204
+
2205
+ function selfUpdateCmd() {
2206
+ const { selfUpdate } = require(path.join(PKG_ROOT, 'scripts', 'check-update'));
2207
+ const success = selfUpdate();
2208
+ process.exit(success ? 0 : 1);
2209
+ }
2210
+
2191
2211
  function dispatchBrief() {
2192
2212
  const args = parseArgs(process.argv.slice(3));
2193
2213
  const {
@@ -3151,6 +3171,7 @@ const SUBCOMMAND_HELP = {
3151
3171
  lessons: 'Usage: npx thumbgate lessons [--query="..."] [--limit=N]\n\nSearch the lesson database (Pro feature).',
3152
3172
  search: 'Usage: npx thumbgate search <query>\n\nSearch ThumbGate knowledge base (Pro feature).',
3153
3173
  'gate-check': 'Usage: npx thumbgate gate-check\n\nPreToolUse hook interface: reads tool call JSON from stdin, outputs gate verdict.',
3174
+ 'hermes-gate': 'Usage: npx thumbgate hermes-gate\n\nNous Research Hermes Agent pre_tool_call shell hook: reads Hermes tool-call JSON from stdin, runs the ThumbGate gate pipeline (strict by default), and outputs {"decision":"block","reason":...} to veto or {} to allow. Gates terminal/patch/skill_manage etc. See adapters/hermes/config.yaml.',
3154
3175
  'break-glass': 'Usage: npx thumbgate break-glass --reason="why" [--ttl=5m] [--json]\n\nShort-lived recovery path for over-firing gates. Allows hook settings edits and satisfies PR-create/thread-check gates without disabling core destructive-action protections.',
3155
3176
  serve: 'Usage: npx thumbgate serve\n\nStart the MCP stdio server. This is for agent runtimes, not the local HTTP dashboard.',
3156
3177
  mcp: 'Usage: npx thumbgate mcp\n\nAlias for `thumbgate serve`.',
@@ -3168,11 +3189,6 @@ const SUBCOMMAND_HELP = {
3168
3189
  'ai-inventory': 'Usage: npx thumbgate ai-inventory [--root <dir>] [--format=summary|json|cyclonedx] [--output <path>] [--max-files=N]\n\nScan source/manifests/model artifacts for AI, ML, agent-framework, vector DB, Vertex, Gemini, and Dialogflow CX components. Use --format=cyclonedx to produce exportable ML-BOM evidence for enterprise reviews.',
3169
3190
  brain: 'Usage: npx thumbgate brain [--write] [--json] [--limit=N]\n\nBuild the agent-readable "context brain" — a single artifact consolidating this\nrepo\'s lessons, prevention rules, active gates, and project context for a coding\nagent to read BEFORE acting. --write saves it to .thumbgate/BRAIN.md (versioned,\ndeterministic). --json emits the structured model. --limit caps lessons (default 15).',
3170
3191
  'team-sync': 'Usage: npx thumbgate team-sync\n\nSynchronize prevention rules and context brain with your team\'s git repository (git pull --rebase & git push), then auto-rebuild the local brain.',
3171
- dream: 'Usage: npx thumbgate dream [--min=N] [--feedback-dir=DIR] [--json]\n\nConsolidate raw history and lessons ("Silicon Dreaming"), merge duplicates, promote recurring failures to gates, and rebuild prevention rules + BRAIN.md.',
3172
- consolidate: 'Usage: npx thumbgate consolidate\n\nAlias for npx thumbgate dream.',
3173
- triage: 'Usage: npx thumbgate triage [--schedule="daily 9:00"] [--json]\n\nRun git updates, test verification, and memory consolidation, or schedule it on a cron.',
3174
- hygiene: 'Usage: npx thumbgate hygiene\n\nAlias for npx thumbgate triage.',
3175
- community: 'Usage: npx thumbgate community query <error> | share <rule-id>\n\nQuery or share verified prevention rules with the community knowledge registry.',
3176
3192
  };
3177
3193
 
3178
3194
  if (_wantsHelp && COMMAND && SUBCOMMAND_HELP[COMMAND]) {
@@ -3275,31 +3291,6 @@ function renderBrainMarkdown(model) {
3275
3291
  return out.join('\n');
3276
3292
  }
3277
3293
 
3278
- function autoWireInstructionFile(fileName) {
3279
- const filePath = path.join(CWD, fileName);
3280
- if (!fs.existsSync(filePath)) return;
3281
- try {
3282
- let content = fs.readFileSync(filePath, 'utf8');
3283
- const blockStart = '<!-- ThumbGate -->';
3284
- const blockEnd = '<!-- End ThumbGate -->';
3285
- const block = `${blockStart}\nIMPORTANT: Read .thumbgate/BRAIN.md first for lessons, prevention rules, and active gates in this repo.\n${blockEnd}\n`;
3286
-
3287
- if (content.includes(blockStart)) {
3288
- const startIdx = content.indexOf(blockStart);
3289
- const endIdx = content.indexOf(blockEnd);
3290
- if (endIdx !== -1) {
3291
- content = content.slice(0, startIdx) + block + content.slice(endIdx + blockEnd.length).replace(/^\n+/, '');
3292
- }
3293
- } else {
3294
- content = block + '\n' + content;
3295
- }
3296
- fs.writeFileSync(filePath, content);
3297
- console.error(` Auto-wired agent pointer into ${fileName}`);
3298
- } catch (err) {
3299
- console.warn(`⚠️ Failed to auto-wire agent pointer in ${fileName}: ${err.message}`);
3300
- }
3301
- }
3302
-
3303
3294
  function cmdBrain(args = {}) {
3304
3295
  const model = buildBrainModel({ limit: args.limit });
3305
3296
  if (args.json) { console.log(JSON.stringify(model, null, 2)); return 0; }
@@ -3319,120 +3310,14 @@ function cmdBrain(args = {}) {
3319
3310
  const lt = (model.lessons && model.lessons.total) || 0;
3320
3311
  const rt = (model.rules && model.rules.total) || 0;
3321
3312
  const gt = (model.gates && model.gates.total) || 0;
3322
- console.error(`\u{1f9e0} Wrote context brain to .thumbgate/BRAIN.md (${lt} lessons · ${rt} rules · ${gt} gates).`);
3323
-
3324
- // Auto-inject pointer block into CLAUDE.md / AGENTS.md
3325
- autoWireInstructionFile('CLAUDE.md');
3326
- autoWireInstructionFile('AGENTS.md');
3327
-
3313
+ console.log(`\u{1f9e0} Wrote context brain to .thumbgate/BRAIN.md (${lt} lessons · ${rt} rules · ${gt} gates).`);
3314
+ console.log(' Point your agent at it: add "Read .thumbgate/BRAIN.md first" to CLAUDE.md / AGENTS.md.');
3328
3315
  return 0;
3329
3316
  }
3330
3317
  process.stdout.write(md);
3331
3318
  return 0;
3332
3319
  }
3333
3320
 
3334
- function brain() {
3335
- const args = parseArgs(process.argv.slice(3));
3336
- const subcommand = process.argv.slice(3).find((arg) => !arg.startsWith('--')) || 'status';
3337
- const {
3338
- buildContextPack,
3339
- checkNeverDo,
3340
- cleanupReport,
3341
- ensureBrain,
3342
- formatContextPack,
3343
- recordMemory,
3344
- refreshNeverDoGates,
3345
- } = require(path.join(PKG_ROOT, 'scripts', 'brain'));
3346
-
3347
- if (subcommand === 'init' || subcommand === 'status') {
3348
- const result = ensureBrain(CWD);
3349
- const gates = refreshNeverDoGates(CWD);
3350
- const payload = { ...result, gateCount: gates.gateCount };
3351
- if (args.json) {
3352
- console.log(JSON.stringify(payload, null, 2));
3353
- return;
3354
- }
3355
- console.log('ThumbGate brain');
3356
- console.log('='.repeat(15));
3357
- console.log(`Brain dir : ${path.relative(CWD, result.brainDir)}`);
3358
- console.log(`Created : ${result.created.length}`);
3359
- console.log(`Soul files: ${result.soulFiles.length}`);
3360
- console.log(`Memory dirs: ${result.memoryDirs.length}`);
3361
- console.log(`Never-do gates: ${gates.gateCount}`);
3362
- return;
3363
- }
3364
-
3365
- if (subcommand === 'context') {
3366
- const task = args.task || process.argv.slice(4).find((arg) => !arg.startsWith('--')) || '';
3367
- const pack = buildContextPack(CWD, { task });
3368
- if (args.json) {
3369
- console.log(JSON.stringify(pack, null, 2));
3370
- return;
3371
- }
3372
- process.stdout.write(formatContextPack(pack));
3373
- return;
3374
- }
3375
-
3376
- if (subcommand === 'remember') {
3377
- const title = args.title || process.argv.slice(4).find((arg) => !arg.startsWith('--')) || '';
3378
- const result = recordMemory(CWD, {
3379
- type: args.type,
3380
- title,
3381
- content: args.content || title,
3382
- reason: args.reason,
3383
- source: args.source,
3384
- tags: args.tags,
3385
- date: args.date,
3386
- });
3387
- if (args.json) {
3388
- console.log(JSON.stringify(result, null, 2));
3389
- return;
3390
- }
3391
- if (!result.ok) {
3392
- console.error(result.error);
3393
- process.exit(1);
3394
- }
3395
- console.log(`Stored brain memory: ${result.path}`);
3396
- return;
3397
- }
3398
-
3399
- if (subcommand === 'check') {
3400
- const text = args.text || args.action || readStdinText();
3401
- const result = checkNeverDo(CWD, { text });
3402
- if (args.json) {
3403
- console.log(JSON.stringify(result, null, 2));
3404
- if (!result.ok) process.exit(2);
3405
- return;
3406
- }
3407
- console.log(`ThumbGate brain decision: ${result.decision.toUpperCase()}`);
3408
- for (const rule of result.blocked) console.log(`- ${rule.text}`);
3409
- if (!result.ok) process.exit(2);
3410
- return;
3411
- }
3412
-
3413
- if (subcommand === 'cleanup') {
3414
- const report = cleanupReport(CWD, args);
3415
- if (args.json) {
3416
- console.log(JSON.stringify(report, null, 2));
3417
- return;
3418
- }
3419
- console.log('ThumbGate brain cleanup report');
3420
- console.log('='.repeat(31));
3421
- console.log(`Memory files: ${report.total}`);
3422
- console.log(`Unsourced : ${report.unsourced.length}`);
3423
- console.log(`Stale : ${report.stale.length}`);
3424
- console.log(`Duplicates : ${report.duplicates.length}`);
3425
- if (report.unsourced.length) {
3426
- console.log('\nUnsourced files:');
3427
- for (const filePath of report.unsourced) console.log(`- ${filePath}`);
3428
- }
3429
- return;
3430
- }
3431
-
3432
- console.error('Usage: npx thumbgate brain init|context|remember|check|cleanup [--json]');
3433
- process.exit(1);
3434
- }
3435
-
3436
3321
  async function teamSync() {
3437
3322
  const { execSync } = require('child_process');
3438
3323
 
@@ -3611,127 +3496,6 @@ switch (COMMAND) {
3611
3496
  }
3612
3497
  break;
3613
3498
  }
3614
- case 'dream':
3615
- case 'consolidate': {
3616
- const args = parseArgs(process.argv.slice(3));
3617
- const { dream } = require(path.join(PKG_ROOT, 'scripts', 'dream-consolidation'));
3618
- dream({
3619
- pkgRoot: PKG_ROOT,
3620
- feedbackDir: args['feedback-dir'] || args.feedbackDir || CWD,
3621
- rulesPath: args.output || path.join(CWD, '.thumbgate', 'prevention-rules.md'),
3622
- minOccurrences: args.min || 2,
3623
- }).then(async (result) => {
3624
- try {
3625
- await cmdBrain({ write: true });
3626
- } catch (brainErr) {
3627
- console.warn(`⚠️ Failed to rebuild context brain: ${brainErr.message}`);
3628
- }
3629
- if (args.json) {
3630
- console.log(JSON.stringify(result, null, 2));
3631
- } else {
3632
- console.log(`✨ [Dreaming] Consolidation complete! Merged ${result.consolidated} duplicate(s) into ${result.lessonsCount} lessons.`);
3633
- }
3634
- process.exit(0);
3635
- }).catch((err) => {
3636
- console.error('❌ Error during memory consolidation:', err && err.message ? err.message : err);
3637
- process.exit(1);
3638
- });
3639
- break;
3640
- }
3641
- case 'triage':
3642
- case 'hygiene': {
3643
- const args = parseArgs(process.argv.slice(3));
3644
- const { runTriageLoop } = require(path.join(PKG_ROOT, 'scripts', 'triage-loop'));
3645
-
3646
- if (args.schedule) {
3647
- const { createSchedule } = require(path.join(PKG_ROOT, 'scripts', 'schedule-manager'));
3648
- const scheduleResult = createSchedule({
3649
- id: 'thumbgate-triage-hygiene',
3650
- name: 'ThumbGate Triage & Hygiene Loop',
3651
- description: 'Run autonomous git checks, test suite verification, and Silicon Dreaming memory consolidation.',
3652
- schedule: args.schedule,
3653
- command: `const { runTriageLoop } = require('${path.join(PKG_ROOT, 'scripts', 'triage-loop')}'); runTriageLoop({ cwd: '${CWD}', pkgRoot: '${PKG_ROOT}' }).catch(console.error);`,
3654
- workingDirectory: CWD,
3655
- });
3656
- if (args.json) {
3657
- console.log(JSON.stringify(scheduleResult, null, 2));
3658
- } else {
3659
- if (scheduleResult.success) {
3660
- console.log(`✅ [Triage] Scheduled triage hygiene loop: ${scheduleResult.message}`);
3661
- } else {
3662
- console.error(`❌ [Triage] Failed to schedule: ${scheduleResult.error}`);
3663
- process.exit(1);
3664
- }
3665
- }
3666
- break;
3667
- }
3668
-
3669
- runTriageLoop({
3670
- cwd: CWD,
3671
- pkgRoot: PKG_ROOT,
3672
- }).then(async (result) => {
3673
- try {
3674
- await cmdBrain({ write: true });
3675
- } catch (brainErr) {
3676
- console.warn(`⚠️ Failed to rebuild context brain: ${brainErr.message}`);
3677
- }
3678
- if (args.json) {
3679
- console.log(JSON.stringify(result, null, 2));
3680
- } else {
3681
- console.log(result.log);
3682
- }
3683
- process.exit(0);
3684
- }).catch((err) => {
3685
- console.error('❌ Error during triage loop execution:', err && err.message ? err.message : err);
3686
- process.exit(1);
3687
- });
3688
- break;
3689
- }
3690
- case 'community': {
3691
- const args = parseArgs(process.argv.slice(3));
3692
- const sub = process.argv.slice(3).find((arg) => !arg.startsWith('--'));
3693
- const { queryCommunity, shareRule } = require(path.join(PKG_ROOT, 'scripts', 'community-knowledge'));
3694
-
3695
- if (sub === 'query') {
3696
- const queryIdx = process.argv.indexOf('query');
3697
- const queryText = process.argv.slice(queryIdx + 1).filter(arg => !arg.startsWith('--')).join(' ');
3698
- const result = queryCommunity(queryText, { remote: args.remote });
3699
- if (args.json) {
3700
- console.log(JSON.stringify(result, null, 2));
3701
- } else {
3702
- console.log(`🔍 Found ${result.resultsCount} community rule(s) matching "${result.query}":`);
3703
- for (const r of result.results) {
3704
- console.log(`\n- [${r.id}] ${r.rule}`);
3705
- console.log(` Remedy: ${r.remedy}`);
3706
- console.log(` Explanation: ${r.explanation}`);
3707
- }
3708
- }
3709
- process.exit(0);
3710
- } else if (sub === 'share') {
3711
- const shareIdx = process.argv.indexOf('share');
3712
- const ruleId = process.argv.slice(shareIdx + 1).find(arg => !arg.startsWith('--'));
3713
- if (!ruleId) {
3714
- console.error('❌ Error: rule ID is required for share subcommand.');
3715
- process.exit(1);
3716
- }
3717
- const result = shareRule(ruleId, { feedbackDir: CWD });
3718
- if (args.json) {
3719
- console.log(JSON.stringify(result, null, 2));
3720
- } else {
3721
- if (result.ok) {
3722
- console.log(`✨ Successfully shared rule "${ruleId}" to community registry.`);
3723
- } else {
3724
- console.error(`❌ Failed to share rule: ${result.error}`);
3725
- process.exit(1);
3726
- }
3727
- }
3728
- process.exit(0);
3729
- } else {
3730
- console.error('Usage: npx thumbgate community query <error> | share <rule-id> [--json]');
3731
- process.exit(1);
3732
- }
3733
- break;
3734
- }
3735
3499
  case 'billing:setup':
3736
3500
  require(path.join(PKG_ROOT, 'scripts', 'billing-setup'));
3737
3501
  break;
@@ -4099,6 +3863,14 @@ switch (COMMAND) {
4099
3863
  case 'pulse':
4100
3864
  pulse();
4101
3865
  break;
3866
+ case 'check-update':
3867
+ case 'upgrade-check':
3868
+ checkUpdateCmd();
3869
+ break;
3870
+ case 'self-update':
3871
+ case 'upgrade-cli':
3872
+ selfUpdateCmd();
3873
+ break;
4102
3874
  case 'dispatch':
4103
3875
  case 'dispatch-brief':
4104
3876
  dispatchBrief();
@@ -4124,6 +3896,53 @@ switch (COMMAND) {
4124
3896
  });
4125
3897
  break;
4126
3898
  }
3899
+ case 'hermes-gate': {
3900
+ // Nous Research Hermes Agent `pre_tool_call` shell hook.
3901
+ // Hermes pipes each pending tool call as JSON to stdin and reads a decision from stdout;
3902
+ // {"decision":"block","reason":...} vetoes the call. We reuse the SAME gate pipeline as
3903
+ // `gate-check` (runAsync → secret guard, security scan, force-push / skill_manage / learned
3904
+ // prevention rules) and translate the verdict into Hermes's format.
3905
+ //
3906
+ // Hermes `pre_tool_call` is binary (block or allow) with no warn channel, and the whole point
3907
+ // of wiring it is to gate, so we run STRICT enforcement by default — otherwise ThumbGate's
3908
+ // warn-by-default posture would pass every deny through and the hook would block nothing.
3909
+ // Opt out with THUMBGATE_HERMES_WARN_ONLY=1; THUMBGATE_HOTFIX_BYPASS=1 still disables checks.
3910
+ // Wire it in ~/.hermes/config.yaml — see adapters/hermes/config.yaml.
3911
+ if (process.env.THUMBGATE_HERMES_WARN_ONLY !== '1' && process.env.THUMBGATE_HOTFIX_BYPASS !== '1') {
3912
+ process.env.THUMBGATE_STRICT_ENFORCEMENT = '1';
3913
+ }
3914
+ const { runAsync: hermesGateRun } = require(path.join(PKG_ROOT, 'scripts', 'gates-engine'));
3915
+ let hermesStdin = '';
3916
+ process.stdin.setEncoding('utf8');
3917
+ process.stdin.on('data', (chunk) => { hermesStdin += chunk; });
3918
+ process.stdin.on('end', async () => {
3919
+ try {
3920
+ const payload = JSON.parse(hermesStdin);
3921
+ // Hermes sends snake_case tool_name/tool_input — gates-engine reads these directly.
3922
+ const verdict = await hermesGateRun({ tool_name: payload.tool_name, tool_input: payload.tool_input });
3923
+ let parsed = {};
3924
+ try { parsed = JSON.parse(verdict); } catch (_e) { parsed = {}; }
3925
+ const hso = parsed.hookSpecificOutput || {};
3926
+ if (hso.permissionDecision === 'deny') {
3927
+ process.stdout.write(JSON.stringify({
3928
+ decision: 'block',
3929
+ reason: hso.permissionDecisionReason || 'Blocked by ThumbGate prevention rule.',
3930
+ }) + '\n');
3931
+ } else {
3932
+ // warn / no match → allow. The gate engine already logged the decision.
3933
+ process.stdout.write(JSON.stringify({}) + '\n');
3934
+ }
3935
+ process.exit(0);
3936
+ } catch (err) {
3937
+ // Hermes hooks fail OPEN on error/timeout — emit an explicit allow so a gate fault
3938
+ // never wedges the agent (reliability ≈ enforcement; keep this fast).
3939
+ process.stderr.write(`hermes-gate error: ${err.message}\n`);
3940
+ process.stdout.write(JSON.stringify({}) + '\n');
3941
+ process.exit(0);
3942
+ }
3943
+ });
3944
+ break;
3945
+ }
4127
3946
  case 'gate-stats':
4128
3947
  gateStats();
4129
3948
  break;
@@ -0,0 +1,23 @@
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
+ }