thumbgate 1.4.2 → 1.4.4

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 (279) hide show
  1. package/.claude-plugin/README.md +45 -34
  2. package/.claude-plugin/marketplace.json +3 -3
  3. package/.claude-plugin/plugin.json +3 -3
  4. package/.well-known/llms.txt +1 -1
  5. package/.well-known/mcp/server-card.json +1 -1
  6. package/README.md +26 -2
  7. package/adapters/README.md +4 -1
  8. package/adapters/claude/.mcp.json +2 -2
  9. package/adapters/codex/config.toml +2 -2
  10. package/adapters/mcp/server-stdio.js +10 -4
  11. package/adapters/opencode/opencode.json +1 -1
  12. package/bin/cli.js +246 -90
  13. package/config/mcp-allowlists.json +11 -3
  14. package/package.json +184 -21
  15. package/scripts/audit-trail.js +25 -15
  16. package/scripts/auto-wire-hooks.js +127 -0
  17. package/scripts/cli-demo.js +102 -0
  18. package/scripts/cli-schema.js +285 -0
  19. package/scripts/cli-status.js +166 -0
  20. package/scripts/cross-encoder-reranker.js +235 -0
  21. package/scripts/explore-subcommands.js +277 -0
  22. package/scripts/explore.js +569 -0
  23. package/scripts/feedback-loop.js +20 -6
  24. package/scripts/lesson-inference.js +7 -1
  25. package/scripts/lesson-reranker.js +263 -0
  26. package/scripts/lesson-retrieval.js +34 -17
  27. package/scripts/lesson-search.js +69 -0
  28. package/scripts/perplexity-client.js +210 -0
  29. package/scripts/reflector-agent.js +2 -2
  30. package/scripts/statusline-local-stats.js +3 -1
  31. package/scripts/statusline.sh +12 -11
  32. package/src/api/server.js +178 -17
  33. package/src/index.js +3 -0
  34. package/.claude-plugin/bundle/icon.png +0 -0
  35. package/.claude-plugin/bundle/icon.svg +0 -18
  36. package/.claude-plugin/bundle/server/index.js +0 -24
  37. package/adapters/chatgpt/INSTALL.md +0 -138
  38. package/bin/memory.sh +0 -64
  39. package/bin/obsidian-sync.sh +0 -20
  40. package/plugins/amp-skill/INSTALL.md +0 -52
  41. package/plugins/amp-skill/SKILL.md +0 -64
  42. package/plugins/claude-codex-bridge/.claude-plugin/plugin.json +0 -22
  43. package/plugins/claude-codex-bridge/.mcp.json +0 -14
  44. package/plugins/claude-codex-bridge/INSTALL.md +0 -43
  45. package/plugins/claude-codex-bridge/README.md +0 -46
  46. package/plugins/claude-codex-bridge/scripts/codex-bridge.js +0 -286
  47. package/plugins/claude-codex-bridge/skills/adversarial-review/SKILL.md +0 -24
  48. package/plugins/claude-codex-bridge/skills/result/SKILL.md +0 -22
  49. package/plugins/claude-codex-bridge/skills/review/SKILL.md +0 -28
  50. package/plugins/claude-codex-bridge/skills/second-pass/SKILL.md +0 -27
  51. package/plugins/claude-codex-bridge/skills/setup/SKILL.md +0 -21
  52. package/plugins/claude-codex-bridge/skills/status/SKILL.md +0 -19
  53. package/plugins/claude-skill/INSTALL.md +0 -55
  54. package/plugins/claude-skill/SKILL.md +0 -46
  55. package/plugins/codex-profile/.codex-plugin/plugin.json +0 -43
  56. package/plugins/codex-profile/.mcp.json +0 -14
  57. package/plugins/codex-profile/AGENTS.md +0 -20
  58. package/plugins/codex-profile/INSTALL.md +0 -89
  59. package/plugins/codex-profile/README.md +0 -61
  60. package/plugins/cursor-marketplace/.cursor-plugin/plugin.json +0 -23
  61. package/plugins/cursor-marketplace/CHANGELOG.md +0 -30
  62. package/plugins/cursor-marketplace/LICENSE +0 -21
  63. package/plugins/cursor-marketplace/README.md +0 -124
  64. package/plugins/cursor-marketplace/agents/reliability-reviewer.md +0 -31
  65. package/plugins/cursor-marketplace/assets/logo-400x400.png +0 -0
  66. package/plugins/cursor-marketplace/commands/capture-feedback.md +0 -33
  67. package/plugins/cursor-marketplace/commands/check-gates.md +0 -25
  68. package/plugins/cursor-marketplace/commands/show-lessons.md +0 -27
  69. package/plugins/cursor-marketplace/hooks/hooks.json +0 -10
  70. package/plugins/cursor-marketplace/mcp.json +0 -14
  71. package/plugins/cursor-marketplace/rules/feedback-capture.mdc +0 -34
  72. package/plugins/cursor-marketplace/rules/pre-action-gates.mdc +0 -30
  73. package/plugins/cursor-marketplace/rules/session-continuity.mdc +0 -28
  74. package/plugins/cursor-marketplace/scripts/gate-check.sh +0 -21
  75. package/plugins/cursor-marketplace/skills/capture-feedback/SKILL.md +0 -48
  76. package/plugins/cursor-marketplace/skills/prevention-rules/SKILL.md +0 -31
  77. package/plugins/cursor-marketplace/skills/recall-context/SKILL.md +0 -30
  78. package/plugins/cursor-marketplace/skills/search-lessons/SKILL.md +0 -33
  79. package/plugins/gemini-extension/INSTALL.md +0 -92
  80. package/plugins/gemini-extension/gemini_prompt.txt +0 -14
  81. package/plugins/gemini-extension/tool_contract.json +0 -45
  82. package/plugins/opencode-profile/INSTALL.md +0 -57
  83. package/public/assets/instagram-card.png +0 -0
  84. package/public/assets/tiktok-agent-memory.mp4 +0 -0
  85. package/public/blog.html +0 -474
  86. package/public/compare/mem0.html +0 -189
  87. package/public/compare/speclock.html +0 -180
  88. package/public/compare.html +0 -310
  89. package/public/dashboard.html +0 -1100
  90. package/public/guide.html +0 -317
  91. package/public/guides/claude-code-prevent-repeated-mistakes.html +0 -161
  92. package/public/guides/codex-cli-guardrails.html +0 -158
  93. package/public/guides/cursor-prevent-repeated-mistakes.html +0 -161
  94. package/public/guides/pre-action-gates.html +0 -162
  95. package/public/guides/stop-repeated-ai-agent-mistakes.html +0 -159
  96. package/public/index.html +0 -1128
  97. package/public/js/buyer-intent.js +0 -252
  98. package/public/learn/agent-harness-pattern.html +0 -180
  99. package/public/learn/ai-agent-persistent-memory.html +0 -203
  100. package/public/learn/learn.css +0 -45
  101. package/public/learn/mcp-pre-action-gates-explained.html +0 -172
  102. package/public/learn/stop-ai-agent-force-push.html +0 -134
  103. package/public/learn/vibe-coding-safety-net.html +0 -142
  104. package/public/learn.html +0 -274
  105. package/public/lessons.html +0 -967
  106. package/public/llm-context.md +0 -140
  107. package/public/pro.html +0 -1087
  108. package/public/vercel.json +0 -8
  109. package/scripts/a2ui-engine.js +0 -73
  110. package/scripts/adk-consolidator.js +0 -274
  111. package/scripts/agent-security-hardening.js +0 -225
  112. package/scripts/ai-search-visibility.js +0 -142
  113. package/scripts/autonomous-sales-agent.js +0 -39
  114. package/scripts/autoresearch-runner.js +0 -216
  115. package/scripts/background-agent-governance.js +0 -229
  116. package/scripts/behavioral-extraction.js +0 -93
  117. package/scripts/budget-enforcer.js +0 -173
  118. package/scripts/budget-guard.js +0 -173
  119. package/scripts/build-claude-mcpb.js +0 -255
  120. package/scripts/build-codex-plugin.js +0 -152
  121. package/scripts/capture-railway-diagnostics.sh +0 -97
  122. package/scripts/changeset-check.js +0 -372
  123. package/scripts/check-congruence.js +0 -443
  124. package/scripts/computer-use-firewall.js +0 -280
  125. package/scripts/content-engine/linkedin-content-generator.js +0 -154
  126. package/scripts/content-engine/output/linkedin-memento-validation.md +0 -17
  127. package/scripts/content-engine/output/linkedin-posts-2026-04-09.md +0 -175
  128. package/scripts/content-engine/reddit-thread-finder.js +0 -154
  129. package/scripts/context-engine.js +0 -710
  130. package/scripts/daily-digest.js +0 -11
  131. package/scripts/data-governance.js +0 -173
  132. package/scripts/deploy-gcp.sh +0 -44
  133. package/scripts/deploy-policy.js +0 -249
  134. package/scripts/disagreement-mining.js +0 -315
  135. package/scripts/dpo-optimizer.js +0 -206
  136. package/scripts/ensure-repo-bootstrap.js +0 -130
  137. package/scripts/ephemeral-agent-store.js +0 -212
  138. package/scripts/eval-harness.js +0 -56
  139. package/scripts/export-kto-pairs.js +0 -309
  140. package/scripts/export-training.js +0 -446
  141. package/scripts/feedback-fallback.js +0 -111
  142. package/scripts/feedback-inbox-read.js +0 -162
  143. package/scripts/feedback-root-consolidator.js +0 -233
  144. package/scripts/feedback-to-memory.js +0 -185
  145. package/scripts/gate-satisfy.js +0 -42
  146. package/scripts/generate-paperbanana-diagrams.sh +0 -99
  147. package/scripts/generate-pretool-hook.sh +0 -40
  148. package/scripts/github-about.js +0 -430
  149. package/scripts/github-outreach.js +0 -65
  150. package/scripts/gtm-revenue-loop.js +0 -535
  151. package/scripts/hallucination-detector.js +0 -226
  152. package/scripts/hf-papers.js +0 -317
  153. package/scripts/hook-auto-capture.sh +0 -100
  154. package/scripts/hook-stop-pr-thread-check.sh +0 -68
  155. package/scripts/hook-stop-self-score.sh +0 -51
  156. package/scripts/hook-stop-verify-deploy.sh +0 -31
  157. package/scripts/hook-verify-before-done.sh +0 -20
  158. package/scripts/managed-dpo-export.js +0 -91
  159. package/scripts/markdown-escape.js +0 -12
  160. package/scripts/marketing-experiment.js +0 -657
  161. package/scripts/memalign-recall.js +0 -111
  162. package/scripts/memory-migration.js +0 -296
  163. package/scripts/meta-policy.js +0 -190
  164. package/scripts/metered-billing.js +0 -16
  165. package/scripts/model-tier-router.js +0 -310
  166. package/scripts/money-watcher.js +0 -218
  167. package/scripts/multi-hop-recall.js +0 -240
  168. package/scripts/per-step-scoring.js +0 -163
  169. package/scripts/perplexity-marketing.js +0 -466
  170. package/scripts/pii-scanner.js +0 -153
  171. package/scripts/plan-gate.js +0 -154
  172. package/scripts/post-everywhere.js +0 -341
  173. package/scripts/post-to-x-retry.sh +0 -22
  174. package/scripts/post-to-x.js +0 -369
  175. package/scripts/pr-manager.js +0 -421
  176. package/scripts/principle-extractor.js +0 -162
  177. package/scripts/pro-features.js +0 -41
  178. package/scripts/prompt-dlp.js +0 -222
  179. package/scripts/prove-adapters.js +0 -860
  180. package/scripts/prove-attribution.js +0 -361
  181. package/scripts/prove-automation.js +0 -651
  182. package/scripts/prove-autoresearch.js +0 -304
  183. package/scripts/prove-claim-verification.js +0 -277
  184. package/scripts/prove-cloudflare-sandbox.js +0 -161
  185. package/scripts/prove-data-pipeline.js +0 -408
  186. package/scripts/prove-data-quality.js +0 -227
  187. package/scripts/prove-evolution.js +0 -352
  188. package/scripts/prove-harnesses.js +0 -287
  189. package/scripts/prove-intelligence.js +0 -257
  190. package/scripts/prove-lancedb.js +0 -425
  191. package/scripts/prove-local-intelligence.js +0 -340
  192. package/scripts/prove-loop-closure.js +0 -263
  193. package/scripts/prove-packaged-runtime.js +0 -326
  194. package/scripts/prove-predictive-insights.js +0 -355
  195. package/scripts/prove-runtime.js +0 -363
  196. package/scripts/prove-seo-gsd.js +0 -234
  197. package/scripts/prove-settings.js +0 -279
  198. package/scripts/prove-subway-upgrades.js +0 -277
  199. package/scripts/prove-tessl.js +0 -229
  200. package/scripts/prove-training-export.js +0 -325
  201. package/scripts/prove-workflow-contract.js +0 -112
  202. package/scripts/prove-xmemory.js +0 -332
  203. package/scripts/publish-decision.js +0 -159
  204. package/scripts/ralph-loop.js +0 -376
  205. package/scripts/ralph-mode-ci.js +0 -331
  206. package/scripts/reddit-dm-outreach.js +0 -192
  207. package/scripts/reddit-monitor-cron.sh +0 -26
  208. package/scripts/reminder-engine.js +0 -132
  209. package/scripts/revenue-status.js +0 -472
  210. package/scripts/rotate-stripe-webhook-secret.js +0 -314
  211. package/scripts/schedule-manager.js +0 -249
  212. package/scripts/self-healing-check.js +0 -193
  213. package/scripts/shieldcortex-memory-firewall-runner.mjs +0 -53
  214. package/scripts/skill-exporter.js +0 -260
  215. package/scripts/skill-materializer.js +0 -134
  216. package/scripts/skill-packs.js +0 -136
  217. package/scripts/skill-proposer.js +0 -99
  218. package/scripts/skill-quality-tracker.js +0 -282
  219. package/scripts/slow-loop.js +0 -72
  220. package/scripts/social-analytics/db/analytics.sqlite +0 -0
  221. package/scripts/social-analytics/db/schema.sql +0 -32
  222. package/scripts/social-analytics/digest.js +0 -256
  223. package/scripts/social-analytics/engagement-audit.js +0 -185
  224. package/scripts/social-analytics/generate-instagram-card.js +0 -97
  225. package/scripts/social-analytics/instagram-thumbgate-post.js +0 -111
  226. package/scripts/social-analytics/install-growth-automation.js +0 -114
  227. package/scripts/social-analytics/load-env.js +0 -77
  228. package/scripts/social-analytics/mcp-server.js +0 -289
  229. package/scripts/social-analytics/normalizer.js +0 -580
  230. package/scripts/social-analytics/notify.js +0 -162
  231. package/scripts/social-analytics/poll-all.js +0 -107
  232. package/scripts/social-analytics/pollers/github.js +0 -195
  233. package/scripts/social-analytics/pollers/instagram.js +0 -253
  234. package/scripts/social-analytics/pollers/linkedin.js +0 -340
  235. package/scripts/social-analytics/pollers/plausible.js +0 -245
  236. package/scripts/social-analytics/pollers/reddit.js +0 -306
  237. package/scripts/social-analytics/pollers/threads.js +0 -233
  238. package/scripts/social-analytics/pollers/tiktok.js +0 -203
  239. package/scripts/social-analytics/pollers/x.js +0 -227
  240. package/scripts/social-analytics/pollers/youtube.js +0 -304
  241. package/scripts/social-analytics/pollers/zernio.js +0 -183
  242. package/scripts/social-analytics/publish-instagram-thumbgate.js +0 -104
  243. package/scripts/social-analytics/publish-thumbgate-launch.js +0 -322
  244. package/scripts/social-analytics/publishers/devto.js +0 -122
  245. package/scripts/social-analytics/publishers/instagram.js +0 -317
  246. package/scripts/social-analytics/publishers/linkedin.js +0 -294
  247. package/scripts/social-analytics/publishers/reddit.js +0 -385
  248. package/scripts/social-analytics/publishers/threads.js +0 -275
  249. package/scripts/social-analytics/publishers/tiktok.js +0 -217
  250. package/scripts/social-analytics/publishers/x.js +0 -259
  251. package/scripts/social-analytics/publishers/youtube.js +0 -223
  252. package/scripts/social-analytics/publishers/zernio.js +0 -539
  253. package/scripts/social-analytics/reconcile-thumbgate-campaign.js +0 -165
  254. package/scripts/social-analytics/run-digest.js +0 -34
  255. package/scripts/social-analytics/schedule-thumbgate-campaign.js +0 -275
  256. package/scripts/social-analytics/store.js +0 -455
  257. package/scripts/social-analytics/sync-launch-assets.js +0 -185
  258. package/scripts/social-analytics/utm.js +0 -143
  259. package/scripts/social-pipeline.js +0 -2626
  260. package/scripts/social-post-hourly.js +0 -228
  261. package/scripts/social-quality-gate.js +0 -134
  262. package/scripts/social-reply-monitor.js +0 -592
  263. package/scripts/status-dashboard.js +0 -155
  264. package/scripts/stripe-live-status.js +0 -115
  265. package/scripts/subagent-profiles.js +0 -79
  266. package/scripts/sync-branch-protection.js +0 -340
  267. package/scripts/sync-gh-secrets-from-env.sh +0 -70
  268. package/scripts/sync-github-about.js +0 -55
  269. package/scripts/sync-version.js +0 -479
  270. package/scripts/synthetic-dpo.js +0 -234
  271. package/scripts/tessl-export.js +0 -369
  272. package/scripts/test-coverage.js +0 -128
  273. package/scripts/thumbgate_session_start.sh +0 -32
  274. package/scripts/train_from_feedback.py +0 -929
  275. package/scripts/validate-feedback.js +0 -581
  276. package/scripts/verify-obsidian-setup.sh +0 -269
  277. package/scripts/verify-run.js +0 -269
  278. package/scripts/weekly-auto-post.js +0 -124
  279. package/scripts/x-autonomous-marketing.js +0 -139
