thumbgate 0.9.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (364) hide show
  1. package/.claude-plugin/README.md +134 -0
  2. package/.claude-plugin/bundle/icon.png +0 -0
  3. package/.claude-plugin/bundle/icon.svg +18 -0
  4. package/.claude-plugin/bundle/server/index.js +24 -0
  5. package/.claude-plugin/marketplace.json +36 -0
  6. package/.claude-plugin/plugin.json +21 -0
  7. package/.well-known/mcp/server-card.json +231 -0
  8. package/LICENSE +21 -0
  9. package/README.md +375 -0
  10. package/adapters/README.md +9 -0
  11. package/adapters/amp/skills/thumbgate-feedback/SKILL.md +22 -0
  12. package/adapters/chatgpt/INSTALL.md +83 -0
  13. package/adapters/chatgpt/openapi.yaml +1281 -0
  14. package/adapters/claude/.mcp.json +14 -0
  15. package/adapters/codex/config.toml +9 -0
  16. package/adapters/gemini/function-declarations.json +224 -0
  17. package/adapters/mcp/server-stdio.js +788 -0
  18. package/adapters/opencode/opencode.json +15 -0
  19. package/bin/cli.js +1484 -0
  20. package/bin/memory.sh +64 -0
  21. package/bin/obsidian-sync.sh +20 -0
  22. package/bin/postinstall.js +37 -0
  23. package/config/build-metadata.json +4 -0
  24. package/config/e2e-critical-flows.json +45 -0
  25. package/config/gate-templates.json +77 -0
  26. package/config/gates/claim-verification.json +29 -0
  27. package/config/gates/computer-use.json +39 -0
  28. package/config/gates/default.json +117 -0
  29. package/config/github-about.json +25 -0
  30. package/config/mcp-allowlists.json +135 -0
  31. package/config/model-tiers.json +33 -0
  32. package/config/partner-routing.json +132 -0
  33. package/config/policy-bundles/constrained-v1.json +64 -0
  34. package/config/policy-bundles/default-v1.json +91 -0
  35. package/config/rubrics/default-v1.json +52 -0
  36. package/config/skill-packs/react-testing.json +23 -0
  37. package/config/skill-packs/stripe-integration/references/api-spec.json +1 -0
  38. package/config/skill-packs/stripe-integration/references/webhook-guide.md +3 -0
  39. package/config/skill-specs/pr-reviewer.json +9 -0
  40. package/config/skill-specs/release-status.json +9 -0
  41. package/config/skill-specs/ticket-triage.json +9 -0
  42. package/config/subagent-profiles.json +32 -0
  43. package/config/tessl-tiles.json +29 -0
  44. package/config/thumbgate-settings.managed.json +12 -0
  45. package/openapi/openapi.yaml +1281 -0
  46. package/package.json +283 -0
  47. package/plugins/amp-skill/INSTALL.md +52 -0
  48. package/plugins/amp-skill/SKILL.md +64 -0
  49. package/plugins/claude-codex-bridge/.claude-plugin/plugin.json +22 -0
  50. package/plugins/claude-codex-bridge/.mcp.json +12 -0
  51. package/plugins/claude-codex-bridge/INSTALL.md +43 -0
  52. package/plugins/claude-codex-bridge/README.md +46 -0
  53. package/plugins/claude-codex-bridge/scripts/codex-bridge.js +288 -0
  54. package/plugins/claude-codex-bridge/skills/adversarial-review/SKILL.md +24 -0
  55. package/plugins/claude-codex-bridge/skills/result/SKILL.md +22 -0
  56. package/plugins/claude-codex-bridge/skills/review/SKILL.md +28 -0
  57. package/plugins/claude-codex-bridge/skills/second-pass/SKILL.md +27 -0
  58. package/plugins/claude-codex-bridge/skills/setup/SKILL.md +21 -0
  59. package/plugins/claude-codex-bridge/skills/status/SKILL.md +19 -0
  60. package/plugins/claude-skill/INSTALL.md +55 -0
  61. package/plugins/claude-skill/SKILL.md +46 -0
  62. package/plugins/codex-profile/.codex-plugin/plugin.json +43 -0
  63. package/plugins/codex-profile/.mcp.json +12 -0
  64. package/plugins/codex-profile/AGENTS.md +20 -0
  65. package/plugins/codex-profile/INSTALL.md +66 -0
  66. package/plugins/codex-profile/README.md +37 -0
  67. package/plugins/cursor-marketplace/.cursor-plugin/plugin.json +23 -0
  68. package/plugins/cursor-marketplace/CHANGELOG.md +30 -0
  69. package/plugins/cursor-marketplace/LICENSE +21 -0
  70. package/plugins/cursor-marketplace/README.md +124 -0
  71. package/plugins/cursor-marketplace/agents/reliability-reviewer.md +31 -0
  72. package/plugins/cursor-marketplace/assets/logo-400x400.png +0 -0
  73. package/plugins/cursor-marketplace/commands/capture-feedback.md +33 -0
  74. package/plugins/cursor-marketplace/commands/check-gates.md +25 -0
  75. package/plugins/cursor-marketplace/commands/show-lessons.md +27 -0
  76. package/plugins/cursor-marketplace/hooks/hooks.json +10 -0
  77. package/plugins/cursor-marketplace/mcp.json +12 -0
  78. package/plugins/cursor-marketplace/rules/feedback-capture.mdc +34 -0
  79. package/plugins/cursor-marketplace/rules/pre-action-gates.mdc +30 -0
  80. package/plugins/cursor-marketplace/rules/session-continuity.mdc +28 -0
  81. package/plugins/cursor-marketplace/scripts/gate-check.sh +11 -0
  82. package/plugins/cursor-marketplace/skills/capture-feedback/SKILL.md +47 -0
  83. package/plugins/cursor-marketplace/skills/prevention-rules/SKILL.md +31 -0
  84. package/plugins/cursor-marketplace/skills/recall-context/SKILL.md +30 -0
  85. package/plugins/cursor-marketplace/skills/search-lessons/SKILL.md +33 -0
  86. package/plugins/gemini-extension/INSTALL.md +92 -0
  87. package/plugins/gemini-extension/gemini_prompt.txt +14 -0
  88. package/plugins/gemini-extension/tool_contract.json +45 -0
  89. package/plugins/opencode-profile/INSTALL.md +57 -0
  90. package/public/assets/instagram-card.png +0 -0
  91. package/public/assets/tiktok-agent-memory.mp4 +0 -0
  92. package/public/blog.html +400 -0
  93. package/public/dashboard.html +1093 -0
  94. package/public/guide.html +317 -0
  95. package/public/index.html +1014 -0
  96. package/public/learn/agent-harness-pattern.html +180 -0
  97. package/public/learn/ai-agent-persistent-memory.html +202 -0
  98. package/public/learn/learn.css +45 -0
  99. package/public/learn/mcp-pre-action-gates-explained.html +172 -0
  100. package/public/learn/stop-ai-agent-force-push.html +134 -0
  101. package/public/learn/vibe-coding-safety-net.html +142 -0
  102. package/public/learn.html +213 -0
  103. package/public/lessons.html +650 -0
  104. package/public/vercel.json +8 -0
  105. package/scripts/__pycache__/train_from_feedback.cpython-312.pyc +0 -0
  106. package/scripts/a2ui-engine.js +73 -0
  107. package/scripts/access-anomaly-detector.js +12 -0
  108. package/scripts/adk-consolidator.js +266 -0
  109. package/scripts/agent-readiness.js +220 -0
  110. package/scripts/agent-security-hardening.js +227 -0
  111. package/scripts/agentic-data-pipeline.js +847 -0
  112. package/scripts/analytics-report.js +328 -0
  113. package/scripts/analytics-window.js +158 -0
  114. package/scripts/async-job-runner.js +1001 -0
  115. package/scripts/audit-trail.js +398 -0
  116. package/scripts/auto-promote-gates.js +299 -0
  117. package/scripts/auto-wire-hooks.js +312 -0
  118. package/scripts/autonomous-sales-agent.js +39 -0
  119. package/scripts/autoresearch-runner.js +216 -0
  120. package/scripts/background-agent-governance.js +237 -0
  121. package/scripts/behavioral-extraction.js +97 -0
  122. package/scripts/belief-update.js +84 -0
  123. package/scripts/billing.js +2438 -0
  124. package/scripts/bot-detector.js +50 -0
  125. package/scripts/budget-guard.js +173 -0
  126. package/scripts/build-claude-mcpb.js +189 -0
  127. package/scripts/build-metadata.js +97 -0
  128. package/scripts/check-congruence.js +322 -0
  129. package/scripts/cli-feedback.js +135 -0
  130. package/scripts/cli-telemetry.js +87 -0
  131. package/scripts/cloudflare-dynamic-sandbox.js +315 -0
  132. package/scripts/code-reasoning.js +350 -0
  133. package/scripts/codegraph-context.js +466 -0
  134. package/scripts/commercial-offer.js +56 -0
  135. package/scripts/computer-use-firewall.js +250 -0
  136. package/scripts/context-engine.js +694 -0
  137. package/scripts/contextfs.js +1287 -0
  138. package/scripts/conversation-context.js +119 -0
  139. package/scripts/creator-campaigns.js +239 -0
  140. package/scripts/daemon-manager.js +108 -0
  141. package/scripts/daily-digest.js +11 -0
  142. package/scripts/dashboard-render-spec.js +395 -0
  143. package/scripts/dashboard.js +1058 -0
  144. package/scripts/data-governance.js +173 -0
  145. package/scripts/delegation-runtime.js +900 -0
  146. package/scripts/deploy-gcp.sh +44 -0
  147. package/scripts/deploy-policy.js +263 -0
  148. package/scripts/disagreement-mining.js +315 -0
  149. package/scripts/dispatch-brief.js +159 -0
  150. package/scripts/distribution-surfaces.js +44 -0
  151. package/scripts/dpo-optimizer.js +209 -0
  152. package/scripts/ephemeral-agent-store.js +219 -0
  153. package/scripts/eval-harness.js +56 -0
  154. package/scripts/evolution-state.js +241 -0
  155. package/scripts/experiment-tracker.js +267 -0
  156. package/scripts/export-databricks-bundle.js +242 -0
  157. package/scripts/export-dpo-pairs.js +345 -0
  158. package/scripts/export-kto-pairs.js +310 -0
  159. package/scripts/export-training.js +448 -0
  160. package/scripts/failure-diagnostics.js +558 -0
  161. package/scripts/feedback-attribution.js +313 -0
  162. package/scripts/feedback-fallback.js +111 -0
  163. package/scripts/feedback-history-distiller.js +391 -0
  164. package/scripts/feedback-inbox-read.js +162 -0
  165. package/scripts/feedback-loop.js +1887 -0
  166. package/scripts/feedback-paths.js +145 -0
  167. package/scripts/feedback-quality.js +139 -0
  168. package/scripts/feedback-root-consolidator.js +238 -0
  169. package/scripts/feedback-schema.js +426 -0
  170. package/scripts/feedback-session.js +286 -0
  171. package/scripts/feedback-to-memory.js +185 -0
  172. package/scripts/feedback-to-rules.js +163 -0
  173. package/scripts/filesystem-search.js +404 -0
  174. package/scripts/funnel-analytics.js +35 -0
  175. package/scripts/gate-satisfy.js +42 -0
  176. package/scripts/gate-stats.js +116 -0
  177. package/scripts/gate-templates.js +70 -0
  178. package/scripts/gates-engine.js +816 -0
  179. package/scripts/generate-paperbanana-diagrams.sh +99 -0
  180. package/scripts/generate-pretool-hook.sh +40 -0
  181. package/scripts/github-about.js +350 -0
  182. package/scripts/github-outreach.js +65 -0
  183. package/scripts/gtm-revenue-loop.js +520 -0
  184. package/scripts/hallucination-detector.js +226 -0
  185. package/scripts/hf-papers.js +317 -0
  186. package/scripts/history-distiller.js +200 -0
  187. package/scripts/hook-auto-capture.sh +95 -0
  188. package/scripts/hook-stop-pr-thread-check.sh +68 -0
  189. package/scripts/hook-stop-self-score.sh +51 -0
  190. package/scripts/hook-stop-verify-deploy.sh +31 -0
  191. package/scripts/hook-thumbgate-cache-updater.js +48 -0
  192. package/scripts/hook-verify-before-done.sh +20 -0
  193. package/scripts/hosted-config.js +170 -0
  194. package/scripts/hybrid-feedback-context.js +676 -0
  195. package/scripts/install-mcp.js +159 -0
  196. package/scripts/intent-router.js +392 -0
  197. package/scripts/internal-agent-bootstrap.js +490 -0
  198. package/scripts/jsonl-watcher.js +155 -0
  199. package/scripts/lesson-db.js +613 -0
  200. package/scripts/lesson-inference.js +315 -0
  201. package/scripts/lesson-retrieval.js +95 -0
  202. package/scripts/lesson-rotation.js +137 -0
  203. package/scripts/lesson-search.js +644 -0
  204. package/scripts/lesson-synthesis.js +196 -0
  205. package/scripts/license.js +50 -0
  206. package/scripts/local-model-profile.js +383 -0
  207. package/scripts/markdown-escape.js +12 -0
  208. package/scripts/marketing-experiment.js +671 -0
  209. package/scripts/mcp-config.js +149 -0
  210. package/scripts/mcp-policy.js +99 -0
  211. package/scripts/memalign-recall.js +111 -0
  212. package/scripts/memory-firewall.js +222 -0
  213. package/scripts/memory-migration.js +296 -0
  214. package/scripts/meta-policy.js +194 -0
  215. package/scripts/metered-billing.js +16 -0
  216. package/scripts/model-tier-router.js +301 -0
  217. package/scripts/money-watcher.js +71 -0
  218. package/scripts/multi-hop-recall.js +240 -0
  219. package/scripts/natural-language-harness.js +330 -0
  220. package/scripts/obsidian-export.js +712 -0
  221. package/scripts/operational-dashboard.js +103 -0
  222. package/scripts/operational-summary.js +93 -0
  223. package/scripts/optimize-context.js +17 -0
  224. package/scripts/org-dashboard.js +201 -0
  225. package/scripts/partner-orchestration.js +146 -0
  226. package/scripts/per-step-scoring.js +165 -0
  227. package/scripts/perplexity-marketing.js +466 -0
  228. package/scripts/pii-scanner.js +153 -0
  229. package/scripts/plan-gate.js +154 -0
  230. package/scripts/post-everywhere.js +308 -0
  231. package/scripts/post-to-x-retry.sh +22 -0
  232. package/scripts/post-to-x.js +369 -0
  233. package/scripts/pr-manager.js +236 -0
  234. package/scripts/predictive-insights.js +356 -0
  235. package/scripts/principle-extractor.js +162 -0
  236. package/scripts/pro-features.js +40 -0
  237. package/scripts/pro-local-dashboard.js +174 -0
  238. package/scripts/problem-detail.js +53 -0
  239. package/scripts/product-feedback.js +134 -0
  240. package/scripts/profile-router.js +245 -0
  241. package/scripts/prompt-dlp.js +221 -0
  242. package/scripts/prompt-guard.js +83 -0
  243. package/scripts/prove-adapters.js +863 -0
  244. package/scripts/prove-attribution.js +365 -0
  245. package/scripts/prove-automation.js +653 -0
  246. package/scripts/prove-autoresearch.js +304 -0
  247. package/scripts/prove-claim-verification.js +277 -0
  248. package/scripts/prove-cloudflare-sandbox.js +163 -0
  249. package/scripts/prove-data-pipeline.js +410 -0
  250. package/scripts/prove-data-quality.js +227 -0
  251. package/scripts/prove-evolution.js +352 -0
  252. package/scripts/prove-harnesses.js +287 -0
  253. package/scripts/prove-intelligence.js +259 -0
  254. package/scripts/prove-lancedb.js +371 -0
  255. package/scripts/prove-local-intelligence.js +342 -0
  256. package/scripts/prove-loop-closure.js +263 -0
  257. package/scripts/prove-predictive-insights.js +357 -0
  258. package/scripts/prove-runtime.js +350 -0
  259. package/scripts/prove-seo-gsd.js +234 -0
  260. package/scripts/prove-settings.js +279 -0
  261. package/scripts/prove-subway-upgrades.js +277 -0
  262. package/scripts/prove-tessl.js +229 -0
  263. package/scripts/prove-training-export.js +327 -0
  264. package/scripts/prove-workflow-contract.js +116 -0
  265. package/scripts/prove-xmemory.js +332 -0
  266. package/scripts/publish-decision.js +133 -0
  267. package/scripts/pulse.js +80 -0
  268. package/scripts/rate-limiter.js +125 -0
  269. package/scripts/reddit-dm-outreach.js +182 -0
  270. package/scripts/reddit-monitor-cron.sh +26 -0
  271. package/scripts/reflector-agent.js +221 -0
  272. package/scripts/reminder-engine.js +132 -0
  273. package/scripts/revenue-status.js +472 -0
  274. package/scripts/risk-scorer.js +458 -0
  275. package/scripts/rlaif-self-audit.js +129 -0
  276. package/scripts/rubric-engine.js +230 -0
  277. package/scripts/schedule-manager.js +251 -0
  278. package/scripts/secret-scanner.js +414 -0
  279. package/scripts/self-heal.js +147 -0
  280. package/scripts/self-healing-check.js +188 -0
  281. package/scripts/semantic-layer.js +98 -0
  282. package/scripts/seo-gsd.js +1153 -0
  283. package/scripts/settings-hierarchy.js +214 -0
  284. package/scripts/shieldcortex-memory-firewall-runner.mjs +53 -0
  285. package/scripts/skill-exporter.js +262 -0
  286. package/scripts/skill-generator.js +446 -0
  287. package/scripts/skill-materializer.js +134 -0
  288. package/scripts/skill-packs.js +136 -0
  289. package/scripts/skill-proposer.js +99 -0
  290. package/scripts/skill-quality-tracker.js +284 -0
  291. package/scripts/slo-alert-engine.js +14 -0
  292. package/scripts/slow-loop.js +72 -0
  293. package/scripts/social-analytics/db/schema.sql +32 -0
  294. package/scripts/social-analytics/digest.js +256 -0
  295. package/scripts/social-analytics/generate-instagram-card.js +97 -0
  296. package/scripts/social-analytics/instagram-thumbgate-post.js +73 -0
  297. package/scripts/social-analytics/mcp-server.js +289 -0
  298. package/scripts/social-analytics/normalizer.js +580 -0
  299. package/scripts/social-analytics/notify.js +162 -0
  300. package/scripts/social-analytics/poll-all.js +107 -0
  301. package/scripts/social-analytics/pollers/github.js +195 -0
  302. package/scripts/social-analytics/pollers/instagram.js +253 -0
  303. package/scripts/social-analytics/pollers/linkedin.js +330 -0
  304. package/scripts/social-analytics/pollers/plausible.js +247 -0
  305. package/scripts/social-analytics/pollers/reddit.js +306 -0
  306. package/scripts/social-analytics/pollers/threads.js +233 -0
  307. package/scripts/social-analytics/pollers/tiktok.js +203 -0
  308. package/scripts/social-analytics/pollers/x.js +227 -0
  309. package/scripts/social-analytics/pollers/youtube.js +304 -0
  310. package/scripts/social-analytics/pollers/zernio.js +180 -0
  311. package/scripts/social-analytics/publish-instagram-thumbgate.js +85 -0
  312. package/scripts/social-analytics/publishers/devto.js +122 -0
  313. package/scripts/social-analytics/publishers/instagram.js +317 -0
  314. package/scripts/social-analytics/publishers/linkedin.js +294 -0
  315. package/scripts/social-analytics/publishers/reddit.js +390 -0
  316. package/scripts/social-analytics/publishers/threads.js +275 -0
  317. package/scripts/social-analytics/publishers/tiktok.js +217 -0
  318. package/scripts/social-analytics/publishers/x.js +259 -0
  319. package/scripts/social-analytics/publishers/youtube.js +223 -0
  320. package/scripts/social-analytics/publishers/zernio.js +209 -0
  321. package/scripts/social-analytics/run-digest.js +34 -0
  322. package/scripts/social-analytics/store.js +257 -0
  323. package/scripts/social-analytics/utm.js +143 -0
  324. package/scripts/social-pipeline.js +2628 -0
  325. package/scripts/social-quality-gate.js +18 -0
  326. package/scripts/social-reply-monitor.js +445 -0
  327. package/scripts/status-dashboard.js +155 -0
  328. package/scripts/statusline-lesson.js +16 -0
  329. package/scripts/statusline-tower.js +8 -0
  330. package/scripts/statusline.sh +116 -0
  331. package/scripts/stripe-live-status.js +115 -0
  332. package/scripts/subagent-profiles.js +79 -0
  333. package/scripts/sync-gh-secrets-from-env.sh +70 -0
  334. package/scripts/sync-github-about.js +52 -0
  335. package/scripts/sync-version.js +451 -0
  336. package/scripts/synthetic-dpo.js +234 -0
  337. package/scripts/telemetry-analytics.js +821 -0
  338. package/scripts/tessl-export.js +371 -0
  339. package/scripts/test-coverage.js +120 -0
  340. package/scripts/thompson-sampling.js +417 -0
  341. package/scripts/thumbgate-search.js +189 -0
  342. package/scripts/tool-kpi-tracker.js +12 -0
  343. package/scripts/tool-registry.js +811 -0
  344. package/scripts/train_from_feedback.py +910 -0
  345. package/scripts/user-profile.js +78 -0
  346. package/scripts/validate-feedback.js +580 -0
  347. package/scripts/validate-workflow-contract.js +287 -0
  348. package/scripts/vector-store.js +198 -0
  349. package/scripts/verification-loop.js +291 -0
  350. package/scripts/verify-obsidian-setup.sh +269 -0
  351. package/scripts/verify-run.js +269 -0
  352. package/scripts/webhook-delivery.js +62 -0
  353. package/scripts/weekly-auto-post.js +124 -0
  354. package/scripts/workflow-runs.js +154 -0
  355. package/scripts/workflow-sprint-intake.js +475 -0
  356. package/scripts/workspace-evolver.js +374 -0
  357. package/scripts/x-autonomous-marketing.js +139 -0
  358. package/scripts/xmemory-lite.js +405 -0
  359. package/skills/agent-memory/SKILL.md +97 -0
  360. package/skills/solve-architecture-autonomy/SKILL.md +17 -0
  361. package/skills/solve-architecture-autonomy/tool.js +33 -0
  362. package/skills/thumbgate/SKILL.md +114 -0
  363. package/skills/thumbgate-feedback/SKILL.md +49 -0
  364. package/src/api/server.js +4208 -0
