affinity-sdk 0.4.7__tar.gz → 0.9.2__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 (388) hide show
  1. affinity_sdk-0.9.2/.claude-plugin/marketplace.json +26 -0
  2. affinity_sdk-0.9.2/.github/PULL_REQUEST_TEMPLATE/release.md +31 -0
  3. affinity_sdk-0.9.2/.github/workflows/ci.yml +134 -0
  4. {affinity_sdk-0.4.7 → affinity_sdk-0.9.2}/.github/workflows/docs.yml +9 -5
  5. {affinity_sdk-0.4.7 → affinity_sdk-0.9.2}/.github/workflows/labels.yml +1 -1
  6. {affinity_sdk-0.4.7 → affinity_sdk-0.9.2}/.github/workflows/linkcheck.yml +2 -2
  7. {affinity_sdk-0.4.7 → affinity_sdk-0.9.2}/.github/workflows/openapi-validation.yml +2 -2
  8. affinity_sdk-0.9.2/.github/workflows/plugin-build.yml +106 -0
  9. affinity_sdk-0.9.2/.github/workflows/plugin-release.yml +152 -0
  10. affinity_sdk-0.9.2/.github/workflows/release-detect.yml +98 -0
  11. affinity_sdk-0.9.2/.github/workflows/release.yml +282 -0
  12. affinity_sdk-0.9.2/.github/workflows/version-check.yml +92 -0
  13. {affinity_sdk-0.4.7 → affinity_sdk-0.9.2}/.gitignore +2 -0
  14. {affinity_sdk-0.4.7 → affinity_sdk-0.9.2}/.pre-commit-config.yaml +16 -3
  15. affinity_sdk-0.9.2/CHANGELOG.md +367 -0
  16. {affinity_sdk-0.4.7 → affinity_sdk-0.9.2}/CONTRIBUTING.md +61 -7
  17. {affinity_sdk-0.4.7 → affinity_sdk-0.9.2}/PKG-INFO +53 -15
  18. {affinity_sdk-0.4.7 → affinity_sdk-0.9.2}/README.md +49 -11
  19. affinity_sdk-0.9.2/VERSIONING.md +175 -0
  20. {affinity_sdk-0.4.7 → affinity_sdk-0.9.2}/affinity/__init__.py +2 -0
  21. {affinity_sdk-0.4.7 → affinity_sdk-0.9.2}/affinity/cli/commands/_entity_files_dump.py +3 -0
  22. {affinity_sdk-0.4.7 → affinity_sdk-0.9.2}/affinity/cli/commands/_v1_parsing.py +28 -3
  23. {affinity_sdk-0.4.7 → affinity_sdk-0.9.2}/affinity/cli/commands/company_cmds.py +587 -548
  24. {affinity_sdk-0.4.7 → affinity_sdk-0.9.2}/affinity/cli/commands/completion_cmd.py +2 -0
  25. {affinity_sdk-0.4.7 → affinity_sdk-0.9.2}/affinity/cli/commands/config_cmds.py +69 -34
  26. affinity_sdk-0.9.2/affinity/cli/commands/entry_cmds.py +33 -0
  27. affinity_sdk-0.9.2/affinity/cli/commands/field_cmds.py +413 -0
  28. affinity_sdk-0.9.2/affinity/cli/commands/interaction_cmds.py +875 -0
  29. {affinity_sdk-0.4.7 → affinity_sdk-0.9.2}/affinity/cli/commands/list_cmds.py +832 -412
  30. {affinity_sdk-0.4.7 → affinity_sdk-0.9.2}/affinity/cli/commands/note_cmds.py +144 -27
  31. {affinity_sdk-0.4.7 → affinity_sdk-0.9.2}/affinity/cli/commands/opportunity_cmds.py +396 -367
  32. {affinity_sdk-0.4.7 → affinity_sdk-0.9.2}/affinity/cli/commands/person_cmds.py +597 -548
  33. affinity_sdk-0.9.2/affinity/cli/commands/query_cmd.py +429 -0
  34. {affinity_sdk-0.4.7 → affinity_sdk-0.9.2}/affinity/cli/commands/relationship_strength_cmds.py +23 -5
  35. {affinity_sdk-0.4.7 → affinity_sdk-0.9.2}/affinity/cli/commands/reminder_cmds.py +184 -39
  36. {affinity_sdk-0.4.7 → affinity_sdk-0.9.2}/affinity/cli/commands/resolve_url_cmd.py +3 -1
  37. affinity_sdk-0.9.2/affinity/cli/commands/session_cmds.py +84 -0
  38. {affinity_sdk-0.4.7 → affinity_sdk-0.9.2}/affinity/cli/commands/task_cmds.py +31 -4
  39. {affinity_sdk-0.4.7 → affinity_sdk-0.9.2}/affinity/cli/commands/version_cmd.py +2 -0
  40. {affinity_sdk-0.4.7 → affinity_sdk-0.9.2}/affinity/cli/commands/whoami_cmd.py +11 -0
  41. {affinity_sdk-0.4.7 → affinity_sdk-0.9.2}/affinity/cli/context.py +32 -2
  42. {affinity_sdk-0.4.7 → affinity_sdk-0.9.2}/affinity/cli/csv_utils.py +85 -0
  43. affinity_sdk-0.9.2/affinity/cli/date_utils.py +42 -0
  44. affinity_sdk-0.9.2/affinity/cli/decorators.py +77 -0
  45. affinity_sdk-0.9.2/affinity/cli/help_json.py +283 -0
  46. {affinity_sdk-0.4.7 → affinity_sdk-0.9.2}/affinity/cli/main.py +94 -17
  47. affinity_sdk-0.9.2/affinity/cli/progress.py +183 -0
  48. affinity_sdk-0.9.2/affinity/cli/query/__init__.py +163 -0
  49. affinity_sdk-0.9.2/affinity/cli/query/aggregates.py +357 -0
  50. affinity_sdk-0.9.2/affinity/cli/query/dates.py +194 -0
  51. affinity_sdk-0.9.2/affinity/cli/query/exceptions.py +147 -0
  52. affinity_sdk-0.9.2/affinity/cli/query/executor.py +1222 -0
  53. affinity_sdk-0.9.2/affinity/cli/query/filters.py +330 -0
  54. affinity_sdk-0.9.2/affinity/cli/query/models.py +333 -0
  55. affinity_sdk-0.9.2/affinity/cli/query/output.py +271 -0
  56. affinity_sdk-0.9.2/affinity/cli/query/parser.py +617 -0
  57. affinity_sdk-0.9.2/affinity/cli/query/planner.py +430 -0
  58. affinity_sdk-0.9.2/affinity/cli/query/progress.py +270 -0
  59. affinity_sdk-0.9.2/affinity/cli/query/schema.py +439 -0
  60. {affinity_sdk-0.4.7 → affinity_sdk-0.9.2}/affinity/cli/render.py +440 -45
  61. affinity_sdk-0.9.2/affinity/cli/resolve.py +222 -0
  62. affinity_sdk-0.9.2/affinity/cli/results.py +308 -0
  63. {affinity_sdk-0.4.7 → affinity_sdk-0.9.2}/affinity/cli/runner.py +14 -3
  64. affinity_sdk-0.9.2/affinity/cli/session_cache.py +276 -0
  65. {affinity_sdk-0.4.7 → affinity_sdk-0.9.2}/affinity/client.py +4 -2
  66. {affinity_sdk-0.4.7 → affinity_sdk-0.9.2}/affinity/clients/http.py +1 -1
  67. {affinity_sdk-0.4.7 → affinity_sdk-0.9.2}/affinity/exceptions.py +22 -0
  68. {affinity_sdk-0.4.7 → affinity_sdk-0.9.2}/affinity/filters.py +5 -1
  69. {affinity_sdk-0.4.7 → affinity_sdk-0.9.2}/affinity/inbound_webhooks.py +7 -0
  70. {affinity_sdk-0.4.7 → affinity_sdk-0.9.2}/affinity/models/entities.py +5 -0
  71. {affinity_sdk-0.4.7 → affinity_sdk-0.9.2}/affinity/models/pagination.py +19 -1
  72. {affinity_sdk-0.4.7 → affinity_sdk-0.9.2}/affinity/models/types.py +42 -6
  73. {affinity_sdk-0.4.7 → affinity_sdk-0.9.2}/affinity/services/companies.py +103 -9
  74. {affinity_sdk-0.4.7 → affinity_sdk-0.9.2}/affinity/services/lists.py +181 -41
  75. {affinity_sdk-0.4.7 → affinity_sdk-0.9.2}/affinity/services/opportunities.py +254 -17
  76. {affinity_sdk-0.4.7 → affinity_sdk-0.9.2}/affinity/services/persons.py +203 -9
  77. {affinity_sdk-0.4.7 → affinity_sdk-0.9.2}/affinity/services/v1_only.py +17 -0
  78. affinity_sdk-0.9.2/docs/public/ai-integrations/index.md +77 -0
  79. {affinity_sdk-0.4.7 → affinity_sdk-0.9.2}/docs/public/cli/commands.md +212 -97
  80. {affinity_sdk-0.4.7 → affinity_sdk-0.9.2}/docs/public/cli/index.md +30 -0
  81. affinity_sdk-0.9.2/docs/public/cli/scripting.md +151 -0
  82. {affinity_sdk-0.4.7 → affinity_sdk-0.9.2}/docs/public/cli-reference.md +44 -6
  83. {affinity_sdk-0.4.7 → affinity_sdk-0.9.2}/docs/public/getting-started.md +1 -1
  84. affinity_sdk-0.9.2/docs/public/guides/claude-code-plugins.md +148 -0
  85. {affinity_sdk-0.4.7 → affinity_sdk-0.9.2}/docs/public/guides/csv-export.md +51 -32
  86. affinity_sdk-0.9.2/docs/public/guides/datetime-handling.md +100 -0
  87. {affinity_sdk-0.4.7 → affinity_sdk-0.9.2}/docs/public/guides/filtering.md +1 -1
  88. {affinity_sdk-0.4.7 → affinity_sdk-0.9.2}/docs/public/guides/performance.md +12 -0
  89. affinity_sdk-0.9.2/docs/public/guides/query-command.md +452 -0
  90. {affinity_sdk-0.4.7 → affinity_sdk-0.9.2}/docs/public/index.md +1 -0
  91. affinity_sdk-0.9.2/docs/public/mcp/index.md +376 -0
  92. affinity_sdk-0.9.2/docs/public/reference/query-language.md +463 -0
  93. affinity_sdk-0.9.2/mcp/.claude-plugin/.gitignore +14 -0
  94. affinity_sdk-0.9.2/mcp/.claude-plugin/.mcp.json +6 -0
  95. affinity_sdk-0.9.2/mcp/.claude-plugin/plugin.json +26 -0
  96. affinity_sdk-0.9.2/mcp/.claude-plugin/skills/affinity-mcp-workflows/SKILL.md +216 -0
  97. affinity_sdk-0.9.2/mcp/.claude-plugin/skills/query-language/SKILL.md +381 -0
  98. affinity_sdk-0.9.2/mcp/.claude-plugin/xaffinity-mcp.sh +107 -0
  99. affinity_sdk-0.9.2/mcp/.gitignore +22 -0
  100. affinity_sdk-0.9.2/mcp/.registry/commands-metadata.json +99 -0
  101. affinity_sdk-0.9.2/mcp/.registry/commands.json +3010 -0
  102. affinity_sdk-0.9.2/mcp/.registry/prompts.json +253 -0
  103. affinity_sdk-0.9.2/mcp/.registry/resource-templates.json +30 -0
  104. affinity_sdk-0.9.2/mcp/.registry/resources.json +41 -0
  105. affinity_sdk-0.9.2/mcp/CHANGELOG.md +301 -0
  106. affinity_sdk-0.9.2/mcp/COMPATIBILITY +31 -0
  107. affinity_sdk-0.9.2/mcp/Makefile +120 -0
  108. affinity_sdk-0.9.2/mcp/README.md +243 -0
  109. affinity_sdk-0.9.2/mcp/VERSION +1 -0
  110. affinity_sdk-0.9.2/mcp/completions/entity-name.sh +51 -0
  111. affinity_sdk-0.9.2/mcp/completions/list-name.sh +42 -0
  112. affinity_sdk-0.9.2/mcp/completions/status-value.sh +46 -0
  113. affinity_sdk-0.9.2/mcp/docs/DEBUGGING.md +151 -0
  114. affinity_sdk-0.9.2/mcp/docs/internal/debugging-improvements-plan.md +375 -0
  115. affinity_sdk-0.9.2/mcp/docs/internal/mcp-bash-progress-timeout-feature-request.md +215 -0
  116. affinity_sdk-0.9.2/mcp/icon.svg +19 -0
  117. affinity_sdk-0.9.2/mcp/lib/cache.sh +124 -0
  118. affinity_sdk-0.9.2/mcp/lib/cli-gateway.sh +451 -0
  119. affinity_sdk-0.9.2/mcp/lib/common.sh +453 -0
  120. affinity_sdk-0.9.2/mcp/lib/entity-types.sh +84 -0
  121. affinity_sdk-0.9.2/mcp/lib/field-resolution.sh +124 -0
  122. affinity_sdk-0.9.2/mcp/mcp-bash.lock +5 -0
  123. affinity_sdk-0.9.2/mcp/mcpb.conf +24 -0
  124. affinity_sdk-0.9.2/mcp/prompts/change-status/change-status.meta.json +26 -0
  125. affinity_sdk-0.9.2/mcp/prompts/change-status/change-status.txt +13 -0
  126. affinity_sdk-0.9.2/mcp/prompts/interaction-brief/interaction-brief.meta.json +19 -0
  127. affinity_sdk-0.9.2/mcp/prompts/interaction-brief/interaction-brief.txt +13 -0
  128. affinity_sdk-0.9.2/mcp/prompts/log-call/log-call.meta.json +32 -0
  129. affinity_sdk-0.9.2/mcp/prompts/log-call/log-call.txt +16 -0
  130. affinity_sdk-0.9.2/mcp/prompts/log-interaction-and-update-workflow/log-interaction-and-update-workflow.meta.json +27 -0
  131. affinity_sdk-0.9.2/mcp/prompts/log-interaction-and-update-workflow/log-interaction-and-update-workflow.txt +16 -0
  132. affinity_sdk-0.9.2/mcp/prompts/log-message/log-message.meta.json +33 -0
  133. affinity_sdk-0.9.2/mcp/prompts/log-message/log-message.txt +16 -0
  134. affinity_sdk-0.9.2/mcp/prompts/pipeline-review/pipeline-review.meta.json +14 -0
  135. affinity_sdk-0.9.2/mcp/prompts/pipeline-review/pipeline-review.txt +17 -0
  136. affinity_sdk-0.9.2/mcp/prompts/prepare-briefing/prepare-briefing.meta.json +19 -0
  137. affinity_sdk-0.9.2/mcp/prompts/prepare-briefing/prepare-briefing.txt +16 -0
  138. affinity_sdk-0.9.2/mcp/prompts/warm-intro/warm-intro.meta.json +18 -0
  139. affinity_sdk-0.9.2/mcp/prompts/warm-intro/warm-intro.txt +17 -0
  140. affinity_sdk-0.9.2/mcp/providers/xaffinity.sh +107 -0
  141. affinity_sdk-0.9.2/mcp/resources/data-model/data-model.md +189 -0
  142. affinity_sdk-0.9.2/mcp/resources/data-model/data-model.meta.json +7 -0
  143. affinity_sdk-0.9.2/mcp/resources/field-catalogs/field-catalogs.meta.json +7 -0
  144. affinity_sdk-0.9.2/mcp/resources/field-catalogs/field-catalogs.sh +76 -0
  145. affinity_sdk-0.9.2/mcp/resources/interaction-enums/interaction-enums.json +13 -0
  146. affinity_sdk-0.9.2/mcp/resources/interaction-enums/interaction-enums.meta.json +7 -0
  147. affinity_sdk-0.9.2/mcp/resources/me/me.meta.json +7 -0
  148. affinity_sdk-0.9.2/mcp/resources/me/me.sh +16 -0
  149. affinity_sdk-0.9.2/mcp/resources/me-person-id/me-person-id.meta.json +7 -0
  150. affinity_sdk-0.9.2/mcp/resources/me-person-id/me-person-id.sh +29 -0
  151. affinity_sdk-0.9.2/mcp/resources/saved-views/saved-views.meta.json +7 -0
  152. affinity_sdk-0.9.2/mcp/resources/saved-views/saved-views.sh +28 -0
  153. affinity_sdk-0.9.2/mcp/resources/workflow-config/workflow-config.meta.json +7 -0
  154. affinity_sdk-0.9.2/mcp/resources/workflow-config/workflow-config.sh +47 -0
  155. affinity_sdk-0.9.2/mcp/scripts/install-framework.sh +80 -0
  156. affinity_sdk-0.9.2/mcp/server.d/env.sh +74 -0
  157. affinity_sdk-0.9.2/mcp/server.d/health-checks.sh +32 -0
  158. affinity_sdk-0.9.2/mcp/server.d/policy.sh +32 -0
  159. affinity_sdk-0.9.2/mcp/server.d/requirements.json +29 -0
  160. affinity_sdk-0.9.2/mcp/server.d/server.meta.json +6 -0
  161. affinity_sdk-0.9.2/mcp/test/README.md +136 -0
  162. affinity_sdk-0.9.2/mcp/test/run.sh +450 -0
  163. affinity_sdk-0.9.2/mcp/test-progress.sh +254 -0
  164. affinity_sdk-0.9.2/mcp/tools/discover-commands/tool.meta.json +46 -0
  165. affinity_sdk-0.9.2/mcp/tools/discover-commands/tool.sh +152 -0
  166. affinity_sdk-0.9.2/mcp/tools/execute-read-command/tool.meta.json +36 -0
  167. affinity_sdk-0.9.2/mcp/tools/execute-read-command/tool.sh +156 -0
  168. affinity_sdk-0.9.2/mcp/tools/execute-write-command/tool.meta.json +36 -0
  169. affinity_sdk-0.9.2/mcp/tools/execute-write-command/tool.sh +207 -0
  170. affinity_sdk-0.9.2/mcp/tools/get-entity-dossier/tool.meta.json +46 -0
  171. affinity_sdk-0.9.2/mcp/tools/get-entity-dossier/tool.sh +131 -0
  172. affinity_sdk-0.9.2/mcp/tools/query/tool.meta.json +94 -0
  173. affinity_sdk-0.9.2/mcp/tools/query/tool.sh +115 -0
  174. affinity_sdk-0.9.2/mcp/tools/read-xaffinity-resource/tool.meta.json +19 -0
  175. affinity_sdk-0.9.2/mcp/tools/read-xaffinity-resource/tool.sh +23 -0
  176. affinity_sdk-0.9.2/mcp/xaffinity-mcp-env.sh +37 -0
  177. affinity_sdk-0.9.2/mcp/xaffinity-mcp.sh +178 -0
  178. {affinity_sdk-0.4.7 → affinity_sdk-0.9.2}/mkdocs.yml +5 -2
  179. affinity_sdk-0.9.2/plugins/affinity-sdk/.claude-plugin/plugin.json +22 -0
  180. affinity_sdk-0.4.7/.claude-plugin/skills/querying-affinity-crm/SDK_REFERENCE.md → affinity_sdk-0.9.2/plugins/affinity-sdk/.claude-plugin/skills/affinity-python-sdk/SKILL.md +101 -72
  181. affinity_sdk-0.9.2/plugins/xaffinity-cli/.claude-plugin/commands/affinity-help.md +56 -0
  182. affinity_sdk-0.9.2/plugins/xaffinity-cli/.claude-plugin/plugin.json +28 -0
  183. affinity_sdk-0.9.2/plugins/xaffinity-cli/.claude-plugin/skills/xaffinity-cli-usage/SKILL.md +193 -0
  184. {affinity_sdk-0.4.7 → affinity_sdk-0.9.2}/pyproject.toml +11 -4
  185. affinity_sdk-0.9.2/tests/test_cli_column_limiting.py +199 -0
  186. affinity_sdk-0.9.2/tests/test_cli_command_context.py +257 -0
  187. affinity_sdk-0.9.2/tests/test_cli_company_cmds_coverage.py +278 -0
  188. {affinity_sdk-0.4.7 → affinity_sdk-0.9.2}/tests/test_cli_company_get.py +18 -5
  189. affinity_sdk-0.9.2/tests/test_cli_csv_export.py +1012 -0
  190. affinity_sdk-0.9.2/tests/test_cli_date_params.py +154 -0
  191. affinity_sdk-0.9.2/tests/test_cli_date_utils.py +82 -0
  192. {affinity_sdk-0.4.7 → affinity_sdk-0.9.2}/tests/test_cli_datetime_formatting.py +1 -1
  193. {affinity_sdk-0.4.7 → affinity_sdk-0.9.2}/tests/test_cli_datetime_header_offsets.py +1 -1
  194. {affinity_sdk-0.4.7 → affinity_sdk-0.9.2}/tests/test_cli_domain_linkification.py +1 -1
  195. affinity_sdk-0.9.2/tests/test_cli_entry_field.py +1317 -0
  196. {affinity_sdk-0.4.7 → affinity_sdk-0.9.2}/tests/test_cli_error_rendering.py +16 -4
  197. affinity_sdk-0.9.2/tests/test_cli_field_history.py +202 -0
  198. {affinity_sdk-0.4.7 → affinity_sdk-0.9.2}/tests/test_cli_field_value_humanization.py +6 -6
  199. affinity_sdk-0.9.2/tests/test_cli_interaction_date_chunking.py +1044 -0
  200. {affinity_sdk-0.4.7 → affinity_sdk-0.9.2}/tests/test_cli_json_safety.py +1 -1
  201. affinity_sdk-0.9.2/tests/test_cli_list_cmds_coverage.py +519 -0
  202. {affinity_sdk-0.4.7 → affinity_sdk-0.9.2}/tests/test_cli_no_network_commands.py +2 -2
  203. {affinity_sdk-0.4.7 → affinity_sdk-0.9.2}/tests/test_cli_opportunity_cmds.py +3 -2
  204. affinity_sdk-0.9.2/tests/test_cli_opportunity_cmds_coverage.py +155 -0
  205. affinity_sdk-0.9.2/tests/test_cli_person_cmds_coverage.py +348 -0
  206. {affinity_sdk-0.4.7 → affinity_sdk-0.9.2}/tests/test_cli_person_get.py +1 -1
  207. affinity_sdk-0.9.2/tests/test_cli_progress_manager.py +164 -0
  208. affinity_sdk-0.9.2/tests/test_cli_query_aggregates.py +481 -0
  209. affinity_sdk-0.9.2/tests/test_cli_query_cmd.py +372 -0
  210. affinity_sdk-0.9.2/tests/test_cli_query_dates.py +205 -0
  211. affinity_sdk-0.9.2/tests/test_cli_query_executor.py +2719 -0
  212. affinity_sdk-0.9.2/tests/test_cli_query_filters.py +538 -0
  213. affinity_sdk-0.9.2/tests/test_cli_query_integration.py +240 -0
  214. affinity_sdk-0.9.2/tests/test_cli_query_parser.py +869 -0
  215. affinity_sdk-0.9.2/tests/test_cli_query_planner.py +625 -0
  216. affinity_sdk-0.9.2/tests/test_cli_query_schema.py +443 -0
  217. {affinity_sdk-0.4.7 → affinity_sdk-0.9.2}/tests/test_cli_rate_limit_rendering.py +2 -2
  218. affinity_sdk-0.9.2/tests/test_cli_result_summary.py +237 -0
  219. affinity_sdk-0.9.2/tests/test_cli_session_cache.py +389 -0
  220. affinity_sdk-0.9.2/tests/test_cli_types.py +152 -0
  221. {affinity_sdk-0.4.7 → affinity_sdk-0.9.2}/tests/test_cli_v1_only_cmds.py +21 -10
  222. {affinity_sdk-0.4.7 → affinity_sdk-0.9.2}/tests/test_cli_write_ops.py +14 -13
  223. affinity_sdk-0.9.2/tests/test_exceptions_coverage.py +341 -0
  224. affinity_sdk-0.9.2/tests/test_hooks.py +404 -0
  225. affinity_sdk-0.9.2/tests/test_isodatetime.py +433 -0
  226. {affinity_sdk-0.4.7 → affinity_sdk-0.9.2}/tests/test_models.py +4 -2
  227. affinity_sdk-0.9.2/tests/test_public_api.py +215 -0
  228. affinity_sdk-0.9.2/tests/test_services_companies_coverage_gaps.py +460 -0
  229. {affinity_sdk-0.4.7 → affinity_sdk-0.9.2}/tests/test_services_lists_additional_coverage.py +6 -8
  230. affinity_sdk-0.9.2/tests/test_services_lists_coverage_gaps.py +402 -0
  231. affinity_sdk-0.9.2/tests/test_services_opportunities_coverage_gaps.py +339 -0
  232. {affinity_sdk-0.4.7 → affinity_sdk-0.9.2}/tests/test_services_persons_companies_additional_coverage.py +519 -0
  233. affinity_sdk-0.9.2/tests/test_services_rate_limits_coverage_gaps.py +287 -0
  234. affinity_sdk-0.9.2/tests/test_services_v1_only_coverage_gaps.py +336 -0
  235. affinity_sdk-0.9.2/tools/generate_cli_commands_registry.py +200 -0
  236. affinity_sdk-0.9.2/tools/sync_mcp_registry.py +136 -0
  237. affinity_sdk-0.9.2/tools/sync_mcp_version.py +63 -0
  238. affinity_sdk-0.9.2/tools/sync_plugin_version.py +69 -0
  239. affinity_sdk-0.9.2/uv.lock +1485 -0
  240. affinity_sdk-0.4.7/.claude-plugin/commands/affinity-help.md +0 -58
  241. affinity_sdk-0.4.7/.claude-plugin/marketplace.json +0 -16
  242. affinity_sdk-0.4.7/.claude-plugin/plugin.json +0 -27
  243. affinity_sdk-0.4.7/.claude-plugin/skills/querying-affinity-crm/CLI_REFERENCE.md +0 -349
  244. affinity_sdk-0.4.7/.claude-plugin/skills/querying-affinity-crm/LIST_EXPORT_EXPAND.md +0 -177
  245. affinity_sdk-0.4.7/.claude-plugin/skills/querying-affinity-crm/SKILL.md +0 -213
  246. affinity_sdk-0.4.7/.github/workflows/ci.yml +0 -56
  247. affinity_sdk-0.4.7/.github/workflows/release.yml +0 -178
  248. affinity_sdk-0.4.7/CHANGELOG.md +0 -94
  249. affinity_sdk-0.4.7/affinity/cli/commands/field_cmds.py +0 -135
  250. affinity_sdk-0.4.7/affinity/cli/commands/interaction_cmds.py +0 -384
  251. affinity_sdk-0.4.7/affinity/cli/progress.py +0 -99
  252. affinity_sdk-0.4.7/affinity/cli/resolve.py +0 -114
  253. affinity_sdk-0.4.7/affinity/cli/results.py +0 -44
  254. affinity_sdk-0.4.7/docs/public/cli/scripting.md +0 -41
  255. affinity_sdk-0.4.7/docs/public/guides/claude-code-plugin.md +0 -86
  256. affinity_sdk-0.4.7/docs/public/guides/v1-v2-routing.md +0 -3
  257. affinity_sdk-0.4.7/tests/test_cli_csv_export.py +0 -2770
  258. affinity_sdk-0.4.7/tests/test_cli_progress_manager.py +0 -9
  259. affinity_sdk-0.4.7/tools/sync_plugin_version.py +0 -48
  260. {affinity_sdk-0.4.7 → affinity_sdk-0.9.2}/.editorconfig +0 -0
  261. {affinity_sdk-0.4.7 → affinity_sdk-0.9.2}/.env.example +0 -0
  262. {affinity_sdk-0.4.7 → affinity_sdk-0.9.2}/.gitattributes +0 -0
  263. {affinity_sdk-0.4.7 → affinity_sdk-0.9.2}/.github/CODEOWNERS +0 -0
  264. {affinity_sdk-0.4.7 → affinity_sdk-0.9.2}/.github/ISSUE_TEMPLATE/bug_report.yml +0 -0
  265. {affinity_sdk-0.4.7 → affinity_sdk-0.9.2}/.github/ISSUE_TEMPLATE/feature_request.yml +0 -0
  266. {affinity_sdk-0.4.7 → affinity_sdk-0.9.2}/.github/PULL_REQUEST_TEMPLATE/cli_command.md +0 -0
  267. {affinity_sdk-0.4.7 → affinity_sdk-0.9.2}/.github/dependabot.yml +0 -0
  268. {affinity_sdk-0.4.7 → affinity_sdk-0.9.2}/.github/labels.yml +0 -0
  269. {affinity_sdk-0.4.7 → affinity_sdk-0.9.2}/.github/pull_request_template.md +0 -0
  270. {affinity_sdk-0.4.7 → affinity_sdk-0.9.2}/CODE_OF_CONDUCT.md +0 -0
  271. {affinity_sdk-0.4.7 → affinity_sdk-0.9.2}/LICENSE +0 -0
  272. {affinity_sdk-0.4.7 → affinity_sdk-0.9.2}/SECURITY.md +0 -0
  273. {affinity_sdk-0.4.7 → affinity_sdk-0.9.2}/affinity/cli/__init__.py +0 -0
  274. {affinity_sdk-0.4.7 → affinity_sdk-0.9.2}/affinity/cli/click_compat.py +0 -0
  275. {affinity_sdk-0.4.7 → affinity_sdk-0.9.2}/affinity/cli/commands/__init__.py +0 -0
  276. {affinity_sdk-0.4.7 → affinity_sdk-0.9.2}/affinity/cli/commands/_list_entry_fields.py +0 -0
  277. {affinity_sdk-0.4.7 → affinity_sdk-0.9.2}/affinity/cli/config.py +0 -0
  278. {affinity_sdk-0.4.7 → affinity_sdk-0.9.2}/affinity/cli/errors.py +0 -0
  279. {affinity_sdk-0.4.7 → affinity_sdk-0.9.2}/affinity/cli/field_utils.py +0 -0
  280. {affinity_sdk-0.4.7 → affinity_sdk-0.9.2}/affinity/cli/logging.py +0 -0
  281. {affinity_sdk-0.4.7 → affinity_sdk-0.9.2}/affinity/cli/options.py +0 -0
  282. {affinity_sdk-0.4.7 → affinity_sdk-0.9.2}/affinity/cli/paths.py +0 -0
  283. {affinity_sdk-0.4.7 → affinity_sdk-0.9.2}/affinity/cli/resolvers.py +0 -0
  284. {affinity_sdk-0.4.7 → affinity_sdk-0.9.2}/affinity/cli/serialization.py +0 -0
  285. {affinity_sdk-0.4.7 → affinity_sdk-0.9.2}/affinity/cli/types.py +0 -0
  286. {affinity_sdk-0.4.7 → affinity_sdk-0.9.2}/affinity/clients/__init__.py +0 -0
  287. {affinity_sdk-0.4.7 → affinity_sdk-0.9.2}/affinity/clients/pipeline.py +0 -0
  288. {affinity_sdk-0.4.7 → affinity_sdk-0.9.2}/affinity/downloads.py +0 -0
  289. {affinity_sdk-0.4.7 → affinity_sdk-0.9.2}/affinity/hooks.py +0 -0
  290. {affinity_sdk-0.4.7 → affinity_sdk-0.9.2}/affinity/models/__init__.py +0 -0
  291. {affinity_sdk-0.4.7 → affinity_sdk-0.9.2}/affinity/models/rate_limit_snapshot.py +0 -0
  292. {affinity_sdk-0.4.7 → affinity_sdk-0.9.2}/affinity/models/secondary.py +0 -0
  293. {affinity_sdk-0.4.7 → affinity_sdk-0.9.2}/affinity/policies.py +0 -0
  294. {affinity_sdk-0.4.7 → affinity_sdk-0.9.2}/affinity/progress.py +0 -0
  295. {affinity_sdk-0.4.7 → affinity_sdk-0.9.2}/affinity/py.typed +0 -0
  296. {affinity_sdk-0.4.7 → affinity_sdk-0.9.2}/affinity/services/__init__.py +0 -0
  297. {affinity_sdk-0.4.7 → affinity_sdk-0.9.2}/affinity/services/rate_limits.py +0 -0
  298. {affinity_sdk-0.4.7 → affinity_sdk-0.9.2}/affinity/services/tasks.py +0 -0
  299. {affinity_sdk-0.4.7 → affinity_sdk-0.9.2}/affinity/types.py +0 -0
  300. {affinity_sdk-0.4.7 → affinity_sdk-0.9.2}/docs/cli-development-guide.md +0 -0
  301. {affinity_sdk-0.4.7 → affinity_sdk-0.9.2}/docs/public/changelog.md +0 -0
  302. {affinity_sdk-0.4.7 → affinity_sdk-0.9.2}/docs/public/examples.md +0 -0
  303. {affinity_sdk-0.4.7 → affinity_sdk-0.9.2}/docs/public/glossary.md +0 -0
  304. {affinity_sdk-0.4.7 → affinity_sdk-0.9.2}/docs/public/guides/api-versions-and-routing.md +0 -0
  305. {affinity_sdk-0.4.7 → affinity_sdk-0.9.2}/docs/public/guides/authentication.md +0 -0
  306. {affinity_sdk-0.4.7 → affinity_sdk-0.9.2}/docs/public/guides/configuration.md +0 -0
  307. {affinity_sdk-0.4.7 → affinity_sdk-0.9.2}/docs/public/guides/debugging-hooks.md +0 -0
  308. {affinity_sdk-0.4.7 → affinity_sdk-0.9.2}/docs/public/guides/errors-and-retries.md +0 -0
  309. {affinity_sdk-0.4.7 → affinity_sdk-0.9.2}/docs/public/guides/field-types-and-values.md +0 -0
  310. {affinity_sdk-0.4.7 → affinity_sdk-0.9.2}/docs/public/guides/field-values.md +0 -0
  311. {affinity_sdk-0.4.7 → affinity_sdk-0.9.2}/docs/public/guides/ids-and-types.md +0 -0
  312. {affinity_sdk-0.4.7 → affinity_sdk-0.9.2}/docs/public/guides/models.md +0 -0
  313. {affinity_sdk-0.4.7 → affinity_sdk-0.9.2}/docs/public/guides/opportunity-associations.md +0 -0
  314. {affinity_sdk-0.4.7 → affinity_sdk-0.9.2}/docs/public/guides/pagination.md +0 -0
  315. {affinity_sdk-0.4.7 → affinity_sdk-0.9.2}/docs/public/guides/rate-limits.md +0 -0
  316. {affinity_sdk-0.4.7 → affinity_sdk-0.9.2}/docs/public/guides/sync-vs-async.md +0 -0
  317. {affinity_sdk-0.4.7 → affinity_sdk-0.9.2}/docs/public/guides/webhooks.md +0 -0
  318. {affinity_sdk-0.4.7 → affinity_sdk-0.9.2}/docs/public/reference/client.md +0 -0
  319. {affinity_sdk-0.4.7 → affinity_sdk-0.9.2}/docs/public/reference/exceptions.md +0 -0
  320. {affinity_sdk-0.4.7 → affinity_sdk-0.9.2}/docs/public/reference/filters.md +0 -0
  321. {affinity_sdk-0.4.7 → affinity_sdk-0.9.2}/docs/public/reference/models.md +0 -0
  322. {affinity_sdk-0.4.7 → affinity_sdk-0.9.2}/docs/public/reference/services/companies.md +0 -0
  323. {affinity_sdk-0.4.7 → affinity_sdk-0.9.2}/docs/public/reference/services/lists.md +0 -0
  324. {affinity_sdk-0.4.7 → affinity_sdk-0.9.2}/docs/public/reference/services/opportunities.md +0 -0
  325. {affinity_sdk-0.4.7 → affinity_sdk-0.9.2}/docs/public/reference/services/persons.md +0 -0
  326. {affinity_sdk-0.4.7 → affinity_sdk-0.9.2}/docs/public/reference/services/tasks.md +0 -0
  327. {affinity_sdk-0.4.7 → affinity_sdk-0.9.2}/docs/public/reference/services/v1/auth.md +0 -0
  328. {affinity_sdk-0.4.7 → affinity_sdk-0.9.2}/docs/public/reference/services/v1/field-values.md +0 -0
  329. {affinity_sdk-0.4.7 → affinity_sdk-0.9.2}/docs/public/reference/services/v1/fields.md +0 -0
  330. {affinity_sdk-0.4.7 → affinity_sdk-0.9.2}/docs/public/reference/services/v1/files.md +0 -0
  331. {affinity_sdk-0.4.7 → affinity_sdk-0.9.2}/docs/public/reference/services/v1/interactions.md +0 -0
  332. {affinity_sdk-0.4.7 → affinity_sdk-0.9.2}/docs/public/reference/services/v1/notes.md +0 -0
  333. {affinity_sdk-0.4.7 → affinity_sdk-0.9.2}/docs/public/reference/services/v1/relationships.md +0 -0
  334. {affinity_sdk-0.4.7 → affinity_sdk-0.9.2}/docs/public/reference/services/v1/reminders.md +0 -0
  335. {affinity_sdk-0.4.7 → affinity_sdk-0.9.2}/docs/public/reference/services/v1/webhooks.md +0 -0
  336. {affinity_sdk-0.4.7 → affinity_sdk-0.9.2}/docs/public/reference/types.md +0 -0
  337. {affinity_sdk-0.4.7 → affinity_sdk-0.9.2}/docs/public/troubleshooting.md +0 -0
  338. {affinity_sdk-0.4.7 → affinity_sdk-0.9.2}/examples/advanced_usage.py +0 -0
  339. {affinity_sdk-0.4.7 → affinity_sdk-0.9.2}/examples/async_lifecycle.py +0 -0
  340. {affinity_sdk-0.4.7 → affinity_sdk-0.9.2}/examples/basic_usage.py +0 -0
  341. {affinity_sdk-0.4.7 → affinity_sdk-0.9.2}/examples/filter_builder.py +0 -0
  342. {affinity_sdk-0.4.7 → affinity_sdk-0.9.2}/examples/hooks_debugging.py +0 -0
  343. {affinity_sdk-0.4.7 → affinity_sdk-0.9.2}/examples/list_management.py +0 -0
  344. {affinity_sdk-0.4.7 → affinity_sdk-0.9.2}/examples/resolve_helpers.py +0 -0
  345. {affinity_sdk-0.4.7 → affinity_sdk-0.9.2}/examples/task_polling.py +0 -0
  346. {affinity_sdk-0.4.7 → affinity_sdk-0.9.2/plugins/xaffinity-cli}/.claude-plugin/hooks/hooks.json +0 -0
  347. {affinity_sdk-0.4.7 → affinity_sdk-0.9.2/plugins/xaffinity-cli}/.claude-plugin/hooks/pre-xaffinity.sh +0 -0
  348. {affinity_sdk-0.4.7 → affinity_sdk-0.9.2}/tests/conftest.py +0 -0
  349. {affinity_sdk-0.4.7 → affinity_sdk-0.9.2}/tests/fixtures/webhooks/field_value_updated.json +0 -0
  350. {affinity_sdk-0.4.7 → affinity_sdk-0.9.2}/tests/fixtures/webhooks/list_entry_created.json +0 -0
  351. {affinity_sdk-0.4.7 → affinity_sdk-0.9.2}/tests/fixtures/webhooks/organization_created.json +0 -0
  352. {affinity_sdk-0.4.7 → affinity_sdk-0.9.2}/tests/fixtures/webhooks/organization_merged.json +0 -0
  353. {affinity_sdk-0.4.7 → affinity_sdk-0.9.2}/tests/fixtures/webhooks/person_created.json +0 -0
  354. {affinity_sdk-0.4.7 → affinity_sdk-0.9.2}/tests/fixtures/webhooks/unknown_event.json +0 -0
  355. {affinity_sdk-0.4.7 → affinity_sdk-0.9.2}/tests/test_affinity_client_wrapper_additional_coverage.py +0 -0
  356. {affinity_sdk-0.4.7 → affinity_sdk-0.9.2}/tests/test_async_file_download_streaming.py +0 -0
  357. {affinity_sdk-0.4.7 → affinity_sdk-0.9.2}/tests/test_cli_config_cmds.py +0 -0
  358. {affinity_sdk-0.4.7 → affinity_sdk-0.9.2}/tests/test_cli_entity_files_dump.py +0 -0
  359. {affinity_sdk-0.4.7 → affinity_sdk-0.9.2}/tests/test_cli_missing_coverage.py +0 -0
  360. {affinity_sdk-0.4.7 → affinity_sdk-0.9.2}/tests/test_cli_pager_logic.py +0 -0
  361. {affinity_sdk-0.4.7 → affinity_sdk-0.9.2}/tests/test_cli_resolve_url_parsing.py +0 -0
  362. {affinity_sdk-0.4.7 → affinity_sdk-0.9.2}/tests/test_cli_serialization.py +0 -0
  363. {affinity_sdk-0.4.7 → affinity_sdk-0.9.2}/tests/test_client.py +0 -0
  364. {affinity_sdk-0.4.7 → affinity_sdk-0.9.2}/tests/test_env_helpers.py +0 -0
  365. {affinity_sdk-0.4.7 → affinity_sdk-0.9.2}/tests/test_field_value_type.py +0 -0
  366. {affinity_sdk-0.4.7 → affinity_sdk-0.9.2}/tests/test_file_download_streaming.py +0 -0
  367. {affinity_sdk-0.4.7 → affinity_sdk-0.9.2}/tests/test_file_upload_helpers_and_validation.py +0 -0
  368. {affinity_sdk-0.4.7 → affinity_sdk-0.9.2}/tests/test_filters.py +0 -0
  369. {affinity_sdk-0.4.7 → affinity_sdk-0.9.2}/tests/test_http_client_additional_coverage.py +0 -0
  370. {affinity_sdk-0.4.7 → affinity_sdk-0.9.2}/tests/test_http_client_remaining_coverage.py +0 -0
  371. {affinity_sdk-0.4.7 → affinity_sdk-0.9.2}/tests/test_inbound_webhooks.py +0 -0
  372. {affinity_sdk-0.4.7 → affinity_sdk-0.9.2}/tests/test_integration_smoke.py +0 -0
  373. {affinity_sdk-0.4.7 → affinity_sdk-0.9.2}/tests/test_interactions_and_files_regressions.py +0 -0
  374. {affinity_sdk-0.4.7 → affinity_sdk-0.9.2}/tests/test_list_entry_membership_and_opportunities.py +0 -0
  375. {affinity_sdk-0.4.7 → affinity_sdk-0.9.2}/tests/test_new_features.py +0 -0
  376. {affinity_sdk-0.4.7 → affinity_sdk-0.9.2}/tests/test_pagination_iterators.py +0 -0
  377. {affinity_sdk-0.4.7 → affinity_sdk-0.9.2}/tests/test_raw_pipeline_hook_events.py +0 -0
  378. {affinity_sdk-0.4.7 → affinity_sdk-0.9.2}/tests/test_requirements_additional.py +0 -0
  379. {affinity_sdk-0.4.7 → affinity_sdk-0.9.2}/tests/test_services_opportunities_additional_coverage.py +0 -0
  380. {affinity_sdk-0.4.7 → affinity_sdk-0.9.2}/tests/test_services_opportunities_tasks_additional_coverage.py +0 -0
  381. {affinity_sdk-0.4.7 → affinity_sdk-0.9.2}/tests/test_services_v1_only_async.py +0 -0
  382. {affinity_sdk-0.4.7 → affinity_sdk-0.9.2}/tests/test_small_modules_coverage.py +0 -0
  383. {affinity_sdk-0.4.7 → affinity_sdk-0.9.2}/tests/test_transport_and_readonly_mode.py +0 -0
  384. {affinity_sdk-0.4.7 → affinity_sdk-0.9.2}/tests/test_v1_only_services_additional_coverage.py +0 -0
  385. {affinity_sdk-0.4.7 → affinity_sdk-0.9.2}/tests/test_v1_only_services_more_coverage.py +0 -0
  386. {affinity_sdk-0.4.7 → affinity_sdk-0.9.2}/tools/check_cli_patterns.py +0 -0
  387. {affinity_sdk-0.4.7 → affinity_sdk-0.9.2}/tools/generate_requirements_mapping.py +0 -0
  388. {affinity_sdk-0.4.7 → affinity_sdk-0.9.2}/tools/validate_openapi_models.py +0 -0
