thoughtleaders-cli 0.9.10__tar.gz → 0.9.12__tar.gz

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 (163) hide show
  1. {thoughtleaders_cli-0.9.10 → thoughtleaders_cli-0.9.12}/.claude-plugin/plugin.json +1 -1
  2. {thoughtleaders_cli-0.9.10 → thoughtleaders_cli-0.9.12}/AGENTS.md +3 -1
  3. {thoughtleaders_cli-0.9.10 → thoughtleaders_cli-0.9.12}/PKG-INFO +1 -1
  4. {thoughtleaders_cli-0.9.10 → thoughtleaders_cli-0.9.12}/pyproject.toml +1 -1
  5. {thoughtleaders_cli-0.9.10 → thoughtleaders_cli-0.9.12}/skills/tl/SKILL.md +2 -3
  6. {thoughtleaders_cli-0.9.10 → thoughtleaders_cli-0.9.12}/skills/tl/references/elasticsearch-schema.md +3 -3
  7. {thoughtleaders_cli-0.9.10 → thoughtleaders_cli-0.9.12}/skills/tl/references/postgres-schema.md +11 -6
  8. {thoughtleaders_cli-0.9.10 → thoughtleaders_cli-0.9.12}/skills/tl-save-report/references/intelligence_filterset_schema.json +0 -12
  9. {thoughtleaders_cli-0.9.10 → thoughtleaders_cli-0.9.12}/skills/tl-save-report/references/sponsorship_filterset_schema.json +0 -12
  10. {thoughtleaders_cli-0.9.10 → thoughtleaders_cli-0.9.12}/src/tl_cli/__init__.py +1 -1
  11. {thoughtleaders_cli-0.9.10 → thoughtleaders_cli-0.9.12}/src/tl_cli/output/formatter.py +1 -1
  12. {thoughtleaders_cli-0.9.10 → thoughtleaders_cli-0.9.12}/.claude-plugin/marketplace.json +0 -0
  13. {thoughtleaders_cli-0.9.10 → thoughtleaders_cli-0.9.12}/.github/dependabot.yml +0 -0
  14. {thoughtleaders_cli-0.9.10 → thoughtleaders_cli-0.9.12}/.github/workflows/ci.yml +0 -0
  15. {thoughtleaders_cli-0.9.10 → thoughtleaders_cli-0.9.12}/.github/workflows/cli-integration.yml +0 -0
  16. {thoughtleaders_cli-0.9.10 → thoughtleaders_cli-0.9.12}/.github/workflows/python-publish.yml +0 -0
  17. {thoughtleaders_cli-0.9.10 → thoughtleaders_cli-0.9.12}/.gitignore +0 -0
  18. {thoughtleaders_cli-0.9.10 → thoughtleaders_cli-0.9.12}/API.md +0 -0
  19. {thoughtleaders_cli-0.9.10 → thoughtleaders_cli-0.9.12}/CLAUDE.md +0 -0
  20. {thoughtleaders_cli-0.9.10 → thoughtleaders_cli-0.9.12}/LICENSE +0 -0
  21. {thoughtleaders_cli-0.9.10 → thoughtleaders_cli-0.9.12}/README.md +0 -0
  22. {thoughtleaders_cli-0.9.10 → thoughtleaders_cli-0.9.12}/agents/keyword-context-classifier.md +0 -0
  23. {thoughtleaders_cli-0.9.10 → thoughtleaders_cli-0.9.12}/agents/keyword-entity-resolver.md +0 -0
  24. {thoughtleaders_cli-0.9.10 → thoughtleaders_cli-0.9.12}/agents/keyword-relevance-validator.md +0 -0
  25. {thoughtleaders_cli-0.9.10 → thoughtleaders_cli-0.9.12}/agents/tl-analyst.md +0 -0
  26. {thoughtleaders_cli-0.9.10 → thoughtleaders_cli-0.9.12}/agents/youtube-comment-classifier.md +0 -0
  27. {thoughtleaders_cli-0.9.10 → thoughtleaders_cli-0.9.12}/hooks/hooks.json +0 -0
  28. {thoughtleaders_cli-0.9.10 → thoughtleaders_cli-0.9.12}/hooks/scripts/load-tl-skill.mjs +0 -0
  29. {thoughtleaders_cli-0.9.10 → thoughtleaders_cli-0.9.12}/hooks/scripts/post-usage.sh +0 -0
  30. {thoughtleaders_cli-0.9.10 → thoughtleaders_cli-0.9.12}/hooks/scripts/pre-check.sh +0 -0
  31. {thoughtleaders_cli-0.9.10 → thoughtleaders_cli-0.9.12}/skills/tl/references/business-glossary.md +0 -0
  32. {thoughtleaders_cli-0.9.10 → thoughtleaders_cli-0.9.12}/skills/tl/references/firebolt-schema.md +0 -0
  33. {thoughtleaders_cli-0.9.10 → thoughtleaders_cli-0.9.12}/skills/tl-channel-authenticity/.gitignore +0 -0
  34. {thoughtleaders_cli-0.9.10 → thoughtleaders_cli-0.9.12}/skills/tl-channel-authenticity/SKILL.md +0 -0
  35. {thoughtleaders_cli-0.9.10 → thoughtleaders_cli-0.9.12}/skills/tl-channel-authenticity/references/comment-patterns.md +0 -0
  36. {thoughtleaders_cli-0.9.10 → thoughtleaders_cli-0.9.12}/skills/tl-channel-authenticity/references/peer-cohort.md +0 -0
  37. {thoughtleaders_cli-0.9.10 → thoughtleaders_cli-0.9.12}/skills/tl-channel-authenticity/references/red-flags.md +0 -0
  38. {thoughtleaders_cli-0.9.10 → thoughtleaders_cli-0.9.12}/skills/tl-channel-authenticity/references/scoring.md +0 -0
  39. {thoughtleaders_cli-0.9.10 → thoughtleaders_cli-0.9.12}/skills/tl-channel-authenticity/scripts/_io_utf8.py +0 -0
  40. {thoughtleaders_cli-0.9.10 → thoughtleaders_cli-0.9.12}/skills/tl-channel-authenticity/scripts/analyze_channel.py +0 -0
  41. {thoughtleaders_cli-0.9.10 → thoughtleaders_cli-0.9.12}/skills/tl-channel-authenticity/scripts/anomaly_detector.py +0 -0
  42. {thoughtleaders_cli-0.9.10 → thoughtleaders_cli-0.9.12}/skills/tl-channel-authenticity/scripts/comment_analyzer.py +0 -0
  43. {thoughtleaders_cli-0.9.10 → thoughtleaders_cli-0.9.12}/skills/tl-channel-authenticity/scripts/comment_scraper.py +0 -0
  44. {thoughtleaders_cli-0.9.10 → thoughtleaders_cli-0.9.12}/skills/tl-channel-authenticity/scripts/engagement_ratios.py +0 -0
  45. {thoughtleaders_cli-0.9.10 → thoughtleaders_cli-0.9.12}/skills/tl-channel-authenticity/scripts/peer_cohort.py +0 -0
  46. {thoughtleaders_cli-0.9.10 → thoughtleaders_cli-0.9.12}/skills/tl-channel-authenticity/scripts/report.py +0 -0
  47. {thoughtleaders_cli-0.9.10 → thoughtleaders_cli-0.9.12}/skills/tl-channel-authenticity/scripts/resolve_channel.py +0 -0
  48. {thoughtleaders_cli-0.9.10 → thoughtleaders_cli-0.9.12}/skills/tl-channel-authenticity/scripts/score.py +0 -0
  49. {thoughtleaders_cli-0.9.10 → thoughtleaders_cli-0.9.12}/skills/tl-channel-authenticity/scripts/tl_cli.py +0 -0
  50. {thoughtleaders_cli-0.9.10 → thoughtleaders_cli-0.9.12}/skills/tl-channel-authenticity/scripts/video_integrity.py +0 -0
  51. {thoughtleaders_cli-0.9.10 → thoughtleaders_cli-0.9.12}/skills/tl-channel-authenticity/scripts/view_curves.py +0 -0
  52. {thoughtleaders_cli-0.9.10 → thoughtleaders_cli-0.9.12}/skills/tl-create-workflow/SKILL.md +0 -0
  53. {thoughtleaders_cli-0.9.10 → thoughtleaders_cli-0.9.12}/skills/tl-create-workflow/references/creating-in-app.md +0 -0
  54. {thoughtleaders_cli-0.9.10 → thoughtleaders_cli-0.9.12}/skills/tl-create-workflow/references/methodology.md +0 -0
  55. {thoughtleaders_cli-0.9.10 → thoughtleaders_cli-0.9.12}/skills/tl-create-workflow/references/pitfalls.md +0 -0
  56. {thoughtleaders_cli-0.9.10 → thoughtleaders_cli-0.9.12}/skills/tl-create-workflow/references/workflow-model.md +0 -0
  57. {thoughtleaders_cli-0.9.10 → thoughtleaders_cli-0.9.12}/skills/tl-keyword-research/SKILL.md +0 -0
  58. {thoughtleaders_cli-0.9.10 → thoughtleaders_cli-0.9.12}/skills/tl-keyword-research/references/elasticsearch-content-search.md +0 -0
  59. {thoughtleaders_cli-0.9.10 → thoughtleaders_cli-0.9.12}/skills/tl-keyword-research/references/help.md +0 -0
  60. {thoughtleaders_cli-0.9.10 → thoughtleaders_cli-0.9.12}/skills/tl-keyword-research/scripts/build_report.py +0 -0
  61. {thoughtleaders_cli-0.9.10 → thoughtleaders_cli-0.9.12}/skills/tl-keyword-research/scripts/expand_entities.py +0 -0
  62. {thoughtleaders_cli-0.9.10 → thoughtleaders_cli-0.9.12}/skills/tl-keyword-research/scripts/fetch_context.py +0 -0
  63. {thoughtleaders_cli-0.9.10 → thoughtleaders_cli-0.9.12}/skills/tl-keyword-research/scripts/probe.py +0 -0
  64. {thoughtleaders_cli-0.9.10 → thoughtleaders_cli-0.9.12}/skills/tl-keyword-research/scripts/search_channels.py +0 -0
  65. {thoughtleaders_cli-0.9.10 → thoughtleaders_cli-0.9.12}/skills/tl-keyword-research/scripts/search_videos.py +0 -0
  66. {thoughtleaders_cli-0.9.10 → thoughtleaders_cli-0.9.12}/skills/tl-keyword-research/scripts/select_keywords.py +0 -0
  67. {thoughtleaders_cli-0.9.10 → thoughtleaders_cli-0.9.12}/skills/tl-save-report/SKILL.md +0 -0
  68. {thoughtleaders_cli-0.9.10 → thoughtleaders_cli-0.9.12}/skills/tl-save-report/references/columns_brands.md +0 -0
  69. {thoughtleaders_cli-0.9.10 → thoughtleaders_cli-0.9.12}/skills/tl-save-report/references/columns_channels.md +0 -0
  70. {thoughtleaders_cli-0.9.10 → thoughtleaders_cli-0.9.12}/skills/tl-save-report/references/columns_content.md +0 -0
  71. {thoughtleaders_cli-0.9.10 → thoughtleaders_cli-0.9.12}/skills/tl-save-report/references/columns_sponsorships.md +0 -0
  72. {thoughtleaders_cli-0.9.10 → thoughtleaders_cli-0.9.12}/skills/tl-save-report/references/intelligence_widget_schema.json +0 -0
  73. {thoughtleaders_cli-0.9.10 → thoughtleaders_cli-0.9.12}/skills/tl-save-report/references/report_glossary.md +0 -0
  74. {thoughtleaders_cli-0.9.10 → thoughtleaders_cli-0.9.12}/skills/tl-save-report/references/sortable_columns.json +0 -0
  75. {thoughtleaders_cli-0.9.10 → thoughtleaders_cli-0.9.12}/skills/tl-save-report/references/sponsorship_widget_schema.json +0 -0
  76. {thoughtleaders_cli-0.9.10 → thoughtleaders_cli-0.9.12}/skills/tl-save-report/references/widgets.md +0 -0
  77. {thoughtleaders_cli-0.9.10 → thoughtleaders_cli-0.9.12}/skills/tl-top-partnerships/SKILL.md +0 -0
  78. {thoughtleaders_cli-0.9.10 → thoughtleaders_cli-0.9.12}/skills/tl-top-partnerships/scripts/top_partnerships.py +0 -0
  79. {thoughtleaders_cli-0.9.10 → thoughtleaders_cli-0.9.12}/skills/tl-views-guarantee/SKILL.md +0 -0
  80. {thoughtleaders_cli-0.9.10 → thoughtleaders_cli-0.9.12}/skills/tl-views-guarantee/scripts/vg.py +0 -0
  81. {thoughtleaders_cli-0.9.10 → thoughtleaders_cli-0.9.12}/src/tl_cli/__main__.py +0 -0
  82. {thoughtleaders_cli-0.9.10 → thoughtleaders_cli-0.9.12}/src/tl_cli/_completions.py +0 -0
  83. {thoughtleaders_cli-0.9.10 → thoughtleaders_cli-0.9.12}/src/tl_cli/_typer_utils.py +0 -0
  84. {thoughtleaders_cli-0.9.10 → thoughtleaders_cli-0.9.12}/src/tl_cli/auth/__init__.py +0 -0
  85. {thoughtleaders_cli-0.9.10 → thoughtleaders_cli-0.9.12}/src/tl_cli/auth/commands.py +0 -0
  86. {thoughtleaders_cli-0.9.10 → thoughtleaders_cli-0.9.12}/src/tl_cli/auth/login.py +0 -0
  87. {thoughtleaders_cli-0.9.10 → thoughtleaders_cli-0.9.12}/src/tl_cli/auth/pkce.py +0 -0
  88. {thoughtleaders_cli-0.9.10 → thoughtleaders_cli-0.9.12}/src/tl_cli/auth/token_store.py +0 -0
  89. {thoughtleaders_cli-0.9.10 → thoughtleaders_cli-0.9.12}/src/tl_cli/client/__init__.py +0 -0
  90. {thoughtleaders_cli-0.9.10 → thoughtleaders_cli-0.9.12}/src/tl_cli/client/errors.py +0 -0
  91. {thoughtleaders_cli-0.9.10 → thoughtleaders_cli-0.9.12}/src/tl_cli/client/http.py +0 -0
  92. {thoughtleaders_cli-0.9.10 → thoughtleaders_cli-0.9.12}/src/tl_cli/commands/__init__.py +0 -0
  93. {thoughtleaders_cli-0.9.10 → thoughtleaders_cli-0.9.12}/src/tl_cli/commands/_comments_common.py +0 -0
  94. {thoughtleaders_cli-0.9.10 → thoughtleaders_cli-0.9.12}/src/tl_cli/commands/balance.py +0 -0
  95. {thoughtleaders_cli-0.9.10 → thoughtleaders_cli-0.9.12}/src/tl_cli/commands/brands.py +0 -0
  96. {thoughtleaders_cli-0.9.10 → thoughtleaders_cli-0.9.12}/src/tl_cli/commands/bulk_import.py +0 -0
  97. {thoughtleaders_cli-0.9.10 → thoughtleaders_cli-0.9.12}/src/tl_cli/commands/changelog.py +0 -0
  98. {thoughtleaders_cli-0.9.10 → thoughtleaders_cli-0.9.12}/src/tl_cli/commands/channels.py +0 -0
  99. {thoughtleaders_cli-0.9.10 → thoughtleaders_cli-0.9.12}/src/tl_cli/commands/credits.py +0 -0
  100. {thoughtleaders_cli-0.9.10 → thoughtleaders_cli-0.9.12}/src/tl_cli/commands/db.py +0 -0
  101. {thoughtleaders_cli-0.9.10 → thoughtleaders_cli-0.9.12}/src/tl_cli/commands/deals.py +0 -0
  102. {thoughtleaders_cli-0.9.10 → thoughtleaders_cli-0.9.12}/src/tl_cli/commands/describe.py +0 -0
  103. {thoughtleaders_cli-0.9.10 → thoughtleaders_cli-0.9.12}/src/tl_cli/commands/doctor.py +0 -0
  104. {thoughtleaders_cli-0.9.10 → thoughtleaders_cli-0.9.12}/src/tl_cli/commands/matches.py +0 -0
  105. {thoughtleaders_cli-0.9.10 → thoughtleaders_cli-0.9.12}/src/tl_cli/commands/memory.py +0 -0
  106. {thoughtleaders_cli-0.9.10 → thoughtleaders_cli-0.9.12}/src/tl_cli/commands/profiles.py +0 -0
  107. {thoughtleaders_cli-0.9.10 → thoughtleaders_cli-0.9.12}/src/tl_cli/commands/proposals.py +0 -0
  108. {thoughtleaders_cli-0.9.10 → thoughtleaders_cli-0.9.12}/src/tl_cli/commands/recommender.py +0 -0
  109. {thoughtleaders_cli-0.9.10 → thoughtleaders_cli-0.9.12}/src/tl_cli/commands/reports.py +0 -0
  110. {thoughtleaders_cli-0.9.10 → thoughtleaders_cli-0.9.12}/src/tl_cli/commands/schema.py +0 -0
  111. {thoughtleaders_cli-0.9.10 → thoughtleaders_cli-0.9.12}/src/tl_cli/commands/setup.py +0 -0
  112. {thoughtleaders_cli-0.9.10 → thoughtleaders_cli-0.9.12}/src/tl_cli/commands/skills.py +0 -0
  113. {thoughtleaders_cli-0.9.10 → thoughtleaders_cli-0.9.12}/src/tl_cli/commands/snapshots.py +0 -0
  114. {thoughtleaders_cli-0.9.10 → thoughtleaders_cli-0.9.12}/src/tl_cli/commands/sponsorships.py +0 -0
  115. {thoughtleaders_cli-0.9.10 → thoughtleaders_cli-0.9.12}/src/tl_cli/commands/uploads.py +0 -0
  116. {thoughtleaders_cli-0.9.10 → thoughtleaders_cli-0.9.12}/src/tl_cli/commands/whoami.py +0 -0
  117. {thoughtleaders_cli-0.9.10 → thoughtleaders_cli-0.9.12}/src/tl_cli/commands/workflows.py +0 -0
  118. {thoughtleaders_cli-0.9.10 → thoughtleaders_cli-0.9.12}/src/tl_cli/config.py +0 -0
  119. {thoughtleaders_cli-0.9.10 → thoughtleaders_cli-0.9.12}/src/tl_cli/filters.py +0 -0
  120. {thoughtleaders_cli-0.9.10 → thoughtleaders_cli-0.9.12}/src/tl_cli/hints.py +0 -0
  121. {thoughtleaders_cli-0.9.10 → thoughtleaders_cli-0.9.12}/src/tl_cli/main.py +0 -0
  122. {thoughtleaders_cli-0.9.10 → thoughtleaders_cli-0.9.12}/src/tl_cli/output/__init__.py +0 -0
  123. {thoughtleaders_cli-0.9.10 → thoughtleaders_cli-0.9.12}/src/tl_cli/query_history.py +0 -0
  124. {thoughtleaders_cli-0.9.10 → thoughtleaders_cli-0.9.12}/src/tl_cli/self_update.py +0 -0
  125. {thoughtleaders_cli-0.9.10 → thoughtleaders_cli-0.9.12}/src/tl_cli/skill_registry.py +0 -0
  126. {thoughtleaders_cli-0.9.10 → thoughtleaders_cli-0.9.12}/tests/__init__.py +0 -0
  127. {thoughtleaders_cli-0.9.10 → thoughtleaders_cli-0.9.12}/tests/test_auth.py +0 -0
  128. {thoughtleaders_cli-0.9.10 → thoughtleaders_cli-0.9.12}/tests/test_brands_winner_channels.py +0 -0
  129. {thoughtleaders_cli-0.9.10 → thoughtleaders_cli-0.9.12}/tests/test_build_report.py +0 -0
  130. {thoughtleaders_cli-0.9.10 → thoughtleaders_cli-0.9.12}/tests/test_channels_lookalike.py +0 -0
  131. {thoughtleaders_cli-0.9.10 → thoughtleaders_cli-0.9.12}/tests/test_db_repeat_warning.py +0 -0
  132. {thoughtleaders_cli-0.9.10 → thoughtleaders_cli-0.9.12}/tests/test_describe.py +0 -0
  133. {thoughtleaders_cli-0.9.10 → thoughtleaders_cli-0.9.12}/tests/test_error_hints.py +0 -0
  134. {thoughtleaders_cli-0.9.10 → thoughtleaders_cli-0.9.12}/tests/test_expand_entities.py +0 -0
  135. {thoughtleaders_cli-0.9.10 → thoughtleaders_cli-0.9.12}/tests/test_filters.py +0 -0
  136. {thoughtleaders_cli-0.9.10 → thoughtleaders_cli-0.9.12}/tests/test_http_auth.py +0 -0
  137. {thoughtleaders_cli-0.9.10 → thoughtleaders_cli-0.9.12}/tests/test_memory.py +0 -0
  138. {thoughtleaders_cli-0.9.10 → thoughtleaders_cli-0.9.12}/tests/test_output.py +0 -0
  139. {thoughtleaders_cli-0.9.10 → thoughtleaders_cli-0.9.12}/tests/test_probe.py +0 -0
  140. {thoughtleaders_cli-0.9.10 → thoughtleaders_cli-0.9.12}/tests/test_profiles.py +0 -0
  141. {thoughtleaders_cli-0.9.10 → thoughtleaders_cli-0.9.12}/tests/test_quota_refusal_message.py +0 -0
  142. {thoughtleaders_cli-0.9.10 → thoughtleaders_cli-0.9.12}/tests/test_refusal_rendering.py +0 -0
  143. {thoughtleaders_cli-0.9.10 → thoughtleaders_cli-0.9.12}/tests/test_reports.py +0 -0
  144. {thoughtleaders_cli-0.9.10 → thoughtleaders_cli-0.9.12}/tests/test_scripts_executable.py +0 -0
  145. {thoughtleaders_cli-0.9.10 → thoughtleaders_cli-0.9.12}/tests/test_search_channels.py +0 -0
  146. {thoughtleaders_cli-0.9.10 → thoughtleaders_cli-0.9.12}/tests/test_search_videos.py +0 -0
  147. {thoughtleaders_cli-0.9.10 → thoughtleaders_cli-0.9.12}/tests/test_select_keywords.py +0 -0
  148. {thoughtleaders_cli-0.9.10 → thoughtleaders_cli-0.9.12}/tests/test_setup.py +0 -0
  149. {thoughtleaders_cli-0.9.10 → thoughtleaders_cli-0.9.12}/tests/test_setup_marker_respect.py +0 -0
  150. {thoughtleaders_cli-0.9.10 → thoughtleaders_cli-0.9.12}/tests/test_skill_registry.py +0 -0
  151. {thoughtleaders_cli-0.9.10 → thoughtleaders_cli-0.9.12}/tests/test_skills_command.py +0 -0
  152. {thoughtleaders_cli-0.9.10 → thoughtleaders_cli-0.9.12}/tests/test_sponsorships.py +0 -0
  153. {thoughtleaders_cli-0.9.10 → thoughtleaders_cli-0.9.12}/tests/test_whoami_newsletter.py +0 -0
  154. {thoughtleaders_cli-0.9.10 → thoughtleaders_cli-0.9.12}/tests/test_workflows.py +0 -0
  155. {thoughtleaders_cli-0.9.10 → thoughtleaders_cli-0.9.12}/tests_cli/AGENTS.md +0 -0
  156. {thoughtleaders_cli-0.9.10 → thoughtleaders_cli-0.9.12}/tests_cli/conftest.py +0 -0
  157. {thoughtleaders_cli-0.9.10 → thoughtleaders_cli-0.9.12}/tests_cli/test_balance.py +0 -0
  158. {thoughtleaders_cli-0.9.10 → thoughtleaders_cli-0.9.12}/tests_cli/test_db_es.py +0 -0
  159. {thoughtleaders_cli-0.9.10 → thoughtleaders_cli-0.9.12}/tests_cli/test_db_fb.py +0 -0
  160. {thoughtleaders_cli-0.9.10 → thoughtleaders_cli-0.9.12}/tests_cli/test_db_pg.py +0 -0
  161. {thoughtleaders_cli-0.9.10 → thoughtleaders_cli-0.9.12}/tests_cli/test_schema.py +0 -0
  162. {thoughtleaders_cli-0.9.10 → thoughtleaders_cli-0.9.12}/tests_cli/test_whoami.py +0 -0
  163. {thoughtleaders_cli-0.9.10 → thoughtleaders_cli-0.9.12}/uv.lock +0 -0
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tl-cli",
3
- "version": "0.9.10",
3
+ "version": "0.9.12",
4
4
  "description": "ThoughtLeaders CLI — query sponsorship deals, channels, brands, uploads, and intelligence from the terminal",
5
5
  "author": {
6
6
  "name": "ThoughtLeaders",
@@ -88,10 +88,12 @@ The version string is defined in three files and all three must be updated toget
88
88
 
89
89
  ## Creating a release
90
90
 
91
- A "release" means using the `gh` command to create a release on GitHub, named like the current package version number.
91
+ A "release" means using the `gh` command to create a release on GitHub, tagged and titled `v<version>` (e.g. `v0.9.11`). The `v` prefix is mandatory: the PyPI publish workflow only runs for `v*` tags, and a release without it fails with an environment protection rule error.
92
92
 
93
93
  Warn the user if they are creating a release and the latest commit didn't bump the version number, and ask for confirmation before releasing.
94
94
 
95
+ Release notes are written by hand for the user, never with `--generate-notes` (that yields only a compare link). Follow the style of previous releases: a `##` heading naming the change from the user's perspective, a short prose explanation of what changed and why it matters, a usage example where one helps, and a closing line on what the user has to do (e.g. `tl setup claude` to pick up skill changes, or nothing). Describe user-visible behaviour only — same rules as commit messages and skills apply, so no internal architecture or server details.
96
+
95
97
  ## Coding
96
98
 
97
99
  * Do not reference internal architecture of the ThoughtLeaders app in comments or skills. Specifially: do not reference internal table names, field names, API endpoints, Python modules or functions (including the sanitizer).
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: thoughtleaders-cli
3
- Version: 0.9.10
3
+ Version: 0.9.12
4
4
  Summary: ThoughtLeaders CLI — query sponsorship data, channels, brands, and intelligence
5
5
  Project-URL: Homepage, https://thoughtleaders.io
6
6
  Project-URL: Repository, https://github.com/ThoughtLeaders-io/thoughtleaders-cli
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "thoughtleaders-cli"
7
- version = "0.9.10"
7
+ version = "0.9.12"
8
8
  description = "ThoughtLeaders CLI — query sponsorship data, channels, brands, and intelligence"
9
9
  readme = "README.md"
10
10
  license = "MIT"
@@ -88,11 +88,11 @@ Other key concepts:
88
88
  - **Adspots** — types of ads a channel is willing to publish (e.g. mention, dedicated video, product placement). Returned by `tl channels show`; each carries price/cost.
89
89
  - **Profiles** — actors that own sponsorship records on behalf of either side of a deal. A profile is either buyer-side or seller-side:
90
90
  - *Buyer-side (brand) profiles* — represent a sponsoring brand. Each brand profile has an M2M link to at most one `Brand` record (which are the actual advertiser identities). On a sponsorship, `advertiser_profile` is the buyer-side profile, and `advertiser_id` is the buyer-side user who created the record — the advertiser is always the buyer/brand side, never the YouTube creator (the channel hangs off `ad_spot_id`).
91
- - *Seller-side (publisher) profiles* — attached to a `Publication`, which in turn owns one or more `Channel` records. A channel's adspots therefore inherit ownership through `channel.publication.profile`.
91
+ - *Seller-side (publisher) profiles* — represent one or more `Channel` records through the `thoughtleaders_profile_channels` link. Representation is not deal ownership: each adspot names its own seller (`ad_spot.publisher`, a user), so a channel's deals belong to whoever sold them, not to everyone who represents the channel.
92
92
  - **How to tell them apart** — three signals on the `thoughtleaders_profile` row, used in this order:
93
93
  1. **`persona`** (canonical) — `1=Brand`, `4=Media Agency`, `3=Talent Manager` are buyer-side; `2=Creator`, `5=Creator Service` are seller-side. May be null on legacy rows.
94
94
  2. **`is_advertiser` / `is_publisher`** booleans — feature flags; either or both can be true for staff-style profiles, but on normal user profiles they reliably mark side.
95
- - Org scoping for sponsorships is profile-mediated: a sponsorship belongs to your org if **either** `advertiser_profile.organization` (brand side) **or** `ad_spot.channel.publication.profile.organization` (publisher side) matches yours.
95
+ - Org scoping for sponsorships is profile-mediated: a sponsorship belongs to your org if **either** `advertiser_profile.organization` (brand side) **or** the adspot seller's organization — `ad_spot.publisher` → that user's profile → `organization` (publisher side) matches yours. Representing the channel does not by itself surface its deals; only a `sees_all_deals` link on `thoughtleaders_profile_channels` widens the publisher side to every deal on that channel.
96
96
  - **MSN** (Media Selling Network) — the ~12k YouTube channels that have opted in to receive sponsorship offers. A channels is in the MSN group if the `channel.media_selling_network_join_date` field is not null.
97
97
  - **MBN** (Media Buying Network) — the brand-side counterpart to MSN: brand profiles that have opted in to receive proposed sponsorships. A profile is in the MBN group if the `profile.media_buying_network_join_date` field is not null.
98
98
  - **TPP** (ThoughtLeaders Partner Program, a.k.a. "TL channels") — the ~170 channels TL has the closest working relationship with. A channel is in the TPP group if `channel.is_tpp` is True. **Prefer TPP channels when booking**: they respond fastest, are the easiest to close, and don't need an outreach round-trip — treat them as immediately bookable. TPP is a strict subset of MSN, so the same booking rules (one active mention adspot, etc.) apply.
@@ -521,7 +521,6 @@ If unsure about what information to find where, read the [references/postgresql-
521
521
  - `Postgres channel.id` ↔ `ES channel.id` (on article docs) ↔ `Firebolt article_metrics.channel_id` / `channel_metrics.id`
522
522
  - `Postgres adlink.article_id` is `<channel_id>:<youtube_id>` — same as ES `_id`. Strip the prefix to get `Firebolt article_metrics.id`.
523
523
  - `Postgres brand.id` ↔ ES `sponsored_brand_mentions[]` / `organic_brand_mentions[]`.
524
- - `publication_id` is **deprecated** — don't use it.
525
524
 
526
525
  **Snapshots are sparse**, especially for older videos. Don't assume two arbitrary dates have data points. For approximations, prefer `tl snapshots` which already implements the project's interpolation logic; falling back to raw `tl db fb` means you handle gaps yourself.
527
526
 
@@ -59,7 +59,7 @@ Filter with `{"term": {"doc_type": "article"}}`. Coverage percentages are live `
59
59
  | `content_type` | keyword | `longform` / `short` / `live` — the complete value set. ~71% of docs; older docs have none (missing ≠ longform). Podcast/RSS docs have no `content_type`. |
60
60
  | `content_aspects` | keyword | Flags: `podcast`, `paid_promotion`, `unlisted` — the complete value set. Only ~2.6% of docs carry any. |
61
61
  | `hashtags` | keyword | Hashtags from the video description, stored **without the leading `#`** and lowercase (e.g. `marchmadness`); non-Latin tags appear percent-encoded (`%D0%B0…`) (~32%) |
62
- | `channel` | object | Embedded channel subset: `channel.id`, `channel.content_category`, `channel.format`, `channel.publication_id`, `channel.country`, `channel.language` — no text fields, no metrics. This is where a video's language/country/format/category live (top-level `language`, `country`, `format`, `content_category` exist only on channel docs). |
62
+ | `channel` | object | Embedded channel subset: `channel.id`, `channel.content_category`, `channel.format`, `channel.country`, `channel.language` — no text fields, no metrics. This is where a video's language/country/format/category live (top-level `language`, `country`, `format`, `content_category` exist only on channel docs). |
63
63
 
64
64
  ⚠️ **Channel-doc fields that look like video fields but match 0 video docs:** `total_views`, `engagement`, `duration_live`/`duration_longform`/`duration_shorts`, `language`, `country`, `format`, `content_category`, `face_on_screen`. They live on channel docs (see below); on video docs use the embedded `channel.*` subset where available.
65
65
 
@@ -108,7 +108,8 @@ Contains a denormalized subset of the PostgreSQL channel data.
108
108
  | `media_selling_network_join_date` | date | MSN join date; non-null = MSN member (~1%) |
109
109
  | `has_outreach_email` | boolean | Has contact email (100%) |
110
110
  | `outreach_email` | text | Contact email (~45%) |
111
- | `social_links` | text | Flat array of the channel's profile URLs (~47%), e.g. `["https://twitter.com/…", "https://instagram.com/…", "https://discord.gg/…"]`. Source is a per-platform map plus a catch-all `_other` map for unrecognized platforms; in ES all of it is flattened into this one URL array (the `_other` URLs are folded in, the platform names are dropped). Occasional stray entries (bare emails, nested arrays) exist. |
111
+ | `social_links` | text | Flat array of the channel's known profile links as **canonical keys** — lowercase `host/path` with no scheme, no `www.`, no query string, and `x.com` spelled as `twitter.com`, e.g. `["twitter.com/mrbeast", "instagram.com/mrbeast", "linktr.ee/foo"]` (~47%, growing). Sourced from the `all_social_links` accumulator (About-page scrapes plus web-search discoveries); platform names are dropped, e-mails never appear. |
112
+ | `social_links.canonical` | text | Subfield of the above with a path-segment analyzer: one token per URL segment, subdomain-insensitive host. `{"match_phrase": {"social_links.canonical": "twitch.tv/ludwig"}}` is the precise way to ask "which channels carry exactly this profile link" — it matches `m.twitch.tv/ludwig` and deep paths under the profile, but never a channel that merely mentions the same words in different links. Prefer it over matching the parent field when the query is a `domain/handle` pair. |
112
113
  | `male_share` | byte | Male audience % — only ~1.6% of channel docs have demographic data |
113
114
  | `usa_share` | byte | US audience % — same ~1.6% coverage |
114
115
  | `device` | object | Audience device demographics where known: `device.primary` (most common device) and `device.share` (per-device % map). Very sparse (~0.2%). |
@@ -282,5 +283,4 @@ The `transcript` field's `_source` is **YouTube timed-text caption XML**, not pl
282
283
  - `sponsored_brand_mentions` and `organic_brand_mentions` are keyword arrays — use `term` queries.
283
284
  - For brand mention details (position, snippet, detection_tool), the data is in the `brand_mentions` nested field.
284
285
  - **Stored-only fields** — retrievable in `_source` but invisible to `exists`/`term`/`match` (queries on them silently match 0 docs): `url`, `image_url`, `es_index_tag`, `not_sponsored_by`.
285
- - **`publication_id` is deprecated** — don't use for joins.
286
286
  - No write access. The CLI only exposes `_search` against `tl-platform-*`.
@@ -353,13 +353,18 @@ LIMIT 50 OFFSET 0
353
353
 
354
354
  ## `thoughtleaders_profile_channels` (Profile ↔ Channel M2M)
355
355
 
356
- | Column | Type |
357
- |--------|------|
358
- | `id` | int PK |
359
- | `profile_id` | int FK |
360
- | `channel_id` | int FK |
356
+ Which channels a seller-side profile represents. One row per profile/channel pair.
361
357
 
362
- Note: separate from the adspot publisher relationship. Not always in sync.
358
+ | Column | Type | Description |
359
+ |--------|------|-------------|
360
+ | `id` | int PK | |
361
+ | `profile_id` | int FK | → `thoughtleaders_profile.id` |
362
+ | `channel_id` | int FK | → `thoughtleaders_channel.id` |
363
+ | `sees_all_deals` | boolean | When true, the profile's organization sees **every** deal on the channel, not only the deals it sold itself. Absent from the sandbox views, so only a full-access context can read it. |
364
+ | `created_where` | varchar | What created the link. NULL on every link that predates the column. |
365
+ | `created_at` | timestamptz | When the link was created. NULL on every link that predates the column — filtering or ordering on it silently drops that whole population. |
366
+
367
+ ⚠️ **Representation is not deal ownership.** A deal's seller is the adspot's own publisher (`thoughtleaders_adspot.publisher_id` → `auth_user`, then `thoughtleaders_profile.user_id` for the org). Joining sponsorships to an org through this table alone over-reports — only a `sees_all_deals = true` row widens the seller side to all of a channel's deals. `publisher_id` is scrubbed from the sandbox adspot view, so the seller-side hop is only queryable from a full-access role.
363
368
 
364
369
  ## Example queries
365
370
 
@@ -362,18 +362,6 @@
362
362
  "uniqueItems": true,
363
363
  "description": "Article IDs to exclude (composite `<channel_id>:<youtube_id>` form). Pairs with a predicate-style FilterSet — useful for 'videos matching X, except these specific ones'.",
364
364
  "_tl_django_m2m": "FilterSet.exclude_articles via FiltersetExcludeArticles"
365
- },
366
-
367
- "networks": {
368
- "type": ["array", "null"],
369
- "items": { "type": "integer", "minimum": 1 },
370
- "uniqueItems": true,
371
- "_tl_django_m2m": "FilterSet.networks → thoughtleaders.Publication"
372
- },
373
- "exclude_networks": {
374
- "type": ["array", "null"],
375
- "items": { "type": "integer", "minimum": 1 },
376
- "uniqueItems": true
377
365
  }
378
366
  },