@@ -0,0 +1,395 @@
1
+ 'use strict';
2
+
3
+ const ALLOWED_COMPONENT_TYPES = Object.freeze([
4
+ 'hero',
5
+ 'stat_grid',
6
+ 'list',
7
+ 'callout',
8
+ ]);
9
+
10
+ const DASHBOARD_VIEWS = Object.freeze({
11
+ TEAM_REVIEW: 'team-review',
12
+ INCIDENT_REVIEW: 'incident-review',
13
+ WORKFLOW_ROLLOUT: 'workflow-rollout',
14
+ });
15
+
16
+ const VIEW_ORDER = Object.freeze([
17
+ DASHBOARD_VIEWS.TEAM_REVIEW,
18
+ DASHBOARD_VIEWS.INCIDENT_REVIEW,
19
+ DASHBOARD_VIEWS.WORKFLOW_ROLLOUT,
20
+ ]);
21
+
22
+ function formatUsdCents(value) {
23
+ const cents = Number(value) || 0;
24
+ return `$${(cents / 100).toFixed(2)}`;
25
+ }
26
+
27
+ function formatPercent(value) {
28
+ if (!Number.isFinite(Number(value))) return '0%';
29
+ return `${Number(value)}%`;
30
+ }
31
+
32
+ function formatCount(value) {
33
+ if (!Number.isFinite(Number(value))) return '0';
34
+ return String(Number(value));
35
+ }
36
+
37
+ function topMapEntries(map, limit) {
38
+ return Object.entries(map || {})
39
+ .map(([key, value]) => ({ key, value: Number(value) || 0 }))
40
+ .sort((left, right) => right.value - left.value)
41
+ .slice(0, limit);
42
+ }
43
+
44
+ function normalizeView(view) {
45
+ if (!view) return DASHBOARD_VIEWS.TEAM_REVIEW;
46
+ if (VIEW_ORDER.includes(view)) return view;
47
+ throw new Error(`Unsupported dashboard render view: ${view}`);
48
+ }
49
+
50
+ function buildHero(title, description) {
51
+ return {
52
+ type: 'hero',
53
+ title,
54
+ description,
55
+ };
56
+ }
57
+
58
+ function buildStatGrid(title, items, columns = 4) {
59
+ return {
60
+ type: 'stat_grid',
61
+ title,
62
+ columns,
63
+ items,
64
+ };
65
+ }
66
+
67
+ function buildList(title, items, emptyMessage) {
68
+ return {
69
+ type: 'list',
70
+ title,
71
+ items,
72
+ emptyMessage,
73
+ };
74
+ }
75
+
76
+ function buildCallout(tone, title, body) {
77
+ return {
78
+ type: 'callout',
79
+ tone,
80
+ title,
81
+ body,
82
+ };
83
+ }
84
+
85
+ function summarizeAnomalyTone(anomalySummary) {
86
+ const severity = String(anomalySummary && anomalySummary.severity || '').toLowerCase();
87
+ if (severity === 'critical' || severity === 'error') return 'danger';
88
+ if (severity === 'warning') return 'warning';
89
+ return 'success';
90
+ }
91
+
92
+ function buildTeamReviewSpec(data) {
93
+ const team = data.team || {};
94
+ const predictive = data.predictive || {};
95
+ const analytics = data.analytics || {};
96
+ const pro = predictive.upgradePropensity ? predictive.upgradePropensity.pro || {} : {};
97
+ const teamPropensity = predictive.upgradePropensity ? predictive.upgradePropensity.team || {} : {};
98
+ const anomalies = Array.isArray(predictive.anomalies) ? predictive.anomalies : [];
99
+ const topRiskAgents = Array.isArray(team.riskAgents) ? team.riskAgents.slice(0, 5) : [];
100
+ const topBlockedGates = Array.isArray(team.topBlockedGates) ? team.topBlockedGates.slice(0, 5) : [];
101
+ const watchlistItems = anomalies.slice(0, 5).map((anomaly) => ({
102
+ title: anomaly.type || 'predictive_alert',
103
+ subtitle: anomaly.message || 'No message available.',
104
+ badge: anomaly.severity || 'info',
105
+ tone: summarizeAnomalyTone({ severity: anomaly.severity }),
106
+ }));
107
+
108
+ return [
109
+ buildHero(
110
+ 'Generated Team Reliability Review',
111
+ 'A constrained hosted view assembled from approved dashboard components. Use it to brief operators on agent drift, gate pressure, and upgrade/conversion risk without hand-building a custom page.'
112
+ ),
113
+ buildStatGrid('Team snapshot', [
114
+ {
115
+ label: 'Active agents',
116
+ value: formatCount(team.activeAgents),
117
+ note: `of ${formatCount(team.totalAgents)} registered agents`,
118
+ tone: 'info',
119
+ },
120
+ {
121
+ label: 'Org adherence',
122
+ value: formatPercent(team.orgAdherenceRate),
123
+ note: `rolling ${formatCount(team.windowHours || 24)}h view`,
124
+ tone: 'success',
125
+ },
126
+ {
127
+ label: 'Team propensity',
128
+ value: teamPropensity.band || 'very_low',
129
+ note: `score ${teamPropensity.score || 0}`,
130
+ tone: 'info',
131
+ },
132
+ {
133
+ label: 'Forecast revenue',
134
+ value: formatUsdCents(predictive.revenueForecast && predictive.revenueForecast.predictedBookedRevenueCents),
135
+ note: `opportunity ${formatUsdCents(predictive.revenueForecast && predictive.revenueForecast.incrementalOpportunityCents)}`,
136
+ tone: 'info',
137
+ },
138
+ ]),
139
+ buildList(
140
+ 'Highest-risk agents',
141
+ topRiskAgents.map((agent) => ({
142
+ title: agent.id || 'agent',
143
+ subtitle: `${agent.project || 'unknown project'}${agent.branch ? ` · ${agent.branch}` : ''}`,
144
+ badge: `${formatPercent(agent.adherenceRate)} adherence`,
145
+ tone: 'warning',
146
+ })),
147
+ 'No risky agents detected in this window.'
148
+ ),
149
+ buildList(
150
+ 'Top blocked gates',
151
+ topBlockedGates.map((gate) => ({
152
+ title: gate.gateId || 'gate',
153
+ subtitle: `${formatCount(gate.warned)} warns`,
154
+ badge: `${formatCount(gate.blocked)} blocks`,
155
+ tone: 'warning',
156
+ })),
157
+ 'No blocked gates recorded yet.'
158
+ ),
159
+ buildList(
160
+ 'Predictive watchlist',
161
+ watchlistItems,
162
+ 'No predictive anomalies detected. Team reliability is stable.'
163
+ ),
164
+ buildCallout(
165
+ pro.band === 'high' || teamPropensity.band === 'high' ? 'warning' : 'success',
166
+ 'Commercial signal',
167
+ `Pro propensity is ${pro.band || 'very_low'} and Team propensity is ${teamPropensity.band || 'very_low'}. Workflow sprint leads currently total ${formatCount(analytics.pipeline && analytics.pipeline.workflowSprintLeads && analytics.pipeline.workflowSprintLeads.total)}.`
168
+ ),
169
+ ];
170
+ }
171
+
172
+ function buildIncidentReviewSpec(data) {
173
+ const gateStats = data.gateStats || {};
174
+ const diagnostics = data.diagnostics || {};
175
+ const liveMetrics = data.liveMetrics || {};
176
+ const predictive = data.predictive || {};
177
+ const gates = Array.isArray(data.gates) ? data.gates.slice(0, 6) : [];
178
+ const diagnosticCategories = Array.isArray(diagnostics.categories) ? diagnostics.categories.slice(0, 5) : [];
179
+ const anomalies = Array.isArray(predictive.anomalies) ? predictive.anomalies.slice(0, 5) : [];
180
+ const recommendations = [];
181
+
182
+ if (gateStats.topBlocked) {
183
+ recommendations.push({
184
+ title: `Audit ${gateStats.topBlocked}`,
185
+ subtitle: 'Confirm the pattern and severity still match the failure mode causing the most blocks.',
186
+ badge: `${formatCount(gateStats.topBlockedCount)} blocks`,
187
+ tone: 'warning',
188
+ });
189
+ }
190
+ if (diagnosticCategories[0]) {
191
+ recommendations.push({
192
+ title: `Investigate ${diagnosticCategories[0].key}`,
193
+ subtitle: 'Use the failure diagnostic log to trace the most common root cause before widening any gate.',
194
+ badge: `${formatCount(diagnosticCategories[0].count)} diagnoses`,
195
+ tone: 'warning',
196
+ });
197
+ }
198
+ if (anomalies[0]) {
199
+ recommendations.push({
200
+ title: `Resolve ${anomalies[0].type || 'predictive_alert'}`,
201
+ subtitle: anomalies[0].message || 'Review the predictive watchlist for the next mitigation.',
202
+ badge: anomalies[0].severity || 'info',
203
+ tone: summarizeAnomalyTone({ severity: anomalies[0].severity }),
204
+ });
205
+ }
206
+
207
+ return [
208
+ buildHero(
209
+ 'Generated Incident Review',
210
+ 'A constrained post-mortem view for the current reliability posture. It prioritizes blocked gates, root causes, and recommended next actions without exposing arbitrary HTML or model-generated code.'
211
+ ),
212
+ buildStatGrid('Incident snapshot', [
213
+ {
214
+ label: 'Active gates',
215
+ value: formatCount(gates.length || gateStats.totalGates),
216
+ note: `${formatCount(gateStats.manualCount)} manual / ${formatCount(gateStats.autoCount)} auto-promoted`,
217
+ tone: 'info',
218
+ },
219
+ {
220
+ label: 'Blocks per day',
221
+ value: String(liveMetrics.gateHitRate && liveMetrics.gateHitRate.blockedPerDay || 0),
222
+ note: `warns/day ${String(liveMetrics.gateHitRate && liveMetrics.gateHitRate.warnedPerDay || 0)}`,
223
+ tone: 'warning',
224
+ },
225
+ {
226
+ label: 'Predictive alerts',
227
+ value: formatCount(predictive.anomalySummary && predictive.anomalySummary.count),
228
+ note: predictive.anomalySummary && predictive.anomalySummary.severity || 'healthy',
229
+ tone: summarizeAnomalyTone(predictive.anomalySummary || {}),
230
+ },
231
+ {
232
+ label: 'Buyer loss signals',
233
+ value: formatCount(data.analytics && data.analytics.buyerLoss && data.analytics.buyerLoss.totalSignals),
234
+ note: 'reasons captured in telemetry',
235
+ tone: 'warning',
236
+ },
237
+ ]),
238
+ buildList(
239
+ 'Active gate pressure',
240
+ gates.map((gate) => ({
241
+ title: gate.name || gate.id || 'gate',
242
+ subtitle: gate.pattern || '',
243
+ badge: String(gate.action || 'block').toUpperCase(),
244
+ tone: gate.action === 'warn' ? 'info' : 'warning',
245
+ })),
246
+ 'No active gates configured.'
247
+ ),
248
+ buildList(
249
+ 'Root cause clusters',
250
+ diagnosticCategories.map((category) => ({
251
+ title: category.key || 'root_cause',
252
+ subtitle: category.examples && category.examples[0] ? category.examples[0] : 'No example captured.',
253
+ badge: `${formatCount(category.count)} cases`,
254
+ tone: 'warning',
255
+ })),
256
+ 'No diagnostic clusters recorded yet.'
257
+ ),
258
+ buildList(
259
+ 'Recommended next actions',
260
+ recommendations,
261
+ 'No active incidents detected. Current reliability posture is healthy.'
262
+ ),
263
+ ];
264
+ }
265
+
266
+ function buildWorkflowRolloutSpec(data) {
267
+ const analytics = data.analytics || {};
268
+ const predictive = data.predictive || {};
269
+ const topSources = topMapEntries(analytics.attribution && analytics.attribution.acquisitionBySource, 5);
270
+ const topCreators = Array.isArray(predictive.topCreators) ? predictive.topCreators.slice(0, 5) : [];
271
+ const topChannels = Array.isArray(predictive.topSources) ? predictive.topSources.slice(0, 5) : [];
272
+ const pipeline = analytics.pipeline || {};
273
+ const revenue = analytics.revenue || {};
274
+ const rolloutMoves = [];
275
+
276
+ if (topCreators[0]) {
277
+ rolloutMoves.push({
278
+ title: `Double down on ${topCreators[0].key}`,
279
+ subtitle: 'Best creator opportunity based on predicted incremental revenue.',
280
+ badge: formatUsdCents(topCreators[0].opportunityRevenueCents),
281
+ tone: 'success',
282
+ });
283
+ }
284
+ if (topChannels[0]) {
285
+ rolloutMoves.push({
286
+ title: `Expand ${topChannels[0].key}`,
287
+ subtitle: 'Top channel opportunity from the predictive layer.',
288
+ badge: formatUsdCents(topChannels[0].opportunityRevenueCents),
289
+ tone: 'success',
290
+ });
291
+ }
292
+ if ((pipeline.workflowSprintLeads && pipeline.workflowSprintLeads.total) > (pipeline.qualifiedWorkflowSprintLeads && pipeline.qualifiedWorkflowSprintLeads.total)) {
293
+ rolloutMoves.push({
294
+ title: 'Qualify pending workflow sprint leads',
295
+ subtitle: 'There is lead volume waiting to move into proof-backed rollout.',
296
+ badge: `${formatCount(pipeline.workflowSprintLeads.total)} total`,
297
+ tone: 'warning',
298
+ });
299
+ }
300
+
301
+ return [
302
+ buildHero(
303
+ 'Generated Workflow Rollout View',
304
+ 'A constrained GTM and team-rollout dashboard. It turns analytics and predictive data into an operator-safe view for qualification, creator prioritization, and proof-backed expansion.'
305
+ ),
306
+ buildStatGrid('Rollout pipeline', [
307
+ {
308
+ label: 'Workflow sprint leads',
309
+ value: formatCount(pipeline.workflowSprintLeads && pipeline.workflowSprintLeads.total),
310
+ note: 'intake-first hosted team funnel',
311
+ tone: 'info',
312
+ },
313
+ {
314
+ label: 'Qualified leads',
315
+ value: formatCount(pipeline.qualifiedWorkflowSprintLeads && pipeline.qualifiedWorkflowSprintLeads.total),
316
+ note: 'ready for proof-backed rollout',
317
+ tone: 'success',
318
+ },
319
+ {
320
+ label: 'Booked revenue',
321
+ value: formatUsdCents(revenue.bookedRevenueCents),
322
+ note: `${formatCount(revenue.paidOrders)} paid orders`,
323
+ tone: 'success',
324
+ },
325
+ {
326
+ label: 'Team propensity',
327
+ value: predictive.upgradePropensity && predictive.upgradePropensity.team ? predictive.upgradePropensity.team.band : 'very_low',
328
+ note: `score ${predictive.upgradePropensity && predictive.upgradePropensity.team ? predictive.upgradePropensity.team.score : 0}`,
329
+ tone: 'info',
330
+ },
331
+ ]),
332
+ buildList(
333
+ 'Top acquisition sources',
334
+ topSources.map((entry) => ({
335
+ title: entry.key || 'source',
336
+ subtitle: 'captured acquisition source',
337
+ badge: `${formatCount(entry.value)} leads`,
338
+ tone: 'info',
339
+ })),
340
+ 'No attributed acquisition sources yet.'
341
+ ),
342
+ buildList(
343
+ 'Creator revenue opportunities',
344
+ topCreators.map((entry) => ({
345
+ title: entry.key || 'creator',
346
+ subtitle: 'predicted incremental revenue opportunity',
347
+ badge: formatUsdCents(entry.opportunityRevenueCents),
348
+ tone: 'success',
349
+ })),
350
+ 'No creator opportunities detected yet.'
351
+ ),
352
+ buildList(
353
+ 'Next rollout moves',
354
+ rolloutMoves,
355
+ 'No rollout recommendations yet. Capture more attribution and workflow sprint activity first.'
356
+ ),
357
+ ];
358
+ }
359
+
360
+ function buildDashboardRenderSpec(dashboardData, options = {}) {
361
+ const view = normalizeView(options.view);
362
+ let components;
363
+
364
+ if (view === DASHBOARD_VIEWS.TEAM_REVIEW) {
365
+ components = buildTeamReviewSpec(dashboardData);
366
+ } else if (view === DASHBOARD_VIEWS.INCIDENT_REVIEW) {
367
+ components = buildIncidentReviewSpec(dashboardData);
368
+ } else {
369
+ components = buildWorkflowRolloutSpec(dashboardData);
370
+ }
371
+
372
+ return {
373
+ version: '1.0.0',
374
+ catalog: 'thumbgate-dashboard-render-spec',
375
+ generatedAt: new Date(options.now || Date.now()).toISOString(),
376
+ view,
377
+ availableViews: VIEW_ORDER.map((value) => ({
378
+ id: value,
379
+ label: value === DASHBOARD_VIEWS.TEAM_REVIEW
380
+ ? 'Team review'
381
+ : value === DASHBOARD_VIEWS.INCIDENT_REVIEW
382
+ ? 'Incident review'
383
+ : 'Workflow rollout',
384
+ })),
385
+ allowedComponentTypes: [...ALLOWED_COMPONENT_TYPES],
386
+ components,
387
+ };
388
+ }
389
+
390
+ module.exports = {
391
+ ALLOWED_COMPONENT_TYPES,
392
+ DASHBOARD_VIEWS,
393
+ buildDashboardRenderSpec,
394
+ normalizeView,
395
+ };