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.
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/PKG-INFO +1 -1
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/__init__.py +1 -1
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/app.py +2 -2
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/bundled_skill/mammoth-cli/SKILL.md +8 -2
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/bundled_skill/mammoth-cli/references/capabilities.md +1 -1
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/bundled_skill/mammoth-cli/references/command-index.md +2 -2
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/project.md +10 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/bundled_skill/mammoth-cli/references/recipes/dashboards.md +2 -1
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/bundled_skill/mammoth-cli/references/recovery.md +1 -1
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/bundled_skill/mammoth-cli/references/report-checklist.md +1 -1
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/commands/dashboard.py +16 -4
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/commands/doctor.py +41 -4
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/commands/project.py +77 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/commands/registry.py +1 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/context/resolver.py +13 -1
- mammoth_cli-2.0.44/mammoth_cli/embed.py +99 -0
- mammoth_cli-2.0.44/mammoth_cli/runtime/embedded.py +56 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/runtime/executor.py +7 -2
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/runtime/session.py +5 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/runtime/updates.py +3 -2
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/services/command_contract.py +2 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/services/dashboard_review.py +37 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/services/mapping.py +34 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/services/positionals.py +1 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/services/sdk_service.py +4 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/pyproject.toml +1 -1
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/spec/manifests/commands/project.yaml +39 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/.gitignore +0 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/LICENSE +0 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/README.md +0 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/__main__.py +0 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/bundled_skill/mammoth-cli/references/about-mammoth.md +0 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/bundled_skill/mammoth-cli/references/auth.md +0 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/bundled_skill/mammoth-cli/references/capabilities-misc.md +0 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/activity.md +0 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/addon.md +0 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/agent.md +0 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/ai.md +0 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/annotation.md +0 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/auth.md +0 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/automation.md +0 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/batch.md +0 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/billing.md +0 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/browse.md +0 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/capability.md +0 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/client-app.md +0 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/completion.md +0 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/config.md +0 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/connector.md +0 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/context.md +0 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/dashboard.md +0 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/data-app.md +0 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/dataset.md +0 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/doctor.md +0 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/external-key.md +0 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/file.md +0 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/folder.md +0 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/job.md +0 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/log.md +0 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/notification.md +0 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/parameter.md +0 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/report.md +0 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/schedule.md +0 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/schema.md +0 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/skill.md +0 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/snippet.md +0 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/support.md +0 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/template.md +0 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/trash.md +0 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/upgrade.md +0 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/user.md +0 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/version.md +0 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/view.md +0 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/webhook.md +0 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/workflow.md +0 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/bundled_skill/mammoth-cli/references/commands/workspace.md +0 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/bundled_skill/mammoth-cli/references/handoff.md +0 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/bundled_skill/mammoth-cli/references/input.md +0 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/bundled_skill/mammoth-cli/references/jobs-drafts.md +0 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/bundled_skill/mammoth-cli/references/machine-output.md +0 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/bundled_skill/mammoth-cli/references/operations.md +0 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/bundled_skill/mammoth-cli/references/recipes/auth-scope.md +0 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/bundled_skill/mammoth-cli/references/recipes/cleanup.md +0 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/bundled_skill/mammoth-cli/references/recipes/end-to-end.md +0 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/bundled_skill/mammoth-cli/references/recipes/exports.md +0 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/bundled_skill/mammoth-cli/references/recipes/index.md +0 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/bundled_skill/mammoth-cli/references/recipes/need-action.md +0 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/bundled_skill/mammoth-cli/references/recipes/resources.md +0 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/bundled_skill/mammoth-cli/references/recipes/transforms.md +0 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/bundled_skill/mammoth-cli/references/recipes/typed-etl-discovery.md +0 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/bundled_skill/mammoth-cli/references/retention.md +0 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/bundled_skill/mammoth-cli/references/safety.md +0 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/bundled_skill/mammoth-cli/references/task-start.md +0 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/commands/__init__.py +0 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/commands/activity.py +0 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/commands/addon.py +0 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/commands/agent.py +0 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/commands/ai.py +0 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/commands/annotation.py +0 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/commands/auth.py +0 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/commands/automation.py +0 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/commands/batch.py +0 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/commands/billing.py +0 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/commands/browse.py +0 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/commands/capability.py +0 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/commands/client_app.py +0 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/commands/completion.py +0 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/commands/config.py +0 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/commands/connector.py +0 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/commands/context.py +0 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/commands/data_app.py +0 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/commands/dataset.py +0 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/commands/external_key.py +0 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/commands/file.py +0 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/commands/folder.py +0 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/commands/job.py +0 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/commands/notification.py +0 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/commands/parameter.py +0 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/commands/report.py +0 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/commands/schedule.py +0 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/commands/schema.py +0 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/commands/skill.py +0 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/commands/snippet.py +0 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/commands/support.py +0 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/commands/template.py +0 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/commands/trash.py +0 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/commands/upgrade.py +0 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/commands/user.py +0 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/commands/view.py +0 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/commands/view_ops.py +0 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/commands/webhook.py +0 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/commands/workflow.py +0 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/commands/workspace.py +0 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/context/__init__.py +0 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/context/credentials.py +0 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/context/endpoint.py +0 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/context/profiles.py +0 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/contracts/__init__.py +0 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/contracts/auth.py +0 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/errors/__init__.py +0 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/errors/envelope.py +0 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/manifest/__init__.py +0 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/manifest/loader.py +0 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/messages/__init__.py +0 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/output/__init__.py +0 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/output/envelope.py +0 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/output/normalize.py +0 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/output/policy.py +0 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/output/progress.py +0 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/output/render.py +0 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/py.typed +0 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/runtime/__init__.py +0 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/runtime/confirm.py +0 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/runtime/dryrun.py +0 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/runtime/input_loader.py +0 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/runtime/invocation.py +0 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/runtime/options.py +0 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/runtime/parents.py +0 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/runtime/runlog.py +0 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/runtime/strict.py +0 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/runtime/validate.py +0 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/services/__init__.py +0 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/services/argspec.py +0 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/services/coerce.py +0 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/services/conditions.py +0 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/services/dashboard_pages.py +0 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/services/data_quality.py +0 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/services/dispatch.py +0 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/services/factory.py +0 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/services/input_fields.py +0 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/services/openapi_types.py +0 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/services/protocol.py +0 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/services/testing.py +0 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/services/type_system.py +0 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/skills/__init__.py +0 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/skills/installer.py +0 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/skills/steering.py +0 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/mammoth_cli/testing.py +0 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/spec/manifests/commands/activity.yaml +0 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/spec/manifests/commands/addon.yaml +0 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/spec/manifests/commands/agent.yaml +0 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/spec/manifests/commands/ai.yaml +0 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/spec/manifests/commands/annotation.yaml +0 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/spec/manifests/commands/auth.yaml +0 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/spec/manifests/commands/automation.yaml +0 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/spec/manifests/commands/batch.yaml +0 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/spec/manifests/commands/billing.yaml +0 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/spec/manifests/commands/browse.yaml +0 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/spec/manifests/commands/capability.yaml +0 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/spec/manifests/commands/client-app.yaml +0 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/spec/manifests/commands/completion.yaml +0 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/spec/manifests/commands/config.yaml +0 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/spec/manifests/commands/connector.yaml +0 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/spec/manifests/commands/context.yaml +0 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/spec/manifests/commands/dashboard.yaml +0 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/spec/manifests/commands/data-app.yaml +0 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/spec/manifests/commands/dataset.yaml +0 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/spec/manifests/commands/doctor.yaml +0 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/spec/manifests/commands/external-key.yaml +0 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/spec/manifests/commands/file.yaml +0 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/spec/manifests/commands/folder.yaml +0 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/spec/manifests/commands/job.yaml +0 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/spec/manifests/commands/log.yaml +0 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/spec/manifests/commands/notification.yaml +0 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/spec/manifests/commands/parameter.yaml +0 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/spec/manifests/commands/report.yaml +0 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/spec/manifests/commands/schedule.yaml +0 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/spec/manifests/commands/schema.yaml +0 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/spec/manifests/commands/skill.yaml +0 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/spec/manifests/commands/snippet.yaml +0 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/spec/manifests/commands/support.yaml +0 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/spec/manifests/commands/template.yaml +0 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/spec/manifests/commands/trash.yaml +0 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/spec/manifests/commands/upgrade.yaml +0 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/spec/manifests/commands/user.yaml +0 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/spec/manifests/commands/version.yaml +0 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/spec/manifests/commands/view.yaml +0 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/spec/manifests/commands/webhook.yaml +0 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/spec/manifests/commands/workflow.yaml +0 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/spec/manifests/commands/workspace.yaml +0 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/spec/manifests/openapi-operations.yaml +0 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/spec/manifests/schema-v1.json +0 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/spec/manifests/sdk-catalog.source.yaml +0 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/spec/manifests/sdk-methods.yaml +0 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/spec/openapi/metadata.json +0 -0
- {mammoth_cli-2.0.42 → mammoth_cli-2.0.44}/spec/openapi/openapi.json +0 -0
|
@@ -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.
|
|
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
|
|
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.
|
|
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.
|
|
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
|
|
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
|
|
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) —
|
|
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
|
-
|
|
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`
|
|
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 (
|
|
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
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
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
|
-
|
|
247
|
-
|
|
248
|
-
|
|
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
|
|
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:
|