mammoth-cli 2.0.71__tar.gz → 2.0.73__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 (230) hide show
  1. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/PKG-INFO +2 -2
  2. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/mammoth_cli/__init__.py +1 -1
  3. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/mammoth_cli/app.py +16 -1
  4. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/mammoth_cli/bundled_skill/mammoth-cli/SKILL.md +55 -58
  5. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/mammoth_cli/bundled_skill/mammoth-cli/references/recipes/resources.md +4 -1
  6. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/mammoth_cli/bundled_skill/mammoth-cli/references/recipes/scheduling.md +4 -0
  7. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/mammoth_cli/commands/registry.py +48 -4
  8. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/mammoth_cli/commands/schema.py +113 -9
  9. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/mammoth_cli/commands/view.py +96 -10
  10. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/mammoth_cli/commands/view_ops.py +32 -0
  11. mammoth_cli-2.0.73/mammoth_cli/runtime/verify.py +189 -0
  12. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/pyproject.toml +2 -2
  13. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/spec/manifests/commands/dataset.yaml +3 -1
  14. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/.gitignore +0 -0
  15. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/LICENSE +0 -0
  16. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/README.md +0 -0
  17. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/mammoth_cli/__main__.py +0 -0
  18. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/mammoth_cli/bundled_skill/mammoth-cli/references/about-mammoth.md +0 -0
  19. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/mammoth_cli/bundled_skill/mammoth-cli/references/auth.md +0 -0
  20. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/mammoth_cli/bundled_skill/mammoth-cli/references/capabilities-misc.md +0 -0
  21. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/mammoth_cli/bundled_skill/mammoth-cli/references/capabilities.md +0 -0
  22. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/mammoth_cli/bundled_skill/mammoth-cli/references/command-index.md +0 -0
  23. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/activity.md +0 -0
  24. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/addon.md +0 -0
  25. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/agent.md +0 -0
  26. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/ai.md +0 -0
  27. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/annotation.md +0 -0
  28. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/auth.md +0 -0
  29. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/automation.md +0 -0
  30. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/batch.md +0 -0
  31. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/billing.md +0 -0
  32. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/browse.md +0 -0
  33. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/capability.md +0 -0
  34. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/client-app.md +0 -0
  35. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/completion.md +0 -0
  36. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/config.md +0 -0
  37. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/connector.md +0 -0
  38. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/context.md +0 -0
  39. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/dashboard-qa.md +0 -0
  40. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/dashboard.md +0 -0
  41. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/data-app.md +0 -0
  42. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/dataset.md +0 -0
  43. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/doctor.md +0 -0
  44. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/external-key.md +0 -0
  45. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/file.md +0 -0
  46. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/folder.md +0 -0
  47. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/job.md +0 -0
  48. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/log.md +0 -0
  49. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/notification.md +0 -0
  50. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/parameter.md +0 -0
  51. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/project.md +0 -0
  52. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/report.md +0 -0
  53. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/schedule.md +0 -0
  54. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/schema.md +0 -0
  55. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/skill.md +0 -0
  56. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/snippet.md +0 -0
  57. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/support.md +0 -0
  58. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/template.md +0 -0
  59. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/trash.md +0 -0
  60. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/upgrade.md +0 -0
  61. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/user.md +0 -0
  62. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/version.md +0 -0
  63. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/view-transform.md +0 -0
  64. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/view.md +0 -0
  65. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/webhook.md +0 -0
  66. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/workflow.md +0 -0
  67. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/workspace.md +0 -0
  68. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/mammoth_cli/bundled_skill/mammoth-cli/references/handoff.md +0 -0
  69. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/mammoth_cli/bundled_skill/mammoth-cli/references/input.md +0 -0
  70. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/mammoth_cli/bundled_skill/mammoth-cli/references/jobs-drafts.md +0 -0
  71. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/mammoth_cli/bundled_skill/mammoth-cli/references/machine-output.md +0 -0
  72. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/mammoth_cli/bundled_skill/mammoth-cli/references/operations.md +0 -0
  73. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/mammoth_cli/bundled_skill/mammoth-cli/references/recipes/auth-scope.md +0 -0
  74. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/mammoth_cli/bundled_skill/mammoth-cli/references/recipes/cleanup.md +0 -0
  75. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/mammoth_cli/bundled_skill/mammoth-cli/references/recipes/dashboards.md +0 -0
  76. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/mammoth_cli/bundled_skill/mammoth-cli/references/recipes/end-to-end.md +0 -0
  77. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/mammoth_cli/bundled_skill/mammoth-cli/references/recipes/exports.md +0 -0
  78. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/mammoth_cli/bundled_skill/mammoth-cli/references/recipes/index.md +0 -0
  79. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/mammoth_cli/bundled_skill/mammoth-cli/references/recipes/need-action.md +0 -0
  80. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/mammoth_cli/bundled_skill/mammoth-cli/references/recipes/transforms.md +0 -0
  81. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/mammoth_cli/bundled_skill/mammoth-cli/references/recipes/typed-etl-discovery.md +0 -0
  82. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/mammoth_cli/bundled_skill/mammoth-cli/references/recovery.md +0 -0
  83. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/mammoth_cli/bundled_skill/mammoth-cli/references/report-checklist.md +0 -0
  84. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/mammoth_cli/bundled_skill/mammoth-cli/references/retention.md +0 -0
  85. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/mammoth_cli/bundled_skill/mammoth-cli/references/safety.md +0 -0
  86. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/mammoth_cli/bundled_skill/mammoth-cli/references/task-start.md +0 -0
  87. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/mammoth_cli/commands/__init__.py +0 -0
  88. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/mammoth_cli/commands/activity.py +0 -0
  89. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/mammoth_cli/commands/addon.py +0 -0
  90. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/mammoth_cli/commands/agent.py +0 -0
  91. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/mammoth_cli/commands/ai.py +0 -0
  92. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/mammoth_cli/commands/annotation.py +0 -0
  93. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/mammoth_cli/commands/auth.py +0 -0
  94. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/mammoth_cli/commands/automation.py +0 -0
  95. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/mammoth_cli/commands/batch.py +0 -0
  96. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/mammoth_cli/commands/billing.py +0 -0
  97. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/mammoth_cli/commands/browse.py +0 -0
  98. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/mammoth_cli/commands/capability.py +0 -0
  99. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/mammoth_cli/commands/client_app.py +0 -0
  100. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/mammoth_cli/commands/completion.py +0 -0
  101. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/mammoth_cli/commands/config.py +0 -0
  102. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/mammoth_cli/commands/connector.py +0 -0
  103. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/mammoth_cli/commands/context.py +0 -0
  104. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/mammoth_cli/commands/dashboard.py +0 -0
  105. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/mammoth_cli/commands/data_app.py +0 -0
  106. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/mammoth_cli/commands/dataset.py +0 -0
  107. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/mammoth_cli/commands/doctor.py +0 -0
  108. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/mammoth_cli/commands/external_key.py +0 -0
  109. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/mammoth_cli/commands/file.py +0 -0
  110. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/mammoth_cli/commands/folder.py +0 -0
  111. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/mammoth_cli/commands/job.py +0 -0
  112. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/mammoth_cli/commands/notification.py +0 -0
  113. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/mammoth_cli/commands/parameter.py +0 -0
  114. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/mammoth_cli/commands/project.py +0 -0
  115. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/mammoth_cli/commands/report.py +0 -0
  116. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/mammoth_cli/commands/schedule.py +0 -0
  117. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/mammoth_cli/commands/skill.py +0 -0
  118. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/mammoth_cli/commands/snippet.py +0 -0
  119. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/mammoth_cli/commands/support.py +0 -0
  120. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/mammoth_cli/commands/template.py +0 -0
  121. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/mammoth_cli/commands/trash.py +0 -0
  122. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/mammoth_cli/commands/upgrade.py +0 -0
  123. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/mammoth_cli/commands/user.py +0 -0
  124. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/mammoth_cli/commands/webhook.py +0 -0
  125. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/mammoth_cli/commands/workflow.py +0 -0
  126. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/mammoth_cli/commands/workspace.py +0 -0
  127. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/mammoth_cli/context/__init__.py +0 -0
  128. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/mammoth_cli/context/credentials.py +0 -0
  129. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/mammoth_cli/context/endpoint.py +0 -0
  130. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/mammoth_cli/context/profiles.py +0 -0
  131. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/mammoth_cli/context/resolver.py +0 -0
  132. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/mammoth_cli/contracts/__init__.py +0 -0
  133. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/mammoth_cli/contracts/auth.py +0 -0
  134. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/mammoth_cli/embed.py +0 -0
  135. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/mammoth_cli/errors/__init__.py +0 -0
  136. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/mammoth_cli/errors/envelope.py +0 -0
  137. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/mammoth_cli/manifest/__init__.py +0 -0
  138. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/mammoth_cli/manifest/loader.py +0 -0
  139. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/mammoth_cli/messages/__init__.py +0 -0
  140. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/mammoth_cli/output/__init__.py +0 -0
  141. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/mammoth_cli/output/envelope.py +0 -0
  142. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/mammoth_cli/output/normalize.py +0 -0
  143. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/mammoth_cli/output/policy.py +0 -0
  144. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/mammoth_cli/output/progress.py +0 -0
  145. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/mammoth_cli/output/render.py +0 -0
  146. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/mammoth_cli/py.typed +0 -0
  147. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/mammoth_cli/runtime/__init__.py +0 -0
  148. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/mammoth_cli/runtime/confirm.py +0 -0
  149. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/mammoth_cli/runtime/dryrun.py +0 -0
  150. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/mammoth_cli/runtime/embedded.py +0 -0
  151. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/mammoth_cli/runtime/executor.py +0 -0
  152. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/mammoth_cli/runtime/input_loader.py +0 -0
  153. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/mammoth_cli/runtime/invocation.py +0 -0
  154. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/mammoth_cli/runtime/options.py +0 -0
  155. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/mammoth_cli/runtime/parents.py +0 -0
  156. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/mammoth_cli/runtime/runlog.py +0 -0
  157. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/mammoth_cli/runtime/session.py +0 -0
  158. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/mammoth_cli/runtime/strict.py +0 -0
  159. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/mammoth_cli/runtime/updates.py +0 -0
  160. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/mammoth_cli/runtime/validate.py +0 -0
  161. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/mammoth_cli/services/__init__.py +0 -0
  162. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/mammoth_cli/services/argspec.py +0 -0
  163. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/mammoth_cli/services/coerce.py +0 -0
  164. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/mammoth_cli/services/command_contract.py +0 -0
  165. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/mammoth_cli/services/conditions.py +0 -0
  166. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/mammoth_cli/services/dashboard_pages.py +0 -0
  167. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/mammoth_cli/services/dashboard_review.py +0 -0
  168. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/mammoth_cli/services/data_quality.py +0 -0
  169. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/mammoth_cli/services/dispatch.py +0 -0
  170. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/mammoth_cli/services/factory.py +0 -0
  171. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/mammoth_cli/services/input_fields.py +0 -0
  172. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/mammoth_cli/services/mapping.py +0 -0
  173. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/mammoth_cli/services/openapi_types.py +0 -0
  174. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/mammoth_cli/services/positionals.py +0 -0
  175. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/mammoth_cli/services/protocol.py +0 -0
  176. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/mammoth_cli/services/sdk_service.py +0 -0
  177. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/mammoth_cli/services/testing.py +0 -0
  178. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/mammoth_cli/services/type_system.py +0 -0
  179. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/mammoth_cli/skills/__init__.py +0 -0
  180. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/mammoth_cli/skills/installer.py +0 -0
  181. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/mammoth_cli/skills/steering.py +0 -0
  182. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/mammoth_cli/testing.py +0 -0
  183. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/spec/manifests/commands/activity.yaml +0 -0
  184. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/spec/manifests/commands/addon.yaml +0 -0
  185. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/spec/manifests/commands/agent.yaml +0 -0
  186. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/spec/manifests/commands/ai.yaml +0 -0
  187. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/spec/manifests/commands/annotation.yaml +0 -0
  188. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/spec/manifests/commands/auth.yaml +0 -0
  189. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/spec/manifests/commands/automation.yaml +0 -0
  190. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/spec/manifests/commands/batch.yaml +0 -0
  191. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/spec/manifests/commands/billing.yaml +0 -0
  192. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/spec/manifests/commands/browse.yaml +0 -0
  193. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/spec/manifests/commands/capability.yaml +0 -0
  194. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/spec/manifests/commands/client-app.yaml +0 -0
  195. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/spec/manifests/commands/completion.yaml +0 -0
  196. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/spec/manifests/commands/config.yaml +0 -0
  197. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/spec/manifests/commands/connector.yaml +0 -0
  198. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/spec/manifests/commands/context.yaml +0 -0
  199. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/spec/manifests/commands/dashboard.yaml +0 -0
  200. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/spec/manifests/commands/data-app.yaml +0 -0
  201. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/spec/manifests/commands/doctor.yaml +0 -0
  202. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/spec/manifests/commands/external-key.yaml +0 -0
  203. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/spec/manifests/commands/file.yaml +0 -0
  204. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/spec/manifests/commands/folder.yaml +0 -0
  205. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/spec/manifests/commands/job.yaml +0 -0
  206. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/spec/manifests/commands/log.yaml +0 -0
  207. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/spec/manifests/commands/notification.yaml +0 -0
  208. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/spec/manifests/commands/parameter.yaml +0 -0
  209. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/spec/manifests/commands/project.yaml +0 -0
  210. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/spec/manifests/commands/report.yaml +0 -0
  211. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/spec/manifests/commands/schedule.yaml +0 -0
  212. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/spec/manifests/commands/schema.yaml +0 -0
  213. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/spec/manifests/commands/skill.yaml +0 -0
  214. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/spec/manifests/commands/snippet.yaml +0 -0
  215. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/spec/manifests/commands/support.yaml +0 -0
  216. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/spec/manifests/commands/template.yaml +0 -0
  217. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/spec/manifests/commands/trash.yaml +0 -0
  218. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/spec/manifests/commands/upgrade.yaml +0 -0
  219. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/spec/manifests/commands/user.yaml +0 -0
  220. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/spec/manifests/commands/version.yaml +0 -0
  221. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/spec/manifests/commands/view.yaml +0 -0
  222. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/spec/manifests/commands/webhook.yaml +0 -0
  223. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/spec/manifests/commands/workflow.yaml +0 -0
  224. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/spec/manifests/commands/workspace.yaml +0 -0
  225. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/spec/manifests/openapi-operations.yaml +0 -0
  226. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/spec/manifests/schema-v1.json +0 -0
  227. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/spec/manifests/sdk-catalog.source.yaml +0 -0
  228. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/spec/manifests/sdk-methods.yaml +0 -0
  229. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/spec/openapi/metadata.json +0 -0
  230. {mammoth_cli-2.0.71 → mammoth_cli-2.0.73}/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.71
