mammoth-cli 2.0.42__tar.gz → 2.0.44__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 (226) hide show
  1. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/PKG-INFO +1 -1
  2. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/__init__.py +1 -1
  3. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/app.py +2 -2
  4. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/bundled_skill/mammoth-cli/SKILL.md +8 -2
  5. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/bundled_skill/mammoth-cli/references/capabilities.md +1 -1
  6. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/bundled_skill/mammoth-cli/references/command-index.md +2 -2
  7. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/project.md +10 -0
  8. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/bundled_skill/mammoth-cli/references/recipes/dashboards.md +2 -1
  9. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/bundled_skill/mammoth-cli/references/recovery.md +1 -1
  10. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/bundled_skill/mammoth-cli/references/report-checklist.md +1 -1
  11. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/commands/dashboard.py +16 -4
  12. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/commands/doctor.py +41 -4
  13. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/commands/project.py +77 -0
  14. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/commands/registry.py +1 -0
  15. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/context/resolver.py +13 -1
  16. mammoth_cli-2.0.44/mammoth_cli/embed.py +99 -0
  17. mammoth_cli-2.0.44/mammoth_cli/runtime/embedded.py +56 -0
  18. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/runtime/executor.py +7 -2
  19. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/runtime/session.py +5 -0
  20. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/runtime/updates.py +3 -2
  21. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/services/command_contract.py +2 -0
  22. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/services/dashboard_review.py +37 -0
  23. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/services/mapping.py +34 -0
  24. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/services/positionals.py +1 -0
  25. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/services/sdk_service.py +4 -0
  26. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/pyproject.toml +1 -1
  27. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/spec/manifests/commands/project.yaml +39 -0
  28. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/.gitignore +0 -0
  29. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/LICENSE +0 -0
  30. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/README.md +0 -0
  31. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/__main__.py +0 -0
  32. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/bundled_skill/mammoth-cli/references/about-mammoth.md +0 -0
  33. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/bundled_skill/mammoth-cli/references/auth.md +0 -0
  34. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/bundled_skill/mammoth-cli/references/capabilities-misc.md +0 -0
  35. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/activity.md +0 -0
  36. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/addon.md +0 -0
  37. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/agent.md +0 -0
  38. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/ai.md +0 -0
  39. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/annotation.md +0 -0
  40. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/auth.md +0 -0
  41. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/automation.md +0 -0
  42. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/batch.md +0 -0
  43. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/billing.md +0 -0
  44. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/browse.md +0 -0
  45. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/capability.md +0 -0
  46. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/client-app.md +0 -0
  47. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/completion.md +0 -0
  48. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/config.md +0 -0
  49. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/connector.md +0 -0
  50. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/context.md +0 -0
  51. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/dashboard.md +0 -0
  52. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/data-app.md +0 -0
  53. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/dataset.md +0 -0
  54. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/doctor.md +0 -0
  55. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/external-key.md +0 -0
  56. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/file.md +0 -0
  57. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/folder.md +0 -0
  58. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/job.md +0 -0
  59. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/log.md +0 -0
  60. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/notification.md +0 -0
  61. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/parameter.md +0 -0
  62. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/report.md +0 -0
  63. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/schedule.md +0 -0
  64. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/schema.md +0 -0
  65. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/skill.md +0 -0
  66. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/snippet.md +0 -0
  67. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/support.md +0 -0
  68. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/template.md +0 -0
  69. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/trash.md +0 -0
  70. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/upgrade.md +0 -0
  71. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/user.md +0 -0
  72. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/version.md +0 -0
  73. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/view.md +0 -0
  74. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/webhook.md +0 -0
  75. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/workflow.md +0 -0
  76. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/workspace.md +0 -0
  77. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/bundled_skill/mammoth-cli/references/handoff.md +0 -0
  78. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/bundled_skill/mammoth-cli/references/input.md +0 -0
  79. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/bundled_skill/mammoth-cli/references/jobs-drafts.md +0 -0
  80. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/bundled_skill/mammoth-cli/references/machine-output.md +0 -0
  81. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/bundled_skill/mammoth-cli/references/operations.md +0 -0
  82. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/bundled_skill/mammoth-cli/references/recipes/auth-scope.md +0 -0
  83. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/bundled_skill/mammoth-cli/references/recipes/cleanup.md +0 -0
  84. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/bundled_skill/mammoth-cli/references/recipes/end-to-end.md +0 -0
  85. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/bundled_skill/mammoth-cli/references/recipes/exports.md +0 -0
  86. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/bundled_skill/mammoth-cli/references/recipes/index.md +0 -0
  87. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/bundled_skill/mammoth-cli/references/recipes/need-action.md +0 -0
  88. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/bundled_skill/mammoth-cli/references/recipes/resources.md +0 -0
  89. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/bundled_skill/mammoth-cli/references/recipes/transforms.md +0 -0
  90. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/bundled_skill/mammoth-cli/references/recipes/typed-etl-discovery.md +0 -0
  91. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/bundled_skill/mammoth-cli/references/retention.md +0 -0
  92. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/bundled_skill/mammoth-cli/references/safety.md +0 -0
  93. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/bundled_skill/mammoth-cli/references/task-start.md +0 -0
  94. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/commands/__init__.py +0 -0
  95. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/commands/activity.py +0 -0
  96. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/commands/addon.py +0 -0
  97. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/commands/agent.py +0 -0
  98. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/commands/ai.py +0 -0
  99. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/commands/annotation.py +0 -0
  100. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/commands/auth.py +0 -0
  101. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/commands/automation.py +0 -0
  102. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/commands/batch.py +0 -0
  103. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/commands/billing.py +0 -0
  104. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/commands/browse.py +0 -0
  105. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/commands/capability.py +0 -0
  106. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/commands/client_app.py +0 -0
  107. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/commands/completion.py +0 -0
  108. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/commands/config.py +0 -0
  109. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/commands/connector.py +0 -0
  110. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/commands/context.py +0 -0
  111. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/commands/data_app.py +0 -0
  112. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/commands/dataset.py +0 -0
  113. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/commands/external_key.py +0 -0
  114. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/commands/file.py +0 -0
  115. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/commands/folder.py +0 -0
  116. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/commands/job.py +0 -0
  117. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/commands/notification.py +0 -0
  118. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/commands/parameter.py +0 -0
  119. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/commands/report.py +0 -0
  120. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/commands/schedule.py +0 -0
  121. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/commands/schema.py +0 -0
  122. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/commands/skill.py +0 -0
  123. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/commands/snippet.py +0 -0
  124. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/commands/support.py +0 -0
  125. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/commands/template.py +0 -0
  126. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/commands/trash.py +0 -0
  127. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/commands/upgrade.py +0 -0
  128. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/commands/user.py +0 -0
  129. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/commands/view.py +0 -0
  130. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/commands/view_ops.py +0 -0
  131. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/commands/webhook.py +0 -0
  132. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/commands/workflow.py +0 -0
  133. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/commands/workspace.py +0 -0
  134. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/context/__init__.py +0 -0
  135. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/context/credentials.py +0 -0
  136. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/context/endpoint.py +0 -0
  137. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/context/profiles.py +0 -0
  138. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/contracts/__init__.py +0 -0
  139. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/contracts/auth.py +0 -0
  140. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/errors/__init__.py +0 -0
  141. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/errors/envelope.py +0 -0
  142. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/manifest/__init__.py +0 -0
  143. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/manifest/loader.py +0 -0
  144. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/messages/__init__.py +0 -0
  145. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/output/__init__.py +0 -0
  146. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/output/envelope.py +0 -0
  147. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/output/normalize.py +0 -0
  148. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/output/policy.py +0 -0
  149. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/output/progress.py +0 -0
  150. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/output/render.py +0 -0
  151. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/py.typed +0 -0
  152. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/runtime/__init__.py +0 -0
  153. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/runtime/confirm.py +0 -0
  154. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/runtime/dryrun.py +0 -0
  155. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/runtime/input_loader.py +0 -0
  156. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/runtime/invocation.py +0 -0
  157. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/runtime/options.py +0 -0
  158. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/runtime/parents.py +0 -0
  159. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/runtime/runlog.py +0 -0
  160. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/runtime/strict.py +0 -0
  161. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/runtime/validate.py +0 -0
  162. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/services/__init__.py +0 -0
  163. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/services/argspec.py +0 -0
  164. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/services/coerce.py +0 -0
  165. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/services/conditions.py +0 -0
  166. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/services/dashboard_pages.py +0 -0
  167. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/services/data_quality.py +0 -0
  168. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/services/dispatch.py +0 -0
  169. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/services/factory.py +0 -0
  170. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/services/input_fields.py +0 -0
  171. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/services/openapi_types.py +0 -0
  172. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/services/protocol.py +0 -0
  173. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/services/testing.py +0 -0
  174. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/services/type_system.py +0 -0
  175. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/skills/__init__.py +0 -0
  176. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/skills/installer.py +0 -0
  177. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/skills/steering.py +0 -0
  178. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/testing.py +0 -0
  179. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/spec/manifests/commands/activity.yaml +0 -0
  180. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/spec/manifests/commands/addon.yaml +0 -0
  181. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/spec/manifests/commands/agent.yaml +0 -0
  182. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/spec/manifests/commands/ai.yaml +0 -0
  183. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/spec/manifests/commands/annotation.yaml +0 -0
  184. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/spec/manifests/commands/auth.yaml +0 -0
  185. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/spec/manifests/commands/automation.yaml +0 -0
  186. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/spec/manifests/commands/batch.yaml +0 -0
  187. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/spec/manifests/commands/billing.yaml +0 -0
  188. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/spec/manifests/commands/browse.yaml +0 -0
  189. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/spec/manifests/commands/capability.yaml +0 -0
  190. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/spec/manifests/commands/client-app.yaml +0 -0
  191. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/spec/manifests/commands/completion.yaml +0 -0
  192. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/spec/manifests/commands/config.yaml +0 -0
  193. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/spec/manifests/commands/connector.yaml +0 -0
  194. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/spec/manifests/commands/context.yaml +0 -0
  195. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/spec/manifests/commands/dashboard.yaml +0 -0
  196. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/spec/manifests/commands/data-app.yaml +0 -0
  197. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/spec/manifests/commands/dataset.yaml +0 -0
  198. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/spec/manifests/commands/doctor.yaml +0 -0
  199. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/spec/manifests/commands/external-key.yaml +0 -0
  200. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/spec/manifests/commands/file.yaml +0 -0
  201. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/spec/manifests/commands/folder.yaml +0 -0
  202. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/spec/manifests/commands/job.yaml +0 -0
  203. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/spec/manifests/commands/log.yaml +0 -0
  204. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/spec/manifests/commands/notification.yaml +0 -0
  205. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/spec/manifests/commands/parameter.yaml +0 -0
  206. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/spec/manifests/commands/report.yaml +0 -0
  207. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/spec/manifests/commands/schedule.yaml +0 -0
  208. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/spec/manifests/commands/schema.yaml +0 -0
  209. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/spec/manifests/commands/skill.yaml +0 -0
  210. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/spec/manifests/commands/snippet.yaml +0 -0
  211. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/spec/manifests/commands/support.yaml +0 -0
  212. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/spec/manifests/commands/template.yaml +0 -0
  213. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/spec/manifests/commands/trash.yaml +0 -0
  214. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/spec/manifests/commands/upgrade.yaml +0 -0
  215. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/spec/manifests/commands/user.yaml +0 -0
  216. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/spec/manifests/commands/version.yaml +0 -0
  217. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/spec/manifests/commands/view.yaml +0 -0
  218. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/spec/manifests/commands/webhook.yaml +0 -0
  219. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/spec/manifests/commands/workflow.yaml +0 -0
  220. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/spec/manifests/commands/workspace.yaml +0 -0
  221. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/spec/manifests/openapi-operations.yaml +0 -0
  222. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/spec/manifests/schema-v1.json +0 -0
  223. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/spec/manifests/sdk-catalog.source.yaml +0 -0
  224. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/spec/manifests/sdk-methods.yaml +0 -0
  225. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/spec/openapi/metadata.json +0 -0
  226. {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/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.42
3
+ Version: 2.0.44
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.42"
9
+ __version__ = "2.0.44"
10
10
 
11
11
  # The versioned machine output envelope contract.
12
12
  SCHEMA_VERSION = 1
@@ -384,7 +384,7 @@ class _EnvelopeGroup(TyperGroup):
384
384
  argv = kwargs.get("args")
385
385
  if argv is None:
386
386
  argv = args[0] if args else None
387
- self._render_usage_error(error, argv)
387
+ self.render_usage_error(error, argv)
388
388
  raise SystemExit(getattr(error, "exit_code", EXIT_USAGE)) from None
389
389
  except _ABORT_ERRORS:
390
390
  typer.echo("Aborted!", err=True)
@@ -395,7 +395,7 @@ class _EnvelopeGroup(TyperGroup):
395
395
  # in-process test runner observe the exit status as before.
396
396
  raise SystemExit(result if isinstance(result, int) else 0)
397
397
 
398
- def _render_usage_error(self, error: Any, argv: Sequence[str] | None) -> None:
398
+ def render_usage_error(self, error: Any, argv: Sequence[str] | None) -> None:
399
399
  """Emit a usage error as the JSON envelope (machine) or Click prose (human).
400
400
 
401
401
  A *missing required argument* is reported with the stable
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: mammoth-cli
3
- version: 2.0.42
3
+ version: 2.0.44
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
@@ -173,6 +175,10 @@ your report. If no column links the files, ask before you combine them.
173
175
  "limit": 50}`.
174
176
  - A timeout, exit 7 or interruption does not prove failure; reconcile an
175
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.
176
182
  - Run the [report checklist](references/report-checklist.md) before stating
177
183
  a number or calling a step done. When files here disagree,
178
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,7 +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 (from the upload, a data read or `deliverable_check`), in every view: the column, the count, and filled, filtered, or kept and why. Kept is a decision only when you write it down |
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 |
12
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 |
13
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) |
14
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,
@@ -12,6 +12,7 @@ overrides no project at all.
12
12
 
13
13
  from __future__ import annotations
14
14
 
15
+ from collections.abc import Mapping
15
16
  from dataclasses import dataclass
16
17
 
17
18
  from mammoth_cli.context import credentials, profiles
@@ -23,6 +24,7 @@ from mammoth_cli.errors.envelope import (
23
24
  EXIT_USAGE,
24
25
  CliError,
25
26
  )
27
+ from mammoth_cli.runtime import embedded
26
28
  from mammoth_cli.runtime.invocation import Invocation
27
29
 
28
30
 
@@ -39,6 +41,9 @@ class ExplicitLogin:
39
41
  workspace_id: The Mammoth workspace id.
40
42
  server_prefix: A one-label server prefix, or None.
41
43
  api_token: The ``mm_...`` Bearer token, instead of a key + secret.
44
+ headers: Extra request headers sent on every API call, after the
45
+ credential headers so they override them. Set only by an
46
+ embedding host that forwards its caller's session.
42
47
  """
43
48
 
44
49
  api_key: str | None
@@ -46,6 +51,7 @@ class ExplicitLogin:
46
51
  workspace_id: int
47
52
  server_prefix: str | None = None
48
53
  api_token: str | None = None
54
+ headers: Mapping[str, str] | None = None
49
55
 
50
56
 
51
57
  @dataclass(frozen=True)
@@ -58,6 +64,7 @@ class ResolvedAuth:
58
64
  workspace_id: The Mammoth workspace id.
59
65
  base_url: The resolved API base url.
60
66
  api_token: The ``mm_...`` Bearer token, or None with a key + secret.
67
+ headers: Extra request headers from an embedding host, or None.
61
68
  """
62
69
 
63
70
  api_key: str | None
@@ -65,6 +72,7 @@ class ResolvedAuth:
65
72
  workspace_id: int
66
73
  base_url: str
67
74
  api_token: str | None = None
75
+ headers: Mapping[str, str] | None = None
68
76
 
69
77
 
70
78
  def not_authenticated_error() -> CliError:
@@ -110,7 +118,8 @@ def resolve_auth(
110
118
  """Resolve credentials, workspace id, and base url for one invocation.
111
119
 
112
120
  Credentials come from an explicit login (a secure prompt or ``--input``
113
- document handed to :func:`resolve_auth` by ``auth login``), otherwise from
121
+ document handed to :func:`resolve_auth` by ``auth login``, or the login of
122
+ the current embedded call, :mod:`mammoth_cli.runtime.embedded`), otherwise from
114
123
  the selected or ``--profile`` saved profile. There is no environment
