mostlyright-data 0.19.1__tar.gz → 0.19.2__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.19.1 → mostlyright_data-0.19.2}/PKG-INFO +7 -5
- {mostlyright_data-0.19.1 → mostlyright_data-0.19.2}/README.md +6 -4
- {mostlyright_data-0.19.1 → mostlyright_data-0.19.2}/pyproject.toml +1 -1
- {mostlyright_data-0.19.1 → mostlyright_data-0.19.2}/skills/mr-data-build/SKILL.md +236 -133
- {mostlyright_data-0.19.1 → mostlyright_data-0.19.2}/skills/mr-data-build/agents/openai.yaml +1 -1
- {mostlyright_data-0.19.1 → mostlyright_data-0.19.2}/.gitignore +0 -0
- {mostlyright_data-0.19.1 → mostlyright_data-0.19.2}/scripts/hatch_build.py +0 -0
- {mostlyright_data-0.19.1 → mostlyright_data-0.19.2}/skills/mr-data-build/scripts/write_research_notebook.py +0 -0
- {mostlyright_data-0.19.1 → mostlyright_data-0.19.2}/src/mostlyright/data_harness/__init__.py +0 -0
- {mostlyright_data-0.19.1 → mostlyright_data-0.19.2}/src/mostlyright/data_harness/canonical.py +0 -0
- {mostlyright_data-0.19.1 → mostlyright_data-0.19.2}/src/mostlyright/data_harness/formats.py +0 -0
- {mostlyright_data-0.19.1 → mostlyright_data-0.19.2}/src/mostlyright/data_harness/hosted_crawler_protocol.py +0 -0
- {mostlyright_data-0.19.1 → mostlyright_data-0.19.2}/src/mostlyright/data_harness/key_seam.py +0 -0
- {mostlyright_data-0.19.1 → mostlyright_data-0.19.2}/src/mostlyright/data_harness/page_coverage.py +0 -0
- {mostlyright_data-0.19.1 → mostlyright_data-0.19.2}/src/mostlyright/data_harness/part_check_evidence.py +0 -0
- {mostlyright_data-0.19.1 → mostlyright_data-0.19.2}/src/mostlyright/data_harness/session_probes.py +0 -0
- {mostlyright_data-0.19.1 → mostlyright_data-0.19.2}/src/mostlyright/data_harness/skill_assets.py +0 -0
- {mostlyright_data-0.19.1 → mostlyright_data-0.19.2}/src/mostlyright/data_harness/table_manifest.py +0 -0
- {mostlyright_data-0.19.1 → mostlyright_data-0.19.2}/src/mostlyright/data_harness/thin/__init__.py +0 -0
- {mostlyright_data-0.19.1 → mostlyright_data-0.19.2}/src/mostlyright/data_harness/thin/acquire.py +0 -0
- {mostlyright_data-0.19.1 → mostlyright_data-0.19.2}/src/mostlyright/data_harness/thin/acquire_cancel.py +0 -0
- {mostlyright_data-0.19.1 → mostlyright_data-0.19.2}/src/mostlyright/data_harness/thin/activity.py +0 -0
- {mostlyright_data-0.19.1 → mostlyright_data-0.19.2}/src/mostlyright/data_harness/thin/approvals.py +0 -0
- {mostlyright_data-0.19.1 → mostlyright_data-0.19.2}/src/mostlyright/data_harness/thin/categories.py +0 -0
- {mostlyright_data-0.19.1 → mostlyright_data-0.19.2}/src/mostlyright/data_harness/thin/commands.py +0 -0
- {mostlyright_data-0.19.1 → mostlyright_data-0.19.2}/src/mostlyright/data_harness/thin/dataset-categories-v1.json +0 -0
- {mostlyright_data-0.19.1 → mostlyright_data-0.19.2}/src/mostlyright/data_harness/thin/download.py +0 -0
- {mostlyright_data-0.19.1 → mostlyright_data-0.19.2}/src/mostlyright/data_harness/thin/narrative.py +0 -0
- {mostlyright_data-0.19.1 → mostlyright_data-0.19.2}/src/mostlyright/data_harness/thin/parity.py +0 -0
- {mostlyright_data-0.19.1 → mostlyright_data-0.19.2}/src/mostlyright/data_harness/thin/probe.py +0 -0
- {mostlyright_data-0.19.1 → mostlyright_data-0.19.2}/src/mostlyright/data_harness/thin/progress_vocabulary.py +0 -0
- {mostlyright_data-0.19.1 → mostlyright_data-0.19.2}/src/mostlyright/data_harness/thin/propose.py +0 -0
- {mostlyright_data-0.19.1 → mostlyright_data-0.19.2}/src/mostlyright/data_harness/thin/recipe.py +0 -0
- {mostlyright_data-0.19.1 → mostlyright_data-0.19.2}/src/mostlyright/data_harness/thin/research.py +0 -0
- {mostlyright_data-0.19.1 → mostlyright_data-0.19.2}/src/mostlyright/data_harness/thin/router.py +0 -0
- {mostlyright_data-0.19.1 → mostlyright_data-0.19.2}/src/mostlyright/data_harness/thin/runs.py +0 -0
- {mostlyright_data-0.19.1 → mostlyright_data-0.19.2}/src/mostlyright/data_harness/thin/session.py +0 -0
- {mostlyright_data-0.19.1 → mostlyright_data-0.19.2}/src/mostlyright/data_harness/thin/stream.py +0 -0
- {mostlyright_data-0.19.1 → mostlyright_data-0.19.2}/src/mostlyright/data_harness/thin/stream_venue.py +0 -0
- {mostlyright_data-0.19.1 → mostlyright_data-0.19.2}/src/mostlyright/data_harness/thin/transport.py +0 -0
- {mostlyright_data-0.19.1 → mostlyright_data-0.19.2}/src/mostlyright/data_harness/thin/user_agent.py +0 -0
- {mostlyright_data-0.19.1 → mostlyright_data-0.19.2}/src/mostlyright/data_harness/thin/v4.py +0 -0
- {mostlyright_data-0.19.1 → mostlyright_data-0.19.2}/src/mostlyright/data_harness/thin/v4_artifacts.py +0 -0
- {mostlyright_data-0.19.1 → mostlyright_data-0.19.2}/src/mostlyright/data_harness/thin/v4_catalog.py +0 -0
- {mostlyright_data-0.19.1 → mostlyright_data-0.19.2}/src/mostlyright/data_harness/thin/v4_connections.py +0 -0
- {mostlyright_data-0.19.1 → mostlyright_data-0.19.2}/src/mostlyright/data_harness/thin/v4_dataset_covers.py +0 -0
- {mostlyright_data-0.19.1 → mostlyright_data-0.19.2}/src/mostlyright/data_harness/thin/v4_datasets.py +0 -0
- {mostlyright_data-0.19.1 → mostlyright_data-0.19.2}/src/mostlyright/data_harness/thin/v4_handoff.py +0 -0
- {mostlyright_data-0.19.1 → mostlyright_data-0.19.2}/src/mostlyright/data_harness/thin/v4_narrative.py +0 -0
- {mostlyright_data-0.19.1 → mostlyright_data-0.19.2}/src/mostlyright/data_harness/thin/v4_query.py +0 -0
- {mostlyright_data-0.19.1 → mostlyright_data-0.19.2}/src/mostlyright/data_harness/thin/v4_runs.py +0 -0
- {mostlyright_data-0.19.1 → mostlyright_data-0.19.2}/src/mostlyright/data_harness/thin/v4_secrets.py +0 -0
- {mostlyright_data-0.19.1 → mostlyright_data-0.19.2}/src/mostlyright/data_harness/thin/v4_stream.py +0 -0
- {mostlyright_data-0.19.1 → mostlyright_data-0.19.2}/src/mostlyright/data_harness/thin/v4_tables.py +0 -0
- {mostlyright_data-0.19.1 → mostlyright_data-0.19.2}/src/mostlyright/data_harness/thin/vocabulary.py +0 -0
- {mostlyright_data-0.19.1 → mostlyright_data-0.19.2}/src/mostlyright/data_harness/ux/__init__.py +0 -0
- {mostlyright_data-0.19.1 → mostlyright_data-0.19.2}/src/mostlyright/data_harness/ux/attendance.py +0 -0
- {mostlyright_data-0.19.1 → mostlyright_data-0.19.2}/src/mostlyright/data_harness/ux/clarification.py +0 -0
- {mostlyright_data-0.19.1 → mostlyright_data-0.19.2}/src/mostlyright/data_harness/ux/cloud_auth.py +0 -0
- {mostlyright_data-0.19.1 → mostlyright_data-0.19.2}/src/mostlyright/data_harness/ux/commands/__init__.py +0 -0
- {mostlyright_data-0.19.1 → mostlyright_data-0.19.2}/src/mostlyright/data_harness/ux/commands/auth.py +0 -0
- {mostlyright_data-0.19.1 → mostlyright_data-0.19.2}/src/mostlyright/data_harness/ux/commands/clarify.py +0 -0
- {mostlyright_data-0.19.1 → mostlyright_data-0.19.2}/src/mostlyright/data_harness/ux/commands/login.py +0 -0
- {mostlyright_data-0.19.1 → mostlyright_data-0.19.2}/src/mostlyright/data_harness/ux/commands/whoami.py +0 -0
- {mostlyright_data-0.19.1 → mostlyright_data-0.19.2}/src/mostlyright/data_harness/ux/credential_native.py +0 -0
- {mostlyright_data-0.19.1 → mostlyright_data-0.19.2}/src/mostlyright/data_harness/ux/credential_store.py +0 -0
- {mostlyright_data-0.19.1 → mostlyright_data-0.19.2}/src/mostlyright/data_harness/ux/credentials.py +0 -0
- {mostlyright_data-0.19.1 → mostlyright_data-0.19.2}/src/mostlyright/data_harness/ux/login.py +0 -0
- {mostlyright_data-0.19.1 → mostlyright_data-0.19.2}/src/mostlyright/data_harness/ux/path_kind.py +0 -0
- {mostlyright_data-0.19.1 → mostlyright_data-0.19.2}/src/mostlyright/data_harness/ux/plain_file.py +0 -0
- {mostlyright_data-0.19.1 → mostlyright_data-0.19.2}/src/mostlyright/data_harness/ux/remediation.py +0 -0
- {mostlyright_data-0.19.1 → mostlyright_data-0.19.2}/src/mostlyright/data_harness/ux/render.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: mostlyright-data
|
|
3
|
-
Version: 0.19.
|
|
3
|
+
Version: 0.19.2
|
|
4
4
|
Summary: Mostly Right hosted CLI for reviewed datasets
|
|
5
5
|
Project-URL: Homepage, https://mostlyright.md/
|
|
6
6
|
Project-URL: Documentation, https://mostlyright.md/docs/guides/cli/
|
|
@@ -111,10 +111,12 @@ worker executables or image publisher.
|
|
|
111
111
|
|
|
112
112
|
## Documentation
|
|
113
113
|
|
|
114
|
-
- [
|
|
115
|
-
- [
|
|
116
|
-
- [
|
|
117
|
-
- [
|
|
114
|
+
- [Install and sign in](https://mostlyright.md/docs/start/install/)
|
|
115
|
+
- [Build your first dataset](https://mostlyright.md/docs/start/first-dataset/)
|
|
116
|
+
- [CLI reference](https://mostlyright.md/docs/reference/cli/)
|
|
117
|
+
- [Recipe reference](https://mostlyright.md/docs/reference/recipe/)
|
|
118
|
+
- [Recipe examples](https://mostlyright.md/docs/recipes/)
|
|
119
|
+
- [Use a public dataset](https://mostlyright.md/docs/guides/use-public-datasets/)
|
|
118
120
|
- [Certified document extraction](docs/DOCUMENT-EXTRACTION.md)
|
|
119
121
|
|
|
120
122
|
Use `mr-data --help` for the full command list and options. Commands that support
|
|
@@ -99,10 +99,12 @@ worker executables or image publisher.
|
|
|
99
99
|
|
|
100
100
|
## Documentation
|
|
101
101
|
|
|
102
|
-
- [
|
|
103
|
-
- [
|
|
104
|
-
- [
|
|
105
|
-
- [
|
|
102
|
+
- [Install and sign in](https://mostlyright.md/docs/start/install/)
|
|
103
|
+
- [Build your first dataset](https://mostlyright.md/docs/start/first-dataset/)
|
|
104
|
+
- [CLI reference](https://mostlyright.md/docs/reference/cli/)
|
|
105
|
+
- [Recipe reference](https://mostlyright.md/docs/reference/recipe/)
|
|
106
|
+
- [Recipe examples](https://mostlyright.md/docs/recipes/)
|
|
107
|
+
- [Use a public dataset](https://mostlyright.md/docs/guides/use-public-datasets/)
|
|
106
108
|
- [Certified document extraction](docs/DOCUMENT-EXTRACTION.md)
|
|
107
109
|
|
|
108
110
|
Use `mr-data --help` for the full command list and options. Commands that support
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: mr-data-build
|
|
3
|
-
description: Build and verify a reproducible Parquet dataset from a data question and supported sources on the hosted Mostly Right backend. Use whenever a user asks to use, test, smoke-test, demonstrate, or debug the Mostly Right Harness or mr-data CLI by producing, reviewing, or verifying a dataset.
|
|
3
|
+
description: Build and verify a reproducible Parquet dataset from a data question and supported sources on the hosted Mostly Right backend. Use whenever a user asks to use, test, smoke-test, demonstrate, or debug the Mostly Right Harness or mr-data CLI by producing, reviewing, or verifying a dataset. The published reference at https://mostlyright.md/docs/ is the contract.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Mostly Right Data Build
|
|
@@ -81,16 +81,49 @@ work, follow it, and read what the backend proved. Studio is the hosted release
|
|
|
81
81
|
|
|
82
82
|
The product is hosted-only and the client is thin. The engine runs on the backend; `mr-data` is a
|
|
83
83
|
pure-Python client that submits work and reads the records Studio holds.
|
|
84
|
-
[
|
|
84
|
+
[Install and sign in](https://mostlyright.md/docs/start/install/) states that one install and where
|
|
85
|
+
a command's work actually runs.
|
|
85
86
|
|
|
86
87
|
Read this document in two parts. Everything except [Not hosted yet](#not-hosted-yet) uses only
|
|
87
88
|
commands this product runs. [Not hosted yet](#not-hosted-yet) is the internal capability map for
|
|
88
89
|
the one command with no implementation behind it.
|
|
89
90
|
|
|
90
|
-
Every
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
91
|
+
Every link below is a page of the published reference at https://mostlyright.md/docs/, and every
|
|
92
|
+
one of them can be fetched from here. This document is installed on its own and remains the whole
|
|
93
|
+
of what a build needs; each page is the longer, current reference behind one section of it.
|
|
94
|
+
|
|
95
|
+
## Reference pages
|
|
96
|
+
|
|
97
|
+
The published reference at https://mostlyright.md/docs/ carries the current contract for every
|
|
98
|
+
field, flag, code and ceiling this document names. Fetch the page for the shape in front of you
|
|
99
|
+
BEFORE drafting it, never guess a field name, and where a page disagrees with what you remember of
|
|
100
|
+
an older version, the page is right.
|
|
101
|
+
|
|
102
|
+
| What you are about to do | Fetch |
|
|
103
|
+
| --- | --- |
|
|
104
|
+
| Write a recipe document | https://mostlyright.md/docs/reference/recipe/ |
|
|
105
|
+
| Declare a check | https://mostlyright.md/docs/reference/checks/ |
|
|
106
|
+
| Plan a transform step | https://mostlyright.md/docs/reference/transforms/ |
|
|
107
|
+
| Name a unit | https://mostlyright.md/docs/reference/units/ |
|
|
108
|
+
| Choose a connector, a source kind or a connector parameter | https://mostlyright.md/docs/reference/sources/ |
|
|
109
|
+
| Pin a Reader | https://mostlyright.md/docs/reference/readers/ |
|
|
110
|
+
| Read any command's flags and `--json` shape | https://mostlyright.md/docs/reference/cli/ , then the group page: `auth`, `dataset`, `recipe`, `run`, `read`, `table`, `stream` under `/docs/reference/cli/` |
|
|
111
|
+
| Read an error code, a refusal or a run state | https://mostlyright.md/docs/reference/run-states-and-errors/ |
|
|
112
|
+
| Check a ceiling before starting a run | https://mostlyright.md/docs/reference/limits/ |
|
|
113
|
+
| Follow the whole lifecycle end to end | https://mostlyright.md/docs/start/how-it-works/ |
|
|
114
|
+
| Install the client and sign in | https://mostlyright.md/docs/start/install/ |
|
|
115
|
+
|
|
116
|
+
Read the worked recipe closest to the source in hand before writing your own.
|
|
117
|
+
https://mostlyright.md/docs/recipes/ lists all eight: `city-temperatures` (daily city
|
|
118
|
+
temperatures), `csv-snapshot` (one CSV file, one table), `json-api` (records pointer and
|
|
119
|
+
pagination), `html-collection` (many HTML pages, one table), `document-extraction` (PDF
|
|
120
|
+
projection), `weather-grib` (GRIB2 and the scientific Readers), `websocket-stream` (a `wss://`
|
|
121
|
+
venue), `multi-source-join` (two sources joined, with checks).
|
|
122
|
+
|
|
123
|
+
The build guides run one per stage of the loop below, each at https://mostlyright.md/docs/build/NAME/
|
|
124
|
+
where NAME is `probe-sources`, `write-a-recipe`, `run-and-inspect`, `publish-and-refresh`,
|
|
125
|
+
`credentials`, `live-streams`, `collections`, `documents` or `troubleshooting`; the list itself is
|
|
126
|
+
at https://mostlyright.md/docs/build/ and the reference index at https://mostlyright.md/docs/reference/.
|
|
94
127
|
|
|
95
128
|
## One install
|
|
96
129
|
|
|
@@ -117,7 +150,7 @@ gap rather than doing anything, and `export-hosted-candidate`, which is a backen
|
|
|
117
150
|
| `mr-data login` | Complete device approval and store a device credential. `login --force` is the compatibility alias for safe `auth rotate`, never an in-place truncate. |
|
|
118
151
|
| `mr-data whoami` | Use the compatibility alias for the remotely validated `auth status` answer. |
|
|
119
152
|
| `mr-data clarify` | Say whether one clarifying question may be put to the user right now, and compose the record of their answer. It reaches nothing, asks nobody and waits for nothing. Exits non-zero when no person can answer or when a recipe is already registered. |
|
|
120
|
-
| `mr-data probe` |
|
|
153
|
+
| `mr-data probe` | `probe SOURCE_ID QUESTION_ID --dataset DATASET_ID [--kind source_inspect\|sample_rows\|profile_columns\|evaluate_expression]` asks one already-registered source one question and prints the answer. **Do not plan a source inspection around it.** Both positionals are identifiers — `QUESTION_ID` is a question identifier, which no v4 registration receipt returns — and the command rides the frozen `/v3/sessions` routes, which a deployment may have switched off. Read a source instead by registering the recipe and taking an unwindowed sample under `--max-rows`, then `peek`, `query` and `receipt`. |
|
|
121
154
|
| `mr-data catalog` | `catalog search "QUESTION"` asks the sealed public-source catalogue which of its entries might answer a question and ranks them best first. Every ranked entry comes back with the disposition its own facts earned — `admitted`, `human_escalation_required` or `refused` — because an entry the catalogue could not vouch for is still a finding. `--format csv` states the one data format the question requires — one token per question, never repeated — and it is not a filter: an entry that does not declare that format still comes back ranked, with disposition `refused` and `filters_match` false, so nothing is held back; `--limit N` ranks at most N, up to 25. It fetches nothing and registers nothing. The catalogue holds one provider (Data.gov) and only part of it, so it is never exhaustive and an empty answer is not evidence that no such source exists. When the answer is `catalog_unavailable`, this deployment has no catalogue to search: record the lane and carry on. |
|
|
122
155
|
| `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`; `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; `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. |
|
|
123
156
|
| `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. `mr-data recipe show ID` reads one back. |
|
|
@@ -160,7 +193,7 @@ step between a run finishing and reading it: `download`, `receipt`, `checks`, `p
|
|
|
160
193
|
answer about a run that is still workspace scratch exactly as they answer about one somebody has
|
|
161
194
|
since made live.
|
|
162
195
|
|
|
163
|
-
[The recipe document](
|
|
196
|
+
[The recipe document](https://mostlyright.md/docs/reference/recipe/) is the reference for what
|
|
164
197
|
`mr-data recipe FILE` sends. Two rules in it are worth knowing before you write one: no fractional
|
|
165
198
|
number appears anywhere in the document, and you neither compute nor state a digest — the server
|
|
166
199
|
canonicalizes the document, digests it, and answers with every identifier it derived. Sending the
|
|
@@ -172,8 +205,9 @@ signed something on a person's own computer, or they were named for a step the p
|
|
|
172
205
|
performs — asking a person before the work starts, reading back a separate body of evidence,
|
|
173
206
|
opening a session before a question could be asked. For a while each still typed and answered with
|
|
174
207
|
where its work went; that ended when the refusing names outnumbered the working ones two to one.
|
|
175
|
-
[
|
|
176
|
-
the
|
|
208
|
+
[Install and sign in](https://mostlyright.md/docs/start/install/) states the one install and the
|
|
209
|
+
whole surface it carries; the deleted names and what replaced each of them are written down only in
|
|
210
|
+
the Harness repository's own `docs/HOSTED-PARITY.md`, which is not installed beside this document.
|
|
177
211
|
|
|
178
212
|
Most of the survivors take a run identifier where the deleted local twin took a folder. That is
|
|
179
213
|
the whole difference in the vocabulary: a hosted build has no folder, and the run identifier is
|
|
@@ -216,7 +250,7 @@ machine that is only using the product installs from `pip` instead.
|
|
|
216
250
|
## Cloud authentication preflight
|
|
217
251
|
|
|
218
252
|
Authentication begins only when the next command will contact the Mostly Right cloud. Immediately
|
|
219
|
-
before hosted `mr-data
|
|
253
|
+
before hosted `mr-data dataset create` or `mr-data recipe`, run
|
|
220
254
|
`mr-data whoami --json` and read its `status`, and it intentionally does not report
|
|
221
255
|
`MOSTLYRIGHT_API_KEY`: when the variable is set, `whoami` validates that effective environment
|
|
222
256
|
credential and reports stored-device metadata separately. It never prints the environment value and
|
|
@@ -394,23 +428,30 @@ provider or bypass it.
|
|
|
394
428
|
reason codes only after the discovery lanes and source comparisons are complete. Claim
|
|
395
429
|
`unsupported` only after every typed-refusal chain ends `lawful_routes_exhausted`.
|
|
396
430
|
|
|
397
|
-
Reading
|
|
431
|
+
**Reading the bytes is the sample run, not `mr-data probe`.** `probe SOURCE_ID QUESTION_ID
|
|
432
|
+
--dataset DATASET_ID` takes two identifiers rather than a question in words, and the question
|
|
433
|
+
identifier is one no v4 registration receipt returns; the command also rides the frozen
|
|
434
|
+
`/v3/sessions` routes, which a deployment may have switched off. So the reading path on a hosted
|
|
435
|
+
workspace is the ordinary loop, one stage early: register the recipe, start an unwindowed sample
|
|
436
|
+
under a row ceiling, and read what came back.
|
|
398
437
|
|
|
399
438
|
```sh
|
|
400
|
-
mr-data
|
|
439
|
+
mr-data run --recipe RECIPE_ID --digest RECIPE_DIGEST --mode sample --max-rows 500 --json
|
|
440
|
+
mr-data peek RUN --json # the columns and types the run sealed
|
|
441
|
+
mr-data query RUN "select count(*) from run_table" --json
|
|
442
|
+
mr-data receipt RUN --json # what was fetched and what those bytes hashed to
|
|
401
443
|
```
|
|
402
444
|
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
445
|
+
That is stages 4 through 6 run once to settle the shape, and a sample that already meets the
|
|
446
|
+
requirements is the table a full run would seal. Where the deployment does answer a probe, keep its
|
|
447
|
+
status, reason code and exit value internal; when a probe result affects a source decision, describe
|
|
448
|
+
only what it settled about the data.
|
|
407
449
|
|
|
408
|
-
**
|
|
409
|
-
evidence is repealed. Every acquisition
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
session
|
|
413
|
-
around a probe from an hour ago still being warm.
|
|
450
|
+
**An acquisition's answer is evidence, and it is cheap to reuse.** The v3 doctrine that a probe was
|
|
451
|
+
never evidence is repealed. Every acquisition produces a receipt, and acquisitions are cacheable by
|
|
452
|
+
source, query digest and window, so a fetch feeds a later build in the same warm session without
|
|
453
|
+
paying for the bytes twice. In v4.0 that cache is session-scoped by owner ruling: it lives for the
|
|
454
|
+
session's lifetime and no longer, so do not plan around a fetch from an hour ago still being warm.
|
|
414
455
|
|
|
415
456
|
Where a source needs a credential, enrol it by name first — see
|
|
416
457
|
[Source credentials](#source-credentials) — and reference the name from the recipe document. Where
|
|
@@ -480,7 +521,7 @@ mr-data recipe RECIPE.json --json
|
|
|
480
521
|
One call. The server canonicalizes the bytes, computes the digest, and registers the dataset, the
|
|
481
522
|
question, the sources, the connector configs and the table plan in one transaction, answering with
|
|
482
523
|
`recipe_id`, `recipe_digest`, `dataset_id`, `table_id` and `source_ids`. Read
|
|
483
|
-
[The recipe document](
|
|
524
|
+
[The recipe document](https://mostlyright.md/docs/reference/recipe/) for the shape of every member.
|
|
484
525
|
|
|
485
526
|
**Name the dataset the recipe binds to.** The document's `dataset` member takes an optional `id`,
|
|
486
527
|
and it is the identifier stage 1 printed. With it, the registration attaches to the page somebody
|
|
@@ -768,25 +809,36 @@ contradicts what the column declared. A `bucket` the span outgrew is not one of
|
|
|
768
809
|
is widened and the chart stays yours. So `none` is the right answer to write for a column you
|
|
769
810
|
already know has no shape, and a wide date range is worth a thought before you promise a timeline.
|
|
770
811
|
|
|
771
|
-
[The recipe document](
|
|
772
|
-
the defaults are, and the two members only some charts take.
|
|
812
|
+
[The recipe document](https://mostlyright.md/docs/reference/recipe/) carries which types each
|
|
813
|
+
chart admits, what the defaults are, and the two members only some charts take.
|
|
773
814
|
|
|
774
815
|
### What the statement must actually return
|
|
775
816
|
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
817
|
+
The last step's relation is projected into the declared columns: every declared column must come
|
|
818
|
+
back BY NAME, in an engine type that narrows into the declared one. A returned column the table does
|
|
819
|
+
not declare is dropped; a declared column no statement returns is `TRANSFORM_PLAN_INVALID` before a
|
|
820
|
+
row exists.
|
|
821
|
+
|
|
822
|
+
A source's `binding` decides what its columns are typed as. `text` — the default, and what leaving
|
|
823
|
+
the member out means — binds every column `VARCHAR` whatever the file said, so each declared type is
|
|
824
|
+
an explicit cast you write. `typed` keeps the types the bytes carry. Under either one the cast is
|
|
825
|
+
checked against what the engine returns:
|
|
779
826
|
|
|
780
827
|
| Declared | The engine type the statement must return |
|
|
781
828
|
| --- | --- |
|
|
782
829
|
| `string` | `VARCHAR` |
|
|
783
830
|
| `integer` | `TINYINT`, `SMALLINT`, `INTEGER`, `BIGINT` — not the widest |
|
|
784
|
-
| `decimal` | `DECIMAL(p,s)` — never `FLOAT` or `DOUBLE` |
|
|
831
|
+
| `decimal` | `DECIMAL(p,s)` with `p` at most 38 — never `FLOAT` or `DOUBLE` |
|
|
832
|
+
| `float` | `DOUBLE`, `FLOAT` |
|
|
785
833
|
| `boolean` | `BOOLEAN` |
|
|
786
834
|
| `date` | `DATE` |
|
|
787
835
|
| `timestamp` | `TIMESTAMP WITH TIME ZONE` |
|
|
788
836
|
| `json` | `JSON` or `VARCHAR` |
|
|
789
837
|
|
|
838
|
+
`decimal` refusing the floating types is the point of that split: an average or a division over
|
|
839
|
+
exact decimals comes back `DOUBLE`, so end the expression in `CAST(… AS DECIMAL(p,s))` where the
|
|
840
|
+
column is exact, and declare `float` where it is genuinely approximate.
|
|
841
|
+
|
|
790
842
|
`TRANSFORM_COLUMN_TYPE_MISMATCH: column obs_time is declared timestamp and the statement returns
|
|
791
843
|
TIMESTAMP` is the time-zone row, and it names the same word twice because the difference is the zone
|
|
792
844
|
rather than the type. Build one from an epoch with `to_timestamp(CAST(x AS BIGINT))`, or from text by
|
|
@@ -823,12 +875,22 @@ ones, so a caller cannot assert a digest for its own bytes even by trying; the d
|
|
|
823
875
|
is the server's reading of what it canonicalized. Registration is idempotent by that digest:
|
|
824
876
|
identical bytes register one recipe rather than two.
|
|
825
877
|
|
|
826
|
-
Before
|
|
827
|
-
[Prediction labels](#prediction-labels). Declare what each measured column measures as a
|
|
828
|
-
from the accepted subset — `
|
|
829
|
-
[Units](
|
|
830
|
-
|
|
831
|
-
|
|
878
|
+
Before writing a step, read [Transforms](#transforms); before proposing a future outcome, read
|
|
879
|
+
[Prediction labels](#prediction-labels). Declare what each measured column measures as a UCUM code
|
|
880
|
+
from the accepted subset — `Cel`, `ug/m3`, `km/h`, `hPa`, `{count}` and the rest of it are written
|
|
881
|
+
out in [Units](https://mostlyright.md/docs/reference/units/). Write the code rather than a name:
|
|
882
|
+
`ug/m3` composes and `microgram_per_cubic_meter` does not.
|
|
883
|
+
|
|
884
|
+
**Nothing resolves the code, so there is no `UNIT_*` refusal to lean on.** The recipe schema bounds
|
|
885
|
+
the length of `unit` and nothing else; registration checks only that `units[].column` names a
|
|
886
|
+
declared column and answers `422 RECIPE_DOCUMENT_INCOHERENT` at `/units/N/column` when it does not;
|
|
887
|
+
the run never reads `units` at all. A code outside the subset therefore costs nothing at build time
|
|
888
|
+
and costs every reader afterwards, and a column declared in metres that holds feet is caught by
|
|
889
|
+
nothing. Convert in the statement, then declare the unit of what the column ends up holding. Leave a
|
|
890
|
+
column out of `units` rather than declare something approximate — a density, a rate, anything whose
|
|
891
|
+
unit is genuinely new. `none` is not a unit and does not become one. Remember that the two
|
|
892
|
+
temperature scales are offsets rather than multipliers, so `Cel` composes with nothing: `Cel/m` and
|
|
893
|
+
`mCel` are both outside the subset.
|
|
832
894
|
|
|
833
895
|
### 5. Build — take an unwindowed sample first
|
|
834
896
|
|
|
@@ -886,7 +948,7 @@ one", not as a failure: a document declaring 8 MiB over a feed that answers 40 K
|
|
|
886
948
|
ceiling on that source:** that does not fetch less data, it truncates the sample or refuses the
|
|
887
949
|
full run. Split the window across several sources — one per month, per region, or per whatever the
|
|
888
950
|
publisher paginates on — and union them in a first transform step. A recipe names up to 256
|
|
889
|
-
sources, which is a great many windows. [The recipe document](
|
|
951
|
+
sources, which is a great many windows. [The recipe document](https://mostlyright.md/docs/reference/recipe/)
|
|
890
952
|
carries the measured numbers behind the ceiling.
|
|
891
953
|
|
|
892
954
|
**A corpus of many pages behind one index is a COLLECTION, not many sources.** See
|
|
@@ -1352,9 +1414,9 @@ access is denied, say the current account cannot view the build evidence and ask
|
|
|
1352
1414
|
to an authorized account or request access.
|
|
1353
1415
|
|
|
1354
1416
|
A flag that cannot mean what it means locally is accepted and reported, never refused.
|
|
1355
|
-
`mr-data
|
|
1356
|
-
that
|
|
1357
|
-
nothing. Only flags actually passed are reported.
|
|
1417
|
+
`mr-data status RUN_ID --receipts` runs, reports the run, and reports under `flags_without_effect`
|
|
1418
|
+
that a run's digests, sources, timings and checks are already on the record. Read that key before
|
|
1419
|
+
repeating an argument that did nothing. Only flags actually passed are reported.
|
|
1358
1420
|
|
|
1359
1421
|
### Asking the table a question
|
|
1360
1422
|
|
|
@@ -1382,7 +1444,7 @@ Two things are currently broken here and are not worth diagnosing again:
|
|
|
1382
1444
|
version digest in `source.connection`, with the query in `parameter_values` and a valid response
|
|
1383
1445
|
reader; set `dataset.id` to the granted dataset. Do not ask the user to re-enter an already saved
|
|
1384
1446
|
credential under Keys. If it is not granted, explain that an owner or administrator must allow
|
|
1385
|
-
the dataset in Settings → Connections & secrets. See [Saved connections](
|
|
1447
|
+
the dataset in Settings → Connections & secrets. See [Saved connections](https://mostlyright.md/docs/build/credentials/)
|
|
1386
1448
|
for the proposal shape. Studio resolves it into the canonical recipe and enforces access during
|
|
1387
1449
|
execution. Named secrets below remain available for sources without saved connections.
|
|
1388
1450
|
|
|
@@ -1646,8 +1708,9 @@ or network search. If every registered, lawful alternative is deterministically
|
|
|
1646
1708
|
record and report the typed impossibility. Do not loop forever, fabricate a dataset, or turn a
|
|
1647
1709
|
refusal into permission.
|
|
1648
1710
|
|
|
1649
|
-
Never download source bytes directly. Never
|
|
1650
|
-
|
|
1711
|
+
Never download source bytes directly. Never transform data on this computer: the transform is the
|
|
1712
|
+
recipe's own `duckdb_sql` steps, run on the backend, and Python, shell or a local SQL engine reading
|
|
1713
|
+
the same bytes is not that. Never create Parquet outside a Harness Build. Never report a standalone Parquet file as a Build.
|
|
1651
1714
|
Do not report completion unless the run succeeded, its declared checks were read, and any artifacts
|
|
1652
1715
|
the user asked for came back with their digests checked.
|
|
1653
1716
|
|
|
@@ -1774,20 +1837,24 @@ the records pointer names an array, and whether `discovery.max_requests` plus
|
|
|
1774
1837
|
they are the four that are cheapest to get right before a run spends anybody's rate limit.
|
|
1775
1838
|
|
|
1776
1839
|
The full contract, including every bound and the coverage block's members, is
|
|
1777
|
-
[
|
|
1840
|
+
[Many-page sources](https://mostlyright.md/docs/build/collections/), with the connector coordinate
|
|
1841
|
+
and its parameters under
|
|
1842
|
+
[Source kinds and connectors](https://mostlyright.md/docs/reference/sources/).
|
|
1778
1843
|
|
|
1779
1844
|
## Readers
|
|
1780
1845
|
|
|
1781
|
-
|
|
1782
|
-
|
|
1783
|
-
|
|
1784
|
-
|
|
1846
|
+
[Readers](https://mostlyright.md/docs/reference/readers/) defines Reader behavior. Certified
|
|
1847
|
+
Readers may be pinned on a hash-pinned
|
|
1848
|
+
`user.file` artifact, on a credential-free public HTTPS source, or on a bounded ordered public HTTPS
|
|
1849
|
+
collection, which applies one exact pin to every member. A Recipe pins the exact Reader name and
|
|
1850
|
+
version. Unsupported versions refuse by name. A version change is a recipe revision.
|
|
1785
1851
|
|
|
1786
1852
|
**Direct CSV supports publisher CSV aliases, including Eurostat SDMX-CSV.**
|
|
1787
1853
|
Accepted labels include `text/csv`, `text/plain`, `application/csv`, `application/x-csv`,
|
|
1788
1854
|
`text/x-csv`, and `application/vnd.sdmx.data+csv`. For title rows, alternate encodings,
|
|
1789
1855
|
headerless files, or padded columns, pin `delimited_text@2.0.0` and configure the layout; see
|
|
1790
|
-
|
|
1856
|
+
[Readers](https://mostlyright.md/docs/reference/readers/). A publisher needing another format can
|
|
1857
|
+
use its matching Reader.
|
|
1791
1858
|
|
|
1792
1859
|
**A v4 recipe pins a Reader through `connector.parameters`, under three reserved names.**
|
|
1793
1860
|
`declared_source` is closed and has no member for a decoder, so the pin rides on the parameter array
|
|
@@ -1807,38 +1874,35 @@ field and finding none does not mean v4 cannot pin one.
|
|
|
1807
1874
|
}
|
|
1808
1875
|
```
|
|
1809
1876
|
|
|
1810
|
-
A parameter under `reader.` that is not one of those three is refused rather than ignored.
|
|
1877
|
+
A parameter under `reader.` that is not one of those three is refused rather than ignored. All three
|
|
1878
|
+
or none: there is no other place a Reader is named. Read the pin grammar and the closed registry of
|
|
1879
|
+
48 coordinates at [Readers](https://mostlyright.md/docs/reference/readers/).
|
|
1880
|
+
|
|
1881
|
+
**No command tries a Reader against a URL.** `mr-data peek` reads the preview one hosted run sealed,
|
|
1882
|
+
and its `--reader`, `--reader-options`, `--format` and `--json-*` flags are accepted and print `no
|
|
1883
|
+
effect here; the hosted preview arrives already decoded`. A Reader is settled the way every other
|
|
1884
|
+
part of the document is settled: pin the coordinate in the recipe, register it, take an unwindowed
|
|
1885
|
+
sample under `--max-rows`, and read the columns back with `peek` and the decode evidence with
|
|
1886
|
+
`receipt`. A wrong coordinate or a wrong settings object is a typed refusal on that run naming the
|
|
1887
|
+
source, which is the answer — change the pin and register the revision.
|
|
1811
1888
|
|
|
1812
1889
|
**`reader.decode_options` is the canonical JSON text of the options the family itself admits**, with
|
|
1813
1890
|
every family-defaulted key filled in. A stated subset digests differently from the pin the worker
|
|
1814
|
-
reconstructs and is refused.
|
|
1815
|
-
|
|
1816
|
-
|
|
1817
|
-
|
|
1818
|
-
from mostlyright.data_harness.canonical import canonical_json_bytes
|
|
1819
|
-
admitted = JsonTabularReaderV1_1().validate_options(
|
|
1820
|
-
{"columns": [{"name": "icao_id", "pointer": "/icaoId"}]}
|
|
1821
|
-
)
|
|
1822
|
-
value = canonical_json_bytes(admitted).decode()
|
|
1823
|
-
```
|
|
1891
|
+
reconstructs and is refused. This client ships no Reader code to derive the value with: copy the
|
|
1892
|
+
family's complete default object from [Readers](https://mostlyright.md/docs/reference/readers/),
|
|
1893
|
+
change only the keys the source needs, keep every other key at its default, and write it as
|
|
1894
|
+
canonical JSON — keys sorted, no whitespace.
|
|
1824
1895
|
|
|
1825
1896
|
A column that may be absent from a record must state `"required": false`. Publishers routinely omit
|
|
1826
1897
|
a key rather than sending null, and a required column that is missing refuses the record.
|
|
1827
1898
|
|
|
1828
|
-
**Open defect: an empty string in the admitted options is refused at the acquisition boundary with
|
|
1829
|
-
`TEXT`, and the refusal names no source.** `records_pointer: ""` is the RFC 6901 pointer for a
|
|
1830
|
-
root-level array, which is what `json.tabular` admits by default and what every API returning a bare
|
|
1831
|
-
JSON array needs, so this blocks that whole class of source. The request-side screen applies the
|
|
1832
|
-
identifier rule — where an empty string is a missing one — to JSON values, where it is not. Fixed by
|
|
1833
|
-
harness PR #503; until that reaches the deployed worker image, a root-array JSON source cannot be
|
|
1834
|
-
pinned. Confirm the deployed worker carries the fix before planning a build around one.
|
|
1835
|
-
|
|
1836
1899
|
When you pin a Reader for a source nobody has approved yet, name the family's highest certified
|
|
1837
1900
|
version rather than its base version. The base version refuses a publisher that merely declined
|
|
1838
1901
|
to describe its file, and a weak-label widening lands as a new coordinate precisely so an
|
|
1839
1902
|
approved recipe is not moved under review's feet -- which makes the base version the wrong
|
|
1840
|
-
default for a source that has no approval to protect.
|
|
1841
|
-
|
|
1903
|
+
default for a source that has no approval to protect. The registry table at
|
|
1904
|
+
[Readers](https://mostlyright.md/docs/reference/readers/) lists every certified coordinate of a
|
|
1905
|
+
family; take the highest within the major you want. For a family whose major version has moved, the highest coordinate is
|
|
1842
1906
|
a different output contract rather than a wider door onto the same one, so choose it
|
|
1843
1907
|
deliberately: `weather.grib2@2.0.0` emits columns `1.0.0` does not.
|
|
1844
1908
|
|
|
@@ -1918,78 +1982,117 @@ response matches the family's exact media-type, settings, and budget contract.
|
|
|
1918
1982
|
|
|
1919
1983
|
## Transforms
|
|
1920
1984
|
|
|
1921
|
-
|
|
1922
|
-
|
|
1923
|
-
|
|
1924
|
-
|
|
1925
|
-
|
|
1926
|
-
|
|
1927
|
-
|
|
1928
|
-
|
|
1929
|
-
|
|
1930
|
-
|
|
1931
|
-
|
|
1932
|
-
|
|
1933
|
-
|
|
1934
|
-
|
|
1935
|
-
|
|
1936
|
-
|
|
1937
|
-
|
|
1938
|
-
|
|
1939
|
-
|
|
1940
|
-
|
|
1941
|
-
|
|
1942
|
-
|
|
1943
|
-
|
|
1944
|
-
|
|
1945
|
-
|
|
1946
|
-
|
|
1947
|
-
|
|
1948
|
-
|
|
1949
|
-
|
|
1950
|
-
|
|
1951
|
-
|
|
1952
|
-
|
|
1953
|
-
|
|
1954
|
-
|
|
1955
|
-
|
|
1956
|
-
|
|
1957
|
-
|
|
1958
|
-
|
|
1959
|
-
|
|
1960
|
-
|
|
1961
|
-
|
|
1962
|
-
|
|
1963
|
-
|
|
1964
|
-
|
|
1965
|
-
|
|
1985
|
+
**A v4 transform is SQL, not an operation vocabulary.** The member is
|
|
1986
|
+
`{"engine": "duckdb_sql", "steps": [...]}`, and each step is `{"step_id": "…", "sql": "…"}` with an
|
|
1987
|
+
optional `description`: at most 64 steps, each statement at most 65536 characters. There is no node
|
|
1988
|
+
graph, no closed operation set and nothing to work around — the statement is the plan. The schema
|
|
1989
|
+
also admits `engine: "none"`, and that document registers and then refuses its first run
|
|
1990
|
+
`TRANSFORM_PLAN_INVALID`, as an empty `steps` array does, because neither says what a build
|
|
1991
|
+
produces. Fetch [Transforms](https://mostlyright.md/docs/reference/transforms/) before writing one:
|
|
1992
|
+
it carries the admitted function table, the worked shapes and every refusal code.
|
|
1993
|
+
|
|
1994
|
+
**What a step reads.** One relation per source, under the source's own `name`, and one relation per
|
|
1995
|
+
earlier step, under its `step_id`. Steps run in array order, never sorted, so a later step reads an
|
|
1996
|
+
earlier one by writing its id. A `step_id` equal to a source `name` is refused
|
|
1997
|
+
`TRANSFORM_STEP_SHADOWS_SOURCE` and two steps sharing an id are `TRANSFORM_STEP_DUPLICATE`. Quote a
|
|
1998
|
+
name that is also a SQL keyword.
|
|
1999
|
+
|
|
2000
|
+
**What the columns are typed as.** The relation carries the ordered header acquisition recorded, and
|
|
2001
|
+
the source's `binding` decides the types: `text` — the default, and what leaving the member out
|
|
2002
|
+
means — binds every column `VARCHAR`, and `typed` keeps what the bytes carry. Under `text` every
|
|
2003
|
+
declared type is a cast you write, which keeps casting an act of the recipe. Two relations are not
|
|
2004
|
+
declared anywhere: a recorded stream source presents one of two fixed text headers — eight
|
|
2005
|
+
columns `epoch`, `event_id`, `event_time`, `message`, `message_class`, `message_type`,
|
|
2006
|
+
`received_at`, `sequence`, or those plus `member` after `event_time` when the connector declares a
|
|
2007
|
+
member field — and a collection source presents the pinned Reader's columns plus seven reserved
|
|
2008
|
+
`page_*` columns.
|
|
2009
|
+
|
|
2010
|
+
**What the last step must return** is under
|
|
2011
|
+
[What the statement must actually return](#what-the-statement-must-actually-return). Row order is
|
|
2012
|
+
the table's `grain` and then every remaining declared column in declaration order, so an `order by`
|
|
2013
|
+
you write is not the sealed order.
|
|
2014
|
+
|
|
2015
|
+
```json
|
|
2016
|
+
"transform": {
|
|
2017
|
+
"engine": "duckdb_sql",
|
|
2018
|
+
"steps": [
|
|
2019
|
+
{
|
|
2020
|
+
"step_id": "readings",
|
|
2021
|
+
"sql": "select station, cast(concat(valid, ':00+00') as timestamp with time zone) as observed_at, cast((try_cast(tmpf as decimal(6,2)) - 32) * 5 / 9 as decimal(6,2)) as air_temp_c from asos_observations where valid is not null and valid <> ''"
|
|
2022
|
+
},
|
|
2023
|
+
{
|
|
2024
|
+
"step_id": "hourly",
|
|
2025
|
+
"sql": "select station, time_bucket(interval 1 hour, observed_at) as hour_start, cast(avg(air_temp_c) as decimal(6,2)) as mean_air_temp_c, count(*) as reading_count from readings group by station, time_bucket(interval 1 hour, observed_at)"
|
|
2026
|
+
}
|
|
2027
|
+
]
|
|
2028
|
+
}
|
|
2029
|
+
```
|
|
2030
|
+
|
|
2031
|
+
`asos_observations` is a source's `name`; `readings` is the first step read by the second. The outer
|
|
2032
|
+
`cast` on each measured column is what makes it a `DECIMAL(6,2)` — without it the division and the
|
|
2033
|
+
`avg` both return `DOUBLE` and the column is refused.
|
|
2034
|
+
|
|
2035
|
+
**One read-only `SELECT` per step.** The engine classifies the statement: more than one is
|
|
2036
|
+
`TRANSFORM_STATEMENT_NOT_SINGLE`, and anything that is not a `SELECT` is
|
|
2037
|
+
`TRANSFORM_STATEMENT_NOT_SELECT` — so `ATTACH`, `COPY`, `INSTALL`, `LOAD`, `PRAGMA`, `CREATE`,
|
|
2038
|
+
`INSERT`, `UPDATE` and `DELETE` are all refused. Common table expressions, `UNION`, `QUALIFY`,
|
|
2039
|
+
`UNPIVOT`, `VALUES` and `SELECT DISTINCT` are each one `SELECT` and are admitted, which is how a
|
|
2040
|
+
long-format reshape, a join, a deduplication and a time bucket are written.
|
|
2041
|
+
|
|
2042
|
+
**The result has to re-derive, and the engine decides that rather than a word list.** A sealed table
|
|
2043
|
+
is rebuilt and compared byte for byte, so a step may read nothing the recipe and the acquired bytes
|
|
2044
|
+
do not fix. The engine's own function catalog is asked about every name the statement references:
|
|
2045
|
+
anything it does not report as re-derivable, anything with side effects, and anything it does not
|
|
2046
|
+
carry at all is refused `TRANSFORM_PLAN_INVALID` before the step runs. That catches `current_date`,
|
|
2047
|
+
`current_timestamp`, `now()`, `today()`, `random()`, `gen_random_uuid()` and anything written in
|
|
2048
|
+
terms of them. The date-granular ones are the dangerous ones: both executions inside one build agree
|
|
2049
|
+
and the table seals, and tomorrow's refresh can never reproduce it. Reach a column a publisher
|
|
2050
|
+
happened to spell like one of those names by qualifying it — `observations.current_date`.
|
|
2051
|
+
|
|
2052
|
+
**The engine reaches nothing.** It is given this run's own source files and scratch directory, then
|
|
2053
|
+
external access is switched off and the settings are locked, so it can open no file, fetch no URL
|
|
2054
|
+
and load no extension. There is no denylist of names in any of it, by design: a source is reached by
|
|
2055
|
+
naming its relation and never by opening its address again. Where that confinement cannot be
|
|
2056
|
+
established the code is `TRANSFORM_ENGINE_UNCONFINED` and no step was attempted.
|
|
2057
|
+
|
|
2058
|
+
**Every table is built in `UTC`**, established before a statement is read. A recipe declaring
|
|
2059
|
+
another `timezone` registers and then refuses its first run `RUN_RECIPE_INVALID`. `ICU` is not
|
|
2060
|
+
loaded, so `AT TIME ZONE` is unavailable; write the conversion into the statement.
|
|
2061
|
+
|
|
2062
|
+
A step the engine itself refused comes back as `RUN_EXECUTION_FAILED` carrying DuckDB's own code and
|
|
2063
|
+
words — `step daily_mean would not run: BINDER_ERROR: …`. Read the detail, not the code. Every
|
|
2064
|
+
transform code reports `failed_stage: "transform"`.
|
|
2065
|
+
|
|
2066
|
+
`units` is declared beside the table, and nothing in the transform reads it or checks the arithmetic
|
|
2067
|
+
against it. Convert in the statement, then declare the unit of what the column ends up holding, per
|
|
2068
|
+
the paragraph under [What each check kind requires](#what-each-check-kind-requires).
|
|
1966
2069
|
|
|
1967
2070
|
## Prediction labels
|
|
1968
2071
|
|
|
1969
|
-
|
|
1970
|
-
something the harness can construct.
|
|
1971
|
-
refuse a graph naming it, with a typed `OPERATION_RETIRED` refusal.
|
|
2072
|
+
There is no prediction-label member in a v4 recipe document and no operation that produces one. Do
|
|
2073
|
+
not offer a future outcome as something the harness can construct.
|
|
1972
2074
|
|
|
1973
|
-
The
|
|
1974
|
-
|
|
1975
|
-
the
|
|
1976
|
-
and none is owed.
|
|
2075
|
+
The horizon such a label needs is a statement about what somebody intends to model, and nothing in
|
|
2076
|
+
the sources says what it should be. A target belongs to the step that consumes the dataset, not to
|
|
2077
|
+
the dataset. There is no replacement, and none is owed.
|
|
1977
2078
|
|
|
1978
|
-
Do not reconstruct it either.
|
|
1979
|
-
|
|
1980
|
-
|
|
1981
|
-
outcome, say that the
|
|
1982
|
-
|
|
2079
|
+
Do not reconstruct it in the statement either. A window function that shifts a measured value
|
|
2080
|
+
forward in time and a self join that reads a later row are the same claim under another spelling,
|
|
2081
|
+
and no check catches either — the transform engine refuses what cannot re-derive, not what is
|
|
2082
|
+
modelled. Where a request asks for a future outcome, say that the build seals the observed table and
|
|
2083
|
+
that the horizon is chosen downstream.
|
|
1983
2084
|
|
|
1984
|
-
Work sealed
|
|
1985
|
-
|
|
1986
|
-
|
|
2085
|
+
Work sealed before the retirement is unaffected: such a table still verifies and replays, and such a
|
|
2086
|
+
Recipe still runs.
|
|
2087
|
+
[Units and vocabulary](https://mostlyright.md/docs/reference/units/) records the withdrawal and what
|
|
2088
|
+
a reader of such a Build should expect from it.
|
|
1987
2089
|
|
|
1988
2090
|
## Boundaries
|
|
1989
2091
|
|
|
1990
|
-
-
|
|
1991
|
-
|
|
1992
|
-
|
|
2092
|
+
- The transform's `duckdb_sql` steps are the only executable text a Recipe carries, and they run on
|
|
2093
|
+
the backend under the confinement above. Everything else in the document stays declarative: no
|
|
2094
|
+
Python, no shell, no plugins, no redirects, no callables.
|
|
2095
|
+
- Use only contract-supported connectors, Readers, checks and resource bounds.
|
|
1993
2096
|
- Do not claim that recipe registration fetched a source, that a declared check released a table
|
|
1994
2097
|
version, or that agent output executed a transformation.
|
|
1995
2098
|
- Preserve the cause and acceptance condition for blocker, critical, and high findings. This
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
interface:
|
|
2
2
|
display_name: "Mostly Right Data Build"
|
|
3
3
|
short_description: "Build and verify reviewed datasets"
|
|
4
|
-
default_prompt: "Use $mr-data-build to autonomously deliver the requested dataset outcome before inspecting CLI help, documentation, schemas, fixtures, examples, prior runs, or installed package details whenever the request uses, tests, demonstrates, or debugs the Harness. If the host requires a skill-use disclosure, send only one outcome-specific sentence naming $mr-data-build before the first tool call; otherwise start silently. Never narrate preparation, skill loading, CLI discovery, authentication, document or contract lookup, example searches, package versions, command batches, or acquisition-document authoring. Never narrate skill instructions, commands, receipts, events, protocols, status codes, service behavior, or notebook mechanics. Open the request's canonical Dataset page first when that address can be minted, and carry on without it rather than blocking. Keep routine work silent unless the host requires periodic status; then send concise outcome-oriented updates without mechanics or internal language, grounded in domain-specific observed evidence, a decision, required user action, or the verified outcome."
|
|
4
|
+
default_prompt: "Use $mr-data-build to autonomously deliver the requested dataset outcome before inspecting CLI help, documentation, schemas, fixtures, examples, prior runs, or installed package details whenever the request uses, tests, demonstrates, or debugs the Harness. If the host requires a skill-use disclosure, send only one outcome-specific sentence naming $mr-data-build before the first tool call; otherwise start silently. Never narrate preparation, skill loading, CLI discovery, authentication, document or contract lookup, example searches, package versions, command batches, or acquisition-document authoring. Never narrate skill instructions, commands, receipts, events, protocols, status codes, service behavior, or notebook mechanics. Open the request's canonical Dataset page first when that address can be minted, and carry on without it rather than blocking. Keep routine work silent unless the host requires periodic status; then send concise outcome-oriented updates without mechanics or internal language, grounded in domain-specific observed evidence, a decision, required user action, or the verified outcome. Fetch the published reference at https://mostlyright.md/docs/ for the recipe field, connector, Reader, transform, check, unit, command flag, error code, ceiling or worked example in front of you before drafting it; it is the contract, it wins over any memory of an older version, and fetching it is preparation you never narrate."
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{mostlyright_data-0.19.1 → mostlyright_data-0.19.2}/src/mostlyright/data_harness/__init__.py
RENAMED
|
File without changes
|
{mostlyright_data-0.19.1 → mostlyright_data-0.19.2}/src/mostlyright/data_harness/canonical.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{mostlyright_data-0.19.1 → mostlyright_data-0.19.2}/src/mostlyright/data_harness/key_seam.py
RENAMED
|
File without changes
|
{mostlyright_data-0.19.1 → mostlyright_data-0.19.2}/src/mostlyright/data_harness/page_coverage.py
RENAMED
|
File without changes
|
|
File without changes
|
{mostlyright_data-0.19.1 → mostlyright_data-0.19.2}/src/mostlyright/data_harness/session_probes.py
RENAMED
|
File without changes
|
{mostlyright_data-0.19.1 → mostlyright_data-0.19.2}/src/mostlyright/data_harness/skill_assets.py
RENAMED
|
File without changes
|
{mostlyright_data-0.19.1 → mostlyright_data-0.19.2}/src/mostlyright/data_harness/table_manifest.py
RENAMED
|
File without changes
|
{mostlyright_data-0.19.1 → mostlyright_data-0.19.2}/src/mostlyright/data_harness/thin/__init__.py
RENAMED
|
File without changes
|
{mostlyright_data-0.19.1 → mostlyright_data-0.19.2}/src/mostlyright/data_harness/thin/acquire.py
RENAMED
|
File without changes
|
|
File without changes
|
{mostlyright_data-0.19.1 → mostlyright_data-0.19.2}/src/mostlyright/data_harness/thin/activity.py
RENAMED
|
File without changes
|
{mostlyright_data-0.19.1 → mostlyright_data-0.19.2}/src/mostlyright/data_harness/thin/approvals.py
RENAMED
|
File without changes
|
{mostlyright_data-0.19.1 → mostlyright_data-0.19.2}/src/mostlyright/data_harness/thin/categories.py
RENAMED
|
File without changes
|
{mostlyright_data-0.19.1 → mostlyright_data-0.19.2}/src/mostlyright/data_harness/thin/commands.py
RENAMED
|
File without changes
|
|
File without changes
|
{mostlyright_data-0.19.1 → mostlyright_data-0.19.2}/src/mostlyright/data_harness/thin/download.py
RENAMED
|
File without changes
|
{mostlyright_data-0.19.1 → mostlyright_data-0.19.2}/src/mostlyright/data_harness/thin/narrative.py
RENAMED
|
File without changes
|
{mostlyright_data-0.19.1 → mostlyright_data-0.19.2}/src/mostlyright/data_harness/thin/parity.py
RENAMED
|
File without changes
|
{mostlyright_data-0.19.1 → mostlyright_data-0.19.2}/src/mostlyright/data_harness/thin/probe.py
RENAMED
|
File without changes
|
|
File without changes
|
{mostlyright_data-0.19.1 → mostlyright_data-0.19.2}/src/mostlyright/data_harness/thin/propose.py
RENAMED
|
File without changes
|
{mostlyright_data-0.19.1 → mostlyright_data-0.19.2}/src/mostlyright/data_harness/thin/recipe.py
RENAMED
|
File without changes
|
{mostlyright_data-0.19.1 → mostlyright_data-0.19.2}/src/mostlyright/data_harness/thin/research.py
RENAMED
|
File without changes
|
{mostlyright_data-0.19.1 → mostlyright_data-0.19.2}/src/mostlyright/data_harness/thin/router.py
RENAMED
|
File without changes
|
{mostlyright_data-0.19.1 → mostlyright_data-0.19.2}/src/mostlyright/data_harness/thin/runs.py
RENAMED
|
File without changes
|
{mostlyright_data-0.19.1 → mostlyright_data-0.19.2}/src/mostlyright/data_harness/thin/session.py
RENAMED
|
File without changes
|
{mostlyright_data-0.19.1 → mostlyright_data-0.19.2}/src/mostlyright/data_harness/thin/stream.py
RENAMED
|
File without changes
|
|
File without changes
|
{mostlyright_data-0.19.1 → mostlyright_data-0.19.2}/src/mostlyright/data_harness/thin/transport.py
RENAMED
|
File without changes
|
{mostlyright_data-0.19.1 → mostlyright_data-0.19.2}/src/mostlyright/data_harness/thin/user_agent.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{mostlyright_data-0.19.1 → mostlyright_data-0.19.2}/src/mostlyright/data_harness/thin/v4_catalog.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{mostlyright_data-0.19.1 → mostlyright_data-0.19.2}/src/mostlyright/data_harness/thin/v4_datasets.py
RENAMED
|
File without changes
|
{mostlyright_data-0.19.1 → mostlyright_data-0.19.2}/src/mostlyright/data_harness/thin/v4_handoff.py
RENAMED
|
File without changes
|
|
File without changes
|
{mostlyright_data-0.19.1 → mostlyright_data-0.19.2}/src/mostlyright/data_harness/thin/v4_query.py
RENAMED
|
File without changes
|
{mostlyright_data-0.19.1 → mostlyright_data-0.19.2}/src/mostlyright/data_harness/thin/v4_runs.py
RENAMED
|
File without changes
|
{mostlyright_data-0.19.1 → mostlyright_data-0.19.2}/src/mostlyright/data_harness/thin/v4_secrets.py
RENAMED
|
File without changes
|
{mostlyright_data-0.19.1 → mostlyright_data-0.19.2}/src/mostlyright/data_harness/thin/v4_stream.py
RENAMED
|
File without changes
|
{mostlyright_data-0.19.1 → mostlyright_data-0.19.2}/src/mostlyright/data_harness/thin/v4_tables.py
RENAMED
|
File without changes
|
{mostlyright_data-0.19.1 → mostlyright_data-0.19.2}/src/mostlyright/data_harness/thin/vocabulary.py
RENAMED
|
File without changes
|
{mostlyright_data-0.19.1 → mostlyright_data-0.19.2}/src/mostlyright/data_harness/ux/__init__.py
RENAMED
|
File without changes
|
{mostlyright_data-0.19.1 → mostlyright_data-0.19.2}/src/mostlyright/data_harness/ux/attendance.py
RENAMED
|
File without changes
|
{mostlyright_data-0.19.1 → mostlyright_data-0.19.2}/src/mostlyright/data_harness/ux/clarification.py
RENAMED
|
File without changes
|
{mostlyright_data-0.19.1 → mostlyright_data-0.19.2}/src/mostlyright/data_harness/ux/cloud_auth.py
RENAMED
|
File without changes
|
|
File without changes
|
{mostlyright_data-0.19.1 → mostlyright_data-0.19.2}/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.19.1 → mostlyright_data-0.19.2}/src/mostlyright/data_harness/ux/credentials.py
RENAMED
|
File without changes
|
{mostlyright_data-0.19.1 → mostlyright_data-0.19.2}/src/mostlyright/data_harness/ux/login.py
RENAMED
|
File without changes
|
{mostlyright_data-0.19.1 → mostlyright_data-0.19.2}/src/mostlyright/data_harness/ux/path_kind.py
RENAMED
|
File without changes
|
{mostlyright_data-0.19.1 → mostlyright_data-0.19.2}/src/mostlyright/data_harness/ux/plain_file.py
RENAMED
|
File without changes
|
{mostlyright_data-0.19.1 → mostlyright_data-0.19.2}/src/mostlyright/data_harness/ux/remediation.py
RENAMED
|
File without changes
|
{mostlyright_data-0.19.1 → mostlyright_data-0.19.2}/src/mostlyright/data_harness/ux/render.py
RENAMED
|
File without changes
|