3
+ Version: 2.0.73
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.32
20
+ Requires-Dist: mammoth-io<0.8,>=0.7.33
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.71"
9
+ __version__ = "2.0.73"
10
10
 
11
11
  # The versioned machine output envelope contract.
12
12
  SCHEMA_VERSION = 1
@@ -44,6 +44,7 @@ from mammoth_cli.output.policy import (
44
44
  from mammoth_cli.runtime import executor, validate
45
45
  from mammoth_cli.runtime.invocation import Invocation
46
46
  from mammoth_cli.runtime.strict import validate_extra_args
47
+ from mammoth_cli.runtime.verify import with_verify
47
48
  from mammoth_cli.services.positionals import PositionalSpec, resolve_positionals
48
49
 
49
50
  OUTPUT_MODES = VALID_OUTPUTS
@@ -823,7 +824,8 @@ def _execute(invocation: Invocation) -> None:
823
824
  raise not_implemented_error(invocation.command_id, sdk_symbol)
824
825
  if invocation.dry_run:
825
826
  return _dry_run(handler, invocation)
826
- return handler(invocation)
827
+ data, meta = handler(invocation)
828
+ return _apply_verify(invocation.command_id, data), meta
827
829
 
828
830
  executor.run(
829
831
  invocation.command_id,
@@ -835,6 +837,19 @@ def _execute(invocation: Invocation) -> None:
835
837
  )
836
838
 
837
839
 
840
+ def _apply_verify(command_id: str, data: Any) -> Any:
841
+ """Add the automatic write read-back to a real, mutating, API-backed result.
842
+
843
+ A read command and a command with no reviewed ``sdk_symbol`` (a local or
844
+ not-yet-backed command) are returned unchanged; ``--dry-run`` never
845
+ reaches this at all, since it returns before the handler's real call.
846
+ """
847
+ record = command_by_id(command_id) or {}
848
+ if record.get("mutation_class") == "read" or not record.get("sdk_symbol"):
849
+ return data
850
+ return with_verify(data)
851
+
852
+
838
853
  def _dry_run(handler: Handler, invocation: Invocation) -> tuple[Any, dict[str, Any]]:
839
854
  """Run ``handler`` until its request would leave; report that request.
840
855
 
@@ -1,14 +1,14 @@
1
1
  ---
2
2
  name: mammoth-cli
3
- version: 2.0.71
3
+ version: 2.0.73
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 (join, merge, pivot, filter, clean), dashboards, exports, and handoffs."
5
5
  ---
6
6
 
7
7
  # Mammoth CLI
8
8
 
9
- Use this skill for Mammoth shell work, not for Python SDK integration. The
10
- CLI is the contract: it validates every request locally, returns one JSON
11
- envelope, and needs no flag for that when you pipe its output.
9
+ Use this skill for Mammoth shell work, not Python SDK integration. The CLI
10
+ is the contract: it validates requests locally and returns one JSON
11
+ envelope, with no flag needed for that when piped.
12
12
 
13
13
  ## What Mammoth is
14
14
 
@@ -18,9 +18,8 @@ calculated in a **pipeline** of tasks on a **view**, and the result is
18
18
  published as a dashboard or delivered as a CSV, a database table, a BI feed
19
19
  or another dataset. The pipeline re-runs when new data arrives, so build the
20
20
  steps in Mammoth rather than computing a result locally. The web app and
21
- this CLI call the same API: every task in the web app's Transform menu is a
22
- `mammoth view transform` command. The data model, the high-level
23
- capabilities and the full web-to-CLI map are in
21
+ this CLI call the same API: every Transform-menu task is a `mammoth view
22
+ transform` command. The data model, capabilities and full web-to-CLI map:
24
23
  [about Mammoth](references/about-mammoth.md).
25
24
 
26
25
  ## Start
@@ -30,13 +29,13 @@ mammoth doctor # auth, endpoint, connectivity, version;
30
29
  mammoth project ensure 'PROJECT NAME' # get-or-create; becomes the active project
31
30
  ```
32
31
 
33
- `doctor` failing is a precondition failure, not a reason to try the business
34
- command anyway. When the connection check fails with a 502, 504 or timeout,
35
- `mammoth doctor --input '{"wait": 300}'` probes again for up to that many
36
- seconds; go on only when it passes. Production is the `app` endpoint; use `release` only when the
37
- task names it, and check `meta.profile`/`auth status` `endpoint` match the
38
- intended environment before doing anything. If no profile has credentials,
39
- tell the operator to run `mammoth auth login` in their own terminal (add
32
+ `doctor` failing is a precondition failure, not a reason to proceed anyway.
33
+ When the connection check fails with a 502, 504 or timeout, `mammoth doctor
34
+ --input '{"wait": 300}'` probes again for up to that many seconds; continue
35
+ only once it passes. Production is the `app` endpoint; use `release` only
36
+ when named, and check `meta.profile`/`auth status` `endpoint` match before
37
+ continuing. If no profile has credentials, tell the operator to run
38
+ `mammoth auth login` in their own terminal (add
40
39
  `--profile NAME` only for a profile other than `default`; [auth](references/auth.md)
41
40
  says where the token comes from) and wait; never ask for the token in chat,
42
41
  never read one from a file or environment variable, never run `auth login`
@@ -65,12 +64,13 @@ State the goal in plain words; the search knows common phrasing, and
65
64
  ```bash
66
65
  mammoth schema find "merge two datasets" # -> view.transform.join
67
66
  mammoth view transform --help # every data transformation
67
+ mammoth schema find "join two datasets; remove duplicates; build a dashboard" # 1 call, 1 result per goal
68
68
  ```
69
69
 
70
70
  | Goal | Command |
71
71
  |---|---|
72
72
  | Combine two datasets on a key (merge, VLOOKUP) | `view transform join`; one value per key: `view transform lookup` |
73
- | Add rows to an existing dataset, or combine two sources | `file upload FILE --input '{"append_to_ds_id": DATASET_ID}'`; then `discard-duplicates` and diff `row_count` before/after ([about Mammoth](references/about-mammoth.md#view-settings-and-what-has-no-command)) |
73
+ | Add rows to an existing dataset, or combine sources | Local file: `file upload FILE --input '{"append_to_ds_id": DATASET_ID}'`. Already in Mammoth: `view export dataset VIEW_ID --input '{"dataset_name": "NAME"}'`, then per further source `view export dataset VIEW_ID --input '{"dataset_name": "NAME", "target_ds_id": DATASET_ID, "save_as_mode": "APPEND_TO_DS"}'` — combine first, clean once; then `discard-duplicates` and diff `row_count` before/after ([about Mammoth](references/about-mammoth.md#view-settings-and-what-has-no-command)) |
74
74
  | Keep or remove rows | `view transform filter` |
75
75
  | Remove duplicate rows | `view transform discard-duplicates` |
76
76
  | Totals, counts, averages per group — just to read the number | `view data aggregate` (read-only: `--input '{"group_by": [...], "aggregations": [{"column": ..., "function": "SUM"}]}'` or `{"metric": {...}}`); never add a `pivot` task just to answer a question |
@@ -83,38 +83,36 @@ mammoth view transform --help # every data transformation
83
83
  | Rank, running total, previous row | `view transform window` |
84
84
  | A dashboard | `dashboard v3 generate`, then `chat edit` ([dashboards](references/recipes/dashboards.md)) |
85
85
  | Deliver the rows | `view export csv`, `view export postgres` (and other destinations), `view export dataset` |
86
- | Run something on a schedule or on new data (refresh, append, alert) | `automation create`: a condition (`at_specific_time`, new file in a folder, ...) and tasks (`run_data_retrieval`, `append_data`, `send_an_alert`, `pull_cloud_files`). `schedule create` only pulls a connector's data. A dataset made from an uploaded file has no source to refresh from; say so. Full recipe, including a known `automation get` backend caveat: [recurring work](references/recipes/scheduling.md) |
86
+ | Run something on a schedule or on new data (refresh, append, alert) | `automation create`: a condition (`at_specific_time`, new file in a folder, ...) and tasks (`run_data_retrieval`, `append_data`, `send_an_alert`, `pull_cloud_files`). `schedule create` only pulls a connector's data. A dataset from an uploaded file or URL is a one-time copy with no source to refresh; say so. Full recipe, including a known `automation get` backend caveat: [recurring work](references/recipes/scheduling.md) |
87
87
 
88
88
  Call a find result (or `suggestions` entry) from its `accepted_fields` and
89
- `agent_example`. Before you
90
- conclude the CLI cannot do something the web app does, check
91
- `view transform --help` and "View settings, and what has no command" in
92
- [about Mammoth](references/about-mammoth.md). Do not switch to the web app
93
- in a browser, or compute the result locally, for work the CLI covers;
94
- report a real gap with the command you tried.
89
+ `agent_example`. Before concluding the CLI cannot do something the web app
90
+ does, check `view transform --help` and "View settings, and what has no
91
+ command" in [about Mammoth](references/about-mammoth.md). Do not switch to
92
+ the browser, or compute locally, for work the CLI covers; report a real gap
93
+ with the command tried.
95
94
 
96
95
  ## Several files, one deliverable
97
96
 
98
97
  Users often upload related files without saying how they relate ("make a
99
- dashboard from t_a and t_b"). Work it out from the data before you build:
100
-
101
- 1. Upload every file. Each upload result carries a `view` preview of what
102
- Mammoth made of the file (`view_id`, column types, sample rows,
103
- `column_warnings`, and `before_dashboard`). Do not open the local files
104
- (`cat`, `head`): what counts is what Mammoth made of them. Run `view data
105
- get VIEW_ID` for each view. The warnings list numbers or dates stored as
106
- text, and blanks, each with the fix.
98
+ dashboard from t_a and t_b"). Work it out from the data before building:
99
+
100
+ 1. Upload every file. Each result carries a `view` preview of what Mammoth
101
+ made of it (`view_id`, column types, sample rows, `column_warnings`,
102
+ `before_dashboard`). Do not open the local files (`cat`, `head`) — what
103
+ Mammoth made of them is what counts. Run `view data get VIEW_ID` per view;
104
+ warnings list numbers/dates stored as text, and blanks, each with its fix.
107
105
  2. Find the keys. A column in one view whose values appear in a column of
108
106
  the other (`customer_id` and `id`, `order_ref` and `order_no`) is a
109
107
  foreign key; the view with many rows per key is the main one.
110
108
  3. Make the keys match before the join: same type (`convert-type`), same
111
109
  case and padding (`text`), no blanks (`set-values`, `filter`).
112
110
  4. Act on every `column_warnings` entry for a column the deliverable uses:
113
- run its `fix` (`convert-type` to `NUMERIC` or `DATE`; the values that are
114
- not numbers become empty). A text `price` cannot be summed on a dashboard.
115
- Then decide on each `blank_values` entry: fill, filter, or keep. Write one
116
- line for each in your report (the column, the count, what you did and
117
- why). A blank that you saw but did not mention is a miss.
111
+ run its `fix` (`convert-type` to `NUMERIC`/`DATE`; non-numeric values
112
+ become empty) — a text `price` cannot be summed on a dashboard. Then
113
+ decide each `blank_values` entry: fill, filter, or keep, and report one
114
+ line per entry (column, count, what and why). A blank seen but unmentioned
115
+ is a miss.
118
116
  5. `view transform join` the lookup view into the main view (`LEFT`). The
119
117
  result's `join_check` gives `match_rate`, `unmatched_rows` and
120
118
  `unmatched_keys`; put them in your report, and stop to compare the keys
@@ -123,9 +121,9 @@ dashboard from t_a and t_b"). Work it out from the data before you build:
123
121
  (`math`, `qty * price`, `new_column`), the `fix` in `before_dashboard`.
124
122
  A dashboard sees only the columns the view had when it was made.
125
123
  7. Build the dashboard from the joined view with one sentence
126
- ([dashboards](references/recipes/dashboards.md)) that charts the sum of
127
- revenue. Do not sum a unit price. Fix each `deliverable_check` warning,
128
- or say in the report why not.
124
+ ([dashboards](references/recipes/dashboards.md)) charting the sum of
125
+ revenue, not a unit price. Fix each `deliverable_check` warning, or say
126
+ why not.
129
127
 
130
128
  For the defaults that most pipelines use (new column or overwrite, `LEFT`
131
129
  joins, date steps), see
@@ -136,7 +134,7 @@ your report. If no column links the files, ask before you combine them.
136
134
  ## Calling a command
137
135
 
138
136
  - Ids are positionals; request fields are one `--input '{...}'` document;
139
- there are no per-field flags (`project create NAME`, not `--name`).
137
+ no per-field flags (`project create NAME`, not `--name`).
140
138
  - `mammoth skill show --input '{"file": "references/recipes/transforms.md"}'`
141
139
  prints any file of this skill; `mammoth skill agents-md install` writes a
142
140
  steering block into a repository's AGENTS.md so later sessions start here.
@@ -150,10 +148,10 @@ your report. If no column links the files, ask before you combine them.
150
148
  status, row_count, `metadata` columns and types, pipeline state);
151
149
  `view get ... --input '{"fields": "__full"}'` or `view list ... --input
152
150
  '{"full": true}'` returns the dependency and display trees too.
153
- - Column inputs and expressions use the exact **display names** the view
151
+ - Column inputs/expressions use the exact **display names** the view
154
152
  returns, never backend aliases.
155
- - `--dry-run` on any API-backed command resolves everything and reports the
156
- request instead of sending it; use it before a write you are not sure of.
153
+ - `--dry-run` on any API-backed command resolves and reports the request
154
+ instead of sending it; use before a write you are unsure of.
157
155
  - Deletes need `--yes`; high-impact ones (`project delete`, access changes)
158
156
  also need `--confirm ID`, and `schema get` shows which. Preserve requested
159
157
  deliverables; cleanup is exact-ID authorized and
@@ -167,14 +165,13 @@ your report. If no column links the files, ask before you combine them.
167
165
  - A success envelope proves the call, not the outcome. After a row-scoped
168
166
  change (set-values, filter, replace, join, fill) run `view data get
169
167
  VIEW_ID` (50 rows by default, `limit` to change) and check rows the
170
- condition should have touched and rows it should not have. Sample the
171
- target column *before* the change so the after-read has a comparison.
168
+ condition should and should not have touched. Sample the target column
169
+ *before* the change for comparison.
172
170
  - A uniform result (every amount 0, every region "Unknown", most join rows
173
171
  unmatched) means the previous step went wrong; stop and re-inspect it.
174
172
  - `column_warnings` on a data read and `join_check` on a join are findings,
175
- not decoration: fix each one the deliverable depends on, or say in the
176
- report why you kept it. `view data get` pages with `{"offset": 51,
177
- "limit": 50}`.
173
+ not decoration: fix each the deliverable depends on, or say why kept.
174
+ `view data get` pages with `{"offset": 51, "limit": 50}`.
178
175
  - A timeout, exit 7 or interruption does not prove failure; reconcile an
179
176
  `outcome_unknown` (`job get`, `view task list`) before replaying.
180
177
  - Check an answer with no write against the question (a trend: time
@@ -182,9 +179,9 @@ your report. If no column links the files, ask before you combine them.
182
179
  - After a write, run `mammoth project check PROJECT_ID` and fix each
183
180
  `to_report` line, or give it one line in the report.
184
181
  - Run the [report checklist](references/report-checklist.md) before stating
185
- a number or calling a step done. When files here disagree,
186
- [capabilities](references/capabilities.md) wins over a recipe, and a recipe
187
- over the generated command catalog.
182
+ a number or calling a step done. When files disagree,
183
+ [capabilities](references/capabilities.md) wins over a recipe, which wins
184
+ over the generated catalog.
188
185
 
189
186
  ## Route only what the task needs
190
187
 
@@ -204,9 +201,9 @@ your report. If no column links the files, ask before you combine them.
204
201
  [recovery](references/recovery.md) — failure modes by message and the
205
202
  stop-condition list
206
203
  - **A known command family or exact command:** [command catalog](references/command-index.md)
207
- — a lookup for the one command you need, not upfront reading; each entry
208
- carries its release status line, and a `not supported` or `observed
209
- blocker` entry names the route to use instead
204
+ — a lookup for one command, not upfront reading; each entry carries its
205
+ release status line, and a `not supported`/`observed blocker` entry names
206
+ the route to use instead
210
207
  - **Whether a route is proven, known-blocked, or untried on release:**
211
208
  [capabilities](references/capabilities.md) — read it before promising a
212
209
  deliverable or reporting a failure as a backend fault
@@ -214,9 +211,9 @@ your report. If no column links the files, ask before you combine them.
214
211
 
215
212
  ## Handoff checklist
216
213
 
217
- Before yielding work, write a nonsecret checkpoint with the intent and
218
- acceptance criteria; authorized profile/workspace/project; observed resource
219
- parents; verified evidence hashes; known jobs and unknown outcomes; remaining
220
- objectives; and exact cleanup ownership. The receiving agent validates that
221
- record and re-reads remote state before deciding what to do next. The handoff
214
+ Before yielding work, write a nonsecret checkpoint: intent and acceptance
215
+ criteria; authorized profile/workspace/project; observed resource parents;
216
+ verified evidence hashes; known jobs and unknown outcomes; remaining
217
+ objectives; exact cleanup ownership. The receiving agent validates that
218
+ record and re-reads remote state before deciding what to do next — a handoff
222
219
  is not a resume command or a grant of authority.
@@ -122,4 +122,7 @@ not sufficient. `dataset.create` waits for its asynchronous work; only the
122
122
  `weburl` creation type is proven, other freeform variants remain unqualified.
123
123
  If the schema does not accept a URL,
124
124
  report URL import unsupported; do not silently substitute local processing. A
125
- 4/5/7 envelope is a failed or uncertain operation, not a usable dataset.
125
+ 4/5/7 envelope is a failed or uncertain operation, not a usable dataset. A
126
+ `weburl` dataset is a one-time copy: it keeps no source details, so it cannot be
127
+ scheduled to refresh (see [recurring work](scheduling.md)); say so rather than
128
+ promising a refreshable source.
@@ -43,6 +43,10 @@ mammoth automation create 'Nightly refresh' --yes --input '{
43
43
  }'
44
44
  ```
45
45
 
46
+ `run_data_retrieval` only refreshes a cloud-connected dataset; a dataset made
47
+ from an uploaded file or a URL (`weburl`) is a one-time copy with no source
48
+ details to refresh from — say so rather than scheduling one.
49
+
46
50
  The other three task types take the shapes documented in `schema get
47
51
  automation.create` under `tasks[].details`:
48
52
 
@@ -152,16 +152,60 @@ def _schema_get(invocation: Invocation) -> HandlerResult:
152
152
  return schema_cmd.brief_schema(entry), {}
153
153
 
154
154
 
155
+ #: Above this many ';'-separated goals in one 'schema find' call, an agent is
156
+ #: almost certainly pasting something else (a whole plan, a sentence with
157
+ #: semicolons) rather than a real goal list; reject with a clear message
158
+ #: instead of silently running dozens of searches.
159
+ _MAX_FIND_GOALS = 12
160
+
161
+ _EMPTY_QUERY_ERROR = CliError(
162
+ code="empty_search_query",
163
+ message="The schema search query must contain at least one word.",
164
+ exit_status=EXIT_USAGE,
165
+ hint="For the complete inventory, use 'mammoth schema list'.",
166
+ )
167
+
168
+
169
+ def _cap_inline_detail(result: dict[str, Any], keep: int) -> None:
170
+ """Strip inline ``accepted_fields``/``agent_example`` past the top `keep`."""
171
+ for key in ("matches", "suggestions"):
172
+ for entry in (result.get(key) or [])[keep:]:
173
+ entry.pop("accepted_fields", None)
174
+ entry.pop("agent_example", None)
175
+
176
+
155
177
  def _schema_find(invocation: Invocation) -> HandlerResult:
156
178
  query = _require_arg(invocation, "search query")
157
179
  if not query.strip():
180
+ raise _EMPTY_QUERY_ERROR
181
+ if ";" not in query:
182
+ return schema_cmd.find_schemas(query), {}
183
+ # Several goals in one call ("join customers onto orders; remove
184
+ # duplicate rows; build a dashboard"): run the existing single-goal
185
+ # search per goal instead of round-tripping once per goal.
186
+ goals = [goal.strip() for goal in query.split(";") if goal.strip()]
187
+ if not goals:
188
+ raise _EMPTY_QUERY_ERROR
189
+ if len(goals) > _MAX_FIND_GOALS:
158
190
  raise CliError(
159
- code="empty_search_query",
160
- message="The schema search query must contain at least one word.",
191
+ code="too_many_goals",
192
+ message=(
193
+ f"schema find accepts at most {_MAX_FIND_GOALS} ';'-separated goals per "
194
+ f"call; got {len(goals)}."
195
+ ),
161
196
  exit_status=EXIT_USAGE,
162
- hint="For the complete inventory, use 'mammoth schema list'.",
197
+ hint="Split the goals across more than one 'schema find' call.",
163
198
  )
164
- return schema_cmd.find_schemas(query), {}
199
+ results = [schema_cmd.find_schemas(goal) for goal in goals]
200
+ if len(results) > 1:
201
+ # Cap inline accepted_fields/agent_example to the top match per goal
202
+ # so a multi-goal envelope stays small even when every goal has
203
+ # several candidates.
204
+ for result in results:
205
+ _cap_inline_detail(result, 1)
206
+ return {
207
+ "goals": [{"goal": goal, **result} for goal, result in zip(goals, results, strict=True)]
208
+ }, {}
165
209
 
166
210
 
167
211
  def _log_path(_: Invocation) -> HandlerResult:
@@ -68,7 +68,8 @@ _COMMAND_DISCOVERY_PURPOSES = {
68
68
  "file.upload-folder": "upload source-data directory folder",
69
69
  "view.export.csv": "export download local CSV file artifact",
70
70
  "view.export.dataset": (
71
- "send copy branch out rows into a dataset in another project append union stack rows"
71
+ "send copy branch out create save the result rows into a new project from an "
72
+ "existing append appending union stack monthly rows across datasets views"
72
73
  ),
73
74
  # One entry per typed export destination, in the way users name the
74
75
  # destination rather than Mammoth's route spelling (which a two-word
@@ -195,7 +196,14 @@ _COMMAND_DISCOVERY_PURPOSES = {
195
196
  "view.transform.date-diff": "date dates difference days between two date columns age duration",
196
197
  "view.transform.delete-columns": "delete drop remove columns",
197
198
  "view.transform.discard-duplicates": (
198
- "duplicate duplicates dedup dedupe deduplicate remove repeated rows unique distinct"
199
+ "duplicate duplicates dedup dedupe deduplicate remove repeated rows unique distinct "
200
+ # "order"/"number" are kept as generic identifying-column vocabulary
201
+ # ("dedupe by an order/number/key"), not the specific business noun
202
+ # "order id" -- "order" also can't be dropped as a data word since
203
+ # view.transform.sort's own purpose text already uses it (sort
204
+ # order), so any query pairing "order" with dedupe words needs it
205
+ # covered here to reach a full match.
206
+ "by order number key column"
199
207
  ),
200
208
  "view.transform.extract-date": (
201
209
  "extract date part year month day hour minute second week quarter weekday "
@@ -211,8 +219,8 @@ _COMMAND_DISCOVERY_PURPOSES = {
211
219
  "view.transform.generate-sql": "generate write sql query from natural language intent question",
212
220
  "view.transform.increment-date": "add subtract days months years to a date column shift",
213
221
  "view.transform.join": (
214
- "join blend merge combine enrich match matching keys rows add columns from another "
215
- "second view views dataset datasets table tables vlookup"
222
+ "join blend merge combine enrich match matching key keys rows add columns from "
223
+ "another second view views dataset datasets table tables vlookup"
216
224
  ),
217
225
  "view.transform.json-extract": "json extract parse nested fields keys into columns",
218
226
  "view.transform.limit-rows": "limit top bottom first last n rows head",
@@ -223,7 +231,7 @@ _COMMAND_DISCOVERY_PURPOSES = {
223
231
  "view.transform.math": (
224
232
  "math arithmetic multiply multiplication divide add subtract formula "
225
233
  "expression amount calculate compute ratio percentage round new column "
226
- "conditional threshold greater than if text"
234
+ "conditional threshold greater than if text times"
227
235
  ),
228
236
  "view.transform.pivot": (
229
237
  "pivot group by aggregate aggregation sum count average summary summarize "
@@ -235,7 +243,7 @@ _COMMAND_DISCOVERY_PURPOSES = {
235
243
  "view.transform.replace": "find replace substitute text value in columns",
236
244
  "view.transform.set-values": (
237
245
  "set values assign overwrite blank empty default where condition label "
238
- "category bucket flag if then conditional value"
246
+ "category bucket flag if then conditional add a column with a constant value"
239
247
  ),
240
248
  "view.transform.small-large": "nth smallest largest value across columns",
241
249
  "view.transform.sort": (
@@ -261,6 +269,14 @@ _COMMAND_DISCOVERY_PURPOSES = {
261
269
  "distribution spread histogram top most common frequent values breakdown share "
262
270
  "percentage profile"
263
271
  ),
272
+ "view.create": "start a new one from an existing dataset, duplicate",
273
+ "dataset.list": "list every dataset in a project workspace",
274
+ # "month"/"week" are kept as generic calendar-grouping vocabulary (a
275
+ # group-by dimension any dataset can have), not a specific business
276
+ # value -- and neither can be dropped as a data word anyway, since
277
+ # view.data.explore's own purpose text already uses both for its trend
278
+ # feature.
279
+ "view.data.aggregate": "group and sum totals by month week without changing the pipeline",
264
280
  # Goals users state in their own words, one entry per command the agent's
265
281
  # system prompt used to spell out by hand.
266
282
  "dashboard.suggestion.list": "ideas suggest suggestions what to show put on a board chart",
@@ -349,6 +365,22 @@ _SCOPE_REQUIREMENTS: dict[str, dict[str, Any]] = {
349
365
  _MAX_FIND_RESULTS = 20
350
366
  # Outranks any word-overlap score: a command named by its full path comes first.
351
367
  _NAMED_COMMAND_BOOST = 10_000
368
+ # Bag-of-words scoring cannot tell "create a NEW VIEW from an existing
369
+ # DATASET" (view.create) apart from "create a DATASET from an existing
370
+ # VIEW" (view.export.dataset): the two goals share the exact same word set,
371
+ # and only word order says which resource is being made and which already
372
+ # exists. No purpose text or synonym can encode that; this pair of small
373
+ # adjacency checks is the intentionally scoped exception. Extend the two
374
+ # dicts, never the regex, if another goal collides the same way.
375
+ _NEW_OBJECT_HINTS: dict[str, str] = {
376
+ "view.create": "view",
377
+ "view.export.dataset": "dataset",
378
+ }
379
+ _EXISTING_OBJECT_HINTS: dict[str, str] = {
380
+ "view.create": "dataset",
381
+ "view.export.dataset": "view",
382
+ }
383
+ _OBJECT_ADJACENCY_BOOST = 150
352
384
  _MAX_FIND_LIMIT = 100
353
385
  # How many of a find's top matches carry inline accepted_fields/agent_example.
354
386
  # 35% of all eval tool calls were command discovery (schema find -> schema
@@ -372,6 +404,12 @@ _DISCOVERY_SYNONYMS: dict[str, tuple[str, ...]] = {
372
404
  "csv": ("spreadsheet", "file", "upload"),
373
405
  "local": ("file", "download", "csv", "artifact"),
374
406
  "download": ("export", "file", "csv", "artifact", "local"),
407
+ # "combine" alone is ambiguous between joining on a key and appending
408
+ # rows; kept a weak alias match (not a literal word) here so a bare
409
+ # "combine datasets" still favors join's own literal "combine" purpose
410
+ # text, while "combine ... by appending rows" still resolves to the
411
+ # export -- its own literal "append"/"union"/"stack" carry that case.
412
+ "combine": ("append", "union", "stack", "merge"),
375
413
  # "publish" a dataset almost always means one of the typed exports
376
414
  # (Power BI, a live DB connection, a webhook, ...); every export
377
415
  # command's path literally contains "export", so this one alias covers
@@ -454,6 +492,12 @@ _DISCOVERY_STOPWORDS = frozenset(
454
492
  "using",
455
493
  "than",
456
494
  "via",
495
+ # Filler prepositions in goal phrasing ("datasets as rows", "datasets
496
+ # in a project", "join two datasets on a key"); no command turns on
497
+ # any of these.
498
+ "as",
499
+ "in",
500
+ "on",
457
501
  }
458
502
  )
459
503
  # How many near misses a search with no full match returns.
@@ -669,6 +713,42 @@ def _adjacent_compound_forms(terms: tuple[str, ...]) -> dict[str, frozenset[str]
669
713
  return {term: frozenset(compounds) for term, compounds in forms.items()}
670
714
 
671
715
 
716
+ @cache
717
+ def _command_vocabulary_tokens() -> frozenset[str]:
718
+ """Every token that names a command or appears in its curated purpose text.
719
+
720
+ Distinguishes genuine CLI vocabulary from a data word -- a column,
721
+ table, or other business noun from the caller's own data (``orders``,
722
+ ``revenue``, ``store``) -- riding along in a goal. Counts a command's own
723
+ id/path (``user``, ``workspace``, ``invoice`` are real resource nouns a
724
+ command is named after) plus ``_COMMAND_DISCOVERY_PURPOSES``/
725
+ ``_GROUP_DISCOVERY_PURPOSES`` -- text hand-curated specifically to
726
+ describe what a command is for. Deliberately excludes ``human_example``/
727
+ ``agent_example`` and OpenAPI-derived operation hints: those are
728
+ illustrative sample values (a placeholder project name like "Revenue
729
+ report", a sample filename like "sales.csv") reused verbatim across
730
+ dozens of unrelated commands, so counting them would make almost any
731
+ plausible business noun look like real vocabulary and defeat this
732
+ check. A term absent from this set is not something any command is
733
+ named after or actually about, so :func:`find_schemas` drops it from a
734
+ goal's required terms rather than letting it sink an otherwise complete
735
+ match.
736
+ """
737
+ vocabulary: set[str] = set()
738
+ for record in load_commands():
739
+ if record.get("disposition") == "alias":
740
+ continue
741
+ command_id = str(record["command_id"])
742
+ command_path = str(record["command_path"])
743
+ text = (
744
+ f"{command_id} {command_path} "
745
+ f"{_COMMAND_DISCOVERY_PURPOSES.get(command_id, '')} "
746
+ f"{_GROUP_DISCOVERY_PURPOSES.get(command_path.split()[0], '')}"
747
+ )
748
+ vocabulary.update(_tokens(text))
749
+ return frozenset(vocabulary)
750
+
751
+
672
752
  def _compact_contract(record: dict[str, Any]) -> dict[str, Any]:
673
753
  """Return the bounded, honest contract used by discovery clients.
674
754
 
@@ -1405,8 +1485,26 @@ def find_schemas(
1405
1485
  """
1406
1486
  # A query made only of filler words keeps them, rather than matching
1407
1487
  # every command.
1408
- terms = _query_tokens(query) or tuple(_tokens(query))
1409
- compound_forms = _adjacent_compound_forms(terms)
1488
+ raw_terms = _query_tokens(query) or tuple(_tokens(query))
1489
+ compound_forms = _adjacent_compound_forms(raw_terms)
1490
+ # A term no command's discovery-purpose text would ever say is a data
1491
+ # word (a column/table/business noun from the caller's own data, not CLI
1492
+ # vocabulary) riding along in the goal; drop it before the all-terms
1493
+ # rule and scoring so it can't sink an otherwise complete match. If
1494
+ # every term would be dropped, keep them all -- a query that is nothing
1495
+ # but data words still deserves its ordinary near-miss treatment rather
1496
+ # than becoming a match-everything wildcard. A literal full-path lookup
1497
+ # (the ``named`` check below) always uses the un-dropped ``raw_terms``,
1498
+ # so naming a command by its exact path never depends on this filter.
1499
+ vocabulary = _command_vocabulary_tokens()
1500
+ cli_terms = tuple(
1501
+ term
1502
+ for term in raw_terms
1503
+ if (_token_aliases(term) & vocabulary)
1504
+ or (compound_forms.get(term, frozenset()) & vocabulary)
1505
+ )
1506
+ terms = cli_terms or raw_terms
1507
+ query_cf = query.casefold()
1410
1508
  # Clamp caller-provided bounds instead of allowing an accidental unbounded
1411
1509
  # discovery response. A negative cursor is a usage mistake, not a request
1412
1510
  # to wrap around the catalog.
@@ -1464,6 +1562,12 @@ def find_schemas(
1464
1562
  action = command_path.split()[1] if len(command_path.split()) > 1 else ""
1465
1563
  if "show" in matched_terms and action in {"list", "get", "browse"}:
1466
1564
  score += 80
1565
+ new_object = _NEW_OBJECT_HINTS.get(command_id)
1566
+ if new_object and re.search(rf"\bnew\s+{new_object}s?\b", query_cf):
1567
+ score += _OBJECT_ADJACENCY_BOOST
1568
+ existing_object = _EXISTING_OBJECT_HINTS.get(command_id)
1569
+ if existing_object and re.search(rf"\bexisting\s+{existing_object}s?\b", query_cf):
1570
+ score += _OBJECT_ADJACENCY_BOOST
1467
1571
  is_support = command_id.startswith("support.")
1468
1572
  entry = {
1469
1573
  "command_id": command_id,
@@ -1484,7 +1588,7 @@ def find_schemas(
1484
1588
  # A query that spells out this command's whole path (``aggregate view
1485
1589
  # data ...``) asks for it by name, whatever goal words ride along.
1486
1590
  path_tokens = set(_tokens(command_path))
1487
- named = len(path_tokens) >= 3 and path_tokens <= set(terms)
1591
+ named = len(path_tokens) >= 3 and path_tokens <= set(raw_terms)
1488
1592
  if named:
1489
1593
  score += _NAMED_COMMAND_BOOST
1490
1594
  if named or len(matched_terms) == len(terms):