379
367
 
@@ -58,18 +58,6 @@
58
58
  "_tl_django_m2m": "FilterSet.exclude_brands via FilterSetExcludeBrand"
59
59
  },
60
60
 
61
- "networks": {
62
- "type": ["array", "null"],
63
- "items": { "type": "integer", "minimum": 1 },
64
- "uniqueItems": true,
65
- "_tl_django_m2m": "FilterSet.networks → thoughtleaders.Publication"
66
- },
67
- "exclude_networks": {
68
- "type": ["array", "null"],
69
- "items": { "type": "integer", "minimum": 1 },
70
- "uniqueItems": true
71
- },
72
-
73
61
  "start_date": {
74
62
  "type": ["string", "null"],
75
63
  "format": "date",
@@ -1,3 +1,3 @@
1
1
  """ThoughtLeaders CLI — query sponsorship data, channels, brands, and intelligence."""
2
2
 
3
- __version__ = "0.9.10"
3
+ __version__ = "0.9.12"
@@ -215,7 +215,7 @@ def _detect_numeric_columns(results: list[dict], columns: list[str]) -> set[str]
215
215
  numeric.discard(col)
216
216
  # Don't treat ID-like columns as numeric
217
217
  for col in list(numeric):
218
- if col.endswith("_id") or col == "id" or "publication" in col:
218
+ if col.endswith("_id") or col == "id":
219
219
  numeric.discard(col)
220
220
  # Columns where every sampled value was None/empty aren't meaningfully numeric
221
221
  for col in list(numeric):