mammoth-cli 2.0.41__tar.gz → 2.0.43__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 (224) hide show
  1. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/PKG-INFO +1 -1
  2. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/mammoth_cli/__init__.py +1 -1
  3. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/mammoth_cli/bundled_skill/mammoth-cli/SKILL.md +12 -5
  4. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/mammoth_cli/bundled_skill/mammoth-cli/references/capabilities.md +1 -1
  5. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/mammoth_cli/bundled_skill/mammoth-cli/references/command-index.md +2 -2
  6. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/project.md +10 -0
  7. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/mammoth_cli/bundled_skill/mammoth-cli/references/recipes/dashboards.md +2 -1
  8. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/mammoth_cli/bundled_skill/mammoth-cli/references/recovery.md +1 -1
  9. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/mammoth_cli/bundled_skill/mammoth-cli/references/report-checklist.md +1 -0
  10. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/mammoth_cli/commands/dashboard.py +16 -4
  11. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/mammoth_cli/commands/doctor.py +41 -4
  12. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/mammoth_cli/commands/project.py +77 -0
  13. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/mammoth_cli/commands/registry.py +1 -0
  14. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/mammoth_cli/services/command_contract.py +2 -0
  15. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/mammoth_cli/services/dashboard_review.py +37 -0
  16. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/mammoth_cli/services/mapping.py +34 -0
  17. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/mammoth_cli/services/positionals.py +1 -0
  18. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/pyproject.toml +1 -1
  19. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/spec/manifests/commands/project.yaml +39 -0
  20. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/.gitignore +0 -0
  21. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/LICENSE +0 -0
  22. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/README.md +0 -0
  23. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/mammoth_cli/__main__.py +0 -0
  24. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/mammoth_cli/app.py +0 -0
  25. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/mammoth_cli/bundled_skill/mammoth-cli/references/about-mammoth.md +0 -0
  26. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/mammoth_cli/bundled_skill/mammoth-cli/references/auth.md +0 -0
  27. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/mammoth_cli/bundled_skill/mammoth-cli/references/capabilities-misc.md +0 -0
  28. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/activity.md +0 -0
  29. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/addon.md +0 -0
  30. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/agent.md +0 -0
  31. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/ai.md +0 -0
  32. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/annotation.md +0 -0
  33. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/auth.md +0 -0
  34. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/automation.md +0 -0
  35. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/batch.md +0 -0
  36. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/billing.md +0 -0
  37. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/browse.md +0 -0
  38. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/capability.md +0 -0
  39. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/client-app.md +0 -0
  40. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/completion.md +0 -0
  41. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/config.md +0 -0
  42. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/connector.md +0 -0
  43. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/context.md +0 -0
  44. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/dashboard.md +0 -0
  45. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/data-app.md +0 -0
  46. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/dataset.md +0 -0
  47. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/doctor.md +0 -0
  48. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/external-key.md +0 -0
  49. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/file.md +0 -0
  50. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/folder.md +0 -0
  51. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/job.md +0 -0
  52. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/log.md +0 -0
  53. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/notification.md +0 -0
  54. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/parameter.md +0 -0
  55. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/report.md +0 -0
  56. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/schedule.md +0 -0
  57. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/schema.md +0 -0
  58. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/skill.md +0 -0
  59. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/snippet.md +0 -0
  60. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/support.md +0 -0
  61. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/template.md +0 -0
  62. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/trash.md +0 -0
  63. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/upgrade.md +0 -0
  64. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/user.md +0 -0
  65. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/version.md +0 -0
  66. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/view.md +0 -0
  67. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/webhook.md +0 -0
  68. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/workflow.md +0 -0
  69. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/workspace.md +0 -0
  70. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/mammoth_cli/bundled_skill/mammoth-cli/references/handoff.md +0 -0
  71. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/mammoth_cli/bundled_skill/mammoth-cli/references/input.md +0 -0
  72. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/mammoth_cli/bundled_skill/mammoth-cli/references/jobs-drafts.md +0 -0
  73. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/mammoth_cli/bundled_skill/mammoth-cli/references/machine-output.md +0 -0
  74. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/mammoth_cli/bundled_skill/mammoth-cli/references/operations.md +0 -0
  75. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/mammoth_cli/bundled_skill/mammoth-cli/references/recipes/auth-scope.md +0 -0
  76. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/mammoth_cli/bundled_skill/mammoth-cli/references/recipes/cleanup.md +0 -0
  77. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/mammoth_cli/bundled_skill/mammoth-cli/references/recipes/end-to-end.md +0 -0
  78. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/mammoth_cli/bundled_skill/mammoth-cli/references/recipes/exports.md +0 -0
  79. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/mammoth_cli/bundled_skill/mammoth-cli/references/recipes/index.md +0 -0
  80. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/mammoth_cli/bundled_skill/mammoth-cli/references/recipes/need-action.md +0 -0
  81. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/mammoth_cli/bundled_skill/mammoth-cli/references/recipes/resources.md +0 -0
  82. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/mammoth_cli/bundled_skill/mammoth-cli/references/recipes/transforms.md +0 -0
  83. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/mammoth_cli/bundled_skill/mammoth-cli/references/recipes/typed-etl-discovery.md +0 -0
  84. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/mammoth_cli/bundled_skill/mammoth-cli/references/retention.md +0 -0
  85. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/mammoth_cli/bundled_skill/mammoth-cli/references/safety.md +0 -0
  86. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/mammoth_cli/bundled_skill/mammoth-cli/references/task-start.md +0 -0
  87. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/mammoth_cli/commands/__init__.py +0 -0
  88. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/mammoth_cli/commands/activity.py +0 -0
  89. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/mammoth_cli/commands/addon.py +0 -0
  90. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/mammoth_cli/commands/agent.py +0 -0
  91. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/mammoth_cli/commands/ai.py +0 -0
  92. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/mammoth_cli/commands/annotation.py +0 -0
  93. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/mammoth_cli/commands/auth.py +0 -0
  94. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/mammoth_cli/commands/automation.py +0 -0
  95. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/mammoth_cli/commands/batch.py +0 -0
  96. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/mammoth_cli/commands/billing.py +0 -0
  97. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/mammoth_cli/commands/browse.py +0 -0
  98. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/mammoth_cli/commands/capability.py +0 -0
  99. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/mammoth_cli/commands/client_app.py +0 -0
  100. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/mammoth_cli/commands/completion.py +0 -0
  101. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/mammoth_cli/commands/config.py +0 -0
  102. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/mammoth_cli/commands/connector.py +0 -0
  103. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/mammoth_cli/commands/context.py +0 -0
  104. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/mammoth_cli/commands/data_app.py +0 -0
  105. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/mammoth_cli/commands/dataset.py +0 -0
  106. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/mammoth_cli/commands/external_key.py +0 -0
  107. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/mammoth_cli/commands/file.py +0 -0
  108. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/mammoth_cli/commands/folder.py +0 -0
  109. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/mammoth_cli/commands/job.py +0 -0
  110. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/mammoth_cli/commands/notification.py +0 -0
  111. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/mammoth_cli/commands/parameter.py +0 -0
  112. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/mammoth_cli/commands/report.py +0 -0
  113. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/mammoth_cli/commands/schedule.py +0 -0
  114. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/mammoth_cli/commands/schema.py +0 -0
  115. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/mammoth_cli/commands/skill.py +0 -0
  116. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/mammoth_cli/commands/snippet.py +0 -0
  117. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/mammoth_cli/commands/support.py +0 -0
  118. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/mammoth_cli/commands/template.py +0 -0
  119. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/mammoth_cli/commands/trash.py +0 -0
  120. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/mammoth_cli/commands/upgrade.py +0 -0
  121. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/mammoth_cli/commands/user.py +0 -0
  122. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/mammoth_cli/commands/view.py +0 -0
  123. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/mammoth_cli/commands/view_ops.py +0 -0
  124. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/mammoth_cli/commands/webhook.py +0 -0
  125. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/mammoth_cli/commands/workflow.py +0 -0
  126. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/mammoth_cli/commands/workspace.py +0 -0
  127. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/mammoth_cli/context/__init__.py +0 -0
  128. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/mammoth_cli/context/credentials.py +0 -0
  129. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/mammoth_cli/context/endpoint.py +0 -0
  130. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/mammoth_cli/context/profiles.py +0 -0
  131. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/mammoth_cli/context/resolver.py +0 -0
  132. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/mammoth_cli/contracts/__init__.py +0 -0
  133. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/mammoth_cli/contracts/auth.py +0 -0
  134. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/mammoth_cli/errors/__init__.py +0 -0
  135. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/mammoth_cli/errors/envelope.py +0 -0
  136. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/mammoth_cli/manifest/__init__.py +0 -0
  137. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/mammoth_cli/manifest/loader.py +0 -0
  138. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/mammoth_cli/messages/__init__.py +0 -0
  139. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/mammoth_cli/output/__init__.py +0 -0
  140. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/mammoth_cli/output/envelope.py +0 -0
  141. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/mammoth_cli/output/normalize.py +0 -0
  142. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/mammoth_cli/output/policy.py +0 -0
  143. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/mammoth_cli/output/progress.py +0 -0
  144. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/mammoth_cli/output/render.py +0 -0
  145. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/mammoth_cli/py.typed +0 -0
  146. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/mammoth_cli/runtime/__init__.py +0 -0
  147. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/mammoth_cli/runtime/confirm.py +0 -0
  148. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/mammoth_cli/runtime/dryrun.py +0 -0
  149. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/mammoth_cli/runtime/executor.py +0 -0
  150. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/mammoth_cli/runtime/input_loader.py +0 -0
  151. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/mammoth_cli/runtime/invocation.py +0 -0
  152. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/mammoth_cli/runtime/options.py +0 -0
  153. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/mammoth_cli/runtime/parents.py +0 -0
  154. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/mammoth_cli/runtime/runlog.py +0 -0
  155. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/mammoth_cli/runtime/session.py +0 -0
  156. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/mammoth_cli/runtime/strict.py +0 -0
  157. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/mammoth_cli/runtime/updates.py +0 -0
  158. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/mammoth_cli/runtime/validate.py +0 -0
  159. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/mammoth_cli/services/__init__.py +0 -0
  160. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/mammoth_cli/services/argspec.py +0 -0
  161. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/mammoth_cli/services/coerce.py +0 -0
  162. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/mammoth_cli/services/conditions.py +0 -0
  163. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/mammoth_cli/services/dashboard_pages.py +0 -0
  164. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/mammoth_cli/services/data_quality.py +0 -0
  165. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/mammoth_cli/services/dispatch.py +0 -0
  166. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/mammoth_cli/services/factory.py +0 -0
  167. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/mammoth_cli/services/input_fields.py +0 -0
  168. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/mammoth_cli/services/openapi_types.py +0 -0
  169. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/mammoth_cli/services/protocol.py +0 -0
  170. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/mammoth_cli/services/sdk_service.py +0 -0
  171. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/mammoth_cli/services/testing.py +0 -0
  172. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/mammoth_cli/services/type_system.py +0 -0
  173. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/mammoth_cli/skills/__init__.py +0 -0
  174. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/mammoth_cli/skills/installer.py +0 -0
  175. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/mammoth_cli/skills/steering.py +0 -0
  176. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/mammoth_cli/testing.py +0 -0
  177. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/spec/manifests/commands/activity.yaml +0 -0
  178. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/spec/manifests/commands/addon.yaml +0 -0
  179. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/spec/manifests/commands/agent.yaml +0 -0
  180. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/spec/manifests/commands/ai.yaml +0 -0
  181. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/spec/manifests/commands/annotation.yaml +0 -0
  182. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/spec/manifests/commands/auth.yaml +0 -0
  183. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/spec/manifests/commands/automation.yaml +0 -0
  184. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/spec/manifests/commands/batch.yaml +0 -0
  185. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/spec/manifests/commands/billing.yaml +0 -0
  186. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/spec/manifests/commands/browse.yaml +0 -0
  187. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/spec/manifests/commands/capability.yaml +0 -0
  188. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/spec/manifests/commands/client-app.yaml +0 -0
  189. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/spec/manifests/commands/completion.yaml +0 -0
  190. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/spec/manifests/commands/config.yaml +0 -0
  191. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/spec/manifests/commands/connector.yaml +0 -0
  192. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/spec/manifests/commands/context.yaml +0 -0
  193. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/spec/manifests/commands/dashboard.yaml +0 -0
  194. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/spec/manifests/commands/data-app.yaml +0 -0
  195. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/spec/manifests/commands/dataset.yaml +0 -0
  196. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/spec/manifests/commands/doctor.yaml +0 -0
  197. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/spec/manifests/commands/external-key.yaml +0 -0
  198. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/spec/manifests/commands/file.yaml +0 -0
  199. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/spec/manifests/commands/folder.yaml +0 -0
  200. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/spec/manifests/commands/job.yaml +0 -0
  201. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/spec/manifests/commands/log.yaml +0 -0
  202. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/spec/manifests/commands/notification.yaml +0 -0
  203. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/spec/manifests/commands/parameter.yaml +0 -0
  204. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/spec/manifests/commands/report.yaml +0 -0
  205. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/spec/manifests/commands/schedule.yaml +0 -0
  206. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/spec/manifests/commands/schema.yaml +0 -0
  207. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/spec/manifests/commands/skill.yaml +0 -0
  208. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/spec/manifests/commands/snippet.yaml +0 -0
  209. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/spec/manifests/commands/support.yaml +0 -0
  210. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/spec/manifests/commands/template.yaml +0 -0
  211. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/spec/manifests/commands/trash.yaml +0 -0
  212. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/spec/manifests/commands/upgrade.yaml +0 -0
  213. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/spec/manifests/commands/user.yaml +0 -0
  214. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/spec/manifests/commands/version.yaml +0 -0
  215. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/spec/manifests/commands/view.yaml +0 -0
  216. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/spec/manifests/commands/webhook.yaml +0 -0
  217. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/spec/manifests/commands/workflow.yaml +0 -0
  218. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/spec/manifests/commands/workspace.yaml +0 -0
  219. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/spec/manifests/openapi-operations.yaml +0 -0
  220. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/spec/manifests/schema-v1.json +0 -0
  221. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/spec/manifests/sdk-catalog.source.yaml +0 -0
  222. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/spec/manifests/sdk-methods.yaml +0 -0
  223. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/spec/openapi/metadata.json +0 -0
  224. {mammoth_cli-2.0.41 → mammoth_cli-2.0.43}/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.41
