mammoth-cli 2.0.24__tar.gz → 2.0.26__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 (218) hide show
  1. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/PKG-INFO +2 -2
  2. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/mammoth_cli/__init__.py +1 -1
  3. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/mammoth_cli/bundled_skill/mammoth-cli/SKILL.md +1 -1
  4. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/mammoth_cli/bundled_skill/mammoth-cli/references/capabilities-misc.md +1 -1
  5. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/mammoth_cli/bundled_skill/mammoth-cli/references/capabilities.md +4 -5
  6. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/view.md +4 -4
  7. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/mammoth_cli/bundled_skill/mammoth-cli/references/recipes/transforms.md +9 -0
  8. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/mammoth_cli/bundled_skill/mammoth-cli/references/recovery.md +1 -0
  9. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/mammoth_cli/commands/schema.py +23 -2
  10. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/mammoth_cli/commands/upgrade.py +36 -17
  11. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/mammoth_cli/commands/view.py +4 -0
  12. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/mammoth_cli/commands/view_ops.py +112 -5
  13. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/mammoth_cli/services/input_fields.py +19 -0
  14. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/pyproject.toml +2 -2
  15. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/spec/manifests/commands/dashboard.yaml +3 -1
  16. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/spec/manifests/commands/view.yaml +14 -10
  17. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/.gitignore +0 -0
  18. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/LICENSE +0 -0
  19. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/README.md +0 -0
  20. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/mammoth_cli/__main__.py +0 -0
  21. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/mammoth_cli/app.py +0 -0
  22. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/mammoth_cli/bundled_skill/mammoth-cli/references/auth.md +0 -0
  23. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/mammoth_cli/bundled_skill/mammoth-cli/references/command-index.md +0 -0
  24. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/activity.md +0 -0
  25. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/addon.md +0 -0
  26. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/agent.md +0 -0
  27. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/ai.md +0 -0
  28. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/annotation.md +0 -0
  29. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/auth.md +0 -0
  30. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/automation.md +0 -0
  31. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/batch.md +0 -0
  32. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/billing.md +0 -0
  33. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/browse.md +0 -0
  34. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/capability.md +0 -0
  35. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/client-app.md +0 -0
  36. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/completion.md +0 -0
  37. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/config.md +0 -0
  38. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/connector.md +0 -0
  39. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/context.md +0 -0
  40. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/dashboard.md +0 -0
  41. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/data-app.md +0 -0
  42. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/dataset.md +0 -0
  43. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/doctor.md +0 -0
  44. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/external-key.md +0 -0
  45. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/file.md +0 -0
  46. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/folder.md +0 -0
  47. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/job.md +0 -0
  48. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/log.md +0 -0
  49. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/notification.md +0 -0
  50. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/parameter.md +0 -0
  51. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/project.md +0 -0
  52. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/report.md +0 -0
  53. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/schedule.md +0 -0
  54. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/schema.md +0 -0
  55. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/skill.md +0 -0
  56. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/snippet.md +0 -0
  57. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/support.md +0 -0
  58. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/template.md +0 -0
  59. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/trash.md +0 -0
  60. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/upgrade.md +0 -0
  61. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/user.md +0 -0
  62. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/version.md +0 -0
  63. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/webhook.md +0 -0
  64. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/workflow.md +0 -0
  65. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/workspace.md +0 -0
  66. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/mammoth_cli/bundled_skill/mammoth-cli/references/handoff.md +0 -0
  67. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/mammoth_cli/bundled_skill/mammoth-cli/references/input.md +0 -0
  68. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/mammoth_cli/bundled_skill/mammoth-cli/references/jobs-drafts.md +0 -0
  69. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/mammoth_cli/bundled_skill/mammoth-cli/references/machine-output.md +0 -0
  70. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/mammoth_cli/bundled_skill/mammoth-cli/references/operations.md +0 -0
  71. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/mammoth_cli/bundled_skill/mammoth-cli/references/recipes/auth-scope.md +0 -0
  72. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/mammoth_cli/bundled_skill/mammoth-cli/references/recipes/cleanup.md +0 -0
  73. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/mammoth_cli/bundled_skill/mammoth-cli/references/recipes/dashboards.md +0 -0
  74. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/mammoth_cli/bundled_skill/mammoth-cli/references/recipes/end-to-end.md +0 -0
  75. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/mammoth_cli/bundled_skill/mammoth-cli/references/recipes/exports.md +0 -0
  76. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/mammoth_cli/bundled_skill/mammoth-cli/references/recipes/index.md +0 -0
  77. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/mammoth_cli/bundled_skill/mammoth-cli/references/recipes/need-action.md +0 -0
  78. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/mammoth_cli/bundled_skill/mammoth-cli/references/recipes/resources.md +0 -0
  79. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/mammoth_cli/bundled_skill/mammoth-cli/references/recipes/typed-etl-discovery.md +0 -0
  80. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/mammoth_cli/bundled_skill/mammoth-cli/references/report-checklist.md +0 -0
  81. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/mammoth_cli/bundled_skill/mammoth-cli/references/retention.md +0 -0
  82. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/mammoth_cli/bundled_skill/mammoth-cli/references/safety.md +0 -0
  83. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/mammoth_cli/bundled_skill/mammoth-cli/references/task-start.md +0 -0
  84. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/mammoth_cli/commands/__init__.py +0 -0
  85. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/mammoth_cli/commands/activity.py +0 -0
  86. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/mammoth_cli/commands/addon.py +0 -0
  87. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/mammoth_cli/commands/agent.py +0 -0
  88. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/mammoth_cli/commands/ai.py +0 -0
  89. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/mammoth_cli/commands/annotation.py +0 -0
  90. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/mammoth_cli/commands/auth.py +0 -0
  91. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/mammoth_cli/commands/automation.py +0 -0
  92. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/mammoth_cli/commands/batch.py +0 -0
  93. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/mammoth_cli/commands/billing.py +0 -0
  94. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/mammoth_cli/commands/browse.py +0 -0
  95. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/mammoth_cli/commands/capability.py +0 -0
  96. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/mammoth_cli/commands/client_app.py +0 -0
  97. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/mammoth_cli/commands/completion.py +0 -0
  98. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/mammoth_cli/commands/config.py +0 -0
  99. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/mammoth_cli/commands/connector.py +0 -0
  100. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/mammoth_cli/commands/context.py +0 -0
  101. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/mammoth_cli/commands/dashboard.py +0 -0
  102. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/mammoth_cli/commands/data_app.py +0 -0
  103. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/mammoth_cli/commands/dataset.py +0 -0
  104. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/mammoth_cli/commands/doctor.py +0 -0
  105. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/mammoth_cli/commands/external_key.py +0 -0
  106. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/mammoth_cli/commands/file.py +0 -0
  107. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/mammoth_cli/commands/folder.py +0 -0
  108. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/mammoth_cli/commands/job.py +0 -0
  109. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/mammoth_cli/commands/notification.py +0 -0
  110. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/mammoth_cli/commands/parameter.py +0 -0
  111. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/mammoth_cli/commands/project.py +0 -0
  112. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/mammoth_cli/commands/registry.py +0 -0
  113. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/mammoth_cli/commands/report.py +0 -0
  114. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/mammoth_cli/commands/schedule.py +0 -0
  115. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/mammoth_cli/commands/skill.py +0 -0
  116. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/mammoth_cli/commands/snippet.py +0 -0
  117. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/mammoth_cli/commands/support.py +0 -0
  118. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/mammoth_cli/commands/template.py +0 -0
  119. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/mammoth_cli/commands/trash.py +0 -0
  120. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/mammoth_cli/commands/user.py +0 -0
  121. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/mammoth_cli/commands/webhook.py +0 -0
  122. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/mammoth_cli/commands/workflow.py +0 -0
  123. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/mammoth_cli/commands/workspace.py +0 -0
  124. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/mammoth_cli/context/__init__.py +0 -0
  125. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/mammoth_cli/context/credentials.py +0 -0
  126. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/mammoth_cli/context/endpoint.py +0 -0
  127. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/mammoth_cli/context/profiles.py +0 -0
  128. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/mammoth_cli/context/resolver.py +0 -0
  129. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/mammoth_cli/contracts/__init__.py +0 -0
  130. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/mammoth_cli/contracts/auth.py +0 -0
  131. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/mammoth_cli/errors/__init__.py +0 -0
  132. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/mammoth_cli/errors/envelope.py +0 -0
  133. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/mammoth_cli/manifest/__init__.py +0 -0
  134. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/mammoth_cli/manifest/loader.py +0 -0
  135. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/mammoth_cli/messages/__init__.py +0 -0
  136. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/mammoth_cli/output/__init__.py +0 -0
  137. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/mammoth_cli/output/envelope.py +0 -0
  138. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/mammoth_cli/output/normalize.py +0 -0
  139. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/mammoth_cli/output/policy.py +0 -0
  140. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/mammoth_cli/output/progress.py +0 -0
  141. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/mammoth_cli/output/render.py +0 -0
  142. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/mammoth_cli/py.typed +0 -0
  143. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/mammoth_cli/runtime/__init__.py +0 -0
  144. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/mammoth_cli/runtime/confirm.py +0 -0
  145. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/mammoth_cli/runtime/executor.py +0 -0
  146. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/mammoth_cli/runtime/input_loader.py +0 -0
  147. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/mammoth_cli/runtime/invocation.py +0 -0
  148. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/mammoth_cli/runtime/options.py +0 -0
  149. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/mammoth_cli/runtime/parents.py +0 -0
  150. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/mammoth_cli/runtime/runlog.py +0 -0
  151. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/mammoth_cli/runtime/session.py +0 -0
  152. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/mammoth_cli/runtime/strict.py +0 -0
  153. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/mammoth_cli/runtime/updates.py +0 -0
  154. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/mammoth_cli/runtime/validate.py +0 -0
  155. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/mammoth_cli/services/__init__.py +0 -0
  156. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/mammoth_cli/services/argspec.py +0 -0
  157. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/mammoth_cli/services/coerce.py +0 -0
  158. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/mammoth_cli/services/command_contract.py +0 -0
  159. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/mammoth_cli/services/conditions.py +0 -0
  160. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/mammoth_cli/services/dispatch.py +0 -0
  161. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/mammoth_cli/services/factory.py +0 -0
  162. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/mammoth_cli/services/mapping.py +0 -0
  163. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/mammoth_cli/services/openapi_types.py +0 -0
  164. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/mammoth_cli/services/positionals.py +0 -0
  165. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/mammoth_cli/services/protocol.py +0 -0
  166. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/mammoth_cli/services/sdk_service.py +0 -0
  167. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/mammoth_cli/services/testing.py +0 -0
  168. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/mammoth_cli/services/type_system.py +0 -0
  169. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/mammoth_cli/skills/__init__.py +0 -0
  170. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/mammoth_cli/skills/installer.py +0 -0
  171. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/mammoth_cli/testing.py +0 -0
  172. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/spec/manifests/commands/activity.yaml +0 -0
  173. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/spec/manifests/commands/addon.yaml +0 -0
  174. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/spec/manifests/commands/agent.yaml +0 -0
  175. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/spec/manifests/commands/ai.yaml +0 -0
  176. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/spec/manifests/commands/annotation.yaml +0 -0
  177. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/spec/manifests/commands/auth.yaml +0 -0
  178. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/spec/manifests/commands/automation.yaml +0 -0
  179. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/spec/manifests/commands/batch.yaml +0 -0
  180. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/spec/manifests/commands/billing.yaml +0 -0
  181. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/spec/manifests/commands/browse.yaml +0 -0
  182. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/spec/manifests/commands/capability.yaml +0 -0
  183. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/spec/manifests/commands/client-app.yaml +0 -0
  184. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/spec/manifests/commands/completion.yaml +0 -0
  185. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/spec/manifests/commands/config.yaml +0 -0
  186. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/spec/manifests/commands/connector.yaml +0 -0
  187. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/spec/manifests/commands/context.yaml +0 -0
  188. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/spec/manifests/commands/data-app.yaml +0 -0
  189. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/spec/manifests/commands/dataset.yaml +0 -0
  190. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/spec/manifests/commands/doctor.yaml +0 -0
  191. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/spec/manifests/commands/external-key.yaml +0 -0
  192. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/spec/manifests/commands/file.yaml +0 -0
  193. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/spec/manifests/commands/folder.yaml +0 -0
  194. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/spec/manifests/commands/job.yaml +0 -0
  195. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/spec/manifests/commands/log.yaml +0 -0
  196. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/spec/manifests/commands/notification.yaml +0 -0
  197. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/spec/manifests/commands/parameter.yaml +0 -0
  198. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/spec/manifests/commands/project.yaml +0 -0
  199. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/spec/manifests/commands/report.yaml +0 -0
  200. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/spec/manifests/commands/schedule.yaml +0 -0
  201. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/spec/manifests/commands/schema.yaml +0 -0
  202. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/spec/manifests/commands/skill.yaml +0 -0
  203. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/spec/manifests/commands/snippet.yaml +0 -0
  204. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/spec/manifests/commands/support.yaml +0 -0
  205. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/spec/manifests/commands/template.yaml +0 -0
  206. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/spec/manifests/commands/trash.yaml +0 -0
  207. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/spec/manifests/commands/upgrade.yaml +0 -0
  208. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/spec/manifests/commands/user.yaml +0 -0
  209. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/spec/manifests/commands/version.yaml +0 -0
  210. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/spec/manifests/commands/webhook.yaml +0 -0
  211. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/spec/manifests/commands/workflow.yaml +0 -0
  212. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/spec/manifests/commands/workspace.yaml +0 -0
  213. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/spec/manifests/openapi-operations.yaml +0 -0
  214. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/spec/manifests/schema-v1.json +0 -0
  215. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/spec/manifests/sdk-catalog.source.yaml +0 -0
  216. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/spec/manifests/sdk-methods.yaml +0 -0
  217. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/spec/openapi/metadata.json +0 -0
  218. {mammoth_cli-2.0.24 → mammoth_cli-2.0.26}/spec/openapi/openapi.json +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mammoth-cli
