mammoth-cli 2.0.91__tar.gz → 2.1.0__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 (249) hide show
  1. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/PKG-INFO +2 -2
  2. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/mammoth_cli/__init__.py +1 -1
  3. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/mammoth_cli/app.py +16 -7
  4. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/mammoth_cli/bundled_skill/mammoth-cli/SKILL.md +28 -27
  5. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/mammoth_cli/bundled_skill/mammoth-cli/references/about-mammoth.md +7 -5
  6. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/view.md +1 -1
  7. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/mammoth_cli/bundled_skill/mammoth-cli/references/recipes/auth-scope.md +4 -0
  8. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/mammoth_cli/bundled_skill/mammoth-cli/references/recipes/cleanup.md +7 -0
  9. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/mammoth_cli/bundled_skill/mammoth-cli/references/recipes/dashboards.md +50 -111
  10. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/mammoth_cli/bundled_skill/mammoth-cli/references/recipes/exports.md +2 -1
  11. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/mammoth_cli/bundled_skill/mammoth-cli/references/recipes/need-action.md +7 -5
  12. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/mammoth_cli/bundled_skill/mammoth-cli/references/recipes/resources.md +4 -0
  13. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/mammoth_cli/bundled_skill/mammoth-cli/references/recipes/scheduling.md +20 -4
  14. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/mammoth_cli/bundled_skill/mammoth-cli/references/recipes/transforms.md +20 -8
  15. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/mammoth_cli/bundled_skill/mammoth-cli/references/recovery.md +6 -5
  16. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/mammoth_cli/bundled_skill/mammoth-cli/references/report-checklist.md +2 -1
  17. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/mammoth_cli/commands/config.py +9 -1
  18. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/mammoth_cli/commands/context.py +8 -0
  19. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/mammoth_cli/commands/dashboard.py +67 -44
  20. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/mammoth_cli/commands/dataset.py +1 -1
  21. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/mammoth_cli/commands/doctor.py +44 -22
  22. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/mammoth_cli/commands/file.py +3 -1
  23. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/mammoth_cli/commands/project.py +19 -3
  24. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/mammoth_cli/commands/view.py +223 -49
  25. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/mammoth_cli/commands/view_ops.py +125 -9
  26. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/mammoth_cli/commands/view_profile.py +30 -6
  27. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/mammoth_cli/context/profiles.py +7 -2
  28. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/mammoth_cli/context/resolver.py +8 -0
  29. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/mammoth_cli/errors/envelope.py +19 -0
  30. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/mammoth_cli/runtime/confirm.py +6 -1
  31. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/mammoth_cli/runtime/dataset_health.py +39 -8
  32. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/mammoth_cli/runtime/dryrun.py +4 -0
  33. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/mammoth_cli/runtime/dryrun_targets.py +49 -0
  34. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/mammoth_cli/runtime/executor.py +23 -1
  35. mammoth_cli-2.1.0/mammoth_cli/runtime/intent_only.py +44 -0
  36. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/mammoth_cli/runtime/invocation.py +3 -0
  37. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/mammoth_cli/runtime/state.py +15 -1
  38. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/mammoth_cli/runtime/verify.py +26 -1
  39. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/mammoth_cli/services/command_contract.py +1 -0
  40. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/mammoth_cli/services/data_quality.py +50 -5
  41. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/mammoth_cli/services/listing.py +33 -10
  42. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/mammoth_cli/services/mapping.py +5 -2
  43. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/mammoth_cli/services/read_queries.py +101 -17
  44. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/mammoth_cli/services/sdk_service.py +56 -29
  45. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/mammoth_cli/services/text_dates.py +60 -3
  46. mammoth_cli-2.1.0/mammoth_cli/services/write_impact.py +259 -0
  47. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/pyproject.toml +2 -2
  48. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/spec/manifests/commands/view.yaml +24 -23
  49. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/spec/manifests/sdk-methods.yaml +87 -13
  50. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/.gitignore +0 -0
  51. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/LICENSE +0 -0
  52. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/README.md +0 -0
  53. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/mammoth_cli/__main__.py +0 -0
  54. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/mammoth_cli/bundled_skill/mammoth-cli/references/auth.md +0 -0
  55. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/mammoth_cli/bundled_skill/mammoth-cli/references/capabilities-misc.md +0 -0
  56. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/mammoth_cli/bundled_skill/mammoth-cli/references/capabilities.md +0 -0
  57. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/mammoth_cli/bundled_skill/mammoth-cli/references/command-index.md +0 -0
  58. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/activity.md +0 -0
  59. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/addon.md +0 -0
  60. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/agent.md +0 -0
  61. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/ai.md +0 -0
  62. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/annotation.md +0 -0
  63. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/auth.md +0 -0
  64. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/automation.md +0 -0
  65. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/batch.md +0 -0
  66. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/billing.md +0 -0
  67. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/browse.md +0 -0
  68. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/calc.md +0 -0
  69. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/capability.md +0 -0
  70. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/client-app.md +0 -0
  71. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/completion.md +0 -0
  72. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/config.md +0 -0
  73. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/connector.md +0 -0
  74. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/context.md +0 -0
  75. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/dashboard-qa.md +0 -0
  76. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/dashboard-style.md +0 -0
  77. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/dashboard.md +0 -0
  78. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/data-app.md +0 -0
  79. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/dataset.md +0 -0
  80. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/doctor.md +0 -0
  81. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/external-key.md +0 -0
  82. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/file.md +0 -0
  83. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/folder.md +0 -0
  84. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/job.md +0 -0
  85. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/log.md +0 -0
  86. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/notification.md +0 -0
  87. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/parameter.md +0 -0
  88. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/project.md +0 -0
  89. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/report.md +0 -0
  90. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/schedule.md +0 -0
  91. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/schema.md +0 -0
  92. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/skill.md +0 -0
  93. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/snippet.md +0 -0
  94. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/support.md +0 -0
  95. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/template.md +0 -0
  96. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/trash.md +0 -0
  97. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/upgrade.md +0 -0
  98. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/user.md +0 -0
  99. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/version.md +0 -0
  100. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/view-transform.md +0 -0
  101. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/webhook.md +0 -0
  102. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/workflow.md +0 -0
  103. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/workspace.md +0 -0
  104. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/mammoth_cli/bundled_skill/mammoth-cli/references/handoff.md +0 -0
  105. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/mammoth_cli/bundled_skill/mammoth-cli/references/input.md +0 -0
  106. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/mammoth_cli/bundled_skill/mammoth-cli/references/jobs-drafts.md +0 -0
  107. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/mammoth_cli/bundled_skill/mammoth-cli/references/machine-output.md +0 -0
  108. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/mammoth_cli/bundled_skill/mammoth-cli/references/operations.md +0 -0
  109. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/mammoth_cli/bundled_skill/mammoth-cli/references/recipes/end-to-end.md +0 -0
  110. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/mammoth_cli/bundled_skill/mammoth-cli/references/recipes/index.md +0 -0
  111. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/mammoth_cli/bundled_skill/mammoth-cli/references/recipes/typed-etl-discovery.md +0 -0
  112. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/mammoth_cli/bundled_skill/mammoth-cli/references/retention.md +0 -0
  113. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/mammoth_cli/bundled_skill/mammoth-cli/references/safety.md +0 -0
  114. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/mammoth_cli/bundled_skill/mammoth-cli/references/task-start.md +0 -0
  115. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/mammoth_cli/commands/__init__.py +0 -0
  116. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/mammoth_cli/commands/activity.py +0 -0
  117. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/mammoth_cli/commands/addon.py +0 -0
  118. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/mammoth_cli/commands/agent.py +0 -0
  119. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/mammoth_cli/commands/ai.py +0 -0
  120. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/mammoth_cli/commands/annotation.py +0 -0
  121. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/mammoth_cli/commands/auth.py +0 -0
  122. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/mammoth_cli/commands/automation.py +0 -0
  123. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/mammoth_cli/commands/batch.py +0 -0
  124. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/mammoth_cli/commands/billing.py +0 -0
  125. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/mammoth_cli/commands/browse.py +0 -0
  126. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/mammoth_cli/commands/calc.py +0 -0
  127. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/mammoth_cli/commands/capability.py +0 -0
  128. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/mammoth_cli/commands/client_app.py +0 -0
  129. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/mammoth_cli/commands/completion.py +0 -0
  130. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/mammoth_cli/commands/connector.py +0 -0
  131. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/mammoth_cli/commands/data_app.py +0 -0
  132. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/mammoth_cli/commands/external_key.py +0 -0
  133. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/mammoth_cli/commands/folder.py +0 -0
  134. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/mammoth_cli/commands/job.py +0 -0
  135. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/mammoth_cli/commands/notification.py +0 -0
  136. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/mammoth_cli/commands/parameter.py +0 -0
  137. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/mammoth_cli/commands/registry.py +0 -0
  138. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/mammoth_cli/commands/report.py +0 -0
  139. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/mammoth_cli/commands/schedule.py +0 -0
  140. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/mammoth_cli/commands/schema.py +0 -0
  141. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/mammoth_cli/commands/skill.py +0 -0
  142. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/mammoth_cli/commands/snippet.py +0 -0
  143. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/mammoth_cli/commands/support.py +0 -0
  144. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/mammoth_cli/commands/template.py +0 -0
  145. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/mammoth_cli/commands/trash.py +0 -0
  146. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/mammoth_cli/commands/upgrade.py +0 -0
  147. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/mammoth_cli/commands/user.py +0 -0
  148. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/mammoth_cli/commands/webhook.py +0 -0
  149. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/mammoth_cli/commands/workflow.py +0 -0
  150. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/mammoth_cli/commands/workspace.py +0 -0
  151. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/mammoth_cli/context/__init__.py +0 -0
  152. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/mammoth_cli/context/credentials.py +0 -0
  153. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/mammoth_cli/context/endpoint.py +0 -0
  154. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/mammoth_cli/contracts/__init__.py +0 -0
  155. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/mammoth_cli/contracts/auth.py +0 -0
  156. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/mammoth_cli/embed.py +0 -0
  157. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/mammoth_cli/errors/__init__.py +0 -0
  158. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/mammoth_cli/manifest/__init__.py +0 -0
  159. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/mammoth_cli/manifest/loader.py +0 -0
  160. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/mammoth_cli/messages/__init__.py +0 -0
  161. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/mammoth_cli/output/__init__.py +0 -0
  162. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/mammoth_cli/output/envelope.py +0 -0
  163. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/mammoth_cli/output/normalize.py +0 -0
  164. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/mammoth_cli/output/policy.py +0 -0
  165. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/mammoth_cli/output/progress.py +0 -0
  166. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/mammoth_cli/output/render.py +0 -0
  167. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/mammoth_cli/py.typed +0 -0
  168. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/mammoth_cli/runtime/__init__.py +0 -0
  169. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/mammoth_cli/runtime/embedded.py +0 -0
  170. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/mammoth_cli/runtime/input_loader.py +0 -0
  171. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/mammoth_cli/runtime/new_data.py +0 -0
  172. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/mammoth_cli/runtime/options.py +0 -0
  173. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/mammoth_cli/runtime/parents.py +0 -0
  174. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/mammoth_cli/runtime/runlog.py +0 -0
  175. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/mammoth_cli/runtime/session.py +0 -0
  176. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/mammoth_cli/runtime/strict.py +0 -0
  177. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/mammoth_cli/runtime/updates.py +0 -0
  178. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/mammoth_cli/runtime/validate.py +0 -0
  179. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/mammoth_cli/services/__init__.py +0 -0
  180. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/mammoth_cli/services/argspec.py +0 -0
  181. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/mammoth_cli/services/board_values.py +0 -0
  182. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/mammoth_cli/services/coerce.py +0 -0
  183. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/mammoth_cli/services/conditions.py +0 -0
  184. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/mammoth_cli/services/dashboard_filters.py +0 -0
  185. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/mammoth_cli/services/dashboard_pages.py +0 -0
  186. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/mammoth_cli/services/dashboard_review.py +0 -0
  187. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/mammoth_cli/services/data_profile.py +0 -0
  188. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/mammoth_cli/services/dispatch.py +0 -0
  189. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/mammoth_cli/services/factory.py +0 -0
  190. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/mammoth_cli/services/input_fields.py +0 -0
  191. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/mammoth_cli/services/openapi_types.py +0 -0
  192. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/mammoth_cli/services/positionals.py +0 -0
  193. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/mammoth_cli/services/protocol.py +0 -0
  194. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/mammoth_cli/services/stored_stats.py +0 -0
  195. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/mammoth_cli/services/testing.py +0 -0
  196. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/mammoth_cli/services/type_system.py +0 -0
  197. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/mammoth_cli/skills/__init__.py +0 -0
  198. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/mammoth_cli/skills/installer.py +0 -0
  199. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/mammoth_cli/skills/steering.py +0 -0
  200. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/mammoth_cli/testing.py +0 -0
  201. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/spec/manifests/commands/activity.yaml +0 -0
  202. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/spec/manifests/commands/addon.yaml +0 -0
  203. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/spec/manifests/commands/agent.yaml +0 -0
  204. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/spec/manifests/commands/ai.yaml +0 -0
  205. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/spec/manifests/commands/annotation.yaml +0 -0
  206. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/spec/manifests/commands/auth.yaml +0 -0
  207. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/spec/manifests/commands/automation.yaml +0 -0
  208. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/spec/manifests/commands/batch.yaml +0 -0
  209. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/spec/manifests/commands/billing.yaml +0 -0
  210. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/spec/manifests/commands/browse.yaml +0 -0
  211. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/spec/manifests/commands/calc.yaml +0 -0
  212. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/spec/manifests/commands/capability.yaml +0 -0
  213. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/spec/manifests/commands/client-app.yaml +0 -0
  214. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/spec/manifests/commands/completion.yaml +0 -0
  215. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/spec/manifests/commands/config.yaml +0 -0
  216. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/spec/manifests/commands/connector.yaml +0 -0
  217. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/spec/manifests/commands/context.yaml +0 -0
  218. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/spec/manifests/commands/dashboard.yaml +0 -0
  219. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/spec/manifests/commands/data-app.yaml +0 -0
  220. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/spec/manifests/commands/dataset.yaml +0 -0
  221. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/spec/manifests/commands/doctor.yaml +0 -0
  222. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/spec/manifests/commands/external-key.yaml +0 -0
  223. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/spec/manifests/commands/file.yaml +0 -0
  224. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/spec/manifests/commands/folder.yaml +0 -0
  225. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/spec/manifests/commands/job.yaml +0 -0
  226. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/spec/manifests/commands/log.yaml +0 -0
  227. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/spec/manifests/commands/notification.yaml +0 -0
  228. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/spec/manifests/commands/parameter.yaml +0 -0
  229. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/spec/manifests/commands/project.yaml +0 -0
  230. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/spec/manifests/commands/report.yaml +0 -0
  231. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/spec/manifests/commands/schedule.yaml +0 -0
  232. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/spec/manifests/commands/schema.yaml +0 -0
  233. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/spec/manifests/commands/skill.yaml +0 -0
  234. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/spec/manifests/commands/snippet.yaml +0 -0
  235. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/spec/manifests/commands/support.yaml +0 -0
  236. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/spec/manifests/commands/template.yaml +0 -0
  237. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/spec/manifests/commands/trash.yaml +0 -0
  238. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/spec/manifests/commands/upgrade.yaml +0 -0
  239. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/spec/manifests/commands/user.yaml +0 -0
  240. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/spec/manifests/commands/version.yaml +0 -0
  241. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/spec/manifests/commands/webhook.yaml +0 -0
  242. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/spec/manifests/commands/workflow.yaml +0 -0
  243. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/spec/manifests/commands/workspace.yaml +0 -0
  244. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/spec/manifests/edits-target.source.yaml +0 -0
  245. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/spec/manifests/openapi-operations.yaml +0 -0
  246. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/spec/manifests/schema-v1.json +0 -0
  247. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/spec/manifests/sdk-catalog.source.yaml +0 -0
  248. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/spec/openapi/metadata.json +0 -0
  249. {mammoth_cli-2.0.91 → mammoth_cli-2.1.0}/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.91
