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,466 @@
1
+ 'use strict';
2
+
3
+ const fs = require('fs');
4
+ const path = require('path');
5
+ const { spawnSync } = require('child_process');
6
+
7
+ const PROJECT_ROOT = path.join(__dirname, '..');
8
+ const DEFAULT_TIMEOUT_MS = 8000;
9
+ const DEFAULT_ITEM_LIMIT = 5;
10
+ const INDEXED_REPOS = new Set();
11
+ const CODE_PATH_PATTERN = /\b([A-Za-z0-9_./-]+\.(?:c|cc|cpp|cs|go|h|hpp|java|js|jsx|kt|mjs|php|py|rb|rs|sh|sql|swift|ts|tsx|yaml|yml))\b/g;
12
+ const CODE_KEYWORDS = [
13
+ 'api',
14
+ 'class',
15
+ 'code',
16
+ 'endpoint',
17
+ 'file',
18
+ 'function',
19
+ 'handler',
20
+ 'implementation',
21
+ 'method',
22
+ 'module',
23
+ 'refactor',
24
+ 'rename',
25
+ 'repo',
26
+ 'symbol',
27
+ 'test',
28
+ ];
29
+ const STOPWORDS = new Set([
30
+ 'about',
31
+ 'after',
32
+ 'before',
33
+ 'change',
34
+ 'changes',
35
+ 'check',
36
+ 'code',
37
+ 'context',
38
+ 'current',
39
+ 'debug',
40
+ 'evidence',
41
+ 'file',
42
+ 'files',
43
+ 'fix',
44
+ 'impact',
45
+ 'intent',
46
+ 'line',
47
+ 'merge',
48
+ 'module',
49
+ 'path',
50
+ 'paths',
51
+ 'plan',
52
+ 'proof',
53
+ 'query',
54
+ 'refactor',
55
+ 'rename',
56
+ 'repo',
57
+ 'task',
58
+ 'tests',
59
+ 'tool',
60
+ 'verify',
61
+ 'workflow',
62
+ ]);
63
+
64
+ function uniqueStrings(values) {
65
+ return Array.from(new Set((values || []).filter(Boolean).map((value) => String(value).trim()).filter(Boolean)));
66
+ }
67
+
68
+ function parsePositiveInt(value, fallback) {
69
+ const parsed = Number(value);
70
+ return Number.isFinite(parsed) && parsed > 0 ? parsed : fallback;
71
+ }
72
+
73
+ function findGitRoot(startPath) {
74
+ const cwd = path.resolve(startPath || process.cwd());
75
+ const result = spawnSync('git', ['rev-parse', '--show-toplevel'], {
76
+ cwd,
77
+ encoding: 'utf8',
78
+ timeout: 2000,
79
+ });
80
+
81
+ if (result.status !== 0) {
82
+ return null;
83
+ }
84
+
85
+ const resolved = String(result.stdout || '').trim();
86
+ return resolved || null;
87
+ }
88
+
89
+ function resolveRepoPath(repoPath) {
90
+ const raw = String(repoPath || '').trim();
91
+
92
+ if (raw) {
93
+ const resolved = path.resolve(raw);
94
+ const existingTarget = fs.existsSync(resolved) && fs.statSync(resolved).isDirectory()
95
+ ? resolved
96
+ : path.dirname(resolved);
97
+ const root = findGitRoot(existingTarget);
98
+ return root || existingTarget;
99
+ }
100
+
101
+ return findGitRoot(process.cwd()) || PROJECT_ROOT;
102
+ }
103
+
104
+ function looksLikeCodeWorkflow(options = {}) {
105
+ if (options.repoPath) return true;
106
+
107
+ const text = `${options.intentId || ''} ${options.context || ''}`.trim();
108
+ if (!text) return false;
109
+ if (CODE_PATH_PATTERN.test(text)) {
110
+ CODE_PATH_PATTERN.lastIndex = 0;
111
+ return true;
112
+ }
113
+ CODE_PATH_PATTERN.lastIndex = 0;
114
+
115
+ const lower = text.toLowerCase();
116
+ return CODE_KEYWORDS.some((keyword) => lower.includes(keyword));
117
+ }
118
+
119
+ function extractFileHints(context = '') {
120
+ const matches = [];
121
+ let match = CODE_PATH_PATTERN.exec(String(context || ''));
122
+ while (match) {
123
+ matches.push(match[1]);
124
+ match = CODE_PATH_PATTERN.exec(String(context || ''));
125
+ }
126
+ CODE_PATH_PATTERN.lastIndex = 0;
127
+ return uniqueStrings(matches).slice(0, DEFAULT_ITEM_LIMIT);
128
+ }
129
+
130
+ function pushSymbolCandidate(candidates, candidate) {
131
+ const value = String(candidate || '').trim();
132
+ if (!value) return;
133
+ if (value.includes('/') || value.includes('\\')) return;
134
+ if (STOPWORDS.has(value.toLowerCase())) return;
135
+ if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(value)) return;
136
+ candidates.push(value);
137
+ }
138
+
139
+ function isCompoundPascalCaseToken(token) {
140
+ const value = String(token || '').trim();
141
+ if (!value || !/^[A-Z][A-Za-z0-9]*$/.test(value)) return false;
142
+
143
+ let segmentCount = 1;
144
+ for (let index = 1; index < value.length; index += 1) {
145
+ const current = value[index];
146
+ const previous = value[index - 1];
147
+ if (/[A-Z]/.test(current) && /[a-z0-9]/.test(previous)) {
148
+ segmentCount += 1;
149
+ }
150
+ }
151
+
152
+ return segmentCount >= 2;
153
+ }
154
+
155
+ function extractSymbolHints(context = '') {
156
+ const text = String(context || '');
157
+ const candidates = [];
158
+
159
+ for (const fileHint of extractFileHints(text)) {
160
+ pushSymbolCandidate(candidates, path.basename(fileHint, path.extname(fileHint)));
161
+ }
162
+
163
+ for (const match of text.matchAll(/`([^`]+)`/g)) {
164
+ pushSymbolCandidate(candidates, match[1]);
165
+ }
166
+
167
+ for (const match of text.matchAll(/\b([A-Za-z_][A-Za-z0-9_]*)(?=\s*\()/g)) {
168
+ pushSymbolCandidate(candidates, match[1]);
169
+ }
170
+
171
+ for (const token of text.split(/[^A-Za-z0-9_]+/)) {
172
+ if (isCompoundPascalCaseToken(token)) {
173
+ pushSymbolCandidate(candidates, token);
174
+ }
175
+ }
176
+
177
+ for (const match of text.matchAll(/\b([a-z][A-Za-z0-9_]{3,})\b/g)) {
178
+ pushSymbolCandidate(candidates, match[1]);
179
+ }
180
+
181
+ return uniqueStrings(candidates).slice(0, 3);
182
+ }
183
+
184
+ function normalizeList(values, limit = DEFAULT_ITEM_LIMIT) {
185
+ return uniqueStrings(values).slice(0, limit);
186
+ }
187
+
188
+ function parseGraphItems(output, limit = DEFAULT_ITEM_LIMIT) {
189
+ const lines = String(output || '')
190
+ .split(/\r?\n/)
191
+ .map((line) => line.trim())
192
+ .filter(Boolean)
193
+ .filter((line) => !/^(info|warn|debug|trace)[:\s]/i.test(line))
194
+ .filter((line) => !/^(analyzing|indexed|indexing|loaded|scanning)\b/i.test(line))
195
+ .filter((line) => !/^(no\s+(callers|callees|dead))/i.test(line))
196
+ .map((line) => line.replace(/^[-*•\d.)\s]+/, '').trim())
197
+ .filter(Boolean);
198
+
199
+ return uniqueStrings(lines).slice(0, limit);
200
+ }
201
+
202
+ function getTimeoutMs(options = {}) {
203
+ return parsePositiveInt(options.timeoutMs || process.env.THUMBGATE_CODEGRAPH_TIMEOUT_MS, DEFAULT_TIMEOUT_MS);
204
+ }
205
+
206
+ function isCodeGraphEnabled() {
207
+ const disabled = String(process.env.THUMBGATE_CODEGRAPH_DISABLED || '').toLowerCase();
208
+ return disabled !== '1' && disabled !== 'true';
209
+ }
210
+
211
+ function shouldAutoIndex() {
212
+ const raw = String(process.env.THUMBGATE_CODEGRAPH_AUTO_INDEX || '').toLowerCase();
213
+ if (!raw) return true;
214
+ return raw !== '0' && raw !== 'false';
215
+ }
216
+
217
+ function getCodeGraphBin() {
218
+ return process.env.THUMBGATE_CODEGRAPH_BIN || 'cgc';
219
+ }
220
+
221
+ function runCodeGraph(bin, args, options = {}) {
222
+ const result = spawnSync(bin, args, {
223
+ cwd: options.cwd,
224
+ encoding: 'utf8',
225
+ timeout: getTimeoutMs(options),
226
+ });
227
+
228
+ if (result.error) {
229
+ throw result.error;
230
+ }
231
+ if (result.status !== 0) {
232
+ const stderr = String(result.stderr || '').trim();
233
+ throw new Error(stderr || `CodeGraphContext exited with status ${result.status}`);
234
+ }
235
+
236
+ return String(result.stdout || '').trim();
237
+ }
238
+
239
+ function ensureIndexed(bin, repoPath, options = {}) {
240
+ if (!shouldAutoIndex()) return;
241
+ if (INDEXED_REPOS.has(repoPath)) return;
242
+ runCodeGraph(bin, ['index', '.'], { cwd: repoPath, timeoutMs: options.timeoutMs });
243
+ INDEXED_REPOS.add(repoPath);
244
+ }
245
+
246
+ function parseStubImpact(input, context = {}) {
247
+ if (!input) return null;
248
+ let parsed = input;
249
+
250
+ if (typeof input === 'string') {
251
+ try {
252
+ parsed = JSON.parse(input);
253
+ } catch (_) {
254
+ return null;
255
+ }
256
+ }
257
+
258
+ return normalizeImpact({
259
+ source: parsed.source || 'stub',
260
+ repoPath: parsed.repoPath || context.repoPath,
261
+ query: parsed.query || context.query,
262
+ symbols: parsed.symbols || context.symbols,
263
+ callers: parsed.callers,
264
+ callees: parsed.callees,
265
+ deadCode: parsed.deadCode || parsed.dead_code,
266
+ });
267
+ }
268
+
269
+ function buildVerificationHints(impact) {
270
+ const hints = [];
271
+ const primarySymbol = impact.symbols[0];
272
+
273
+ if (primarySymbol && impact.callers.length > 0) {
274
+ hints.push(`Inspect upstream callers of ${primarySymbol} before merge.`);
275
+ }
276
+ if (primarySymbol && impact.callees.length > 0) {
277
+ hints.push(`Exercise downstream dependencies touched by ${primarySymbol}.`);
278
+ }
279
+ if (impact.deadCode.length > 0) {
280
+ hints.push('Review potential dead code before claiming the change is complete.');
281
+ }
282
+
283
+ return hints;
284
+ }
285
+
286
+ function summarizeImpact(impact) {
287
+ const primarySymbol = impact.symbols[0];
288
+ const segments = [];
289
+
290
+ if (primarySymbol) {
291
+ segments.push(`Focus symbol: ${primarySymbol}.`);
292
+ }
293
+ if (impact.callers.length > 0) {
294
+ segments.push(`${impact.callers.length} caller path${impact.callers.length === 1 ? '' : 's'} to verify.`);
295
+ }
296
+ if (impact.callees.length > 0) {
297
+ segments.push(`${impact.callees.length} downstream dependency path${impact.callees.length === 1 ? '' : 's'} touched.`);
298
+ }
299
+ if (impact.deadCode.length > 0) {
300
+ segments.push(`${impact.deadCode.length} potential dead-code candidate${impact.deadCode.length === 1 ? '' : 's'} detected.`);
301
+ }
302
+
303
+ return segments.join(' ');
304
+ }
305
+
306
+ function normalizeImpact(raw = {}) {
307
+ const symbols = normalizeList(raw.symbols);
308
+ const callers = normalizeList(raw.callers);
309
+ const callees = normalizeList(raw.callees);
310
+ const deadCode = normalizeList(raw.deadCode);
311
+ const impactScore = Math.min(10, (callers.length * 2) + callees.length + deadCode.length + symbols.length);
312
+
313
+ const impact = {
314
+ enabled: true,
315
+ automated: true,
316
+ source: raw.source || 'codegraphcontext',
317
+ repoPath: raw.repoPath || null,
318
+ query: raw.query || '',
319
+ symbols,
320
+ callers,
321
+ callees,
322
+ deadCode,
323
+ hasImpact: symbols.length > 0 || callers.length > 0 || callees.length > 0 || deadCode.length > 0,
324
+ evidence: {
325
+ symbolCount: symbols.length,
326
+ callerCount: callers.length,
327
+ calleeCount: callees.length,
328
+ deadCodeCount: deadCode.length,
329
+ impactScore,
330
+ },
331
+ };
332
+
333
+ impact.verificationHints = buildVerificationHints(impact);
334
+ impact.summary = summarizeImpact(impact);
335
+ return impact;
336
+ }
337
+
338
+ function unavailableImpact(context, reason) {
339
+ return {
340
+ enabled: false,
341
+ automated: true,
342
+ source: 'unavailable',
343
+ repoPath: context.repoPath || null,
344
+ query: context.query || '',
345
+ symbols: context.symbols || [],
346
+ callers: [],
347
+ callees: [],
348
+ deadCode: [],
349
+ hasImpact: false,
350
+ evidence: {
351
+ symbolCount: (context.symbols || []).length,
352
+ callerCount: 0,
353
+ calleeCount: 0,
354
+ deadCodeCount: 0,
355
+ impactScore: 0,
356
+ },
357
+ verificationHints: [],
358
+ summary: '',
359
+ reason,
360
+ };
361
+ }
362
+
363
+ function analyzeCodeGraphImpact(options = {}) {
364
+ const rawQuery = String(options.context || options.query || '').trim();
365
+ const rawRepoPath = String(options.repoPath || '').trim();
366
+ const context = {
367
+ intentId: options.intentId || '',
368
+ query: rawQuery,
369
+ repoPath: rawRepoPath ? resolveRepoPath(rawRepoPath) : null,
370
+ };
371
+ context.symbols = extractSymbolHints(context.query);
372
+
373
+ if (!isCodeGraphEnabled()) {
374
+ return unavailableImpact(context, 'Code graph analysis disabled');
375
+ }
376
+
377
+ if (!looksLikeCodeWorkflow({ intentId: context.intentId, context: context.query, repoPath: options.repoPath })) {
378
+ return unavailableImpact(context, 'Task does not look like a coding workflow');
379
+ }
380
+
381
+ if (!context.repoPath) {
382
+ context.repoPath = resolveRepoPath();
383
+ }
384
+
385
+ const stub = parseStubImpact(options.stubResponse || process.env.THUMBGATE_CODEGRAPH_STUB_RESPONSE, context);
386
+ if (stub) {
387
+ return stub;
388
+ }
389
+
390
+ if (context.symbols.length === 0) {
391
+ return unavailableImpact(context, 'No code symbols detected in task context');
392
+ }
393
+
394
+ const bin = getCodeGraphBin();
395
+ try {
396
+ ensureIndexed(bin, context.repoPath, options);
397
+
398
+ const callers = [];
399
+ const callees = [];
400
+ for (const symbol of context.symbols.slice(0, 2)) {
401
+ callers.push(...parseGraphItems(runCodeGraph(bin, ['analyze', 'callers', symbol], {
402
+ cwd: context.repoPath,
403
+ timeoutMs: options.timeoutMs,
404
+ })));
405
+ callees.push(...parseGraphItems(runCodeGraph(bin, ['analyze', 'calls', symbol], {
406
+ cwd: context.repoPath,
407
+ timeoutMs: options.timeoutMs,
408
+ })));
409
+ }
410
+
411
+ const deadCode = parseGraphItems(runCodeGraph(bin, ['analyze', 'dead-code'], {
412
+ cwd: context.repoPath,
413
+ timeoutMs: options.timeoutMs,
414
+ }));
415
+
416
+ return normalizeImpact({
417
+ source: 'codegraphcontext',
418
+ repoPath: context.repoPath,
419
+ query: context.query,
420
+ symbols: context.symbols,
421
+ callers,
422
+ callees,
423
+ deadCode,
424
+ });
425
+ } catch (err) {
426
+ return unavailableImpact(context, err && err.message ? err.message : 'Code graph analysis failed');
427
+ }
428
+ }
429
+
430
+ function formatCodeGraphRecallSection(impact) {
431
+ if (!impact || !impact.enabled || !impact.hasImpact) {
432
+ return '';
433
+ }
434
+
435
+ const lines = ['## Code Graph Impact', ''];
436
+ if (impact.summary) {
437
+ lines.push(impact.summary);
438
+ lines.push('');
439
+ }
440
+ if (impact.symbols.length > 0) {
441
+ lines.push(`Focus symbols: ${impact.symbols.join(', ')}`);
442
+ }
443
+ if (impact.callers.length > 0) {
444
+ lines.push(`Upstream callers: ${impact.callers.join(' | ')}`);
445
+ }
446
+ if (impact.callees.length > 0) {
447
+ lines.push(`Downstream dependencies: ${impact.callees.join(' | ')}`);
448
+ }
449
+ if (impact.deadCode.length > 0) {
450
+ lines.push(`Potential dead code: ${impact.deadCode.join(' | ')}`);
451
+ }
452
+ if (impact.verificationHints.length > 0) {
453
+ lines.push(`Verification focus: ${impact.verificationHints.join(' ')}`);
454
+ }
455
+
456
+ return lines.join('\n');
457
+ }
458
+
459
+ module.exports = {
460
+ analyzeCodeGraphImpact,
461
+ extractSymbolHints,
462
+ formatCodeGraphRecallSection,
463
+ isCodeGraphEnabled,
464
+ looksLikeCodeWorkflow,
465
+ resolveRepoPath,
466
+ };
@@ -0,0 +1,56 @@
1
+ 'use strict';
2
+
3
+ const PRO_MONTHLY_PAYMENT_LINK = 'https://buy.stripe.com/5kQ4gzbmI9Lo6tPayn3sI06';
4
+ const PRO_ANNUAL_PAYMENT_LINK = 'https://buy.stripe.com/3cI8wPfCYaPs2dzdKz3sI07';
5
+ const PRO_FOUNDER_PAYMENT_LINK = 'https://buy.stripe.com/aFa4gz1M84r419v7mb3sI05';
6
+
7
+ const PRO_MONTHLY_PRICE_ID = 'price_1THQY7GGBpd520QYHoS7RG0J';
8
+ const PRO_ANNUAL_PRICE_ID = 'price_1THQZ7GGBpd520QYxzDRnxhB';
9
+ const TEAM_MONTHLY_PRICE_ID = 'price_1THQa5GGBpd520QYoqdq1R1S';
10
+
11
+ const PRO_MONTHLY_PRICE_DOLLARS = 19;
12
+ const PRO_ANNUAL_PRICE_DOLLARS = 149;
13
+ const TEAM_MONTHLY_PRICE_DOLLARS = 12;
14
+ const TEAM_ANNUAL_PRICE_DOLLARS = 99;
15
+ const TEAM_MIN_SEATS = 3;
16
+
17
+ const PRO_PRICE_LABEL = '$19/mo or $149/yr';
18
+ const TEAM_PRICE_LABEL = 'Starts at $36/mo for 3 seats, then $12/seat/mo';
19
+
20
+ function normalizePlanId(value) {
21
+ const text = String(value || '').trim().toLowerCase();
22
+ return text || 'pro';
23
+ }
24
+
25
+ function normalizeBillingCycle(value) {
26
+ const text = String(value || '').trim().toLowerCase();
27
+ if (text === 'yearly') return 'annual';
28
+ return text || 'monthly';
29
+ }
30
+
31
+ function normalizeSeatCount(value, fallback = TEAM_MIN_SEATS) {
32
+ const parsed = Number(value);
33
+ if (!Number.isFinite(parsed) || parsed <= 0) {
34
+ return fallback;
35
+ }
36
+ return Math.max(TEAM_MIN_SEATS, Math.round(parsed));
37
+ }
38
+
39
+ module.exports = {
40
+ PRO_MONTHLY_PAYMENT_LINK,
41
+ PRO_ANNUAL_PAYMENT_LINK,
42
+ PRO_FOUNDER_PAYMENT_LINK,
43
+ PRO_MONTHLY_PRICE_ID,
44
+ PRO_ANNUAL_PRICE_ID,
45
+ TEAM_MONTHLY_PRICE_ID,
46
+ PRO_MONTHLY_PRICE_DOLLARS,
47
+ PRO_ANNUAL_PRICE_DOLLARS,
48
+ TEAM_MONTHLY_PRICE_DOLLARS,
49
+ TEAM_ANNUAL_PRICE_DOLLARS,
50
+ TEAM_MIN_SEATS,
51
+ PRO_PRICE_LABEL,
52
+ TEAM_PRICE_LABEL,
53
+ normalizePlanId,
54
+ normalizeBillingCycle,
55
+ normalizeSeatCount,
56
+ };