115
124
  credential path; ``mammoth auth login`` is the only way to authenticate.
116
125
 
@@ -126,6 +135,8 @@ def resolve_auth(
126
135
  ``invalid_workspace_id`` when the resolved workspace id is not a
127
136
  positive integer; endpoint errors from :func:`resolve_base_url`.
128
137
  """
138
+ if explicit_login is None and (call := embedded.current()) is not None:
139
+ explicit_login = call.login
129
140
  if explicit_login is not None:
130
141
  base_url = _endpoint(explicit_login.server_prefix)
131
142
  return ResolvedAuth(
@@ -134,6 +145,7 @@ def resolve_auth(
134
145
  workspace_id=_require_positive_workspace(explicit_login.workspace_id, source="login"),
135
146
  base_url=base_url,
136
147
  api_token=explicit_login.api_token,
148
+ headers=explicit_login.headers,
137
149
  )
138
150
 
139
151
  profile_name = invocation.profile or profiles.get_selected()
@@ -0,0 +1,99 @@
1
+ """Run one CLI command in-process and return its envelope.
2
+
3
+ For a host (for example a server-side agent) that runs commands for its own
4
+ signed-in users. Each call carries its own login, is forced to machine output
5
+ and no prompts, writes nothing to stdout or stderr, and returns the success or
6
+ error envelope as a dict. Calls are safe to run concurrently in threads: the
7
+ login and the captured envelope live in a context variable
8
+ (:mod:`mammoth_cli.runtime.embedded`), and the update check, the run log and
9
+ saved profiles are not used.
10
+
11
+ Example::
12
+
13
+ from mammoth_cli.context.resolver import ExplicitLogin
14
+ from mammoth_cli.embed import invoke
15
+
16
+ login = ExplicitLogin(
17
+ api_key=None, api_secret=None, workspace_id=7, api_token="...",
18
+ server_prefix="app", headers={"Cookie": "..."},
19
+ )
20
+ envelope = invoke(["project", "list"], login=login)
21
+ """
22
+
23
+ from __future__ import annotations
24
+
25
+ from collections.abc import Sequence
26
+ from typing import Any
27
+
28
+ from mammoth_cli.app import _ABORT_ERRORS, _USAGE_ERRORS, _root_click_command
29
+ from mammoth_cli.context.resolver import ExplicitLogin
30
+ from mammoth_cli.errors.envelope import EXIT_API, EXIT_INTERRUPT, EXIT_USAGE, CliError
31
+ from mammoth_cli.runtime import embedded
32
+
33
+
34
+ def invoke(
35
+ args: Sequence[str],
36
+ *,
37
+ login: ExplicitLogin,
38
+ project_id: int | None = None,
39
+ timeout: float | None = None,
40
+ ) -> dict[str, Any]:
41
+ """Run ``mammoth <args>`` as ``login`` and return its envelope.
42
+
43
+ Args:
44
+ args: The command line after ``mammoth``, for example
45
+ ``["view", "data", "get", "12"]``.
46
+ login: The credentials, endpoint and extra headers for this call.
47
+ project_id: The active project, sent as ``--project`` unless ``args``
48
+ already names one.
49
+ timeout: Per-request timeout in seconds, sent as ``--timeout`` unless
50
+ ``args`` already sets one.
51
+
52
+ Returns:
53
+ The success envelope (``data`` + ``meta``) or the error envelope
54
+ (``error``). A CLI error is returned, never raised.
55
+ """
56
+ argv = _argv(args, project_id=project_id, timeout=timeout)
57
+ call = embedded.EmbeddedCall(login=login)
58
+ token = embedded.enter(call)
59
+ try:
60
+ _run(argv)
61
+ finally:
62
+ embedded.leave(token)
63
+ if call.envelopes:
64
+ return call.envelopes[-1]
65
+ return _error("no_output", "This command printed text only (help or version).", EXIT_USAGE)
66
+
67
+
68
+ def _argv(args: Sequence[str], *, project_id: int | None, timeout: float | None) -> list[str]:
69
+ """``args`` plus the options an embedded call always runs with."""
70
+ argv = list(args)
71
+ if project_id is not None and not _has_option(argv, "--project"):
72
+ argv += ["--project", str(project_id)]
73
+ if timeout is not None and not _has_option(argv, "--timeout"):
74
+ argv += ["--timeout", str(timeout)]
75
+ # Last, so they win over any output or input option in ``args``.
76
+ return [*argv, "--output", "json", "--no-input"]
77
+
78
+
79
+ def _has_option(argv: Sequence[str], name: str) -> bool:
80
+ return any(token == name or token.startswith(f"{name}=") for token in argv)
81
+
82
+
83
+ def _run(argv: list[str]) -> None:
84
+ """Run the command; every outcome ends as a captured envelope."""
85
+ root = _root_click_command()
86
+ try:
87
+ root.main(args=argv, prog_name="mammoth", standalone_mode=False)
88
+ except _USAGE_ERRORS as error:
89
+ root.render_usage_error(error, argv)
90
+ except _ABORT_ERRORS:
91
+ embedded.capture(_error("aborted", "The command was aborted.", EXIT_INTERRUPT))
92
+ except SystemExit:
93
+ return
94
+ except Exception as exc: # noqa: BLE001 -- the host gets an envelope, never a traceback
95
+ embedded.capture(_error("internal_error", f"{type(exc).__name__}: {exc}", EXIT_API))
96
+
97
+
98
+ def _error(code: str, message: str, exit_status: int) -> dict[str, Any]:
99
+ return CliError(code=code, message=message, exit_status=exit_status).to_envelope()
@@ -0,0 +1,56 @@
1
+ """Per-call state for an in-process (embedded) invocation.
2
+
3
+ :func:`mammoth_cli.embed.invoke` runs a command inside a host process that may
4
+ run several commands at once, each for a different user. The login and the
5
+ captured envelope therefore live in a :class:`contextvars.ContextVar`, never in
6
+ ``os.environ`` or a profile file: each thread (or task) sees only its own.
7
+ """
8
+
9
+ from __future__ import annotations
10
+
11
+ from contextvars import ContextVar
12
+ from dataclasses import dataclass, field
13
+ from typing import TYPE_CHECKING, Any
14
+
15
+ if TYPE_CHECKING:
16
+ from mammoth_cli.context.resolver import ExplicitLogin
17
+
18
+
19
+ @dataclass
20
+ class EmbeddedCall:
21
+ """The login for one embedded call and the envelope it produced."""
22
+
23
+ login: ExplicitLogin
24
+ envelopes: list[dict[str, Any]] = field(default_factory=list)
25
+
26
+
27
+ _CURRENT: ContextVar[EmbeddedCall | None] = ContextVar("mammoth_cli_embedded", default=None)
28
+
29
+
30
+ def current() -> EmbeddedCall | None:
31
+ """The embedded call running in this context, or None for a normal CLI run."""
32
+ return _CURRENT.get()
33
+
34
+
35
+ def active() -> bool:
36
+ """Whether this context runs an embedded call."""
37
+ return _CURRENT.get() is not None
38
+
39
+
40
+ def capture(envelope: dict[str, Any]) -> bool:
41
+ """Keep ``envelope`` for the embedded caller; False when not embedded."""
42
+ call = _CURRENT.get()
43
+ if call is None:
44
+ return False
45
+ call.envelopes.append(envelope)
46
+ return True
47
+
48
+
49
+ def enter(call: EmbeddedCall) -> Any:
50
+ """Make ``call`` current; returns the token for :func:`leave`."""
51
+ return _CURRENT.set(call)
52
+
53
+
54
+ def leave(token: Any) -> None:
55
+ """Restore the context that was current before :func:`enter`."""
56
+ _CURRENT.reset(token)
@@ -18,9 +18,10 @@ import typer
18
18
 
19
19
  from mammoth_cli.errors.envelope import EXIT_USAGE, CliError
20
20
  from mammoth_cli.output.envelope import Meta, Result
21
+ from mammoth_cli.output.normalize import normalize
21
22
  from mammoth_cli.output.policy import MACHINE_OUTPUTS, VALID_OUTPUTS
22
23
  from mammoth_cli.output.render import render
23
- from mammoth_cli.runtime import updates
24
+ from mammoth_cli.runtime import embedded, updates
24
25
  from mammoth_cli.runtime.invocation import Invocation
25
26
  from mammoth_cli.runtime.runlog import RunLog
26
27
  from mammoth_cli.services.mapping import map_sdk_exception
@@ -98,6 +99,8 @@ def emit_success(
98
99
  update_available=update_available,
99
100
  )
100
101
  envelope = Result(data=data, meta=meta).to_envelope()
102
+ if embedded.capture(normalize(envelope)):
103
+ return
101
104
  render(envelope, output=output)
102
105
 
103
106
 
@@ -113,6 +116,8 @@ def emit_error(error: CliError, *, machine: bool, output: str = "json") -> None:
113
116
  output: The selected machine mode. Only ``ndjson`` selects lifecycle
114
117
  framing; all other machine errors retain the JSON envelope.
115
118
  """
119
+ if embedded.capture(normalize(error.to_envelope())):
120
+ return
116
121
  if machine:
117
122
  render(
118
123
  error.to_envelope(),
@@ -237,7 +242,7 @@ def _sync_skill_installs(command_id: str, output: str) -> None:
237
242
 
238
243
  def _open_run_log(command_id: str, invocation: Invocation | None) -> RunLog | None:
239
244
  """Open the run log for ``invocation``; never let logging break a command."""
240
- if invocation is None:
245
+ if invocation is None or embedded.active():
241
246
  return None
242
247
  try:
243
248
  return RunLog.start(
@@ -21,6 +21,7 @@ from mammoth_cli.context.resolver import ResolvedAuth, resolve_auth, resolve_pro
21
21
  from mammoth_cli.errors.envelope import missing_project_error
22
22
  from mammoth_cli.manifest.loader import command_by_id
23
23
  from mammoth_cli.output.policy import resolve_policy
24
+ from mammoth_cli.runtime import embedded
24
25
  from mammoth_cli.runtime.invocation import Invocation
25
26
  from mammoth_cli.services import factory
26
27
  from mammoth_cli.services.protocol import MammothService
@@ -101,6 +102,10 @@ def resolved_project(invocation: Invocation) -> int | None:
101
102
  Returns:
102
103
  The resolved project id, or None when none is set.
103
104
  """
105
+ if embedded.active():
106
+ # An embedded call has no profile: the host's saved profiles belong to
107
+ # the host's OS user, not to the user the call runs for.
108
+ return invocation.project
104
109
  profile_name = invocation.profile or profiles.get_selected()
105
110
  return resolve_project(invocation, profiles.get_profile(profile_name))
106
111
 
@@ -33,6 +33,7 @@ from typing import Any
33
33
  import platformdirs
34
34
 
35
35
  from mammoth_cli import __version__
36
+ from mammoth_cli.runtime import embedded
36
37
 
37
38
  DISABLE_ENV = "MAMMOTH_NO_UPDATE_CHECK"
38
39
  AUTO_UPGRADE_ENV = "MAMMOTH_AUTO_UPGRADE"
@@ -60,8 +61,8 @@ def _flag(name: str) -> bool:
60
61
 
61
62
 
62
63
  def enabled() -> bool:
63
- """Whether the check runs at all (``MAMMOTH_NO_UPDATE_CHECK`` unset)."""
64
- return not _flag(DISABLE_ENV)
64
+ """Whether the check runs at all (``MAMMOTH_NO_UPDATE_CHECK`` unset, not embedded)."""
65
+ return not _flag(DISABLE_ENV) and not embedded.active()
65
66
 
66
67
 
67
68
  def auto_upgrade_enabled() -> bool: