mostlyright-data 0.29.7__tar.gz → 0.29.9__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.29.7 → mostlyright_data-0.29.9}/PKG-INFO +1 -1
- {mostlyright_data-0.29.7 → mostlyright_data-0.29.9}/pyproject.toml +1 -1
- {mostlyright_data-0.29.7 → mostlyright_data-0.29.9}/skills/mr-data-build/references/commands.md +1 -1
- {mostlyright_data-0.29.7 → mostlyright_data-0.29.9}/skills/mr-data-build/references/live-run.md +3 -2
- {mostlyright_data-0.29.7 → mostlyright_data-0.29.9}/src/mostlyright/data_harness/thin/recipe.py +6 -5
- {mostlyright_data-0.29.7 → mostlyright_data-0.29.9}/src/mostlyright/data_harness/thin/recipe_explain.py +9 -7
- {mostlyright_data-0.29.7 → mostlyright_data-0.29.9}/src/mostlyright/data_harness/thin/v4.py +39 -10
- {mostlyright_data-0.29.7 → mostlyright_data-0.29.9}/src/mostlyright/data_harness/thin/v4_query.py +1 -2
- {mostlyright_data-0.29.7 → mostlyright_data-0.29.9}/src/mostlyright/data_harness/thin/v4_runs.py +156 -26
- {mostlyright_data-0.29.7 → mostlyright_data-0.29.9}/.gitignore +0 -0
- {mostlyright_data-0.29.7 → mostlyright_data-0.29.9}/README.md +0 -0
- {mostlyright_data-0.29.7 → mostlyright_data-0.29.9}/scripts/hatch_build.py +0 -0
- {mostlyright_data-0.29.7 → mostlyright_data-0.29.9}/skills/mr-data-build/SKILL.md +0 -0
- {mostlyright_data-0.29.7 → mostlyright_data-0.29.9}/skills/mr-data-build/agents/openai.yaml +0 -0
- {mostlyright_data-0.29.7 → mostlyright_data-0.29.9}/skills/mr-data-build/references/1-open-the-page-and-the-link-to-it-in-the-first-message.md +0 -0
- {mostlyright_data-0.29.7 → mostlyright_data-0.29.9}/skills/mr-data-build/references/2-brief-two-to-four-questions-each-with-a-recommended-answer.md +0 -0
- {mostlyright_data-0.29.7 → mostlyright_data-0.29.9}/skills/mr-data-build/references/3-probe-read-a-source-before-committing-to-it.md +0 -0
- {mostlyright_data-0.29.7 → mostlyright_data-0.29.9}/skills/mr-data-build/references/4-decide-say-what-you-chose-what-you-refused-and-ask-one-question.md +0 -0
- {mostlyright_data-0.29.7 → mostlyright_data-0.29.9}/skills/mr-data-build/references/5-draft-one-recipe-document-one-call.md +0 -0
- {mostlyright_data-0.29.7 → mostlyright_data-0.29.9}/skills/mr-data-build/references/6-build-one-run-sized-to-acquire-every-measured-source-whole.md +0 -0
- {mostlyright_data-0.29.7 → mostlyright_data-0.29.9}/skills/mr-data-build/references/7-interrogate-ask-the-run-what-it-actually-delivered.md +0 -0
- {mostlyright_data-0.29.7 → mostlyright_data-0.29.9}/skills/mr-data-build/references/8-fix-revise-the-document-and-register-it-again.md +0 -0
- {mostlyright_data-0.29.7 → mostlyright_data-0.29.9}/skills/mr-data-build/references/9-present-only-what-survived-inspection-with-caveats.md +0 -0
- {mostlyright_data-0.29.7 → mostlyright_data-0.29.9}/skills/mr-data-build/references/agent-protocol.md +0 -0
- {mostlyright_data-0.29.7 → mostlyright_data-0.29.9}/skills/mr-data-build/references/autonomous-delivery.md +0 -0
- {mostlyright_data-0.29.7 → mostlyright_data-0.29.9}/skills/mr-data-build/references/before-the-first-tool-call.md +0 -0
- {mostlyright_data-0.29.7 → mostlyright_data-0.29.9}/skills/mr-data-build/references/boundaries.md +0 -0
- {mostlyright_data-0.29.7 → mostlyright_data-0.29.9}/skills/mr-data-build/references/cloud-authentication-preflight.md +0 -0
- {mostlyright_data-0.29.7 → mostlyright_data-0.29.9}/skills/mr-data-build/references/cross-repository-protocol-reference.md +0 -0
- {mostlyright_data-0.29.7 → mostlyright_data-0.29.9}/skills/mr-data-build/references/installation-parity.md +0 -0
- {mostlyright_data-0.29.7 → mostlyright_data-0.29.9}/skills/mr-data-build/references/making-a-table-incremental.md +0 -0
- {mostlyright_data-0.29.7 → mostlyright_data-0.29.9}/skills/mr-data-build/references/narrating-the-run.md +0 -0
- {mostlyright_data-0.29.7 → mostlyright_data-0.29.9}/skills/mr-data-build/references/not-hosted-yet.md +0 -0
- {mostlyright_data-0.29.7 → mostlyright_data-0.29.9}/skills/mr-data-build/references/one-install.md +0 -0
- {mostlyright_data-0.29.7 → mostlyright_data-0.29.9}/skills/mr-data-build/references/prediction-labels.md +0 -0
- {mostlyright_data-0.29.7 → mostlyright_data-0.29.9}/skills/mr-data-build/references/preparing-table-search.md +0 -0
- {mostlyright_data-0.29.7 → mostlyright_data-0.29.9}/skills/mr-data-build/references/promote.md +0 -0
- {mostlyright_data-0.29.7 → mostlyright_data-0.29.9}/skills/mr-data-build/references/readers.md +0 -0
- {mostlyright_data-0.29.7 → mostlyright_data-0.29.9}/skills/mr-data-build/references/receipts.md +0 -0
- {mostlyright_data-0.29.7 → mostlyright_data-0.29.9}/skills/mr-data-build/references/recording-a-stream-venue.md +0 -0
- {mostlyright_data-0.29.7 → mostlyright_data-0.29.9}/skills/mr-data-build/references/recovering-an-import-failure.md +0 -0
- {mostlyright_data-0.29.7 → mostlyright_data-0.29.9}/skills/mr-data-build/references/reference-pages.md +0 -0
- {mostlyright_data-0.29.7 → mostlyright_data-0.29.9}/skills/mr-data-build/references/required-protocol.md +0 -0
- {mostlyright_data-0.29.7 → mostlyright_data-0.29.9}/skills/mr-data-build/references/source-credentials.md +0 -0
- {mostlyright_data-0.29.7 → mostlyright_data-0.29.9}/skills/mr-data-build/references/sources.md +0 -0
- {mostlyright_data-0.29.7 → mostlyright_data-0.29.9}/skills/mr-data-build/references/the-one-thing-to-say-about-the-skill-itself.md +0 -0
- {mostlyright_data-0.29.7 → mostlyright_data-0.29.9}/skills/mr-data-build/references/transforms.md +0 -0
- {mostlyright_data-0.29.7 → mostlyright_data-0.29.9}/skills/mr-data-build/references/user-communication-contract.md +0 -0
- {mostlyright_data-0.29.7 → mostlyright_data-0.29.9}/skills/mr-data-build/references/writing-a-decision-record.md +0 -0
- {mostlyright_data-0.29.7 → mostlyright_data-0.29.9}/skills/mr-data-build/scripts/write_research_notebook.py +0 -0
- {mostlyright_data-0.29.7 → mostlyright_data-0.29.9}/src/mostlyright/data_harness/__init__.py +0 -0
- {mostlyright_data-0.29.7 → mostlyright_data-0.29.9}/src/mostlyright/data_harness/agent_protocol.py +0 -0
- {mostlyright_data-0.29.7 → mostlyright_data-0.29.9}/src/mostlyright/data_harness/canonical.py +0 -0
- {mostlyright_data-0.29.7 → mostlyright_data-0.29.9}/src/mostlyright/data_harness/formats.py +0 -0
- {mostlyright_data-0.29.7 → mostlyright_data-0.29.9}/src/mostlyright/data_harness/hosted_crawler_protocol.py +0 -0
- {mostlyright_data-0.29.7 → mostlyright_data-0.29.9}/src/mostlyright/data_harness/key_seam.py +0 -0
- {mostlyright_data-0.29.7 → mostlyright_data-0.29.9}/src/mostlyright/data_harness/page_coverage.py +0 -0
- {mostlyright_data-0.29.7 → mostlyright_data-0.29.9}/src/mostlyright/data_harness/part_check_evidence.py +0 -0
- {mostlyright_data-0.29.7 → mostlyright_data-0.29.9}/src/mostlyright/data_harness/session_probes.py +0 -0
- {mostlyright_data-0.29.7 → mostlyright_data-0.29.9}/src/mostlyright/data_harness/skill_assets.py +0 -0
- {mostlyright_data-0.29.7 → mostlyright_data-0.29.9}/src/mostlyright/data_harness/table_manifest.py +0 -0
- {mostlyright_data-0.29.7 → mostlyright_data-0.29.9}/src/mostlyright/data_harness/thin/__init__.py +0 -0
- {mostlyright_data-0.29.7 → mostlyright_data-0.29.9}/src/mostlyright/data_harness/thin/acquire.py +0 -0
- {mostlyright_data-0.29.7 → mostlyright_data-0.29.9}/src/mostlyright/data_harness/thin/acquire_cancel.py +0 -0
- {mostlyright_data-0.29.7 → mostlyright_data-0.29.9}/src/mostlyright/data_harness/thin/activity.py +0 -0
- {mostlyright_data-0.29.7 → mostlyright_data-0.29.9}/src/mostlyright/data_harness/thin/approvals.py +0 -0
- {mostlyright_data-0.29.7 → mostlyright_data-0.29.9}/src/mostlyright/data_harness/thin/categories.py +0 -0
- {mostlyright_data-0.29.7 → mostlyright_data-0.29.9}/src/mostlyright/data_harness/thin/commands.py +0 -0
- {mostlyright_data-0.29.7 → mostlyright_data-0.29.9}/src/mostlyright/data_harness/thin/dataset-categories-v1.json +0 -0
- {mostlyright_data-0.29.7 → mostlyright_data-0.29.9}/src/mostlyright/data_harness/thin/download.py +0 -0
- {mostlyright_data-0.29.7 → mostlyright_data-0.29.9}/src/mostlyright/data_harness/thin/fast_features.py +0 -0
- {mostlyright_data-0.29.7 → mostlyright_data-0.29.9}/src/mostlyright/data_harness/thin/narrative.py +0 -0
- {mostlyright_data-0.29.7 → mostlyright_data-0.29.9}/src/mostlyright/data_harness/thin/parity.py +0 -0
- {mostlyright_data-0.29.7 → mostlyright_data-0.29.9}/src/mostlyright/data_harness/thin/probe.py +0 -0
- {mostlyright_data-0.29.7 → mostlyright_data-0.29.9}/src/mostlyright/data_harness/thin/progress_rate.py +0 -0
- {mostlyright_data-0.29.7 → mostlyright_data-0.29.9}/src/mostlyright/data_harness/thin/progress_vocabulary.py +0 -0
- {mostlyright_data-0.29.7 → mostlyright_data-0.29.9}/src/mostlyright/data_harness/thin/propose.py +0 -0
- {mostlyright_data-0.29.7 → mostlyright_data-0.29.9}/src/mostlyright/data_harness/thin/recipe_brief.py +0 -0
- {mostlyright_data-0.29.7 → mostlyright_data-0.29.9}/src/mostlyright/data_harness/thin/recipe_forecast.py +0 -0
- {mostlyright_data-0.29.7 → mostlyright_data-0.29.9}/src/mostlyright/data_harness/thin/recipe_lint.py +0 -0
- {mostlyright_data-0.29.7 → mostlyright_data-0.29.9}/src/mostlyright/data_harness/thin/research.py +0 -0
- {mostlyright_data-0.29.7 → mostlyright_data-0.29.9}/src/mostlyright/data_harness/thin/router.py +0 -0
- {mostlyright_data-0.29.7 → mostlyright_data-0.29.9}/src/mostlyright/data_harness/thin/run_diagnose.py +0 -0
- {mostlyright_data-0.29.7 → mostlyright_data-0.29.9}/src/mostlyright/data_harness/thin/runs.py +0 -0
- {mostlyright_data-0.29.7 → mostlyright_data-0.29.9}/src/mostlyright/data_harness/thin/session.py +0 -0
- {mostlyright_data-0.29.7 → mostlyright_data-0.29.9}/src/mostlyright/data_harness/thin/stream.py +0 -0
- {mostlyright_data-0.29.7 → mostlyright_data-0.29.9}/src/mostlyright/data_harness/thin/stream_venue.py +0 -0
- {mostlyright_data-0.29.7 → mostlyright_data-0.29.9}/src/mostlyright/data_harness/thin/studio_capabilities.py +0 -0
- {mostlyright_data-0.29.7 → mostlyright_data-0.29.9}/src/mostlyright/data_harness/thin/transport.py +0 -0
- {mostlyright_data-0.29.7 → mostlyright_data-0.29.9}/src/mostlyright/data_harness/thin/user_agent.py +0 -0
- {mostlyright_data-0.29.7 → mostlyright_data-0.29.9}/src/mostlyright/data_harness/thin/v4_artifacts.py +0 -0
- {mostlyright_data-0.29.7 → mostlyright_data-0.29.9}/src/mostlyright/data_harness/thin/v4_catalog.py +0 -0
- {mostlyright_data-0.29.7 → mostlyright_data-0.29.9}/src/mostlyright/data_harness/thin/v4_connected.py +0 -0
- {mostlyright_data-0.29.7 → mostlyright_data-0.29.9}/src/mostlyright/data_harness/thin/v4_connections.py +0 -0
- {mostlyright_data-0.29.7 → mostlyright_data-0.29.9}/src/mostlyright/data_harness/thin/v4_dataset_covers.py +0 -0
- {mostlyright_data-0.29.7 → mostlyright_data-0.29.9}/src/mostlyright/data_harness/thin/v4_datasets.py +0 -0
- {mostlyright_data-0.29.7 → mostlyright_data-0.29.9}/src/mostlyright/data_harness/thin/v4_handoff.py +0 -0
- {mostlyright_data-0.29.7 → mostlyright_data-0.29.9}/src/mostlyright/data_harness/thin/v4_narrative.py +0 -0
- {mostlyright_data-0.29.7 → mostlyright_data-0.29.9}/src/mostlyright/data_harness/thin/v4_public.py +0 -0
- {mostlyright_data-0.29.7 → mostlyright_data-0.29.9}/src/mostlyright/data_harness/thin/v4_reader.py +0 -0
- {mostlyright_data-0.29.7 → mostlyright_data-0.29.9}/src/mostlyright/data_harness/thin/v4_search.py +0 -0
- {mostlyright_data-0.29.7 → mostlyright_data-0.29.9}/src/mostlyright/data_harness/thin/v4_secrets.py +0 -0
- {mostlyright_data-0.29.7 → mostlyright_data-0.29.9}/src/mostlyright/data_harness/thin/v4_stream.py +0 -0
- {mostlyright_data-0.29.7 → mostlyright_data-0.29.9}/src/mostlyright/data_harness/thin/v4_tables.py +0 -0
- {mostlyright_data-0.29.7 → mostlyright_data-0.29.9}/src/mostlyright/data_harness/thin/vocabulary.py +0 -0
- {mostlyright_data-0.29.7 → mostlyright_data-0.29.9}/src/mostlyright/data_harness/ux/__init__.py +0 -0
- {mostlyright_data-0.29.7 → mostlyright_data-0.29.9}/src/mostlyright/data_harness/ux/attendance.py +0 -0
- {mostlyright_data-0.29.7 → mostlyright_data-0.29.9}/src/mostlyright/data_harness/ux/clarification.py +0 -0
- {mostlyright_data-0.29.7 → mostlyright_data-0.29.9}/src/mostlyright/data_harness/ux/cloud_auth.py +0 -0
- {mostlyright_data-0.29.7 → mostlyright_data-0.29.9}/src/mostlyright/data_harness/ux/commands/__init__.py +0 -0
- {mostlyright_data-0.29.7 → mostlyright_data-0.29.9}/src/mostlyright/data_harness/ux/commands/auth.py +0 -0
- {mostlyright_data-0.29.7 → mostlyright_data-0.29.9}/src/mostlyright/data_harness/ux/commands/clarify.py +0 -0
- {mostlyright_data-0.29.7 → mostlyright_data-0.29.9}/src/mostlyright/data_harness/ux/commands/login.py +0 -0
- {mostlyright_data-0.29.7 → mostlyright_data-0.29.9}/src/mostlyright/data_harness/ux/commands/whoami.py +0 -0
- {mostlyright_data-0.29.7 → mostlyright_data-0.29.9}/src/mostlyright/data_harness/ux/credential_native.py +0 -0
- {mostlyright_data-0.29.7 → mostlyright_data-0.29.9}/src/mostlyright/data_harness/ux/credential_store.py +0 -0
- {mostlyright_data-0.29.7 → mostlyright_data-0.29.9}/src/mostlyright/data_harness/ux/credentials.py +0 -0
- {mostlyright_data-0.29.7 → mostlyright_data-0.29.9}/src/mostlyright/data_harness/ux/login.py +0 -0
- {mostlyright_data-0.29.7 → mostlyright_data-0.29.9}/src/mostlyright/data_harness/ux/path_kind.py +0 -0
- {mostlyright_data-0.29.7 → mostlyright_data-0.29.9}/src/mostlyright/data_harness/ux/plain_file.py +0 -0
- {mostlyright_data-0.29.7 → mostlyright_data-0.29.9}/src/mostlyright/data_harness/ux/remediation.py +0 -0
- {mostlyright_data-0.29.7 → mostlyright_data-0.29.9}/src/mostlyright/data_harness/ux/render.py +0 -0
{mostlyright_data-0.29.7 → mostlyright_data-0.29.9}/skills/mr-data-build/references/commands.md
RENAMED
|
@@ -18,7 +18,7 @@ gap rather than doing anything, and `export-hosted-candidate`, which is a backen
|
|
|
18
18
|
| `mr-data dataset` | Bring the dataset page into existence before there is anything on it, then fill it in while somebody watches. `dataset create --name TEXT` mints it and prints the `dataset_id`, unless the user's own request already has an empty dataset open, in which case it answers `open_request_reused` with that `dataset_id` and mints nothing (`--separate` mints a new one for a different dataset); `dataset show ID` reads it back; `dataset set ID --name TEXT --topics "a,b,c" --license ID --description-file F` writes the title, the descriptive tags, the SPDX licence and the description under the version it was read at, retrying once if somebody else wrote first, and an empty `--topics` or `--license` takes that value off the page; send `--name` and `--topics` whenever you send `--description-file`, because a description sent on its own can make Studio write a new title and new tags, and read `changed` and `written_by_studio` on the receipt for every field the write moved; a saved write whose public sync fails exits 2 and reports `public_projection_synced: false` — use `dataset sync ID` to retry that sync without rewriting Studio; `dataset note ID --heading H --blocks-file B` writes one cell of the decision record that OUTLIVES every run, and `--list` reads it back; `dataset watch ID` follows the page's own event stream; `dataset activity ID --phase P --message TEXT` says what is happening right now, silently, and is never a chat message and never a cell; `dataset publish ID [--mode public|link|private]` says who can read the dataset — `public` lists it in the public directory and serves it at an address anybody can read, `link` serves it at an unlisted address, `private` takes it back to the workspace — and `dataset publish ID --show` reads that back without changing it; `dataset archive ID --confirm-name TITLE` retires the page and frees its title, deleting nothing. |
|
|
19
19
|
| `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. 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 --digest DIGEST` 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. `mr-data recipe readiness --table TABLE_ID --current-only` reads the revision one table runs now. [Making a table incremental](making-a-table-incremental.md#the-loop-explain-forecast-run-diagnose) says when to use each. |
|
|
20
20
|
| `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. |
|
|
21
|
-
| `mr-data run` | Start one run against a registered recipe, named as `--recipe RECIPE_ID --digest RECIPE_DIGEST` — both required, neither positional, and the digest is the bare hex the registration receipt printed. 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. 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` tries one failed run again when its triple carries `room_fault: true`, re-stating that run's own coordinate
|
|
21
|
+
| `mr-data run` | Start one run against a registered recipe, named as `--recipe RECIPE_ID --digest RECIPE_DIGEST` — both required, neither positional, and the digest is the bare hex the registration receipt printed. 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. 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` tries one failed run 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 refuses with the triple when the recipe was at fault. `--cancel RUN` stops one. |
|
|
22
22
|
| `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. |
|
|
23
23
|
| `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. |
|
|
24
24
|
| `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. |
|
{mostlyright_data-0.29.7 → mostlyright_data-0.29.9}/skills/mr-data-build/references/live-run.md
RENAMED
|
@@ -28,8 +28,9 @@ appends again, and `watch` stops rather than reconnecting.
|
|
|
28
28
|
|
|
29
29
|
**A terminal run is cached against `(recipe, digest, mode, clamps)`.** Re-running that exact
|
|
30
30
|
coordinate replays the stored result rather than making a new attempt — a stored failure included —
|
|
31
|
-
which is why `mr-data run --retry RUN_ID`
|
|
32
|
-
|
|
31
|
+
which is why `mr-data run --retry RUN_ID` names the failed run to Studio rather than re-sending the
|
|
32
|
+
request as it was; the ceilings stay the same unless Studio does not admit the named retry, and
|
|
33
|
+
then the byte ceiling is raised as it was before. It is also why `SANDBOX_MEMORY_BOUNDARY` reads as a source problem and is not one: it names
|
|
33
34
|
the source being fetched, the cause is a clean room with no delegated memory cgroup, it is
|
|
34
35
|
intermittent and per-instance, and `room_fault` is true on that run so nothing has to be inferred
|
|
35
36
|
from the wording. Report the failure once, retry it when supported, then report the replacement
|
{mostlyright_data-0.29.7 → mostlyright_data-0.29.9}/src/mostlyright/data_harness/thin/recipe.py
RENAMED
|
@@ -80,11 +80,9 @@ SHOW_SCHEMA = f"{THIN_SCHEMA_PREFIX}-recipe-read.v1"
|
|
|
80
80
|
READINESS_SCHEMA = f"{THIN_SCHEMA_PREFIX}-recipe-readiness.v1"
|
|
81
81
|
PROPOSE_SCHEMA = f"{THIN_SCHEMA_PREFIX}-recipe-propose.v1"
|
|
82
82
|
|
|
83
|
-
#:
|
|
84
|
-
#:
|
|
85
|
-
|
|
86
|
-
#: it has to clear is the canonical form's.
|
|
87
|
-
MAX_DOCUMENT_BYTES = 4 * 262_144
|
|
83
|
+
#: A plain input file may occupy up to Studio's 2 MiB body ceiling. Before submission,
|
|
84
|
+
#: the complete canonical UTF-8 request envelope must also fit that ceiling.
|
|
85
|
+
MAX_DOCUMENT_BYTES = v4.MAX_RECIPE_REQUEST_BYTES
|
|
88
86
|
|
|
89
87
|
#: ``recipe.schema.json#/$defs/recipe_document``'s required members, in the order the schema lists
|
|
90
88
|
#: them. Checked here before the network, for the reason every early refusal in this client
|
|
@@ -1187,6 +1185,9 @@ def register(
|
|
|
1187
1185
|
"""
|
|
1188
1186
|
|
|
1189
1187
|
document = read_document(Path(args.target))
|
|
1188
|
+
# UUIDs have fixed wire length. Refuse an oversized envelope before credentials,
|
|
1189
|
+
# capability reads or delegation writes; the actual client checks it again.
|
|
1190
|
+
v4.recipe_registration_body(document, "00000000-0000-0000-0000-000000000000")
|
|
1190
1191
|
# New grammar must be refused as unserved before local lint can diagnose its shape.
|
|
1191
1192
|
keyless = any(
|
|
1192
1193
|
capability == "keyless_window" for _, capability in recipe_explain.gated_grammar(document)
|
|
@@ -39,6 +39,7 @@ from mostlyright.data_harness.thin.transport import ThinLaneError
|
|
|
39
39
|
from mostlyright.data_harness.thin.v4 import (
|
|
40
40
|
EXPLAIN_AND_FORECAST_REQUEST_VERSION,
|
|
41
41
|
StudioV4Client,
|
|
42
|
+
check_recipe_request_size,
|
|
42
43
|
identifier,
|
|
43
44
|
)
|
|
44
45
|
|
|
@@ -1231,17 +1232,18 @@ def explain_document_at_studio(
|
|
|
1231
1232
|
nothing, which is what makes it safe to ask before a registration.
|
|
1232
1233
|
"""
|
|
1233
1234
|
|
|
1235
|
+
body = {
|
|
1236
|
+
"schema_version": ROUTES_REQUEST_VERSION,
|
|
1237
|
+
"workspace_id": str(client.session.workspace_id),
|
|
1238
|
+
"document": dict(document),
|
|
1239
|
+
}
|
|
1240
|
+
check_recipe_request_size(body)
|
|
1234
1241
|
try:
|
|
1235
|
-
# The one inherited `_call`
|
|
1236
|
-
# ceiling and refusal translation as every other V4 call.
|
|
1242
|
+
# The one inherited `_call` carries the ordinary response ceiling.
|
|
1237
1243
|
answer = client._call(
|
|
1238
1244
|
"POST",
|
|
1239
1245
|
EXPLAIN_REFRESH_PATH,
|
|
1240
|
-
body=
|
|
1241
|
-
"schema_version": ROUTES_REQUEST_VERSION,
|
|
1242
|
-
"workspace_id": str(client.session.workspace_id),
|
|
1243
|
-
"document": dict(document),
|
|
1244
|
-
},
|
|
1246
|
+
body=body,
|
|
1245
1247
|
expected=(200,),
|
|
1246
1248
|
)
|
|
1247
1249
|
except ThinLaneError as refusal:
|
|
@@ -39,6 +39,7 @@ from collections.abc import Mapping
|
|
|
39
39
|
from typing import Any
|
|
40
40
|
from uuid import UUID
|
|
41
41
|
|
|
42
|
+
from mostlyright.data_harness.canonical import canonical_json_bytes
|
|
42
43
|
from mostlyright.data_harness.thin.runs import StudioApiClient
|
|
43
44
|
from mostlyright.data_harness.thin.transport import ThinLaneError
|
|
44
45
|
|
|
@@ -915,6 +916,35 @@ def identifier(value: str, field: str) -> str:
|
|
|
915
916
|
raise ThinLaneError("THIN_REQUEST_INVALID", f"{value!r} is not a {field}") from error
|
|
916
917
|
|
|
917
918
|
|
|
919
|
+
# Studio's API request-body middleware accepts at most 2 MiB. Bound the complete
|
|
920
|
+
# UTF-8 wire envelope, not the recipe's character count or its formatted file size.
|
|
921
|
+
MAX_RECIPE_REQUEST_BYTES = 2 * 1024 * 1024
|
|
922
|
+
# A GET recipe includes the document plus identifiers and registration metadata.
|
|
923
|
+
# Give that envelope 1 MiB headroom; ordinary JSON routes retain their 1 MiB cap.
|
|
924
|
+
MAX_RECIPE_RESPONSE_BYTES = MAX_RECIPE_REQUEST_BYTES + 1024 * 1024
|
|
925
|
+
|
|
926
|
+
|
|
927
|
+
def check_recipe_request_size(body: Mapping[str, Any]) -> None:
|
|
928
|
+
size = len(canonical_json_bytes(body))
|
|
929
|
+
if size > MAX_RECIPE_REQUEST_BYTES:
|
|
930
|
+
raise ThinLaneError(
|
|
931
|
+
"THIN_RECIPE_REQUEST_TOO_LARGE",
|
|
932
|
+
f"the serialized recipe request is {size} bytes; Studio accepts at most "
|
|
933
|
+
f"{MAX_RECIPE_REQUEST_BYTES} bytes including its request envelope. "
|
|
934
|
+
"Reduce the recipe before submitting it",
|
|
935
|
+
)
|
|
936
|
+
|
|
937
|
+
|
|
938
|
+
def recipe_registration_body(document: Mapping[str, Any], workspace_id: str) -> dict[str, Any]:
|
|
939
|
+
body = {
|
|
940
|
+
"workspace_id": workspace_id,
|
|
941
|
+
"document": dict(document),
|
|
942
|
+
"require_category": True,
|
|
943
|
+
}
|
|
944
|
+
check_recipe_request_size(body)
|
|
945
|
+
return body
|
|
946
|
+
|
|
947
|
+
|
|
918
948
|
class StudioV4Client(StudioApiClient):
|
|
919
949
|
"""The V4 routes, over the transport and the hardening :class:`StudioApiClient` already has.
|
|
920
950
|
|
|
@@ -993,11 +1023,7 @@ class StudioV4Client(StudioApiClient):
|
|
|
993
1023
|
return self._call(
|
|
994
1024
|
"POST",
|
|
995
1025
|
CREATE_RECIPE_PATH,
|
|
996
|
-
body=
|
|
997
|
-
"workspace_id": str(self.session.workspace_id),
|
|
998
|
-
"document": dict(document),
|
|
999
|
-
"require_category": True,
|
|
1000
|
-
},
|
|
1026
|
+
body=recipe_registration_body(document, str(self.session.workspace_id)),
|
|
1001
1027
|
expected=(201,),
|
|
1002
1028
|
)
|
|
1003
1029
|
|
|
@@ -1008,6 +1034,7 @@ class StudioV4Client(StudioApiClient):
|
|
|
1008
1034
|
"GET",
|
|
1009
1035
|
GET_RECIPE_PATH.format(recipe_id=identifier(recipe_id, "recipe identifier")),
|
|
1010
1036
|
expected=(200,),
|
|
1037
|
+
maximum=MAX_RECIPE_RESPONSE_BYTES,
|
|
1011
1038
|
)
|
|
1012
1039
|
|
|
1013
1040
|
def recipe_readiness(
|
|
@@ -1049,14 +1076,16 @@ class StudioV4Client(StudioApiClient):
|
|
|
1049
1076
|
def explain_recipe_refresh(self, document: Mapping[str, Any]) -> dict[str, Any]:
|
|
1050
1077
|
"""Judge one unregistered recipe document for refresh, and read what this Studio serves."""
|
|
1051
1078
|
|
|
1079
|
+
body = {
|
|
1080
|
+
"schema_version": EXPLAIN_AND_FORECAST_REQUEST_VERSION,
|
|
1081
|
+
"workspace_id": str(self.session.workspace_id),
|
|
1082
|
+
"document": dict(document),
|
|
1083
|
+
}
|
|
1084
|
+
check_recipe_request_size(body)
|
|
1052
1085
|
return self._call(
|
|
1053
1086
|
"POST",
|
|
1054
1087
|
EXPLAIN_RECIPE_REFRESH_PATH,
|
|
1055
|
-
body=
|
|
1056
|
-
"schema_version": EXPLAIN_AND_FORECAST_REQUEST_VERSION,
|
|
1057
|
-
"workspace_id": str(self.session.workspace_id),
|
|
1058
|
-
"document": dict(document),
|
|
1059
|
-
},
|
|
1088
|
+
body=body,
|
|
1060
1089
|
expected=(200,),
|
|
1061
1090
|
)
|
|
1062
1091
|
|
{mostlyright_data-0.29.7 → mostlyright_data-0.29.9}/src/mostlyright/data_harness/thin/v4_query.py
RENAMED
|
@@ -54,7 +54,6 @@ from mostlyright.data_harness.thin.session import (
|
|
|
54
54
|
)
|
|
55
55
|
from mostlyright.data_harness.thin.transport import ThinLaneError, UrlLibTransport
|
|
56
56
|
from mostlyright.data_harness.thin.v4 import (
|
|
57
|
-
GET_RECIPE_PATH,
|
|
58
57
|
GET_RUN_PATH,
|
|
59
58
|
GET_RUN_QUERY_PATH,
|
|
60
59
|
RUN_QUERY_PATH,
|
|
@@ -278,7 +277,7 @@ class StudioV4QueryClient(StudioV4Client):
|
|
|
278
277
|
def recipe_source_ids(self, recipe_id: str) -> list[str]:
|
|
279
278
|
"""The sources a recipe registered, which a session opened for its dataset may probe."""
|
|
280
279
|
|
|
281
|
-
record = self.
|
|
280
|
+
record = self.recipe(recipe_id)
|
|
282
281
|
listed = record.get("source_ids")
|
|
283
282
|
sources = (
|
|
284
283
|
[item for item in listed if isinstance(item, str) and item]
|
{mostlyright_data-0.29.7 → mostlyright_data-0.29.9}/src/mostlyright/data_harness/thin/v4_runs.py
RENAMED
|
@@ -129,8 +129,10 @@ DISCARD_HISTORY_FLAG = "--discard-snapshot-history"
|
|
|
129
129
|
#: ⚠ AND ANOTHER ATTEMPT NEEDS A DIFFERENT COORDINATE. Studio derives a run's identity from
|
|
130
130
|
#: ``(recipe_id, recipe_digest, mode, clamps, resource_class)`` and replays a terminal result for
|
|
131
131
|
#: an identical command, so re-issuing the same request returns the same failure without waking a
|
|
132
|
-
#: worker. ``mr-data run --retry RUN_ID`` is what turns that into one command
|
|
133
|
-
#:
|
|
132
|
+
#: worker. ``mr-data run --retry RUN_ID`` is what turns that into one command: it names the failed
|
|
133
|
+
#: run as ``retry_of_run_id``, which Studio folds into the identity, and the ceilings go out as
|
|
134
|
+
#: they were. See :func:`retry_clamps` for the coordinate it moves instead when Studio answers
|
|
135
|
+
#: ``RUN_NOT_RETRYABLE`` or a stored run that is already over.
|
|
134
136
|
ROOM_FAULT_CODES: frozenset[str] = frozenset(
|
|
135
137
|
{
|
|
136
138
|
"EXECUTION_LEASE_EXPIRED",
|
|
@@ -591,9 +593,12 @@ def declare_run_arguments(parser: argparse.ArgumentParser) -> None:
|
|
|
591
593
|
"--retry",
|
|
592
594
|
metavar="RUN_ID",
|
|
593
595
|
help="try this failed run again, when what failed was the room rather than the recipe; "
|
|
594
|
-
"the same recipe, digest, mode and ceilings go out
|
|
595
|
-
"
|
|
596
|
-
"that
|
|
596
|
+
"the same recipe, digest, mode and ceilings go out naming the failed run, so Studio "
|
|
597
|
+
"starts a new attempt rather than replaying the stored failure. When Studio does not "
|
|
598
|
+
"admit that for the run, or answers with a stored run that is already over, the "
|
|
599
|
+
"command goes out once more under a byte clamp raised above what the document "
|
|
600
|
+
"declares. A stored run that is queued or running is printed as it is and no second "
|
|
601
|
+
"run is started",
|
|
597
602
|
)
|
|
598
603
|
parser.add_argument(
|
|
599
604
|
"--approve-full",
|
|
@@ -1289,12 +1294,45 @@ def fresh_full_record(run: Mapping[str, Any]) -> bool:
|
|
|
1289
1294
|
)
|
|
1290
1295
|
|
|
1291
1296
|
|
|
1297
|
+
#: The refusals of a retry that named the failed run after which the same retry goes out once
|
|
1298
|
+
#: more under a moved byte clamp, which is what this command sent before it named the run.
|
|
1299
|
+
#: ``RUN_NOT_RETRYABLE`` is Studio declining ``retry_of_run_id`` for this run: its list of
|
|
1300
|
+
#: platform failures is its own, and a Studio that has not yet deployed a code this client reads
|
|
1301
|
+
#: as a room fault answers with it. The snapshot-history refusal is here because the command it
|
|
1302
|
+
#: prints is re-typed without ``retry_of_run_id`` (there is no flag for it), so that command has
|
|
1303
|
+
#: to carry a coordinate of its own.
|
|
1304
|
+
#:
|
|
1305
|
+
#: ``KEEL_ENGINE_REQUIRED`` is here because naming the run can cause it. Studio never hands a
|
|
1306
|
+
#: retry of a Python run to Keel (``v4/runs.py``, ``retry_of_python_run``), and then refuses a
|
|
1307
|
+
#: recipe the Python engine does not build. The body this command sent before it named the run
|
|
1308
|
+
#: carries no ``retry_of_run_id``, so admission chooses the engine again and the run can start.
|
|
1309
|
+
#: When the second answer is the same refusal, it is raised as it is.
|
|
1310
|
+
_CLAMP_RETRY_CODES: frozenset[str] = frozenset(
|
|
1311
|
+
{"RUN_NOT_RETRYABLE", SNAPSHOT_HISTORY_CODE, "KEEL_ENGINE_REQUIRED"}
|
|
1312
|
+
)
|
|
1313
|
+
|
|
1314
|
+
#: The states of a run answered to the named retry that mean no new attempt started. Studio's own
|
|
1315
|
+
#: automatic resume of a lost progressive full starts its successor with the body the named retry
|
|
1316
|
+
#: sends (``apps/api/.../v4/auto_resume.py``: the lost run's clamps and resource class, with
|
|
1317
|
+
#: ``resume_capture_run_id`` and ``retry_of_run_id`` both naming it), so once that successor
|
|
1318
|
+
#: exists the named retry derives its run id and Studio answers ``201`` with the successor's
|
|
1319
|
+
#: stored record. When that record is already over, the retry goes out under the moved byte
|
|
1320
|
+
#: clamp, which is a coordinate the successor does not hold.
|
|
1321
|
+
#:
|
|
1322
|
+
#: ``succeeded`` is a member for the same reason as the other two: a run that is over is not the
|
|
1323
|
+
#: attempt this command was asked for. A plain start of the same command is answered with the
|
|
1324
|
+
#: failed run's stored record, so without this the table could not be built again from this
|
|
1325
|
+
#: command once a successor had succeeded, and 0.29.7 started a run here.
|
|
1326
|
+
_STORED_END_STATUSES: frozenset[str] = TERMINAL_RUN_STATUSES
|
|
1327
|
+
|
|
1328
|
+
|
|
1292
1329
|
def retry_body(
|
|
1293
1330
|
run: Mapping[str, Any],
|
|
1294
1331
|
run_id: str,
|
|
1295
1332
|
*,
|
|
1296
1333
|
declared_bytes: int = 0,
|
|
1297
1334
|
fresh_read_control: bool = False,
|
|
1335
|
+
clamp_moved: bool = False,
|
|
1298
1336
|
) -> dict[str, Any]:
|
|
1299
1337
|
"""The ``create_run_command`` that is this failed run again, rebuilt off its own record.
|
|
1300
1338
|
|
|
@@ -1302,6 +1340,12 @@ def retry_body(
|
|
|
1302
1340
|
nothing else: the whole point of ``--retry RUN_ID`` is that it does not require somebody to
|
|
1303
1341
|
have kept the recipe, the digest, the mode and the ceilings the first attempt went out with.
|
|
1304
1342
|
|
|
1343
|
+
THE FAILED RUN IS NAMED, AND THE CEILINGS ARE THE ONES IT CARRIED. ``retry_of_run_id`` enters
|
|
1344
|
+
the identity Studio derives, so the command is a new attempt without any ceiling changing
|
|
1345
|
+
(planning#234). ``clamp_moved`` builds the other body instead: no ``retry_of_run_id``, and
|
|
1346
|
+
:func:`retry_clamps` in place of the stated ceilings, for a Studio that answered
|
|
1347
|
+
``RUN_NOT_RETRYABLE`` to the first.
|
|
1348
|
+
|
|
1305
1349
|
⚠ A FRESH FULL IS RETRIED FRESH, AND THE BODY SAYS SO. Studio already keeps a resumed chain
|
|
1306
1350
|
on the answer lineage its origin was admitted with, so a retry of a fresh full reads fresh
|
|
1307
1351
|
whatever this body says; stating ``reuse_saved_answers: false`` makes the body, and the rerun
|
|
@@ -1319,7 +1363,16 @@ def retry_body(
|
|
|
1319
1363
|
"THIN_RESPONSE_INVALID", f"Studio reported run {run_id} without a {member}"
|
|
1320
1364
|
)
|
|
1321
1365
|
body[member] = stated
|
|
1322
|
-
|
|
1366
|
+
if clamp_moved:
|
|
1367
|
+
body["clamps"] = retry_clamps(run, declared_bytes=declared_bytes)
|
|
1368
|
+
else:
|
|
1369
|
+
carried = run.get("clamps")
|
|
1370
|
+
clamps = dict(carried) if isinstance(carried, Mapping) else {}
|
|
1371
|
+
if "window" in clamps:
|
|
1372
|
+
clamps["window"] = _command_window(clamps["window"])
|
|
1373
|
+
if clamps:
|
|
1374
|
+
body["clamps"] = clamps
|
|
1375
|
+
body["retry_of_run_id"] = identifier(run_id, "run identifier")
|
|
1323
1376
|
if body["mode"] == "full":
|
|
1324
1377
|
body["progressive"] = True
|
|
1325
1378
|
if run.get("progressive") is True:
|
|
@@ -1395,7 +1448,67 @@ def retry(run_id: str, *, client: StudioV4RunClient) -> dict[str, Any]:
|
|
|
1395
1448
|
"--mode replay --sources-from RUN_ID once the room is well, or build the recipe "
|
|
1396
1449
|
"rather than replaying it",
|
|
1397
1450
|
)
|
|
1398
|
-
# ⚠ THE
|
|
1451
|
+
# ⚠ THE CAPABILITY IS READ ONLY WHEN IT CAN CHANGE THE BODY. A retry of anything but a fresh
|
|
1452
|
+
# full sends the same body whatever this Studio serves, so asking would be a round trip that
|
|
1453
|
+
# decides nothing.
|
|
1454
|
+
fresh_read_control = False
|
|
1455
|
+
if fresh_full_record(run):
|
|
1456
|
+
table_id = run.get("table_id")
|
|
1457
|
+
if isinstance(table_id, str) and table_id:
|
|
1458
|
+
fresh_read_control = (
|
|
1459
|
+
table_capabilities(client, identifier(table_id, "table identifier")).get(
|
|
1460
|
+
FRESH_READ_CONTROL
|
|
1461
|
+
)
|
|
1462
|
+
is True
|
|
1463
|
+
)
|
|
1464
|
+
body = retry_body(run, run_id, fresh_read_control=fresh_read_control)
|
|
1465
|
+
try:
|
|
1466
|
+
started = client.create_run(body)
|
|
1467
|
+
except ThinLaneError as refusal:
|
|
1468
|
+
if getattr(refusal, "studio_code", None) in _CLAMP_RETRY_CODES:
|
|
1469
|
+
return _retry_under_a_moved_clamp(
|
|
1470
|
+
run, run_id, client=client, triple=triple, fresh_read_control=fresh_read_control
|
|
1471
|
+
)
|
|
1472
|
+
held = _held_for_confirmation(refusal, body)
|
|
1473
|
+
if held is None:
|
|
1474
|
+
raise
|
|
1475
|
+
# ⚠ SETTLED BY THE HELD RUN'S OWN ID. A re-typed start has no flag for
|
|
1476
|
+
# `retry_of_run_id`, so it would name the failed run's coordinate and Studio would answer
|
|
1477
|
+
# with the stored failure. The refusal names the run Studio held, and `--confirm-held`
|
|
1478
|
+
# confirms that exact record.
|
|
1479
|
+
held["confirm_command"] = confirm_held_command(
|
|
1480
|
+
identifier(str(held["run_id"]), "run identifier")
|
|
1481
|
+
)
|
|
1482
|
+
held["retry_of"] = run_id
|
|
1483
|
+
held["retried_failure"] = triple
|
|
1484
|
+
return held
|
|
1485
|
+
if started.get("status") in _STORED_END_STATUSES:
|
|
1486
|
+
# ⚠ A RUN THAT IS ALREADY OVER IS NOT ANOTHER ATTEMPT. Studio answered the named retry
|
|
1487
|
+
# with a record it had stored under the same identity (see `_STORED_END_STATUSES`), so
|
|
1488
|
+
# printing it as `run_retried` would hand back a stored failure as the retry
|
|
1489
|
+
# (planning#234). The moved clamp is the coordinate 0.29.7 sent, and it starts a run.
|
|
1490
|
+
return _retry_under_a_moved_clamp(
|
|
1491
|
+
run, run_id, client=client, triple=triple, fresh_read_control=fresh_read_control
|
|
1492
|
+
)
|
|
1493
|
+
return _retried(client, started, run_id=run_id, triple=triple, clamp_moved=False)
|
|
1494
|
+
|
|
1495
|
+
|
|
1496
|
+
def _retry_under_a_moved_clamp(
|
|
1497
|
+
run: Mapping[str, Any],
|
|
1498
|
+
run_id: str,
|
|
1499
|
+
*,
|
|
1500
|
+
client: StudioV4RunClient,
|
|
1501
|
+
triple: Mapping[str, Any],
|
|
1502
|
+
fresh_read_control: bool,
|
|
1503
|
+
) -> dict[str, Any]:
|
|
1504
|
+
"""The same retry without ``retry_of_run_id``, under the one ceiling that can move.
|
|
1505
|
+
|
|
1506
|
+
What ``--retry`` sent before it named the failed run, kept for a Studio that answers
|
|
1507
|
+
``RUN_NOT_RETRYABLE`` or ``KEEL_ENGINE_REQUIRED`` to the named retry, or answers it with a
|
|
1508
|
+
stored run that is already over.
|
|
1509
|
+
"""
|
|
1510
|
+
|
|
1511
|
+
# ⚠ THE RECIPE IS READ BEFORE THIS BODY IS BUILT, and that round trip is the price of the
|
|
1399
1512
|
# clamp being inert. Studio projects from the document's own declared ceilings, so a clamp
|
|
1400
1513
|
# chosen without reading them is a clamp that might lower what the run projects -- and
|
|
1401
1514
|
# `projected_bytes` is what the spend and sample-first thresholds are read against.
|
|
@@ -1411,24 +1524,12 @@ def retry(run_id: str, *, client: StudioV4RunClient) -> dict[str, Any]:
|
|
|
1411
1524
|
"Studio answered without the recipe document this run was started against, so the "
|
|
1412
1525
|
"bytes it is projected against could not be read and a retry cannot be sized",
|
|
1413
1526
|
)
|
|
1414
|
-
# ⚠ THE CAPABILITY IS READ ONLY WHEN IT CAN CHANGE THE BODY. A retry of anything but a fresh
|
|
1415
|
-
# full sends the same body whatever this Studio serves, so asking would be a round trip that
|
|
1416
|
-
# decides nothing.
|
|
1417
|
-
fresh_read_control = False
|
|
1418
|
-
if fresh_full_record(run):
|
|
1419
|
-
table_id = run.get("table_id")
|
|
1420
|
-
if isinstance(table_id, str) and table_id:
|
|
1421
|
-
fresh_read_control = (
|
|
1422
|
-
table_capabilities(client, identifier(table_id, "table identifier")).get(
|
|
1423
|
-
FRESH_READ_CONTROL
|
|
1424
|
-
)
|
|
1425
|
-
is True
|
|
1426
|
-
)
|
|
1427
1527
|
body = retry_body(
|
|
1428
1528
|
run,
|
|
1429
1529
|
run_id,
|
|
1430
1530
|
declared_bytes=declared_source_bytes(document),
|
|
1431
1531
|
fresh_read_control=fresh_read_control,
|
|
1532
|
+
clamp_moved=True,
|
|
1432
1533
|
)
|
|
1433
1534
|
try:
|
|
1434
1535
|
started = client.create_run(body)
|
|
@@ -1450,10 +1551,25 @@ def retry(run_id: str, *, client: StudioV4RunClient) -> dict[str, Any]:
|
|
|
1450
1551
|
held["retry_of"] = run_id
|
|
1451
1552
|
held["retried_failure"] = triple
|
|
1452
1553
|
return held
|
|
1554
|
+
return _retried(client, started, run_id=run_id, triple=triple, clamp_moved=True)
|
|
1555
|
+
|
|
1556
|
+
|
|
1557
|
+
def _retried(
|
|
1558
|
+
client: StudioV4RunClient,
|
|
1559
|
+
started: Mapping[str, Any],
|
|
1560
|
+
*,
|
|
1561
|
+
run_id: str,
|
|
1562
|
+
triple: Mapping[str, Any],
|
|
1563
|
+
clamp_moved: bool,
|
|
1564
|
+
) -> dict[str, Any]:
|
|
1565
|
+
"""The receipt of a retry Studio started, with the cell that says why the run exists."""
|
|
1566
|
+
|
|
1453
1567
|
payload = _started(started, client.session, status="run_retried")
|
|
1454
1568
|
payload["retry_of"] = run_id
|
|
1455
1569
|
payload["retried_failure"] = triple
|
|
1456
|
-
payload["note"] = _retry_note(
|
|
1570
|
+
payload["note"] = _retry_note(
|
|
1571
|
+
client, started, run_id=run_id, triple=triple, clamp_moved=clamp_moved
|
|
1572
|
+
)
|
|
1457
1573
|
return payload
|
|
1458
1574
|
|
|
1459
1575
|
|
|
@@ -1497,6 +1613,7 @@ def _retry_note(
|
|
|
1497
1613
|
*,
|
|
1498
1614
|
run_id: str,
|
|
1499
1615
|
triple: Mapping[str, Any],
|
|
1616
|
+
clamp_moved: bool = False,
|
|
1500
1617
|
) -> dict[str, Any] | None:
|
|
1501
1618
|
"""One cell on the NEW run saying which fault it is another attempt at, or ``None``.
|
|
1502
1619
|
|
|
@@ -1524,17 +1641,31 @@ def _retry_note(
|
|
|
1524
1641
|
except ThinLaneError:
|
|
1525
1642
|
return None
|
|
1526
1643
|
try:
|
|
1527
|
-
cell = client.append_cell(
|
|
1644
|
+
cell = client.append_cell(
|
|
1645
|
+
fresh, body=_retry_cell(client, fresh, run_id, triple, clamp_moved=clamp_moved)
|
|
1646
|
+
)
|
|
1528
1647
|
except ThinLaneError as refusal:
|
|
1529
1648
|
return {"written": False, "refusal": {"code": refusal.code, "detail": refusal.detail}}
|
|
1530
1649
|
return {"written": True, "cell_id": cell.get("cell_id")}
|
|
1531
1650
|
|
|
1532
1651
|
|
|
1533
1652
|
def _retry_cell(
|
|
1534
|
-
client: StudioV4RunClient,
|
|
1653
|
+
client: StudioV4RunClient,
|
|
1654
|
+
fresh: str,
|
|
1655
|
+
run_id: str,
|
|
1656
|
+
triple: Mapping[str, Any],
|
|
1657
|
+
*,
|
|
1658
|
+
clamp_moved: bool = False,
|
|
1535
1659
|
) -> dict[str, Any]:
|
|
1536
1660
|
"""The append command that cell is, composed where its refusals are already being caught."""
|
|
1537
1661
|
|
|
1662
|
+
coordinate = (
|
|
1663
|
+
"A byte ceiling above anything the sources can deliver gives the attempt a coordinate "
|
|
1664
|
+
"of its own; an identical command would have replayed the stored failure."
|
|
1665
|
+
if clamp_moved
|
|
1666
|
+
else "The attempt names the failed run and carries the same ceilings; an identical "
|
|
1667
|
+
"command that did not name it would have replayed the stored failure."
|
|
1668
|
+
)
|
|
1538
1669
|
return run_cell_body(
|
|
1539
1670
|
workspace_id=client.session.workspace_id,
|
|
1540
1671
|
run_id=fresh,
|
|
@@ -1544,9 +1675,8 @@ def _retry_cell(
|
|
|
1544
1675
|
f"Run {run_id} failed at the {triple['failed_stage']} stage with "
|
|
1545
1676
|
f"{triple['failure_code']}: {triple['failure_detail']}\n\n"
|
|
1546
1677
|
"That code is about the room the run landed in rather than about this recipe, so the "
|
|
1547
|
-
"document is unchanged.
|
|
1548
|
-
"
|
|
1549
|
-
"stored failure. Full retries use progressive acquisition. When the failed full was "
|
|
1678
|
+
f"document is unchanged. {coordinate} "
|
|
1679
|
+
"Full retries use progressive acquisition. When the failed full was "
|
|
1550
1680
|
"already progressive, the retry also names it as the capture ancestor so Studio can "
|
|
1551
1681
|
"reuse compatible sealed pages."
|
|
1552
1682
|
),
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{mostlyright_data-0.29.7 → mostlyright_data-0.29.9}/skills/mr-data-build/references/boundaries.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{mostlyright_data-0.29.7 → mostlyright_data-0.29.9}/skills/mr-data-build/references/one-install.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{mostlyright_data-0.29.7 → mostlyright_data-0.29.9}/skills/mr-data-build/references/promote.md
RENAMED
|
File without changes
|
{mostlyright_data-0.29.7 → mostlyright_data-0.29.9}/skills/mr-data-build/references/readers.md
RENAMED
|
File without changes
|
{mostlyright_data-0.29.7 → mostlyright_data-0.29.9}/skills/mr-data-build/references/receipts.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{mostlyright_data-0.29.7 → mostlyright_data-0.29.9}/skills/mr-data-build/references/sources.md
RENAMED
|
File without changes
|
|
File without changes
|
{mostlyright_data-0.29.7 → mostlyright_data-0.29.9}/skills/mr-data-build/references/transforms.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{mostlyright_data-0.29.7 → mostlyright_data-0.29.9}/src/mostlyright/data_harness/__init__.py
RENAMED
|
File without changes
|
{mostlyright_data-0.29.7 → mostlyright_data-0.29.9}/src/mostlyright/data_harness/agent_protocol.py
RENAMED
|
File without changes
|
{mostlyright_data-0.29.7 → mostlyright_data-0.29.9}/src/mostlyright/data_harness/canonical.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{mostlyright_data-0.29.7 → mostlyright_data-0.29.9}/src/mostlyright/data_harness/key_seam.py
RENAMED
|
File without changes
|
{mostlyright_data-0.29.7 → mostlyright_data-0.29.9}/src/mostlyright/data_harness/page_coverage.py
RENAMED
|
File without changes
|
|
File without changes
|
{mostlyright_data-0.29.7 → mostlyright_data-0.29.9}/src/mostlyright/data_harness/session_probes.py
RENAMED
|
File without changes
|
{mostlyright_data-0.29.7 → mostlyright_data-0.29.9}/src/mostlyright/data_harness/skill_assets.py
RENAMED
|
File without changes
|
{mostlyright_data-0.29.7 → mostlyright_data-0.29.9}/src/mostlyright/data_harness/table_manifest.py
RENAMED
|
File without changes
|
{mostlyright_data-0.29.7 → mostlyright_data-0.29.9}/src/mostlyright/data_harness/thin/__init__.py
RENAMED
|
File without changes
|
{mostlyright_data-0.29.7 → mostlyright_data-0.29.9}/src/mostlyright/data_harness/thin/acquire.py
RENAMED
|
File without changes
|
|
File without changes
|
{mostlyright_data-0.29.7 → mostlyright_data-0.29.9}/src/mostlyright/data_harness/thin/activity.py
RENAMED
|
File without changes
|
{mostlyright_data-0.29.7 → mostlyright_data-0.29.9}/src/mostlyright/data_harness/thin/approvals.py
RENAMED
|
File without changes
|
{mostlyright_data-0.29.7 → mostlyright_data-0.29.9}/src/mostlyright/data_harness/thin/categories.py
RENAMED
|
File without changes
|
{mostlyright_data-0.29.7 → mostlyright_data-0.29.9}/src/mostlyright/data_harness/thin/commands.py
RENAMED
|
File without changes
|
|
File without changes
|
{mostlyright_data-0.29.7 → mostlyright_data-0.29.9}/src/mostlyright/data_harness/thin/download.py
RENAMED
|
File without changes
|
|
File without changes
|
{mostlyright_data-0.29.7 → mostlyright_data-0.29.9}/src/mostlyright/data_harness/thin/narrative.py
RENAMED
|
File without changes
|
{mostlyright_data-0.29.7 → mostlyright_data-0.29.9}/src/mostlyright/data_harness/thin/parity.py
RENAMED
|
File without changes
|
{mostlyright_data-0.29.7 → mostlyright_data-0.29.9}/src/mostlyright/data_harness/thin/probe.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{mostlyright_data-0.29.7 → mostlyright_data-0.29.9}/src/mostlyright/data_harness/thin/propose.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{mostlyright_data-0.29.7 → mostlyright_data-0.29.9}/src/mostlyright/data_harness/thin/recipe_lint.py
RENAMED
|
File without changes
|
{mostlyright_data-0.29.7 → mostlyright_data-0.29.9}/src/mostlyright/data_harness/thin/research.py
RENAMED
|
File without changes
|
{mostlyright_data-0.29.7 → mostlyright_data-0.29.9}/src/mostlyright/data_harness/thin/router.py
RENAMED
|
File without changes
|
|
File without changes
|
{mostlyright_data-0.29.7 → mostlyright_data-0.29.9}/src/mostlyright/data_harness/thin/runs.py
RENAMED
|
File without changes
|
{mostlyright_data-0.29.7 → mostlyright_data-0.29.9}/src/mostlyright/data_harness/thin/session.py
RENAMED
|
File without changes
|
{mostlyright_data-0.29.7 → mostlyright_data-0.29.9}/src/mostlyright/data_harness/thin/stream.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{mostlyright_data-0.29.7 → mostlyright_data-0.29.9}/src/mostlyright/data_harness/thin/transport.py
RENAMED
|
File without changes
|
{mostlyright_data-0.29.7 → mostlyright_data-0.29.9}/src/mostlyright/data_harness/thin/user_agent.py
RENAMED
|
File without changes
|
|
File without changes
|
{mostlyright_data-0.29.7 → mostlyright_data-0.29.9}/src/mostlyright/data_harness/thin/v4_catalog.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{mostlyright_data-0.29.7 → mostlyright_data-0.29.9}/src/mostlyright/data_harness/thin/v4_datasets.py
RENAMED
|
File without changes
|
{mostlyright_data-0.29.7 → mostlyright_data-0.29.9}/src/mostlyright/data_harness/thin/v4_handoff.py
RENAMED
|
File without changes
|
|
File without changes
|
{mostlyright_data-0.29.7 → mostlyright_data-0.29.9}/src/mostlyright/data_harness/thin/v4_public.py
RENAMED
|
File without changes
|
{mostlyright_data-0.29.7 → mostlyright_data-0.29.9}/src/mostlyright/data_harness/thin/v4_reader.py
RENAMED
|
File without changes
|
{mostlyright_data-0.29.7 → mostlyright_data-0.29.9}/src/mostlyright/data_harness/thin/v4_search.py
RENAMED
|
File without changes
|
{mostlyright_data-0.29.7 → mostlyright_data-0.29.9}/src/mostlyright/data_harness/thin/v4_secrets.py
RENAMED
|
File without changes
|
{mostlyright_data-0.29.7 → mostlyright_data-0.29.9}/src/mostlyright/data_harness/thin/v4_stream.py
RENAMED
|
File without changes
|
{mostlyright_data-0.29.7 → mostlyright_data-0.29.9}/src/mostlyright/data_harness/thin/v4_tables.py
RENAMED
|
File without changes
|
{mostlyright_data-0.29.7 → mostlyright_data-0.29.9}/src/mostlyright/data_harness/thin/vocabulary.py
RENAMED
|
File without changes
|
{mostlyright_data-0.29.7 → mostlyright_data-0.29.9}/src/mostlyright/data_harness/ux/__init__.py
RENAMED
|
File without changes
|
{mostlyright_data-0.29.7 → mostlyright_data-0.29.9}/src/mostlyright/data_harness/ux/attendance.py
RENAMED
|
File without changes
|
{mostlyright_data-0.29.7 → mostlyright_data-0.29.9}/src/mostlyright/data_harness/ux/clarification.py
RENAMED
|
File without changes
|
{mostlyright_data-0.29.7 → mostlyright_data-0.29.9}/src/mostlyright/data_harness/ux/cloud_auth.py
RENAMED
|
File without changes
|
|
File without changes
|
{mostlyright_data-0.29.7 → mostlyright_data-0.29.9}/src/mostlyright/data_harness/ux/commands/auth.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{mostlyright_data-0.29.7 → mostlyright_data-0.29.9}/src/mostlyright/data_harness/ux/credentials.py
RENAMED
|
File without changes
|
{mostlyright_data-0.29.7 → mostlyright_data-0.29.9}/src/mostlyright/data_harness/ux/login.py
RENAMED
|
File without changes
|
{mostlyright_data-0.29.7 → mostlyright_data-0.29.9}/src/mostlyright/data_harness/ux/path_kind.py
RENAMED
|
File without changes
|
{mostlyright_data-0.29.7 → mostlyright_data-0.29.9}/src/mostlyright/data_harness/ux/plain_file.py
RENAMED
|
File without changes
|
{mostlyright_data-0.29.7 → mostlyright_data-0.29.9}/src/mostlyright/data_harness/ux/remediation.py
RENAMED
|
File without changes
|
{mostlyright_data-0.29.7 → mostlyright_data-0.29.9}/src/mostlyright/data_harness/ux/render.py
RENAMED
|
File without changes
|