thumbgate 1.25.2 → 1.26.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/marketplace.json +2 -2
- package/.claude-plugin/plugin.json +1 -1
- package/.well-known/mcp/server-card.json +1 -1
- package/README.md +62 -31
- package/adapters/claude/.mcp.json +2 -2
- package/adapters/mcp/server-stdio.js +84 -7
- package/adapters/opencode/opencode.json +1 -1
- package/bin/cli.js +390 -14
- package/config/mcp-allowlists.json +3 -0
- package/package.json +16 -3
- package/public/agents-cost-savings.html +2 -0
- package/public/index.html +10 -2
- package/public/numbers.html +2 -2
- package/scripts/action-receipts.js +324 -0
- package/scripts/cli-schema.js +24 -0
- package/scripts/context-manager.js +10 -0
- package/scripts/dashboard.js +6 -1
- package/scripts/gates-engine.js +68 -9
- package/scripts/install-shim.js +84 -0
- package/scripts/llm-client.js +90 -4
- package/scripts/local-model-profile.js +15 -8
- package/scripts/meta-agent-loop.js +9 -5
- package/scripts/noop-detect.js +285 -0
- package/scripts/operational-dashboard.js +160 -0
- package/scripts/plan-gate.js +243 -0
- package/scripts/repeat-metric.js +121 -0
- package/scripts/silent-failure-cluster.js +22 -3
- package/scripts/thompson-sampling.js +20 -5
- package/scripts/tool-registry.js +50 -0
- package/scripts/trajectory-scorer.js +63 -0
package/bin/cli.js
CHANGED
|
@@ -29,6 +29,7 @@
|
|
|
29
29
|
'use strict';
|
|
30
30
|
|
|
31
31
|
const fs = require('fs');
|
|
32
|
+
const os = require('os');
|
|
32
33
|
const path = require('path');
|
|
33
34
|
const crypto = require('crypto');
|
|
34
35
|
const { execSync, execFileSync } = require('child_process');
|
|
@@ -610,6 +611,91 @@ function detectAgent(projectDir) {
|
|
|
610
611
|
return null;
|
|
611
612
|
}
|
|
612
613
|
|
|
614
|
+
async function setupVertex() {
|
|
615
|
+
const { execSync } = require('child_process');
|
|
616
|
+
console.log(`\nthumbgate setup-vertex v${pkgVersion()}`);
|
|
617
|
+
console.log(' Zero-friction Google Cloud & Vertex AI onboarding...');
|
|
618
|
+
console.log('');
|
|
619
|
+
|
|
620
|
+
// 1. Detect gcloud CLI
|
|
621
|
+
let activeAccount = '';
|
|
622
|
+
let activeProject = '';
|
|
623
|
+
try {
|
|
624
|
+
activeAccount = execSync('gcloud config get-value account', { stdio: ['ignore', 'pipe', 'ignore'] }).toString().trim();
|
|
625
|
+
activeProject = execSync('gcloud config get-value project', { stdio: ['ignore', 'pipe', 'ignore'] }).toString().trim();
|
|
626
|
+
} catch (_) {
|
|
627
|
+
console.log(' ⚠️ Google Cloud SDK (gcloud CLI) not detected or not logged in.');
|
|
628
|
+
console.log(' To automate setup, install the Google Cloud CLI and run: gcloud auth login');
|
|
629
|
+
console.log(' Otherwise, manually set the following variables in your .env file:');
|
|
630
|
+
console.log(' THUMBGATE_PROVIDER_MODE=vertex');
|
|
631
|
+
console.log(' VERTEX_PROJECT_ID=<your-gcp-project-id>');
|
|
632
|
+
console.log('');
|
|
633
|
+
return;
|
|
634
|
+
}
|
|
635
|
+
|
|
636
|
+
if (!activeAccount) {
|
|
637
|
+
console.log(' ⚠️ No active Google Cloud account set. Run: gcloud auth login');
|
|
638
|
+
return;
|
|
639
|
+
}
|
|
640
|
+
|
|
641
|
+
console.log(` Active Account : \x1b[36m${activeAccount}\x1b[0m`);
|
|
642
|
+
if (!activeProject) {
|
|
643
|
+
console.log(' ⚠️ No active Google Cloud project set. Run: gcloud config set project <PROJECT_ID>');
|
|
644
|
+
return;
|
|
645
|
+
}
|
|
646
|
+
console.log(` Active Project : \x1b[36m${activeProject}\x1b[0m`);
|
|
647
|
+
|
|
648
|
+
// Validate project ID matches GCP format before use in shell
|
|
649
|
+
if (!/^[a-z][a-z0-9-]{4,28}[a-z0-9]$/.test(activeProject)) {
|
|
650
|
+
console.log(' ⚠️ Invalid GCP project ID format. Aborting.');
|
|
651
|
+
return;
|
|
652
|
+
}
|
|
653
|
+
|
|
654
|
+
// 2. Auto-enable Vertex AI API
|
|
655
|
+
console.log(' ⚙️ Enabling Vertex AI API in your project (this can take a few seconds)...');
|
|
656
|
+
try {
|
|
657
|
+
execSync(`gcloud services enable aiplatform.googleapis.com --project=${activeProject}`, { stdio: 'inherit' });
|
|
658
|
+
console.log(' ✅ Vertex AI API successfully enabled.');
|
|
659
|
+
} catch (err) {
|
|
660
|
+
console.log(' ⚠️ Could not programmatically enable Vertex AI API. Please make sure your billing is open.');
|
|
661
|
+
}
|
|
662
|
+
|
|
663
|
+
// 3. Write env config to .env
|
|
664
|
+
const envPath = path.join(process.cwd(), '.env');
|
|
665
|
+
let envContent = '';
|
|
666
|
+
if (fs.existsSync(envPath)) {
|
|
667
|
+
envContent = fs.readFileSync(envPath, 'utf8');
|
|
668
|
+
}
|
|
669
|
+
|
|
670
|
+
// Helper to update or append env values
|
|
671
|
+
function updateEnvKey(content, key, value) {
|
|
672
|
+
const regex = new RegExp(`^${key}=.*$`, 'm');
|
|
673
|
+
if (regex.test(content)) {
|
|
674
|
+
return content.replace(regex, `${key}=${value}`);
|
|
675
|
+
}
|
|
676
|
+
return content.trim() + `\n${key}=${value}\n`;
|
|
677
|
+
}
|
|
678
|
+
|
|
679
|
+
let updatedContent = updateEnvKey(envContent, 'THUMBGATE_PROVIDER_MODE', 'vertex');
|
|
680
|
+
updatedContent = updateEnvKey(updatedContent, 'VERTEX_PROJECT_ID', activeProject);
|
|
681
|
+
|
|
682
|
+
fs.writeFileSync(envPath, updatedContent, 'utf8');
|
|
683
|
+
console.log(' ✅ Wrote configuration to local .env file.');
|
|
684
|
+
|
|
685
|
+
// 4. Print gorgeous success activation box
|
|
686
|
+
console.log('');
|
|
687
|
+
console.log(' ╭──────────────────────────────────────────────────────────╮');
|
|
688
|
+
console.log(' │ 🎉 Vertex AI Setup Complete — ZERO FRICTION! │');
|
|
689
|
+
console.log(' │ │');
|
|
690
|
+
console.log(' │ ThumbGate is now fully wired to your GCP environment. │');
|
|
691
|
+
console.log(' │ All agent checks will route securely via Vertex AI. │');
|
|
692
|
+
console.log(' │ │');
|
|
693
|
+
console.log(' │ Try a test run: │');
|
|
694
|
+
console.log(' │ npx thumbgate feedback-self-test │');
|
|
695
|
+
console.log(' ╰──────────────────────────────────────────────────────────╯');
|
|
696
|
+
console.log('');
|
|
697
|
+
}
|
|
698
|
+
|
|
613
699
|
function quickStart() {
|
|
614
700
|
const qsArgs = parseArgs(process.argv.slice(3));
|
|
615
701
|
const projectDir = process.cwd();
|
|
@@ -845,17 +931,12 @@ function init(cliArgs = parseArgs(process.argv.slice(3))) {
|
|
|
845
931
|
// ---------------------------------------------------------------------------
|
|
846
932
|
console.log('');
|
|
847
933
|
console.log(' ╭──────────────────────────────────────────────────────────╮');
|
|
848
|
-
console.log(' │ NEXT:
|
|
934
|
+
console.log(' │ NEXT: Prove feedback capture works │');
|
|
849
935
|
console.log(' │ │');
|
|
850
|
-
console.log(' │
|
|
936
|
+
console.log(' │ npx thumbgate feedback-self-test │');
|
|
851
937
|
console.log(' │ │');
|
|
852
|
-
console.log(' │
|
|
853
|
-
console.log(' │
|
|
854
|
-
console.log(' │ --what-went-wrong="ran rm on .env" \\ │');
|
|
855
|
-
console.log(' │ --what-to-change="never delete .env files" │');
|
|
856
|
-
console.log(' │ │');
|
|
857
|
-
console.log(' │ ThumbGate auto-promotes this to a prevention rule │');
|
|
858
|
-
console.log(' │ that blocks the mistake from happening again. │');
|
|
938
|
+
console.log(' │ Then dogfood it in chat: │');
|
|
939
|
+
console.log(' │ thumbs down: agent skipped verification │');
|
|
859
940
|
console.log(' ╰──────────────────────────────────────────────────────────╯');
|
|
860
941
|
console.log('');
|
|
861
942
|
printInitConversionPrompt(onboardingEmail);
|
|
@@ -906,13 +987,35 @@ function capture() {
|
|
|
906
987
|
return;
|
|
907
988
|
}
|
|
908
989
|
|
|
909
|
-
|
|
990
|
+
// Parse pure positional arguments
|
|
991
|
+
const rawArgv = process.argv.slice(3);
|
|
992
|
+
const positionalArgs = [];
|
|
993
|
+
const BOOLEAN_FLAGS = new Set(['--json', '--verbose', '--quiet', '--dry-run', '--stats', '--summary', '--no-nudge', '--help']);
|
|
994
|
+
for (let i = 0; i < rawArgv.length; i++) {
|
|
995
|
+
const arg = rawArgv[i];
|
|
996
|
+
if (arg.startsWith('--')) {
|
|
997
|
+
if (!arg.includes('=') && !BOOLEAN_FLAGS.has(arg)) {
|
|
998
|
+
i++;
|
|
999
|
+
}
|
|
1000
|
+
} else {
|
|
1001
|
+
positionalArgs.push(arg);
|
|
1002
|
+
}
|
|
1003
|
+
}
|
|
1004
|
+
|
|
1005
|
+
let signal = (args.feedback || '').toLowerCase();
|
|
1006
|
+
if (!signal && positionalArgs[0]) {
|
|
1007
|
+
const firstPos = positionalArgs[0].toLowerCase();
|
|
1008
|
+
if (['up', 'down', 'thumbsup', 'thumbsdown', 'thumbs_up', 'thumbs_down', 'positive', 'negative'].some(v => firstPos.includes(v))) {
|
|
1009
|
+
signal = firstPos;
|
|
1010
|
+
}
|
|
1011
|
+
}
|
|
1012
|
+
|
|
910
1013
|
const normalized = ['up', 'thumbsup', 'thumbs_up', 'positive'].some(v => signal.includes(v)) ? 'up'
|
|
911
1014
|
: ['down', 'thumbsdown', 'thumbs_down', 'negative'].some(v => signal.includes(v)) ? 'down'
|
|
912
1015
|
: signal;
|
|
913
1016
|
|
|
914
1017
|
if (normalized !== 'up' && normalized !== 'down') {
|
|
915
|
-
console.error('Missing or unrecognized --feedback=up|down');
|
|
1018
|
+
console.error('Missing or unrecognized --feedback=up|down (or positional argument)');
|
|
916
1019
|
process.exit(1);
|
|
917
1020
|
}
|
|
918
1021
|
|
|
@@ -922,11 +1025,30 @@ function capture() {
|
|
|
922
1025
|
process.exit(1);
|
|
923
1026
|
}
|
|
924
1027
|
|
|
1028
|
+
let context = args.context || '';
|
|
1029
|
+
if (!context && positionalArgs[1]) {
|
|
1030
|
+
context = positionalArgs[1];
|
|
1031
|
+
}
|
|
1032
|
+
|
|
1033
|
+
let whatWentWrong = args['what-went-wrong'];
|
|
1034
|
+
if (!whatWentWrong && positionalArgs[2]) {
|
|
1035
|
+
whatWentWrong = positionalArgs[2];
|
|
1036
|
+
} else if (!whatWentWrong && normalized === 'down' && context) {
|
|
1037
|
+
whatWentWrong = context;
|
|
1038
|
+
}
|
|
1039
|
+
|
|
1040
|
+
let whatToChange = args['what-to-change'];
|
|
1041
|
+
if (!whatToChange && positionalArgs[3]) {
|
|
1042
|
+
whatToChange = positionalArgs[3];
|
|
1043
|
+
} else if (!whatToChange && normalized === 'down' && context) {
|
|
1044
|
+
whatToChange = `avoid: ${context}`;
|
|
1045
|
+
}
|
|
1046
|
+
|
|
925
1047
|
const result = captureFeedback({
|
|
926
1048
|
signal: normalized,
|
|
927
|
-
context:
|
|
928
|
-
whatWentWrong:
|
|
929
|
-
whatToChange:
|
|
1049
|
+
context: context,
|
|
1050
|
+
whatWentWrong: whatWentWrong,
|
|
1051
|
+
whatToChange: whatToChange,
|
|
930
1052
|
whatWorked: args['what-worked'],
|
|
931
1053
|
tags: args.tags,
|
|
932
1054
|
gateAction: gateAction || undefined,
|
|
@@ -989,6 +1111,116 @@ function capture() {
|
|
|
989
1111
|
}
|
|
990
1112
|
}
|
|
991
1113
|
|
|
1114
|
+
function readJsonlEntries(filePath) {
|
|
1115
|
+
try {
|
|
1116
|
+
return fs.readFileSync(filePath, 'utf8')
|
|
1117
|
+
.split(/\r?\n/)
|
|
1118
|
+
.map((line) => line.trim())
|
|
1119
|
+
.filter(Boolean)
|
|
1120
|
+
.map((line) => JSON.parse(line));
|
|
1121
|
+
} catch (_) {
|
|
1122
|
+
return [];
|
|
1123
|
+
}
|
|
1124
|
+
}
|
|
1125
|
+
|
|
1126
|
+
function shellSingleQuote(value) {
|
|
1127
|
+
return `'${String(value).replace(/'/g, `'\\''`)}'`;
|
|
1128
|
+
}
|
|
1129
|
+
|
|
1130
|
+
function feedbackSelfTest() {
|
|
1131
|
+
const args = parseArgs(process.argv.slice(3));
|
|
1132
|
+
const signalArg = String(args.feedback || args.signal || 'down').toLowerCase();
|
|
1133
|
+
const normalized = ['up', 'thumbsup', 'thumbs_up', 'positive'].some((v) => signalArg.includes(v)) ? 'up'
|
|
1134
|
+
: ['down', 'thumbsdown', 'thumbs_down', 'negative'].some((v) => signalArg.includes(v)) ? 'down'
|
|
1135
|
+
: signalArg;
|
|
1136
|
+
|
|
1137
|
+
if (normalized !== 'up' && normalized !== 'down') {
|
|
1138
|
+
console.error('feedback-self-test needs --feedback=up|down when overriding the default.');
|
|
1139
|
+
process.exit(1);
|
|
1140
|
+
}
|
|
1141
|
+
|
|
1142
|
+
const previousFeedbackDir = process.env.THUMBGATE_FEEDBACK_DIR;
|
|
1143
|
+
const previousNoNudge = process.env.THUMBGATE_NO_NUDGE;
|
|
1144
|
+
const feedbackDir = args['feedback-dir']
|
|
1145
|
+
? path.resolve(CWD, args['feedback-dir'])
|
|
1146
|
+
: args.persist
|
|
1147
|
+
? null
|
|
1148
|
+
: fs.mkdtempSync(path.join(os.tmpdir(), 'thumbgate-feedback-self-test-'));
|
|
1149
|
+
const isolated = Boolean(feedbackDir);
|
|
1150
|
+
|
|
1151
|
+
if (feedbackDir) process.env.THUMBGATE_FEEDBACK_DIR = feedbackDir;
|
|
1152
|
+
process.env.THUMBGATE_NO_NUDGE = '1';
|
|
1153
|
+
|
|
1154
|
+
try {
|
|
1155
|
+
const { captureFeedback, getFeedbackPaths } = require(path.join(PKG_ROOT, 'scripts', 'feedback-loop'));
|
|
1156
|
+
const context = args.context || `feedback self-test: typed thumbs ${normalized} reaches ThumbGate capture`;
|
|
1157
|
+
const result = captureFeedback({
|
|
1158
|
+
signal: normalized,
|
|
1159
|
+
context,
|
|
1160
|
+
whatWentWrong: normalized === 'down'
|
|
1161
|
+
? (args['what-went-wrong'] || 'Need proof that feedback capture is wired in this runtime')
|
|
1162
|
+
: undefined,
|
|
1163
|
+
whatToChange: normalized === 'down'
|
|
1164
|
+
? (args['what-to-change'] || 'Run a one-command self-test before claiming thumbs feedback is captured')
|
|
1165
|
+
: undefined,
|
|
1166
|
+
whatWorked: normalized === 'up'
|
|
1167
|
+
? (args['what-worked'] || 'Feedback capture persisted and was verified by a self-test')
|
|
1168
|
+
: undefined,
|
|
1169
|
+
tags: args.tags || 'self-test,dogfood,feedback-capture',
|
|
1170
|
+
});
|
|
1171
|
+
|
|
1172
|
+
const paths = getFeedbackPaths();
|
|
1173
|
+
const feedbackRows = readJsonlEntries(paths.FEEDBACK_LOG_PATH);
|
|
1174
|
+
const memoryRows = readJsonlEntries(paths.MEMORY_LOG_PATH);
|
|
1175
|
+
const feedbackId = result.feedbackEvent && result.feedbackEvent.id;
|
|
1176
|
+
const memoryId = result.memoryRecord && result.memoryRecord.id;
|
|
1177
|
+
const feedbackStored = Boolean(feedbackId && feedbackRows.some((row) => row.id === feedbackId));
|
|
1178
|
+
const memoryStored = Boolean(memoryId && memoryRows.some((row) => row.id === memoryId));
|
|
1179
|
+
const ok = Boolean(result.accepted && feedbackStored && memoryStored);
|
|
1180
|
+
|
|
1181
|
+
const payload = {
|
|
1182
|
+
ok,
|
|
1183
|
+
command: 'feedback-self-test',
|
|
1184
|
+
signal: normalized,
|
|
1185
|
+
accepted: Boolean(result.accepted),
|
|
1186
|
+
feedbackId: feedbackId || null,
|
|
1187
|
+
memoryId: memoryId || null,
|
|
1188
|
+
feedbackStored,
|
|
1189
|
+
memoryStored,
|
|
1190
|
+
isolated,
|
|
1191
|
+
feedbackDir: paths.FEEDBACK_DIR,
|
|
1192
|
+
nextDogfoodCommand: `npx thumbgate capture --feedback=${normalized} --context=${shellSingleQuote(context)}`,
|
|
1193
|
+
};
|
|
1194
|
+
|
|
1195
|
+
if (args.json) {
|
|
1196
|
+
console.log(JSON.stringify(payload, null, 2));
|
|
1197
|
+
} else if (ok) {
|
|
1198
|
+
console.log('\nThumbGate feedback self-test: PASS');
|
|
1199
|
+
console.log('─'.repeat(50));
|
|
1200
|
+
console.log(` Captured : ${normalized} (${feedbackId})`);
|
|
1201
|
+
console.log(` Stored lesson: ${memoryId}`);
|
|
1202
|
+
console.log(` Storage : ${paths.FEEDBACK_DIR}`);
|
|
1203
|
+
console.log(` Mode : ${isolated ? 'isolated test store' : 'active ThumbGate store'}`);
|
|
1204
|
+
console.log('\nDogfood in chat with:');
|
|
1205
|
+
console.log(` thumbs ${normalized}: ${context}`);
|
|
1206
|
+
} else {
|
|
1207
|
+
console.log('\nThumbGate feedback self-test: FAIL');
|
|
1208
|
+
console.log('─'.repeat(50));
|
|
1209
|
+
console.log(` Accepted : ${payload.accepted}`);
|
|
1210
|
+
console.log(` Feedback stored: ${feedbackStored}`);
|
|
1211
|
+
console.log(` Memory stored : ${memoryStored}`);
|
|
1212
|
+
console.log(` Storage : ${paths.FEEDBACK_DIR}`);
|
|
1213
|
+
}
|
|
1214
|
+
|
|
1215
|
+
if (!ok) process.exit(2);
|
|
1216
|
+
} finally {
|
|
1217
|
+
if (previousFeedbackDir === undefined) delete process.env.THUMBGATE_FEEDBACK_DIR;
|
|
1218
|
+
else process.env.THUMBGATE_FEEDBACK_DIR = previousFeedbackDir;
|
|
1219
|
+
if (previousNoNudge === undefined) delete process.env.THUMBGATE_NO_NUDGE;
|
|
1220
|
+
else process.env.THUMBGATE_NO_NUDGE = previousNoNudge;
|
|
1221
|
+
}
|
|
1222
|
+
}
|
|
1223
|
+
|
|
992
1224
|
function stats() {
|
|
993
1225
|
trackEvent('cli_stats', { command: 'stats' });
|
|
994
1226
|
const args = parseArgs(process.argv.slice(3));
|
|
@@ -2456,12 +2688,14 @@ function help() {
|
|
|
2456
2688
|
console.log('');
|
|
2457
2689
|
console.log('Common commands:');
|
|
2458
2690
|
console.log(' init Detect agent and wire ThumbGate hooks');
|
|
2691
|
+
console.log(' feedback-self-test Prove thumbs capture works locally');
|
|
2459
2692
|
console.log(' capture --feedback=up|down --context="<text>" Capture a thumbs signal as a stored lesson');
|
|
2460
2693
|
console.log(' stats Approval rate, recent trend, blocked-pattern count');
|
|
2461
2694
|
console.log(' lessons [query] Search promoted lessons');
|
|
2462
2695
|
console.log(' explore Interactive TUI for lessons, gates, stats');
|
|
2463
2696
|
console.log(' dashboard Open the local ThumbGate dashboard');
|
|
2464
2697
|
console.log(' doctor Audit runtime isolation + bootstrap context');
|
|
2698
|
+
console.log(' brain [--write] Build the agent-readable context brain (lessons + rules + gates)');
|
|
2465
2699
|
console.log(' pro ThumbGate Pro (dashboard, exports, sync)');
|
|
2466
2700
|
console.log(' subscribe <email> Get the 5-min setup guide + weekly tips by email');
|
|
2467
2701
|
console.log('');
|
|
@@ -2557,6 +2791,7 @@ function help() {
|
|
|
2557
2791
|
|
|
2558
2792
|
console.log('Examples:');
|
|
2559
2793
|
console.log(' npx thumbgate init');
|
|
2794
|
+
console.log(' npx thumbgate feedback-self-test');
|
|
2560
2795
|
console.log(' npx thumbgate status --json');
|
|
2561
2796
|
console.log(' npx thumbgate explore lessons --json');
|
|
2562
2797
|
console.log(' npx thumbgate explore gates --json');
|
|
@@ -2598,6 +2833,8 @@ const _wantsHelp = _cliSubArgs.includes('--help') || _cliSubArgs.includes('-h');
|
|
|
2598
2833
|
const SUBCOMMAND_HELP = {
|
|
2599
2834
|
capture: 'Usage: npx thumbgate capture --feedback=up|down --context="..." [--what-worked="..."] [--what-went-wrong="..."] [--what-to-change="..."] [--tags=a,b]',
|
|
2600
2835
|
feedback: 'Usage: npx thumbgate feedback --feedback=up|down --context="..." [--what-worked="..."] [--what-went-wrong="..."] [--what-to-change="..."] [--tags=a,b]',
|
|
2836
|
+
'feedback-self-test': 'Usage: npx thumbgate feedback-self-test [--json] [--persist] [--feedback=up|down]\n\nCapture a synthetic thumbs signal and verify feedback-log + memory-log writes. Defaults to an isolated test store; use --persist to dogfood the active ThumbGate store.',
|
|
2837
|
+
dogfood: 'Usage: npx thumbgate dogfood [--json] [--persist] [--feedback=up|down]\n\nAlias for feedback-self-test.',
|
|
2601
2838
|
stats: 'Usage: npx thumbgate stats\n\nShow gate enforcement statistics: blocked/warned counts, active gates, time saved.',
|
|
2602
2839
|
trial: 'Usage: npx thumbgate trial\n\nShow Pro trial status, remaining days, and upgrade path.',
|
|
2603
2840
|
pro: 'Usage: npx thumbgate pro [--activate <key>]\n\nLaunch the local Pro dashboard or activate a Pro license key.',
|
|
@@ -2613,6 +2850,8 @@ const SUBCOMMAND_HELP = {
|
|
|
2613
2850
|
suggest: 'Usage: npx thumbgate suggest <gate-id>\n\nSuggest fixes for a specific gate based on lesson history.',
|
|
2614
2851
|
cost: 'Usage: npx thumbgate cost [--json] [--stats <path>] [--mix \'{"claude-sonnet-4-5":0.8,...}\']\n\nShow cumulative $ and tokens saved by PreToolUse gate blocks. Reads ~/.thumbgate/gate-stats.json.',
|
|
2615
2852
|
savings: 'Usage: npx thumbgate savings [--json] [--stats <path>] [--mix \'{"claude-sonnet-4-5":0.8,...}\']\n\nAlias for `thumbgate cost`.',
|
|
2853
|
+
'setup-vertex': 'Usage: npx thumbgate setup-vertex\n\nAuto-enable Vertex AI API on GCP and write secure credentials to local .env.',
|
|
2854
|
+
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).',
|
|
2616
2855
|
};
|
|
2617
2856
|
|
|
2618
2857
|
if (_wantsHelp && COMMAND && SUBCOMMAND_HELP[COMMAND]) {
|
|
@@ -2620,6 +2859,128 @@ if (_wantsHelp && COMMAND && SUBCOMMAND_HELP[COMMAND]) {
|
|
|
2620
2859
|
process.exit(0);
|
|
2621
2860
|
}
|
|
2622
2861
|
|
|
2862
|
+
// -----------------------------------------------------------------------------
|
|
2863
|
+
// brain — consolidate ThumbGate's institutional memory (lessons + prevention
|
|
2864
|
+
// rules + active gates + project context) into a single, versioned,
|
|
2865
|
+
// agent-readable "context brain". The persistent context a coding agent should
|
|
2866
|
+
// read BEFORE acting, so it stops repeating mistakes. Composes the existing
|
|
2867
|
+
// explore-subcommands primitives; output is deterministic (no volatile
|
|
2868
|
+
// timestamp) so `.thumbgate/BRAIN.md` diffs only when the underlying memory
|
|
2869
|
+
// changes.
|
|
2870
|
+
// -----------------------------------------------------------------------------
|
|
2871
|
+
function buildBrainModel(opts = {}) {
|
|
2872
|
+
const { exploreLessons, exploreRules, exploreGates } = require(path.join(PKG_ROOT, 'scripts', 'explore-subcommands'));
|
|
2873
|
+
let feedbackDir;
|
|
2874
|
+
try {
|
|
2875
|
+
const { getFeedbackPaths } = require(path.join(PKG_ROOT, 'scripts', 'feedback-loop'));
|
|
2876
|
+
feedbackDir = getFeedbackPaths().FEEDBACK_DIR;
|
|
2877
|
+
} catch (_) { feedbackDir = path.join(CWD, '.thumbgate'); }
|
|
2878
|
+
const limit = Math.max(1, Number(opts.limit) || 15);
|
|
2879
|
+
const safe = (fn, fallback) => { try { return fn(); } catch (_) { return fallback; } };
|
|
2880
|
+
const lessons = safe(() => exploreLessons({ feedbackDir, pkgRoot: PKG_ROOT, limit, json: true }), { lessons: [], total: 0 });
|
|
2881
|
+
const rules = safe(() => exploreRules({ feedbackDir, pkgRoot: PKG_ROOT, json: true }), { rules: [], total: 0 });
|
|
2882
|
+
const gates = safe(() => exploreGates({ feedbackDir, pkgRoot: PKG_ROOT, json: true }), { gates: [], total: 0 });
|
|
2883
|
+
const instructionFiles = ['CLAUDE.md', 'AGENTS.md', 'GEMINI.md', '.cursorrules', '.thumbgate/config.json']
|
|
2884
|
+
.filter((f) => { try { return fs.existsSync(path.join(CWD, f)); } catch (_) { return false; } });
|
|
2885
|
+
return { lessons, rules, gates, project: { root: CWD, instructionFiles } };
|
|
2886
|
+
}
|
|
2887
|
+
|
|
2888
|
+
function renderBrainMarkdown(model) {
|
|
2889
|
+
const out = [];
|
|
2890
|
+
out.push('# ThumbGate Context Brain');
|
|
2891
|
+
out.push('');
|
|
2892
|
+
out.push('<!-- The persistent context a coding agent should read BEFORE acting in this repo.');
|
|
2893
|
+
out.push(' Generated by `npx thumbgate brain`. Rebuild after capturing feedback. -->');
|
|
2894
|
+
out.push('');
|
|
2895
|
+
out.push('> Institutional memory for AI coding agents working here: what has been');
|
|
2896
|
+
out.push('> learned, what to avoid, and what is enforced. Read this first.');
|
|
2897
|
+
out.push('');
|
|
2898
|
+
|
|
2899
|
+
out.push('## What this codebase taught its agents (lessons)');
|
|
2900
|
+
out.push('');
|
|
2901
|
+
const lessons = (model.lessons && model.lessons.lessons) || [];
|
|
2902
|
+
if (!lessons.length) {
|
|
2903
|
+
out.push('_No lessons captured yet. Run `npx thumbgate capture --feedback=down --context="what failed"`._');
|
|
2904
|
+
} else {
|
|
2905
|
+
for (const l of lessons) {
|
|
2906
|
+
const sig = String(l.signal || '').toLowerCase();
|
|
2907
|
+
const mark = (sig.includes('positive') || sig === 'up') ? '✅' : ((sig.includes('negative') || sig === 'down') ? '⛔' : '•');
|
|
2908
|
+
const enforced = l.confidence === 'active' ? ' _(enforced)_' : '';
|
|
2909
|
+
const ctx = String(l.context || '').replace(/\s+/g, ' ').trim().slice(0, 220);
|
|
2910
|
+
if (ctx) out.push(`- ${mark} ${ctx}${enforced}`);
|
|
2911
|
+
}
|
|
2912
|
+
}
|
|
2913
|
+
out.push('');
|
|
2914
|
+
|
|
2915
|
+
out.push('## Guardrails — do NOT repeat these (prevention rules)');
|
|
2916
|
+
out.push('');
|
|
2917
|
+
const rules = (model.rules && model.rules.rules) || [];
|
|
2918
|
+
if (!rules.length) {
|
|
2919
|
+
out.push('_No prevention rules yet._');
|
|
2920
|
+
} else {
|
|
2921
|
+
for (const r of rules) {
|
|
2922
|
+
out.push(`- **${String(r.title || '').trim()}**`);
|
|
2923
|
+
const body = String(r.body || '').split('\n')[0].trim();
|
|
2924
|
+
if (body && body !== r.title) out.push(` - ${body.slice(0, 200)}`);
|
|
2925
|
+
}
|
|
2926
|
+
}
|
|
2927
|
+
out.push('');
|
|
2928
|
+
|
|
2929
|
+
out.push('## Active enforcement (gates)');
|
|
2930
|
+
out.push('');
|
|
2931
|
+
const gates = (model.gates && model.gates.gates) || [];
|
|
2932
|
+
if (!gates.length) {
|
|
2933
|
+
out.push('_No active gates._');
|
|
2934
|
+
} else {
|
|
2935
|
+
for (const g of gates) {
|
|
2936
|
+
const occ = g.occurrences ? ` (${g.occurrences}×)` : '';
|
|
2937
|
+
out.push(`- \`${g.pattern || g.id}\` → **${g.action}**${occ}`);
|
|
2938
|
+
}
|
|
2939
|
+
}
|
|
2940
|
+
out.push('');
|
|
2941
|
+
|
|
2942
|
+
out.push('## Project context');
|
|
2943
|
+
out.push('');
|
|
2944
|
+
out.push(`- Repo root: \`${model.project.root}\``);
|
|
2945
|
+
const files = model.project.instructionFiles;
|
|
2946
|
+
out.push(`- Agent instruction files: ${files.length ? files.map((f) => '`' + f + '`').join(', ') : '_none detected_'}`);
|
|
2947
|
+
out.push('');
|
|
2948
|
+
out.push('---');
|
|
2949
|
+
const lt = (model.lessons && model.lessons.total) || 0;
|
|
2950
|
+
const rt = (model.rules && model.rules.total) || 0;
|
|
2951
|
+
const gt = (model.gates && model.gates.total) || 0;
|
|
2952
|
+
out.push(`_${lt} lessons · ${rt} rules · ${gt} gates. Rebuild with \`npx thumbgate brain --write\`._`);
|
|
2953
|
+
out.push('');
|
|
2954
|
+
return out.join('\n');
|
|
2955
|
+
}
|
|
2956
|
+
|
|
2957
|
+
function cmdBrain(args = {}) {
|
|
2958
|
+
const model = buildBrainModel({ limit: args.limit });
|
|
2959
|
+
if (args.json) { console.log(JSON.stringify(model, null, 2)); return 0; }
|
|
2960
|
+
const md = renderBrainMarkdown(model);
|
|
2961
|
+
if (args.write) {
|
|
2962
|
+
const dir = path.join(CWD, '.thumbgate');
|
|
2963
|
+
const target = path.join(dir, 'BRAIN.md');
|
|
2964
|
+
try {
|
|
2965
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
2966
|
+
fs.writeFileSync(target, md);
|
|
2967
|
+
} catch (err) {
|
|
2968
|
+
// Surface a clean, actionable error instead of an uncaught stack trace
|
|
2969
|
+
// (e.g. permission denied, read-only filesystem).
|
|
2970
|
+
console.error(`Could not write ${target}: ${err && err.message ? err.message : err}`);
|
|
2971
|
+
return 1;
|
|
2972
|
+
}
|
|
2973
|
+
const lt = (model.lessons && model.lessons.total) || 0;
|
|
2974
|
+
const rt = (model.rules && model.rules.total) || 0;
|
|
2975
|
+
const gt = (model.gates && model.gates.total) || 0;
|
|
2976
|
+
console.log(`\u{1f9e0} Wrote context brain to .thumbgate/BRAIN.md (${lt} lessons · ${rt} rules · ${gt} gates).`);
|
|
2977
|
+
console.log(' Point your agent at it: add "Read .thumbgate/BRAIN.md first" to CLAUDE.md / AGENTS.md.');
|
|
2978
|
+
return 0;
|
|
2979
|
+
}
|
|
2980
|
+
process.stdout.write(md);
|
|
2981
|
+
return 0;
|
|
2982
|
+
}
|
|
2983
|
+
|
|
2623
2984
|
switch (COMMAND) {
|
|
2624
2985
|
case '--version':
|
|
2625
2986
|
case '-v':
|
|
@@ -2666,6 +3027,16 @@ switch (COMMAND) {
|
|
|
2666
3027
|
capture();
|
|
2667
3028
|
upgradeNudge();
|
|
2668
3029
|
break;
|
|
3030
|
+
case 'feedback-self-test':
|
|
3031
|
+
case 'dogfood':
|
|
3032
|
+
feedbackSelfTest();
|
|
3033
|
+
break;
|
|
3034
|
+
case 'setup-vertex':
|
|
3035
|
+
setupVertex().catch((err) => {
|
|
3036
|
+
console.error(err && err.message ? err.message : err);
|
|
3037
|
+
process.exit(1);
|
|
3038
|
+
});
|
|
3039
|
+
break;
|
|
2669
3040
|
case 'stats':
|
|
2670
3041
|
stats();
|
|
2671
3042
|
upgradeNudge();
|
|
@@ -2685,6 +3056,11 @@ switch (COMMAND) {
|
|
|
2685
3056
|
// a test runner stubs process.exit (flagged by gitar-bot on PR #2281).
|
|
2686
3057
|
break;
|
|
2687
3058
|
}
|
|
3059
|
+
case 'brain': {
|
|
3060
|
+
const brainArgs = parseArgs(process.argv.slice(3));
|
|
3061
|
+
process.exit(cmdBrain(brainArgs));
|
|
3062
|
+
break;
|
|
3063
|
+
}
|
|
2688
3064
|
case 'billing:setup':
|
|
2689
3065
|
require(path.join(PKG_ROOT, 'scripts', 'billing-setup'));
|
|
2690
3066
|
break;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "thumbgate",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.26.1",
|
|
4
4
|
"description": "ThumbGate self-improving agent governance: thumbs-up/down turns every mistake into a prevention rule and blocks repeat patterns. 36 pre-action checks, budget enforcement, and self-protection for Claude Code, Cursor, Codex, Gemini CLI, and Amp.",
|
|
5
5
|
"homepage": "https://thumbgate.ai",
|
|
6
6
|
"repository": {
|
|
@@ -16,6 +16,7 @@
|
|
|
16
16
|
},
|
|
17
17
|
"files": [
|
|
18
18
|
"scripts/access-anomaly-detector.js",
|
|
19
|
+
"scripts/action-receipts.js",
|
|
19
20
|
"scripts/activation-tracker.js",
|
|
20
21
|
"scripts/agent-audit-trace.js",
|
|
21
22
|
"scripts/agent-design-governance.js",
|
|
@@ -101,6 +102,7 @@
|
|
|
101
102
|
"scripts/hybrid-feedback-context.js",
|
|
102
103
|
"scripts/hybrid-supervisor-agent.js",
|
|
103
104
|
"scripts/inference-cache-policy.js",
|
|
105
|
+
"scripts/install-shim.js",
|
|
104
106
|
"scripts/install-mcp.js",
|
|
105
107
|
"scripts/internal-agent-bootstrap.js",
|
|
106
108
|
"scripts/intervention-policy.js",
|
|
@@ -131,11 +133,14 @@
|
|
|
131
133
|
"scripts/multimodal-retrieval-plan.js",
|
|
132
134
|
"scripts/native-messaging-audit.js",
|
|
133
135
|
"scripts/natural-language-harness.js",
|
|
136
|
+
"scripts/noop-detect.js",
|
|
134
137
|
"scripts/obsidian-export.js",
|
|
138
|
+
"scripts/operational-dashboard.js",
|
|
135
139
|
"scripts/operational-integrity.js",
|
|
136
140
|
"scripts/oss-pr-opportunity-scout.js",
|
|
137
141
|
"scripts/otel-declarative-config.js",
|
|
138
142
|
"scripts/perplexity-client.js",
|
|
143
|
+
"scripts/plan-gate.js",
|
|
139
144
|
"scripts/plausible-server-events.js",
|
|
140
145
|
"scripts/pr-manager.js",
|
|
141
146
|
"scripts/private-core-boundary.js",
|
|
@@ -154,6 +159,7 @@
|
|
|
154
159
|
"scripts/rag-precision-guardrails.js",
|
|
155
160
|
"scripts/rate-limiter.js",
|
|
156
161
|
"scripts/reasoning-efficiency-guardrails.js",
|
|
162
|
+
"scripts/repeat-metric.js",
|
|
157
163
|
"scripts/reward-hacking-guardrails.js",
|
|
158
164
|
"scripts/risk-scorer.js",
|
|
159
165
|
"scripts/rlaif-self-audit.js",
|
|
@@ -189,6 +195,7 @@
|
|
|
189
195
|
"scripts/thompson-sampling.js",
|
|
190
196
|
"scripts/thumbgate-bench.js",
|
|
191
197
|
"scripts/thumbgate-search.js",
|
|
198
|
+
"scripts/trajectory-scorer.js",
|
|
192
199
|
"scripts/token-savings.js",
|
|
193
200
|
"scripts/token-tco.js",
|
|
194
201
|
"scripts/tool-registry.js",
|
|
@@ -340,7 +347,7 @@
|
|
|
340
347
|
"social:prospect:bluesky:dry": "node scripts/social-bluesky-prospecting.js --dry-run",
|
|
341
348
|
"social:reply-publish:bluesky:dry": "node scripts/social-reply-monitor-bluesky.js --publish-approved --dry-run",
|
|
342
349
|
"test:python": "python3 -m pytest tests/*.py",
|
|
343
|
-
"test": "npm run test:python && 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:platform-limits && npm run test:post-video && npm run test:post-everywhere-instagram && npm run test:post-everywhere-channels && npm run test:post-everywhere-zernio-default && npm run test:zernio-canonical-pollers && npm run test:zernio-status && 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:memory-scope-readiness && npm run test:belief-update && npm run test:hosted-config && npm run test:operational-summary && npm run test:operational-dashboard && npm run test:operator-artifacts && npm run test:operator-key-auth && npm run test:cloudflare-sandbox && npm run test:mcp-config && npm run test:mcp-tool-annotations && npm run test:mcp-oauth && npm run test:mcp-oauth-flow && 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:audit-pr-bot-contamination && npm run test:stripe-bootstrap-saas-catalog && 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:lesson-semantic-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:predictive-credible-range && 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:lesson-canonical && 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:community-course-platform-launch-kit && 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:social-dedupe-cleanup && 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 && npm run test:bot-detection && npm run test:checkout-archived-product-guard && npm run test:postgres-guard && npm run test:checkout-bot-guard && npm run test:checkout-pro-confirmation-gate && npm run test:session-health && npm run test:session-episodes && npm run test:spec-gate && npm run test:decision-trace && npm run test:dashboard-insights && npm run test:telemetry-tracked-link-slug && npm run test:prompt-eval && npm run test:demo-voiceover && npm run test:gate-coherence && npm run test:gate-eval && npm run test:high-roi && npm run test:public-static-assets && npm run test:token-savings && npm run test:numbers-page && npm run test:workflow-gate-checkpoint && npm run test:lesson-export-import && npm run test:landing-page-claims && npm run test:competitive-positioning-marketing && npm run test:medium-weekly && npm run test:dashboard-deeplink-e2e && npm run test:public-package-parity && npm run test:token-savings-dashboard && npm run test:cursor-wiring && npm run test:pretooluse-injection && npm run test:recent-corrective-context && npm run test:durability-step && npm run test:mailer && npm run test:brand-assets && npm run test:enforcement-teeth && npm run test:bayes-optimal-gate && npm run test:swarm-coordinator && npm run test:session-report && npm run test:agent-reasoning-traces && npm run test:judge-reward && npm run test:llm-behavior-monitor && npm run test:prompting-os && npm run test:single-use-credential-gate && npm run test:structured-prompt-driven && npm run test:require-evidence-gate && npm run test:rule-validator && npm run test:bluesky-atproto && npm run test:social-reply-monitor-bluesky && npm run test:bluesky-delete-replies && npm run test:architect-kit-memory-bridge && npm run test:sonar-review-hotspots && npm run test:actionable-remediations && npm run test:gemini-embedding-policy && npm run test:agent-design-governance && npm run test:public-core-boundary && npm run test:hook-stop-verify-deploy && npm run test:hook-stop-anti-claim && npm run test:plausible-server-events && npm run test:activation-tracker && npm run test:unified-revenue-rollup && npm run test:conversion-rate-stats && npm run test:external-customer-audit && npm run test:telemetry-export && npm run test:stripe-checkout-diagnostic && npm run test:stripe-business-identity-probe && npm run test:revenue-observability-doctor && npm run test:public-bundle-ratchet && npm run test:stripe-payment-link-update && npm run test:ci-cd-hygiene-audit && npm run test:verify-marketing-pages-deployed && npm run test:install-email-capture && npm run test:install-shim && npm run test:hook-runtime-subcommands && npm run test:implementation-notes && npm run test:daily-block-cap && npm run test:free-to-paid-conversion-units && npm run test:metrics-real-endpoint && npm run test:cli-trial-and-help && npm run test:cost-cli && npm run test:silent-failure-cluster && npm run test:proof:truth && node --test tests/adaptive-reliability.test.js && npm run test:mcp-oauth-reviewer",
|
|
350
|
+
"test": "npm run test:python && 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:platform-limits && npm run test:post-video && npm run test:post-everywhere-instagram && npm run test:post-everywhere-channels && npm run test:post-everywhere-zernio-default && npm run test:zernio-canonical-pollers && npm run test:zernio-status && 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:repeat-metric && npm run test:noop-detect && npm run test:action-receipts && npm run test:feedback-to-rules && npm run test:memory-firewall && npm run test:memory-scope-readiness && npm run test:belief-update && npm run test:hosted-config && npm run test:operational-summary && npm run test:operational-dashboard && npm run test:operator-artifacts && npm run test:operator-key-auth && npm run test:cloudflare-sandbox && npm run test:mcp-config && npm run test:mcp-tool-annotations && npm run test:mcp-oauth && npm run test:mcp-oauth-flow && 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:audit-pr-bot-contamination && npm run test:stripe-bootstrap-saas-catalog && 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:lesson-semantic-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:predictive-credible-range && 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:lesson-canonical && 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:community-course-platform-launch-kit && 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:social-dedupe-cleanup && 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 && npm run test:bot-detection && npm run test:checkout-archived-product-guard && npm run test:postgres-guard && npm run test:checkout-bot-guard && npm run test:checkout-pro-confirmation-gate && npm run test:session-health && npm run test:session-episodes && npm run test:spec-gate && npm run test:decision-trace && npm run test:dashboard-insights && npm run test:telemetry-tracked-link-slug && npm run test:prompt-eval && npm run test:demo-voiceover && npm run test:gate-coherence && npm run test:gate-eval && npm run test:high-roi && npm run test:public-static-assets && npm run test:token-savings && npm run test:numbers-page && npm run test:workflow-gate-checkpoint && npm run test:lesson-export-import && npm run test:landing-page-claims && npm run test:competitive-positioning-marketing && npm run test:medium-weekly && npm run test:dashboard-deeplink-e2e && npm run test:public-package-parity && npm run test:token-savings-dashboard && npm run test:cursor-wiring && npm run test:pretooluse-injection && npm run test:recent-corrective-context && npm run test:durability-step && npm run test:mailer && npm run test:brand-assets && npm run test:enforcement-teeth && npm run test:bayes-optimal-gate && npm run test:swarm-coordinator && npm run test:session-report && npm run test:agent-reasoning-traces && npm run test:judge-reward && npm run test:llm-behavior-monitor && npm run test:prompting-os && npm run test:single-use-credential-gate && npm run test:structured-prompt-driven && npm run test:require-evidence-gate && npm run test:rule-validator && npm run test:bluesky-atproto && npm run test:social-reply-monitor-bluesky && npm run test:bluesky-delete-replies && npm run test:architect-kit-memory-bridge && npm run test:sonar-review-hotspots && npm run test:actionable-remediations && npm run test:gemini-embedding-policy && npm run test:agent-design-governance && npm run test:public-core-boundary && npm run test:hook-stop-verify-deploy && npm run test:hook-stop-anti-claim && npm run test:plausible-server-events && npm run test:activation-tracker && npm run test:unified-revenue-rollup && npm run test:conversion-rate-stats && npm run test:external-customer-audit && npm run test:telemetry-export && npm run test:stripe-checkout-diagnostic && npm run test:stripe-business-identity-probe && npm run test:revenue-observability-doctor && npm run test:public-bundle-ratchet && npm run test:stripe-payment-link-update && npm run test:ci-cd-hygiene-audit && npm run test:verify-marketing-pages-deployed && npm run test:install-email-capture && npm run test:install-shim && npm run test:hook-runtime-subcommands && npm run test:implementation-notes && npm run test:daily-block-cap && npm run test:free-to-paid-conversion-units && npm run test:metrics-real-endpoint && npm run test:cli-trial-and-help && npm run test:cost-cli && npm run test:silent-failure-cluster && npm run test:proof:truth && node --test tests/adaptive-reliability.test.js && npm run test:mcp-oauth-reviewer && npm run test:dfcx-gate && npm run test:dfcx-gate-server && npm run test:vertex-scorer",
|
|
344
351
|
"test:hook-stop-verify-deploy": "node --test tests/hook-stop-verify-deploy.test.js",
|
|
345
352
|
"test:hook-stop-anti-claim": "node --test tests/hook-stop-anti-claim.test.js",
|
|
346
353
|
"test:plausible-server-events": "node --test tests/plausible-server-events.test.js tests/plausible-poller.test.js",
|
|
@@ -393,6 +400,12 @@
|
|
|
393
400
|
"test:sync-version": "node --test tests/sync-version.test.js",
|
|
394
401
|
"test:check-congruence": "node --test tests/check-congruence.test.js",
|
|
395
402
|
"test:tool-registry": "node --test tests/tool-registry.test.js",
|
|
403
|
+
"test:dfcx-gate": "node --test tests/dfcx-webhook-gate.test.js",
|
|
404
|
+
"test:dfcx-gate-server": "node --test tests/dfcx-gate-server.test.js",
|
|
405
|
+
"test:vertex-scorer": "node --test tests/vertex-scorer.test.js",
|
|
406
|
+
"test:repeat-metric": "node --test tests/repeat-metric.test.js",
|
|
407
|
+
"test:noop-detect": "node --test tests/noop-detect.test.js",
|
|
408
|
+
"test:action-receipts": "node --test tests/action-receipts.test.js",
|
|
396
409
|
"test:learn-hub": "node --test tests/learn-hub.test.js",
|
|
397
410
|
"test:feedback-to-rules": "node --test tests/feedback-to-rules.test.js",
|
|
398
411
|
"test:memory-firewall": "node --test tests/memory-firewall.test.js",
|
|
@@ -687,7 +700,7 @@
|
|
|
687
700
|
"test:dashboard-page-clickability": "playwright test tests/e2e/dashboard-page-clickability.spec.js",
|
|
688
701
|
"test:agent-manager-page-clickability": "playwright test tests/e2e/agent-manager-page-clickability.spec.js",
|
|
689
702
|
"test:pricing-page-clickability": "playwright test tests/e2e/pricing-page-clickability.spec.js",
|
|
690
|
-
"test:proof:truth": "node --test tests/knowledge-entropy.test.js tests/mcp-wiring-doctor.test.js tests/sequence-guard.test.js tests/slopsquat-guard.test.js tests/slopsquat-stress.test.js tests/truth-and-proof.test.js tests/wire-proof-gate.test.js tests/adaptive-reliability.test.js",
|
|
703
|
+
"test:proof:truth": "node --test tests/knowledge-entropy.test.js tests/mcp-wiring-doctor.test.js tests/sequence-guard.test.js tests/slopsquat-guard.test.js tests/slopsquat-stress.test.js tests/truth-and-proof.test.js tests/wire-proof-gate.test.js tests/adaptive-reliability.test.js tests/coderabbit-patterns.test.js",
|
|
691
704
|
"build:grok-plugin": "node scripts/build-grok-plugin.js",
|
|
692
705
|
"promote:launch": "node scripts/x-autonomous-marketing.js",
|
|
693
706
|
"feedback:ingest": "node scripts/ingest-manual-feedback.js",
|