@@ -0,0 +1,26 @@
1
+ {
2
+ "name": "xaffinity",
3
+ "owner": {
4
+ "name": "Yaniv Golan"
5
+ },
6
+ "metadata": {
7
+ "description": "Plugins for Affinity CRM - Python SDK, CLI, and MCP integrations"
8
+ },
9
+ "plugins": [
10
+ {
11
+ "name": "sdk",
12
+ "source": "./plugins/affinity-sdk/.claude-plugin",
13
+ "description": "Python SDK for Affinity CRM - typed IDs, async support, pagination patterns for developers"
14
+ },
15
+ {
16
+ "name": "cli",
17
+ "source": "./plugins/xaffinity-cli/.claude-plugin",
18
+ "description": "Command-line interface for Affinity CRM - search, export, filter CRM data via xaffinity commands"
19
+ },
20
+ {
21
+ "name": "mcp",
22
+ "source": "./mcp/.claude-plugin",
23
+ "description": "MCP server for Affinity CRM - workflow tools, relationship intelligence, pipeline management"
24
+ }
25
+ ]
26
+ }
@@ -0,0 +1,31 @@
1
+ ---
2
+ name: Release
3
+ about: Checklist for SDK or MCP releases
4
+ ---
5
+
6
+ ## Release Type
7
+
8
+ - [ ] SDK Release (vX.Y.Z)
9
+ - [ ] MCP Release (plugin-vX.Y.Z)
10
+
11
+ ## SDK Release Checklist (vX.Y.Z)
12
+
13
+ - [ ] Version bumped in `pyproject.toml`
14
+ - [ ] Plugin versions synced (pre-commit should handle)
15
+ - [ ] `CHANGELOG.md` updated with breaking changes noted
16
+ - [ ] If CLI output format changed: MCP `COMPATIBILITY` updated
17
+ - [ ] Tests pass locally and in CI
18
+
19
+ ## MCP Release Checklist (plugin-vX.Y.Z)
20
+
21
+ - [ ] Version bumped in `mcp/VERSION`
22
+ - [ ] `mcp/.claude-plugin/plugin.json` version updated
23
+ - [ ] `mcp/mcpb.conf` MCPB_VERSION updated
24
+ - [ ] `mcp/COMPATIBILITY` CLI requirements updated if needed
25
+ - [ ] `mcp/CHANGELOG.md` documents CLI compatibility
26
+ - [ ] Builds successfully: `cd mcp && make all verify`
27
+
28
+ ## Post-Merge
29
+
30
+ - [ ] Tag pushed: `git tag vX.Y.Z && git push --tags` (SDK)
31
+ - [ ] Tag pushed: `git tag plugin-vX.Y.Z && git push --tags` (MCP)
@@ -0,0 +1,134 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ pull_request:
6
+
7
+ jobs:
8
+ mcp-plugin:
9
+ runs-on: ubuntu-latest
10
+ steps:
11
+ - uses: actions/checkout@v6
12
+
13
+ - name: Build MCP plugin
14
+ run: make -C mcp plugin
15
+
16
+ - name: Verify plugin structure
17
+ run: |
18
+ # Ensure critical files exist after build (ZIP-based distribution)
19
+ make -C mcp verify
20
+ test -f mcp/.claude-plugin/xaffinity-mcp.sh
21
+ test -f mcp/.claude-plugin/plugin.json
22
+ test -f mcp/.claude-plugin/xaffinity-mcp-plugin.zip
23
+ test -f mcp/.claude-plugin/VERSION
24
+ echo "Plugin structure validated successfully"
25
+
26
+ - name: Test ZIP extraction
27
+ run: |
28
+ cd mcp/.claude-plugin
29
+ mkdir -p .mcp-extracted
30
+ unzip -q xaffinity-mcp-plugin.zip -d .mcp-extracted
31
+ test -x .mcp-extracted/xaffinity-mcp.sh
32
+ test -d .mcp-extracted/tools
33
+ test -d .mcp-extracted/prompts
34
+ echo "ZIP extraction test passed"
35
+
36
+ test:
37
+ runs-on: ubuntu-latest
38
+ strategy:
39
+ fail-fast: false
40
+ matrix:
41
+ python-version: ["3.10", "3.11", "3.12", "3.13"]
42
+
43
+ steps:
44
+ - uses: actions/checkout@v6
45
+
46
+ - name: Set up Python
47
+ uses: actions/setup-python@v6
48
+ with:
49
+ python-version: ${{ matrix.python-version }}
50
+ cache: pip
51
+ cache-dependency-path: pyproject.toml
52
+
53
+ - name: Install
54
+ run: |
55
+ python -m pip install --upgrade pip
56
+ python -m pip install -e ".[dev]"
57
+
58
+ - name: Lint
59
+ run: |
60
+ ruff format --check .
61
+ ruff check .
62
+
63
+ - name: Type check
64
+ run: |
65
+ mypy affinity
66
+
67
+ - name: Test
68
+ run: |
69
+ pytest --cov=affinity --cov-report=term-missing --cov-report=xml
70
+
71
+ - name: Upload coverage to Codecov
72
+ uses: codecov/codecov-action@v5
73
+ with:
74
+ token: ${{ secrets.CODECOV_TOKEN }}
75
+ files: ./coverage.xml
76
+ fail_ci_if_error: false
77
+
78
+ - name: Traceability mapping is up to date
79
+ run: |
80
+ if [ -d docs/internal ]; then
81
+ python tools/generate_requirements_mapping.py
82
+ git diff --exit-code docs/internal/requirements_to_tests_mapping.md
83
+ else
84
+ echo "Skipping traceability mapping (docs/internal not present in repo checkout)."
85
+ fi
86
+
87
+ - name: CLI commands registry is valid
88
+ run: |
89
+ # Verify registry file exists and is valid JSON with expected structure
90
+ python -c "
91
+ import json
92
+ import sys
93
+ with open('mcp/.registry/commands.json') as f:
94
+ data = json.load(f)
95
+ assert 'commands' in data, 'Missing commands key'
96
+ assert isinstance(data['commands'], list), 'commands must be a list'
97
+ assert len(data['commands']) > 0, 'commands list is empty'
98
+ for cmd in data['commands']:
99
+ assert 'name' in cmd, f'Command missing name: {cmd}'
100
+ assert 'category' in cmd, f'Command {cmd[\"name\"]} missing category'
101
+ assert cmd['category'] in ('read', 'write', 'local'), f'Invalid category for {cmd[\"name\"]}'
102
+ print(f'Registry valid: {len(data[\"commands\"])} commands')
103
+ "
104
+ # Regenerate registry and verify it matches committed version
105
+ python tools/generate_cli_commands_registry.py
106
+ git diff --exit-code mcp/.registry/commands.json
107
+
108
+ test-timezone:
109
+ runs-on: ubuntu-latest
110
+ strategy:
111
+ fail-fast: false
112
+ matrix:
113
+ tz: ["UTC", "America/New_York", "Europe/London", "Asia/Tokyo"]
114
+
115
+ steps:
116
+ - uses: actions/checkout@v6
117
+
118
+ - name: Set up Python
119
+ uses: actions/setup-python@v6
120
+ with:
121
+ python-version: "3.12"
122
+ cache: pip
123
+ cache-dependency-path: pyproject.toml
124
+
125
+ - name: Install
126
+ run: |
127
+ python -m pip install --upgrade pip
128
+ python -m pip install -e ".[dev]"
129
+
130
+ - name: Test with TZ=${{ matrix.tz }}
131
+ env:
132
+ TZ: ${{ matrix.tz }}
133
+ run: |
134
+ pytest tests/test_isodatetime.py -v
@@ -13,12 +13,12 @@ jobs:
13
13
  build:
14
14
  runs-on: ubuntu-latest
15
15
  steps:
16
- - uses: actions/checkout@v4
16
+ - uses: actions/checkout@v6
17
17
  with:
18
18
  fetch-depth: 0
19
19
 
20
20
  - name: Set up Python
21
- uses: actions/setup-python@v5
21
+ uses: actions/setup-python@v6
22
22
  with:
23
23
  python-version: "3.12"
24
24
  cache: pip
@@ -54,14 +54,14 @@ jobs:
54
54
  contents: write
55
55
  concurrency:
56
56
  group: docs-deploy
57
- cancel-in-progress: true
57
+ cancel-in-progress: false
58
58
  steps:
59
- - uses: actions/checkout@v4
59
+ - uses: actions/checkout@v6
60
60
  with:
61
61
  fetch-depth: 0
62
62
 
63
63
  - name: Set up Python
64
- uses: actions/setup-python@v5
64
+ uses: actions/setup-python@v6
65
65
  with:
66
66
  python-version: "3.12"
67
67
  cache: pip
@@ -81,6 +81,10 @@ jobs:
81
81
  git config user.name "github-actions[bot]"
82
82
  git config user.email "github-actions[bot]@users.noreply.github.com"
83
83
 
84
+ - name: Fetch gh-pages branch
85
+ run: |
86
+ git fetch origin gh-pages:gh-pages || true
87
+
84
88
  - name: Deploy (dev)