3
+ Version: 2.0.43
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
@@ -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.41"
9
+ __version__ = "2.0.43"
10
10
 
11
11
  # The versioned machine output envelope contract.
12
12
  SCHEMA_VERSION = 1
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: mammoth-cli
3
- version: 2.0.41
3
+ version: 2.0.43
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
 
@@ -31,7 +31,9 @@ mammoth project ensure 'PROJECT NAME' # get-or-create; becomes the active proj
31
31
  ```
32
32
 
33
33
  `doctor` failing is a precondition failure, not a reason to try the business
34
- command anyway. Production is the `app` endpoint; use `release` only when the
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
35
37
  task names it, and check `meta.profile`/`auth status` `endpoint` match the
36
38
  intended environment before doing anything. If no profile has credentials,
37
39
  tell the operator to run `mammoth auth login` in their own terminal (add
@@ -95,9 +97,10 @@ dashboard from t_a and t_b"). Work it out from the data before you build:
95
97
 
96
98
  1. Upload every file. Each upload result carries a `view` preview of what
97
99
  Mammoth made of the file (`view_id`, column types, sample rows,
98
- `column_warnings`, and `before_dashboard`). Read every view in Mammoth, not
99
- the local files: `view data get VIEW_ID` for each one. The warnings list
100
- numbers or dates stored as text, and blanks, each with the fix.
100
+ `column_warnings`, and `before_dashboard`). Do not open the local files
101
+ (`cat`, `head`): what counts is what Mammoth made of them. Run `view data
102
+ get VIEW_ID` for each view. The warnings list numbers or dates stored as
103
+ text, and blanks, each with the fix.
101
104
  2. Find the keys. A column in one view whose values appear in a column of
102
105
  the other (`customer_id` and `id`, `order_ref` and `order_no`) is a
103
106
  foreign key; the view with many rows per key is the main one.
@@ -172,6 +175,10 @@ your report. If no column links the files, ask before you combine them.
172
175
  "limit": 50}`.
