thumbgate 0.9.10 ā 0.9.11
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/README.md +2 -2
- package/.claude-plugin/marketplace.json +4 -2
- package/.claude-plugin/plugin.json +1 -1
- package/.well-known/mcp/server-card.json +1 -1
- package/README.md +115 -312
- package/adapters/README.md +1 -1
- package/adapters/claude/.mcp.json +2 -2
- package/adapters/codex/config.toml +4 -4
- package/adapters/mcp/server-stdio.js +61 -1
- package/adapters/opencode/opencode.json +4 -2
- package/bin/cli.js +156 -8
- package/bin/memory.sh +3 -3
- package/config/e2e-critical-flows.json +4 -0
- package/config/gates/default.json +74 -2
- package/config/github-about.json +1 -1
- package/config/mcp-allowlists.json +27 -0
- package/package.json +22 -5
- package/plugins/amp-skill/INSTALL.md +1 -0
- package/plugins/amp-skill/SKILL.md +1 -0
- package/plugins/claude-codex-bridge/.claude-plugin/plugin.json +1 -1
- package/plugins/claude-codex-bridge/.mcp.json +4 -2
- package/plugins/claude-skill/INSTALL.md +1 -0
- package/plugins/codex-profile/.codex-plugin/plugin.json +1 -1
- package/plugins/codex-profile/.mcp.json +4 -2
- package/plugins/codex-profile/INSTALL.md +1 -1
- package/plugins/codex-profile/README.md +1 -1
- package/plugins/cursor-marketplace/.cursor-plugin/plugin.json +1 -1
- package/plugins/cursor-marketplace/README.md +3 -3
- package/plugins/cursor-marketplace/mcp.json +3 -1
- package/plugins/cursor-marketplace/scripts/gate-check.sh +15 -5
- package/plugins/gemini-extension/INSTALL.md +3 -3
- package/plugins/opencode-profile/INSTALL.md +1 -1
- package/public/dashboard.html +15 -8
- package/public/index.html +125 -185
- package/public/js/buyer-intent.js +252 -0
- package/public/pro.html +1085 -0
- package/scripts/__pycache__/train_from_feedback.cpython-312.pyc +0 -0
- package/scripts/adk-consolidator.js +14 -2
- package/scripts/agent-readiness.js +3 -1
- package/scripts/agent-security-hardening.js +4 -4
- package/scripts/auto-promote-gates.js +2 -0
- package/scripts/auto-wire-hooks.js +105 -17
- package/scripts/behavioral-extraction.js +2 -6
- package/scripts/billing.js +107 -3
- package/scripts/budget-guard.js +2 -2
- package/scripts/build-metadata.js +14 -0
- package/scripts/context-engine.js +1 -0
- package/scripts/deploy-policy.js +3 -17
- package/scripts/dpo-optimizer.js +3 -6
- package/scripts/ensure-repo-bootstrap.js +129 -0
- package/scripts/export-dpo-pairs.js +2 -3
- package/scripts/export-kto-pairs.js +3 -4
- package/scripts/export-training.js +8 -6
- package/scripts/feedback-attribution.js +23 -11
- package/scripts/feedback-loop.js +40 -2
- package/scripts/feedback-to-rules.js +2 -1
- package/scripts/filesystem-search.js +3 -2
- package/scripts/gates-engine.js +760 -29
- package/scripts/generate-pretool-hook.sh +0 -0
- package/scripts/gtm-revenue-loop.js +20 -1
- package/scripts/hook-auto-capture.sh +8 -3
- package/scripts/hook-runtime.js +89 -0
- package/scripts/hook-stop-self-score.sh +3 -3
- package/scripts/hook-thumbgate-cache-updater.js +99 -38
- package/scripts/hosted-config.js +4 -16
- package/scripts/hybrid-feedback-context.js +54 -14
- package/scripts/install-mcp.js +13 -0
- package/scripts/intent-router.js +2 -2
- package/scripts/license.js +52 -14
- package/scripts/local-model-profile.js +3 -2
- package/scripts/mcp-config.js +68 -6
- package/scripts/meta-policy.js +4 -8
- package/scripts/money-watcher.js +166 -16
- package/scripts/obsidian-export.js +1 -0
- package/scripts/operational-integrity.js +480 -0
- package/scripts/post-everywhere.js +7 -12
- package/scripts/pr-manager.js +14 -11
- package/scripts/profile-router.js +2 -0
- package/scripts/prompt-dlp.js +1 -0
- package/scripts/publish-decision.js +10 -0
- package/scripts/published-cli.js +34 -0
- package/scripts/risk-scorer.js +3 -2
- package/scripts/rlhf_session_start.sh +32 -0
- package/scripts/skill-quality-tracker.js +3 -5
- package/scripts/social-analytics/db/social-analytics.db-shm +0 -0
- package/scripts/social-analytics/db/social-analytics.db-wal +0 -0
- package/scripts/social-analytics/engagement-audit.js +202 -0
- package/scripts/social-analytics/instagram-thumbgate-post.js +45 -7
- package/scripts/social-analytics/install-growth-automation.js +114 -0
- package/scripts/social-analytics/load-env.js +46 -0
- package/scripts/social-analytics/poll-all.js +3 -18
- package/scripts/social-analytics/pollers/zernio.js +3 -0
- package/scripts/social-analytics/publish-instagram-thumbgate.js +22 -3
- package/scripts/social-analytics/publish-thumbgate-launch.js +316 -0
- package/scripts/social-analytics/publishers/reddit.js +7 -12
- package/scripts/social-analytics/publishers/zernio.js +210 -22
- package/scripts/social-analytics/reconcile-thumbgate-campaign.js +165 -0
- package/scripts/social-analytics/schedule-thumbgate-campaign.js +275 -0
- package/scripts/social-analytics/sync-launch-assets.js +185 -0
- package/scripts/social-post-hourly.js +185 -0
- package/scripts/social-quality-gate.js +119 -3
- package/scripts/social-reply-monitor.js +148 -32
- package/scripts/statusline-cache-path.js +27 -0
- package/scripts/statusline-meta.js +22 -0
- package/scripts/statusline.sh +24 -32
- package/scripts/sync-version.js +11 -3
- package/scripts/test-coverage.js +20 -13
- package/scripts/tool-registry.js +97 -0
- package/scripts/train_from_feedback.py +32 -9
- package/scripts/validate-feedback.js +3 -2
- package/scripts/vector-store.js +2 -3
- package/scripts/verify-obsidian-setup.sh +3 -3
- package/src/api/server.js +281 -33
package/scripts/mcp-config.js
CHANGED
|
@@ -3,6 +3,9 @@
|
|
|
3
3
|
const fs = require('fs');
|
|
4
4
|
const path = require('path');
|
|
5
5
|
const { execFileSync } = require('child_process');
|
|
6
|
+
const { publishedCliArgs, runPublishedCliHelp } = require('./published-cli');
|
|
7
|
+
const DEFAULT_PKG_ROOT = path.join(__dirname, '..');
|
|
8
|
+
const cliAvailabilityCache = new Map();
|
|
6
9
|
|
|
7
10
|
function isSourceCheckout(pkgRoot) {
|
|
8
11
|
return fs.existsSync(path.join(pkgRoot, '.git'));
|
|
@@ -17,17 +20,40 @@ function parseWorktreePaths(raw) {
|
|
|
17
20
|
}
|
|
18
21
|
|
|
19
22
|
function resolveStableSourceRoot(pkgRoot) {
|
|
20
|
-
|
|
23
|
+
const effectivePkgRoot =
|
|
24
|
+
typeof pkgRoot === 'string' && pkgRoot.trim() ? pkgRoot : DEFAULT_PKG_ROOT;
|
|
25
|
+
|
|
26
|
+
if (!isSourceCheckout(effectivePkgRoot)) {
|
|
21
27
|
return null;
|
|
22
28
|
}
|
|
23
29
|
|
|
30
|
+
let preferredBasenames = [];
|
|
31
|
+
try {
|
|
32
|
+
const pkg = JSON.parse(fs.readFileSync(path.join(effectivePkgRoot, 'package.json'), 'utf8'));
|
|
33
|
+
const packageName = String(pkg && pkg.name || '').trim().toLowerCase();
|
|
34
|
+
if (packageName) {
|
|
35
|
+
preferredBasenames.push(packageName);
|
|
36
|
+
preferredBasenames.push(packageName.replace(/[^a-z0-9]+/g, ''));
|
|
37
|
+
}
|
|
38
|
+
} catch (_) {
|
|
39
|
+
preferredBasenames = [];
|
|
40
|
+
}
|
|
41
|
+
|
|
24
42
|
try {
|
|
25
|
-
const output = execFileSync('git', ['-C',
|
|
43
|
+
const output = execFileSync('git', ['-C', effectivePkgRoot, 'worktree', 'list', '--porcelain'], {
|
|
26
44
|
encoding: 'utf8',
|
|
27
45
|
stdio: ['ignore', 'pipe', 'ignore'],
|
|
28
46
|
});
|
|
29
47
|
const worktreePaths = parseWorktreePaths(output);
|
|
30
48
|
|
|
49
|
+
for (const worktreePath of worktreePaths) {
|
|
50
|
+
const baseName = path.basename(worktreePath).toLowerCase();
|
|
51
|
+
const normalizedBaseName = baseName.replace(/[^a-z0-9]+/g, '');
|
|
52
|
+
if (preferredBasenames.includes(baseName) || preferredBasenames.includes(normalizedBaseName)) {
|
|
53
|
+
return worktreePath;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
31
57
|
for (const worktreePath of worktreePaths) {
|
|
32
58
|
const gitPath = path.join(worktreePath, '.git');
|
|
33
59
|
if (!fs.existsSync(gitPath)) {
|
|
@@ -38,10 +64,10 @@ function resolveStableSourceRoot(pkgRoot) {
|
|
|
38
64
|
}
|
|
39
65
|
}
|
|
40
66
|
} catch (_) {
|
|
41
|
-
return
|
|
67
|
+
return effectivePkgRoot;
|
|
42
68
|
}
|
|
43
69
|
|
|
44
|
-
return
|
|
70
|
+
return effectivePkgRoot;
|
|
45
71
|
}
|
|
46
72
|
|
|
47
73
|
function resolveGitCommonDir(dirPath) {
|
|
@@ -76,7 +102,7 @@ function resolveLocalServerPath(pkgRoot, scope = 'project') {
|
|
|
76
102
|
function portableMcpEntry(pkgVersion) {
|
|
77
103
|
return {
|
|
78
104
|
command: 'npx',
|
|
79
|
-
args:
|
|
105
|
+
args: publishedCliArgs(pkgVersion, ['serve']),
|
|
80
106
|
};
|
|
81
107
|
}
|
|
82
108
|
|
|
@@ -125,17 +151,53 @@ function isVersionPublished(pkgVersion) {
|
|
|
125
151
|
return published;
|
|
126
152
|
}
|
|
127
153
|
|
|
154
|
+
function publishedCliOverride() {
|
|
155
|
+
const override = String(process.env.THUMBGATE_PUBLISHED_CLI_STATE || '').trim().toLowerCase();
|
|
156
|
+
if (override === 'available') {
|
|
157
|
+
return true;
|
|
158
|
+
}
|
|
159
|
+
if (override === 'unavailable') {
|
|
160
|
+
return false;
|
|
161
|
+
}
|
|
162
|
+
return null;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
function publishedCliAvailable(pkgVersion) {
|
|
166
|
+
if (!isVersionPublished(pkgVersion)) {
|
|
167
|
+
return false;
|
|
168
|
+
}
|
|
169
|
+
const override = publishedCliOverride();
|
|
170
|
+
if (override !== null) {
|
|
171
|
+
return override;
|
|
172
|
+
}
|
|
173
|
+
if (cliAvailabilityCache.has(pkgVersion)) {
|
|
174
|
+
return cliAvailabilityCache.get(pkgVersion);
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
let available = false;
|
|
178
|
+
try {
|
|
179
|
+
runPublishedCliHelp(pkgVersion, { timeout: 8000 });
|
|
180
|
+
available = true;
|
|
181
|
+
} catch (_) {
|
|
182
|
+
available = false;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
cliAvailabilityCache.set(pkgVersion, available);
|
|
186
|
+
return available;
|
|
187
|
+
}
|
|
188
|
+
|
|
128
189
|
function resolveMcpEntry({ pkgRoot, pkgVersion, scope = 'project', targetDir = pkgRoot }) {
|
|
129
190
|
if (!isSourceCheckout(pkgRoot)) {
|
|
130
191
|
return portableMcpEntry(pkgVersion);
|
|
131
192
|
}
|
|
132
|
-
if (scope === 'project' && !isSameCheckoutFamily(pkgRoot, targetDir) &&
|
|
193
|
+
if (scope === 'project' && !isSameCheckoutFamily(pkgRoot, targetDir) && publishedCliAvailable(pkgVersion)) {
|
|
133
194
|
return portableMcpEntry(pkgVersion);
|
|
134
195
|
}
|
|
135
196
|
return localMcpEntry(pkgRoot, scope);
|
|
136
197
|
}
|
|
137
198
|
|
|
138
199
|
module.exports = {
|
|
200
|
+
publishedCliAvailable,
|
|
139
201
|
isVersionPublished,
|
|
140
202
|
isSourceCheckout,
|
|
141
203
|
isSameCheckoutFamily,
|
package/scripts/meta-policy.js
CHANGED
|
@@ -17,10 +17,10 @@
|
|
|
17
17
|
|
|
18
18
|
const fs = require('fs');
|
|
19
19
|
const path = require('path');
|
|
20
|
-
const os = require('os');
|
|
21
20
|
const { parseTimestamp } = require('./feedback-schema');
|
|
22
21
|
const { timeDecayWeight } = require('./thompson-sampling');
|
|
23
22
|
const { inferDomain } = require('./feedback-loop');
|
|
23
|
+
const { resolveFeedbackDir } = require('./feedback-paths');
|
|
24
24
|
|
|
25
25
|
const MIN_OCCURRENCES = 2;
|
|
26
26
|
const RECENT_DAYS = 7;
|
|
@@ -30,13 +30,11 @@ const RECENT_MS = RECENT_DAYS * 24 * 3600 * 1000;
|
|
|
30
30
|
* Extract meta-policy rules from memory-log.jsonl feedback trends.
|
|
31
31
|
*
|
|
32
32
|
* @param {object} opts
|
|
33
|
-
* @param {string} [opts.feedbackDir] - Override feedback directory (default:
|
|
33
|
+
* @param {string} [opts.feedbackDir] - Override feedback directory (default: active ThumbGate feedback dir)
|
|
34
34
|
* @returns {Array<{category: string, confidence: number, trend: string, occurrence_count: number, last_seen: string}>}
|
|
35
35
|
*/
|
|
36
36
|
function extractMetaPolicyRules(opts = {}) {
|
|
37
|
-
const feedbackDir = opts.feedbackDir
|
|
38
|
-
|| process.env.THUMBGATE_FEEDBACK_DIR
|
|
39
|
-
|| path.join(os.homedir(), '.claude', 'memory', 'feedback');
|
|
37
|
+
const feedbackDir = opts.feedbackDir || resolveFeedbackDir();
|
|
40
38
|
|
|
41
39
|
const memoryLogPath = path.join(feedbackDir, 'memory-log.jsonl');
|
|
42
40
|
|
|
@@ -160,9 +158,7 @@ function extractMetaPolicyRules(opts = {}) {
|
|
|
160
158
|
* @returns {{ rules: Array, outputPath: string }}
|
|
161
159
|
*/
|
|
162
160
|
function run(opts = {}) {
|
|
163
|
-
const feedbackDir = opts.feedbackDir
|
|
164
|
-
|| process.env.THUMBGATE_FEEDBACK_DIR
|
|
165
|
-
|| path.join(os.homedir(), '.claude', 'memory', 'feedback');
|
|
161
|
+
const feedbackDir = opts.feedbackDir || resolveFeedbackDir();
|
|
166
162
|
|
|
167
163
|
const rules = extractMetaPolicyRules({ ...opts, feedbackDir });
|
|
168
164
|
|
package/scripts/money-watcher.js
CHANGED
|
@@ -6,10 +6,19 @@
|
|
|
6
6
|
|
|
7
7
|
'use strict';
|
|
8
8
|
|
|
9
|
+
const fs = require('node:fs');
|
|
10
|
+
const path = require('node:path');
|
|
9
11
|
const { getOperationalBillingSummary } = require('./operational-summary');
|
|
10
12
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
+
const DEFAULT_STATE_PATH = path.resolve(__dirname, '..', '.thumbgate', 'commercial-watch-state.json');
|
|
14
|
+
const DEFAULT_ALERT_LOG_PATH = path.resolve(__dirname, '..', '.thumbgate', 'commercial-alerts.jsonl');
|
|
15
|
+
|
|
16
|
+
function ensureParentDir(filePath) {
|
|
17
|
+
fs.mkdirSync(path.dirname(filePath), { recursive: true });
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function getCommercialRevenueSnapshot(summary = {}) {
|
|
21
|
+
const revenue = summary && typeof summary === 'object' ? summary.revenue || {} : {};
|
|
13
22
|
return {
|
|
14
23
|
paidOrders: revenue.paidOrders || 0,
|
|
15
24
|
bookedRevenueCents: revenue.bookedRevenueCents || 0,
|
|
@@ -18,10 +27,86 @@ function getCommercialRevenueSnapshot(summary) {
|
|
|
18
27
|
};
|
|
19
28
|
}
|
|
20
29
|
|
|
21
|
-
|
|
30
|
+
function readSnapshotState(statePath = DEFAULT_STATE_PATH) {
|
|
31
|
+
try {
|
|
32
|
+
if (!fs.existsSync(statePath)) {
|
|
33
|
+
return null;
|
|
34
|
+
}
|
|
35
|
+
return JSON.parse(fs.readFileSync(statePath, 'utf8'));
|
|
36
|
+
} catch {
|
|
37
|
+
return null;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function writeSnapshotState(snapshot, statePath = DEFAULT_STATE_PATH) {
|
|
42
|
+
ensureParentDir(statePath);
|
|
43
|
+
fs.writeFileSync(statePath, `${JSON.stringify(snapshot, null, 2)}\n`, 'utf8');
|
|
44
|
+
return statePath;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function buildCommercialAlert(previousSnapshot = {}, currentSnapshot = {}, meta = {}) {
|
|
48
|
+
const newPaidOrders = (currentSnapshot.paidOrders || 0) - (previousSnapshot.paidOrders || 0);
|
|
49
|
+
const newBookedRevenueCents = (currentSnapshot.bookedRevenueCents || 0) - (previousSnapshot.bookedRevenueCents || 0);
|
|
50
|
+
|
|
51
|
+
if (newPaidOrders <= 0 && newBookedRevenueCents <= 0) {
|
|
52
|
+
return null;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
return {
|
|
56
|
+
detectedAt: new Date().toISOString(),
|
|
57
|
+
source: meta.source || null,
|
|
58
|
+
fallbackReason: meta.fallbackReason || null,
|
|
59
|
+
newPaidOrders,
|
|
60
|
+
newBookedRevenueCents,
|
|
61
|
+
latestPaidAt: currentSnapshot.latestPaidAt || null,
|
|
62
|
+
latestPaidOrder: currentSnapshot.latestPaidOrder || null,
|
|
63
|
+
paidOrders: currentSnapshot.paidOrders || 0,
|
|
64
|
+
bookedRevenueCents: currentSnapshot.bookedRevenueCents || 0,
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
function recordCommercialAlert(alert, alertLogPath = DEFAULT_ALERT_LOG_PATH) {
|
|
69
|
+
ensureParentDir(alertLogPath);
|
|
70
|
+
fs.appendFileSync(alertLogPath, `${JSON.stringify(alert)}\n`, 'utf8');
|
|
71
|
+
return alertLogPath;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
async function checkForCommercialChange(options = {}) {
|
|
75
|
+
const statePath = options.statePath || DEFAULT_STATE_PATH;
|
|
76
|
+
const alertLogPath = options.alertLogPath || DEFAULT_ALERT_LOG_PATH;
|
|
77
|
+
const previousSnapshot = options.previousSnapshot || readSnapshotState(statePath) || getCommercialRevenueSnapshot();
|
|
78
|
+
const summaryResolver = options.getSummary || getOperationalBillingSummary;
|
|
79
|
+
const { source, summary, fallbackReason } = await summaryResolver();
|
|
80
|
+
const currentSnapshot = getCommercialRevenueSnapshot(summary);
|
|
81
|
+
const alert = buildCommercialAlert(previousSnapshot, currentSnapshot, {
|
|
82
|
+
source,
|
|
83
|
+
fallbackReason,
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
writeSnapshotState(currentSnapshot, statePath);
|
|
87
|
+
if (alert) {
|
|
88
|
+
recordCommercialAlert(alert, alertLogPath);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
return {
|
|
92
|
+
changed: Boolean(alert),
|
|
93
|
+
alert,
|
|
94
|
+
previousSnapshot,
|
|
95
|
+
currentSnapshot,
|
|
96
|
+
source,
|
|
97
|
+
fallbackReason: fallbackReason || null,
|
|
98
|
+
statePath,
|
|
99
|
+
alertLogPath,
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
async function watchMoney(intervalMs = 10000, options = {}) {
|
|
22
104
|
console.log('š Money Watcher activated. Polling billing summary for commercial changes...');
|
|
23
105
|
const initialState = await getOperationalBillingSummary();
|
|
24
|
-
let initialSnapshot =
|
|
106
|
+
let initialSnapshot = options.initialSnapshot
|
|
107
|
+
|| readSnapshotState(options.statePath || DEFAULT_STATE_PATH)
|
|
108
|
+
|| getCommercialRevenueSnapshot(initialState.summary);
|
|
109
|
+
writeSnapshotState(initialSnapshot, options.statePath || DEFAULT_STATE_PATH);
|
|
25
110
|
let polling = false;
|
|
26
111
|
|
|
27
112
|
return setInterval(async () => {
|
|
@@ -30,21 +115,18 @@ async function watchMoney(intervalMs = 10000) {
|
|
|
30
115
|
try {
|
|
31
116
|
const { source, summary, fallbackReason } = await getOperationalBillingSummary();
|
|
32
117
|
const currentSnapshot = getCommercialRevenueSnapshot(summary);
|
|
118
|
+
const alert = buildCommercialAlert(initialSnapshot, currentSnapshot, {
|
|
119
|
+
source,
|
|
120
|
+
fallbackReason,
|
|
121
|
+
});
|
|
122
|
+
writeSnapshotState(currentSnapshot, options.statePath || DEFAULT_STATE_PATH);
|
|
33
123
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
if (newPaidOrders > 0 || newBookedRevenue > 0) {
|
|
124
|
+
if (alert) {
|
|
125
|
+
recordCommercialAlert(alert, options.alertLogPath || DEFAULT_ALERT_LOG_PATH);
|
|
38
126
|
console.log('\nšØšØšØ COMMERCIAL ALERT: NET-NEW PAID ACTIVITY DETECTED! šØšØšØ');
|
|
39
127
|
console.log('Operational billing summary:');
|
|
40
128
|
console.log(JSON.stringify({
|
|
41
|
-
|
|
42
|
-
fallbackReason,
|
|
43
|
-
newPaidOrders,
|
|
44
|
-
newBookedRevenueCents: newBookedRevenue,
|
|
45
|
-
latestPaidAt: currentSnapshot.latestPaidAt,
|
|
46
|
-
latestPaidOrder: currentSnapshot.latestPaidOrder,
|
|
47
|
-
bookedRevenueCents: currentSnapshot.bookedRevenueCents,
|
|
129
|
+
...alert,
|
|
48
130
|
activeKeys: summary.keys.active,
|
|
49
131
|
totalUsage: summary.keys.totalUsage,
|
|
50
132
|
}, null, 2));
|
|
@@ -58,14 +140,82 @@ async function watchMoney(intervalMs = 10000) {
|
|
|
58
140
|
}, intervalMs);
|
|
59
141
|
}
|
|
60
142
|
|
|
143
|
+
function parseArgs(argv = []) {
|
|
144
|
+
const options = {
|
|
145
|
+
once: false,
|
|
146
|
+
intervalMs: 10000,
|
|
147
|
+
statePath: DEFAULT_STATE_PATH,
|
|
148
|
+
alertLogPath: DEFAULT_ALERT_LOG_PATH,
|
|
149
|
+
};
|
|
150
|
+
|
|
151
|
+
for (let index = 0; index < argv.length; index += 1) {
|
|
152
|
+
const arg = String(argv[index] || '').trim();
|
|
153
|
+
|
|
154
|
+
if (arg === '--once') {
|
|
155
|
+
options.once = true;
|
|
156
|
+
continue;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
if (arg === '--interval-ms' && argv[index + 1]) {
|
|
160
|
+
options.intervalMs = Number.parseInt(argv[index + 1], 10) || options.intervalMs;
|
|
161
|
+
index += 1;
|
|
162
|
+
continue;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
if (arg.startsWith('--interval-ms=')) {
|
|
166
|
+
options.intervalMs = Number.parseInt(arg.split('=').slice(1).join('='), 10) || options.intervalMs;
|
|
167
|
+
continue;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
if (arg === '--state-path' && argv[index + 1]) {
|
|
171
|
+
options.statePath = path.resolve(String(argv[index + 1]));
|
|
172
|
+
index += 1;
|
|
173
|
+
continue;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
if (arg.startsWith('--state-path=')) {
|
|
177
|
+
options.statePath = path.resolve(arg.split('=').slice(1).join('='));
|
|
178
|
+
continue;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
if (arg === '--alert-log-path' && argv[index + 1]) {
|
|
182
|
+
options.alertLogPath = path.resolve(String(argv[index + 1]));
|
|
183
|
+
index += 1;
|
|
184
|
+
continue;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
if (arg.startsWith('--alert-log-path=')) {
|
|
188
|
+
options.alertLogPath = path.resolve(arg.split('=').slice(1).join('='));
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
return options;
|
|
193
|
+
}
|
|
194
|
+
|
|
61
195
|
if (require.main === module) {
|
|
62
|
-
|
|
196
|
+
const options = parseArgs(process.argv.slice(2));
|
|
197
|
+
const runner = options.once
|
|
198
|
+
? checkForCommercialChange(options).then((result) => {
|
|
199
|
+
console.log(JSON.stringify(result, null, 2));
|
|
200
|
+
return result;
|
|
201
|
+
})
|
|
202
|
+
: watchMoney(options.intervalMs, options);
|
|
203
|
+
|
|
204
|
+
runner.catch((err) => {
|
|
63
205
|
console.error(err && err.message ? err.message : err);
|
|
64
206
|
process.exit(1);
|
|
65
207
|
});
|
|
66
208
|
}
|
|
67
209
|
|
|
68
210
|
module.exports = {
|
|
211
|
+
DEFAULT_ALERT_LOG_PATH,
|
|
212
|
+
DEFAULT_STATE_PATH,
|
|
213
|
+
buildCommercialAlert,
|
|
214
|
+
checkForCommercialChange,
|
|
69
215
|
getCommercialRevenueSnapshot,
|
|
216
|
+
parseArgs,
|
|
217
|
+
readSnapshotState,
|
|
218
|
+
recordCommercialAlert,
|
|
70
219
|
watchMoney,
|
|
220
|
+
writeSnapshotState,
|
|
71
221
|
};
|
|
@@ -346,6 +346,7 @@ function exportGates(configPath, outputDir) {
|
|
|
346
346
|
// Read auto-promoted gates if present (check common locations)
|
|
347
347
|
const autoGatePaths = [
|
|
348
348
|
path.join(path.dirname(configPath), '..', '.thumbgate', 'auto-promoted-gates.json'),
|
|
349
|
+
path.join(path.dirname(configPath), '..', '.rlhf', 'auto-promoted-gates.json'),
|
|
349
350
|
path.join(path.dirname(configPath), '..', '.claude', 'memory', 'feedback', 'auto-promoted-gates.json'),
|
|
350
351
|
];
|
|
351
352
|
for (const agPath of autoGatePaths) {
|