85
89
  if: github.ref == 'refs/heads/main'
86
90
  run: |
@@ -15,7 +15,7 @@ jobs:
15
15
  sync:
16
16
  runs-on: ubuntu-latest
17
17
  steps:
18
- - uses: actions/checkout@v4
18
+ - uses: actions/checkout@v6
19
19
  - name: Sync labels
20
20
  uses: EndBug/label-sync@v2
21
21
  with:
@@ -13,10 +13,10 @@ jobs:
13
13
  runs-on: ubuntu-latest
14
14
  timeout-minutes: 10
15
15
  steps:
16
- - uses: actions/checkout@v4
16
+ - uses: actions/checkout@v6
17
17
 
18
18
  - name: Set up Python
19
- uses: actions/setup-python@v5
19
+ uses: actions/setup-python@v6
20
20
  with:
21
21
  python-version: "3.12"
22
22
  cache: pip
@@ -11,10 +11,10 @@ jobs:
11
11
  timeout-minutes: 10
12
12
 
13
13
  steps:
14
- - uses: actions/checkout@v4
14
+ - uses: actions/checkout@v6
15
15
 
16
16
  - name: Set up Python
17
- uses: actions/setup-python@v5
17
+ uses: actions/setup-python@v6
18
18
  with:
19
19
  python-version: "3.12"
