mammoth-cli 2.0.82__tar.gz → 2.0.84__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 (236) hide show
  1. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/PKG-INFO +2 -2
  2. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/mammoth_cli/__init__.py +1 -1
  3. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/mammoth_cli/app.py +3 -1
  4. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/mammoth_cli/bundled_skill/mammoth-cli/references/capabilities-misc.md +0 -2
  5. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/mammoth_cli/bundled_skill/mammoth-cli/references/capabilities.md +2 -2
  6. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/mammoth_cli/bundled_skill/mammoth-cli/references/command-index.md +2 -2
  7. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/billing.md +1 -11
  8. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/connector.md +6 -4
  9. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/dataset.md +10 -0
  10. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/mammoth_cli/commands/billing.py +2 -13
  11. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/mammoth_cli/commands/dataset.py +12 -0
  12. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/mammoth_cli/commands/registry.py +1 -1
  13. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/mammoth_cli/commands/schema.py +18 -1
  14. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/mammoth_cli/commands/view.py +68 -13
  15. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/mammoth_cli/commands/view_ops.py +26 -7
  16. mammoth_cli-2.0.84/mammoth_cli/runtime/dataset_health.py +62 -0
  17. mammoth_cli-2.0.84/mammoth_cli/runtime/new_data.py +86 -0
  18. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/mammoth_cli/runtime/verify.py +10 -2
  19. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/mammoth_cli/services/conditions.py +5 -0
  20. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/mammoth_cli/services/data_quality.py +82 -1
  21. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/pyproject.toml +2 -2
  22. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/spec/manifests/commands/billing.yaml +1 -42
  23. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/spec/manifests/commands/connector.yaml +6 -5
  24. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/spec/manifests/commands/dataset.yaml +39 -0
  25. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/spec/manifests/openapi-operations.yaml +10 -10
  26. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/spec/manifests/sdk-catalog.source.yaml +7 -7
  27. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/spec/manifests/sdk-methods.yaml +19 -17
  28. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/.gitignore +0 -0
  29. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/LICENSE +0 -0
  30. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/README.md +0 -0
  31. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/mammoth_cli/__main__.py +0 -0
  32. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/mammoth_cli/bundled_skill/mammoth-cli/SKILL.md +0 -0
  33. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/mammoth_cli/bundled_skill/mammoth-cli/references/about-mammoth.md +0 -0
  34. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/mammoth_cli/bundled_skill/mammoth-cli/references/auth.md +0 -0
  35. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/activity.md +0 -0
  36. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/addon.md +0 -0
  37. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/agent.md +0 -0
  38. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/ai.md +0 -0
  39. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/annotation.md +0 -0
  40. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/auth.md +0 -0
  41. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/automation.md +0 -0
  42. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/batch.md +0 -0
  43. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/browse.md +0 -0
  44. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/calc.md +0 -0
  45. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/capability.md +0 -0
  46. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/client-app.md +0 -0
  47. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/completion.md +0 -0
  48. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/config.md +0 -0
  49. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/context.md +0 -0
  50. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/dashboard-qa.md +0 -0
  51. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/dashboard.md +0 -0
  52. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/data-app.md +0 -0
  53. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/doctor.md +0 -0
  54. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/external-key.md +0 -0
  55. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/file.md +0 -0
  56. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/folder.md +0 -0
  57. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/job.md +0 -0
  58. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/log.md +0 -0
  59. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/notification.md +0 -0
  60. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/parameter.md +0 -0
  61. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/project.md +0 -0
  62. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/report.md +0 -0
  63. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/schedule.md +0 -0
  64. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/schema.md +0 -0
  65. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/skill.md +0 -0
  66. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/snippet.md +0 -0
  67. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/support.md +0 -0
  68. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/template.md +0 -0
  69. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/trash.md +0 -0
  70. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/upgrade.md +0 -0
  71. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/user.md +0 -0
  72. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/version.md +0 -0
  73. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/view-transform.md +0 -0
  74. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/view.md +0 -0
  75. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/webhook.md +0 -0
  76. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/workflow.md +0 -0
  77. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/workspace.md +0 -0
  78. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/mammoth_cli/bundled_skill/mammoth-cli/references/handoff.md +0 -0
  79. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/mammoth_cli/bundled_skill/mammoth-cli/references/input.md +0 -0
  80. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/mammoth_cli/bundled_skill/mammoth-cli/references/jobs-drafts.md +0 -0
  81. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/mammoth_cli/bundled_skill/mammoth-cli/references/machine-output.md +0 -0
  82. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/mammoth_cli/bundled_skill/mammoth-cli/references/operations.md +0 -0
  83. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/mammoth_cli/bundled_skill/mammoth-cli/references/recipes/auth-scope.md +0 -0
  84. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/mammoth_cli/bundled_skill/mammoth-cli/references/recipes/cleanup.md +0 -0
  85. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/mammoth_cli/bundled_skill/mammoth-cli/references/recipes/dashboards.md +0 -0
  86. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/mammoth_cli/bundled_skill/mammoth-cli/references/recipes/end-to-end.md +0 -0
  87. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/mammoth_cli/bundled_skill/mammoth-cli/references/recipes/exports.md +0 -0
  88. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/mammoth_cli/bundled_skill/mammoth-cli/references/recipes/index.md +0 -0
  89. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/mammoth_cli/bundled_skill/mammoth-cli/references/recipes/need-action.md +0 -0
  90. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/mammoth_cli/bundled_skill/mammoth-cli/references/recipes/resources.md +0 -0
  91. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/mammoth_cli/bundled_skill/mammoth-cli/references/recipes/scheduling.md +0 -0
  92. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/mammoth_cli/bundled_skill/mammoth-cli/references/recipes/transforms.md +0 -0
  93. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/mammoth_cli/bundled_skill/mammoth-cli/references/recipes/typed-etl-discovery.md +0 -0
  94. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/mammoth_cli/bundled_skill/mammoth-cli/references/recovery.md +0 -0
  95. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/mammoth_cli/bundled_skill/mammoth-cli/references/report-checklist.md +0 -0
  96. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/mammoth_cli/bundled_skill/mammoth-cli/references/retention.md +0 -0
  97. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/mammoth_cli/bundled_skill/mammoth-cli/references/safety.md +0 -0
  98. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/mammoth_cli/bundled_skill/mammoth-cli/references/task-start.md +0 -0
  99. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/mammoth_cli/commands/__init__.py +0 -0
  100. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/mammoth_cli/commands/activity.py +0 -0
  101. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/mammoth_cli/commands/addon.py +0 -0
  102. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/mammoth_cli/commands/agent.py +0 -0
  103. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/mammoth_cli/commands/ai.py +0 -0
  104. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/mammoth_cli/commands/annotation.py +0 -0
  105. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/mammoth_cli/commands/auth.py +0 -0
  106. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/mammoth_cli/commands/automation.py +0 -0
  107. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/mammoth_cli/commands/batch.py +0 -0
  108. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/mammoth_cli/commands/browse.py +0 -0
  109. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/mammoth_cli/commands/calc.py +0 -0
  110. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/mammoth_cli/commands/capability.py +0 -0
  111. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/mammoth_cli/commands/client_app.py +0 -0
  112. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/mammoth_cli/commands/completion.py +0 -0
  113. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/mammoth_cli/commands/config.py +0 -0
  114. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/mammoth_cli/commands/connector.py +0 -0
  115. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/mammoth_cli/commands/context.py +0 -0
  116. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/mammoth_cli/commands/dashboard.py +0 -0
  117. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/mammoth_cli/commands/data_app.py +0 -0
  118. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/mammoth_cli/commands/doctor.py +0 -0
  119. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/mammoth_cli/commands/external_key.py +0 -0
  120. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/mammoth_cli/commands/file.py +0 -0
  121. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/mammoth_cli/commands/folder.py +0 -0
  122. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/mammoth_cli/commands/job.py +0 -0
  123. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/mammoth_cli/commands/notification.py +0 -0
  124. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/mammoth_cli/commands/parameter.py +0 -0
  125. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/mammoth_cli/commands/project.py +0 -0
  126. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/mammoth_cli/commands/report.py +0 -0
  127. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/mammoth_cli/commands/schedule.py +0 -0
  128. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/mammoth_cli/commands/skill.py +0 -0
  129. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/mammoth_cli/commands/snippet.py +0 -0
  130. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/mammoth_cli/commands/support.py +0 -0
  131. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/mammoth_cli/commands/template.py +0 -0
  132. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/mammoth_cli/commands/trash.py +0 -0
  133. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/mammoth_cli/commands/upgrade.py +0 -0
  134. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/mammoth_cli/commands/user.py +0 -0
  135. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/mammoth_cli/commands/webhook.py +0 -0
  136. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/mammoth_cli/commands/workflow.py +0 -0
  137. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/mammoth_cli/commands/workspace.py +0 -0
  138. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/mammoth_cli/context/__init__.py +0 -0
  139. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/mammoth_cli/context/credentials.py +0 -0
  140. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/mammoth_cli/context/endpoint.py +0 -0
  141. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/mammoth_cli/context/profiles.py +0 -0
  142. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/mammoth_cli/context/resolver.py +0 -0
  143. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/mammoth_cli/contracts/__init__.py +0 -0
  144. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/mammoth_cli/contracts/auth.py +0 -0
  145. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/mammoth_cli/embed.py +0 -0
  146. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/mammoth_cli/errors/__init__.py +0 -0
  147. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/mammoth_cli/errors/envelope.py +0 -0
  148. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/mammoth_cli/manifest/__init__.py +0 -0
  149. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/mammoth_cli/manifest/loader.py +0 -0
  150. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/mammoth_cli/messages/__init__.py +0 -0
  151. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/mammoth_cli/output/__init__.py +0 -0
  152. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/mammoth_cli/output/envelope.py +0 -0
  153. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/mammoth_cli/output/normalize.py +0 -0
  154. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/mammoth_cli/output/policy.py +0 -0
  155. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/mammoth_cli/output/progress.py +0 -0
  156. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/mammoth_cli/output/render.py +0 -0
  157. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/mammoth_cli/py.typed +0 -0
  158. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/mammoth_cli/runtime/__init__.py +0 -0
  159. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/mammoth_cli/runtime/confirm.py +0 -0
  160. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/mammoth_cli/runtime/dryrun.py +0 -0
  161. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/mammoth_cli/runtime/embedded.py +0 -0
  162. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/mammoth_cli/runtime/executor.py +0 -0
  163. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/mammoth_cli/runtime/input_loader.py +0 -0
  164. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/mammoth_cli/runtime/invocation.py +0 -0
  165. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/mammoth_cli/runtime/options.py +0 -0
  166. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/mammoth_cli/runtime/parents.py +0 -0
  167. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/mammoth_cli/runtime/runlog.py +0 -0
  168. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/mammoth_cli/runtime/session.py +0 -0
  169. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/mammoth_cli/runtime/state.py +0 -0
  170. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/mammoth_cli/runtime/strict.py +0 -0
  171. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/mammoth_cli/runtime/updates.py +0 -0
  172. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/mammoth_cli/runtime/validate.py +0 -0
  173. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/mammoth_cli/services/__init__.py +0 -0
  174. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/mammoth_cli/services/argspec.py +0 -0
  175. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/mammoth_cli/services/coerce.py +0 -0
  176. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/mammoth_cli/services/command_contract.py +0 -0
  177. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/mammoth_cli/services/dashboard_pages.py +0 -0
  178. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/mammoth_cli/services/dashboard_review.py +0 -0
  179. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/mammoth_cli/services/dispatch.py +0 -0
  180. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/mammoth_cli/services/factory.py +0 -0
  181. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/mammoth_cli/services/input_fields.py +0 -0
  182. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/mammoth_cli/services/mapping.py +0 -0
  183. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/mammoth_cli/services/openapi_types.py +0 -0
  184. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/mammoth_cli/services/positionals.py +0 -0
  185. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/mammoth_cli/services/protocol.py +0 -0
  186. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/mammoth_cli/services/sdk_service.py +0 -0
  187. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/mammoth_cli/services/testing.py +0 -0
  188. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/mammoth_cli/services/type_system.py +0 -0
  189. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/mammoth_cli/skills/__init__.py +0 -0
  190. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/mammoth_cli/skills/installer.py +0 -0
  191. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/mammoth_cli/skills/steering.py +0 -0
  192. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/mammoth_cli/testing.py +0 -0
  193. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/spec/manifests/commands/activity.yaml +0 -0
  194. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/spec/manifests/commands/addon.yaml +0 -0
  195. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/spec/manifests/commands/agent.yaml +0 -0
  196. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/spec/manifests/commands/ai.yaml +0 -0
  197. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/spec/manifests/commands/annotation.yaml +0 -0
  198. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/spec/manifests/commands/auth.yaml +0 -0
  199. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/spec/manifests/commands/automation.yaml +0 -0
  200. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/spec/manifests/commands/batch.yaml +0 -0
  201. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/spec/manifests/commands/browse.yaml +0 -0
  202. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/spec/manifests/commands/calc.yaml +0 -0
  203. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/spec/manifests/commands/capability.yaml +0 -0
  204. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/spec/manifests/commands/client-app.yaml +0 -0
  205. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/spec/manifests/commands/completion.yaml +0 -0
  206. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/spec/manifests/commands/config.yaml +0 -0
  207. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/spec/manifests/commands/context.yaml +0 -0
  208. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/spec/manifests/commands/dashboard.yaml +0 -0
  209. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/spec/manifests/commands/data-app.yaml +0 -0
  210. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/spec/manifests/commands/doctor.yaml +0 -0
  211. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/spec/manifests/commands/external-key.yaml +0 -0
  212. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/spec/manifests/commands/file.yaml +0 -0
  213. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/spec/manifests/commands/folder.yaml +0 -0
  214. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/spec/manifests/commands/job.yaml +0 -0
  215. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/spec/manifests/commands/log.yaml +0 -0
  216. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/spec/manifests/commands/notification.yaml +0 -0
  217. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/spec/manifests/commands/parameter.yaml +0 -0
  218. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/spec/manifests/commands/project.yaml +0 -0
  219. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/spec/manifests/commands/report.yaml +0 -0
  220. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/spec/manifests/commands/schedule.yaml +0 -0
  221. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/spec/manifests/commands/schema.yaml +0 -0
  222. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/spec/manifests/commands/skill.yaml +0 -0
  223. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/spec/manifests/commands/snippet.yaml +0 -0
  224. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/spec/manifests/commands/support.yaml +0 -0
  225. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/spec/manifests/commands/template.yaml +0 -0
  226. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/spec/manifests/commands/trash.yaml +0 -0
  227. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/spec/manifests/commands/upgrade.yaml +0 -0
  228. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/spec/manifests/commands/user.yaml +0 -0
  229. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/spec/manifests/commands/version.yaml +0 -0
  230. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/spec/manifests/commands/view.yaml +0 -0
  231. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/spec/manifests/commands/webhook.yaml +0 -0
  232. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/spec/manifests/commands/workflow.yaml +0 -0
  233. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/spec/manifests/commands/workspace.yaml +0 -0
  234. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/spec/manifests/schema-v1.json +0 -0
  235. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/spec/openapi/metadata.json +0 -0
  236. {mammoth_cli-2.0.82 → mammoth_cli-2.0.84}/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.82