@@ -146,31 +146,32 @@ case "${TREND}" in
146
146
  improving) ARROW="↗" ;; degrading) ARROW="↘" ;; stable) ARROW="→" ;; *) ARROW="?" ;;
147
147
  esac
148
148
 
149
- inline_link() {
149
+ # OSC 8 hyperlink: \e]8;;URL\a LABEL \e]8;;\a
150
+ # Falls back to plain label when URL is empty or localhost.
151
+ osc_link() {
150
152
  local url="$1"
151
153
  local label="$2"
152
- if [ -n "$url" ]; then
153
- printf '%s (%s)' "$label" "$url"
154
- else
155
- printf '%s' "$label"
156
- fi
154
+ case "$url" in
155
+ *localhost*|*127.0.0.1*|"") printf '%s' "$label" ;;
156
+ *) printf '\033]8;;%s\007%s\033]8;;\007' "$url" "$label" ;;
157
+ esac
158
+ return 0
157
159
  }
158
160
 
159
161
  UP_ICON="👍"
160
162
  DOWN_ICON="👎"
161
- DASHBOARD_LINK="$DASHBOARD_LABEL"
162
- LESSONS_LINK="$LESSONS_LABEL"
163
+ DASHBOARD_LINK="$(osc_link "$DASHBOARD_URL" "$DASHBOARD_LABEL")"
164
+ LESSONS_LINK="$(osc_link "$LESSONS_URL" "$LESSONS_LABEL")"
163
165
  LATEST_LESSON_LINK=""