20
20
  cache: pip
@@ -0,0 +1,106 @@
1
+ name: Build MCP Plugin
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ paths:
7
+ - 'mcp/**'
8
+ - '!mcp/dist/**'
9
+ workflow_dispatch:
10
+
11
+ permissions:
12
+ contents: read
13
+
14
+ jobs:
15
+ build:
16
+ runs-on: ubuntu-latest
17
+ steps:
18
+ - uses: actions/checkout@v6
19
+ with:
20
+ token: ${{ secrets.GITHUB_TOKEN }}
21
+
22
+ - name: Install jq
23
+ run: sudo apt-get install -y jq
24
+
25
+ - name: Install mcp-bash framework
26
+ run: |
27
+ # Source version and commit from lockfile (single source of truth)
28
+ source mcp/mcp-bash.lock
29
+ echo "Installing mcp-bash v${MCPBASH_VERSION} (${MCPBASH_COMMIT})"
30
+ curl -fsSL https://raw.githubusercontent.com/yaniv-golan/mcp-bash-framework/main/install.sh | \
31
+ bash -s -- --version "v${MCPBASH_VERSION}" --yes
32
+ echo "$HOME/.local/bin" >> $GITHUB_PATH
33
+ # Verify installed commit matches lockfile
34
+ INSTALLED_COMMIT=$(git -C "${XDG_DATA_HOME:-$HOME/.local/share}/mcp-bash" rev-parse HEAD)
35
+ if [[ "$INSTALLED_COMMIT" != "$MCPBASH_COMMIT" ]]; then
36
+ echo "::error::mcp-bash commit mismatch: expected $MCPBASH_COMMIT, got $INSTALLED_COMMIT"
37
+ exit 1
38
+ fi
39
+
40
+ - name: Verify mcp-bash installation
41
+ run: |
42
+ mcp-bash --version
43
+ echo "mcp-bash installed successfully"
44
+
45
+ - name: Build MCP plugin ZIP
46
+ run: make -C mcp plugin
47
+
48
+ - name: Verify plugin structure
49
+ run: |
50
+ make -C mcp verify
51
+ test -f mcp/.claude-plugin/xaffinity-mcp.sh
52
+ test -f mcp/.claude-plugin/plugin.json
53
+ test -f mcp/.claude-plugin/xaffinity-mcp-plugin.zip
54
+ test -f mcp/.claude-plugin/VERSION
55
+ echo "Plugin structure validated"
56
+
57
+ - name: Test extraction
58
+ run: |
59
+ cd mcp/.claude-plugin
60
+ mkdir -p .mcp-extracted
61
+ unzip -q xaffinity-mcp-plugin.zip -d .mcp-extracted
62
+ test -x .mcp-extracted/xaffinity-mcp.sh
63
+ test -f .mcp-extracted/VERSION
64
+ rm -rf .mcp-extracted
65
+ echo "Extraction test passed"
66
+
67
+ - name: Validate MCPB configuration
68
+ run: |
69
+ cd mcp
70
+ mcp-bash bundle --validate
71
+ echo "MCPB configuration validated"
72
+
73
+ - name: Build MCPB bundle
74
+ run: |
75
+ cd mcp
76
+ mcp-bash bundle --output dist --verbose
77
+ ls -la dist/*.mcpb
78
+ echo "MCPB bundle created"
79
+
80
+ - name: Validate MCPB bundle structure
81
+ run: |
82
+ cd mcp
83
+ MCPB_FILE=$(ls dist/*.mcpb | head -1)
84
+ unzip -t "$MCPB_FILE"
85
+ unzip -p "$MCPB_FILE" manifest.json | jq .
86
+ echo "MCPB bundle structure validated"
87
+
88
+ - name: Test MCPB bundle health check
89
+ run: |
90
+ cd mcp
91
+ MCPB_FILE=$(ls dist/*.mcpb | head -1)
92
+ EXTRACT_DIR=$(mktemp -d)
93
+ unzip -q "$MCPB_FILE" -d "$EXTRACT_DIR"
94
+ # Test the wrapper script health check
95
+ "$EXTRACT_DIR/server/run-server.sh" --health || echo "Health check not available (expected if CLI not configured)"
96
+ rm -rf "$EXTRACT_DIR"
97
+ echo "MCPB bundle test completed"
98
+
99
+ - name: Upload plugin artifacts
100
+ uses: actions/upload-artifact@v6
101
+ with:
102
+ name: mcp-plugin
103
+ path: |
104
+ mcp/.claude-plugin/xaffinity-mcp-plugin.zip
105
+ mcp/dist/*.mcpb
106
+ retention-days: 30
@@ -0,0 +1,152 @@
1
+ name: Release MCP Plugin
2
+
3
+ on:
4
+ push:
5
+ tags: ["mcp-v*.*.*"] # Renamed from plugin-v*
6
+ workflow_call:
7
+ inputs:
8
+ version:
9
+ description: "Version to release (without prefix)"
10
+ required: true
11
+ type: string
12
+ triggered_by:
13
+ description: "What triggered this release"
14
+ required: false
15
+ type: string
16
+ default: "tag"
17
+ workflow_dispatch:
18
+ inputs:
19
+ tag:
20
+ description: 'Tag to release (e.g., mcp-v1.0.0)'
21
+ required: true
22
+
23
+ permissions:
24
+ contents: write
25
+
26
+ jobs:
27
+ release:
28
+ runs-on: ubuntu-latest
29
+ steps:
30
+ - name: Determine version and tag
31
+ id: version
32
+ run: |
33
+ set -euo pipefail
34
+ if [[ -n "${{ inputs.version }}" ]]; then
35
+ # Called via workflow_call
36
+ echo "version=${{ inputs.version }}" >> $GITHUB_OUTPUT
37
+ echo "tag_name=mcp-v${{ inputs.version }}" >> $GITHUB_OUTPUT
38
+ echo "is_workflow_call=true" >> $GITHUB_OUTPUT
39
+ echo "Mode: workflow_call, version=${{ inputs.version }}"
40
+ else
41
+ # Called via tag push or workflow_dispatch
42
+ TAG_NAME="${{ github.event.inputs.tag || github.ref_name }}"
43
+ VERSION="${TAG_NAME#mcp-v}"
44
+ echo "version=$VERSION" >> $GITHUB_OUTPUT
45
+ echo "tag_name=$TAG_NAME" >> $GITHUB_OUTPUT
46
+ echo "is_workflow_call=false" >> $GITHUB_OUTPUT
47
+ echo "Mode: tag/dispatch, tag=$TAG_NAME, version=$VERSION"
48
+ fi
49
+
50
+ - uses: actions/checkout@v6
51
+ with:
52
+ ref: ${{ steps.version.outputs.is_workflow_call == 'true' && 'main' || (github.event.inputs.tag || github.ref) }}
53
+
54
+ - name: Validate version matches VERSION file
55
+ run: |
56
+ set -euo pipefail
57
+ FILE_VERSION=$(cat mcp/VERSION | tr -d '[:space:]')
58
+ INPUT_VERSION="${{ steps.version.outputs.version }}"
59
+ if [[ "$FILE_VERSION" != "$INPUT_VERSION" ]]; then
60
+ echo "::error::Version mismatch: mcp/VERSION=$FILE_VERSION, expected=$INPUT_VERSION"
61
+ exit 1
62
+ fi
63
+ echo "Version validated: $FILE_VERSION"
64
+
65
+ - name: Install jq
66
+ run: sudo apt-get install -y jq
67
+
68
+ - name: Install mcp-bash framework
69
+ run: |
70
+ # Source version and commit from lockfile (single source of truth)
71
+ source mcp/mcp-bash.lock
72
+ echo "Installing mcp-bash v${MCPBASH_VERSION} (${MCPBASH_COMMIT})"
73
+ curl -fsSL https://raw.githubusercontent.com/yaniv-golan/mcp-bash-framework/main/install.sh | \
74
+ bash -s -- --version "v${MCPBASH_VERSION}" --yes
75
+ echo "$HOME/.local/bin" >> $GITHUB_PATH
76
+ # Verify installed commit matches lockfile
77
+ INSTALLED_COMMIT=$(git -C "${XDG_DATA_HOME:-$HOME/.local/share}/mcp-bash" rev-parse HEAD)
78
+ if [[ "$INSTALLED_COMMIT" != "$MCPBASH_COMMIT" ]]; then
79
+ echo "::error::mcp-bash commit mismatch: expected $MCPBASH_COMMIT, got $INSTALLED_COMMIT"
80
+ exit 1
81
+ fi
82
+
83
+ - name: Verify mcp-bash installation
84
+ run: mcp-bash --version
85
+
86
+ - name: Build Claude Code plugin ZIP
87
+ run: |
88
+ cd mcp
89
+ make plugin
90
+ echo "Plugin version: $(cat .claude-plugin/VERSION)"
91
+ ls -la .claude-plugin/xaffinity-mcp-plugin.zip
92
+
93
+ - name: Validate MCPB configuration
94
+ run: |
95
+ cd mcp
96
+ mcp-bash bundle --validate
97
+
98
+ - name: Build MCPB bundle
99
+ run: |
100
+ cd mcp
101
+ mcp-bash bundle --output dist --verbose
102
+ ls -la dist/*.mcpb
103
+
104
+ - name: Validate MCPB bundle structure
105
+ run: |
106
+ cd mcp
107
+ MCPB_FILE=$(ls dist/*.mcpb | head -1)
108
+ unzip -t "$MCPB_FILE"
109
+ unzip -p "$MCPB_FILE" manifest.json | jq .
110
+ echo "MCPB bundle validated"
111
+
112
+ - name: Test MCPB bundle health check
113
+ run: |
114
+ cd mcp
115
+ MCPB_FILE=$(ls dist/*.mcpb | head -1)
116
+ EXTRACT_DIR=$(mktemp -d)
117
+ unzip -q "$MCPB_FILE" -d "$EXTRACT_DIR"
118
+ "$EXTRACT_DIR/server/run-server.sh" --health || echo "Health check not available (expected if CLI not configured)"
119
+ rm -rf "$EXTRACT_DIR"
120
+
121
+ - name: Create and push tag
122
+ if: steps.version.outputs.is_workflow_call == 'true'
123
+ run: |
124
+ git config user.name "github-actions[bot]"
125
+ git config user.email "github-actions[bot]@users.noreply.github.com"
126
+ git tag -a "${{ steps.version.outputs.tag_name }}" -m "Release ${{ steps.version.outputs.tag_name }}"
127
+ git push origin "${{ steps.version.outputs.tag_name }}"
128
+
129
+ - name: Create GitHub Release
130
+ uses: softprops/action-gh-release@v2
131
+ with:
132
+ tag_name: ${{ steps.version.outputs.tag_name }}
133
+ files: |
134
+ mcp/.claude-plugin/xaffinity-mcp-plugin.zip
135
+ mcp/dist/*.mcpb
136
+ generate_release_notes: true
137
+ name: MCP Server ${{ steps.version.outputs.tag_name }}
138
+ body: |
139
+ ## Installation
140
+
141
+ ### One-click install (Claude Desktop)
142
+ Download `xaffinity-mcp-*.mcpb` and double-click or drag to Claude Desktop.
143
+
144
+ ### Claude Code
145
+ ```bash
146
+ /plugin marketplace add yaniv-golan/affinity-sdk
147
+ /plugin install mcp@xaffinity
148
+ ```
149
+
150
+ ### Manual configuration
151
+ Download `xaffinity-mcp-plugin.zip` and configure your MCP client manually.
152
+ See [documentation](https://yaniv-golan.github.io/affinity-sdk/latest/mcp/) for details.
@@ -0,0 +1,98 @@
1
+ name: Release Detection
2
+
3
+ # Triggers releases automatically when version files change on main
4
+ # Only runs AFTER CI passes successfully
5
+ #
6
+ # Detection strategy: Compare current version against existing release tags.
7
+ # This is more robust than checking HEAD~1 because it works regardless of
8
+ # how many commits are pushed together, squash merges, rebases, etc.
9
+
10
+ on:
11
+ workflow_run:
12
+ workflows: ["CI"]
13
+ types: [completed]
14
+ branches: [main]
15
+
16
+ permissions:
17
+ contents: read
18
+
19
+ jobs:
20
+ detect-changes:
21
+ # Only run if CI passed and it was a push (not PR)
22
+ if: >
23
+ github.event.workflow_run.conclusion == 'success' &&
24
+ github.event.workflow_run.event == 'push'
25
+ runs-on: ubuntu-latest
26
+ outputs:
27
+ sdk_changed: ${{ steps.changes.outputs.sdk }}
28
+ mcp_changed: ${{ steps.changes.outputs.mcp }}
29
+ sdk_version: ${{ steps.versions.outputs.sdk }}
30
+ mcp_version: ${{ steps.versions.outputs.mcp }}
31
+ steps:
32
+ - uses: actions/checkout@v6
33
+ with:
34
+ ref: ${{ github.event.workflow_run.head_sha }}
35
+ fetch-depth: 0 # Full history needed to check tags
36
+
37
+ - name: Extract versions
38
+ id: versions
39
+ run: |
40
+ set -euo pipefail
41
+ SDK_VERSION=$(grep '^version = ' pyproject.toml | head -1 | cut -d'"' -f2)
42
+ MCP_VERSION=$(cat mcp/VERSION | tr -d '[:space:]')
43
+ echo "sdk=$SDK_VERSION" >> $GITHUB_OUTPUT
44
+ echo "mcp=$MCP_VERSION" >> $GITHUB_OUTPUT
45
+ echo "SDK version in pyproject.toml: $SDK_VERSION"
46
+ echo "MCP version in mcp/VERSION: $MCP_VERSION"
47
+
48
+ - name: Detect unreleased versions
49
+ id: changes
50
+ run: |
51
+ set -euo pipefail
52
+
53
+ SDK_VERSION="${{ steps.versions.outputs.sdk }}"
54
+ MCP_VERSION="${{ steps.versions.outputs.mcp }}"
55
+
56
+ echo "Checking if releases exist for current versions..."
57
+
58
+ # Check if SDK version has a release tag
59
+ SDK_TAG="v${SDK_VERSION}"
60
+ if git tag -l "$SDK_TAG" | grep -q "^${SDK_TAG}$"; then
61
+ echo "SDK tag $SDK_TAG already exists - no release needed"
62
+ else
63
+ echo "SDK tag $SDK_TAG does not exist - release needed"
64
+ echo "sdk=true" >> $GITHUB_OUTPUT
65
+ fi
66
+
67
+ # Check if MCP version has a release tag
68
+ MCP_TAG="mcp-v${MCP_VERSION}"
69
+ if git tag -l "$MCP_TAG" | grep -q "^${MCP_TAG}$"; then
70
+ echo "MCP tag $MCP_TAG already exists - no release needed"
71
+ else
72
+ echo "MCP tag $MCP_TAG does not exist - release needed"
73
+ echo "mcp=true" >> $GITHUB_OUTPUT
74
+ fi
75
+
76
+ trigger-sdk-release:
77
+ needs: detect-changes
78
+ if: needs.detect-changes.outputs.sdk_changed == 'true'
79
+ uses: ./.github/workflows/release.yml
80
+ with:
81
+ version: ${{ needs.detect-changes.outputs.sdk_version }}
82
+ triggered_by: version-bump
83
+ secrets: inherit
84
+ permissions:
85
+ contents: write
86
+ id-token: write
87
+ attestations: write
88
+
89
+ trigger-mcp-release:
90
+ needs: detect-changes
91
+ if: needs.detect-changes.outputs.mcp_changed == 'true'
92
+ uses: ./.github/workflows/plugin-release.yml
93
+ with:
94
+ version: ${{ needs.detect-changes.outputs.mcp_version }}
95
+ triggered_by: version-bump
96
+ secrets: inherit
97
+ permissions:
98
+ contents: write