3
+ Version: 2.1.0
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.41
20
+ Requires-Dist: mammoth-io<0.9,>=0.8.0
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.91"
9
+ __version__ = "2.1.0"
10
10
 
11
11
  # The versioned machine output envelope contract.
12
12
  SCHEMA_VERSION = 1
@@ -43,8 +43,9 @@ from mammoth_cli.output.policy import (
43
43
  )
44
44
  from mammoth_cli.runtime import executor, validate
45
45
  from mammoth_cli.runtime.dataset_health import with_dataset_health
46
- from mammoth_cli.runtime.new_data import with_new_data_path
46
+ from mammoth_cli.runtime.intent_only import refuse_hand_crafted_write
47
47
  from mammoth_cli.runtime.invocation import Invocation
48
+ from mammoth_cli.runtime.new_data import with_new_data_path
48
49
  from mammoth_cli.runtime.state import with_state
49
50
  from mammoth_cli.runtime.strict import validate_extra_args
50
51
  from mammoth_cli.runtime.verify import with_verify
@@ -822,6 +823,7 @@ def _execute(invocation: Invocation) -> None:
822
823
  invocation = replace(invocation, profile=profiles.get_selected())
823
824
 
824
825
  def producer() -> tuple[Any, dict[str, Any]]:
826
+ refuse_hand_crafted_write(invocation.command_id)
825
827
  validate.validate_invocation(invocation)
826
828
  validate_extra_args(invocation.command_id, invocation.extra_args)
827
829
  validate.validate_positional_ids(invocation.command_id, invocation.extra_args)
@@ -885,18 +887,25 @@ def _dry_run(handler: Handler, invocation: Invocation) -> tuple[Any, dict[str, A
885
887
  gated SDK call at all (a pure read path); its result is returned as is.
886
888
  """
887
889
  from mammoth_cli.runtime.dryrun import DryRunStop
888
- from mammoth_cli.runtime.dryrun_targets import resolve_targets
890
+ from mammoth_cli.runtime.dryrun_targets import resolve_dependents, resolve_targets
889
891
  from mammoth_cli.runtime.session import open_service, resolved_project
890
892
 
891
893
  try:
892
894
  return handler(invocation)
893
895
  except DryRunStop as stop:
894
896
  with open_service(invocation) as (service, _auth):
895
- targets = resolve_targets(service, invocation.command_id, stop.record["would_call"])
896
- return {**stop.record, "targets": targets}, {
897
- "profile": invocation.profile,
898
- "project_id": resolved_project(invocation),
899
- }
897
+ would_call = stop.record["would_call"]
898
+ targets = resolve_targets(service, invocation.command_id, would_call)
899
+ dependents = resolve_dependents(
900
+ service, invocation.command_id, would_call, resolved_project(invocation)
901
+ )
902
+ impact = invocation.predicted_impact
903
+ report = {**stop.record, "targets": targets}
904
+ if dependents is not None:
905
+ report["dependents"] = dependents
906
+ if impact is not None:
907
+ report["predicted_impact"] = impact
908
+ return report, {"profile": invocation.profile, "project_id": resolved_project(invocation)}
900
909
 
901
910
 
902
911
  def _command_help(command_id: str, record: dict[str, Any] | None) -> str | None:
@@ -25,30 +25,31 @@ transform` command. The data model, capabilities and full web-to-CLI map:
25
25
  ## Start
26
26
 
27
27
  ```bash
28
- mammoth doctor # auth, endpoint, connectivity, version; must succeed
29
- mammoth project ensure 'PROJECT NAME' # get-or-create; becomes the active project
28
+ mammoth doctor # auth, endpoint, connectivity; must succeed
29
+ mammoth project ensure 'PROJECT NAME' # get-or-create; active project
30
30
  ```
31
31
 
32
- `doctor` failing is a precondition failure; never 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
39
- `--profile NAME` only if not `default`; [auth](references/auth.md)
40
- says where the token comes from) and wait; never ask for the token in chat,
41
- never read one from a file/env var, never run `auth login`
42
- yourself. If any envelope carries `meta.update_available`, run its `command`
43
- before the next step.
44
-
45
- In a shell: piped stdout is compact JSON and prompts are off; in a session
46
- that is not piped, `export MAMMOTH_OUTPUT=json MAMMOTH_NO_INPUT=1` once.
47
- `project ensure` saves the active project (`--project`, `MAMMOTH_PROFILE`
48
- and `MAMMOTH_PROJECT` override it). `mammoth skill show --input '{"file":
49
- "references/recipes/transforms.md"}'` prints any file of this skill;
50
- `mammoth skill agents-md install` writes a steering block into a
51
- repository's AGENTS.md so later sessions start here.
32
+ Never proceed if `doctor` fails.
33
+ On a 502, 504 or timeout, `mammoth doctor --input '{"wait": 300}'`
34
+ re-probes that long; continue once it passes. Production is the `app` endpoint; use `release` only
35
+ when named, and check `meta.profile`/`auth status` `endpoint` match. If no profile has credentials, tell the operator to run
36
+ `mammoth auth login` in their own terminal (`--profile NAME` unless
37
+ `default`; [auth](references/auth.md) says where the token comes from) and
38
+ wait; never ask for the token in chat, read one from a file/env var, or run
39
+ `auth login` yourself. If an envelope carries `meta.update_available`, run its `command` first.
40
+
41
+ Piped stdout is compact JSON with prompts off; if not piped, `export
42
+ MAMMOTH_OUTPUT=json MAMMOTH_NO_INPUT=1` once.
43
+ `project ensure` saves the active project (`--project`, `MAMMOTH_PROFILE`,
44
+ `MAMMOTH_PROJECT` override it). `mammoth skill show --input '{"file":
45
+ "references/recipes/transforms.md"}'` prints any file of this skill.
46
+
47
+ ## Running inside the Mammoth app
48
+
49
+ Use the project you are given; never `project ensure`. No `doctor`, auth,
50
+ profiles, `config set`, `upgrade`, `skill install`, env vars, local files,
51
+ stdin, `--input FILE` or `output_path` (they fail `not_available_embedded`);
52
+ downloads return `download_url`. On an auth error, ask the user to reload.
52
53
 
53
54
  ## Defaults you do not repeat
54
55
 
@@ -75,7 +76,7 @@ mammoth schema find "join two datasets; remove duplicates; build a dashboard"
75
76
  | Combine two datasets on a key (merge, VLOOKUP) | `view transform join`; one value per key: `view transform lookup` |
76
77
  | 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)) |
77
78
  | Keep or remove rows | `view transform filter` |
78
- | Remove duplicate rows | `view transform discard-duplicates` |
79
+ | Remove duplicate rows | read `duplicates`; 0: stop. Else `view transform discard-duplicates` |
79
80
  | 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 |
80
81
  | Totals, counts, averages per group — as a lasting change to the pipeline | `view transform pivot` |
81
82
  | A calculated column | `view transform math` |
@@ -86,7 +87,7 @@ mammoth schema find "join two datasets; remove duplicates; build a dashboard"
86
87
  | Rank, running total, previous row | `view transform window` |
87
88
  | A dashboard | `dashboard v3 generate`, then `chat edit` ([dashboards](references/recipes/dashboards.md)) |
88
89
  | Deliver the rows | `view export csv`, `view export postgres` (and other destinations), `view export dataset` |
89
- | 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) |
90
+ | 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. Recipe and caveats: [recurring work](references/recipes/scheduling.md) |
90
91
 
91
92
  Call a find result (or `suggestions` entry) from its `accepted_fields` and
92
93
  `agent_example`. Before concluding the CLI cannot do something the web app
@@ -108,7 +109,7 @@ dashboard from t_a and t_b"). Work it out from the data before building:
108
109
  2. Find the keys. A column in one view whose values appear in a column of
109
110
  the other (`customer_id` and `id`, `order_ref` and `order_no`) is a
110
111
  foreign key; the view with many rows per key is the main one.
111
- 3. Make the keys match before the join: same type (`convert-type`), same
112
+ 3. Read both key columns, then match the keys: same type (`convert-type`), same
112
113
  case and padding (`text`), no blanks (`set-values`, `filter`).
113
114
  4. Act on every `column_warnings` entry for a column the deliverable uses:
114
115
  run its `fix` (`convert-type` to `NUMERIC`/`DATE`; non-numeric values
@@ -176,8 +177,8 @@ your report. If no column links the files, ask before you combine them.
176
177
  - Check an answer with no write against the question (a trend: time
177
178
  buckets, a partial period named; no `project check`); a reported number
178
179
  comes from `calc`/`view data compare`, never mental math.
179
- - After a write, run `mammoth project check PROJECT_ID` and fix each
180
- `to_report` line, or note it in the report.
180
+ - After a write, run `mammoth project check PROJECT_ID DATASET_ID`; fix
181
+ only the `to_report` lines your request touches.
181
182
  - Run the [report checklist](references/report-checklist.md) before stating
182
183
  a number or calling a step done. When files disagree,
183
184
  [capabilities](references/capabilities.md) wins over a recipe, then the
@@ -61,7 +61,7 @@ workspace account and billing; an API token belongs to one workspace
61
61
  | Check data quality in the pipeline | Data Check, Checkpoint Alert | `view data-check create`, `view checkpoint create` |
62
62
  | Reuse a value or a SQL block | Parameters, Snippets | `parameter ...`, `snippet ...` |
63
63
  | Inspect or restore pipeline history | Version history | `view version list`, `view version apply` |
64
- | Build a dashboard | Publish | `dashboard create-blank`, `dashboard v3 generate`, `dashboard canvas ...` |
64
+ | Build a dashboard | Publish | `dashboard v3 generate`, `dashboard chat edit` |
65
65
  | Deliver data | Export, Send to dataset | `view export csv`, `view export postgres` (and other destinations), `view export dataset` |
66
66
  | Automate | Automations | `automation ...`, `workflow ...` |
67
67
  | Undo a delete | Trash | `trash list`, `trash restore` |
@@ -146,10 +146,12 @@ No command:
146
146
  appends again into the target dataset, not just the first run. To stack
147
147
  rows into a brand-new dataset instead of an existing one, omit
148
148
  `target_ds_id`. A row present in both sources lands twice: note the
149
- appended view's `row_count` (`view get`), run `view transform
150
- discard-duplicates` on it (`ignore_columns` for any column you added per
151
- source, e.g. a region tag, since it would make shared rows differ), read
152
- `row_count` again, and report the difference as duplicates removed.
149
+ appended view's `row_count` (`view get`) and its `duplicates` fact
150
+ (`view data get`; zero means nothing to remove: report that and stop). If
151
+ there are duplicates, run `view transform discard-duplicates` on it
152
+ (`ignore_columns` for any column you added per source, e.g. a region tag,
153
+ since it would make shared rows differ), read `row_count` again, and
154
+ report the difference as duplicates removed.
153
155
  - **Hide or reorder columns.** Display changes in the web app; they do not
154
156
  change the data.
155
157
 
@@ -418,7 +418,7 @@ Status on release: untried; no live run recorded.
418
418
 
419
419
  Run: `mammoth view export create`. Exact input fields: `mammoth schema get view.export.create`.
420
420
 
421
- Example: `mammoth view export create 123 --input '{"export_spec": {"DATAVIEW_ID": 1, "handler_type": "postgres", "trigger_type": "none", "target_properties": {"file": "./sales.csv", "file_type": "./sales.csv", "include_hidden": true, "is_format_set": true, "use_format": true}, "additional_properties": {}, "run_immediately": true}}'`. Illustrative only: append `--yes` after observing an owned target.
421
+ Example: `mammoth view export create 123 --input '{"export_spec": {"DATAVIEW_ID": 1, "handler_type": "postgres", "trigger_type": "none", "run_immediately": true}}'`. Illustrative only: append `--yes` after observing an owned target.
422
422
 
423
423
  Result: `ViewExportCreateResult`; mutation `external_effect`, confirmation `yes_always`, wait policy `returns_job`.
424
424
 
@@ -17,3 +17,7 @@ condition, not permission to retry mutations. The credential rule lives in
17
17
  [auth](../auth.md); this recipe does not restate it.
18
18
 
19
19
  Exit 4 is auth/authorization; preserve the structured error and stop safely.
20
+
21
+ In the Mammoth app none of the above applies: there is no `auth status`,
22
+ `doctor` or profile, and the app passes the login and project. On exit 4 ask
23
+ the user to reload the page.
@@ -10,9 +10,16 @@ requested dataset, dashboard, view, or export artifact as incidental tidy-up.
10
10
  mammoth schema find "trash"
11
11
  mammoth schema find "restore"
12
12
  mammoth schema get dataset.delete
13
+ mammoth dataset delete OWNED_DATASET_ID --project PROJECT_ID --dry-run
13
14
  mammoth dataset delete OWNED_DATASET_ID --project PROJECT_ID --yes
14
15
  ```
15
16
 
17
+ Run the `--dry-run` first for a dataset, view, task or column delete. Its
18
+ `dependents` block lists the views, dashboards and pipelines that read the
19
+ resource (from `project resource-dependencies`); show it at the confirm step.
20
+ `dependents.checked: false` means the lookup failed, not that nothing depends
21
+ on it: run `project resource-dependencies` yourself before you delete.
22
+
16
23
  Keep an immutable typed baseline: before creating anything, record every
17
24
  pre-existing id by type (`project list`, `dataset list`, `dashboard list`,
18
25
  `view list DATASET_ID` for each dataset you will touch). Before deleting,
@@ -2,12 +2,17 @@
2
2
 
3
3
  `dashboard create` (the legacy AI-generation engine) does not exist as a
4
4
  command: it has no handler in current apiv2 (always 404s; historically HTTP
5
- 409 `4DASH012 DASHBOARD_LEGACY_CREATION_RETIRED`). Build a board from one
6
- sentence with `v3 generate`, and change it with `chat edit`. Author or edit the
7
- canvas yourself (`create-blank`, `canvas get` then `canvas save`, `pages add`)
8
- for what a sentence cannot say exactly: units, hiding a built-in tile or
9
- insight, an exact layout. `dashboard filter add` puts a filter control on a
10
- board (below).
5
+ 409 `4DASH012 DASHBOARD_LEGACY_CREATION_RETIRED`).
6
+
7
+ **Intent only.** Every dashboard is built and changed from what the user asked
8
+ for, in their own words: `dashboard v3 generate` builds a board, `dashboard chat
9
+ edit` changes one. Pass the user's request as the `intent` / `prompt`; do not
10
+ write canvas JSON, KPI cards, charts, filters or layout yourself, and do not
11
+ work around a request the builder handled badly by hand-crafting the result.
12
+ `dashboard create-blank`, `canvas save`, `canvas restore`, `pages add`,
13
+ `template apply|fit|use|create` and `import-workbook` are for a person at the
14
+ standalone CLI; an in-product run refuses them with `intent_only_dashboards`.
15
+ Reads (`dashboard get`, `canvas get`, `descriptor-data`) are always fine.
11
16
  `dashboard source list` is an observed blocker on release (see
12
17
  capabilities); verify the view binding with `dashboard get DASHBOARD_ID`
13
18
  (`data.sources`) instead.
@@ -26,64 +31,20 @@ Before you say anything about a board that already exists (what a chart shows,
26
31
  its numbers, the period it covers), run `dashboard get DASHBOARD_ID`: its
27
32
  `values` carry every KPI card's and tile's number and the `period` it counts.
28
33
  Answer from those, never from an earlier turn.
34
+ `dashboard get ID` and `dashboard canvas get ID` read by id whichever project is
35
+ active, so a board open in another project needs no `--project`; the result's
36
+ `project_id` names the project it lives in (null when the backend does not say).
29
37
 
30
- Discover page/widget/publish routes and verify the binding, draft/published
31
- data and terminal jobs. Use only returned IDs and schema confirmation policy;
32
- do not invent dashboard JSON or opaque task specs.
38
+ Verify the board with `dashboard get DASHBOARD_ID` (binding, `values`) after
39
+ every change. A creation response alone is not proof of a usable published
40
+ view. If the dashboard is requested as a deliverable, keep the dashboard ID
41
+ named in the returned `data` and do not clean it up. Otherwise, classify it
42
+ explicitly as temporary/intermediate before authorizing deletion.
33
43
 
34
- Expected create-blank input is currently typed as
35
- `{"params":{"dataview_id":VIEW_ID,"title":"TITLE"}}`; confirm with
36
- `schema get dashboard.create-blank` first. If the dashboard is requested as a
37
- deliverable, preserve the dashboard ID actually named in the returned `data`
38
- object and do not clean it up. Otherwise, classify it explicitly as
39
- temporary/intermediate before authorizing deletion. Then run:
40
-
41
- ```bash
42
- mammoth dashboard get DASHBOARD_ID
43
- mammoth schema find "dashboard page"
44
- mammoth schema find "dashboard"
45
- ```
46
-
47
- Page/widget schemas vary by release. Read each schema, use returned IDs, and
48
- verify the binding plus draft/published data after every mutation. A
49
- creation response alone is not proof of a usable published view.
50
-
51
- ## Authoring a board from a blank canvas
52
-
53
- `create-blank` gives one empty page. Author it by reading the canvas,
54
- editing the **active page** (`pages[0]`; a root-level `focus` is stored but
55
- never baked when pages exist) and writing the whole object back:
56
-
57
- ```bash
58
- mammoth dashboard create-blank --yes --input '{"params": {"dataview_id": VIEW_ID, "title": "Overview"}}'
59
- mammoth dashboard canvas get DASHBOARD_ID > canvas.json # data.canvas is the object to edit
60
- # pages[0].focus = {"measure": "Sales Actual", "dim": "Location",
61
- # "kpis": [{"field": "Sales Actual", "agg": "sum", "label": "Sales", "unit": {"prefix": "£"}, "decimals": 0},
62
- # {"field": "Employee Ref", "agg": "countDistinct", "label": "Distinct staff"}]}
63
- # pages[0].added = [{"kind": "bar", "title": "Actual vs Budget by Month", "measure": "Sales Actual", "measure2": "Sales Budget",
64
- # "agg": "sum", "date_bucket": {"field": "Month", "unit": "month"}},
65
- # {"kind": "hbar", "title": "Sales by Location", "dim": "Location", "measure": "Sales Actual", "agg": "sum", "sort": "desc"},
66
- # {"kind": "line", "title": "Occupancy rate", "measure": "occupancy_rate", "date_bucket": {"field": "Month", "unit": "month"}},
67
- # {"kind": "table", "title": "Detail", "columns": ["Location", "Month", "Places"], "sort_by": "Month", "limit": 100}]
68
- # derived = [{"id": "occupancy_rate", "label": "Occupancy rate", "numerator": "Occupied", "denominator": "Places"}]
69
- # filters = [{"field": "Month", "control": "range", "label": "Month"}, {"field": "Location", "control": "multi"}]
70
- mammoth dashboard canvas save DASHBOARD_ID --input '{"body": {"params": {"canvas": <edited data.canvas>}}}'
71
- mammoth job wait BAKE_JOB_ID # data.bake_job_id from the save
72
- ```
73
-
74
- Rules the backend enforces (each returns the pydantic path on failure):
75
- `added[].measure` is a column name — a ratio lives in `canvas.derived[]` and
76
- is referenced by id; `focus.kpis[].agg` accepts `countDistinct` (the only
77
- correct aggregation for a "distinct people" card under a date filter);
78
- `unit.prefix` goes on money cards only. `dashboard pages add --yes --confirm
79
- ID --input '{"body": {"params": {"pages": [{"title": ..., "focus": {...},
80
- "charts": [...]}]}}}'` adds a page, but that route runs through the LLM
81
- guard and may drop a unit it cannot evidence (it says so in `data.message`);
82
- `canvas save` keeps what you wrote. When the route refuses a chart (for
83
- example a `pie` that the data does not support), `data.chart_check.refused`
84
- names it. A new page that got no charts is removed, and
85
- `data.chart_check.removed_pages` lists it. Add a chart of a different kind
86
- (`hbar`, `line`, `table`) for that page.
44
+ If the board is not what the user asked for (a wrong chart, a missing unit, a
45
+ tile they do not want), say so in the next `chat edit` prompt in the user's
46
+ words ("show revenue in pounds", "remove the Key insights tile"); the builder
47
+ decides how.
87
48
 
88
49
  ## "Per region", "per month", "for each X": one board and a filter control
89
50
 
@@ -115,32 +76,6 @@ chart that groups by month (`date_bucket`).
115
76
  Build only the board you were asked for. If the user wants the board for one
116
77
  region only, that is the control's `default`, not a second board.
117
78
 
118
- ## Hide a built-in tile or insight
119
-
120
- A board's built-in parts (Key insights, the KPI strip, the breakdown, trend and
121
- table tiles) re-derive from the data, so they cannot be deleted; the product's
122
- "Remove" hides them: it adds the tile's key to `hidden` on the page. Do the
123
- same with `canvas save`: read the canvas, add the key to the page's `hidden`,
124
- write it back.
125
-
126
- ```bash
127
- mammoth dashboard canvas get DASHBOARD_ID > canvas.json # data.canvas is the object to edit
128
- # pages[0].hidden = ["summary"] Key insights tile
129
- # ["kpis"] the whole KPI strip
130
- # ["breakdown", "mix", "secondary", "trend", "table"] the other built-in tiles
131
- # canvas.hidden (no pages) is the same list on a canvas without pages
132
- mammoth dashboard canvas save DASHBOARD_ID --input '{"body": {"params": {"canvas": <edited data.canvas>}}}'
133
- mammoth job wait BAKE_JOB_ID # data.bake_job_id from the save
134
- ```
135
-
136
- `hidden` sits on the page you mean (`pages[i]`, the page the tile is on), not
137
- on the canvas root, when the canvas has `pages`. Keep the keys already in the
138
- list. A single KPI card is removed by taking its entry out of
139
- `pages[i].focus.kpis`. To hide one insight rather than the whole tile, put its
140
- tag in `insights.hide` (tags: `leader`, `momentum`, `gap`, `laggard`,
141
- `concentration`, `secondary`, `peak`, `quality`, `spread`). Read the board back
142
- with `dashboard canvas get` and check the key is in `hidden`.
143
-
144
79
  ## Put the money on the board
145
80
 
146
81
  If the data has money (a price, an amount, revenue or cost), the dashboard
@@ -158,20 +93,20 @@ mammoth view transform math VIEW_ID --project PROJECT_ID \
158
93
  --input '{"dataset_id":DATASET_ID,"expression":"qty * price","new_column":"revenue"}'
159
94
  ```
160
95
 
161
- - Add every column the board needs before `create-blank`. A dashboard sees
162
- only the columns the view had when the dashboard was made: `pages add`
163
- refuses a later column ("isn't a measure in this data"). If you added it
164
- after, make a new dashboard and delete the old one if you made it for this
165
- task. The upload result's `before_dashboard` names the column to add.
166
- - Put revenue in a KPI (`focus.kpis`, `agg` `sum`, `unit.prefix` for the
167
- currency) and in one or more charts (revenue by product, by segment, by
168
- month). Rows with an empty price give an empty revenue. Say how many there
169
- are in your report.
170
- - `create-blank`, `canvas save` and `pages add` return `deliverable_check`:
171
- `money_not_shown` (with the `math` command in `fix`), `unit_price_summed`,
172
- `columns_not_on_dashboard` (view columns added after the dashboard was
173
- made, with the `create-blank` command in `fix`), and one `blank_values` entry for each column on the board that has blanks.
174
- Fix each warning, or say in your report why you kept it.
96
+ - Add every column the board needs before `v3 generate`. A dashboard sees
97
+ only the columns the view had when the dashboard was made; a later column
98
+ is not on it. If you added it after, generate a new dashboard and delete the
99
+ old one if you made it for this task. The upload result's `before_dashboard`
100
+ names the column to add.
101
+ - Ask for the money in the intent ("revenue by product, by segment and by
102
+ month, with a revenue card"). Rows with an empty price give an empty
103
+ revenue. Say how many there are in your report.
104
+ - A generate or edit result may carry `deliverable_check`: `money_not_shown`
105
+ (with the `math` command in `fix`), `unit_price_summed`,
106
+ `columns_not_on_dashboard` (view columns added after the dashboard was made)
107
+ and one `blank_values` entry for each column on the board that has blanks.
108
+ Fix each warning (add the column, then ask again in words), or say in your
109
+ report why you kept it.
175
110
 
176
111
  **Read the bindings back, then the numbers.** `dashboard canvas get` returns
177
112
  `data.meta.figures` — `"p1:kpi:2": {"descriptors": {"value": "<id>"}}` per
@@ -190,15 +125,9 @@ that equals a row count, is a wrong binding, not a data fact.
190
125
 
191
126
  ## Canvas, widget data and PDF
192
127
 
193
- Never save an invented canvas. Read it, change it, write it back:
194
-
195
- ```bash
196
- mammoth dashboard canvas get DASHBOARD_ID # data.canvas incl. style_tokens
197
- mammoth dashboard canvas save DASHBOARD_ID --input '{"body":{"params":{"canvas":CANVAS_FROM_GET}}}'
198
- ```
199
-
200
- `canvas save` with `{"canvas": {}}` fails (`dataset` and other fields are
201
- required); the object returned by `canvas get` is the only known-good shape.
128
+ `dashboard canvas get DASHBOARD_ID` reads the canvas (`data.canvas` incl.
129
+ `style_tokens`). It is for reading; change a board with `chat edit`, never by
130
+ writing a canvas back.
202
131
  Widget ids for `dashboard data draft` / `dashboard data published` come from
203
132
  that canvas: `--input '{"widget_id": "WIDGET_UUID"}'` (optional
204
133
  `global_filters` / `drilldown_filters` objects). `dashboard query` needs a
@@ -257,3 +186,13 @@ returns the plaintext signing secret once, never on a read) and `dashboard
257
186
  embed lifetime set WORKSPACE_ID --input '{"token_ttl": 900}'` (60-3600
258
187
  seconds, how long a minted embed viewer session lives).
259
188
 
189
+
190
+ ## Pin a dashboard, file it "under" a name
191
+
192
+ Pinning is a per-user preference: `user preference get`, read
193
+ `GLOBAL.DASHBOARDS.pinned_ids`, then write the whole list back with the id
194
+ appended as a string: `user preference update --input
195
+ '{"patch":[{"op":"replace","path":"global.dashboards","value":{"pinned_ids":["123"]}}]}'`
196
+ (unpin = write it without the id). Dashboards live in no folder, so
197
+ `folder move` cannot file one; the library groups by tags: `dashboard tags set
198
+ DASHBOARD_ID --input '{"tags":["Finance"]}' --yes --confirm DASHBOARD_ID`.
@@ -23,7 +23,8 @@ reconciliation before replay.
23
23
  Representative successful local export data is typically an envelope with a
24
24
  returned export/artifact identifier or path under `data`; verify that path is
25
25
  owned, exists, has the expected schema/row count, and hash it. If the command
26
- returns `job_id`, read it until terminal success before inspecting the artifact.
26
+ returns `job_id`, run `mammoth job wait JOB_ID` (not a hand-rolled poll of
27
+ `job get`) and read the result once before inspecting the artifact.
27
28
  If `schema get view.export.csv` rejects requested fields, preserve the
28
29
  structured error and discover another declared export route rather than using
29
30
  raw HTTP.
@@ -28,11 +28,13 @@ mammoth dataset file-settings update DATASET_ID --project PROJECT_ID \
28
28
  --input '{"delimiter": ",", "has_header": true, "initial_skip_count": 0, "quotechar": "\"", "date_format": "US"}'
29
29
  ```
30
30
 
31
- The response is a job (`operation: "understand_csv"`). Poll `dataset get`
32
- (the record is under `data.dataset`, so read `data.dataset.status`) until
33
- the status leaves `need_action`. It usually reaches `ready` within seconds;
34
- on prague an ISO `YYYY-MM-DD` column was flagged ambiguous and took about
35
- three minutes, so poll for up to five minutes before treating it as stuck.
31
+ The response is a job (`operation: "understand_csv"`). Run
32
+ `mammoth job wait JOB_ID` on its `job_id` instead of polling by hand, then
33
+ read `dataset get` once (the record is under `data.dataset`, so read
34
+ `data.dataset.status`) to confirm the status left `need_action`. It usually
35
+ reaches `ready` within seconds; on prague an ISO `YYYY-MM-DD` column was
36
+ flagged ambiguous and took about three minutes, so allow up to five minutes
37
+ before treating it as stuck.
36
38
  Then `view list` returns the generated view and typed transforms can
37
39
  proceed. Every environment can ask, release included: on 2026-09-24 release
38
40
  flagged an ISO `YYYY-MM-DD` column too and reached `ready` within seconds of
@@ -10,6 +10,10 @@ Discover exact contracts, then upload and read back explicit parents.
10
10
 
11
11
  ## Where uploads land
12
12
 
13
+ In the Mammoth app, use the project you are given and never run `project
14
+ ensure` or `project create` for a scratch project; the rest of this section is
15
+ for the CLI in a terminal.
16
+
13
17
  Unless the task names a project, work in one project of your own and put
14
18
  every dataset of the task there. The user's real projects then stay clean, and
15
19
  one sweep removes everything. `project ensure` is idempotent get-or-create
@@ -37,7 +37,7 @@ mammoth automation create 'Nightly refresh' --yes --input '{
37
37
  ],
38
38
  "conditions": [
39
39
  {"condition_type": "at_specific_time", "details": {
40
- "frequency": "daily", "interval": 1, "start_at": "2026-01-01T02:00:00Z"
40
+ "frequency": "daily", "interval": 1, "start_at": "2027-01-01T02:00:00Z"
41
41
  }}
42
42
  ]
43
43
  }'
@@ -71,7 +71,7 @@ mammoth automation create 'Monthly brand spend to client' --yes --input '{
71
71
  ],
72
72
  "conditions": [
73
73
  {"condition_type": "at_specific_time", "details": {
74
- "frequency": "monthly", "interval": 1, "start_at": "2026-01-01T02:00:00Z"
74
+ "frequency": "monthly", "interval": 1, "start_at": "2027-01-01T02:00:00Z"
75
75
  }}
76
76
  ]
77
77
  }'
@@ -102,6 +102,21 @@ automation.create` under `tasks[].details`:
102
102
  or via its other condition types (new file in a folder, etc.), not on a
103
103
  recurrence.
104
104
 
105
+ ## Create once: list first, update instead of create
106
+
107
+ `automation create` is not idempotent: running it twice makes two
108
+ automations that both fire (two client emails a month). Before every create:
109
+
110
+ ```bash
111
+ mammoth automation list # is there already one with this name or these recipients?
112
+ ```
113
+
114
+ If one exists, change it with `automation update AUTOMATION_ID` (see below)
115
+ instead of creating another. Before a schedule that emails a client, send the
116
+ same email to the user first (or `--dry-run` the create and show the
117
+ recipients, subject and attached views) and get a yes. Give `start_at` a time
118
+ in the future; a past `start_at` may fire straight away or never.
119
+
105
120
  ## Read it back
106
121
 
107
122
  ```bash
@@ -123,7 +138,8 @@ matching the empty response body (a normal validation error returns a JSON
123
138
  envelope; this does not). Do not report "the automation vanished"; if `get`
124
139
  or `list` fail this way right after a create, treat the create's own 200/202
125
140
  response and `automation_id` as the source of truth, and say so in the
126
- report. This is not something the CLI can work around — do not retry
141
+ report as "created, unconfirmed" (the create returned 200 but the read-back
142
+ failed): never re-run the create to "fix" it, which makes a duplicate. This is not something the CLI can work around — do not retry
127
143
  `automation get` more than once for this.
128
144
 
129
145
  ## Update: disable / enable, change tasks, run now
@@ -155,7 +171,7 @@ mammoth automation trash AUTOMATION_ID # reversible; automation.restor
155
171
  ```bash
156
172
  mammoth schema get schedule.create
157
173
  mammoth schedule create --yes --input '{"spec": {
158
- "rrule": {"frequency": "daily", "start": "2026-01-01T02:00:00Z"},
174
+ "rrule": {"frequency": "daily", "start": "2027-01-01T02:00:00Z"},
159
175
  "work_items": [{"name": "pull_cloud_data", "execution_params": {
160
176
  "schedule_type": "moment", "first_pull_at": "now", "on_refresh_action": "replace"
161
177
  }, "args": [DATASET_ID]}]
@@ -38,8 +38,9 @@ Compare the two reads: the row count is unchanged, the rows that were blank
38
38
  now read `0`, and every non-blank value is identical to the before-sample.
39
39
  If every row now reads `0`, or a non-blank value changed, the condition was
40
40
  dropped: stop, do not build joins or summaries on this view, and report it.
41
- Use `view data get` (paged, 400 rows per page) for this, not `view preview`
42
- (50 rows), and sample from more than one page on a large view.
41
+ Use `view data get` (paged, 50 rows per page by default; pass `limit` and
42
+ `offset` for more) for this, not `view preview`, and sample from more than
43
+ one page on a large view.
43
44
 
44
45
  - `filter` keeps matching rows by default (`filter_type: "SHOW"`); to drop
45
46
  rows, say so: `{"condition":{"column":"units","operator":"LT","value":0},"filter_type":"REMOVE"}`. For each operation, a successful result should contain a returned
@@ -84,9 +85,12 @@ In a math `expression`, write a multi-word display name bare (`Quantity * Unit
84
85
  Price`) or quoted (`Quantity * \"Unit Price\"` inside the JSON string).
85
86
 
86
87
  The released catalog exposes typed dedupe through `schema find duplicate` as
87
- `view.transform.discard-duplicates`. Inspect its optional `ignore_columns`
88
- field before submitting. For a join, verify both schemas and
89
- expected multiplicity:
88
+ `view.transform.discard-duplicates`. Observe before writing: `view data get`
89
+ states `duplicates` (`exact_duplicate_rows` over `rows_checked` of `row_count`;
90
+ on a later page it names the table-wide check). When it is 0, report "none,
91
+ no change needed" and add no step. Only then inspect its optional
92
+ `ignore_columns` field and submit; `--dry-run` reports `predicted_impact` or
93
+ fails `no_op`. For a join, verify both schemas and expected multiplicity:
90
94
 
91
95
  ```bash
92
96
  mammoth schema get view.transform.discard-duplicates
@@ -111,9 +115,12 @@ as defaults, and let the user's request override them:
111
115
  - Joins are nearly always `LEFT` on one key column. Use `INNER`, `RIGHT`,
112
116
  `OUTER` or a key of two or more columns only when the user asks for it or
113
117
  the data needs it, and say why in your report.
114
- - Check the key before a join or lookup. Most keys go in without a prep
115
- step, so a type, case or padding difference shows up as unmatched rows. Read
116
- both key columns first (`view data get`) and act on `join_check`.
118
+ - Always read both key columns before a join or lookup (`view data get`, and
119
+ `view data profile` for blanks and spelling), then run the join with
120
+ `--dry-run`: its `join_preview` gives `match_rate` and `unmatched_keys`
121
+ without writing. A low rate means a type, case or padding difference: fix
122
+ the keys first (`convert-type`, `text`). After the real join, act on
123
+ `join_check`.
117
124
  - Date steps (`increment-date`, `extract-date`, and `text` on date columns)
118
125
  fail more often than other steps. Before a date step, confirm that the
119
126
  column type is `DATE` (`view get`); if it is `TEXT`, run `convert-type`
@@ -198,6 +205,11 @@ values you are summing.
198
205
  `view list` returns `data.dataviews[]`, `view data get` returns rows keyed by
199
206
  display name. Read the envelope you got, not the one you expected.
200
207
 
208
+ Read-only way to answer a by-weekday or by-month question: `view data aggregate`
209
+ with a `part` group, for example `--input '{"group_by": [{"column": "Order Date",
210
+ "part": "weekday"}], "aggregations": [{"column": "Sales", "function": "SUM",
211
+ "as_name": "Total"}], "order_by": ["Total desc"]}'`. Do not build a temporary view.
212
+
201
213
  Prefer `pivot` over `add-sql` for a grouped summary when `capabilities.md`
202
214
  lists it as run on release; `add-sql` replaces every column of the view, so
203
215
  never run it on a deliverable view.