173
176
  - A timeout, exit 7 or interruption does not prove failure; reconcile an
174
177
  `outcome_unknown` (`job get`, `view task list`) before replaying.
178
+ - Before you report, run `mammoth project check PROJECT_ID`. Its `to_report`
179
+ has one line for each open finding in every view and dashboard (blanks,
180
+ text numbers, money not shown, columns a dashboard cannot see). Fix each
181
+ one, or give it one line in the report.
175
182
  - Run the [report checklist](references/report-checklist.md) before stating
176
183
  a number or calling a step done. When files here disagree,
177
184
  [capabilities](references/capabilities.md) wins over a recipe, and a recipe
@@ -1,7 +1,7 @@
1
1
  # What is proven on release
2
2
 
3
3
  Generated from `docs/release-capability-matrix.json`; do not edit by hand.
4
- The CLI publishes 556 commands. 455 of them bind one of the 528 API operations in the matrix; the remainder are local commands (`schema`, `auth`, `doctor`, `log`, ...) or typed variants that share an operation (`view transform *` commands submit through `view.task.add`, except `rename-columns` and `sort`, which set view display properties through `view.update`). 262 bound commands ran once successfully on release, 2 are not supported there, and the rest are untried. Untried is not broken: discover the contract with `mammoth schema get COMMAND_ID`, run it, and treat the structured error envelope as the answer.
4
+ The CLI publishes 557 commands. 455 of them bind one of the 528 API operations in the matrix; the remainder are local commands (`schema`, `auth`, `doctor`, `log`, ...) or typed variants that share an operation (`view transform *` commands submit through `view.task.add`, except `rename-columns` and `sort`, which set view display properties through `view.update`). 262 bound commands ran once successfully on release, 2 are not supported there, and the rest are untried. Untried is not broken: discover the contract with `mammoth schema get COMMAND_ID`, run it, and treat the structured error envelope as the answer.
5
5
 