164
166
  if [ -n "$LESSON_LABEL" ]; then
165
- # Only include link if it's a real URL (not localhost)
166
167
  _DISPLAY_LINK="$LESSON_LINK"
167
168
  case "$_DISPLAY_LINK" in
168
169
  *localhost*|*127.0.0.1*) _DISPLAY_LINK="" ;;
169
170
  esac
170
171
  if [ -n "$LESSON_TEXT" ]; then
171
- LATEST_LESSON_LINK="$(inline_link "$_DISPLAY_LINK" "${LESSON_LABEL}: ${LESSON_TEXT}")"
172
+ LATEST_LESSON_LINK="$(osc_link "$_DISPLAY_LINK" "${LESSON_LABEL}: ${LESSON_TEXT}")"
172
173
  else
173
- LATEST_LESSON_LINK="$(inline_link "$_DISPLAY_LINK" "$LESSON_LABEL")"
174
+ LATEST_LESSON_LINK="$(osc_link "$_DISPLAY_LINK" "$LESSON_LABEL")"
174
175
  fi
175
176
  fi
176
177
 
package/src/api/server.js CHANGED
@@ -5,6 +5,37 @@ const fs = require('fs');
5
5
  const path = require('path');
6
6
  const pkg = require('../../package.json');
7
7
 
