mostlyright-data 0.31.7__tar.gz → 0.31.8__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.
- {mostlyright_data-0.31.7 → mostlyright_data-0.31.8}/PKG-INFO +1 -1
- {mostlyright_data-0.31.7 → mostlyright_data-0.31.8}/skills/mr-data-build/SKILL.md +24 -6
- {mostlyright_data-0.31.7 → mostlyright_data-0.31.8}/skills/mr-data-build/references/commands.md +2 -2
- {mostlyright_data-0.31.7 → mostlyright_data-0.31.8}/skills/mr-data-build/references/promote.md +7 -0
- {mostlyright_data-0.31.7 → mostlyright_data-0.31.8}/src/mostlyright/data_harness/thin/delivery.py +213 -17
- mostlyright_data-0.31.8/src/mostlyright/data_harness/thin/table_view.py +384 -0
- {mostlyright_data-0.31.7 → mostlyright_data-0.31.8}/src/mostlyright/data_harness/thin/v4_tables.py +71 -9
- {mostlyright_data-0.31.7 → mostlyright_data-0.31.8}/src/mostlyright/data_harness/thin/vocabulary.py +2 -1
- {mostlyright_data-0.31.7 → mostlyright_data-0.31.8}/src/mostlyright/data_harness/ux/render.py +3 -0
- {mostlyright_data-0.31.7 → mostlyright_data-0.31.8}/.gitignore +0 -0
- {mostlyright_data-0.31.7 → mostlyright_data-0.31.8}/README.md +0 -0
- {mostlyright_data-0.31.7 → mostlyright_data-0.31.8}/pyproject.toml +0 -0
- {mostlyright_data-0.31.7 → mostlyright_data-0.31.8}/scripts/hatch_build.py +0 -0
- {mostlyright_data-0.31.7 → mostlyright_data-0.31.8}/skills/mr-data-build/agents/openai.yaml +0 -0
- {mostlyright_data-0.31.7 → mostlyright_data-0.31.8}/skills/mr-data-build/references/1-open-the-page-and-the-link-to-it-in-the-first-message.md +0 -0
- {mostlyright_data-0.31.7 → mostlyright_data-0.31.8}/skills/mr-data-build/references/2-brief-two-to-four-questions-each-with-a-recommended-answer.md +0 -0
- {mostlyright_data-0.31.7 → mostlyright_data-0.31.8}/skills/mr-data-build/references/3-probe-read-a-source-before-committing-to-it.md +0 -0
- {mostlyright_data-0.31.7 → mostlyright_data-0.31.8}/skills/mr-data-build/references/4-decide-say-what-you-chose-what-you-refused-and-ask-one-question.md +0 -0
- {mostlyright_data-0.31.7 → mostlyright_data-0.31.8}/skills/mr-data-build/references/5-draft-one-recipe-document-one-call.md +0 -0
- {mostlyright_data-0.31.7 → mostlyright_data-0.31.8}/skills/mr-data-build/references/6-build-one-run-sized-to-acquire-every-measured-source-whole.md +0 -0
- {mostlyright_data-0.31.7 → mostlyright_data-0.31.8}/skills/mr-data-build/references/7-interrogate-ask-the-run-what-it-actually-delivered.md +0 -0
- {mostlyright_data-0.31.7 → mostlyright_data-0.31.8}/skills/mr-data-build/references/8-fix-revise-the-document-and-register-it-again.md +0 -0
- {mostlyright_data-0.31.7 → mostlyright_data-0.31.8}/skills/mr-data-build/references/9-present-only-what-survived-inspection-with-caveats.md +0 -0
- {mostlyright_data-0.31.7 → mostlyright_data-0.31.8}/skills/mr-data-build/references/agent-protocol.md +0 -0
- {mostlyright_data-0.31.7 → mostlyright_data-0.31.8}/skills/mr-data-build/references/autonomous-delivery.md +0 -0
- {mostlyright_data-0.31.7 → mostlyright_data-0.31.8}/skills/mr-data-build/references/before-the-first-tool-call.md +0 -0
- {mostlyright_data-0.31.7 → mostlyright_data-0.31.8}/skills/mr-data-build/references/boundaries.md +0 -0
- {mostlyright_data-0.31.7 → mostlyright_data-0.31.8}/skills/mr-data-build/references/cloud-authentication-preflight.md +0 -0
- {mostlyright_data-0.31.7 → mostlyright_data-0.31.8}/skills/mr-data-build/references/cross-repository-protocol-reference.md +0 -0
- {mostlyright_data-0.31.7 → mostlyright_data-0.31.8}/skills/mr-data-build/references/enriching-with-small-models.md +0 -0
- {mostlyright_data-0.31.7 → mostlyright_data-0.31.8}/skills/mr-data-build/references/installation-parity.md +0 -0
- {mostlyright_data-0.31.7 → mostlyright_data-0.31.8}/skills/mr-data-build/references/live-run.md +0 -0
- {mostlyright_data-0.31.7 → mostlyright_data-0.31.8}/skills/mr-data-build/references/making-a-table-incremental.md +0 -0
- {mostlyright_data-0.31.7 → mostlyright_data-0.31.8}/skills/mr-data-build/references/narrating-the-run.md +0 -0
- {mostlyright_data-0.31.7 → mostlyright_data-0.31.8}/skills/mr-data-build/references/not-hosted-yet.md +0 -0
- {mostlyright_data-0.31.7 → mostlyright_data-0.31.8}/skills/mr-data-build/references/one-install.md +0 -0
- {mostlyright_data-0.31.7 → mostlyright_data-0.31.8}/skills/mr-data-build/references/patterns.md +0 -0
- {mostlyright_data-0.31.7 → mostlyright_data-0.31.8}/skills/mr-data-build/references/prediction-labels.md +0 -0
- {mostlyright_data-0.31.7 → mostlyright_data-0.31.8}/skills/mr-data-build/references/preparing-table-search.md +0 -0
- {mostlyright_data-0.31.7 → mostlyright_data-0.31.8}/skills/mr-data-build/references/readers.md +0 -0
- {mostlyright_data-0.31.7 → mostlyright_data-0.31.8}/skills/mr-data-build/references/receipts.md +0 -0
- {mostlyright_data-0.31.7 → mostlyright_data-0.31.8}/skills/mr-data-build/references/recipe-test.md +0 -0
- {mostlyright_data-0.31.7 → mostlyright_data-0.31.8}/skills/mr-data-build/references/recording-a-stream-venue.md +0 -0
- {mostlyright_data-0.31.7 → mostlyright_data-0.31.8}/skills/mr-data-build/references/recovering-an-import-failure.md +0 -0
- {mostlyright_data-0.31.7 → mostlyright_data-0.31.8}/skills/mr-data-build/references/reference-pages.md +0 -0
- {mostlyright_data-0.31.7 → mostlyright_data-0.31.8}/skills/mr-data-build/references/required-protocol.md +0 -0
- {mostlyright_data-0.31.7 → mostlyright_data-0.31.8}/skills/mr-data-build/references/source-credentials.md +0 -0
- {mostlyright_data-0.31.7 → mostlyright_data-0.31.8}/skills/mr-data-build/references/sources.md +0 -0
- {mostlyright_data-0.31.7 → mostlyright_data-0.31.8}/skills/mr-data-build/references/the-one-thing-to-say-about-the-skill-itself.md +0 -0
- {mostlyright_data-0.31.7 → mostlyright_data-0.31.8}/skills/mr-data-build/references/transforms.md +0 -0
- {mostlyright_data-0.31.7 → mostlyright_data-0.31.8}/skills/mr-data-build/references/user-communication-contract.md +0 -0
- {mostlyright_data-0.31.7 → mostlyright_data-0.31.8}/skills/mr-data-build/references/writing-a-decision-record.md +0 -0
- {mostlyright_data-0.31.7 → mostlyright_data-0.31.8}/skills/mr-data-build/scripts/write_research_notebook.py +0 -0
- {mostlyright_data-0.31.7 → mostlyright_data-0.31.8}/src/mostlyright/data_harness/__init__.py +0 -0
- {mostlyright_data-0.31.7 → mostlyright_data-0.31.8}/src/mostlyright/data_harness/agent_protocol.py +0 -0
- {mostlyright_data-0.31.7 → mostlyright_data-0.31.8}/src/mostlyright/data_harness/canonical.py +0 -0
- {mostlyright_data-0.31.7 → mostlyright_data-0.31.8}/src/mostlyright/data_harness/formats.py +0 -0
- {mostlyright_data-0.31.7 → mostlyright_data-0.31.8}/src/mostlyright/data_harness/hosted_crawler_protocol.py +0 -0
- {mostlyright_data-0.31.7 → mostlyright_data-0.31.8}/src/mostlyright/data_harness/key_seam.py +0 -0
- {mostlyright_data-0.31.7 → mostlyright_data-0.31.8}/src/mostlyright/data_harness/page_coverage.py +0 -0
- {mostlyright_data-0.31.7 → mostlyright_data-0.31.8}/src/mostlyright/data_harness/part_check_evidence.py +0 -0
- {mostlyright_data-0.31.7 → mostlyright_data-0.31.8}/src/mostlyright/data_harness/session_probes.py +0 -0
- {mostlyright_data-0.31.7 → mostlyright_data-0.31.8}/src/mostlyright/data_harness/skill_assets.py +0 -0
- {mostlyright_data-0.31.7 → mostlyright_data-0.31.8}/src/mostlyright/data_harness/table_manifest.py +0 -0
- {mostlyright_data-0.31.7 → mostlyright_data-0.31.8}/src/mostlyright/data_harness/thin/__init__.py +0 -0
- {mostlyright_data-0.31.7 → mostlyright_data-0.31.8}/src/mostlyright/data_harness/thin/acquire.py +0 -0
- {mostlyright_data-0.31.7 → mostlyright_data-0.31.8}/src/mostlyright/data_harness/thin/acquire_cancel.py +0 -0
- {mostlyright_data-0.31.7 → mostlyright_data-0.31.8}/src/mostlyright/data_harness/thin/activity.py +0 -0
- {mostlyright_data-0.31.7 → mostlyright_data-0.31.8}/src/mostlyright/data_harness/thin/approvals.py +0 -0
- {mostlyright_data-0.31.7 → mostlyright_data-0.31.8}/src/mostlyright/data_harness/thin/backoff.py +0 -0
- {mostlyright_data-0.31.7 → mostlyright_data-0.31.8}/src/mostlyright/data_harness/thin/categories.py +0 -0
- {mostlyright_data-0.31.7 → mostlyright_data-0.31.8}/src/mostlyright/data_harness/thin/commands.py +0 -0
- {mostlyright_data-0.31.7 → mostlyright_data-0.31.8}/src/mostlyright/data_harness/thin/dataset-categories-v1.json +0 -0
- {mostlyright_data-0.31.7 → mostlyright_data-0.31.8}/src/mostlyright/data_harness/thin/description_shape.py +0 -0
- {mostlyright_data-0.31.7 → mostlyright_data-0.31.8}/src/mostlyright/data_harness/thin/download.py +0 -0
- {mostlyright_data-0.31.7 → mostlyright_data-0.31.8}/src/mostlyright/data_harness/thin/enrichment.py +0 -0
- {mostlyright_data-0.31.7 → mostlyright_data-0.31.8}/src/mostlyright/data_harness/thin/fast_features.py +0 -0
- {mostlyright_data-0.31.7 → mostlyright_data-0.31.8}/src/mostlyright/data_harness/thin/matching_benchmark.py +0 -0
- {mostlyright_data-0.31.7 → mostlyright_data-0.31.8}/src/mostlyright/data_harness/thin/narrative.py +0 -0
- {mostlyright_data-0.31.7 → mostlyright_data-0.31.8}/src/mostlyright/data_harness/thin/parity.py +0 -0
- {mostlyright_data-0.31.7 → mostlyright_data-0.31.8}/src/mostlyright/data_harness/thin/probe.py +0 -0
- {mostlyright_data-0.31.7 → mostlyright_data-0.31.8}/src/mostlyright/data_harness/thin/progress_rate.py +0 -0
- {mostlyright_data-0.31.7 → mostlyright_data-0.31.8}/src/mostlyright/data_harness/thin/progress_vocabulary.py +0 -0
- {mostlyright_data-0.31.7 → mostlyright_data-0.31.8}/src/mostlyright/data_harness/thin/propose.py +0 -0
- {mostlyright_data-0.31.7 → mostlyright_data-0.31.8}/src/mostlyright/data_harness/thin/recipe.py +0 -0
- {mostlyright_data-0.31.7 → mostlyright_data-0.31.8}/src/mostlyright/data_harness/thin/recipe_brief.py +0 -0
- {mostlyright_data-0.31.7 → mostlyright_data-0.31.8}/src/mostlyright/data_harness/thin/recipe_explain.py +0 -0
- {mostlyright_data-0.31.7 → mostlyright_data-0.31.8}/src/mostlyright/data_harness/thin/recipe_forecast.py +0 -0
- {mostlyright_data-0.31.7 → mostlyright_data-0.31.8}/src/mostlyright/data_harness/thin/recipe_lint.py +0 -0
- {mostlyright_data-0.31.7 → mostlyright_data-0.31.8}/src/mostlyright/data_harness/thin/recipe_test.py +0 -0
- {mostlyright_data-0.31.7 → mostlyright_data-0.31.8}/src/mostlyright/data_harness/thin/refresh_rehearsal.py +0 -0
- {mostlyright_data-0.31.7 → mostlyright_data-0.31.8}/src/mostlyright/data_harness/thin/release_check.py +0 -0
- {mostlyright_data-0.31.7 → mostlyright_data-0.31.8}/src/mostlyright/data_harness/thin/research.py +0 -0
- {mostlyright_data-0.31.7 → mostlyright_data-0.31.8}/src/mostlyright/data_harness/thin/router.py +0 -0
- {mostlyright_data-0.31.7 → mostlyright_data-0.31.8}/src/mostlyright/data_harness/thin/run_diagnose.py +0 -0
- {mostlyright_data-0.31.7 → mostlyright_data-0.31.8}/src/mostlyright/data_harness/thin/run_prefix.py +0 -0
- {mostlyright_data-0.31.7 → mostlyright_data-0.31.8}/src/mostlyright/data_harness/thin/runs.py +0 -0
- {mostlyright_data-0.31.7 → mostlyright_data-0.31.8}/src/mostlyright/data_harness/thin/session.py +0 -0
- {mostlyright_data-0.31.7 → mostlyright_data-0.31.8}/src/mostlyright/data_harness/thin/stream.py +0 -0
- {mostlyright_data-0.31.7 → mostlyright_data-0.31.8}/src/mostlyright/data_harness/thin/stream_venue.py +0 -0
- {mostlyright_data-0.31.7 → mostlyright_data-0.31.8}/src/mostlyright/data_harness/thin/studio_capabilities.py +0 -0
- {mostlyright_data-0.31.7 → mostlyright_data-0.31.8}/src/mostlyright/data_harness/thin/support.py +0 -0
- {mostlyright_data-0.31.7 → mostlyright_data-0.31.8}/src/mostlyright/data_harness/thin/table_search_contract.json +0 -0
- {mostlyright_data-0.31.7 → mostlyright_data-0.31.8}/src/mostlyright/data_harness/thin/transport.py +0 -0
- {mostlyright_data-0.31.7 → mostlyright_data-0.31.8}/src/mostlyright/data_harness/thin/user_agent.py +0 -0
- {mostlyright_data-0.31.7 → mostlyright_data-0.31.8}/src/mostlyright/data_harness/thin/v4.py +0 -0
- {mostlyright_data-0.31.7 → mostlyright_data-0.31.8}/src/mostlyright/data_harness/thin/v4_artifacts.py +0 -0
- {mostlyright_data-0.31.7 → mostlyright_data-0.31.8}/src/mostlyright/data_harness/thin/v4_catalog.py +0 -0
- {mostlyright_data-0.31.7 → mostlyright_data-0.31.8}/src/mostlyright/data_harness/thin/v4_connected.py +0 -0
- {mostlyright_data-0.31.7 → mostlyright_data-0.31.8}/src/mostlyright/data_harness/thin/v4_connections.py +0 -0
- {mostlyright_data-0.31.7 → mostlyright_data-0.31.8}/src/mostlyright/data_harness/thin/v4_dataset_covers.py +0 -0
- {mostlyright_data-0.31.7 → mostlyright_data-0.31.8}/src/mostlyright/data_harness/thin/v4_datasets.py +0 -0
- {mostlyright_data-0.31.7 → mostlyright_data-0.31.8}/src/mostlyright/data_harness/thin/v4_handoff.py +0 -0
- {mostlyright_data-0.31.7 → mostlyright_data-0.31.8}/src/mostlyright/data_harness/thin/v4_matching.py +0 -0
- {mostlyright_data-0.31.7 → mostlyright_data-0.31.8}/src/mostlyright/data_harness/thin/v4_narrative.py +0 -0
- {mostlyright_data-0.31.7 → mostlyright_data-0.31.8}/src/mostlyright/data_harness/thin/v4_public.py +0 -0
- {mostlyright_data-0.31.7 → mostlyright_data-0.31.8}/src/mostlyright/data_harness/thin/v4_query.py +0 -0
- {mostlyright_data-0.31.7 → mostlyright_data-0.31.8}/src/mostlyright/data_harness/thin/v4_reader.py +0 -0
- {mostlyright_data-0.31.7 → mostlyright_data-0.31.8}/src/mostlyright/data_harness/thin/v4_runs.py +0 -0
- {mostlyright_data-0.31.7 → mostlyright_data-0.31.8}/src/mostlyright/data_harness/thin/v4_search.py +0 -0
- {mostlyright_data-0.31.7 → mostlyright_data-0.31.8}/src/mostlyright/data_harness/thin/v4_search_contract.py +0 -0
- {mostlyright_data-0.31.7 → mostlyright_data-0.31.8}/src/mostlyright/data_harness/thin/v4_secrets.py +0 -0
- {mostlyright_data-0.31.7 → mostlyright_data-0.31.8}/src/mostlyright/data_harness/thin/v4_stream.py +0 -0
- {mostlyright_data-0.31.7 → mostlyright_data-0.31.8}/src/mostlyright/data_harness/ux/__init__.py +0 -0
- {mostlyright_data-0.31.7 → mostlyright_data-0.31.8}/src/mostlyright/data_harness/ux/attendance.py +0 -0
- {mostlyright_data-0.31.7 → mostlyright_data-0.31.8}/src/mostlyright/data_harness/ux/clarification.py +0 -0
- {mostlyright_data-0.31.7 → mostlyright_data-0.31.8}/src/mostlyright/data_harness/ux/cloud_auth.py +0 -0
- {mostlyright_data-0.31.7 → mostlyright_data-0.31.8}/src/mostlyright/data_harness/ux/commands/__init__.py +0 -0
- {mostlyright_data-0.31.7 → mostlyright_data-0.31.8}/src/mostlyright/data_harness/ux/commands/auth.py +0 -0
- {mostlyright_data-0.31.7 → mostlyright_data-0.31.8}/src/mostlyright/data_harness/ux/commands/clarify.py +0 -0
- {mostlyright_data-0.31.7 → mostlyright_data-0.31.8}/src/mostlyright/data_harness/ux/commands/login.py +0 -0
- {mostlyright_data-0.31.7 → mostlyright_data-0.31.8}/src/mostlyright/data_harness/ux/commands/whoami.py +0 -0
- {mostlyright_data-0.31.7 → mostlyright_data-0.31.8}/src/mostlyright/data_harness/ux/credential_native.py +0 -0
- {mostlyright_data-0.31.7 → mostlyright_data-0.31.8}/src/mostlyright/data_harness/ux/credential_store.py +0 -0
- {mostlyright_data-0.31.7 → mostlyright_data-0.31.8}/src/mostlyright/data_harness/ux/credentials.py +0 -0
- {mostlyright_data-0.31.7 → mostlyright_data-0.31.8}/src/mostlyright/data_harness/ux/login.py +0 -0
- {mostlyright_data-0.31.7 → mostlyright_data-0.31.8}/src/mostlyright/data_harness/ux/path_kind.py +0 -0
- {mostlyright_data-0.31.7 → mostlyright_data-0.31.8}/src/mostlyright/data_harness/ux/plain_file.py +0 -0
- {mostlyright_data-0.31.7 → mostlyright_data-0.31.8}/src/mostlyright/data_harness/ux/remediation.py +0 -0
|
@@ -14,6 +14,15 @@ offer the small models (classify, extract, match) for the judgement no rule can
|
|
|
14
14
|
wait for the person to name a model. Steps 3, 4, 5, 8 and 10 say where, and
|
|
15
15
|
[enriching with small models](references/enriching-with-small-models.md) says how.
|
|
16
16
|
|
|
17
|
+
## Set the goal as a checklist
|
|
18
|
+
|
|
19
|
+
At the start of every build, write the goal as a checklist with the host's todo or plan tool:
|
|
20
|
+
TodoWrite in Claude Code, todowrite in opencode, or the plan tool where the host has one. List
|
|
21
|
+
each deliverable the brief names. Then list every delivery step: the description in the skill's
|
|
22
|
+
shape, the cover, search on the main table, the table view review, the refresh cadence and the
|
|
23
|
+
enrichment offer. Keep the list current as you work. Each item ends done, or skipped on purpose
|
|
24
|
+
with the reason written beside it. Do not report the build as done while an item is open.
|
|
25
|
+
|
|
17
26
|
## Four gates
|
|
18
27
|
|
|
19
28
|
Every build passes these four gates in order. Do not skip one. The numbered steps below carry
|
|
@@ -196,9 +205,11 @@ step 6. The stage 3 reference holds its rule. Gate 4 is step 6.
|
|
|
196
205
|
|
|
197
206
|
## Work in parallel
|
|
198
207
|
|
|
199
|
-
When the host can run subagents
|
|
200
|
-
|
|
201
|
-
|
|
208
|
+
When the host can run subagents, use them. The discovery lanes in step 4 and the probes of the
|
|
209
|
+
shortlisted sources must fan out: one subagent per lane and one per source, all started at the
|
|
210
|
+
same time. Run them one after another only when there is one lane or one source. Give other
|
|
211
|
+
independent work to subagents or background commands the same way. The lead agent keeps the
|
|
212
|
+
brief, every decision, every write and every word to the user.
|
|
202
213
|
|
|
203
214
|
- **What fans out.** The discovery lanes in step 4, one subagent per lane. Probing the sources
|
|
204
215
|
on the shortlist, one subagent per source, each with `mr-data source inspect`. Bounded gate-3
|
|
@@ -272,10 +283,17 @@ merely to obtain a green run. Read [recovery details](references/agent-protocol.
|
|
|
272
283
|
serves that model. Confirm each lead against the rows before you offer it.
|
|
273
284
|
A succeeded full run's `mr-data status` and `mr-data watch` output carries a `delivery` block.
|
|
274
285
|
It names a missing cover, a description that is missing or out of the skill's shape,
|
|
275
|
-
natural-language search when the run's table has none,
|
|
286
|
+
natural-language search when the run's table has none, a view review when the table has no
|
|
287
|
+
saved view, a refresh cadence when none is recorded, and always the enrichment offer.
|
|
276
288
|
Complete every step before you report the build as done. Studio marks no main table, so you
|
|
277
|
-
judge it: skip the search
|
|
278
|
-
you test and demote owes none of these steps.
|
|
289
|
+
judge it: skip the search and view steps for a supporting table and say so in one line. A
|
|
290
|
+
scratch table you test and demote owes none of these steps.
|
|
291
|
+
Review the view with `mr-data table view TABLE_ID --json`. It lists the view kinds this
|
|
292
|
+
deployment offers and the roles each one binds. Choose from the columns and a bounded sample,
|
|
293
|
+
check the choice with `--set VIEW.json --dry-run`, then save it. The plain table is fine when
|
|
294
|
+
it reads best, but save it as a deliberate choice.
|
|
295
|
+
Record the cadence under step 9's readiness rule. A fixed snapshot has no cadence to record:
|
|
296
|
+
write that decision as a dataset note and skip the step, saying so in one line.
|
|
279
297
|
Offering enrichment is mandatory. Accepting it is the person's choice, and a no is a complete
|
|
280
298
|
answer.
|
|
281
299
|
9. Any truncated source means a preview, not the requested complete dataset. Inspect coverage
|
{mostlyright_data-0.31.7 → mostlyright_data-0.31.8}/skills/mr-data-build/references/commands.md
RENAMED
|
@@ -26,7 +26,7 @@ run in full.
|
|
|
26
26
|
| `mr-data recipe` | Register one recipe document (dataset, question, table plan, sources, transform, checks and units) in one call, and print the identifiers the server derived. The document is read first and every fault comes back in one refusal, each with the JSON pointer that names it. `--no-lint` sends it as written instead. A recipe that misses a feature that sets how fast a run fetches (a stated `pages.concurrency` under 64, a per-row request open to `batch`, a page walk open to `pagination.parallel`, or a Parquet file open to a ranged read) is refused `THIN_RECIPE_SLOW`, with each feature's pointer and fix, before anything is sent. Apply the fixes, or pass `--accept-slow "REASON"` with one sentence on why the slow path is right for this source. The receipt prints the reason and the features it covered. Registration refuses `THIN_BRIEF_MISSING` when the dataset's record carries no answered question and no delegation, and `THIN_RECIPE_DATASET_UNBOUND` when the document names no `dataset.id`. `--delegated "their words"` writes the delegation onto the dataset and registers in the same command, and clears the first of those two and never the second. `mr-data recipe show ID` reads one back. `mr-data recipe explain FILE` (or a recipe identifier) lists every reason its table can or cannot refresh, each with a rule code and Studio's suggested repair, and exits 2 when one blocks it. `mr-data recipe forecast RECIPE_ID` says what one run would ask of each source before it runs, and exits 3 when the run would overrun today's platform quota or one attempt. `--digest` is optional there, and without it the digest the recipe was registered with is forecast. `mr-data recipe readiness --table TABLE_ID --current-only` reads the revision one table runs now. The explanation's `fast_features` names each fast feature the recipe uses or misses, with a one-line fix. [Making a table incremental](making-a-table-incremental.md#the-loop-explain-forecast-run-diagnose) says when to use each. |
|
|
27
27
|
| `mr-data cover` | Generate and attach one branded 1200×630 dataset cover. Give it the dataset ID and what the image should depict; Studio fixes the model, single-color style, curated random palette, dimensions and storage. |
|
|
28
28
|
| `mr-data run` | Start one run against a registered recipe, named as `--recipe RECIPE_ID`, with `--digest RECIPE_DIGEST` when you want the run to assert which bytes it means. Neither is positional. The digest is the bare hex the registration receipt printed. Left out, the run reads it back from the registered recipe, which is the same value, because a recipe identifier names one revision. A full of a recipe that misses a fetch-speed feature is refused `THIN_RECIPE_SLOW`, as registration is, unless `--accept-slow "REASON"` is passed. Other modes print the missed features and are not refused. The mode is one of six: `sample`, `full`, `refresh`, `backfill`, `compact` and `replay`. Four have a shorthand flag (`--sample`, `--full`, `--refresh`, `--backfill`) and two do not, so write `--mode MODE`, which is accepted for every one of them. A refresh executes only Studio's persisted source-action plan, and a plan shape it does not refresh returns `RESYNC_REQUIRED` before acquisition. [Which plans refresh](making-a-table-incremental.md#which-plans-refresh) lists them, and `mr-data recipe explain` says which one a table is. Use `mr-data table resync TABLE_ID --request-id UUID` for an explicit full source reread, retaining that UUID if the response is uncertain. `--backfill` states the exact window with `--window START END`. `--mode replay --sources-from RUN_ID` asks Studio to run the registered revision against the RETAINED RAW INPUTS of one named successful run of the same table: nothing is fetched from this computer, nothing is acquired again, the result is compared against that run and never becomes the live version, and it neither asks for nor records an approval. Where Studio has replay switched off, or the named run is not successful, not the same table, or no longer retains its inputs, it answers a typed refusal. Report the code rather than retrying in another mode. `--sources-from` on any other mode is refused `THIN_ARGUMENT_INVALID` before anything is sent. `--max-rows` and `--max-source-bytes` bound ONE SOURCE rather than the finished table. `--max-rows` cuts rows after a source is fetched and decoded, so it does not shorten a collection walk. A sample with no clamp is refused: `CLAMPS_REQUIRED` from Studio, and `THIN_REQUEST_INVALID` from this client first. A table's first succeeded run goes live, truncated or not, so test on a scratch table as [the probe rule](3-probe-read-a-source-before-committing-to-it.md#the-probe-rule-test-on-a-scratch-table-never-on-the-real-table) says. A large run is held for a size confirmation (not a charge), which `--confirm` settles and whose printed `confirm_command` re-states every argument the request carried. `--approve-full RUN_ID` releases the full an existing legacy sample-first pair is holding once its preview has succeeded, naming either half of the pair. Where the deployment still wants a person at a browser it answers `THIN_INTERACTIVE_HUMAN_REQUIRED` and names the run page. `--retry RUN_ID` resumes a failed or cancelled progressive full from the pages it saved (`resume_capture_run_id` and the ceilings it carried; `retry_of_run_id` as well only when Studio admits a named retry). A failure that says the recipe must change is refused before anything is posted. Any other failed run is tried again when its triple carries `room_fault: true`, re-stating that run's own coordinate and ceilings and naming the failed run so Studio starts a new attempt, and is refused with the triple and the next step Studio's recovery category names when it is not. `room_fault` is Studio's `recovery.room_fault` where Studio states one. A source that kept refusing (`SOURCE_RATE_LIMITED`, `SOURCE_HTTP_5XX`, `SOURCE_PROXY_BUSY`) is sent anyway: Studio admits it 120 seconds after the failure and refuses `RUN_RETRY_TOO_SOON` with a Retry-After before then, so wait that long and run `--retry` again. `--cancel RUN` stops one. |
|
|
29
|
-
| `mr-data status` | Report which of the seven states one run is in, what it delivered and whether a ceiling cut it short, and — on a failure — what failed, where, and whether the fault was the execution room's rather than the recipe's. Exits non-zero on a failed run. `--diagnose` adds everything else Studio can say about the run: its progress, a per-row source's plan counts, its checkpoints, and how each attempt ended, with a lost attempt's cause marked as an inference. A succeeded full run carries `delivery`: the steps still owed before the build is done (a description missing or out of the skill's shape, a missing cover, natural-language search when the dataset's main table has none, and always the enrichment offer), each with its command. It never changes the exit code. |
|
|
29
|
+
| `mr-data status` | Report which of the seven states one run is in, what it delivered and whether a ceiling cut it short, and — on a failure — what failed, where, and whether the fault was the execution room's rather than the recipe's. Exits non-zero on a failed run. `--diagnose` adds everything else Studio can say about the run: its progress, a per-row source's plan counts, its checkpoints, and how each attempt ended, with a lost attempt's cause marked as an inference. A succeeded full run carries `delivery`: the steps still owed before the build is done (a description missing or out of the skill's shape, a missing cover, natural-language search when the dataset's main table has none, a view review when the table has no saved view, a refresh cadence when none is recorded, and always the enrichment offer), each with its command. A read that fails adds a note, never a step. It never changes the exit code. |
|
|
30
30
|
| `mr-data runs` | Report this workspace's own runs: identifier, mode, state and creation time, plus the failure triple of any that failed and whether that failure was the execution room's. `--dataset DATASET_ID` narrows it to one dataset's runs, so "what have I run for this dataset?" is one scoped read, and a value that is not an identifier is refused `THIN_ARGUMENT_INVALID`. `--status` and `--mode` narrow it too and are refused `THIN_ARGUMENT_INVALID` for a word outside the seven states or the six modes; the three combine. Studio narrows before it cuts a page, so a filtered page holds the newest runs that match however many runs the workspace has. `--limit` says how many, and pages are followed to reach it; a listing that does not end says how many were read and suggests a smaller `--limit` or a narrower filter. The answer prints `next_cursor`, and `--cursor` continues from it. |
|
|
31
31
|
| `mr-data watch` | Stream one run's live progress under the durable event type of each stage, resuming across stream cuts. Exits non-zero when the run failed. `mr-data watch RUN_ID RUN_ID ...` follows up to 16 runs at once, prints one line as each ends, and returns once all have finished with one receipt per run (`failed_run_ids`, `refused_run_ids`); it exits 2 when any run failed and 1 when a run could not be watched. `--from-seq` and `--last-event-id` resume one run only. A full run that succeeds carries the same `delivery` block as `mr-data status`, and the multi-run receipt merges every run's steps. |
|
|
32
32
|
| `mr-data query` | Run one bounded read-only SQL statement over a finished run's own table and print the rows. Name the table `run_table` in the SQL, whatever the recipe called it. Bounded on rows, on answer bytes and on time, and refused by name when a bound is crossed. When no worker can answer, the refusal names `mr-data download RUN_ID` as `fallback_command`, which brings the table here to read locally. The question is asked through Mostly Right Cloud; while its usage paywall is on and the workspace is unsubscribed, each answered query counts toward the person's monthly allowance, and a spent allowance refuses `THIN_USAGE_LIMIT`. A refusal after the question was queued names its `query_id`; running the same command again reads that query back. |
|
|
@@ -47,7 +47,7 @@ run in full.
|
|
|
47
47
|
| `mr-data open` | Mint a single-use, short-lived address that continues this session in a browser at one dashboard path, and print it. `--open` hands it to the platform opener. The credential decides who mints: a device credential — what `mr-data login` stores — mints at Cloud, and a personal access token mints at Studio. |
|
|
48
48
|
| `mr-data promote` | Record the cadence one table refreshes on and the reasoning behind it. A table's first succeeded run goes live on its own, so this is not what makes it readable; it is idempotent on a table that is already live, and it is how a withdrawn table is put back. The Harness worker does not perform the catch-up or scheduled refresh; report those only when another deployed component returns durable evidence that it did. |
|
|
49
49
|
| `mr-data reschedule` | Change how often one live table refreshes, without the demote and promote that would reset its bookkeeping and buy a catch-up run. `--cadence` takes a cron expression or an interval such as `every 6h`; `--why` records the reasoning. It starts no run. `--lock` freezes the schedule so Studio stops adjusting it; `--unlock` lets it follow the source again. A table that cannot refresh answers `table_schedule_held` and exits 2, naming the two repairs: declare `rebuild`, or `table resync`. |
|
|
50
|
-
| `mr-data table` | Report what one table is serving and how its refresh schedule is going: the state in plain words, the schedule in force, the next refresh, the schedule that was asked for and the reason given for it, and — once Studio has settled on one — the interval it measured and how many source updates that rests on. Where Studio reports it, it also prints the table's refresh strategy: "rebuilds every 7d; next T" or "held: blocker". `table rename TABLE --name NAME` writes a new name, lowercase snake_case and unique within its dataset, fenced on that dataset's version and retried once if somebody else wrote first; nothing is rebuilt, because every run, version and schedule hangs off the identifier, which does not move. `table archive TABLE --confirm-name NAME` retires one table you name by the name it is called, and frees that name; a live table is refused until you `demote` it, and nothing built is deleted. `table archive TABLE [TABLE ...] --confirm DELETE` retires as many tables as you name at once: `DELETE` is the literal word, typed exactly, and it confirms the identifiers you typed rather than a name, so each table is retired under the name Studio is holding for it. Every table is attempted whatever the one before it answered, one line is printed for each, and the command exits non-zero if any was not retired — so read the outcome of each rather than the exit code alone. `--confirm-name` is refused when you name more than one table. |
|
|
50
|
+
| `mr-data table` | Report what one table is serving and how its refresh schedule is going: the state in plain words, the schedule in force, the next refresh, the schedule that was asked for and the reason given for it, and — once Studio has settled on one — the interval it measured and how many source updates that rests on. Where Studio reports it, it also prints the table's refresh strategy: "rebuilds every 7d; next T" or "held: blocker". `table rename TABLE --name NAME` writes a new name, lowercase snake_case and unique within its dataset, fenced on that dataset's version and retried once if somebody else wrote first; nothing is rebuilt, because every run, version and schedule hangs off the identifier, which does not move. `table archive TABLE --confirm-name NAME` retires one table you name by the name it is called, and frees that name; a live table is refused until you `demote` it, and nothing built is deleted. `table archive TABLE [TABLE ...] --confirm DELETE` retires as many tables as you name at once: `DELETE` is the literal word, typed exactly, and it confirms the identifiers you typed rather than a name, so each table is retired under the name Studio is holding for it. Every table is attempted whatever the one before it answered, one line is printed for each, and the command exits non-zero if any was not retired — so read the outcome of each rather than the exit code alone. `--confirm-name` is refused when you name more than one table. `table view TABLE` says whether a live table has a saved view (`view_saved`) and lists the view kinds (`table`, `cards`, `places`, `products`, `events`, `jobs`, `people`, `articles`) and the roles each binds. There is no map or chart kind, and `places` are location cards. `table view TABLE --set VIEW.json` saves `{"version": 1, "template": KIND, "fields": {ROLE: COLUMN}}`, with optional `facts` (up to 4 columns) and `imageStyle`. `--dry-run` has Cloud validate it against the live table and save nothing. The file is checked here before anything is sent. Replacing a saved view needs its revision as `--expected-revision`, which MCP `get_table` reports, because Cloud serves no CLI read of it. A stale revision is refused `THIN_TABLE_VIEW_VIEW_CHANGED`. The command uses the device key. |
|
|
51
51
|
| `mr-data pin` | Ask Studio to freeze one table pointer on an exact version, for a rollback or a hold. |
|
|
52
52
|
| `mr-data unpin` | Ask Studio to resume pointer tracking; read the returned state before claiming it resumed. |
|
|
53
53
|
| `mr-data demote` | Ask Studio to withdraw the pointer and any schedule it owns, for one table or for as many as you name: `demote TABLE [TABLE ...]` withdraws them one after another, attempts every one of them whatever the one before it answered, prints a line for each, and exits non-zero if any is still live. Pair it with `table archive` when you are retiring a set: a live table cannot be archived, so it is withdraw-then-archive, two commands rather than a loop. |
|
{mostlyright_data-0.31.7 → mostlyright_data-0.31.8}/skills/mr-data-build/references/promote.md
RENAMED
|
@@ -55,6 +55,13 @@ simply omitting the cadence command. Do not promise that ongoing work is disable
|
|
|
55
55
|
state proving it, and do not demote or archive a requested readable dataset as a workaround. If the
|
|
56
56
|
available controls cannot preserve the requested snapshot and refresh behavior, report that gap.
|
|
57
57
|
|
|
58
|
+
**A fixed snapshot is a recorded decision, not a missing cadence.** Studio has no cadence that
|
|
59
|
+
means never. Leave the table unscheduled, confirm `mr-data table TABLE_ID` shows no schedule,
|
|
60
|
+
and record the decision and its reason with
|
|
61
|
+
`mr-data dataset note DATASET_ID --heading "Fixed snapshot: no refresh" --markdown-file NOTE.md`.
|
|
62
|
+
Then skip the delivery block's cadence step, saying so in one line. The step stays listed, and
|
|
63
|
+
the note is the record.
|
|
64
|
+
|
|
58
65
|
This call records a schedule; it is not proof of data continuation. Schedule only a current recipe
|
|
59
66
|
that `mr-data recipe readiness --table TABLE_ID --current-only --json` reports as refresh-ready, or
|
|
60
67
|
one that declares `rebuild`. [Making a table incremental](making-a-table-incremental.md) says
|
{mostlyright_data-0.31.7 → mostlyright_data-0.31.8}/src/mostlyright/data_harness/thin/delivery.py
RENAMED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
"""The steps a succeeded full run still owes before the build is reported as done.
|
|
2
2
|
|
|
3
3
|
A full run that succeeded has data on the page. The page is not finished until it has a real
|
|
4
|
-
description and a cover,
|
|
5
|
-
|
|
6
|
-
|
|
4
|
+
description and a cover, the main table has search and a deliberately chosen view, the table's
|
|
5
|
+
refresh cadence is recorded, and the person has been offered enrichment. This module names what
|
|
6
|
+
is missing, reading the dataset, the table's search, the table and its saved view once each, and
|
|
7
|
+
always names the enrichment offer. It never raises: a read that fails adds a note, never a step.
|
|
7
8
|
"""
|
|
8
9
|
|
|
9
10
|
from __future__ import annotations
|
|
@@ -14,7 +15,7 @@ from typing import Any
|
|
|
14
15
|
from mostlyright.data_harness.thin import description_shape
|
|
15
16
|
from mostlyright.data_harness.thin.session import StudioSession
|
|
16
17
|
from mostlyright.data_harness.thin.transport import ThinLaneError, Transport
|
|
17
|
-
from mostlyright.data_harness.thin.v4 import identifier
|
|
18
|
+
from mostlyright.data_harness.thin.v4 import GET_TABLE_PATH, identifier
|
|
18
19
|
from mostlyright.data_harness.thin.v4_datasets import StudioV4DatasetClient
|
|
19
20
|
|
|
20
21
|
DELIVERY_VERSION = 1
|
|
@@ -34,7 +35,14 @@ _FAILURE_SAYS: dict[str, str] = {
|
|
|
34
35
|
}
|
|
35
36
|
|
|
36
37
|
#: The step names, in the order a person does them.
|
|
37
|
-
STEPS: tuple[str, ...] = (
|
|
38
|
+
STEPS: tuple[str, ...] = (
|
|
39
|
+
"description",
|
|
40
|
+
"cover",
|
|
41
|
+
"search",
|
|
42
|
+
"table_view",
|
|
43
|
+
"cadence",
|
|
44
|
+
"enrichment_offer",
|
|
45
|
+
)
|
|
38
46
|
|
|
39
47
|
_ENRICHMENT_WHY = (
|
|
40
48
|
"Offering enrichment is required on every full build. Confirm each lead against the rows, "
|
|
@@ -51,6 +59,42 @@ _SEARCH_WHY = (
|
|
|
51
59
|
"authoring, or when the table has nothing searchable."
|
|
52
60
|
)
|
|
53
61
|
|
|
62
|
+
_VIEW_WHY = (
|
|
63
|
+
"Review how its rows read best and save that view. mr-data table view lists the view kinds "
|
|
64
|
+
"this deployment offers and the roles each one binds. Inspect the columns and a bounded "
|
|
65
|
+
"sample with mr-data peek, check the view with --set VIEW.json --dry-run, then save it. The "
|
|
66
|
+
"plain table is a valid choice when it reads best, but save it as a deliberate choice. Skip "
|
|
67
|
+
"it, saying why in one line, for a supporting table."
|
|
68
|
+
)
|
|
69
|
+
|
|
70
|
+
_SNAPSHOT = (
|
|
71
|
+
"Studio has no cadence that means never. When the agreed answer is a fixed snapshot, leave "
|
|
72
|
+
"the table unscheduled, record that decision with mr-data dataset note {dataset_id} "
|
|
73
|
+
'--heading "Fixed snapshot: no refresh" --markdown-file NOTE.md, and skip this step, saying '
|
|
74
|
+
"so in one line. The step stays listed after the note, because the note is the record."
|
|
75
|
+
)
|
|
76
|
+
|
|
77
|
+
_CADENCE_WHY = (
|
|
78
|
+
"Record it from the update answer in the brief. First confirm mr-data recipe readiness "
|
|
79
|
+
"--table {table_id} --current-only --json reports the current revision refresh-ready, or that "
|
|
80
|
+
"the recipe declares rebuild. A recipe that is not refresh-ready is a design fault to repair "
|
|
81
|
+
"with mr-data recipe explain, not a reason to skip this step. Then record the cadence and "
|
|
82
|
+
"the reasoning with promote. "
|
|
83
|
+
)
|
|
84
|
+
|
|
85
|
+
_NOT_READY_WHY = (
|
|
86
|
+
"Its current recipe is not refresh-ready: {blocker}. That is a design fault to repair, not a "
|
|
87
|
+
"state to wait out. Run mr-data recipe explain RECIPE_ID --json, repair the recipe, register "
|
|
88
|
+
"the revision and resync once, then record the cadence and the reasoning with promote. "
|
|
89
|
+
)
|
|
90
|
+
|
|
91
|
+
_PARKED_WHY = (
|
|
92
|
+
"A cadence was requested, but Studio holds it because the current recipe is not "
|
|
93
|
+
"refresh-ready: {blocker}. That is a design fault to repair, not a state to wait out. Run "
|
|
94
|
+
"mr-data recipe explain RECIPE_ID --json, repair the recipe, register the revision and resync "
|
|
95
|
+
"once. Studio restores the held schedule when the recipe is ready."
|
|
96
|
+
)
|
|
97
|
+
|
|
54
98
|
#: Every block says this: a scratch table is a test, not the delivered dataset.
|
|
55
99
|
SCOPE = "A scratch table you test and demote owes none of these steps."
|
|
56
100
|
|
|
@@ -137,7 +181,7 @@ def _search_state(answer: Mapping[str, Any], table_id: str) -> str:
|
|
|
137
181
|
|
|
138
182
|
|
|
139
183
|
def _search_step(
|
|
140
|
-
client: StudioV4DatasetClient,
|
|
184
|
+
client: StudioV4DatasetClient, table_id: str
|
|
141
185
|
) -> tuple[dict[str, str] | None, str | None]:
|
|
142
186
|
"""The search step when the run's table has no search, and any note. Never raises.
|
|
143
187
|
|
|
@@ -145,10 +189,6 @@ def _search_step(
|
|
|
145
189
|
for a supporting table.
|
|
146
190
|
"""
|
|
147
191
|
|
|
148
|
-
try:
|
|
149
|
-
table_id = identifier(run.get("table_id"), "table identifier")
|
|
150
|
-
except Exception: # a record without a usable table identifier is still a delivered run
|
|
151
|
-
return None, "Search could not be checked: the run names no table."
|
|
152
192
|
try:
|
|
153
193
|
# Imported here: the search module's imports reach the run module, which imports this one.
|
|
154
194
|
from mostlyright.data_harness.thin.v4_search import TABLE_SEARCH_PATH
|
|
@@ -179,6 +219,153 @@ def _search_unchecked(table_id: str, why: str) -> str:
|
|
|
179
219
|
return f"Search could not be checked{why}. Read mr-data search status {table_id}."
|
|
180
220
|
|
|
181
221
|
|
|
222
|
+
def _refusal_said(error: BaseException) -> str:
|
|
223
|
+
return f" ({error.code})" if isinstance(error, ThinLaneError) else ""
|
|
224
|
+
|
|
225
|
+
|
|
226
|
+
def _table_record(
|
|
227
|
+
client: StudioV4DatasetClient, table_id: str
|
|
228
|
+
) -> tuple[Mapping[str, Any] | None, str | None]:
|
|
229
|
+
"""The Studio table record, or a note saying it could not be read. Never raises."""
|
|
230
|
+
|
|
231
|
+
try:
|
|
232
|
+
record = client._call("GET", GET_TABLE_PATH.format(table_id=table_id), expected=(200,))
|
|
233
|
+
except Exception as error: # a failed read must never fail the command
|
|
234
|
+
return None, (
|
|
235
|
+
f"View and cadence could not be checked{_refusal_said(error)}. "
|
|
236
|
+
f"Read mr-data table {table_id}."
|
|
237
|
+
)
|
|
238
|
+
if not isinstance(record, Mapping) or record.get("table_id") != table_id:
|
|
239
|
+
return None, f"View and cadence could not be checked. Read mr-data table {table_id}."
|
|
240
|
+
return record, None
|
|
241
|
+
|
|
242
|
+
|
|
243
|
+
def cadence_step(
|
|
244
|
+
record: Mapping[str, Any], *, table_id: str, dataset_id: str
|
|
245
|
+
) -> dict[str, str] | None:
|
|
246
|
+
"""The cadence step when a live table has no schedule and no cadence recorded.
|
|
247
|
+
|
|
248
|
+
Studio reports both as null until an explicit cadence is chosen, and while a readiness hold
|
|
249
|
+
parks a requested schedule. Studio also reads every such live table as ``held``, so ``held``
|
|
250
|
+
alone says nothing: a parked schedule or a named blocker is what makes it a repair.
|
|
251
|
+
"""
|
|
252
|
+
|
|
253
|
+
if record.get("promotion_status") != "live":
|
|
254
|
+
return None
|
|
255
|
+
if record.get("schedule") is not None or record.get("cadence") is not None:
|
|
256
|
+
return None
|
|
257
|
+
strategy = record.get("refresh_strategy")
|
|
258
|
+
strategy = strategy if isinstance(strategy, Mapping) else {}
|
|
259
|
+
blocker = strategy.get("blocker") or strategy.get("blocker_code")
|
|
260
|
+
said = blocker if isinstance(blocker, str) and blocker else "a blocking finding"
|
|
261
|
+
readiness = f"mr-data recipe readiness --table {table_id} --current-only --json"
|
|
262
|
+
if isinstance(strategy.get("held_schedule"), Mapping):
|
|
263
|
+
why = (
|
|
264
|
+
_PARKED_WHY.format(blocker=said)
|
|
265
|
+
if isinstance(blocker, str) and blocker
|
|
266
|
+
else "A cadence was requested, and Studio has not yet restored it. Read "
|
|
267
|
+
f"{readiness} and mr-data table {table_id} until the schedule is in force."
|
|
268
|
+
)
|
|
269
|
+
return _step(
|
|
270
|
+
"cadence",
|
|
271
|
+
readiness,
|
|
272
|
+
f"This run's table, {table_id}, has no refresh cadence in force. " + why,
|
|
273
|
+
)
|
|
274
|
+
snapshot = _SNAPSHOT.format(dataset_id=dataset_id)
|
|
275
|
+
if isinstance(blocker, str) and blocker:
|
|
276
|
+
return _step(
|
|
277
|
+
"cadence",
|
|
278
|
+
readiness,
|
|
279
|
+
f"This run's table, {table_id}, has no refresh cadence recorded. "
|
|
280
|
+
+ _NOT_READY_WHY.format(blocker=said)
|
|
281
|
+
+ snapshot,
|
|
282
|
+
)
|
|
283
|
+
return _step(
|
|
284
|
+
"cadence",
|
|
285
|
+
f'mr-data promote {table_id} --cadence "CRON OR every Nh" --why "WHY THIS FITS THE '
|
|
286
|
+
'SOURCE" --json',
|
|
287
|
+
f"This run's table, {table_id}, has no refresh cadence recorded. "
|
|
288
|
+
+ _CADENCE_WHY.format(table_id=table_id)
|
|
289
|
+
+ snapshot,
|
|
290
|
+
)
|
|
291
|
+
|
|
292
|
+
|
|
293
|
+
def _cloud_view_client(transport: Transport) -> Any:
|
|
294
|
+
"""The Cloud table-view client on the stored device key. Tests replace it."""
|
|
295
|
+
|
|
296
|
+
# Imported here: the view module reads the credential store, which only this step needs.
|
|
297
|
+
from mostlyright.data_harness.thin import table_view
|
|
298
|
+
|
|
299
|
+
return table_view.cloud_client(transport)
|
|
300
|
+
|
|
301
|
+
|
|
302
|
+
def _view_step(
|
|
303
|
+
record: Mapping[str, Any], *, table_id: str, transport: Transport
|
|
304
|
+
) -> tuple[dict[str, str] | None, str | None]:
|
|
305
|
+
"""The view step when the live table has no saved view, and any note. Never raises."""
|
|
306
|
+
|
|
307
|
+
from mostlyright.data_harness.thin import table_view
|
|
308
|
+
|
|
309
|
+
try:
|
|
310
|
+
coordinates = table_view.live_coordinates(record)
|
|
311
|
+
except Exception:
|
|
312
|
+
coordinates = None
|
|
313
|
+
if coordinates is None:
|
|
314
|
+
return None, None
|
|
315
|
+
dataset_id, live = coordinates
|
|
316
|
+
try:
|
|
317
|
+
saved = table_view.saved_state(
|
|
318
|
+
_cloud_view_client(transport),
|
|
319
|
+
dataset_id=dataset_id,
|
|
320
|
+
table_id=table_id,
|
|
321
|
+
live_version_id=live,
|
|
322
|
+
)
|
|
323
|
+
except Exception as error: # a failed read must never fail the command
|
|
324
|
+
return None, (
|
|
325
|
+
f"The table view could not be checked{_refusal_said(error)}. "
|
|
326
|
+
f"Read mr-data table view {table_id}."
|
|
327
|
+
)
|
|
328
|
+
if saved:
|
|
329
|
+
return None, None
|
|
330
|
+
why = f"This run's table, {table_id}, has no saved view. {_VIEW_WHY}"
|
|
331
|
+
return _step("table_view", f"mr-data table view {table_id} --json", why), None
|
|
332
|
+
|
|
333
|
+
|
|
334
|
+
def _table_steps(
|
|
335
|
+
client: StudioV4DatasetClient,
|
|
336
|
+
run: Mapping[str, Any],
|
|
337
|
+
*,
|
|
338
|
+
dataset_id: str,
|
|
339
|
+
transport: Transport,
|
|
340
|
+
) -> tuple[list[dict[str, str]], list[str]]:
|
|
341
|
+
"""Search, view and cadence for the run's table, in that order, and any notes."""
|
|
342
|
+
|
|
343
|
+
try:
|
|
344
|
+
table_id = identifier(run.get("table_id"), "table identifier")
|
|
345
|
+
except Exception: # a record without a usable table identifier is still a delivered run
|
|
346
|
+
return [], ["Search, view and cadence could not be checked: the run names no table."]
|
|
347
|
+
steps: list[dict[str, str]] = []
|
|
348
|
+
notes: list[str] = []
|
|
349
|
+
search, note = _search_step(client, table_id)
|
|
350
|
+
if search is not None:
|
|
351
|
+
steps.append(search)
|
|
352
|
+
if note is not None:
|
|
353
|
+
notes.append(note)
|
|
354
|
+
record, note = _table_record(client, table_id)
|
|
355
|
+
if record is None:
|
|
356
|
+
notes.append(str(note))
|
|
357
|
+
return steps, notes
|
|
358
|
+
view, note = _view_step(record, table_id=table_id, transport=transport)
|
|
359
|
+
if view is not None:
|
|
360
|
+
steps.append(view)
|
|
361
|
+
if note is not None:
|
|
362
|
+
notes.append(note)
|
|
363
|
+
cadence = cadence_step(record, table_id=table_id, dataset_id=dataset_id)
|
|
364
|
+
if cadence is not None:
|
|
365
|
+
steps.append(cadence)
|
|
366
|
+
return steps, notes
|
|
367
|
+
|
|
368
|
+
|
|
182
369
|
def _unchecked(run_id: str, note: str) -> dict[str, Any]:
|
|
183
370
|
return {
|
|
184
371
|
"version": DELIVERY_VERSION,
|
|
@@ -188,7 +375,13 @@ def _unchecked(run_id: str, note: str) -> dict[str, Any]:
|
|
|
188
375
|
}
|
|
189
376
|
|
|
190
377
|
|
|
191
|
-
def block(
|
|
378
|
+
def block(
|
|
379
|
+
client: StudioV4DatasetClient,
|
|
380
|
+
run: Mapping[str, Any],
|
|
381
|
+
run_id: str,
|
|
382
|
+
*,
|
|
383
|
+
transport: Transport | None = None,
|
|
384
|
+
) -> dict[str, Any]:
|
|
192
385
|
"""The ``delivery`` member for one succeeded full run. Never raises."""
|
|
193
386
|
|
|
194
387
|
try:
|
|
@@ -208,12 +401,13 @@ def block(client: StudioV4DatasetClient, run: Mapping[str, Any], run_id: str) ->
|
|
|
208
401
|
f"Presentation could not be checked{why}. Read mr-data dataset show {dataset_id}.",
|
|
209
402
|
)
|
|
210
403
|
steps = required_steps(record, dataset_id=dataset_id, run_id=run_id)
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
404
|
+
table, notes = _table_steps(
|
|
405
|
+
client, run, dataset_id=dataset_id, transport=transport or client.transport
|
|
406
|
+
)
|
|
407
|
+
steps[len(steps) - 1 : len(steps) - 1] = table
|
|
214
408
|
delivered: dict[str, Any] = {"version": DELIVERY_VERSION, "scope": SCOPE, "required": steps}
|
|
215
|
-
if
|
|
216
|
-
delivered["note"] =
|
|
409
|
+
if notes:
|
|
410
|
+
delivered["note"] = " ".join(notes)
|
|
217
411
|
return delivered
|
|
218
412
|
|
|
219
413
|
|
|
@@ -230,7 +424,9 @@ def for_run(
|
|
|
230
424
|
if not applies(run, succeeded=succeeded):
|
|
231
425
|
return None
|
|
232
426
|
try:
|
|
233
|
-
return block(
|
|
427
|
+
return block(
|
|
428
|
+
StudioV4DatasetClient(session, transport=transport), run, run_id, transport=transport
|
|
429
|
+
)
|
|
234
430
|
except Exception: # the block must never fail the command
|
|
235
431
|
return _unchecked(run_id, "Presentation could not be checked.")
|
|
236
432
|
|