3
- Version: 2.0.24
3
+ Version: 2.0.26
4
4
  Summary: Command-line interface for the Mammoth Analytics platform
5
5
  Project-URL: homepage, https://mammoth.io
6
6
  Project-URL: repository, https://github.com/EdgeMetric/mammothsdk
@@ -17,7 +17,7 @@ Classifier: Topic :: Software Development :: Libraries :: Python Modules
17
17
  Requires-Python: <3.15,>=3.12
18
18
  Requires-Dist: jsonschema>=4.20
19
19
  Requires-Dist: keyring<26,>=25.7
20
- Requires-Dist: mammoth-io<0.8,>=0.7.11
20
+ Requires-Dist: mammoth-io<0.8,>=0.7.12
21
21
  Requires-Dist: platformdirs<5,>=4.10
22
22
  Requires-Dist: pydantic<3,>=2.13
23
23
  Requires-Dist: pyyaml<7,>=6
@@ -6,7 +6,7 @@ not implement a second HTTP client and does not call private SDK members.
6
6
 
7
7
  from __future__ import annotations
8
8
 
9
- __version__ = "2.0.24"
9
+ __version__ = "2.0.26"
10
10
 
11
11
  # The versioned machine output envelope contract.
12
12
  SCHEMA_VERSION = 1
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: mammoth-cli
3
- version: 2.0.24
3
+ version: 2.0.26
4
4
  description: "Use Mammoth Analytics from a terminal: install or authenticate the CLI, discover its live command contract, and safely manage projects, data, views, pipelines, dashboards, exports, and handoffs."
5
5
  ---
6
6
 
@@ -140,4 +140,4 @@ Ran once: `workflow.create`, `workflow.delete`, `workflow.get`, `workflow.graph`
140
140
 
141
141
  Ran once: `workspace.app-usage`, `workspace.get`, `workspace.list`, `workspace.segment.list`, `workspace.segment.update`, `workspace.storage-breakdown`, `workspace.user.list`
142
142
 
143
- Evidence collected on CLI releases 1.1.5 through 2.0.21; each row's release is recorded in `docs/release-capability-matrix.json` (`evidence_version`). A row that ran on an older release has not been re-run since unless its note says so. Details: `docs/capability-evidence/` in the repository.
143
+ Evidence collected on CLI releases 1.1.5 through 2.0.24; each row's release is recorded in `docs/release-capability-matrix.json` (`evidence_version`). A row that ran on an older release has not been re-run since unless its note says so. Details: `docs/capability-evidence/` in the repository.
@@ -1,7 +1,7 @@
1
1
  # What is proven on release
2
2
 
3
3
  Generated from `docs/release-capability-matrix.json`; do not edit by hand.
4
- The CLI publishes 552 commands. 455 of them bind one of the 528 API operations in the matrix; the remainder are local commands (`schema`, `auth`, `doctor`, `log`, ...) or typed variants that share an operation (every `view transform *` command submits through `view.task.add`). 260 bound commands ran once successfully on release, 2 are not supported there, and the rest are untried. Untried is not broken: discover the contract with `mammoth schema get COMMAND_ID`, run it, and treat the structured error envelope as the answer.
4
+ The CLI publishes 552 commands. 455 of them bind one of the 528 API operations in the matrix; the remainder are local commands (`schema`, `auth`, `doctor`, `log`, ...) or typed variants that share an operation (every `view transform *` command submits through `view.task.add`). 261 bound commands ran once successfully on release, 2 are not supported there, and the rest are untried. Untried is not broken: discover the contract with `mammoth schema get COMMAND_ID`, run it, and treat the structured error envelope as the answer.
5
5
 
6
6
  Status meanings:
7
7
 
@@ -18,7 +18,7 @@ The typed `view transform *` commands all submit through `view.task.add`; its ma
18
18
  | Family | Commands | Ran once | Not supported | Untried |
19
19
  |---|---|---|---|---|
20
20
  | `dashboard` | 104 | 81 | 2 | 21 |
21
- | `view` | 62 | 56 | 0 | 6 |
21
+ | `view` | 62 | 57 | 0 | 5 |
22
22
  | `support` | 45 | 9 | 0 | 36 |
23
23
  | `billing` | 23 | 4 | 0 | 19 |
24
24
  | `connector` | 22 | 3 | 0 | 19 |