8
+ const POSTHOG_API_PATHS = new Set(['/capture', '/batch', '/decide', '/e', '/engage']);
9
+ const POSTHOG_INGEST_HOST = 'us.i.posthog.com';
10
+ const POSTHOG_STATIC_PATH_PREFIX = '/static/';
11
+
12
+ function getPosthogProxyPath(pathname) {
13
+ return pathname.slice('/ingest'.length) || '/';
14
+ }
15
+
16
+ function isExactOrChildPath(pathname, basePath) {
17
+ return pathname === basePath || pathname.startsWith(`${basePath}/`);
18
+ }
19
+
20
+ function isAllowedPosthogProxyPath(pathname) {
21
+ if (pathname === '/') return true;
22
+ if (pathname.startsWith(POSTHOG_STATIC_PATH_PREFIX)) return true;
23
+ return Array.from(POSTHOG_API_PATHS).some((basePath) => isExactOrChildPath(pathname, basePath));
24
+ }
25
+
26
+ function buildPosthogProxyRequestOptions(req, posthogPath, search) {
27
+ return {
28
+ protocol: 'https:',
29
+ hostname: POSTHOG_INGEST_HOST,
30
+ path: `${posthogPath}${search || ''}`,
31
+ method: req.method,
32
+ headers: {
33
+ ...req.headers,
34
+ host: POSTHOG_INGEST_HOST,
35
+ },
36
+ };
37
+ }
38
+
8
39
  const {
9
40
  captureFeedback,
10
41
  analyzeFeedback,
@@ -1032,38 +1063,131 @@ function loadProPageHtml(runtimeConfig, pageContext = {}) {
1032
1063
  return loadPublicMarketingTemplateHtml(PRO_PAGE_PATH, runtimeConfig, pageContext);
1033
1064
  }
1034
1065
 
1035
- function loadDashboardPageHtml(req, expectedApiKey) {
1036
- const template = fs.readFileSync(DASHBOARD_PAGE_PATH, 'utf-8');
1066
+ function readOptionalPublicTemplate(filePath) {
1067
+ try {
1068
+ return fs.readFileSync(filePath, 'utf-8');
1069
+ } catch (error) {
1070
+ if (error?.code === 'ENOENT') return null;
1071
+ throw error;
1072
+ }
1073
+ }
1074
+
1075
+ function resolveLocalPageBootstrap(req, expectedApiKey) {
1037
1076
  const forwardedHost = req.headers['x-forwarded-host'];
1038
1077
  const hostHeader = Array.isArray(forwardedHost)
1039
1078
  ? forwardedHost[0]
1040
1079
  : forwardedHost || req.headers.host || '';
1041
1080
  const localProBootstrap = process.env.THUMBGATE_PRO_MODE === '1' && Boolean(expectedApiKey) && isLoopbackHost(hostHeader);
1042
- // Developer override: auth is disabled (expectedApiKey===null), auto-connect with dummy key
1043
1081
  const devOverride = expectedApiKey === null && isLoopbackHost(hostHeader);
1044
1082
  const bootstrapActive = localProBootstrap || devOverride;
1045
1083
  const serializedBootstrapKey = JSON.stringify(localProBootstrap ? expectedApiKey : devOverride ? 'dev-override' : '').replace(/</g, '\\u003c');
1046
1084
 
1085
+ return {
1086
+ bootstrapActive,
1087
+ serializedBootstrapKey,
1088
+ };
1089
+ }
1090
+
1091
+ function renderPackagedDashboardHtml({ bootstrapActive, serializedBootstrapKey }) {
1092
+ return `<!doctype html>
1093
+ <html lang="en">
1094
+ <head>
1095
+ <meta charset="utf-8">
1096
+ <meta name="viewport" content="width=device-width, initial-scale=1">
1097
+ <title>ThumbGate Dashboard</title>
1098
+ <style>
1099
+ :root { color-scheme: light dark; --bg:#0f172a; --panel:#111827; --text:#f8fafc; --muted:#94a3b8; --line:#334155; --accent:#22c55e; }
1100
+ body { margin:0; font-family: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; background:linear-gradient(135deg,#020617,#111827); color:var(--text); }
1101
+ main { max-width:920px; margin:0 auto; padding:48px 20px; }
1102
+ .panel { border:1px solid var(--line); border-radius:20px; background:rgba(15,23,42,.86); padding:28px; box-shadow:0 24px 80px rgba(0,0,0,.32); }
1103
+ .eyebrow { color:var(--accent); font-size:13px; font-weight:700; letter-spacing:.12em; text-transform:uppercase; }
1104
+ h1 { font-size:clamp(32px,5vw,54px); line-height:1; margin:14px 0; }
1105
+ p { color:var(--muted); font-size:18px; line-height:1.6; }
1106
+ .grid { display:grid; grid-template-columns:repeat(auto-fit,minmax(220px,1fr)); gap:14px; margin-top:26px; }
1107
+ a { color:var(--text); text-decoration:none; }
1108
+ .card { display:block; border:1px solid var(--line); border-radius:16px; padding:18px; background:rgba(30,41,59,.7); }
1109
+ .card strong { display:block; margin-bottom:8px; }
1110
+ .card span { color:var(--muted); font-size:14px; line-height:1.5; }
1111
+ </style>
1112
+ <script>
1113
+ window.THUMBGATE_DASHBOARD_BOOTSTRAP = { enabled: ${bootstrapActive ? 'true' : 'false'}, apiKey: ${serializedBootstrapKey} };
1114
+ </script>
1115
+ </head>
1116
+ <body>
1117
+ <main>
1118
+ <section class="panel">
1119
+ <div class="eyebrow">Packaged runtime</div>
1120
+ <h1>ThumbGate is running locally.</h1>
1121
+ <p>This lightweight npm dashboard is bundled without marketing assets, so installs stay small while core feedback, lessons, and API routes remain available.</p>
1122
+ <div class="grid">
1123
+ <a class="card" href="/v1/dashboard"><strong>Dashboard JSON</strong><span>Inspect feedback totals, lesson counts, and Reliability Gateway health.</span></a>
1124
+ <a class="card" href="/lessons"><strong>Lessons</strong><span>Review remembered thumbs-up/down lessons and enforcement context.</span></a>
1125
+ <a class="card" href="/health"><strong>Health</strong><span>Verify the installed package version and runtime status.</span></a>
1126
+ </div>
1127
+ </section>
1128
+ </main>
1129
+ </body>
1130
+ </html>`;
1131
+ }
1132
+
1133
+ function renderPackagedLessonsHtml({ bootstrapActive, serializedBootstrapKey }) {
1134
+ return `<!doctype html>
1135
+ <html lang="en">
1136
+ <head>
1137
+ <meta charset="utf-8">
1138
+ <meta name="viewport" content="width=device-width, initial-scale=1">
1139
+ <title>ThumbGate Lessons</title>
1140
+ <style>
1141
+ :root { color-scheme: light dark; --bg:#0f172a; --panel:#111827; --text:#f8fafc; --muted:#94a3b8; --line:#334155; --accent:#38bdf8; }
1142
+ body { margin:0; font-family: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; background:linear-gradient(135deg,#020617,#0f172a); color:var(--text); }
1143
+ main { max-width:920px; margin:0 auto; padding:48px 20px; }
1144
+ .panel { border:1px solid var(--line); border-radius:20px; background:rgba(15,23,42,.86); padding:28px; box-shadow:0 24px 80px rgba(0,0,0,.32); }
1145
+ .eyebrow { color:var(--accent); font-size:13px; font-weight:700; letter-spacing:.12em; text-transform:uppercase; }
1146
+ h1 { font-size:clamp(32px,5vw,54px); line-height:1; margin:14px 0; }
1147
+ p { color:var(--muted); font-size:18px; line-height:1.6; }
1148
+ .actions { display:flex; flex-wrap:wrap; gap:12px; margin-top:26px; }
1149
+ a { color:var(--text); text-decoration:none; border:1px solid var(--line); border-radius:999px; padding:12px 16px; background:rgba(30,41,59,.7); }
1150
+ </style>
1151
+ <script>
1152
+ window.THUMBGATE_LESSONS_BOOTSTRAP = { enabled: ${bootstrapActive ? 'true' : 'false'}, apiKey: ${serializedBootstrapKey} };
1153
+ </script>
1154
+ </head>
1155
+ <body>
1156
+ <main>
1157
+ <section class="panel">
1158
+ <div class="eyebrow">Packaged runtime</div>
1159
+ <h1>ThumbGate lessons are available.</h1>
1160
+ <p>The full hosted lessons UI is excluded from the npm tarball, but installed packages still expose the lesson APIs and detail pages needed for local agent feedback loops.</p>
1161
+ <div class="actions">
1162
+ <a href="/v1/lessons/search">Search lessons JSON</a>
1163
+ <a href="/v1/feedback/stats">Feedback stats JSON</a>
1164
+ <a href="/dashboard">Back to dashboard</a>
1165
+ </div>
1166
+ </section>
1167
+ </main>
1168
+ </body>
1169
+ </html>`;
1170
+ }
1171
+
1172
+ function loadDashboardPageHtml(req, expectedApiKey) {
1173
+ const bootstrap = resolveLocalPageBootstrap(req, expectedApiKey);
1174
+ const template = readOptionalPublicTemplate(DASHBOARD_PAGE_PATH);
1175
+ if (!template) return renderPackagedDashboardHtml(bootstrap);
1176
+
1047
1177
  return fillTemplate(template, {
1048
- '__DASHBOARD_BOOTSTRAP_KEY__': serializedBootstrapKey,
1049
- '__DASHBOARD_BOOTSTRAP_ENABLED__': bootstrapActive ? 'true' : 'false',
1178
+ '__DASHBOARD_BOOTSTRAP_KEY__': bootstrap.serializedBootstrapKey,
1179
+ '__DASHBOARD_BOOTSTRAP_ENABLED__': bootstrap.bootstrapActive ? 'true' : 'false',
1050
1180
  });
1051
1181
  }
1052
1182
 
1053
1183
  function loadLessonsPageHtml(req, expectedApiKey) {
1054
- const template = fs.readFileSync(LESSONS_PAGE_PATH, 'utf-8');
1055
- const forwardedHost = req.headers['x-forwarded-host'];
1056
- const hostHeader = Array.isArray(forwardedHost)
1057
- ? forwardedHost[0]
1058
- : forwardedHost || req.headers.host || '';
1059
- const localProBootstrap = process.env.THUMBGATE_PRO_MODE === '1' && Boolean(expectedApiKey) && isLoopbackHost(hostHeader);
1060
- const devOverride = expectedApiKey === null && isLoopbackHost(hostHeader);
1061
- const bootstrapActive = localProBootstrap || devOverride;
1062
- const serializedBootstrapKey = JSON.stringify(localProBootstrap ? expectedApiKey : devOverride ? 'dev-override' : '').replace(/</g, '\\u003c');
1184
+ const bootstrap = resolveLocalPageBootstrap(req, expectedApiKey);
1185
+ const template = readOptionalPublicTemplate(LESSONS_PAGE_PATH);
1186
+ if (!template) return renderPackagedLessonsHtml(bootstrap);
1063
1187
 
1064
1188
  return fillTemplate(template, {
1065
- '__LESSONS_BOOTSTRAP_KEY__': serializedBootstrapKey,
1066
- '__LESSONS_BOOTSTRAP_ENABLED__': bootstrapActive ? 'true' : 'false',
1189
+ '__LESSONS_BOOTSTRAP_KEY__': bootstrap.serializedBootstrapKey,
1190
+ '__LESSONS_BOOTSTRAP_ENABLED__': bootstrap.bootstrapActive ? 'true' : 'false',
1067
1191
  });
1068
1192
  }
1069
1193
 
@@ -2354,6 +2478,29 @@ function createApiServer() {
2354
2478
  const requestFeedbackDir = requestFeedbackPaths.FEEDBACK_DIR;
2355
2479
  const requestSafeDataDir = getSafeDataDir(req, parsed);
2356
2480
 
2481
+ // PostHog reverse proxy -- bypasses ad blockers.
2482
+ // Only allow known PostHog API paths to prevent SSRF (CodeQL js/request-forgery).
2483
+ if (pathname.startsWith('/ingest')) {
2484
+ const posthogPath = getPosthogProxyPath(pathname);
2485
+ if (!isAllowedPosthogProxyPath(posthogPath)) {
2486
+ res.writeHead(403, { 'Content-Type': 'text/plain' });
2487
+ res.end('Forbidden');
2488
+ return;
2489
+ }
2490
+ let body = '';
2491
+ req.on('data', chunk => { body += chunk; });
2492
+ req.on('end', () => {
2493
+ const proxyReq = https.request(buildPosthogProxyRequestOptions(req, posthogPath, parsed.search), (proxyRes) => {
2494
+ res.writeHead(proxyRes.statusCode, proxyRes.headers);
2495
+ proxyRes.pipe(res);
2496
+ });
2497
+ proxyReq.on('error', () => { res.writeHead(502); res.end(); });
2498
+ if (body) proxyReq.write(body);
2499
+ proxyReq.end();
2500
+ });
2501
+ return;
2502
+ }
2503
+
2357
2504
  // Public MCP endpoint — responds to Smithery registry scanning and MCP initialize
2358
2505
  // The initialize handshake is unauthenticated; subsequent tool calls require Bearer auth
2359
2506
  if (pathname === '/mcp') {
@@ -3770,7 +3917,14 @@ async function addContext(){
3770
3917
  return;
3771
3918
  }
3772
3919
 
3773
- if (!isAuthorized(req, expectedApiKey)) {
3920
+ // Operator key is allowed to bypass the general admin gate for its dedicated endpoint
3921
+ const _reqToken = extractApiKey(req);
3922
+ const isOperatorBillingRequest = Boolean(expectedOperatorKey)
3923
+ && _reqToken === expectedOperatorKey
3924
+ && req.method === 'GET'
3925
+ && pathname === '/v1/billing/summary';
3926
+
3927
+ if (!isOperatorBillingRequest && !isAuthorized(req, expectedApiKey)) {
3774
3928
  sendProblem(res, {
3775
3929
  type: PROBLEM_TYPES.UNAUTHORIZED,
3776
3930
  title: 'Unauthorized',
@@ -5014,7 +5168,14 @@ module.exports = {
5014
5168
  startServer,
5015
5169
  __test__: {
5016
5170
  buildCheckoutFallbackUrl,
5171
+ buildPosthogProxyRequestOptions,
5172
+ getPosthogProxyPath,
5173
+ isAllowedPosthogProxyPath,
5017
5174
  renderSitemapXml,
5175
+ renderPackagedDashboardHtml,
5176
+ renderPackagedLessonsHtml,
5177
+ readOptionalPublicTemplate,
5178
+ resolveLocalPageBootstrap,
5018
5179
  },
5019
5180
  };
5020
5181
 
package/src/index.js ADDED
@@ -0,0 +1,3 @@
1
+ 'use strict';
2
+
3
+ module.exports = require('../scripts/feedback-loop');
Binary file
@@ -1,18 +0,0 @@
1
- <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" role="img" aria-labelledby="title desc">
2
- <title>ThumbGate</title>
3
- <desc>Gateway icon for the Claude Desktop workflow hardening extension.</desc>
4
- <defs>
5
- <linearGradient id="bg" x1="0%" x2="100%" y1="0%" y2="100%">
6
- <stop offset="0%" stop-color="#111827"/>
7
- <stop offset="100%" stop-color="#1f2937"/>
8
- </linearGradient>
9
- <linearGradient id="gate" x1="0%" x2="100%" y1="0%" y2="100%">
10
- <stop offset="0%" stop-color="#f97316"/>
11
- <stop offset="100%" stop-color="#fb7185"/>
12
- </linearGradient>
13
- </defs>
14
- <rect width="512" height="512" rx="96" fill="url(#bg)"/>
15
- <path fill="url(#gate)" d="M152 128h208c17.7 0 32 14.3 32 32v64h-64v-32H184v128h144v-32h64v64c0 17.7-14.3 32-32 32H152c-17.7 0-32-14.3-32-32V160c0-17.7 14.3-32 32-32Z"/>
16
- <path fill="#fff4ed" d="M248 180h96v48h-48v56h48v48h-96z"/>
17
- <circle cx="196" cy="256" r="26" fill="#fef3c7"/>
18
- </svg>
@@ -1,24 +0,0 @@
1
- #!/usr/bin/env node
2
- 'use strict';
3
-
4
- const path = require('path');
5
- const { spawn } = require('child_process');
6
-
7
- const cliPath = path.join(__dirname, '..', '..', 'bin', 'cli.js');
8
- const child = spawn(process.execPath, [cliPath, 'serve'], {
9
- stdio: 'inherit',
10
- env: process.env,
11
- });
12
-
13
- child.on('exit', (code, signal) => {
14
- if (signal) {
15
- process.kill(process.pid, signal);
16
- return;
17
- }
18
- process.exit(code ?? 1);
19
- });
20
-
21
- child.on('error', (error) => {
22
- console.error(`[thumbgate] Failed to launch Claude Desktop bundle runtime: ${error.message}`);
23
- process.exit(1);
24
- });
@@ -1,138 +0,0 @@
1
- # ChatGPT GPT Actions: ThumbGate Install
2
-
3
- Use the published ThumbGate GPT from GPT Store when it is visible for your account, or import the OpenAPI spec into a Custom GPT in under 5 minutes. Regular users use it by replying with 👍/👎 or "thumbs up/down" on ChatGPT answers so ThumbGate remembers lessons, prevents repeated bad answers, and reinforces the answers that worked.
4
-
5
- ## GPT Store path
6
-
7
- 1. Open ChatGPT.
8
- 2. Open **Explore GPTs**.
9
- 3. Search for `ThumbGate`.
10
- 4. Choose the GPT by **Igor Ganapolsky** in the **Programming** category.
11
-
12
- Direct store URL status: published by the operator on April 13, 2026, but the public `chatgpt.com/g/...` URL has not been captured in this repo yet. Do not invent a URL; add it here once the share link is available.
13
-
14
- ## 30-second regular-user flow
15
-
16
- 1. Ask the ThumbGate GPT any normal question.
17
- 2. If the answer helped, reply with `👍` plus one sentence about what worked.
18
- 3. If the answer missed, reply with `👎` plus one sentence about what to change.
19
- 4. Ask `What do you remember about how I like answers?` to verify the saved lessons.
20
-
21
- The user should never need to know what MCP, OpenAPI, Actions, DPO, or prevention rules mean. The GPT should explain the loop as: "Reply 👍 or 👎. I remember the lesson for next time."
22
-
23
- ## Regular-user prompts
24
-
25
- Use these as GPT conversation starters so regular users know how to teach ThumbGate:
26
-
27
- 1. `👎 this answer was too vague. Next time give me exact steps.`
28
- 2. `👍 this format worked. Remember to answer with short numbered steps.`
29
- 3. `Thumbs down: you assumed I know technical terms. Next time explain it for a beginner first.`
30
- 4. `Remember this lesson: I prefer direct answers with examples before theory.`
31
- 5. `Search my ThumbGate lessons before answering this.`
32
-
33
- Use typed chat replies. ChatGPT's native feedback buttons may send feedback to OpenAI, but they should not be described as the ThumbGate capture path unless OpenAI exposes them to GPT Actions.
34
-
35
- ## Pre-action gate flow
36
-
37
- Use this when the user asks whether an AI agent should run a proposed action, command, file edit, deployment, merge, or publish step:
38
-
39
- 1. The GPT calls `evaluateDecision` (`POST /v1/decisions/evaluate`) before answering.
40
- 2. If the response has `decisionControl.executionMode: "blocked"`, the GPT says the action is blocked and explains the returned reason.
41
- 3. If the response has `decisionControl.executionMode: "checkpoint_required"`, the GPT asks for explicit confirmation before proceeding.
42
- 4. If the response has `decisionControl.executionMode: "auto_execute"`, the GPT can say the action is allowed and summarize why.
43
-
44
- Plain thumbs-up/down feedback is the memory loop. The decision endpoint is the gate loop. Do not claim hard blocking unless the decision endpoint, a saved lesson, or a prevention rule was actually applied.
45
-
46
- ## Best first GPT message
47
-
48
- Use this as the first response for regular users:
49
-
50
- ```text
51
- Ask me anything. After my answer, reply 👍 if it helped or 👎 plus one sentence if it missed. I will remember the lesson, avoid repeating bad answer patterns, and reuse the formats you like.
52
- ```
53
-
54
- ## Prerequisites
55
-
56
- - A ChatGPT Plus or Team account (Custom GPTs require a paid plan)
57
- - ThumbGate API running at `https://thumbgate-production.up.railway.app`
58
- - Privacy policy URL: `https://thumbgate-production.up.railway.app/privacy`
59
- - Owner-managed `THUMBGATE_API_KEY` for one-time GPT Builder Actions auth
60
-
61
- Regular GPT users should not need an API key, JSON payload, OpenAPI knowledge, or developer setup. They should only see the thumbs-up/down memory loop.
62
-
63
- ## Step 1 — Open GPT Builder
64
-
65
- 1. Go to [https://chat.openai.com/gpts/editor](https://chat.openai.com/gpts/editor)
66
- 2. Click **Create a GPT**
67
- 3. Switch to the **Configure** tab
68
-
69
- ## Step 2 — Add Actions
70
-
71
- 1. Scroll to the **Actions** section
72
- 2. Click **Create new action**
73
- 3. Click **Import from URL** — paste your hosted spec URL:
74
- ```
75
- https://thumbgate-production.up.railway.app/openapi.yaml
76
- ```
77
- Or click **Upload file** and select:
78
- ```
79
- adapters/chatgpt/openapi.yaml
80
- ```
81
-
82
- ## Step 3 — Set Authentication
83
-
84
- In the Actions panel:
85
-
86
- 1. Select **Authentication type: API Key**
87
- 2. **Auth type**: Bearer
88
- 3. **API Key**: paste your `THUMBGATE_API_KEY` value
89
-
90
- This is an owner setup field. Do not ask regular GPT users to provide an API key.
91
-
92
- ## Step 4 — Update the Server URL
93
-
94
- In the imported spec, confirm the `servers.url` points to your deployed API:
95
-
96
- ```yaml
97
- servers:
98
- - url: https://thumbgate-production.up.railway.app
99
- ```
100
-
101
- If you uploaded the file, edit the server URL in the GPT Actions editor.
102
-
103
- ## Step 5 — Verify
104
-
105
- Click **Test** on the `captureFeedback` action:
106
-
107
- ```json
108
- {
109
- "signal": "up",
110
- "context": "GPT Actions install verified with a successful test call",
111
- "whatWorked": "The hosted action returned accepted=true and a promoted status"
112
- }
113
- ```
114
-
115
- Expected response: `200 OK` with `{ "accepted": true, "status": "promoted" }`.
116
-
117
- If you only send a bare `thumbs up/down` style payload, expect `422` with `status: "clarification_required"` and a follow-up `prompt`.
118
-
119
- ## Available Actions
120
-
121
- | Action | Method | Path | Description |
122
- |---|---|---|---|
123
- | `captureFeedback` | POST | `/v1/feedback/capture` | Capture up/down signal plus one-line why |
124
- | `getFeedbackStats` | GET | `/v1/feedback/stats` | Aggregated feedback statistics |
125
- | `getFeedbackSummary` | GET | `/v1/feedback/summary` | Recent feedback summary |
126
- | `generatePreventionRules` | POST | `/v1/feedback/rules` | Generate prevention rules |
127
- | `exportDpoPairs` | POST | `/v1/dpo/export` | Export DPO preference pairs |
128
- | `listIntentCatalog` | GET | `/v1/intents/catalog` | List available intents |
129
- | `planIntent` | POST | `/v1/intents/plan` | Generate policy-scoped plan |
130
- | `constructContextPack` | POST | `/v1/context/construct` | Build context pack |
131
-
132
- Full spec: `adapters/chatgpt/openapi.yaml`
133
-
134
- ## Troubleshooting
135
-
136
- - **401 Unauthorized**: Verify `THUMBGATE_API_KEY` is set and matches the Bearer token
137
- - **Connection refused**: Confirm Railway deployment is live (`curl https://<domain>/health`)
138
- - **Schema errors**: Ensure you are using the latest `openapi.yaml` (version 1.1.0+)
package/bin/memory.sh DELETED
@@ -1,64 +0,0 @@
1
- #!/bin/bash
2
- # bin/memory.sh - Layer 3 & 4 & 5 Memory Stack Refresher
3
-
4
- PRIMER_FILE="primer.md"
5
-
6
- if [ ! -f "$PRIMER_FILE" ]; then
7
- echo "Error: $PRIMER_FILE not found."
8
- exit 1
9
- fi
10
-
11
- echo "🤖 [Memory Stack] Refreshing context..."
12
-
13
- # 1. Behavioral Extraction (Layer 4)
14
- node scripts/behavioral-extraction.js > /dev/null
15
- TRAITS_FILE="$(node -e "const path = require('path'); const { resolveFeedbackDir } = require('./scripts/feedback-paths'); process.stdout.write(path.join(resolveFeedbackDir(), 'behavioral-traits.json'));" 2>/dev/null)"
16
- if [ -z "$TRAITS_FILE" ]; then
17
- TRAITS_FILE=".thumbgate/behavioral-traits.json"
18
- fi
19
-
20
- # 2. Capture git context (Layer 3)
21
- CURRENT_BRANCH=$(git rev-parse --abbrev-ref HEAD 2>/dev/null || echo "unknown")
22
- LAST_COMMITS=$(git log -n 5 --oneline 2>/dev/null || echo "No commits found")
23
- DIRTY_FILES=$(git status --short 2>/dev/null || echo "")
24
-
25
- # 3. Rebuild Primer
26
- TEMP_FILE=$(mktemp)
27
-
28
- # Read primer until "## Behavioral Traits"
29
- sed -n '1,/## Behavioral Traits/p' "$PRIMER_FILE" > "$TEMP_FILE"
30
- echo "" >> "$TEMP_FILE"
31
-
32
- if [ -f "$TRAITS_FILE" ]; then
33
- # Extract trait descriptions from JSON
34
- cat "$TRAITS_FILE" | grep "description" | sed 's/.*: "//;s/".*//' | sed 's/^/- /' >> "$TEMP_FILE"
35
- else
36
- echo "_No strong behavioral patterns identified yet._" >> "$TEMP_FILE"
37
- fi
38
-
39
- echo "" >> "$TEMP_FILE"
40
- echo "## Live Git Context" >> "$TEMP_FILE"
41
- echo "" >> "$TEMP_FILE"
42
- echo "### Branch: $CURRENT_BRANCH" >> "$TEMP_FILE"
43
- echo "" >> "$TEMP_FILE"
44
- echo "### Last 5 Commits:" >> "$TEMP_FILE"
45
- echo '```' >> "$TEMP_FILE"
46
- echo "$LAST_COMMITS" >> "$TEMP_FILE"
47
- echo '```' >> "$TEMP_FILE"
48
- echo "" >> "$TEMP_FILE"
49
- echo "### Modified Files:" >> "$TEMP_FILE"
50
- if [ -z "$DIRTY_FILES" ]; then
51
- echo "_None (Clean working tree)_" >> "$TEMP_FILE"
52
- else
53
- echo '```' >> "$TEMP_FILE"
54
- echo "$DIRTY_FILES" >> "$TEMP_FILE"
55
- echo '```' >> "$TEMP_FILE"
56
- fi
57
-
58
- mv "$TEMP_FILE" "$PRIMER_FILE"
59
-
60
- # 4. Sync to Obsidian (Layer 5)
61
- chmod +x bin/obsidian-sync.sh
62
- ./bin/obsidian-sync.sh
63
-
64
- echo "✅ Context refresh complete."
@@ -1,20 +0,0 @@
1
- #!/bin/bash
2
-
3
- # obsidian-sync.sh
4
- #
5
- # Layer 5: Obsidian Knowledge Bridge
6
- # Exports ThumbGate data as interlinked Obsidian markdown notes to a vault.
7
-
8
- VAULT_PATH=$THUMBGATE_OBSIDIAN_VAULT_PATH
9
- PROJECT_NAME=$(basename "$(pwd)")
10
-
11
- if [ -z "$VAULT_PATH" ]; then
12
- echo "🤖 [Layer 5] THUMBGATE_OBSIDIAN_VAULT_PATH not set. Skipping sync."
13
- exit 0
14
- fi
15
-
16
- echo "🤖 [Layer 5] Exporting memories to Obsidian vault: $VAULT_PATH/AI-Memories/$PROJECT_NAME"
17
-
18
- npx thumbgate obsidian-export --vault-path="$VAULT_PATH" --output-dir="AI-Memories/$PROJECT_NAME"
19
-
20
- echo "✅ Sync complete."
@@ -1,52 +0,0 @@
1
- # Amp: ThumbGate Feedback Skill Install
2
-
3
- Install the ThumbGate skill for Amp in under 60 seconds. No manual file editing required.
4
-
5
- ## One-Command Install
6
-
7
- ```bash
8
- cp plugins/amp-skill/SKILL.md .amp/skills/thumbgate-feedback.md
9
- ```
10
-
11
- Or from the npm package:
12
-
13
- ```bash
14
- npx thumbgate init
15
- cp node_modules/thumbgate/plugins/amp-skill/SKILL.md .amp/skills/thumbgate-feedback.md
16
- ```
17
-
18
- ## What This Does
19
-
20
- Copies the skill definition to `.amp/skills/` so Amp loads it automatically on next launch.
21
-
22
- ## Verify
23
-
24
- After copying, restart Amp. The skill will appear in the active skills list.
25
-
26
- Then test:
27
-
28
- ```bash
29
- npx thumbgate capture --feedback=up --context="amp skill install verified" --tags="install"
30
- ```
31
-
32
- ## Available Commands (via skill)
33
-
34
- ```bash
35
- # Positive feedback
36
- npx thumbgate capture --feedback=up --context="..." --tags="..."
37
-
38
- # Negative feedback
39
- npx thumbgate capture --feedback=down --context="..." --what-went-wrong="..." --what-to-change="..." --tags="..."
40
- ```
41
-
42
- ## Requirements
43
-
44
- - Amp (any version with skills support)
45
- - Node.js 18+ in PATH
46
- - `.thumbgate/` directory (created by `npx thumbgate init`)
47
-
48
- ## Uninstall
49
-
50
- ```bash
51
- rm .amp/skills/thumbgate-feedback.md
52
- ```