6
6
  Status meanings:
7
7
 
@@ -1,6 +1,6 @@
1
1
  # Published CLI command catalog
2
2
 
3
- This generated catalog is a lookup table for every command in the published CLI manifest, currently 556; each entry carries its release status line. It is a command-contract index, not an assertion that every backend/OpenAPI operation has a CLI binding. For an exact local CLI contract, run `mammoth schema get COMMAND_ID`; `mammoth capability list` is an API-binding inventory and can omit typed/local CLI routes. For focused workflows, read the [recipes index](recipes/index.md). Sensitive structured input must come from a private file or pipe; never put secrets in literal argv.
3
+ This generated catalog is a lookup table for every command in the published CLI manifest, currently 557; each entry carries its release status line. It is a command-contract index, not an assertion that every backend/OpenAPI operation has a CLI binding. For an exact local CLI contract, run `mammoth schema get COMMAND_ID`; `mammoth capability list` is an API-binding inventory and can omit typed/local CLI routes. For focused workflows, read the [recipes index](recipes/index.md). Sensitive structured input must come from a private file or pipe; never put secrets in literal argv.
4
4
 
5
5
  Load only the applicable domain file:
6
6
 
@@ -31,7 +31,7 @@ Load only the applicable domain file:
31
31
  - [log](commands/log.md) — 2 published commands
32
32
  - [notification](commands/notification.md) — 5 published commands
33
33
  - [parameter](commands/parameter.md) — 14 published commands
34
- - [project](commands/project.md) — 19 published commands
34
+ - [project](commands/project.md) — 20 published commands
35
35
  - [report](commands/report.md) — 1 published commands
36
36
  - [schedule](commands/schedule.md) — 5 published commands
37
37
  - [schema](commands/schema.md) — 3 published commands