@@ -110,14 +110,13 @@ Ran once: `project.bulk-delete`, `project.bulk-update`, `project.checkpoint.list
110
110
 
111
111
  ## `view`
112
112
 
113
- Ran once: `view.active-user.list`, `view.active-user.mark`, `view.ai.generate-data`, `view.ai.profile`, `view.bulk-delete`, `view.checkpoint.create`, `view.checkpoint.delete`, `view.checkpoint.get`, `view.checkpoint.list`, `view.checkpoint.update`, `view.conditional-format.create`, `view.conditional-format.delete-all`, `view.conditional-format.list`, `view.conditional-format.update`, `view.create`, `view.data-check.create`, `view.data-check.delete`, `view.data-check.get`, `view.data-check.list`, `view.data.get`, `view.data.query`, `view.delete`, `view.derivative.create`, `view.derivative.delete`, `view.derivative.list`, `view.derivative.update`, `view.draft.command`, `view.export.delete`, `view.export.get`, `view.export.list`, `view.export.publish-db`, `view.export.update`, `view.exportable-config.apply`, `view.exportable-config.get`, `view.get`, `view.list`, `view.parameter-context`, `view.pipeline.edit`, `view.pipeline.get`, `view.pipeline.items`, `view.pipeline.rerun`, `view.preview`, `view.restore`, `view.task.add`, `view.task.delete`, `view.task.get`, `view.task.list`, `view.task.preview`, `view.task.update`, `view.trash`, `view.version.apply`, `view.version.delete`, `view.version.get`, `view.version.list`, `view.version.update`
113
+ Ran once: `view.active-user.list`, `view.active-user.mark`, `view.ai.generate-data`, `view.ai.profile`, `view.bulk-delete`, `view.checkpoint.create`, `view.checkpoint.delete`, `view.checkpoint.get`, `view.checkpoint.list`, `view.checkpoint.update`, `view.conditional-format.create`, `view.conditional-format.delete-all`, `view.conditional-format.list`, `view.conditional-format.update`, `view.create`, `view.data-check.create`, `view.data-check.delete`, `view.data-check.get`, `view.data-check.list`, `view.data.get`, `view.data.query`, `view.delete`, `view.derivative.create`, `view.derivative.data`, `view.derivative.delete`, `view.derivative.list`, `view.derivative.update`, `view.draft.command`, `view.export.delete`, `view.export.get`, `view.export.list`, `view.export.publish-db`, `view.export.update`, `view.exportable-config.apply`, `view.exportable-config.get`, `view.get`, `view.list`, `view.parameter-context`, `view.pipeline.edit`, `view.pipeline.get`, `view.pipeline.items`, `view.pipeline.rerun`, `view.preview`, `view.restore`, `view.task.add`, `view.task.delete`, `view.task.get`, `view.task.list`, `view.task.preview`, `view.task.update`, `view.trash`, `view.version.apply`, `view.version.delete`, `view.version.get`, `view.version.list`, `view.version.update`
114
114
 
115
115
  | Command | State | Note |
116
116
  |---|---|---|
117
117
  | `view.ai.generation-info` | observed blocker | backend: GET /workspaces/4/projects/24/datasets/54/dataviews/76/data/generate -> HTTP 400 5GENR011 NOT_IMPLEMENTED 'Not implemented', request_id:null |
118
118
  | `view.data-check.update` | observed blocker | backend_error: PATCH with the schema's documented {op: command, path: enable/disable, value: null} shape returns HTTP 500 empty body (CLI outcome_unknown, exit 7) while the mutatio |
119
- | `view.derivative.data` | observed blocker | backend_error: SUSPECTED DEFECT: using the CLI's own documented agent_example body verbatim, derivative data fetch returns HTTP 500 empty body / outcome_unknown, reproduced twice ( |
120
119
  | `view.export.create` | observed blocker | backend: CLI accepts the request (exit 0, job 358 accepted on POST /dataviews/76/actions), but job get 358 -> status:error, response:{"error":{"message":"'destination'"}} (a raw Py |
121
120
  | `view.export.publish-db-update` | CLI defect fixed, untried since | 2.0.16 (example value is the documented {"odbc_type": "postgres"} object (a bare string is rejected)) |
122
121
 
123
- Evidence collected on CLI releases 1.1.5 through 2.0.21; each row's release is recorded in `docs/release-capability-matrix.json` (`evidence_version`). A row that ran on an older release has not been re-run since unless its note says so. Details: `docs/capability-evidence/` in the repository.
122
+ Evidence collected on CLI releases 1.1.5 through 2.0.24; each row's release is recorded in `docs/release-capability-matrix.json` (`evidence_version`). A row that ran on an older release has not been re-run since unless its note says so. Details: `docs/capability-evidence/` in the repository.
@@ -246,21 +246,21 @@ Status on release: ran once on CLI 2.0.18 — golden-data check 2026-09-19: exit
246
246
 
247
247
  Run: `mammoth view derivative create`. Exact input fields: `mammoth schema get view.derivative.create`.
248
248
 
249
- Example: `mammoth view derivative create 123 123 --input '{"body": {"param": {"METRIC": {"AS": "sample", "EXPRESSION": [{"TYPE": "FUNCTION", "VALUE": {"ARGUMENT": "sample", "FUNCTION": "SUM"}}]}}}}'`. Placeholders are illustrative; resolve IDs and input from observed reads.
249
+ Example: `mammoth view derivative create 123 123 --input '{"body": {"param": {"METRIC": {"AS": "total", "EXPRESSION": [{"TYPE": "FUNCTION", "VALUE": {"ARGUMENT": "column_1", "FUNCTION": "SUM"}}]}}}}'`. Placeholders are illustrative; resolve IDs and input from observed reads.
250
250
 
251
251
  Result: `ViewDerivativeCreateResult`; mutation `benign_mutation`, confirmation `none`, wait policy `not_async`.
252
252
 
253
- Status on release: ran once on CLI 2.0.21 — Partial bounded evidence only (earlier run); ergonomics sweep 2026-09-19 (CLI 2.0.21) observed backend_error: POST .../derivatives with the example shape (METRIC object) returns HTTP 500 empty body / outcome_unknown on release today. A list under METRIC is re…
253
+ Status on release: ran once on CLI 2.0.24 — payload probe 2026-09-19: exit 0 on release with CLI 2.0.24. Created derivative id=6 on view 123 (project 52, dataset 104) with the column INTERNAL name as ARGUMENT; metric_status DONE on read-back. The same call with the display name reproduces the HTTP 500…
254
254
 
255
255
  ### `view.derivative.data`
256
256
 
257
257
  Run: `mammoth view derivative data`. Exact input fields: `mammoth schema get view.derivative.data`.
258
258
 
259
- Example: `mammoth view derivative data 123 123 123 --input '{"body": {"condition": {"FILTER_TYPE": "SHOW"}}}'`. Placeholders are illustrative; resolve IDs and input from observed reads.
259
+ Example: `mammoth view derivative data 123 123 123 --input '{"body": {"limit": null}}'`. Placeholders are illustrative; resolve IDs and input from observed reads.
260
260
 
261
261
  Result: `ViewDerivativeDataResult`; mutation `benign_mutation`, confirmation `none`, wait policy `not_async`.
262
262
 
263
- Status on release: observed blocker — backend_error: SUSPECTED DEFECT: using the CLI's own documented agent_example body verbatim, derivative data fetch returns HTTP 500 empty body / outcome_unknown, reproduced twice (. Re-check before relying on it.
263
+ Status on release: ran once on CLI 2.0.24 — payload probe 2026-09-19: exit 0 on release with CLI 2.0.24. STATUS READY, data [{RESULT: 60.0}], metadata total/RESULT/NUMERIC, row_count 1. {"condition": null, "limit": null} (the web app's body) also works; {} is 4GENR007. Example corrected in 2.0.25. Sing…
264
264
 
265
265
  ### `view.derivative.delete`
266
266
 
@@ -89,6 +89,15 @@ but the copy answers every read with `4DTVW019` and its copied tasks never
89
89
  execute. A plain `view create DATASET_ID` (no `clone_from`) gives a fresh view
90
90
  of the raw upload, without the pipeline:
91
91
 
92
+ A task must fit the column's type: `replace-values`, `bulk-replace` and the
93
+ text operations take TEXT columns, `math` takes NUMERIC. Check `type` in the
94
+ `metadata` from `view get` first; the uploader already types `$1,234.56` as
95
+ NUMERIC, so strip nothing. When a task does not fit, the CLI answers
96
+ `pipeline_reference_error` with the column, the reason and the exact
97
+ `view task delete VIEW_ID TASK_ID --yes` that removes it; until then the view
98
+ is in `ref_error` and every read of it fails with `4DTVW019`. `convert-type`
99
+ changes the column's type when the task really needs the other one.
100
+
92
101
  Every pivot `as_name` must be a display name that does not already exist on
93
102
  the view (`4DTVW018 Same display name cannot be reused`): to carry a joined
94
103
  column such as `monthly_target` into the summary, aggregate it under a new
@@ -27,6 +27,7 @@ these commands are not blanket permission to replay a mutation.
27
27
  | `invalid_condition` (exit 2, `details.accepted` lists operators) | operator not in the accepted set (symbols `=`, `>` are accepted as aliases of EQ/GT; words like `GREATER` are not) | use an operator from references/input.md |
28
28
  | `resource_not_found` (exit 5) after `view get VIEW_ID` / `view data get VIEW_ID` without a parent | discovery could not find the view in the selected project | pass `--project PROJECT_ID` and the `DATASET_ID` positional from `view list` |
29
29
  | `{"data": "<unserializable View>"}` from `view get VIEW_ID` | CLI ≤ 2.0.17 only; fixed in 2.0.18 | upgrade, or rerun as `view get VIEW_ID DATASET_ID` |
30
+ | `pipeline_reference_error` (exit 1) from a transform or `view task add`, `details.reference_errors[].reason` `type mismatch` / `not available` | the backend stored the task but cannot bind it to that column (find/replace and text operations take TEXT columns, math takes NUMERIC); the view is in `ref_error` and every read of it fails with `4DTVW019` until the task goes | run the printed `view task delete VIEW_ID TASK_ID --yes`, then convert-type the column or pick a transform for its type; CLI ≤ 2.0.24 reported this as success with `has_error: true` |
30
31
  | `4DTVW019 INVALID_RESPONSE_GENERATED` on every read of a view made with `view create ... "clone_from"` | backend: the clone is never processed (tasks stay `added`) | delete the copy; export the source view's rows, then run the summary in place as the last step; see recipes/end-to-end.md |
31
32
  | `status: ready` with `status_info.ready` "more than one plausible way to be read" and `view list` empty | all-text CSV; the platform did not process it | `file upload` (2.0.18) reports this as `need_action`; see recipes/need-action.md |
32
33
  | `need_action` in `file upload` result | the platform needs a parsing decision (e.g. ambiguous dates) | run the `next_command` it returns (`dataset file-settings get ID`), then `dataset file-settings update ID`; see recipes/need-action.md |
@@ -70,6 +70,17 @@ _COMMAND_DISCOVERY_PURPOSES = {
70
70
  "view.transform.convert-type": "convert type cast numeric text date column",
71
71
  "view.transform.fill-missing": "fill missing null empty impute carry forward values",
72
72
  "view.transform.join": "join blend lookup merge matching keys rows",
73
+ "view.transform.extract-date": (
74
+ "extract date part year month day hour minute second week quarter weekday "
75
+ "month_text into a new column"
76
+ ),
77
+ "view.transform.date-diff": "date difference days between two date columns age duration",
78
+ "view.transform.increment-date": "add subtract days months years to a date column shift",
79
+ "view.transform.math": "math arithmetic multiply divide add subtract formula expression amount",
80
+ "view.transform.pivot": "pivot group by aggregate sum count summary per region total",
81
+ "view.transform.set-values": "set values assign overwrite blank empty default where condition",
82
+ "view.transform.text": "text case upper lower title trim whitespace normalise",
83
+ "view.transform.bulk-replace": "find replace strip characters text values mapping",
73
84
  }
74
85
 
75
86
  # A compact string scope is retained for existing discovery consumers. These
@@ -268,8 +279,18 @@ def _humanize_sample(value: Any, field_name: str) -> Any:
268
279
 
269
280
 
270
281
  def _tokens(value: str) -> frozenset[str]:
271
- """Tokenize search text consistently across platforms and Python runs."""
272
- return frozenset(_TOKEN_RE.findall(value.casefold()))
282
+ """Tokenize search text consistently across platforms and Python runs.
283
+
284
+ A hyphenated word is kept whole and also split into its parts, so that
285
+ ``date`` finds ``extract-date`` and ``date-diff`` as well as ``convert-type``'s
286
+ example text.
287
+ """
288
+ tokens: set[str] = set()
289
+ for token in _TOKEN_RE.findall(value.casefold()):
290
+ tokens.add(token)
291
+ if "-" in token:
292
+ tokens.update(token.split("-"))
293
+ return frozenset(tokens)
273
294
 
274
295
 
275
296
  def _query_tokens(query: str) -> tuple[str, ...]:
@@ -19,6 +19,7 @@ real subprocess.
19
19
  from __future__ import annotations
20
20
 
21
21
  import json
22
+ import os
22
23
  import shutil
23
24
  import subprocess
24
25
  import sys
@@ -54,37 +55,50 @@ ACTION_ALREADY_CURRENT = "already_current"
54
55
  ACTION_WOULD_UPGRADE = "would_upgrade"
55
56
 
56
57
 
57
- def _uv_tool_lists_package() -> bool:
58
- """Whether ``uv tool list`` reports this package as a uv-managed tool.
58
+ def _tool_root(argv: list[str]) -> str | None:
59
+ """Return the directory a tool manager keeps its venvs in, or None.
59
60
 
60
- Returns False (rather than raising) when ``uv`` is absent or the listing
61
- fails, so detection can fall through to the next manager.
61
+ ``uv tool dir`` / ``pipx environment --value PIPX_LOCAL_VENVS`` answer
62
+ with one path. Returns None (rather than raising) when the manager is
63
+ absent or the query fails, so detection can fall through.
62
64
  """
63
- uv = shutil.which("uv")
64
- if not uv:
65
- return False
65
+ binary = shutil.which(argv[0])
66
+ if not binary:
67
+ return None
66
68
  try:
67
- result = subprocess.run( # noqa: S603 - fixed argv, no shell, trusted uv path
68
- [uv, "tool", "list"],
69
+ result = subprocess.run( # noqa: S603 - fixed argv, no shell, trusted path
70
+ [binary, *argv[1:]],
69
71
  capture_output=True,
70
72
  text=True,
71
73
  timeout=30,
72
74
  check=False,
73
75
  )
74
76
  except (OSError, subprocess.SubprocessError):
75
- return False
77
+ return None
76
78
  if result.returncode != 0:
79
+ return None
80
+ root = result.stdout.strip().splitlines()
81
+ return root[0].strip() if root else None
82
+
83
+
84
+ def _runs_under(root: str | None) -> bool:
85
+ """Whether the running interpreter's environment lives under ``root``."""
86
+ if not root:
77
87
  return False
78
- return PACKAGE_NAME in result.stdout
88
+ prefix = os.path.realpath(sys.prefix)
89
+ return prefix.startswith(os.path.realpath(root).rstrip("/\\") + os.sep)
79
90
 
80
91
 
81
92
  def detect_manager() -> str:
82
93
  """Detect which tool manages this CLI install.
83
94
 
84
- Detection order is ``uv tool`` (the running executable lives under a uv
85
- tools directory, or ``uv tool list`` reports the package), then ``pipx``
86
- (the executable lives under a pipx venvs directory), then a ``pip``
87
- fallback.
95
+ The decision is about the *running* environment, never about what else
96
+ is installed on the machine: a plain venv on a host that also has a
97
+ ``uv tool`` install must be upgraded with pip in that venv, or the
98
+ upgrade lands somewhere else and the caller keeps the old version.
99
+ Detection order is ``uv tool`` (``sys.executable`` under a uv tools
100
+ directory, or ``sys.prefix`` under ``uv tool dir``), then ``pipx`` (the
101
+ same for its venvs directory), then the ``pip`` of the running interpreter.
88
102
 
89
103
  Returns:
90
104
  One of :data:`MANAGER_UV`, :data:`MANAGER_PIPX`, or :data:`MANAGER_PIP`.
@@ -94,8 +108,13 @@ def detect_manager() -> str:
94
108
  return MANAGER_UV
95
109
  if "/pipx/venvs/" in location or "/pipx/venv/" in location:
96
110
  return MANAGER_PIPX
97
- if _uv_tool_lists_package():
98
- return MANAGER_UV
111
+ if sys.prefix != sys.base_prefix:
112
+ # Inside some virtual environment: only a manager that owns *this*
113
+ # environment may upgrade it.
114
+ if _runs_under(_tool_root(["uv", "tool", "dir"])):
115
+ return MANAGER_UV
116
+ if _runs_under(_tool_root(["pipx", "environment", "--value", "PIPX_LOCAL_VENVS"])):
117
+ return MANAGER_PIPX
99
118
  return MANAGER_PIP
100
119
 
101
120
 
@@ -1447,6 +1447,10 @@ def view_task_add(invocation: Invocation) -> HandlerResult:
1447
1447
  _forward_optional(document, kwargs, ("dataset_id",))
1448
1448
  with open_service(invocation) as (service, auth):
1449
1449
  data = service.call(_symbol(invocation), **kwargs)
1450
+ # Imported here: view_ops imports this module for the brief record helpers.
1451
+ from mammoth_cli.commands.view_ops import reject_pipeline_reference_errors
1452
+
1453
+ reject_pipeline_reference_errors(service, dataview_id, kwargs.get("dataset_id"), data)
1450
1454
  return data, _meta(invocation, auth.workspace_id, None)
1451
1455
 
1452
1456
 
@@ -32,6 +32,7 @@ from mammoth_cli.errors.envelope import (
32
32
  CODE_MISSING_ARGUMENT,
33
33
  CODE_MISSING_FIELD,
34
34
  CODE_SDK_SYMBOL_UNRESOLVED,
35
+ EXIT_API,
35
36
  EXIT_USAGE,
36
37
  CliError,
37
38
  )
@@ -45,6 +46,20 @@ from mammoth_cli.services.conditions import CONDITION_KWARG
45
46
 
46
47
  HandlerResult = tuple[Any, dict[str, Any]]
47
48
 
49
+ #: Error code for a task the backend accepted but could not bind to the view.
50
+ CODE_PIPELINE_REFERENCE_ERROR = "pipeline_reference_error"
51
+ _PIPELINE_SYMBOL = "mammoth.api.pipeline.PipelineAPI.get_pipeline"
52
+ _PIPELINE_ITEMS_SYMBOL = "mammoth.api.pipeline.PipelineAPI.items"
53
+ _PIPELINE_ITEMS_FULL = "__full"
54
+ _REFERROR_REASON_HINTS = {
55
+ "type mismatch": (
56
+ "the task needs a different column type (find/replace and text operations "
57
+ "take TEXT columns, math takes NUMERIC); convert-type the column first or "
58
+ "use a transform for that type"
59
+ ),
60
+ "not available": "the column does not exist in the view at that point in the pipeline",
61
+ }
62
+
48
63
 
49
64
  def _symbol(invocation: Invocation) -> str:
50
65
  """Return the reviewed backing SDK symbol for this command."""
@@ -236,14 +251,106 @@ def _dispatch_view(
236
251
  with open_service(invocation) as (service, auth):
237
252
  if dataset_id is None:
238
253
  dataset_id = parents.lookup(_profile_name(invocation), auth.workspace_id, view_id)
239
- if dataset_id is None:
240
- _require_discovery_allowed(invocation, view_id)
241
- data = service.call_view(view_id, method, **kwargs)
242
- else:
243
- data = service.call_view(view_id, method, dataset_id=int(dataset_id), **kwargs)
254
+ try:
255
+ if dataset_id is None:
256
+ _require_discovery_allowed(invocation, view_id)
257
+ data = service.call_view(view_id, method, **kwargs)
258
+ else:
259
+ data = service.call_view(view_id, method, dataset_id=int(dataset_id), **kwargs)
260
+ except CliError as exc:
261
+ # SDK >= 0.7.12 raises on the same job result; enrich it the same way.
262
+ response = exc.details.get("response") if isinstance(exc.details, dict) else None
263
+ reject_pipeline_reference_errors(service, view_id, dataset_id, response)
264
+ raise
265
+ reject_pipeline_reference_errors(service, view_id, dataset_id, data)
244
266
  return data, _meta(invocation, auth.workspace_id)
245
267
 
246
268
 
269
+ def _compact_reference_error(entry: Any) -> dict[str, Any]:
270
+ if not isinstance(entry, dict):
271
+ return {"reason": str(entry)}
272
+ raw_column = entry.get("column")
273
+ column: dict[str, Any] = raw_column if isinstance(raw_column, dict) else {}
274
+ return {
275
+ "column": column.get("display_name"),
276
+ "internal_name": column.get("internal_name"),
277
+ "type": column.get("type"),
278
+ "reason": entry.get("reason"),
279
+ "error_code": entry.get("error_code"),
280
+ }
281
+
282
+
283
+ def reject_pipeline_reference_errors(
284
+ service: Any, view_id: int, dataset_id: Any, data: Any
285
+ ) -> None:
286
+ """Fail a pipeline mutation whose task the backend accepted but could not bind.
287
+
288
+ A task that references a missing column or the wrong column type is stored
289
+ with ``reference_errors`` and answered with ``has_error: true``; the
290
+ pipeline then sits in ``ref_error`` and every read of the view fails with
291
+ 4DTVW019 until the task is removed. The SDK reads the view's draft flag
292
+ after the submit, and the backend flips that flag on a reference error, so
293
+ the SDK returns the job result instead of raising. Turn that into one
294
+ envelope that names the column, the reason and the exact repair command.
295
+ """
296
+ if not (isinstance(data, dict) and data.get("has_error") is True):
297
+ return
298
+ kwargs: dict[str, Any] = {"dataview_id": view_id}
299
+ if dataset_id is not None:
300
+ kwargs["dataset_id"] = int(dataset_id)
301
+ pipeline: dict[str, Any] = {}
302
+ broken: list[dict[str, Any]] = []
303
+ try:
304
+ read = service.call(_PIPELINE_SYMBOL, **kwargs)
305
+ if isinstance(read, dict):
306
+ pipeline = read
307
+ items = service.call(_PIPELINE_ITEMS_SYMBOL, fields=_PIPELINE_ITEMS_FULL, **kwargs)
308
+ if isinstance(items, dict):
309
+ broken = [
310
+ item
311
+ for item in items.get("items") or []
312
+ if isinstance(item, dict) and item.get("reference_errors")
313
+ ]
314
+ except CliError:
315
+ # The mutation already failed; a failed follow-up read must not hide that.
316
+ pass
317
+ reference_errors = [
318
+ _compact_reference_error(entry)
319
+ for item in broken
320
+ for entry in (item.get("reference_errors") or {}).get("reference_errors") or []
321
+ ]
322
+ task_ids = [item.get("id") for item in broken if item.get("id") is not None]
323
+ first = reference_errors[0] if reference_errors else {}
324
+ reason = str(first.get("reason") or "").lower()
325
+ column = first.get("column")
326
+ what = f"column '{column}' ({first.get('type')})" if column else "a column it references"
327
+ why = _REFERROR_REASON_HINTS.get(reason, f"reason: {reason or 'unknown'}")
328
+ raise CliError(
329
+ code=CODE_PIPELINE_REFERENCE_ERROR,
330
+ message=(
331
+ f"The task was added to view {view_id} but cannot bind to {what}; "
332
+ "the pipeline is in ref_error and the data did not change."
333
+ ),
334
+ exit_status=EXIT_API,
335
+ hint=(
336
+ f"Reads of view {view_id} fail (4DTVW019) until the task is removed: "
337
+ f"run the recovery command, then fix the input ({why})."
338
+ ),
339
+ details={
340
+ "view_id": view_id,
341
+ "dataset_id": kwargs.get("dataset_id"),
342
+ "pipeline_state": pipeline.get("state"),
343
+ "task_ids": task_ids,
344
+ "reference_errors": reference_errors,
345
+ "response": data,
346
+ },
347
+ recovery_commands=[
348
+ f"mammoth view task delete {view_id} {task_id} --yes" for task_id in task_ids
349
+ ]
350
+ or [f'mammoth view pipeline items {view_id} --input \'{{"fields": "__full"}}\''],
351
+ )
352
+
353
+
247
354
  def _profile_name(invocation: Invocation) -> str:
248
355
  return invocation.profile or profiles.get_selected()
249
356
 
@@ -269,6 +269,25 @@ _EXAMPLE_INPUT_HINTS: dict[str, dict[str, Any]] = {
269
269
  "view.data-check.update": {
270
270
  "body": {"patches": [{"op": "command", "path": "disable", "value": None}]},
271
271
  },
272
+ # ARGUMENT is the column's *internal* name (metadata[].internal_name from
273
+ # view get); a display name makes the backend fail with HTTP 500.
274
+ "view.derivative.create": {
275
+ "body": {
276
+ "param": {
277
+ "METRIC": {
278
+ "AS": "total",
279
+ "EXPRESSION": [
280
+ {
281
+ "TYPE": "FUNCTION",
282
+ "VALUE": {"ARGUMENT": "column_1", "FUNCTION": "SUM"},
283
+ }
284
+ ],
285
+ }
286
+ }
287
+ },
288
+ },
289
+ # The web app posts {condition, limit: null}; an empty body is 4GENR007.
290
+ "view.derivative.data": {"body": {"limit": None}},
272
291
  # The backend accepts NUMERIC, TEXT or DATE (4PARM008 otherwise).
273
292
  "parameter.create": {"param_type": "TEXT", "value": "Q3"},
274
293
  # The backend requires a placement ("Data check position must be given");
@@ -1,13 +1,13 @@
1
1
  [project]
2
2
  name = "mammoth-cli"
3
- version = "2.0.24"
3
+ version = "2.0.26"
4
4
  description = "Command-line interface for the Mammoth Analytics platform"
5
5
  authors = [{name = "Mammoth Analytics", email = "support@mammoth.io"}]
6
6
  readme = "README.md"
7
7
  license = "LicenseRef-Proprietary"
8
8
  requires-python = ">=3.12,<3.15"
9
9
  dependencies = [
10
- "mammoth-io (>=0.7.11,<0.8)",
10
+ "mammoth-io (>=0.7.12,<0.8)",
11
11
  "typer (>=0.27,<0.28)",
12
12
  "rich (>=15,<16)",
13
13
  "platformdirs (>=4.10,<5)",
@@ -3560,7 +3560,9 @@ commands:
3560
3560
  - CT-DASHBOARD-TEMPLATE-CREATE-ERROR
3561
3561
  draft_test: null
3562
3562
  undo_test: null
3563
- known_restrictions: null
3563
+ known_restrictions: 'dashboard_id must name a dashboard whose widgets bind dataset columns; a blank dashboard
3564
+ fails with "None of the columns this template binds are in the dataset". Build the dashboard first (dashboard
3565
+ create, then widgets), then save it as a template.'
3564
3566
  reviewed_by: primary
3565
3567
  - command_id: dashboard.template.delete
3566
3568
  command_path: dashboard template delete
@@ -993,7 +993,7 @@ commands:
993
993
  - CT-VIEW-DATA-CHECK-UPDATE-ERROR
994
994
  draft_test: null
995
995
  undo_test: null
996
- known_restrictions: 'patches are {op: command, path: enable|disable, value: null} or {op: replace, path: spec, value: AddDataCheckSpec}. On release the PATCH returns HTTP 500 (outcome_unknown) after applying; read the check back with view data-check get.'
996
+ known_restrictions: 'patches are {op: command, path: enable|disable, value: null} or {op: replace, path: spec, value: AddDataCheckSpec}, the same body the web app sends. On release the PATCH returns HTTP 500 (outcome_unknown) from backend validation that runs after the change is committed; read the check back with view data-check get before retrying.'
997
997
  reviewed_by: primary
998
998
  - command_id: view.data.get
999
999
  command_path: view data get
@@ -1173,7 +1173,7 @@ commands:
1173
1173
  secret_fields: []
1174
1174
  human_example: mammoth view derivative create VIEW_ID --help
1175
1175
  agent_example: 'mammoth view derivative create 123 123 --input ''{"body": {"param": {"METRIC": {"AS":
1176
- "sample", "EXPRESSION": [{"TYPE": "FUNCTION", "VALUE": {"ARGUMENT": "sample", "FUNCTION": "SUM"}}]}}}}'''
1176
+ "total", "EXPRESSION": [{"TYPE": "FUNCTION", "VALUE": {"ARGUMENT": "column_1", "FUNCTION": "SUM"}}]}}}}'''
1177
1177
  unit_tests:
1178
1178
  - UT-VIEW-DERIVATIVE-CREATE
1179
1179
  contract_tests:
@@ -1182,7 +1182,9 @@ commands:
1182
1182
  - CT-VIEW-DERIVATIVE-CREATE-ERROR
1183
1183
  draft_test: null
1184
1184
  undo_test: null
1185
- known_restrictions: null
1185
+ known_restrictions: 'ARGUMENT and any column reference in the METRIC expression are internal names (metadata[].internal_name
1186
+ from view get, e.g. column_1), not display names; a display name makes the backend fail with HTTP 500. The
1187
+ result is {"id": N}; read the value with view derivative data.'
1186
1188
  reviewed_by: primary
1187
1189
  - command_id: view.derivative.data
1188
1190
  command_path: view derivative data
@@ -1226,8 +1228,7 @@ commands:
1226
1228
  required_fixture_guard: null
1227
1229
  secret_fields: []
1228
1230
  human_example: mammoth view derivative data VIEW_ID DERIVATIVE_ID --help
1229
- agent_example: 'mammoth view derivative data 123 123 123 --input ''{"body": {"condition": {"FILTER_TYPE":
1230
- "SHOW"}}}'''
1231
+ agent_example: 'mammoth view derivative data 123 123 123 --input ''{"body": {"limit": null}}'''
1231
1232
  unit_tests:
1232
1233
  - UT-VIEW-DERIVATIVE-DATA
1233
1234
  contract_tests:
@@ -1236,7 +1237,9 @@ commands:
1236
1237
  - CT-VIEW-DERIVATIVE-DATA-ERROR
1237
1238
  draft_test: null
1238
1239
  undo_test: null
1239
- known_restrictions: null
1240
+ known_restrictions: 'body is {"condition": CONDITION_OR_NULL, "limit": null}, the same document the web app posts;
1241
+ {"limit": null} is the minimal accepted body and an empty body is rejected (4GENR007). Returns STATUS, the
1242
+ metric row(s) under data and their metadata.'
1240
1243
  reviewed_by: primary
1241
1244
  - command_id: view.derivative.delete
1242
1245
  command_path: view derivative delete
@@ -3786,8 +3789,7 @@ commands:
3786
3789
  - CT-VIEW-TRANSFORM-BULK-REPLACE-ERROR
3787
3790
  draft_test: LT-VIEW-TRANSFORM-BULK-REPLACE-DRAFT
3788
3791
  undo_test: LT-VIEW-TRANSFORM-BULK-REPLACE-UNDO
3789
- known_restrictions: Complete flags/defaults/result/draft/undo/live contract is specified in plan 02's
3790
- 'Complete bulk-replace command contract'; this appendix does not narrow or replace it.
3792
+ known_restrictions: 'Complete flags/defaults/result/draft/undo/live contract is specified in plan 02''s ''Complete bulk-replace command contract''; this appendix does not narrow or replace it. columns must be TEXT (metadata[].type from view get): a NUMERIC or DATE column is stored with a type-mismatch reference error, the view enters ref_error and the CLI answers pipeline_reference_error with the view task delete that removes the task.'
3791
3793
  reviewed_by: primary
3792
3794
  - command_id: view.transform.combine-columns
3793
3795
  command_path: view transform combine-columns
@@ -4535,7 +4537,9 @@ commands:
4535
4537
  - CT-VIEW-TRANSFORM-PIVOT-ERROR
4536
4538
  draft_test: LT-VIEW-TRANSFORM-PIVOT-DRAFT
4537
4539
  undo_test: LT-VIEW-TRANSFORM-PIVOT-UNDO
4538
- known_restrictions: null
4540
+ known_restrictions: 'Replaces the view''s columns with the summary, so run it last (export rows first). Every as_name
4541
+ must be a display name that does not already exist on the view (4DTVW018 SAME_DISPLAY_NAME_CANNOT_BE_REUSED):
4542
+ aggregate a joined column under a new name.'
4539
4543
  reviewed_by: primary
4540
4544
  - command_id: view.transform.replace
4541
4545
  command_path: view transform replace
@@ -4576,7 +4580,7 @@ commands:
4576
4580
  - CT-VIEW-TRANSFORM-REPLACE-ERROR
4577
4581
  draft_test: LT-VIEW-TRANSFORM-REPLACE-DRAFT
4578
4582
  undo_test: LT-VIEW-TRANSFORM-REPLACE-UNDO
4579
- known_restrictions: null
4583
+ known_restrictions: 'columns must be TEXT (metadata[].type from view get): a NUMERIC or DATE column is stored with a type-mismatch reference error, the view enters ref_error and the CLI answers pipeline_reference_error with the view task delete that removes the task.'
4580
4584
  reviewed_by: primary
4581
4585
  - command_id: view.transform.set-values
4582
4586
  command_path: view transform set-values
File without changes
File without changes
File without changes