thumbgate 1.15.0 → 1.16.0
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 +6 -6
- package/.claude-plugin/plugin.json +3 -3
- package/.well-known/llms.txt +5 -5
- package/.well-known/mcp/server-card.json +1 -1
- package/README.md +59 -35
- package/adapters/chatgpt/openapi.yaml +118 -2
- package/adapters/claude/.mcp.json +2 -2
- package/adapters/mcp/server-stdio.js +210 -84
- package/adapters/opencode/opencode.json +1 -1
- package/bench/prompt-eval-suite.json +5 -1
- package/bin/cli.js +157 -8
- package/config/evals/agent-safety-eval.json +338 -22
- package/config/gates/routine.json +43 -0
- package/config/github-about.json +3 -3
- package/config/model-candidates.json +131 -0
- package/openapi/openapi.yaml +118 -2
- package/package.json +55 -48
- package/public/blog.html +7 -7
- package/public/codex-plugin.html +6 -6
- package/public/compare.html +29 -23
- package/public/dashboard.html +82 -10
- package/public/guide.html +28 -28
- package/public/index.html +216 -98
- package/public/learn.html +50 -22
- package/public/lessons.html +1 -1
- package/public/numbers.html +17 -17
- package/public/pro.html +82 -18
- package/scripts/agent-audit-trace.js +55 -0
- package/scripts/agent-memory-lifecycle.js +96 -0
- package/scripts/agent-readiness-plan.js +118 -0
- package/scripts/agentic-data-pipeline.js +21 -1
- package/scripts/agents-sdk-sandbox-plan.js +57 -0
- package/scripts/ai-org-governance.js +98 -0
- package/scripts/ai-search-distribution.js +43 -0
- package/scripts/artifact-agent-plan.js +81 -0
- package/scripts/billing.js +27 -8
- package/scripts/cli-schema.js +18 -2
- package/scripts/code-mode-mcp-plan.js +71 -0
- package/scripts/context-engine.js +1 -2
- package/scripts/context-manager.js +4 -1
- package/scripts/dashboard-render-spec.js +1 -1
- package/scripts/dashboard.js +275 -9
- package/scripts/decision-journal.js +13 -3
- package/scripts/document-workflow-governance.js +62 -0
- package/scripts/enterprise-agent-rollout.js +34 -0
- package/scripts/experience-replay-governance.js +69 -0
- package/scripts/export-hf-dataset.js +1 -1
- package/scripts/feedback-loop.js +92 -4
- package/scripts/feedback-to-rules.js +17 -23
- package/scripts/gates-engine.js +4 -6
- package/scripts/growth-campaigns.js +49 -0
- package/scripts/harness-selector.js +16 -4
- package/scripts/hybrid-supervisor-agent.js +64 -0
- package/scripts/inference-cache-policy.js +72 -0
- package/scripts/inference-economics.js +53 -0
- package/scripts/internal-agent-bootstrap.js +12 -2
- package/scripts/knowledge-layer-plan.js +108 -0
- package/scripts/lesson-inference.js +183 -44
- package/scripts/lesson-search.js +4 -1
- package/scripts/llm-client.js +157 -26
- package/scripts/mailer/resend-mailer.js +112 -1
- package/scripts/mcp-transport-strategy.js +66 -0
- package/scripts/memory-store-governance.js +60 -0
- package/scripts/meta-agent-loop.js +7 -13
- package/scripts/model-access-eligibility.js +38 -0
- package/scripts/model-migration-readiness.js +55 -0
- package/scripts/operational-integrity.js +96 -3
- package/scripts/otel-declarative-config.js +56 -0
- package/scripts/perplexity-client.js +1 -1
- package/scripts/post-training-governance.js +34 -0
- package/scripts/private-core-boundary.js +72 -0
- package/scripts/production-agent-readiness.js +40 -0
- package/scripts/prompt-eval.js +564 -32
- package/scripts/prompt-programs.js +93 -0
- package/scripts/provider-action-normalizer.js +585 -0
- package/scripts/scaling-law-claims.js +60 -0
- package/scripts/security-scanner.js +1 -1
- package/scripts/self-distill-agent.js +7 -32
- package/scripts/seo-gsd.js +232 -55
- package/scripts/skill-rag-router.js +53 -0
- package/scripts/spec-gate.js +1 -1
- package/scripts/student-consistent-training.js +73 -0
- package/scripts/synthetic-data-provenance.js +98 -0
- package/scripts/task-context-result.js +81 -0
- package/scripts/telemetry-analytics.js +149 -0
- package/scripts/thompson-sampling.js +2 -2
- package/scripts/token-savings.js +7 -6
- package/scripts/token-tco.js +46 -0
- package/scripts/tool-registry.js +63 -3
- package/scripts/verification-loop.js +10 -1
- package/scripts/verifier-scoring.js +71 -0
- package/scripts/workflow-sentinel.js +284 -28
- package/scripts/workspace-agent-routines.js +118 -0
- package/src/api/server.js +381 -120
- package/scripts/analytics-report.js +0 -328
- package/scripts/autonomous-workflow.js +0 -377
- package/scripts/billing-setup.js +0 -109
- package/scripts/creator-campaigns.js +0 -239
- package/scripts/cross-encoder-reranker.js +0 -235
- package/scripts/daemon-manager.js +0 -108
- package/scripts/decision-trace.js +0 -354
- package/scripts/delegation-runtime.js +0 -896
- package/scripts/dispatch-brief.js +0 -159
- package/scripts/distribution-surfaces.js +0 -110
- package/scripts/feedback-history-distiller.js +0 -382
- package/scripts/funnel-analytics.js +0 -35
- package/scripts/history-distiller.js +0 -200
- package/scripts/hosted-job-launcher.js +0 -256
- package/scripts/intent-router.js +0 -392
- package/scripts/lesson-reranker.js +0 -263
- package/scripts/lesson-retrieval.js +0 -148
- package/scripts/managed-lesson-agent.js +0 -183
- package/scripts/operational-dashboard.js +0 -103
- package/scripts/operational-summary.js +0 -129
- package/scripts/operator-artifacts.js +0 -608
- package/scripts/optimize-context.js +0 -17
- package/scripts/org-dashboard.js +0 -206
- package/scripts/partner-orchestration.js +0 -146
- package/scripts/predictive-insights.js +0 -356
- package/scripts/pulse.js +0 -80
- package/scripts/reflector-agent.js +0 -221
- package/scripts/sales-pipeline.js +0 -681
- package/scripts/session-episode-store.js +0 -329
- package/scripts/session-health-sensor.js +0 -242
- package/scripts/session-report.js +0 -120
- package/scripts/swarm-coordinator.js +0 -81
- package/scripts/tool-kpi-tracker.js +0 -12
- package/scripts/webhook-delivery.js +0 -62
- package/scripts/workflow-sprint-intake.js +0 -475
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
function estimateToolSchemaTokens(endpointCount, tokensPerEndpoint = 450) {
|
|
4
|
+
return Math.max(0, Number(endpointCount || 0) * Number(tokensPerEndpoint || 0));
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
function buildCodeModeMcpPlan(options = {}) {
|
|
8
|
+
const endpointCount = Number(options.endpointCount || 0);
|
|
9
|
+
const traditionalTokens = estimateToolSchemaTokens(endpointCount, options.tokensPerEndpoint);
|
|
10
|
+
const codeModeTokens = Number(options.codeModeTokens || 1000);
|
|
11
|
+
|
|
12
|
+
return {
|
|
13
|
+
pattern: 'code_mode_mcp',
|
|
14
|
+
endpointCount,
|
|
15
|
+
traditionalTokens,
|
|
16
|
+
codeModeTokens,
|
|
17
|
+
tokenReductionPercent: traditionalTokens > 0
|
|
18
|
+
? Number((((traditionalTokens - codeModeTokens) / traditionalTokens) * 100).toFixed(2))
|
|
19
|
+
: 0,
|
|
20
|
+
tools: [
|
|
21
|
+
{
|
|
22
|
+
name: 'search',
|
|
23
|
+
purpose: 'Find the relevant API area, path, operation, or type without loading the whole schema into context.',
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
name: 'execute',
|
|
27
|
+
purpose: 'Run a bounded code snippet against typed API helpers inside a sandbox.',
|
|
28
|
+
},
|
|
29
|
+
],
|
|
30
|
+
sandbox: {
|
|
31
|
+
filesystem: 'none',
|
|
32
|
+
environmentVariables: 'not_exposed',
|
|
33
|
+
outboundRequests: 'explicit_handlers_only',
|
|
34
|
+
maxExecutionMs: Number(options.maxExecutionMs || 10000),
|
|
35
|
+
},
|
|
36
|
+
gates: [
|
|
37
|
+
'search before execute',
|
|
38
|
+
'execute only against typed helper SDK',
|
|
39
|
+
'block raw credential access',
|
|
40
|
+
'record code snippet and API calls in audit log',
|
|
41
|
+
'require idempotency key for write operations',
|
|
42
|
+
],
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function evaluateCodeModeMcpPlan(plan = {}) {
|
|
47
|
+
const issues = [];
|
|
48
|
+
if (Number(plan.endpointCount || 0) < 100) issues.push('api_surface_too_small_for_code_mode');
|
|
49
|
+
if (!Array.isArray(plan.tools) || plan.tools.length !== 2) issues.push('expected_search_and_execute_only');
|
|
50
|
+
if (plan.sandbox?.filesystem !== 'none') issues.push('filesystem_must_be_disabled');
|
|
51
|
+
if (plan.sandbox?.environmentVariables !== 'not_exposed') issues.push('env_vars_must_not_be_exposed');
|
|
52
|
+
if (plan.sandbox?.outboundRequests !== 'explicit_handlers_only') issues.push('outbound_requests_need_handlers');
|
|
53
|
+
if (!Array.isArray(plan.gates) || !plan.gates.includes('search before execute')) {
|
|
54
|
+
issues.push('search_before_execute_required');
|
|
55
|
+
}
|
|
56
|
+
if (!Array.isArray(plan.gates) || !plan.gates.includes('require idempotency key for write operations')) {
|
|
57
|
+
issues.push('write_idempotency_required');
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
return {
|
|
61
|
+
decision: issues.length ? 'warn' : 'allow',
|
|
62
|
+
issues,
|
|
63
|
+
tokenReductionPercent: plan.tokenReductionPercent || 0,
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
module.exports = {
|
|
68
|
+
buildCodeModeMcpPlan,
|
|
69
|
+
estimateToolSchemaTokens,
|
|
70
|
+
evaluateCodeModeMcpPlan,
|
|
71
|
+
};
|
|
@@ -9,8 +9,7 @@
|
|
|
9
9
|
* topical bundles and route queries to the most relevant subset. This reduces
|
|
10
10
|
* MCP tool calls and context window consumption.
|
|
11
11
|
*
|
|
12
|
-
*
|
|
13
|
-
* Ported from Subway_RN_Demo/scripts/context-engine.js for thumbgate.
|
|
12
|
+
* Context assembly engine for ThumbGate feedback memory.
|
|
14
13
|
* PATH: PROJECT_ROOT = path.join(__dirname, '..') — 1 level up from scripts/
|
|
15
14
|
*/
|
|
16
15
|
|
|
@@ -26,7 +26,10 @@ const {
|
|
|
26
26
|
readSessionHandoff,
|
|
27
27
|
recordProvenance,
|
|
28
28
|
} = require('./contextfs');
|
|
29
|
-
const {
|
|
29
|
+
const { loadOptionalModule } = require('./private-core-boundary');
|
|
30
|
+
const { retrieveRelevantLessons } = loadOptionalModule('./lesson-retrieval', () => ({
|
|
31
|
+
retrieveRelevantLessons: () => [],
|
|
32
|
+
}));
|
|
30
33
|
const { evaluatePretool } = require('./hybrid-feedback-context');
|
|
31
34
|
const { loadProfile } = require('./user-profile');
|
|
32
35
|
const {
|
|
@@ -243,7 +243,7 @@ function buildIncidentReviewSpec(data) {
|
|
|
243
243
|
badge: String(gate.action || 'block').toUpperCase(),
|
|
244
244
|
tone: gate.action === 'warn' ? 'info' : 'warning',
|
|
245
245
|
})),
|
|
246
|
-
'No active
|
|
246
|
+
'No active checks configured.'
|
|
247
247
|
),
|
|
248
248
|
buildList(
|
|
249
249
|
'Root cause clusters',
|
package/scripts/dashboard.js
CHANGED
|
@@ -6,16 +6,36 @@ const path = require('path');
|
|
|
6
6
|
const { aggregateFailureDiagnostics } = require('./failure-diagnostics');
|
|
7
7
|
const { AUDIT_LOG_FILENAME } = require('./audit-trail');
|
|
8
8
|
const { getBillingSummary, loadFunnelLedger, loadResolvedRevenueEvents } = require('./billing');
|
|
9
|
+
const {
|
|
10
|
+
createUnavailableReport,
|
|
11
|
+
loadOptionalModule,
|
|
12
|
+
} = require('./private-core-boundary');
|
|
9
13
|
const { getTelemetryAnalytics, loadTelemetryEvents } = require('./telemetry-analytics');
|
|
10
14
|
const { getAutoGatesPath } = require('./auto-promote-gates');
|
|
11
|
-
const { summarizeDelegation } = require('./delegation-runtime');
|
|
12
15
|
const { loadGatesConfig } = require('./gates-engine');
|
|
13
16
|
const { filterEntriesForWindow, resolveAnalyticsWindow } = require('./analytics-window');
|
|
14
17
|
const { resolveHostedBillingConfig } = require('./hosted-config');
|
|
15
18
|
const { generateAgentReadinessReport } = require('./agent-readiness');
|
|
16
19
|
const { summarizeGateTemplates } = require('./gate-templates');
|
|
17
|
-
const {
|
|
18
|
-
|
|
20
|
+
const { buildPredictiveInsights } = loadOptionalModule('./predictive-insights', () => ({
|
|
21
|
+
buildPredictiveInsights: () => ({
|
|
22
|
+
upgradePropensity: {
|
|
23
|
+
pro: { band: 'unavailable', score: 0 },
|
|
24
|
+
team: { band: 'unavailable', score: 0 },
|
|
25
|
+
},
|
|
26
|
+
revenueForecast: {
|
|
27
|
+
predictedBookedRevenueCents: 0,
|
|
28
|
+
incrementalOpportunityCents: 0,
|
|
29
|
+
},
|
|
30
|
+
anomalySummary: {
|
|
31
|
+
count: 0,
|
|
32
|
+
severity: 'none',
|
|
33
|
+
},
|
|
34
|
+
topCreators: [],
|
|
35
|
+
topSources: [],
|
|
36
|
+
...createUnavailableReport('Predictive insights'),
|
|
37
|
+
}),
|
|
38
|
+
}));
|
|
19
39
|
const { routeProfile } = require('./profile-router');
|
|
20
40
|
const { getSettingsStatus } = require('./settings-hierarchy');
|
|
21
41
|
const { summarizeWorkflowRuns } = require('./workflow-runs');
|
|
@@ -28,6 +48,40 @@ const DEFAULT_GATES_PATH = path.join(PROJECT_ROOT, 'config', 'gates', 'default.j
|
|
|
28
48
|
const LANDING_PAGE_PATH = path.join(PROJECT_ROOT, 'public', 'index.html');
|
|
29
49
|
const DASHBOARD_REVIEW_STATE_FILE = 'dashboard-review-state.json';
|
|
30
50
|
|
|
51
|
+
function loadOrgDashboardModule() {
|
|
52
|
+
const modulePath = path.resolve(__dirname, 'org-dashboard.js');
|
|
53
|
+
if (!fs.existsSync(modulePath)) return null;
|
|
54
|
+
return loadOptionalModule('./org-dashboard', () => ({
|
|
55
|
+
generateOrgDashboard: ({ windowHours } = {}) => buildUnavailableOrgDashboard(windowHours || 24),
|
|
56
|
+
}));
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
function loadDelegationRuntimeModule() {
|
|
60
|
+
const modulePath = path.resolve(__dirname, 'delegation-runtime.js');
|
|
61
|
+
if (!fs.existsSync(modulePath)) return null;
|
|
62
|
+
return require(modulePath);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
function buildUnavailableOrgDashboard(windowHours) {
|
|
66
|
+
return {
|
|
67
|
+
available: false,
|
|
68
|
+
windowHours,
|
|
69
|
+
totalAgents: 0,
|
|
70
|
+
activeAgents: 0,
|
|
71
|
+
totalToolCalls: 0,
|
|
72
|
+
totalBlocked: 0,
|
|
73
|
+
totalWarned: 0,
|
|
74
|
+
totalAllowed: 0,
|
|
75
|
+
orgAdherenceRate: 100,
|
|
76
|
+
topBlockedGates: [],
|
|
77
|
+
riskAgents: [],
|
|
78
|
+
agents: [],
|
|
79
|
+
proRequired: true,
|
|
80
|
+
upgradeMessage: 'Org dashboard is available only in the private ThumbGate Core runtime (ThumbGate-Core).',
|
|
81
|
+
availability: 'private_core',
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
|
|
31
85
|
// ---------------------------------------------------------------------------
|
|
32
86
|
// Data readers
|
|
33
87
|
// ---------------------------------------------------------------------------
|
|
@@ -665,6 +719,197 @@ function countCoverage(entries, resolver) {
|
|
|
665
719
|
return safeRate(matched, entries.length);
|
|
666
720
|
}
|
|
667
721
|
|
|
722
|
+
function sumCounterValues(counter = {}) {
|
|
723
|
+
return Object.values(counter).reduce((sum, value) => sum + (Number(value) || 0), 0);
|
|
724
|
+
}
|
|
725
|
+
|
|
726
|
+
function sumKeysMatching(counter = {}, matcher) {
|
|
727
|
+
return Object.entries(counter).reduce((sum, entry) => {
|
|
728
|
+
const [key, value] = entry;
|
|
729
|
+
return matcher(key) ? sum + (Number(value) || 0) : sum;
|
|
730
|
+
}, 0);
|
|
731
|
+
}
|
|
732
|
+
|
|
733
|
+
function rankCounter(counter = {}, limit = 5) {
|
|
734
|
+
return Object.entries(counter)
|
|
735
|
+
.sort((a, b) => b[1] - a[1])
|
|
736
|
+
.slice(0, limit)
|
|
737
|
+
.map(([key, count]) => ({ key, count }));
|
|
738
|
+
}
|
|
739
|
+
|
|
740
|
+
function mapBuyerLossTheme(reasonCode) {
|
|
741
|
+
const normalized = String(reasonCode || 'unknown').toLowerCase();
|
|
742
|
+
if (['too_expensive', 'price_shock', 'budget', 'need_budget_approval'].includes(normalized)) {
|
|
743
|
+
return 'pricing';
|
|
744
|
+
}
|
|
745
|
+
if (['need_more_proof', 'trust_gap', 'security_unclear'].includes(normalized)) {
|
|
746
|
+
return 'trust';
|
|
747
|
+
}
|
|
748
|
+
if (['not_ready', 'later', 'just_researching'].includes(normalized)) {
|
|
749
|
+
return 'timing';
|
|
750
|
+
}
|
|
751
|
+
if (['need_team_features', 'need_team_approval'].includes(normalized)) {
|
|
752
|
+
return 'team';
|
|
753
|
+
}
|
|
754
|
+
if (['integration_unclear', 'setup_confusing'].includes(normalized)) {
|
|
755
|
+
return 'integration';
|
|
756
|
+
}
|
|
757
|
+
if (['prefer_oss'].includes(normalized)) {
|
|
758
|
+
return 'open_source';
|
|
759
|
+
}
|
|
760
|
+
return 'unknown';
|
|
761
|
+
}
|
|
762
|
+
|
|
763
|
+
function buildLossAnalysis(analytics) {
|
|
764
|
+
const telemetry = analytics.telemetry || {};
|
|
765
|
+
const visitors = telemetry.visitors || {};
|
|
766
|
+
const ctas = telemetry.ctas || {};
|
|
767
|
+
const behavior = telemetry.behavior || {};
|
|
768
|
+
const buyerLoss = analytics.buyerLoss || {};
|
|
769
|
+
const conversionFunnel = telemetry.conversionFunnel || {};
|
|
770
|
+
const runtimeConfig = resolveHostedBillingConfig();
|
|
771
|
+
const monthlyPriceCents = Math.round((Number(runtimeConfig.proPriceDollars) || 19) * 100);
|
|
772
|
+
const pageViews = visitors.pageViews || 0;
|
|
773
|
+
const checkoutStarts = ctas.checkoutStarts || 0;
|
|
774
|
+
const paidOrders = analytics.funnel ? analytics.funnel.paidOrders || 0 : 0;
|
|
775
|
+
const trialEmails = conversionFunnel.trialEmails || 0;
|
|
776
|
+
const explicitReasons = buyerLoss.reasonsByCode || {};
|
|
777
|
+
const reasonThemes = {};
|
|
778
|
+
Object.entries(explicitReasons).forEach(([reasonCode, count]) => {
|
|
779
|
+
const theme = mapBuyerLossTheme(reasonCode);
|
|
780
|
+
reasonThemes[theme] = (reasonThemes[theme] || 0) + count;
|
|
781
|
+
});
|
|
782
|
+
|
|
783
|
+
const proImpressions = sumKeysMatching(behavior.ctaImpressionsById || {}, (key) => /pro|pricing/i.test(key));
|
|
784
|
+
const proClicks = sumKeysMatching(ctas.byId || {}, (key) => /pro|pricing/i.test(key));
|
|
785
|
+
const pricingViews = sumKeysMatching(behavior.sectionViewsById || {}, (key) => /pricing/i.test(key));
|
|
786
|
+
const proofViews = sumKeysMatching(behavior.sectionViewsById || {}, (key) => /proof/i.test(key));
|
|
787
|
+
const exitsBeforePricing = sumKeysMatching(behavior.exitsByLastVisibleSection || {}, (key) => !/pricing|faq/i.test(key));
|
|
788
|
+
const checkoutLossCount = Math.max(0, checkoutStarts - paidOrders);
|
|
789
|
+
|
|
790
|
+
const stageDropoff = [
|
|
791
|
+
{
|
|
792
|
+
key: 'landing_to_checkout',
|
|
793
|
+
stage: 'landing',
|
|
794
|
+
lostCount: Math.max(0, pageViews - checkoutStarts),
|
|
795
|
+
rate: safeRate(Math.max(0, pageViews - checkoutStarts), pageViews),
|
|
796
|
+
},
|
|
797
|
+
{
|
|
798
|
+
key: 'cta_impression_to_click',
|
|
799
|
+
stage: 'message',
|
|
800
|
+
lostCount: Math.max(0, proImpressions - proClicks),
|
|
801
|
+
rate: safeRate(Math.max(0, proImpressions - proClicks), proImpressions),
|
|
802
|
+
},
|
|
803
|
+
{
|
|
804
|
+
key: 'email_focus_to_capture',
|
|
805
|
+
stage: 'lead_capture',
|
|
806
|
+
lostCount: Math.max(0, (behavior.emailFocusEvents || 0) - trialEmails),
|
|
807
|
+
rate: safeRate(Math.max(0, (behavior.emailFocusEvents || 0) - trialEmails), behavior.emailFocusEvents || 0),
|
|
808
|
+
},
|
|
809
|
+
{
|
|
810
|
+
key: 'checkout_to_paid',
|
|
811
|
+
stage: 'checkout',
|
|
812
|
+
lostCount: checkoutLossCount,
|
|
813
|
+
rate: safeRate(checkoutLossCount, checkoutStarts),
|
|
814
|
+
},
|
|
815
|
+
].sort((a, b) => b.lostCount - a.lostCount);
|
|
816
|
+
|
|
817
|
+
const inferredCauses = [];
|
|
818
|
+
if (exitsBeforePricing > 0) {
|
|
819
|
+
inferredCauses.push({
|
|
820
|
+
key: 'message_drop_before_pricing',
|
|
821
|
+
stage: 'landing',
|
|
822
|
+
count: exitsBeforePricing,
|
|
823
|
+
evidence: {
|
|
824
|
+
topExitSection: behavior.topExitSection,
|
|
825
|
+
pricingViews,
|
|
826
|
+
pageExits: behavior.pageExits || 0,
|
|
827
|
+
},
|
|
828
|
+
});
|
|
829
|
+
}
|
|
830
|
+
if (proImpressions > 0 && proClicks < proImpressions) {
|
|
831
|
+
inferredCauses.push({
|
|
832
|
+
key: 'weak_pricing_cta_response',
|
|
833
|
+
stage: 'message',
|
|
834
|
+
count: Math.max(0, proImpressions - proClicks),
|
|
835
|
+
evidence: {
|
|
836
|
+
proImpressions,
|
|
837
|
+
proClicks,
|
|
838
|
+
impressionToClickRate: safeRate(proClicks, proImpressions),
|
|
839
|
+
},
|
|
840
|
+
});
|
|
841
|
+
}
|
|
842
|
+
if ((behavior.emailAbandonEvents || 0) > 0) {
|
|
843
|
+
inferredCauses.push({
|
|
844
|
+
key: 'email_capture_friction',
|
|
845
|
+
stage: 'lead_capture',
|
|
846
|
+
count: behavior.emailAbandonEvents || 0,
|
|
847
|
+
evidence: {
|
|
848
|
+
emailFocusEvents: behavior.emailFocusEvents || 0,
|
|
849
|
+
emailAbandonEvents: behavior.emailAbandonEvents || 0,
|
|
850
|
+
emailAbandonRate: behavior.emailAbandonRate || 0,
|
|
851
|
+
},
|
|
852
|
+
});
|
|
853
|
+
}
|
|
854
|
+
if (checkoutLossCount > 0 || ctas.checkoutFailures || ctas.lookupFailures || ctas.checkoutCancelled || ctas.checkoutAbandoned) {
|
|
855
|
+
inferredCauses.push({
|
|
856
|
+
key: 'checkout_friction',
|
|
857
|
+
stage: 'checkout',
|
|
858
|
+
count: checkoutLossCount,
|
|
859
|
+
evidence: {
|
|
860
|
+
checkoutStarts,
|
|
861
|
+
paidOrders,
|
|
862
|
+
checkoutCancelled: ctas.checkoutCancelled || 0,
|
|
863
|
+
checkoutAbandoned: ctas.checkoutAbandoned || 0,
|
|
864
|
+
checkoutFailures: ctas.checkoutFailures || 0,
|
|
865
|
+
lookupFailures: ctas.lookupFailures || 0,
|
|
866
|
+
},
|
|
867
|
+
});
|
|
868
|
+
}
|
|
869
|
+
const topTheme = rankCounter(reasonThemes, 1)[0] || null;
|
|
870
|
+
if (topTheme) {
|
|
871
|
+
inferredCauses.push({
|
|
872
|
+
key: `explicit_${topTheme.key}`,
|
|
873
|
+
stage: topTheme.key === 'pricing' ? 'pricing' : 'objection',
|
|
874
|
+
count: topTheme.count,
|
|
875
|
+
evidence: {
|
|
876
|
+
theme: topTheme.key,
|
|
877
|
+
topReasons: rankCounter(explicitReasons, 3),
|
|
878
|
+
},
|
|
879
|
+
});
|
|
880
|
+
}
|
|
881
|
+
|
|
882
|
+
inferredCauses.sort((a, b) => b.count - a.count);
|
|
883
|
+
|
|
884
|
+
return {
|
|
885
|
+
primaryIssue: inferredCauses[0] || null,
|
|
886
|
+
stageDropoff,
|
|
887
|
+
inferredCauses,
|
|
888
|
+
explicitThemes: rankCounter(reasonThemes, 6),
|
|
889
|
+
explicitReasons: rankCounter(explicitReasons, 6),
|
|
890
|
+
behaviorSignals: {
|
|
891
|
+
topViewedSection: behavior.topViewedSection || null,
|
|
892
|
+
topExitSection: behavior.topExitSection || null,
|
|
893
|
+
topExitDwellBucket: behavior.topExitDwellBucket || null,
|
|
894
|
+
topImpressionCta: behavior.topImpressionCta || null,
|
|
895
|
+
pricingViews,
|
|
896
|
+
proofViews,
|
|
897
|
+
pageExits: behavior.pageExits || 0,
|
|
898
|
+
exitsBeforePricing,
|
|
899
|
+
averageExitEngagementMs: behavior.averageExitEngagementMs || 0,
|
|
900
|
+
averageExitScrollPercent: behavior.averageExitScrollPercent || 0,
|
|
901
|
+
emailFocusEvents: behavior.emailFocusEvents || 0,
|
|
902
|
+
emailAbandonEvents: behavior.emailAbandonEvents || 0,
|
|
903
|
+
},
|
|
904
|
+
revenueOpportunity: {
|
|
905
|
+
currentMonthlyPriceCents: monthlyPriceCents,
|
|
906
|
+
checkoutLossCount,
|
|
907
|
+
explicitBuyerLossCount: buyerLoss.totalSignals || 0,
|
|
908
|
+
opportunityAtCurrentMonthlyPriceCents: checkoutLossCount * monthlyPriceCents,
|
|
909
|
+
},
|
|
910
|
+
};
|
|
911
|
+
}
|
|
912
|
+
|
|
668
913
|
function computeAnalyticsSummary(feedbackDir, options = {}) {
|
|
669
914
|
const analyticsWindow = resolveAnalyticsWindow(options.analyticsWindow || options);
|
|
670
915
|
const telemetryEntries = filterEntriesForWindow(
|
|
@@ -749,6 +994,13 @@ function computeAnalyticsSummary(feedbackDir, options = {}) {
|
|
|
749
994
|
topSurface: null,
|
|
750
995
|
topQuery: null,
|
|
751
996
|
},
|
|
997
|
+
trackedLinks: telemetry.trackedLinks || {
|
|
998
|
+
totalHits: 0,
|
|
999
|
+
totalCheckoutStarts: 0,
|
|
1000
|
+
overallConversionRate: 0,
|
|
1001
|
+
bySlug: {},
|
|
1002
|
+
topSlug: null,
|
|
1003
|
+
},
|
|
752
1004
|
efficiency,
|
|
753
1005
|
revenue: billing.revenue || {
|
|
754
1006
|
paidProviderEvents: 0,
|
|
@@ -1150,9 +1402,19 @@ function generateDashboard(feedbackDir, options = {}) {
|
|
|
1150
1402
|
analyticsWindow,
|
|
1151
1403
|
billingSummary,
|
|
1152
1404
|
});
|
|
1405
|
+
analytics.lossAnalysis = buildLossAnalysis(analytics);
|
|
1153
1406
|
const observability = computeObservabilityStats(diagnosticEntries, diagnostics, secretGuard, analytics.telemetry);
|
|
1154
1407
|
const instrumentation = computeInstrumentationReadiness(analytics, billingSummary);
|
|
1155
|
-
const
|
|
1408
|
+
const delegationRuntime = loadDelegationRuntimeModule();
|
|
1409
|
+
const delegation = delegationRuntime
|
|
1410
|
+
? delegationRuntime.summarizeDelegation(feedbackDir)
|
|
1411
|
+
: {
|
|
1412
|
+
totalHandoffs: 0,
|
|
1413
|
+
successfulHandoffs: 0,
|
|
1414
|
+
blockedHandoffs: 0,
|
|
1415
|
+
activePlans: [],
|
|
1416
|
+
availability: 'private_core',
|
|
1417
|
+
};
|
|
1156
1418
|
const readiness = generateAgentReadinessReport({ projectRoot: PROJECT_ROOT });
|
|
1157
1419
|
const harness = computeHarnessOverview(feedbackDir, entries);
|
|
1158
1420
|
const interventionPolicy = getInterventionPolicySummary(feedbackDir);
|
|
@@ -1219,11 +1481,15 @@ function generateDashboard(feedbackDir, options = {}) {
|
|
|
1219
1481
|
day.lessons = lessonPipeline.lessonsByDay.get(day.dayKey) || 0;
|
|
1220
1482
|
}
|
|
1221
1483
|
|
|
1222
|
-
const
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1484
|
+
const teamWindowHours = resolveTeamWindowHours(analyticsWindow);
|
|
1485
|
+
const orgDashboard = loadOrgDashboardModule();
|
|
1486
|
+
const team = orgDashboard
|
|
1487
|
+
? orgDashboard.generateOrgDashboard({
|
|
1488
|
+
windowHours: teamWindowHours,
|
|
1489
|
+
authContext: options.authContext,
|
|
1490
|
+
proOverride: options.teamProOverride,
|
|
1491
|
+
})
|
|
1492
|
+
: buildUnavailableOrgDashboard(teamWindowHours);
|
|
1227
1493
|
const templateLibrary = summarizeGateTemplates();
|
|
1228
1494
|
const predictive = buildPredictiveInsights({
|
|
1229
1495
|
telemetryAnalytics: analytics.telemetry,
|
|
@@ -192,8 +192,18 @@ function collapseDecisionTimeline(records) {
|
|
|
192
192
|
});
|
|
193
193
|
}
|
|
194
194
|
|
|
195
|
-
function
|
|
196
|
-
|
|
195
|
+
function resolveNow(now) {
|
|
196
|
+
if (now instanceof Date) return new Date(now.getTime());
|
|
197
|
+
if (typeof now === 'number' && Number.isFinite(now)) return new Date(now);
|
|
198
|
+
if (typeof now === 'string' && now) {
|
|
199
|
+
const parsed = new Date(now);
|
|
200
|
+
if (!Number.isNaN(parsed.getTime())) return parsed;
|
|
201
|
+
}
|
|
202
|
+
return new Date();
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
function initializeDaySeries(dayCount, now) {
|
|
206
|
+
const today = resolveNow(now);
|
|
197
207
|
today.setHours(0, 0, 0, 0);
|
|
198
208
|
const days = [];
|
|
199
209
|
for (let offset = dayCount - 1; offset >= 0; offset -= 1) {
|
|
@@ -224,7 +234,7 @@ function computeDecisionMetrics(feedbackDir, options = {}) {
|
|
|
224
234
|
const dayCount = Number.isInteger(options.dayCount) ? options.dayCount : DEFAULT_DAY_COUNT;
|
|
225
235
|
const records = readDecisionLog(getDecisionLogPath(feedbackDir));
|
|
226
236
|
const actions = collapseDecisionTimeline(records).filter((entry) => entry.evaluation);
|
|
227
|
-
const series = initializeDaySeries(dayCount);
|
|
237
|
+
const series = initializeDaySeries(dayCount, options.now);
|
|
228
238
|
const dayMap = new Map(series.map((day) => [day.dayKey, day]));
|
|
229
239
|
const outcomeCounts = {
|
|
230
240
|
accepted: 0,
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
function buildDocumentWorkflowPlan(options = {}) {
|
|
4
|
+
const provider = options.provider || 'secure_content_layer';
|
|
5
|
+
const workflow = options.workflow || 'document_intake_routing';
|
|
6
|
+
|
|
7
|
+
return {
|
|
8
|
+
workflow,
|
|
9
|
+
provider,
|
|
10
|
+
steps: [
|
|
11
|
+
'discover eligible folders through approved connector scope',
|
|
12
|
+
'extract document metadata inside sandbox',
|
|
13
|
+
'classify document type with structured output',
|
|
14
|
+
'route document to approved destination',
|
|
15
|
+
'write audit event for every read, extraction, decision, and route',
|
|
16
|
+
],
|
|
17
|
+
zeroTrust: {
|
|
18
|
+
leastPrivilegeScopes: true,
|
|
19
|
+
credentialsOutsideSandbox: true,
|
|
20
|
+
noRawDocumentExportByDefault: true,
|
|
21
|
+
perFolderApproval: true,
|
|
22
|
+
},
|
|
23
|
+
requiredEvidence: [
|
|
24
|
+
'connector scope',
|
|
25
|
+
'source document id',
|
|
26
|
+
'classification result',
|
|
27
|
+
'route destination',
|
|
28
|
+
'audit event id',
|
|
29
|
+
'sandbox manifest',
|
|
30
|
+
],
|
|
31
|
+
gates: [
|
|
32
|
+
'block routing when connector scope is missing',
|
|
33
|
+
'block raw content export unless explicitly approved',
|
|
34
|
+
'block completion claims without audit event id',
|
|
35
|
+
'require human review for legal, financial, medical, or HR documents',
|
|
36
|
+
],
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function evaluateDocumentWorkflowRun(run = {}) {
|
|
41
|
+
const issues = [];
|
|
42
|
+
if (!run.connectorScope) issues.push('missing_connector_scope');
|
|
43
|
+
if (!run.sourceDocumentId) issues.push('missing_source_document_id');
|
|
44
|
+
if (!run.classification) issues.push('missing_classification');
|
|
45
|
+
if (!run.routeDestination) issues.push('missing_route_destination');
|
|
46
|
+
if (!run.auditEventId) issues.push('missing_audit_event_id');
|
|
47
|
+
if (!run.sandboxManifest) issues.push('missing_sandbox_manifest');
|
|
48
|
+
if (run.rawExport && !run.rawExportApproved) issues.push('raw_export_requires_approval');
|
|
49
|
+
if (['legal', 'financial', 'medical', 'hr'].includes(String(run.classification).toLowerCase()) && !run.humanReviewed) {
|
|
50
|
+
issues.push('sensitive_document_human_review_required');
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
return {
|
|
54
|
+
decision: issues.length ? 'deny' : 'allow',
|
|
55
|
+
issues,
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
module.exports = {
|
|
60
|
+
buildDocumentWorkflowPlan,
|
|
61
|
+
evaluateDocumentWorkflowRun,
|
|
62
|
+
};
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
function buildEnterpriseAgentRollout(input = {}) {
|
|
5
|
+
const industry = input.industry || 'enterprise software';
|
|
6
|
+
return {
|
|
7
|
+
program: 'ThumbGate Enterprise Agent Acceleration',
|
|
8
|
+
industry,
|
|
9
|
+
operatingModel: {
|
|
10
|
+
forwardDeployedEngineer: true,
|
|
11
|
+
humanInTheLead: true,
|
|
12
|
+
domainExpertsRequired: true,
|
|
13
|
+
sovereignDeploymentOption: true,
|
|
14
|
+
},
|
|
15
|
+
phases: [
|
|
16
|
+
{ id: 'discover', outcome: 'rank workflows by measurable business value and risk' },
|
|
17
|
+
{ id: 'prototype', outcome: 'ship one governed agent with evidence and rollback' },
|
|
18
|
+
{ id: 'scale', outcome: 'publish reusable agent catalog and approval policies' },
|
|
19
|
+
{ id: 'operate', outcome: 'review traces, ROI, incidents, and policy drift weekly' },
|
|
20
|
+
],
|
|
21
|
+
governance: [
|
|
22
|
+
'human oversight for high-stakes recommendations',
|
|
23
|
+
'sovereign data boundary when required',
|
|
24
|
+
'agent catalog with owner and allowed tools',
|
|
25
|
+
'decision journal for every business-critical action',
|
|
26
|
+
'measurable outcome before expansion',
|
|
27
|
+
],
|
|
28
|
+
metrics: ['cycle_time_saved', 'blocked_risky_actions', 'approved_agent_runs', 'business_value_cents', 'incident_rate'],
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
module.exports = {
|
|
33
|
+
buildEnterpriseAgentRollout,
|
|
34
|
+
};
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
function buildExperienceReplayPolicy(options = {}) {
|
|
4
|
+
const maxStalenessHours = Number.isFinite(options.maxStalenessHours) ? options.maxStalenessHours : 24;
|
|
5
|
+
const replayRatio = Number.isFinite(options.replayRatio) ? options.replayRatio : 0.25;
|
|
6
|
+
const minEntropy = Number.isFinite(options.minEntropy) ? options.minEntropy : 0.65;
|
|
7
|
+
|
|
8
|
+
return {
|
|
9
|
+
policyId: 'feedback_experience_replay',
|
|
10
|
+
purpose: 'Reuse high-signal feedback trajectories without letting stale lessons dominate training.',
|
|
11
|
+
buffer: {
|
|
12
|
+
strategy: 'fifo_with_quality_filters',
|
|
13
|
+
maxStalenessHours,
|
|
14
|
+
replayRatio,
|
|
15
|
+
sampleWithoutRemoval: true,
|
|
16
|
+
},
|
|
17
|
+
filters: [
|
|
18
|
+
'redacted',
|
|
19
|
+
'source_feedback_id_present',
|
|
20
|
+
'outcome_evidence_present',
|
|
21
|
+
'not_contradicted_by_newer_lesson',
|
|
22
|
+
'not_low_confidence_or_vague_feedback',
|
|
23
|
+
],
|
|
24
|
+
monitors: {
|
|
25
|
+
maxStalenessHours,
|
|
26
|
+
minEntropy,
|
|
27
|
+
compareAgainstFreshOnly: true,
|
|
28
|
+
metrics: ['gate_precision', 'gate_recall', 'unsupported_claim_rate', 'policy_entropy', 'compute_saved_percent'],
|
|
29
|
+
},
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function evaluateReplayCandidate(candidate = {}, policy = buildExperienceReplayPolicy()) {
|
|
34
|
+
const issues = [];
|
|
35
|
+
if (!candidate.sourceFeedbackId) issues.push('missing_source_feedback_id');
|
|
36
|
+
if (!candidate.redacted) issues.push('redaction_required');
|
|
37
|
+
if (!candidate.outcomeEvidence) issues.push('missing_outcome_evidence');
|
|
38
|
+
if (candidate.contradictedByNewerLesson) issues.push('contradicted_by_newer_lesson');
|
|
39
|
+
if (candidate.vagueFeedback) issues.push('vague_feedback_not_replayable');
|
|
40
|
+
|
|
41
|
+
const ageHours = Number(candidate.ageHours || 0);
|
|
42
|
+
if (ageHours > policy.buffer.maxStalenessHours) issues.push('stale_replay_sample');
|
|
43
|
+
|
|
44
|
+
return {
|
|
45
|
+
decision: issues.length ? 'reject' : 'accept',
|
|
46
|
+
issues,
|
|
47
|
+
replayWeight: issues.length ? 0 : Math.min(policy.buffer.replayRatio, Number(candidate.qualityScore || 1)),
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function evaluateReplayRun(run = {}, policy = buildExperienceReplayPolicy()) {
|
|
52
|
+
const issues = [];
|
|
53
|
+
if (Number(run.replayRatio || 0) > 0.5) issues.push('replay_ratio_too_high');
|
|
54
|
+
if (Number(run.policyEntropy || 0) < policy.monitors.minEntropy) issues.push('policy_entropy_too_low');
|
|
55
|
+
if (!run.freshOnlyBaseline) issues.push('missing_fresh_only_baseline');
|
|
56
|
+
if (!run.computeSavedPercent && run.computeSavedPercent !== 0) issues.push('missing_compute_saved_metric');
|
|
57
|
+
|
|
58
|
+
return {
|
|
59
|
+
decision: issues.length ? 'warn' : 'allow',
|
|
60
|
+
issues,
|
|
61
|
+
computeEfficient: Number(run.computeSavedPercent || 0) > 0 && Number(run.policyEntropy || 0) >= policy.monitors.minEntropy,
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
module.exports = {
|
|
66
|
+
buildExperienceReplayPolicy,
|
|
67
|
+
evaluateReplayCandidate,
|
|
68
|
+
evaluateReplayRun,
|
|
69
|
+
};
|
|
@@ -123,7 +123,7 @@ function buildPreferenceRow(pair, index) {
|
|
|
123
123
|
function buildDatasetInfo({ traceCount, preferenceCount, exportedAt }) {
|
|
124
124
|
return {
|
|
125
125
|
dataset_info: {
|
|
126
|
-
description: 'Agent traces and DPO preference pairs from ThumbGate — pre-action
|
|
126
|
+
description: 'Agent traces and DPO preference pairs from ThumbGate — pre-action checks for AI coding agents. Contains real-world tool call feedback, failure patterns, and learned corrections.',
|
|
127
127
|
citation: '',
|
|
128
128
|
homepage: 'https://github.com/IgorGanapolsky/ThumbGate',
|
|
129
129
|
license: 'MIT',
|