@@ -22,6 +22,16 @@ Result: `ProjectBulkUpdateResult`; mutation `high_impact`, confirmation `confirm
22
22
 
23
23
  Status on release: ran once on CLI 2.0.15 — re-verification 2026-09-18: exit 0 on release with CLI 2.0.15. Fix held: body accepted as ProjectsPatch naming project_id in every value item; confirmation named the workspace scope (message: 'bulk-update roles in projects 23 of workspace 4', hint 'Pass --con…
24
24
 
25
+ ### `project.check`
26
+
27
+ Run: `mammoth project check`. Exact input fields: `mammoth schema get project.check`.
28
+
29
+ Example: `mammoth project check 123`. Placeholders are illustrative; resolve IDs and input from observed reads.
30
+
31
+ Result: `ProjectCheckResult`; mutation `read`, confirmation `none`, wait policy `not_async`.
32
+
33
+ Status on release: untried; no live run recorded.
34
+
25
35
  ### `project.checkpoint.list`
26
36
 
27
37
  Run: `mammoth project checkpoint list`. Exact input fields: `mammoth schema get project.checkpoint.list`.
@@ -99,7 +99,8 @@ mammoth view transform math VIEW_ID --project PROJECT_ID \
99
99
  are in your report.
100
100
  - `create-blank`, `canvas save` and `pages add` return `deliverable_check`:
101
101
  `money_not_shown` (with the `math` command in `fix`), `unit_price_summed`,
102
- and one `blank_values` entry for each column on the board that has blanks.
102
+ `columns_not_on_dashboard` (view columns added after the dashboard was
103
+ made, with the `create-blank` command in `fix`), and one `blank_values` entry for each column on the board that has blanks.
103
104
  Fix each warning, or say in your report why you kept it.
104
105
 
105
106
  **Read the bindings back, then the numbers.** `dashboard canvas get` returns
@@ -36,7 +36,7 @@ these commands are not blanket permission to replay a mutation.
36
36
  | `4DASH012 DASHBOARD_LEGACY_CREATION_RETIRED` (HTTP 409) from `dashboard create` | legacy engine retired | `dashboard create-blank` or `dashboard v3 generate` |
37
37
  | `4GENR001 ... params.data` (HTTP 400) from `dashboard pdf export` | route needs a browser-rendered payload | not available from the CLI; report it, do not retry with `{"data": {}}` |
38
38
  | `'destination'` KeyError in a `view export create` job with handler_type csv_file | generic export route is broken for CSV on release | use `view export csv` |
39
- | `timeout` / `outcome_unknown` (exit 7) | the request may have completed | `job get JOB_ID` if you have one, else re-list the resource (`dataset list`, `view task list VIEW_ID DATASET_ID`) before any replay |
39
+ | `timeout` / `outcome_unknown` (exit 7) | the request may have completed | run the envelope's `recovery_commands` first: `job get JOB_ID`, `project get ID` after a delete (repeat until `resource_not_found`), `dashboard list` after `create-blank` (look for your title), `dashboard canvas get ID` after a canvas or pages write. Else re-list the resource (`dataset list`, `view task list VIEW_ID DATASET_ID`) before any replay |
40
40
  | HTTP 502 / connection errors on every command | backend outage | `mammoth doctor`; wait and re-run doctor until it succeeds; do not replay mutations blindly |
41
41
 
42
42
  Every error envelope from CLI 2.0.18 carries `error.log_ref` `{file, run_id}`.
@@ -8,6 +8,7 @@ Every "yes" must point at a command you ran in this task and its response.
8
8
  | State rows in and rows out for every step that can change row count (filter, discard-duplicates, join, limit, unnest, pivot) | `view data get` or `view get` (`row_count`) before and after the step, or the `view data get` around a set-values |
9
9
  | Read back every value-changing transform | `view data get VIEW_ID DATASET_ID` (full page; `view data query` with `limit`/`condition` for a slice) after the job reached `success`; the sample shows the intended change and nothing else changed |
10
10
  | No measure column is all-zero, all-null, or all one value after a transform | inspect the readback sample; an all-`0` / all-`Unknown` column means the condition or column mapping was wrong, not that the data is like that |
11
+ | Decide on every blank the deliverable uses | one report line for each `blank_values` entry (`project check` lists them all: from every view and dashboard): the column, the count, and filled, filtered, or kept and why. Kept is a decision only when you write it down |
11
12
  | A join states its match rate and explains unmatched rows | row count before/after, `IS_EMPTY` filter count on a right-side column, and the key columns named exactly as both view schemas show them |
12
13
  | Group counts add up | Σ of per-group counts from a pivot/crosstab equals the source row count (or nulls in the group key explain the difference) |
13
14
  | Every job you submitted reached a terminal state | `job get JOB_ID` shows `success`; report anything else as failed/unknown, not done |
@@ -43,6 +43,7 @@ from mammoth_cli.services.dashboard_pages import check_added_pages
43
43
  from mammoth_cli.services.dashboard_review import (
44
44
  CANVAS_GET,
45
45
  NEW_COLUMN_NOTE,
46
+ columns_not_on_dashboard,
46
47
  has_profiles,
47
48
  review,
48
49
  )
@@ -721,10 +722,21 @@ def _with_deliverable_check(
721
722
  if isinstance(view_id, int)
722
723
  else None
723
724
  )
724
- fallback = None
725
- if not has_profiles(canvas_doc) and isinstance(view_id, int) and dataset_id is not None:
726
- fallback = view_profiles(service, dataset_id, view_id, resolved_project(invocation))
727
- warnings = review(canvas_doc, dataset_id, fallback)
725
+ current = (
726
+ view_profiles(service, dataset_id, view_id, resolved_project(invocation))
727
+ if isinstance(view_id, int) and dataset_id is not None
728
+ else None
729
+ )
730
+ if has_profiles(canvas_doc):
731
+ stale = columns_not_on_dashboard(canvas_doc, current)
732
+ warnings = stale + [
733
+ warning
734
+ for warning in review(canvas_doc, dataset_id)
735
+ # On a stale board the money advice is the rebuild, not a new column.
736
+ if not (stale and warning["issue"] in {"money_not_shown", "unit_price_summed"})
737
+ ]
738
+ else:
739
+ warnings = review(canvas_doc, dataset_id, current)
728
740
  except Exception: # noqa: BLE001 -- advice must never fail the authoring step
729
741
  return data
730
742
  if warnings:
@@ -13,6 +13,7 @@ import platform
13
13
  import re
14
14
  import shlex
15
15
  import sys
16
+ import time
16
17
  from pathlib import Path
17
18
  from typing import Any, cast
18
19
  from urllib.parse import urlsplit
@@ -132,6 +133,25 @@ def _nearest_existing(path: Path) -> Path:
132
133
  return path
133
134
 
134
135
 
136
+ #: ``doctor --input '{"wait": N}'``: retry a failing connection for up to N
137
+ #: seconds (capped), probing every ``_WAIT_INTERVAL`` seconds.
138
+ _WAIT_INTERVAL = 15
139
+ _WAIT_MAX = 900
140
+
141
+
142
+ def _wait_seconds(invocation: Invocation) -> float:
143
+ document = invocation.load_input() or {}
144
+ try:
145
+ value = float(document.get("wait") or 0)
146
+ except (TypeError, ValueError):
147
+ raise CliError(
148
+ code="invalid_argument",
149
+ message="wait must be a number of seconds.",
150
+ hint="mammoth doctor --input '{\"wait\": 300}'",
151
+ ) from None
152
+ return max(0.0, min(value, _WAIT_MAX))
153
+
154
+
135
155
  def doctor(invocation: Invocation) -> HandlerResult:
136
156
  """Run environment and connectivity diagnostics.
137
157
 
@@ -241,13 +261,30 @@ def doctor(invocation: Invocation) -> HandlerResult:
241
261
  connection_ok = False
242
262
  connection_detail = "not attempted"
243
263
  projects: list[dict[str, Any]] | None = None
264
+ wait_seconds = _wait_seconds(invocation)
244
265
  if auth_ok:
266
+ started = time.monotonic()
267
+ retries = 0
245
268
  try:
246
- with open_service(invocation) as (service, _auth):
247
- service.check_connection()
248
- projects = _visible_projects(service)
269
+ while True:
270
+ try:
271
+ with open_service(invocation) as (service, _auth):
272
+ service.check_connection()
273
+ projects = _visible_projects(service)
274
+ break
275
+ except CliError as error:
276
+ # A 502/504 or timeout during an outage: with ``wait``,
277
+ # probe again instead of failing on the first try.
278
+ remaining = wait_seconds - (time.monotonic() - started)
279
+ if not error.retryable or remaining <= 0:
280
+ raise
281
+ time.sleep(min(_WAIT_INTERVAL, remaining))
282
+ retries += 1
283
+ waited = time.monotonic() - started
249
284
  connection_ok = True
250
- connection_detail = "authenticated request succeeded"
285
+ connection_detail = "authenticated request succeeded" + (
286
+ f" after {retries} retries over {round(waited)}s" if retries else ""
287
+ )
251
288
  except CliError as error:
252
289
  diagnostics = _safe_connection_diagnostics(error, debug=invocation.debug)
253
290
  connection_detail = diagnostics.pop("detail")
@@ -509,3 +509,80 @@ def project_user_update(invocation: Invocation) -> HandlerResult:
509
509
  with open_service(invocation) as (service, auth):
510
510
  data = service.call(_symbol(invocation), **kwargs)
511
511
  return data, _meta(invocation, auth.workspace_id, project_id)
512
+
513
+
514
+ _DATASETS_LIST_SYMBOL = "mammoth.api.datasets.DatasetsAPI.list_all"
515
+ _DASHBOARDS_LIST_SYMBOL = "mammoth.api.dashboards.DashboardsAPI.list"
516
+
517
+
518
+ def _report_line(where: str, warning: dict[str, Any]) -> str:
519
+ column = warning.get("column")
520
+ subject = f"{where}, column {column}" if column else where
521
+ return f"{subject}: {warning.get('issue')}. {warning.get('detail', '')}".strip()
522
+
523
+
524
+ def project_check(invocation: Invocation) -> HandlerResult:
525
+ """List what a report on this project must still account for.
526
+
527
+ Read-only local composite, run before reporting: for each dataset, the
528
+ first view's ``column_warnings`` and ``before_dashboard``; for each
529
+ dashboard, its ``deliverable_check``. ``to_report`` flattens them into
530
+ one line per finding. Cold-agent evals (2.0.41) left one column's blanks
531
+ undecided in every run, because the warning sat in an earlier result.
532
+ """
533
+ from mammoth_cli.commands.dashboard import _with_deliverable_check
534
+ from mammoth_cli.commands.view import upload_preview
535
+
536
+ project_id = _project_id(invocation)
537
+ views: list[dict[str, Any]] = []
538
+ dashboards: list[dict[str, Any]] = []
539
+ to_report: list[str] = []
540
+ with open_service(invocation) as (service, auth):
541
+ listing = service.call(_DATASETS_LIST_SYMBOL, project_id=project_id)
542
+ datasets = listing.get("datasets", []) if isinstance(listing, dict) else []
543
+ for dataset in datasets:
544
+ dataset_id = dataset.get("id") if isinstance(dataset, dict) else None
545
+ if not isinstance(dataset_id, int):
546
+ continue
547
+ preview = upload_preview(service, dataset_id, project_id)
548
+ if preview is None:
549
+ continue
550
+ entry = {
551
+ "dataset_id": dataset_id,
552
+ "dataset_name": dataset.get("name"),
553
+ "view_id": preview["view_id"],
554
+ "row_count": preview.get("row_count"),
555
+ "column_warnings": preview.get("column_warnings", []),
556
+ }
557
+ if "before_dashboard" in preview:
558
+ entry["before_dashboard"] = preview["before_dashboard"]
559
+ views.append(entry)
560
+ where = f"view {preview['view_id']} ({dataset.get('name')})"
561
+ to_report += [_report_line(where, w) for w in entry["column_warnings"]]
562
+ boards = service.call(_DASHBOARDS_LIST_SYMBOL, project_id=project_id)
563
+ for board in boards if isinstance(boards, list) else []:
564
+ dashboard_id = board.get("id") if isinstance(board, dict) else None
565
+ if not isinstance(dashboard_id, int):
566
+ continue
567
+ checked = _with_deliverable_check(
568
+ invocation, service, auth, {"dashboard_id": dashboard_id}, {"id": dashboard_id}
569
+ )
570
+ check = checked.get("deliverable_check") if isinstance(checked, dict) else None
571
+ warnings = check.get("warnings", []) if isinstance(check, dict) else []
572
+ dashboards.append(
573
+ {"id": dashboard_id, "title": board.get("title"), "warnings": warnings}
574
+ )
575
+ to_report += [_report_line(f"dashboard {dashboard_id}", w) for w in warnings]
576
+ meta = _meta(invocation, auth.workspace_id, project_id)
577
+ return {
578
+ "project_id": project_id,
579
+ "views": views,
580
+ "dashboards": dashboards,
581
+ "to_report": to_report,
582
+ "note": (
583
+ "Before you report: fix each finding, or give it one line in the report "
584
+ "(what you did and why). A finding you do not mention is a miss."
585
+ if to_report
586
+ else "Nothing open in the views or dashboards."
587
+ ),
588
+ }, meta
@@ -205,6 +205,7 @@ HANDLERS: dict[str, Handler] = {
205
205
  # project family (read-only)
206
206
  "project.list": project_cmd.project_list,
207
207
  "project.get": project_cmd.project_get,
208
+ "project.check": project_cmd.project_check,
208
209
  "project.pending-changes": project_cmd.project_pending_changes,
209
210
  "project.resource-status": project_cmd.project_resource_status,
210
211
  "project.resource-dependencies": project_cmd.project_resource_dependencies,
@@ -257,6 +257,7 @@ _PILOT_ADAPTER_INPUTS: dict[str, frozenset[str]] = {
257
257
  # values that may cross the structured-input boundary.
258
258
  _LOCAL_CONTRACT_FIELDS: dict[str, tuple[FieldSpec, ...]] = {
259
259
  "project.ensure": (FieldSpec("name", required=False, annotation=str),),
260
+ "doctor": (FieldSpec("wait", required=False, annotation=int, default=0),),
260
261
  "schema.get": (FieldSpec("full", required=False, annotation=bool, default=False),),
261
262
  "schema.list": (
262
263
  FieldSpec("family", required=False, annotation=str | None, default=None),
@@ -346,6 +347,7 @@ _LOCAL_COMMANDS = frozenset(
346
347
  "context.project.use",
347
348
  "dataset.find",
348
349
  "doctor",
350
+ "project.check",
349
351
  "project.ensure",
350
352
  "folder.find",
351
353
  "log.path",
@@ -279,6 +279,43 @@ def upload_hints(
279
279
  return warnings
280
280
 
281
281
 
282
+ def columns_not_on_dashboard(
283
+ canvas_doc: Any, view_columns: Iterable[Mapping[str, Any]] | None
284
+ ) -> list[dict[str, Any]]:
285
+ """Warn about view columns that the dashboard's profile does not have.
286
+
287
+ A dashboard sees the view as it was when the dashboard was made
288
+ (``NEW_COLUMN_NOTE``), so a column added later cannot be charted there.
289
+ ``view_columns`` is the view's own profile (``profiles_from_view``).
290
+ """
291
+ known = {p["name"] for p in _profiles(canvas_doc)} if isinstance(canvas_doc, Mapping) else set()
292
+ if not known or not view_columns:
293
+ return []
294
+ missing = [
295
+ str(c["name"])
296
+ for c in view_columns
297
+ if isinstance(c.get("name"), str) and c["name"] not in known
298
+ ]
299
+ if not missing:
300
+ return []
301
+ canvas = canvas_doc.get("canvas")
302
+ source = canvas.get("dataset") if isinstance(canvas, Mapping) else None
303
+ view_id = source.get("dataview_id") if isinstance(source, Mapping) else None
304
+ spec = json.dumps({"params": {"dataview_id": view_id if view_id is not None else "VIEW_ID"}})
305
+ return [
306
+ {
307
+ "issue": "columns_not_on_dashboard",
308
+ "columns": missing,
309
+ "detail": (
310
+ f"The view has {', '.join(missing)}, but this dashboard was made before "
311
+ f"and cannot chart {'it' if len(missing) == 1 else 'them'}. Make a new "
312
+ "dashboard on the view and build there."
313
+ ),
314
+ "fix": f"mammoth dashboard create-blank --input '{spec}' --yes",
315
+ }
316
+ ]
317
+
318
+
282
319
  def has_profiles(canvas_doc: Any) -> bool:
283
320
  """Whether a canvas read carries the backend's column profile."""
284
321
  return isinstance(canvas_doc, Mapping) and bool(_profiles(canvas_doc))
@@ -2,6 +2,7 @@
2
2
 
3
3
  from __future__ import annotations
4
4
 
5
+ import re
5
6
  import shlex
6
7
  from typing import Any
7
8
 
@@ -106,6 +107,35 @@ def _job_recovery(job_id: object, *, profile: str | None = None) -> list[str]:
106
107
  ]
107
108
 
108
109
 
110
+ _PROJECT_DELETE = re.compile(r"/workspaces/\d+/projects/(\d+)/?$")
111
+ _DASHBOARD_WRITE = re.compile(r"/dashboards/(\d+)(?:/|$)")
112
+
113
+
114
+ def _resource_recovery(
115
+ method: object, endpoint: object, project_id: object, *, profile: str | None = None
116
+ ) -> list[str]:
117
+ """Reads that settle an unknown outcome for writes with no job handle.
118
+
119
+ Seen on release during an outage: ``dashboard create-blank`` and
120
+ ``project delete`` timed out with nothing to inspect, and agents could
121
+ not tell whether to replay. Each command here answers that question.
122
+ """
123
+ if not isinstance(endpoint, str):
124
+ return []
125
+ options = f"{' --profile ' + shlex.quote(profile) if profile else ''}"
126
+ verb = str(method or "").upper()
127
+ if verb == "DELETE" and (match := _PROJECT_DELETE.search(endpoint)):
128
+ # Deletion is asynchronous (202): read until resource_not_found.
129
+ return [f"mammoth project get {match.group(1)}{options}"]
130
+ if verb == "POST" and endpoint.rstrip("/").endswith("/dashboards/v3/blank"):
131
+ project = f" --project {project_id}" if isinstance(project_id, int) else ""
132
+ # Look for a dashboard with the title you sent before creating another.
133
+ return [f"mammoth dashboard list{project}{options}"]
134
+ if verb in {"POST", "PUT", "PATCH"} and (match := _DASHBOARD_WRITE.search(endpoint)):
135
+ return [f"mammoth dashboard canvas get {match.group(1)}{options}"]
136
+ return []
137
+
138
+
109
139
  def map_sdk_exception(
110
140
  exc: BaseException,
111
141
  *,
@@ -250,6 +280,10 @@ def map_sdk_exception(
250
280
  )
251
281
  )
252
282
  if uncertain_effect:
283
+ if not recovery:
284
+ recovery = _resource_recovery(
285
+ method, details.get("endpoint"), project_id, profile=profile
286
+ )
253
287
  details.setdefault("operation_state", CODE_OUTCOME_UNKNOWN)
254
288
  if method is None:
255
289
  details.setdefault("metadata_missing", ["method", "operation_state"])
@@ -242,6 +242,7 @@ POSITIONAL_OVERRIDES: dict[str, tuple[PositionalSpec, ...]] = {
242
242
  # active project). The SDK signature marks it required or omits it, so the
243
243
  # dual-sourced optional locator is authored here.
244
244
  "project.get": _optional_project_id(),
245
+ "project.check": _optional_project_id(),
245
246
  "project.pending-changes": _optional_project_id(),
246
247
  "project.resource-status": _optional_project_id(),
247
248
  "project.resource-dependencies": _optional_project_id(),
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "mammoth-cli"
3
- version = "2.0.41"
3
+ version = "2.0.43"
4
4
  description = "Command-line interface for the Mammoth Analytics platform"
5
5
  authors = [{name = "Mammoth Analytics", email = "support@mammoth.io"}]
6
6
  readme = "README.md"
@@ -71,6 +71,45 @@ commands:
71
71
  The CLI requires every patches[].value item to name a project_id and the confirmation names
72
72
  those ids; a body that names no project is refused before dispatch. Not verified live.
73
73
  reviewed_by: primary
74
+ - command_id: project.check
75
+ command_path: project check
76
+ disposition: command
77
+ alias_of: null
78
+ operation_ids: []
79
+ positionals:
80
+ - name: project_id
81
+ type: int
82
+ required: false
83
+ metavar: PROJECT_ID
84
+ falls_back_to_field: null
85
+ help: ID of the project to act on; defaults to the active project.
86
+ options: []
87
+ sdk_symbol: mammoth_cli.commands.project.project_check
88
+ sdk_conversion: Call mammoth_cli.commands.project.project_check with validated request fields.
89
+ request_model: ProjectCheckRequest
90
+ result_model: ProjectCheckResult
91
+ mutation_class: read
92
+ confirmation: none
93
+ wait_policy: not_async
94
+ pagination_policy: none
95
+ acceptance_evidence: live_read_only
96
+ live_test: null
97
+ live_exemption_reason: Local composite over already-covered dataset, view and dashboard reads.
98
+ contract_fixture: null
99
+ required_fixture_guard: null
100
+ secret_fields: []
101
+ human_example: mammoth project check --help
102
+ agent_example: mammoth project check 123
103
+ unit_tests:
104
+ - UT-PROJECT-CHECK
105
+ contract_tests:
106
+ - CT-PROJECT-CHECK-HUMAN
107
+ - CT-PROJECT-CHECK-JSON
108
+ - CT-PROJECT-CHECK-ERROR
109
+ draft_test: null
110
+ undo_test: null
111
+ known_restrictions: Reads the first view of each dataset (the one uploads and the playbooks use) and one data page per view.
112
+ reviewed_by: primary
74
113
  - command_id: project.checkpoint.list
75
114
  command_path: project checkpoint list
76
115
  disposition: command
File without changes
File without changes
File without changes