3
+ Version: 2.0.84
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.36
20
+ Requires-Dist: mammoth-io<0.8,>=0.7.38
21
21
  Requires-Dist: platformdirs<5,>=4.10
22
22
  Requires-Dist: pydantic<3,>=2.12.5
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.82"
9
+ __version__ = "2.0.84"
10
10
 
11
11
  # The versioned machine output envelope contract.
12
12
  SCHEMA_VERSION = 1
@@ -42,6 +42,8 @@ from mammoth_cli.output.policy import (
42
42
  resolve_output,
43
43
  )
44
44
  from mammoth_cli.runtime import executor, validate
45
+ from mammoth_cli.runtime.dataset_health import with_dataset_health
46
+ from mammoth_cli.runtime.new_data import with_new_data_path
45
47
  from mammoth_cli.runtime.invocation import Invocation
46
48
  from mammoth_cli.runtime.state import with_state
47
49
  from mammoth_cli.runtime.strict import validate_extra_args
@@ -826,7 +828,7 @@ def _execute(invocation: Invocation) -> None:
826
828
  if invocation.dry_run:
827
829
  return _dry_run(handler, invocation)
828
830
  data, meta = handler(invocation)
829
- return _apply_verify(invocation, data), meta
831
+ return with_new_data_path(with_dataset_health(_apply_verify(invocation, data))), meta
830
832
 
831
833
  executor.run(
832
834
  invocation.command_id,
@@ -47,8 +47,6 @@ Ran once: `billing.stripe.history`, `billing.stripe.payment-method.list`, `billi
47
47
  | Command | State | Note |
48
48
  |---|---|---|
49
49
  | `billing.chargebee-plan` | observed blocker | backend_error: The CLI gates this GET behind --yes --confirm WORKSPACE_ID; with confirmation: HTTP 400 4SUBS014 'Chargebee plan not found for the given workspace' (workspace 4 is n |
50
- | `billing.invoice.get` | observed blocker | blocked_missing_fixture: The CLI gates this GET behind --yes --confirm WORKSPACE_ID; with confirmation: billing invoice list answered HTTP 500, so no invoice id was observed |
51
- | `billing.invoice.list` | observed blocker | backend_error: The CLI gates this GET behind --yes --confirm WORKSPACE_ID; with confirmation: HTTP 500 with empty body on GET /workspaces/4/subscription_v1/invoices |
52
50
  | `billing.stripe.preview-invoice` | observed blocker | backend_error: The CLI gates this GET behind --yes --confirm WORKSPACE_ID; with confirmation: HTTP 400 4SUBS037 'Failed to perform subscription operation' |
53
51
  | `billing.stripe.upcoming-invoice` | observed blocker | backend_error: The CLI gates this GET behind --yes --confirm WORKSPACE_ID; with confirmation: HTTP 400 4SUBS074 'Upcoming invoice not found' (no active Stripe subscription on works |
54
52
  | `billing.stripe.usage` | observed blocker | backend_error: The CLI gates this GET behind --yes --confirm WORKSPACE_ID; with confirmation: HTTP 400 5GENR010 UNKNOWN_ERROR 'Unknown error occurred |
@@ -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 567 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 (`view transform *` commands submit through `view.task.add`, except `rename-columns` and `sort`, which set view display properties through `view.update`). 262 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 573 commands. 453 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 (`view transform *` commands submit through `view.task.add`, except `rename-columns` and `sort`, which set view display properties through `view.update`). 262 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
 
@@ -20,8 +20,8 @@ The typed `view transform *` commands all submit through `view.task.add` (`renam
20
20
  | `dashboard` | 104 | 81 | 2 | 21 |
21
21
  | `view` | 62 | 58 | 0 | 4 |
22
22
  | `support` | 45 | 9 | 0 | 36 |
23
- | `billing` | 23 | 4 | 0 | 19 |
24
23
  | `connector` | 22 | 3 | 0 | 19 |
24
+ | `billing` | 21 | 4 | 0 | 17 |
25
25
  | `workspace` | 19 | 7 | 0 | 12 |
26
26
  | `project` | 17 | 15 | 0 | 2 |
27
27
  | `workflow` | 16 | 9 | 0 | 7 |
@@ -12,7 +12,7 @@ Load only the applicable domain file:
12
12
  - [auth](commands/auth.md) — 3 published commands
13
13
  - [automation](commands/automation.md) — 7 published commands
14
14
  - [batch](commands/batch.md) — 7 published commands
15
- - [billing](commands/billing.md) — 23 published commands
15
+ - [billing](commands/billing.md) — 22 published commands
16
16
  - [browse](commands/browse.md) — 4 published commands
17
17
  - [calc](commands/calc.md) — 1 published commands
18
18
  - [capability](commands/capability.md) — 3 published commands
@@ -24,7 +24,7 @@ Load only the applicable domain file:
24
24
  - [dashboard-qa](commands/dashboard-qa.md) — 13 published commands
25
25
  - [dashboard](commands/dashboard.md) — 100 published commands
26
26
  - [data-app](commands/data-app.md) — 12 published commands
27
- - [dataset](commands/dataset.md) — 17 published commands
27
+ - [dataset](commands/dataset.md) — 18 published commands
28
28
  - [doctor](commands/doctor.md) — 1 published commands
29
29
  - [external-key](commands/external-key.md) — 4 published commands
30
30
  - [file](commands/file.md) — 9 published commands
@@ -32,16 +32,6 @@ Result: `BillingInvoiceChargeResult`; mutation `high_impact`, confirmation `conf
32
32
 
33
33
  Status on release: untried; no live run recorded.
34
34
 
35
- ### `billing.invoice.get`
36
-
37
- Run: `mammoth billing invoice get`. Exact input fields: `mammoth schema get billing.invoice.get`.
38
-
39
- Example: `mammoth billing invoice get 123`. Placeholders are illustrative; resolve IDs and input from observed reads.
40
-
41
- Result: `BillingInvoiceGetResult`; mutation `read`, confirmation `none`, wait policy `not_async`.
42
-
43
- Status on release: observed blocker — blocked_missing_fixture: The CLI gates this GET behind --yes --confirm WORKSPACE_ID; with confirmation: billing invoice list answered HTTP 500, so no invoice id was observed. Re-check before relying on it.
44
-
45
35
  ### `billing.invoice.list`
46
36
 
47
37
  Run: `mammoth billing invoice list`. Exact input fields: `mammoth schema get billing.invoice.list`.
@@ -50,7 +40,7 @@ Example: `mammoth billing invoice list`. Placeholders are illustrative; resolve
50
40
 
51
41
  Result: `BillingInvoiceListResult`; mutation `read`, confirmation `none`, wait policy `not_async`.
52
42
 
53
- Status on release: observed blocker — backend_error: The CLI gates this GET behind --yes --confirm WORKSPACE_ID; with confirmation: HTTP 500 with empty body on GET /workspaces/4/subscription_v1/invoices. Re-check before relying on it.
43
+ Status on release: untried; no live run recorded.
54
44
 
55
45
  ### `billing.stripe.cancel`
56
46
 
@@ -76,7 +76,9 @@ Status on release: untried; no live run recorded.
76
76
 
77
77
  Run: `mammoth connector connection create`. Exact input fields: `mammoth schema get connector.connection.create`.
78
78
 
79
- Example: `mammoth connector connection create sample --input '{"config": {"sample_key": "Status"}}'`. Illustrative only: append `--yes` after observing an owned target.
79
+ Example: `mammoth connector connection create sample --input /private/path/request.json`. Illustrative only: append `--yes` after observing an owned target.
80
+
81
+ Secret fields: pass the body as `--input FILE` (mode 0600); never inline.
80
82
 
81
83
  Result: `ConnectorConnectionCreateResult`; mutation `external_effect`, confirmation `yes_always`, wait policy `not_async`.
82
84
 
@@ -116,7 +118,9 @@ Status on release: observed blocker — server_error: see sweep report. Re-check
116
118
 
117
119
  Run: `mammoth connector connection update`. Exact input fields: `mammoth schema get connector.connection.update`.
118
120
 
119
- Example: `mammoth connector connection update sample sample --input '{"credentials": {"sample_key": "Status"}}'`. Illustrative only: append `--yes` after observing an owned target.
121
+ Example: `mammoth connector connection update sample sample --input /private/path/request.json`. Illustrative only: append `--yes` after observing an owned target.
122
+
123
+ Secret fields: pass the body as `--input FILE` (mode 0600); never inline.
120
124
 
121
125
  Result: `ConnectorConnectionUpdateResult`; mutation `external_effect`, confirmation `yes_always`, wait policy `not_async`.
122
126
 
@@ -200,8 +204,6 @@ Example: `mammoth connector list`. Placeholders are illustrative; resolve IDs an
200
204
 
201
205
  Result: `ConnectorListResult`; mutation `read`, confirmation `none`, wait policy `not_async`.
202
206
 
203
- `is_premium: true` with `is_added: false` means the connector must be enabled by Mammoth sales before this workspace can use it -- not that nobody has set it up yet. Such an item also carries `availability: "premium_not_enabled"` and an `availability_note` saying so. Tell the user why (premium, not enabled here) and offer to contact Mammoth sales; there is no CLI command that enables a premium connector or contacts sales on the user's behalf.
204
-
205
207
  Status on release: ran once on CLI 2.0.18 — fixture-lifecycle sweep 2026-09-19: exit 0 on release with CLI 2.0.18. Listed 42 available connectors (name_key, disp_name, api_type, is_added, is_premium). Single invocation only.
206
208
 
207
209
  ### `connector.query.generate`
@@ -12,6 +12,16 @@ Result: `DatasetBatchDataResult`; mutation `read`, confirmation `none`, wait pol
12
12
 
13
13
  Status on release: ran once on CLI 1.1.11 — Published PyPI CLI 1.1.11 / SDK 0.7.1 batch-data read succeeded for an ID observed from retained dataset 29; bounded 50-row page. One observed-ID chain and page; not Full.
14
14
 
15
+ ### `dataset.broken-rows.list`
16
+
17
+ Run: `mammoth dataset broken-rows list`. Exact input fields: `mammoth schema get dataset.broken-rows.list`.
18
+
19
+ Example: `mammoth dataset broken-rows list 123`. Placeholders are illustrative; resolve IDs and input from observed reads.
20
+
21
+ Result: `DatasetBrokenRowsListResult`; mutation `read`, confirmation `none`, wait policy `not_async`.
22
+
23
+ Status on release: untried; no live run recorded.
24
+
15
25
  ### `dataset.bulk-delete`
16
26
 
17
27
  Run: `mammoth dataset bulk-delete`. Exact input fields: `mammoth schema get dataset.bulk-delete`.
@@ -171,21 +171,10 @@ def billing_invoice_charge(invocation: Invocation) -> HandlerResult:
171
171
  return data, _meta(invocation, auth.workspace_id, None)
172
172
 
173
173
 
174
- def billing_invoice_get(invocation: Invocation) -> HandlerResult:
175
- """Get one invoice by id."""
176
- invoice_id = _require_int_positional(invocation, "invoice id")
177
- with open_service(invocation) as (service, auth):
178
- data = service.call(_symbol(invocation), invoice_id=invoice_id)
179
- return data, _meta(invocation, auth.workspace_id, None)
180
-
181
-
182
174
  def billing_invoice_list(invocation: Invocation) -> HandlerResult:
183
- """List invoices for the workspace."""
184
- document = _bound_document(invocation)
185
- kwargs: dict[str, Any] = {}
186
- _forward_optional(document, kwargs, ("limit", "sort"))
175
+ """List invoices for the workspace (Stripe billing history)."""
187
176
  with open_service(invocation) as (service, auth):
188
- data = service.call(_symbol(invocation), **kwargs)
177
+ data = service.call(_symbol(invocation))
189
178
  return data, _meta(invocation, auth.workspace_id, None)
190
179
 
191
180
 
@@ -28,6 +28,7 @@ from mammoth_cli.runtime.confirm import (
28
28
  enforce_confirmation,
29
29
  )
30
30
  from mammoth_cli.runtime.invocation import Invocation
31
+ from mammoth_cli.runtime.new_data import with_file_upload_path
31
32
  from mammoth_cli.runtime.session import open_service, require_project
32
33
 
33
34
  HandlerResult = tuple[Any, dict[str, Any]]
@@ -322,6 +323,17 @@ def dataset_batch_data(invocation: Invocation) -> HandlerResult:
322
323
 
323
324
  def dataset_file_settings(invocation: Invocation) -> HandlerResult:
324
325
  """Get file settings (delimiter, header, dates, ...) for a dataset."""
326
+ data, meta = _read_dataset(invocation)
327
+ return with_file_upload_path(data, _require_int_positional(invocation, "dataset id")), meta
328
+
329
+
330
+ def dataset_broken_rows(invocation: Invocation) -> HandlerResult:
331
+ """List the lines of a dataset's uploaded file that could not be parsed."""
332
+ return _read_dataset(invocation)
333
+
334
+
335
+ def _read_dataset(invocation: Invocation) -> HandlerResult:
336
+ """Call this command's SDK read with the DATASET_ID positional."""
325
337
  project_id = require_project(invocation)
326
338
  dataset_id = _require_int_positional(invocation, "dataset id")
327
339
  if dataset_id <= 0:
@@ -314,6 +314,7 @@ HANDLERS: dict[str, Handler] = {
314
314
  "dataset.file-settings.get": dataset_cmd.dataset_file_settings,
315
315
  "dataset.file-settings.update": dataset_cmd.dataset_file_settings_update,
316
316
  "dataset.file-settings.undo": dataset_cmd.dataset_file_settings_undo,
317
+ "dataset.broken-rows.list": dataset_cmd.dataset_broken_rows,
317
318
  "dataset.create": dataset_cmd.dataset_create,
318
319
  "dataset.create-from-pdf": dataset_cmd.dataset_create_from_pdf,
319
320
  "dataset.rename": dataset_cmd.dataset_rename,
@@ -565,7 +566,6 @@ HANDLERS: dict[str, Handler] = {
565
566
  "billing.chargebee-plan": billing_cmd.billing_chargebee_plan,
566
567
  "billing.hosted-page": billing_cmd.billing_hosted_page,
567
568
  "billing.invoice.charge": billing_cmd.billing_invoice_charge,
568
- "billing.invoice.get": billing_cmd.billing_invoice_get,
569
569
  "billing.invoice.list": billing_cmd.billing_invoice_list,
570
570
  "billing.stripe.cancel": billing_cmd.billing_stripe_cancel,
571
571
  "billing.stripe.checkout-url": billing_cmd.billing_stripe_checkout_url,
@@ -1402,7 +1402,9 @@ def _schema_common(record: dict[str, Any]) -> dict[str, Any]:
1402
1402
  contract_level = (
1403
1403
  "opaque_expert"
1404
1404
  if record["command_id"] in _OPAQUE_EXPERT_COMMANDS
1405
- else "partially_typed" if opaque_fields else "typed"
1405
+ else "partially_typed"
1406
+ if opaque_fields
1407
+ else "typed"
1406
1408
  )
1407
1409
  return {
1408
1410
  "positionals": _positionals(record["command_id"]),
@@ -1558,6 +1560,13 @@ def _inline_call_detail(entries: list[dict[str, Any]]) -> None:
1558
1560
  entry["agent_example"] = record["agent_example"]
1559
1561
 
1560
1562
 
1563
+ #: How to drill down from a find: a family's full command list, or every family.
1564
+ _BROWSE_NEXT = (
1565
+ "mammoth schema list FAMILY lists every command in a family; mammoth schema list "
1566
+ "lists the families"
1567
+ )
1568
+
1569
+
1561
1570
  def find_schemas(
1562
1571
  query: str,
1563
1572
  *,
@@ -1747,9 +1756,17 @@ def find_schemas(
1747
1756
  if result["suggestions"]
1748
1757
  else _NO_MATCH_HINT_NO_SUGGESTIONS
1749
1758
  )
1759
+ result["browse"] = _browse(page or result.get("suggestions", []))
1750
1760
  return result
1751
1761
 
1752
1762
 
1763
+ def _browse(entries: list[dict[str, Any]]) -> dict[str, Any]:
1764
+ """The families behind *entries* and how to list each one in full: a keyword
1765
+ find surfaces one way to do a thing, its family holds the siblings."""
1766
+ families = list(dict.fromkeys(entry["command_path"].split()[0] for entry in entries))
1767
+ return {"families": families, "next": _BROWSE_NEXT}
1768
+
1769
+
1753
1770
  def get_schema(command_id: str) -> dict[str, Any] | None:
1754
1771
  record = command_by_id(command_id)
1755
1772
  if record is None or record.get("disposition") == "alias":
@@ -2073,13 +2073,16 @@ def view_pipeline_rerun(invocation: Invocation) -> HandlerResult:
2073
2073
  kwargs: dict[str, Any] = {"dataview_id": dataview_id}
2074
2074
  _forward_optional(document, kwargs, ("from_sequence", "dataset_id"))
2075
2075
  with open_service(invocation) as (service, auth):
2076
- data = service.call(_symbol(invocation), **kwargs)
2077
2076
  dataset_id = kwargs.get("dataset_id")
2078
2077
  if dataset_id is None:
2079
2078
  dataset_id = _resolve_dataset_id_for_settle(
2080
2079
  service, invocation, dataview_id, document, 1
2081
2080
  )
2082
- data = _settle_async_view_write(service, dataset_id, dataview_id, invocation.project, data)
2081
+ before = _rows_before(service, dataset_id, dataview_id, invocation.project)
2082
+ data = service.call(_symbol(invocation), **kwargs)
2083
+ data = _settle_async_view_write(
2084
+ service, dataset_id, dataview_id, invocation.project, data, before
2085
+ )
2083
2086
  return data, _meta(invocation, auth.workspace_id, None)
2084
2087
 
2085
2088
 
@@ -2133,13 +2136,16 @@ def view_task_delete(invocation: Invocation) -> HandlerResult:
2133
2136
  kwargs: dict[str, Any] = {"dataview_id": dataview_id, "task_id": task_id}
2134
2137
  _forward_optional(document, kwargs, ("dataset_id",))
2135
2138
  with open_service(invocation) as (service, auth):
2136
- data = service.call(_symbol(invocation), **kwargs)
2137
2139
  dataset_id = kwargs.get("dataset_id")
2138
2140
  if dataset_id is None:
2139
2141
  dataset_id = _resolve_dataset_id_for_settle(
2140
2142
  service, invocation, dataview_id, document, 2
2141
2143
  )
2142
- data = _settle_async_view_write(service, dataset_id, dataview_id, invocation.project, data)
2144
+ before = _rows_before(service, dataset_id, dataview_id, invocation.project)
2145
+ data = service.call(_symbol(invocation), **kwargs)
2146
+ data = _settle_async_view_write(
2147
+ service, dataset_id, dataview_id, invocation.project, data, before
2148
+ )
2143
2149
  return data, _meta(invocation, auth.workspace_id, None)
2144
2150
 
2145
2151
 
@@ -2193,13 +2199,16 @@ def view_task_update(invocation: Invocation) -> HandlerResult:
2193
2199
  assert document is not None
2194
2200
  _forward_optional(document, kwargs, ("dataset_id",))
2195
2201
  with open_service(invocation) as (service, auth):
2196
- data = service.call(_symbol(invocation), **kwargs)
2197
2202
  dataset_id = kwargs.get("dataset_id")
2198
2203
  if dataset_id is None:
2199
2204
  dataset_id = _resolve_dataset_id_for_settle(
2200
2205
  service, invocation, dataview_id, document, 2
2201
2206
  )
2202
- data = _settle_async_view_write(service, dataset_id, dataview_id, invocation.project, data)
2207
+ before = _rows_before(service, dataset_id, dataview_id, invocation.project)
2208
+ data = service.call(_symbol(invocation), **kwargs)
2209
+ data = _settle_async_view_write(
2210
+ service, dataset_id, dataview_id, invocation.project, data, before
2211
+ )
2203
2212
  return data, _meta(invocation, auth.workspace_id, None)
2204
2213
 
2205
2214
 
@@ -2509,6 +2518,33 @@ _SPECIAL_EXPORT_COMMON_FIELDS = frozenset(
2509
2518
  )
2510
2519
 
2511
2520
 
2521
+ def _reject_export_into_draft(service: Any, dataview_id: int, dataset_id: int) -> None:
2522
+ """Refuse a dataset export on a view whose changes are held in a draft.
2523
+
2524
+ With auto-run off the view keeps new pipeline changes in a draft, so the
2525
+ export would only be staged and write nothing; the SDK then waits out its
2526
+ whole timeout for a write that cannot happen (eval T1-O-11).
2527
+ """
2528
+ pipeline = service.call(_PIPELINE_GET_SYMBOL, dataview_id=dataview_id, dataset_id=dataset_id)
2529
+ draft_mode = pipeline.get("draft_mode") if isinstance(pipeline, dict) else None
2530
+ if draft_mode in (None, "off"):
2531
+ return
2532
+ raise CliError(
2533
+ code="view_in_draft",
2534
+ message=(
2535
+ f"View {dataview_id} holds its changes in a draft (auto-run is off), so an "
2536
+ "export added now would be staged and write nothing."
2537
+ ),
2538
+ exit_status=EXIT_USAGE,
2539
+ hint=(
2540
+ f"Turn auto-run on with mammoth view draft auto-run {dataview_id} --input "
2541
+ "'{\"enabled\": true}', add the export, then turn auto-run off again if the "
2542
+ f"dataset should only update when asked (mammoth view pipeline rerun {dataview_id})."
2543
+ ),
2544
+ details={"dataview_id": dataview_id, "draft_mode": draft_mode},
2545
+ )
2546
+
2547
+
2512
2548
  def view_export_specialized(invocation: Invocation) -> HandlerResult:
2513
2549
  """Run one of the SDK's typed ``View.export`` destination helpers."""
2514
2550
  route = _SPECIAL_EXPORTS.get(invocation.command_id)
@@ -2596,6 +2632,8 @@ def view_export_specialized(invocation: Invocation) -> HandlerResult:
2596
2632
  ),
2597
2633
  details={"dataset_id": dataset_id, "target_ds_id": int(target_ds_id)},
2598
2634
  )
2635
+ if is_dataset_route:
2636
+ _reject_export_into_draft(service, dataview_id, dataset_id)
2599
2637
  target_view_before = None
2600
2638
  target_only_columns: list[str] = []
2601
2639
  if target_ds_id is not None:
@@ -2999,8 +3037,30 @@ def _row_count_now(service: Any, dataset_id: int, view_id: int, project_id: int
2999
3037
  return info.get("row_count") if isinstance(info, dict) else None
3000
3038
 
3001
3039
 
3040
+ def _rows_before(
3041
+ service: Any, dataset_id: Any, view_id: int, project_id: int | None
3042
+ ) -> dict[str, Any] | None:
3043
+ """The view's row count read BEFORE an async write is sent.
3044
+
3045
+ Read after the call, a small view may already have recomputed, so the
3046
+ "before" would be the new count and a real change would look like none.
3047
+ None when the parent dataset is unknown (the settle step is skipped then).
3048
+ """
3049
+ if dataset_id is None:
3050
+ return None
3051
+ try:
3052
+ return {"rows_before": _row_count_now(service, int(dataset_id), view_id, project_id)}
3053
+ except CliError as exc:
3054
+ return {"rows_before": None, "rows_before_error": f"{type(exc).__name__}: {exc}"}
3055
+
3056
+
3002
3057
  def _settle_async_view_write(
3003
- service: Any, dataset_id: Any, view_id: int, project_id: int | None, data: Any
3058
+ service: Any,
3059
+ dataset_id: Any,
3060
+ view_id: int,
3061
+ project_id: int | None,
3062
+ data: Any,
3063
+ before: dict[str, Any] | None,
3004
3064
  ) -> Any:
3005
3065
  """Turn an async view write's immediate response into a final one.
3006
3066
 
@@ -3017,12 +3077,7 @@ def _settle_async_view_write(
3017
3077
  if dataset_id is None or not isinstance(data, dict):
3018
3078
  return data
3019
3079
  dataset_id = int(dataset_id)
3020
- try:
3021
- row_check: dict[str, Any] = {
3022
- "rows_before": _row_count_now(service, dataset_id, view_id, project_id)
3023
- }
3024
- except CliError as exc:
3025
- row_check = {"rows_before": None, "rows_before_error": f"{type(exc).__name__}: {exc}"}
3080
+ row_check: dict[str, Any] = dict(before or {"rows_before": None})
3026
3081
  rows_after, pipeline_error = wait_for_view_row_count(service, dataset_id, view_id, project_id)
3027
3082
  row_check["rows_after"] = rows_after
3028
3083
  data = {**data, "row_check": row_check}
@@ -674,6 +674,23 @@ def _require_clone_from_same_dataset(service: Any, clone_from: int, dataset_id:
674
674
  )
675
675
 
676
676
 
677
+ _DASHBOARDS_LIST_SYMBOL = "mammoth.api.dashboards.DashboardsAPI.list"
678
+
679
+
680
+ def _with_dashboards(service: Any, view_id: int, record: Any) -> Any:
681
+ """Add the dashboards built on this view, so a user on the view's page who
682
+ says "this board" is understood (eval T1-D-22); unchanged when none."""
683
+ if not isinstance(record, dict):
684
+ return record
685
+ boards = service.call(_DASHBOARDS_LIST_SYMBOL)
686
+ built_on = [
687
+ {"id": board.get("id"), "title": board.get("title")}
688
+ for board in (boards if isinstance(boards, list) else [])
689
+ if isinstance(board, dict) and view_id in (board.get("sources") or [])
690
+ ]
691
+ return {**record, "dashboards": built_on} if built_on else record
692
+
693
+
677
694
  def view_get(invocation: Invocation) -> HandlerResult:
678
695
  """Get one view by id, optionally scoped to an exact dataset parent."""
679
696
  view_id = _view_id(invocation)
@@ -699,7 +716,8 @@ def view_get(invocation: Invocation) -> HandlerResult:
699
716
  with open_service(invocation) as (service, auth):
700
717
  data = service.call("mammoth.api.dataviews.DataviewsAPI.get", **kwargs)
701
718
  parents.remember(_profile_name(invocation), auth.workspace_id, {view_id: dataset_id})
702
- data = apply_column_renames(data) if document.get("fields") else brief_view_record(data)
719
+ data = apply_column_renames(data) if document.get("fields") else brief_view_record(data)
720
+ data = _with_dashboards(service, view_id, data)
703
721
  return data, _meta(invocation, auth.workspace_id)
704
722
  context: dict[str, Any] = {"view_id": view_id}
705
723
  if dataset_id is not None:
@@ -718,12 +736,13 @@ def view_get(invocation: Invocation) -> HandlerResult:
718
736
  data = service.call(_symbol(invocation), **kwargs)
719
737
  payload = _view_payload(data)
720
738
  parents.remember_records(_profile_name(invocation), auth.workspace_id, payload)
721
- if not document.get("fields"):
722
- # The discovery path returns the standard record; trim it to the same
723
- # brief shape the exact path asks the server for.
724
- payload = brief_view_record(payload)
725
- else:
726
- payload = apply_column_renames(payload)
739
+ if not document.get("fields"):
740
+ # The discovery path returns the standard record; trim it to the same
741
+ # brief shape the exact path asks the server for.
742
+ payload = brief_view_record(payload)
743
+ else:
744
+ payload = apply_column_renames(payload)
745
+ payload = _with_dashboards(service, view_id, payload)
727
746
  return payload, _meta(invocation, auth.workspace_id)
728
747
 
729
748
 
@@ -0,0 +1,62 @@
1
+ """Dataset health, stated wherever a dataset appears in a result.
2
+
3
+ A dataset's ``status`` can say it did not load cleanly, but a bare status word
4
+ reads as fine to an agent that is looking for rows. :func:`with_dataset_health`
5
+ turns each such status into a ``dataset_health`` entry that says what it means
6
+ and which command fixes it. It runs on every result, read or write, and never
7
+ makes a request.
8
+ """
9
+
10
+ from __future__ import annotations
11
+
12
+ from collections.abc import Iterator
13
+ from typing import Any
14
+
15
+ #: Status to (what it means, which command to run first) -- ``{id}`` is filled in.
16
+ _UNHEALTHY: dict[str, tuple[str, str]] = {
17
+ "has_unstructured_data": (
18
+ "Some rows of this file could not be split into columns, so they are held "
19
+ "apart and the dataset may have few or no usable rows. The usual cause is "
20
+ "the wrong delimiter or quote character.",
21
+ "mammoth dataset broken-rows list {id} shows the rows and why each does "
22
+ "not fit; then mammoth dataset file-settings get {id} and mammoth dataset "
23
+ "file-settings update {id} with the right delimiter or quote character",
24
+ ),
25
+ }
26
+ #: Nesting to search: a result, a listing inside it, a record in the listing.
27
+ _MAX_DEPTH = 3
28
+
29
+
30
+ def with_dataset_health(data: Any) -> Any:
31
+ """Return ``data`` with a ``dataset_health`` list when any dataset in it is
32
+ unhealthy; anything else is returned unchanged."""
33
+ if not isinstance(data, dict):
34
+ return data
35
+ health = [_entry(record) for record in _unhealthy(data, 0)]
36
+ if not health:
37
+ return data
38
+ return {**data, "dataset_health": health}
39
+
40
+
41
+ def _unhealthy(value: Any, depth: int) -> Iterator[dict[str, Any]]:
42
+ if depth > _MAX_DEPTH:
43
+ return
44
+ if isinstance(value, dict):
45
+ if value.get("status") in _UNHEALTHY and isinstance(value.get("id"), int):
46
+ yield value
47
+ for child in value.values():
48
+ yield from _unhealthy(child, depth + 1)
49
+ elif isinstance(value, list):
50
+ for child in value:
51
+ yield from _unhealthy(child, depth + 1)
52
+
53
+
54
+ def _entry(record: dict[str, Any]) -> dict[str, Any]:
55
+ detail, fix = _UNHEALTHY[record["status"]]
56
+ return {
57
+ "dataset_id": record["id"],
58
+ "name": record.get("name"),
59
+ "status": record["status"],
60
+ "detail": detail,
61
+ "fix": fix.format(id=record["id"]),
62
+ }
@@ -0,0 +1,86 @@
1
+ """How new data reaches a dataset, stated wherever such a dataset appears.
2
+
3
+ A dataset made from an uploaded file reads as a one-time snapshot, so an agent
4
+ asked for a recurring report concludes nothing new will ever arrive; the next
5
+ file appends to it as a new batch and its views re-run. A dataset written by a
6
+ view's export reads as a standalone copy, so an agent cannot tell what writes it
7
+ or what deleting it takes with it. :func:`with_new_data_path`
8
+ states either path; it never makes a request.
9
+ """
10
+
11
+ from __future__ import annotations
12
+
13
+ from collections.abc import Iterator
14
+ from typing import Any
15
+
16
+ _FROM_FILE = (
17
+ "Made from an uploaded file; the next period's file joins this dataset as a "
18
+ "new batch with mammoth file upload FILE --input '{{\"append_to_ds_id\": {id}}}'. "
19
+ "Its views re-run on the added rows, so a scheduled automation on a view "
20
+ "sends the updated data without anyone rebuilding the pipeline."
21
+ )
22
+ _FROM_EXPORT = (
23
+ "Written by export {export_id} in view {view_id}'s pipeline, which fills it "
24
+ "again on every run of that view. Deleting this dataset also removes that "
25
+ "export; to keep the dataset but stop the updates, run mammoth view export "
26
+ "delete {view_id} {export_id}."
27
+ )
28
+ #: Nesting to search: a result, a listing inside it, a record in the listing.
29
+ _MAX_DEPTH = 3
30
+
31
+
32
+ def with_new_data_path(data: Any) -> Any:
33
+ """Return ``data`` with a ``new_data`` list when any dataset in it was made
34
+ from an uploaded file or is written by a view's export; anything else is
35
+ returned unchanged."""
36
+ if not isinstance(data, dict):
37
+ return data
38
+ paths = [
39
+ {"dataset_id": record["id"], "name": record.get("name"), "how": how}
40
+ for record, how in _fed_datasets(data, 0)
41
+ ]
42
+ if not paths:
43
+ return data
44
+ return {**data, "new_data": paths}
45
+
46
+
47
+ def with_file_upload_path(data: Any, dataset_id: int) -> Any:
48
+ """Return file settings with a ``new_data`` entry: settings with a delimiter
49
+ exist only for a parsed upload, which the next period's file can join."""
50
+ info = data.get("info") if isinstance(data, dict) else None
51
+ if not isinstance(info, dict) or not info.get("delimiter"):
52
+ return data
53
+ how = _FROM_FILE.format(id=dataset_id)
54
+ return {**data, "new_data": [{"dataset_id": dataset_id, "name": None, "how": how}]}
55
+
56
+
57
+ def _fed_datasets(value: Any, depth: int) -> Iterator[tuple[dict[str, Any], str]]:
58
+ if depth > _MAX_DEPTH:
59
+ return
60
+ if isinstance(value, dict):
61
+ how = _how(value)
62
+ if how is not None:
63
+ yield value, how
64
+ for child in value.values():
65
+ yield from _fed_datasets(child, depth + 1)
66
+ elif isinstance(value, list):
67
+ for child in value:
68
+ yield from _fed_datasets(child, depth + 1)
69
+
70
+
71
+ def _how(record: dict[str, Any]) -> str | None:
72
+ if not isinstance(record.get("id"), int):
73
+ return None
74
+ info = record.get("additional_info")
75
+ if (
76
+ isinstance(info, dict)
77
+ and isinstance(info.get("DATAVIEW_ID"), int)
78
+ and isinstance(info.get("TRIGGER_ID"), int)
79
+ ):
80
+ return _FROM_EXPORT.format(view_id=info["DATAVIEW_ID"], export_id=info["TRIGGER_ID"])
81
+ sources = record.get("sources")
82
+ if isinstance(sources, list) and any(
83
+ isinstance(s, dict) and s.get("type") == "file" for s in sources
84
+ ):
85
+ return _FROM_FILE.format(id=record["id"])
86
+ return None