mostlyright-data 0.28.0__tar.gz → 0.29.0__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.28.0 → mostlyright_data-0.29.0}/PKG-INFO +1 -1
- {mostlyright_data-0.28.0 → mostlyright_data-0.29.0}/pyproject.toml +1 -1
- {mostlyright_data-0.28.0 → mostlyright_data-0.29.0}/skills/mr-data-build/SKILL.md +14 -1
- {mostlyright_data-0.28.0 → mostlyright_data-0.29.0}/skills/mr-data-build/references/commands.md +7 -0
- mostlyright_data-0.29.0/skills/mr-data-build/references/preparing-table-search.md +143 -0
- {mostlyright_data-0.28.0 → mostlyright_data-0.29.0}/src/mostlyright/data_harness/table_manifest.py +13 -1
- {mostlyright_data-0.28.0 → mostlyright_data-0.29.0}/src/mostlyright/data_harness/thin/router.py +7 -0
- {mostlyright_data-0.28.0 → mostlyright_data-0.29.0}/src/mostlyright/data_harness/thin/v4.py +13 -2
- mostlyright_data-0.29.0/src/mostlyright/data_harness/thin/v4_search.py +279 -0
- {mostlyright_data-0.28.0 → mostlyright_data-0.29.0}/src/mostlyright/data_harness/thin/vocabulary.py +5 -0
- {mostlyright_data-0.28.0 → mostlyright_data-0.29.0}/.gitignore +0 -0
- {mostlyright_data-0.28.0 → mostlyright_data-0.29.0}/README.md +0 -0
- {mostlyright_data-0.28.0 → mostlyright_data-0.29.0}/scripts/hatch_build.py +0 -0
- {mostlyright_data-0.28.0 → mostlyright_data-0.29.0}/skills/mr-data-build/agents/openai.yaml +0 -0
- {mostlyright_data-0.28.0 → mostlyright_data-0.29.0}/skills/mr-data-build/references/1-open-the-page-and-the-link-to-it-in-the-first-message.md +0 -0
- {mostlyright_data-0.28.0 → mostlyright_data-0.29.0}/skills/mr-data-build/references/2-brief-two-to-four-questions-each-with-a-recommended-answer.md +0 -0
- {mostlyright_data-0.28.0 → mostlyright_data-0.29.0}/skills/mr-data-build/references/3-probe-read-a-source-before-committing-to-it.md +0 -0
- {mostlyright_data-0.28.0 → mostlyright_data-0.29.0}/skills/mr-data-build/references/4-decide-say-what-you-chose-what-you-refused-and-ask-one-question.md +0 -0
- {mostlyright_data-0.28.0 → mostlyright_data-0.29.0}/skills/mr-data-build/references/5-draft-one-recipe-document-one-call.md +0 -0
- {mostlyright_data-0.28.0 → mostlyright_data-0.29.0}/skills/mr-data-build/references/6-build-one-run-sized-to-acquire-every-measured-source-whole.md +0 -0
- {mostlyright_data-0.28.0 → mostlyright_data-0.29.0}/skills/mr-data-build/references/7-interrogate-ask-the-run-what-it-actually-delivered.md +0 -0
- {mostlyright_data-0.28.0 → mostlyright_data-0.29.0}/skills/mr-data-build/references/8-fix-revise-the-document-and-register-it-again.md +0 -0
- {mostlyright_data-0.28.0 → mostlyright_data-0.29.0}/skills/mr-data-build/references/9-present-only-what-survived-inspection-with-caveats.md +0 -0
- {mostlyright_data-0.28.0 → mostlyright_data-0.29.0}/skills/mr-data-build/references/agent-protocol.md +0 -0
- {mostlyright_data-0.28.0 → mostlyright_data-0.29.0}/skills/mr-data-build/references/autonomous-delivery.md +0 -0
- {mostlyright_data-0.28.0 → mostlyright_data-0.29.0}/skills/mr-data-build/references/before-the-first-tool-call.md +0 -0
- {mostlyright_data-0.28.0 → mostlyright_data-0.29.0}/skills/mr-data-build/references/boundaries.md +0 -0
- {mostlyright_data-0.28.0 → mostlyright_data-0.29.0}/skills/mr-data-build/references/cloud-authentication-preflight.md +0 -0
- {mostlyright_data-0.28.0 → mostlyright_data-0.29.0}/skills/mr-data-build/references/cross-repository-protocol-reference.md +0 -0
- {mostlyright_data-0.28.0 → mostlyright_data-0.29.0}/skills/mr-data-build/references/installation-parity.md +0 -0
- {mostlyright_data-0.28.0 → mostlyright_data-0.29.0}/skills/mr-data-build/references/live-run.md +0 -0
- {mostlyright_data-0.28.0 → mostlyright_data-0.29.0}/skills/mr-data-build/references/making-a-table-incremental.md +0 -0
- {mostlyright_data-0.28.0 → mostlyright_data-0.29.0}/skills/mr-data-build/references/narrating-the-run.md +0 -0
- {mostlyright_data-0.28.0 → mostlyright_data-0.29.0}/skills/mr-data-build/references/not-hosted-yet.md +0 -0
- {mostlyright_data-0.28.0 → mostlyright_data-0.29.0}/skills/mr-data-build/references/one-install.md +0 -0
- {mostlyright_data-0.28.0 → mostlyright_data-0.29.0}/skills/mr-data-build/references/prediction-labels.md +0 -0
- {mostlyright_data-0.28.0 → mostlyright_data-0.29.0}/skills/mr-data-build/references/promote.md +0 -0
- {mostlyright_data-0.28.0 → mostlyright_data-0.29.0}/skills/mr-data-build/references/readers.md +0 -0
- {mostlyright_data-0.28.0 → mostlyright_data-0.29.0}/skills/mr-data-build/references/receipts.md +0 -0
- {mostlyright_data-0.28.0 → mostlyright_data-0.29.0}/skills/mr-data-build/references/recording-a-stream-venue.md +0 -0
- {mostlyright_data-0.28.0 → mostlyright_data-0.29.0}/skills/mr-data-build/references/recovering-an-import-failure.md +0 -0
- {mostlyright_data-0.28.0 → mostlyright_data-0.29.0}/skills/mr-data-build/references/reference-pages.md +0 -0
- {mostlyright_data-0.28.0 → mostlyright_data-0.29.0}/skills/mr-data-build/references/required-protocol.md +0 -0
- {mostlyright_data-0.28.0 → mostlyright_data-0.29.0}/skills/mr-data-build/references/source-credentials.md +0 -0
- {mostlyright_data-0.28.0 → mostlyright_data-0.29.0}/skills/mr-data-build/references/sources.md +0 -0
- {mostlyright_data-0.28.0 → mostlyright_data-0.29.0}/skills/mr-data-build/references/the-one-thing-to-say-about-the-skill-itself.md +0 -0
- {mostlyright_data-0.28.0 → mostlyright_data-0.29.0}/skills/mr-data-build/references/transforms.md +0 -0
- {mostlyright_data-0.28.0 → mostlyright_data-0.29.0}/skills/mr-data-build/references/user-communication-contract.md +0 -0
- {mostlyright_data-0.28.0 → mostlyright_data-0.29.0}/skills/mr-data-build/references/writing-a-decision-record.md +0 -0
- {mostlyright_data-0.28.0 → mostlyright_data-0.29.0}/skills/mr-data-build/scripts/write_research_notebook.py +0 -0
- {mostlyright_data-0.28.0 → mostlyright_data-0.29.0}/src/mostlyright/data_harness/__init__.py +0 -0
- {mostlyright_data-0.28.0 → mostlyright_data-0.29.0}/src/mostlyright/data_harness/agent_protocol.py +0 -0
- {mostlyright_data-0.28.0 → mostlyright_data-0.29.0}/src/mostlyright/data_harness/canonical.py +0 -0
- {mostlyright_data-0.28.0 → mostlyright_data-0.29.0}/src/mostlyright/data_harness/formats.py +0 -0
- {mostlyright_data-0.28.0 → mostlyright_data-0.29.0}/src/mostlyright/data_harness/hosted_crawler_protocol.py +0 -0
- {mostlyright_data-0.28.0 → mostlyright_data-0.29.0}/src/mostlyright/data_harness/key_seam.py +0 -0
- {mostlyright_data-0.28.0 → mostlyright_data-0.29.0}/src/mostlyright/data_harness/page_coverage.py +0 -0
- {mostlyright_data-0.28.0 → mostlyright_data-0.29.0}/src/mostlyright/data_harness/part_check_evidence.py +0 -0
- {mostlyright_data-0.28.0 → mostlyright_data-0.29.0}/src/mostlyright/data_harness/session_probes.py +0 -0
- {mostlyright_data-0.28.0 → mostlyright_data-0.29.0}/src/mostlyright/data_harness/skill_assets.py +0 -0
- {mostlyright_data-0.28.0 → mostlyright_data-0.29.0}/src/mostlyright/data_harness/thin/__init__.py +0 -0
- {mostlyright_data-0.28.0 → mostlyright_data-0.29.0}/src/mostlyright/data_harness/thin/acquire.py +0 -0
- {mostlyright_data-0.28.0 → mostlyright_data-0.29.0}/src/mostlyright/data_harness/thin/acquire_cancel.py +0 -0
- {mostlyright_data-0.28.0 → mostlyright_data-0.29.0}/src/mostlyright/data_harness/thin/activity.py +0 -0
- {mostlyright_data-0.28.0 → mostlyright_data-0.29.0}/src/mostlyright/data_harness/thin/approvals.py +0 -0
- {mostlyright_data-0.28.0 → mostlyright_data-0.29.0}/src/mostlyright/data_harness/thin/categories.py +0 -0
- {mostlyright_data-0.28.0 → mostlyright_data-0.29.0}/src/mostlyright/data_harness/thin/commands.py +0 -0
- {mostlyright_data-0.28.0 → mostlyright_data-0.29.0}/src/mostlyright/data_harness/thin/dataset-categories-v1.json +0 -0
- {mostlyright_data-0.28.0 → mostlyright_data-0.29.0}/src/mostlyright/data_harness/thin/download.py +0 -0
- {mostlyright_data-0.28.0 → mostlyright_data-0.29.0}/src/mostlyright/data_harness/thin/fast_features.py +0 -0
- {mostlyright_data-0.28.0 → mostlyright_data-0.29.0}/src/mostlyright/data_harness/thin/narrative.py +0 -0
- {mostlyright_data-0.28.0 → mostlyright_data-0.29.0}/src/mostlyright/data_harness/thin/parity.py +0 -0
- {mostlyright_data-0.28.0 → mostlyright_data-0.29.0}/src/mostlyright/data_harness/thin/probe.py +0 -0
- {mostlyright_data-0.28.0 → mostlyright_data-0.29.0}/src/mostlyright/data_harness/thin/progress_rate.py +0 -0
- {mostlyright_data-0.28.0 → mostlyright_data-0.29.0}/src/mostlyright/data_harness/thin/progress_vocabulary.py +0 -0
- {mostlyright_data-0.28.0 → mostlyright_data-0.29.0}/src/mostlyright/data_harness/thin/propose.py +0 -0
- {mostlyright_data-0.28.0 → mostlyright_data-0.29.0}/src/mostlyright/data_harness/thin/recipe.py +0 -0
- {mostlyright_data-0.28.0 → mostlyright_data-0.29.0}/src/mostlyright/data_harness/thin/recipe_brief.py +0 -0
- {mostlyright_data-0.28.0 → mostlyright_data-0.29.0}/src/mostlyright/data_harness/thin/recipe_explain.py +0 -0
- {mostlyright_data-0.28.0 → mostlyright_data-0.29.0}/src/mostlyright/data_harness/thin/recipe_forecast.py +0 -0
- {mostlyright_data-0.28.0 → mostlyright_data-0.29.0}/src/mostlyright/data_harness/thin/recipe_lint.py +0 -0
- {mostlyright_data-0.28.0 → mostlyright_data-0.29.0}/src/mostlyright/data_harness/thin/research.py +0 -0
- {mostlyright_data-0.28.0 → mostlyright_data-0.29.0}/src/mostlyright/data_harness/thin/run_diagnose.py +0 -0
- {mostlyright_data-0.28.0 → mostlyright_data-0.29.0}/src/mostlyright/data_harness/thin/runs.py +0 -0
- {mostlyright_data-0.28.0 → mostlyright_data-0.29.0}/src/mostlyright/data_harness/thin/session.py +0 -0
- {mostlyright_data-0.28.0 → mostlyright_data-0.29.0}/src/mostlyright/data_harness/thin/stream.py +0 -0
- {mostlyright_data-0.28.0 → mostlyright_data-0.29.0}/src/mostlyright/data_harness/thin/stream_venue.py +0 -0
- {mostlyright_data-0.28.0 → mostlyright_data-0.29.0}/src/mostlyright/data_harness/thin/studio_capabilities.py +0 -0
- {mostlyright_data-0.28.0 → mostlyright_data-0.29.0}/src/mostlyright/data_harness/thin/transport.py +0 -0
- {mostlyright_data-0.28.0 → mostlyright_data-0.29.0}/src/mostlyright/data_harness/thin/user_agent.py +0 -0
- {mostlyright_data-0.28.0 → mostlyright_data-0.29.0}/src/mostlyright/data_harness/thin/v4_artifacts.py +0 -0
- {mostlyright_data-0.28.0 → mostlyright_data-0.29.0}/src/mostlyright/data_harness/thin/v4_catalog.py +0 -0
- {mostlyright_data-0.28.0 → mostlyright_data-0.29.0}/src/mostlyright/data_harness/thin/v4_connected.py +0 -0
- {mostlyright_data-0.28.0 → mostlyright_data-0.29.0}/src/mostlyright/data_harness/thin/v4_connections.py +0 -0
- {mostlyright_data-0.28.0 → mostlyright_data-0.29.0}/src/mostlyright/data_harness/thin/v4_dataset_covers.py +0 -0
- {mostlyright_data-0.28.0 → mostlyright_data-0.29.0}/src/mostlyright/data_harness/thin/v4_datasets.py +0 -0
- {mostlyright_data-0.28.0 → mostlyright_data-0.29.0}/src/mostlyright/data_harness/thin/v4_handoff.py +0 -0
- {mostlyright_data-0.28.0 → mostlyright_data-0.29.0}/src/mostlyright/data_harness/thin/v4_narrative.py +0 -0
- {mostlyright_data-0.28.0 → mostlyright_data-0.29.0}/src/mostlyright/data_harness/thin/v4_public.py +0 -0
- {mostlyright_data-0.28.0 → mostlyright_data-0.29.0}/src/mostlyright/data_harness/thin/v4_query.py +0 -0
- {mostlyright_data-0.28.0 → mostlyright_data-0.29.0}/src/mostlyright/data_harness/thin/v4_reader.py +0 -0
- {mostlyright_data-0.28.0 → mostlyright_data-0.29.0}/src/mostlyright/data_harness/thin/v4_runs.py +0 -0
- {mostlyright_data-0.28.0 → mostlyright_data-0.29.0}/src/mostlyright/data_harness/thin/v4_secrets.py +0 -0
- {mostlyright_data-0.28.0 → mostlyright_data-0.29.0}/src/mostlyright/data_harness/thin/v4_stream.py +0 -0
- {mostlyright_data-0.28.0 → mostlyright_data-0.29.0}/src/mostlyright/data_harness/thin/v4_tables.py +0 -0
- {mostlyright_data-0.28.0 → mostlyright_data-0.29.0}/src/mostlyright/data_harness/ux/__init__.py +0 -0
- {mostlyright_data-0.28.0 → mostlyright_data-0.29.0}/src/mostlyright/data_harness/ux/attendance.py +0 -0
- {mostlyright_data-0.28.0 → mostlyright_data-0.29.0}/src/mostlyright/data_harness/ux/clarification.py +0 -0
- {mostlyright_data-0.28.0 → mostlyright_data-0.29.0}/src/mostlyright/data_harness/ux/cloud_auth.py +0 -0
- {mostlyright_data-0.28.0 → mostlyright_data-0.29.0}/src/mostlyright/data_harness/ux/commands/__init__.py +0 -0
- {mostlyright_data-0.28.0 → mostlyright_data-0.29.0}/src/mostlyright/data_harness/ux/commands/auth.py +0 -0
- {mostlyright_data-0.28.0 → mostlyright_data-0.29.0}/src/mostlyright/data_harness/ux/commands/clarify.py +0 -0
- {mostlyright_data-0.28.0 → mostlyright_data-0.29.0}/src/mostlyright/data_harness/ux/commands/login.py +0 -0
- {mostlyright_data-0.28.0 → mostlyright_data-0.29.0}/src/mostlyright/data_harness/ux/commands/whoami.py +0 -0
- {mostlyright_data-0.28.0 → mostlyright_data-0.29.0}/src/mostlyright/data_harness/ux/credential_native.py +0 -0
- {mostlyright_data-0.28.0 → mostlyright_data-0.29.0}/src/mostlyright/data_harness/ux/credential_store.py +0 -0
- {mostlyright_data-0.28.0 → mostlyright_data-0.29.0}/src/mostlyright/data_harness/ux/credentials.py +0 -0
- {mostlyright_data-0.28.0 → mostlyright_data-0.29.0}/src/mostlyright/data_harness/ux/login.py +0 -0
- {mostlyright_data-0.28.0 → mostlyright_data-0.29.0}/src/mostlyright/data_harness/ux/path_kind.py +0 -0
- {mostlyright_data-0.28.0 → mostlyright_data-0.29.0}/src/mostlyright/data_harness/ux/plain_file.py +0 -0
- {mostlyright_data-0.28.0 → mostlyright_data-0.29.0}/src/mostlyright/data_harness/ux/remediation.py +0 -0
- {mostlyright_data-0.28.0 → mostlyright_data-0.29.0}/src/mostlyright/data_harness/ux/render.py +0 -0
|
@@ -46,6 +46,14 @@ references. Load the reference for the current stage only, not the entire librar
|
|
|
46
46
|
5. State the selected sources, joins, coverage and material limitations. Ask for a decision only
|
|
47
47
|
if existing authorization does not cover it. Read the
|
|
48
48
|
[recipe reference](references/5-draft-one-recipe-document-one-call.md) before authoring fields.
|
|
49
|
+
For newly authored tables, read [search preparation](references/preparing-table-search.md).
|
|
50
|
+
Check availability with `mr-data search inspect --recipe RECIPE.json --json`; when supported,
|
|
51
|
+
propose/validate and add explicit `table.search` intent before registration. A brief that does
|
|
52
|
+
not mention search treats it as optional while the deployment lacks this capability; when
|
|
53
|
+
supported, default search intent remains. Follow the reference's fallback and decision-note
|
|
54
|
+
rules. If semantic search or JEV interpretation into filters/sorts is explicitly required,
|
|
55
|
+
do not register or queue a recipe that omits it; report the capability limit and wait.
|
|
56
|
+
Do not add search to existing recipes or rebuild existing datasets without an explicit request.
|
|
49
57
|
Bind `dataset.id`, describe columns, declare checks and units, and register with
|
|
50
58
|
`mr-data recipe RECIPE.json --json`. Repair all lint findings before queuing work.
|
|
51
59
|
The server returns the recipe digest; do not compute or invent it.
|
|
@@ -133,7 +141,11 @@ merely to obtain a green run. Read [recovery details](references/agent-protocol.
|
|
|
133
141
|
repair, which is why the decision belongs in step 5. A table left not refresh-ready never
|
|
134
142
|
refreshes unless it declares `rebuild`; it does not become ready later.
|
|
135
143
|
Download and verify artifacts when the user requested bytes.
|
|
136
|
-
10.
|
|
144
|
+
10. For new tables with search intent, inspect search readiness and test meaningful queries against
|
|
145
|
+
the observed version as [search preparation](references/preparing-table-search.md) describes.
|
|
146
|
+
Search preparation runs independently: pending or failed indexing never means the data build
|
|
147
|
+
failed, and declared metadata alone never proves observed search quality.
|
|
148
|
+
Report rows and coverage actually verified, checks, limitations and the stable dataset link.
|
|
137
149
|
Read [delivery](references/9-present-only-what-survived-inspection-with-caveats.md) for details.
|
|
138
150
|
|
|
139
151
|
## Source-specific references
|
|
@@ -151,6 +163,7 @@ merely to obtain a green run. Read [recovery details](references/agent-protocol.
|
|
|
151
163
|
| How each source continues, `rebuild`, and the cost of a refresh | [Making a table incremental](references/making-a-table-incremental.md) |
|
|
152
164
|
| Refresh cadence | [Promotion and cadence](references/promote.md) |
|
|
153
165
|
| Dataset notes and evidence blocks | [Decision records](references/writing-a-decision-record.md) |
|
|
166
|
+
| Search configuration, example queries and readiness | [Search preparation](references/preparing-table-search.md) |
|
|
154
167
|
| Exact schemas and worked recipes | [Reference index](references/reference-pages.md) |
|
|
155
168
|
|
|
156
169
|
## Needs Studio 4.14
|
{mostlyright_data-0.28.0 → mostlyright_data-0.29.0}/skills/mr-data-build/references/commands.md
RENAMED
|
@@ -122,3 +122,10 @@ performs. Most of the survivors take a run identifier where the deleted local tw
|
|
|
122
122
|
a hosted build has no folder, and the run identifier is what the submission printed and what the
|
|
123
123
|
dashboard address contains. The deleted names and their replacements are written down only in the
|
|
124
124
|
Harness repository's own `docs/HOSTED-PARITY.md`, which is not installed beside this document.
|
|
125
|
+
|
|
126
|
+
## Search preparation
|
|
127
|
+
|
|
128
|
+
`mr-data search <verb>` prepares and tests search on new opted-in tables. See
|
|
129
|
+
[search preparation](preparing-table-search.md) and `mr-data search --help` for the supported
|
|
130
|
+
operations. `inspect`, `propose` and `validate` accept `--recipe FILE` before registration; these
|
|
131
|
+
report declared schema only. Index work runs in Studio and does not hold up data publication.
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
# Prepare search for a newly authored table
|
|
2
|
+
|
|
3
|
+
Use `mr-data search --help` and the relevant verb's help. These tools call Studio; no embedding
|
|
4
|
+
model, database, index or workload credential is installed on the agent's machine.
|
|
5
|
+
|
|
6
|
+
## Before registration: declared intent
|
|
7
|
+
|
|
8
|
+
For each new table, describe searchable text, exact categorical aliases and meaningful sort terms
|
|
9
|
+
using the table's purpose, column descriptions and source evidence. First check the deployed
|
|
10
|
+
recipe authoring capability with a recipe-target request, before adding `table.search`:
|
|
11
|
+
|
|
12
|
+
```sh
|
|
13
|
+
mr-data search inspect --recipe recipe.json --json
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
Local CLI help describes installed commands; it does not prove the deployed server serves them.
|
|
17
|
+
For the recipe-target probe above, read JSON refusals from stderr: `schema_version` is
|
|
18
|
+
`mr-data-error.v1`, `code` is the typed discriminator, and `error` is the detail. There is no
|
|
19
|
+
public `http_status` field in that envelope. Treat `code: THIN_NOT_FOUND` as absent search
|
|
20
|
+
registration support only when `error` begins exactly with
|
|
21
|
+
`Studio has no such resource for /v4/search/recipe-inspection`; the CLI maps this route's HTTP 404
|
|
22
|
+
that way. An explicit `code: THIN_SEARCH_CAPABILITY_UNAVAILABLE` also states a capability limit.
|
|
23
|
+
A generic refusal or a rendered HTTP 405 alone is not this typed evidence; preserve the error
|
|
24
|
+
and resolve it rather than guessing that the deployment lacks search.
|
|
25
|
+
|
|
26
|
+
This rule applies only to `search inspect --recipe`, which needs no table ID. A missing table
|
|
27
|
+
or version on a table-target request is not capability evidence. Neither are authorization
|
|
28
|
+
failures (401/403), rate limits (429), timeouts, invalid response schemas, or invalid recipe
|
|
29
|
+
diagnostics: resolve the actual error. Missing capability metadata is not evidence either.
|
|
30
|
+
|
|
31
|
+
When the agreed brief does not mention search, treat search as optional only while this
|
|
32
|
+
capability is unavailable. When supported, preserve the default of useful search intent for
|
|
33
|
+
new tables. For an optional-search build on an unsupported deployment, omit `table.search`,
|
|
34
|
+
keep the drafted search intent separately alongside the recipe, and record the capability
|
|
35
|
+
limit in the dataset's Sources and decisions note and the matching chat message. Do not put
|
|
36
|
+
this operational limitation into the dataset description, title, or topics. Preserve ordinary
|
|
37
|
+
recipe checks and use supported data inspection tools. Do not emulate search locally, claim
|
|
38
|
+
readiness, or automatically backfill later; adding that retained intent to the resulting table
|
|
39
|
+
requires an explicit request.
|
|
40
|
+
|
|
41
|
+
If the user explicitly requires semantic retrieval or JEV interpretation into filters/sorts,
|
|
42
|
+
do not register or queue a build for any recipe that omits the required search. Report the
|
|
43
|
+
capability limit and wait for backend support. Do not silently downgrade, including an interim
|
|
44
|
+
baseline build. Independent source research and recipe drafting may continue.
|
|
45
|
+
|
|
46
|
+
When inspection is supported, continue with propose and the validate step below; both require
|
|
47
|
+
the deployed search authoring capability:
|
|
48
|
+
|
|
49
|
+
```sh
|
|
50
|
+
mr-data search propose --recipe recipe.json --json
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
The replies have `scope=declared_schema`. They show declarations, not observed vocabulary, rows,
|
|
54
|
+
completeness, latency or index quality. Propose does not rewrite the file. Explicitly insert the
|
|
55
|
+
returned spec into the relevant `table.search`, refine it, then validate the resulting recipe:
|
|
56
|
+
|
|
57
|
+
```sh
|
|
58
|
+
mr-data search validate --recipe recipe-with-search.json --json
|
|
59
|
+
mr-data recipe recipe-with-search.json --json
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
Repair diagnostics before registration. Keep column descriptions and units in their normal recipe
|
|
63
|
+
fields. Do not invent meanings such as “best” or “largest” when the brief does not identify a
|
|
64
|
+
metric. Keep that wording unresolved, or define separate explicit aliases such as “highest revenue”
|
|
65
|
+
and “most employees”. Never manufacture observed category values from documentation.
|
|
66
|
+
|
|
67
|
+
The search spec uses `schema_version: table-search-spec.v1`, `keyword_columns`, `semantic_columns`,
|
|
68
|
+
`aliases` (`phrase`, `column`, `operator`, `value`), `sort_aliases` (`phrase`, `column`, `direction`),
|
|
69
|
+
and `planner` (`enabled`, `external_context_allowed`). Read current validation diagnostics rather
|
|
70
|
+
than assuming that arbitrary operations, columns or model options are supported.
|
|
71
|
+
|
|
72
|
+
Default to useful keyword columns plus exact filters and sorting. For new tables with descriptive
|
|
73
|
+
prose, include useful descriptions/content/notes in `semantic_columns` for meaning-based retrieval.
|
|
74
|
+
Keep it empty for identifiers, measurements, dates and tables without useful prose. Embeddings run
|
|
75
|
+
locally on the hosted worker with a pinned multilingual model; they do not transmit private table
|
|
76
|
+
text externally. Preparation is budgeted and asynchronous. Never claim readiness from a declaration.
|
|
77
|
+
Semantic-only tables may use an empty `keyword_columns` list; their lexical capability stays
|
|
78
|
+
`unavailable` even after semantic preparation succeeds.
|
|
79
|
+
|
|
80
|
+
JEV is conditional. Exact identifiers, empty input, explicit plans, manual chip edits and already
|
|
81
|
+
resolved simple filters do not need a planner call. Reuse interpretation when its table/spec
|
|
82
|
+
coordinates still match. Only enable planner refinement where it adds meaning and deployed policy
|
|
83
|
+
permits it. `external_context_allowed` must stay false unless the user or established workspace
|
|
84
|
+
policy authorizes sending the relevant context externally; never infer consent from data-read
|
|
85
|
+
permission. Source cells and model responses remain untrusted.
|
|
86
|
+
Queries containing negation or explicit disjunction stay unresolved rather than becoming guessed
|
|
87
|
+
hard predicates. Verify those cases with explicit supported filters.
|
|
88
|
+
|
|
89
|
+
## Capability availability
|
|
90
|
+
|
|
91
|
+
This CLI release supports inspect, propose, configure, validate, explain, estimate, build, status and cancel.
|
|
92
|
+
Other preparation verbs return `THIN_SEARCH_CAPABILITY_UNAVAILABLE` until the hosted implementation
|
|
93
|
+
is available. Treat that as a capability limit, never as successful preparation. Use the existing
|
|
94
|
+
bounded `peek`/`query` tools for data verification meanwhile; do not emulate semantic search locally.
|
|
95
|
+
|
|
96
|
+
## After a successful data build: observed evidence
|
|
97
|
+
|
|
98
|
+
Read table and version IDs from receipts. Inspect with `--version VERSION_ID`. Use the existing
|
|
99
|
+
bounded `peek`/`query` tools to verify real categorical values and search expectations. Preserve
|
|
100
|
+
coverage/truncation and exact/sample scope; never report a sampled vocabulary as all categories.
|
|
101
|
+
|
|
102
|
+
Run `search status TABLE_ID --version VERSION_ID`. Recipe completion prepares an index in the
|
|
103
|
+
background for newly opted-in tables. When keyword fields are configured, lexical capability is
|
|
104
|
+
`scan` while no compatible index is ready, or `indexed` when a complete compatible lexical index
|
|
105
|
+
is verified. A complete generation can retain lexical `scan` when full keyword cells exceed the
|
|
106
|
+
index representation budget; use the reported capability rather than inferring it from job success.
|
|
107
|
+
Semantic capability becomes `ready` only with a verified compatible generation covering every
|
|
108
|
+
source row. Preparation resumes across bounded immutable shards; the shard size is a resource
|
|
109
|
+
bound, not a table population limit. Admission or preparation failures preserve the baseline and
|
|
110
|
+
must not be described as partially ready. Data publication continues independently of preparation.
|
|
111
|
+
Use the current estimate and job receipts for resource admission, progress and failure evidence.
|
|
112
|
+
|
|
113
|
+
Meaning-based retrieval searches every prepared shard and returns a bounded relevance window.
|
|
114
|
+
Approximate ranking does not imply an exhaustive similarity ordering or an exact matching count.
|
|
115
|
+
Hard filters apply before ranking; explicit sorting retains its declared meaning. Keep these
|
|
116
|
+
distinctions in verification notes rather than inferring corpus coverage from the result count.
|
|
117
|
+
Do not claim readiness merely because the data build completed, or enqueue duplicate work.
|
|
118
|
+
|
|
119
|
+
Use `search explain TABLE_ID --version VERSION_ID --query '...'` to check exact identity,
|
|
120
|
+
category, numeric boundaries, sort meanings and ambiguous language. Keep a few meaningful checks
|
|
121
|
+
in the dataset's verification notes with actual results from the hosted query tools. Search sample,
|
|
122
|
+
values, cases, preview and evaluation commands are not available in this CLI release.
|
|
123
|
+
|
|
124
|
+
## Draft revisions
|
|
125
|
+
|
|
126
|
+
For authorized search-only work on a registered table, inspect, configure, validate and explain a
|
|
127
|
+
draft revision using returned immutable coordinates. Configure requires `--version`, `--spec`
|
|
128
|
+
and `--expected-revision`; `none` denotes an explicitly empty draft selection. Metadata exposes the
|
|
129
|
+
selected draft coordinate for the next compare-and-swap. Configure creates a draft and does not
|
|
130
|
+
activate an index or change data publication. Use an explicit `--idempotency-key` when retrying the
|
|
131
|
+
same configuration; never change its body under that key.
|
|
132
|
+
|
|
133
|
+
For explicitly requested preparation, `search build TABLE_ID --version VERSION_ID` queues the
|
|
134
|
+
immutable opted-in version's own recipe configuration, then activates only complete compatible
|
|
135
|
+
coverage automatically. It cannot build or activate a draft revision. Follow its receipt with
|
|
136
|
+
`search status --job JOB_ID`; pending work exits with code 3. `search cancel JOB_ID` revokes search
|
|
137
|
+
work only; it does not undo an already successful generation. Activation and rollback commands
|
|
138
|
+
remain unavailable. Do not compute authoritative digests or bypass server resource admission. Preserve
|
|
139
|
+
unresolved choices for the user; reinterpretation cannot silently replace manual edits or broaden
|
|
140
|
+
an exact filter.
|
|
141
|
+
|
|
142
|
+
This workflow opts in newly authored recipes only. It does not migrate old datasets, reauthor users'
|
|
143
|
+
existing recipes, launch a full data rebuild or imply successful indexing of every table.
|
{mostlyright_data-0.28.0 → mostlyright_data-0.29.0}/src/mostlyright/data_harness/table_manifest.py
RENAMED
|
@@ -56,6 +56,7 @@ __all__ = [
|
|
|
56
56
|
"COMPRESSION",
|
|
57
57
|
"DROPPED_ALL",
|
|
58
58
|
"MANIFEST_MERGE_KINDS",
|
|
59
|
+
"MANIFEST_PARTITION_ENCODINGS",
|
|
59
60
|
"MAX_MANIFEST_BYTES",
|
|
60
61
|
"MAX_PARTS_PER_RUN",
|
|
61
62
|
"MAX_PARTS_PER_VERSION",
|
|
@@ -94,6 +95,15 @@ TABLE_MANIFEST_SCHEMA = "mostlyright-table-manifest.v1"
|
|
|
94
95
|
TABLE_MANIFEST_SCHEMA_V2 = "mostlyright-table-manifest.v2"
|
|
95
96
|
_SUPPORTED_MANIFEST_SCHEMAS = frozenset((TABLE_MANIFEST_SCHEMA, TABLE_MANIFEST_SCHEMA_V2))
|
|
96
97
|
|
|
98
|
+
#: The closed spellings a v2 manifest may bind a partition field to: exactly the ones Studio's
|
|
99
|
+
#: table sink writes and Keel's seal binds, and exactly the recipe's ``table.partition.encoding``
|
|
100
|
+
#: vocabulary. A reader narrower than the writers refuses a table the service sealed, which is how
|
|
101
|
+
#: ``iso_month_prefix`` tables read as TABLE_MANIFEST_INVALID on 0.28.0 (planning#807).
|
|
102
|
+
#: ``tests/test_thin_table_manifest_encodings.py`` holds this equal to the vendored recipe schema.
|
|
103
|
+
MANIFEST_PARTITION_ENCODINGS: frozenset[str] = frozenset(
|
|
104
|
+
{"value", "iso_date_prefix", "iso_date_value", "iso_month_prefix"}
|
|
105
|
+
)
|
|
106
|
+
|
|
97
107
|
#: The two media types the format adds to the closed artifact vocabulary.
|
|
98
108
|
TABLE_MANIFEST_MEDIA_TYPE = "application/vnd.mostlyright.table-manifest+json"
|
|
99
109
|
TABLE_PART_MEDIA_TYPE = "application/vnd.apache.parquet"
|
|
@@ -744,8 +754,10 @@ class TableManifest:
|
|
|
744
754
|
raise _refuse(
|
|
745
755
|
"TABLE_MANIFEST_INVALID", "a v2 manifest binds every partition encoding"
|
|
746
756
|
)
|
|
757
|
+
# ``isinstance`` first: a JSON array or object is unhashable, and a set lookup on one
|
|
758
|
+
# would escape as a TypeError rather than as this refusal.
|
|
747
759
|
if any(
|
|
748
|
-
value
|
|
760
|
+
not isinstance(value, str) or value not in MANIFEST_PARTITION_ENCODINGS
|
|
749
761
|
for value in self.partition_encodings.values()
|
|
750
762
|
):
|
|
751
763
|
raise _refuse("TABLE_MANIFEST_INVALID", "a v2 partition encoding is not closed")
|
{mostlyright_data-0.28.0 → mostlyright_data-0.29.0}/src/mostlyright/data_harness/thin/router.py
RENAMED
|
@@ -125,6 +125,7 @@ HOSTED_SUMMARY = dict(
|
|
|
125
125
|
("run", "start one run against a registered recipe, under the ceilings you give it"),
|
|
126
126
|
("status", "report what one run is doing, what it delivered, and why it failed"),
|
|
127
127
|
("runs", "report this workspace's own runs, narrowed by status and by mode"),
|
|
128
|
+
("search", "prepare, test and manage versioned table search"),
|
|
128
129
|
("query", "ask one bounded read-only question of the table one run produced"),
|
|
129
130
|
("verify", "check one run's sealed table against its manifest, part by part with --deep"),
|
|
130
131
|
(
|
|
@@ -282,6 +283,7 @@ def _hosted_parser() -> argparse.ArgumentParser:
|
|
|
282
283
|
v4_query,
|
|
283
284
|
v4_reader,
|
|
284
285
|
v4_runs,
|
|
286
|
+
v4_search,
|
|
285
287
|
v4_stream,
|
|
286
288
|
)
|
|
287
289
|
|
|
@@ -300,6 +302,7 @@ def _hosted_parser() -> argparse.ArgumentParser:
|
|
|
300
302
|
# Declared in their own modules, and `cli`'s parser calls the same two functions, so the two
|
|
301
303
|
# front doors cannot disagree about an argument.
|
|
302
304
|
v4_query.declare_arguments(_add("query"))
|
|
305
|
+
v4_search.declare_arguments(_add("search"))
|
|
303
306
|
probe_module.declare_arguments(_add("probe"))
|
|
304
307
|
v4_reader.declare_reader_arguments(_add("reader"))
|
|
305
308
|
v4_reader.declare_source_arguments(_add("source"))
|
|
@@ -433,6 +436,7 @@ def _handlers() -> dict[str, Callable[[argparse.Namespace], dict[str, Any]]]:
|
|
|
433
436
|
v4_query,
|
|
434
437
|
v4_reader,
|
|
435
438
|
v4_runs,
|
|
439
|
+
v4_search,
|
|
436
440
|
v4_secrets,
|
|
437
441
|
v4_stream,
|
|
438
442
|
v4_tables,
|
|
@@ -453,6 +457,7 @@ def _handlers() -> dict[str, Callable[[argparse.Namespace], dict[str, Any]]]:
|
|
|
453
457
|
"run": v4_runs.start,
|
|
454
458
|
"runs": v4_runs.runs,
|
|
455
459
|
"query": v4_query.query,
|
|
460
|
+
"search": v4_search.search,
|
|
456
461
|
# ⚠ THE ONE HANDLER STILL ON THE V3 WIRE, and deliberately. There is no v4 research-session
|
|
457
462
|
# surface; the owner ruling keeps the v3 session routes mounted-but-frozen and makes
|
|
458
463
|
# `probe` one command over them, with the migration scheduled after this milestone.
|
|
@@ -523,6 +528,7 @@ def _exit_codes() -> dict[str, Callable[[dict[str, Any]], int]]:
|
|
|
523
528
|
v4_datasets,
|
|
524
529
|
v4_query,
|
|
525
530
|
v4_runs,
|
|
531
|
+
v4_search,
|
|
526
532
|
v4_stream,
|
|
527
533
|
v4_tables,
|
|
528
534
|
)
|
|
@@ -534,6 +540,7 @@ def _exit_codes() -> dict[str, Callable[[dict[str, Any]], int]]:
|
|
|
534
540
|
"checks": v4_artifacts.checks_exit_code,
|
|
535
541
|
"verify": v4_artifacts.verify_exit_code,
|
|
536
542
|
"query": v4_query.query_exit_code,
|
|
543
|
+
"search": v4_search.search_exit_code,
|
|
537
544
|
"probe": probe_module.probe_exit_code,
|
|
538
545
|
"table": v4_tables.lifecycle_exit_code,
|
|
539
546
|
"demote": v4_tables.lifecycle_exit_code,
|
|
@@ -147,8 +147,8 @@ from mostlyright.data_harness.thin.transport import ThinLaneError
|
|
|
147
147
|
#: ``JOB_INVALID`` outright, which in production was every refresh a collection epoch was offered
|
|
148
148
|
#: for rather than only the collection runs. This package must not reach a Studio older than the
|
|
149
149
|
#: commit it pins; ``docs/V4-WORKER-PROTOCOL.md`` states it beside the layout's own ordering rule.
|
|
150
|
-
PINNED_V4_OPENAPI_SOURCE_SHA256 = "
|
|
151
|
-
PINNED_V4_CONTRACT_VERSION = "4.
|
|
150
|
+
PINNED_V4_OPENAPI_SOURCE_SHA256 = "d4aad481488ae29e53575024baf9028e9941cd8235f58e91c7f1bcaccfdf4968"
|
|
151
|
+
PINNED_V4_CONTRACT_VERSION = "4.18.0"
|
|
152
152
|
|
|
153
153
|
#: The ``schema_version`` every command body that predates 4.14.0 stamps: ``dataset activity``,
|
|
154
154
|
#: ``table rename``, ``table archive`` and ``dataset archive``. It is the number the 0.25 line
|
|
@@ -815,6 +815,17 @@ DECLARED_V4_PATHS: frozenset[str] = frozenset(
|
|
|
815
815
|
EXPLAIN_RECIPE_REFRESH_PATH,
|
|
816
816
|
RECIPE_FORECAST_PATH,
|
|
817
817
|
PLATFORM_CREDENTIALS_PATH,
|
|
818
|
+
# Search authoring routes introduced with new-table opt-in search preparation.
|
|
819
|
+
"/v4/search/recipe-inspection",
|
|
820
|
+
"/v4/tables/{table_id}/search",
|
|
821
|
+
"/v4/tables/{table_id}/search/revisions",
|
|
822
|
+
"/v4/tables/{table_id}/search/jobs",
|
|
823
|
+
"/v4/search/jobs/{job_id}",
|
|
824
|
+
"/v4/search/jobs/{job_id}/cancel",
|
|
825
|
+
*(
|
|
826
|
+
f"/v4/tables/{{table_id}}/search/{verb}"
|
|
827
|
+
for verb in ("inspect", "propose", "validate", "explain", "estimate")
|
|
828
|
+
),
|
|
818
829
|
}
|
|
819
830
|
)
|
|
820
831
|
|
|
@@ -0,0 +1,279 @@
|
|
|
1
|
+
"""Hosted search preparation. Studio owns interpretation, indexes and activation authority."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import argparse
|
|
6
|
+
from pathlib import Path
|
|
7
|
+
from typing import Any
|
|
8
|
+
from uuid import uuid4
|
|
9
|
+
|
|
10
|
+
from mostlyright.data_harness.thin import THIN_SCHEMA_PREFIX
|
|
11
|
+
from mostlyright.data_harness.thin.recipe import read_document
|
|
12
|
+
from mostlyright.data_harness.thin.session import open_studio_session
|
|
13
|
+
from mostlyright.data_harness.thin.transport import ThinLaneError
|
|
14
|
+
from mostlyright.data_harness.thin.v4 import StudioV4Client, identifier
|
|
15
|
+
from mostlyright.data_harness.ux.credentials import resolve_cloud_credentials
|
|
16
|
+
|
|
17
|
+
COMMAND_HELP = "prepare, test and manage versioned table search"
|
|
18
|
+
VERBS = (
|
|
19
|
+
"inspect",
|
|
20
|
+
"sample",
|
|
21
|
+
"values",
|
|
22
|
+
"propose",
|
|
23
|
+
"configure",
|
|
24
|
+
"validate",
|
|
25
|
+
"add-cases",
|
|
26
|
+
"explain",
|
|
27
|
+
"preview",
|
|
28
|
+
"evaluate",
|
|
29
|
+
"estimate",
|
|
30
|
+
"build",
|
|
31
|
+
"status",
|
|
32
|
+
"activate",
|
|
33
|
+
"cancel",
|
|
34
|
+
"rollback",
|
|
35
|
+
)
|
|
36
|
+
RECIPE_VERBS = frozenset({"inspect", "propose", "validate"})
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def declare_arguments(parser: argparse.ArgumentParser) -> None:
|
|
40
|
+
parser.description = (
|
|
41
|
+
"Prepare search through Studio. No local model or index runs. Inspect/propose/validate "
|
|
42
|
+
"accept --recipe FILE before registration. Recipe inspection is "
|
|
43
|
+
"declared-schema evidence; readiness requires built data. Builds return promptly with job "
|
|
44
|
+
"coordinates. Unsupported preparation operations return a capability-unavailable error."
|
|
45
|
+
)
|
|
46
|
+
subparsers = parser.add_subparsers(
|
|
47
|
+
dest="search_operation", required=True, help="the search preparation operation"
|
|
48
|
+
)
|
|
49
|
+
for verb in VERBS:
|
|
50
|
+
sub = subparsers.add_parser(verb)
|
|
51
|
+
sub.add_argument("--json", action="store_true", default=argparse.SUPPRESS)
|
|
52
|
+
sub.add_argument("target", nargs="?", help="table ID, or job ID for cancel")
|
|
53
|
+
if verb in RECIPE_VERBS:
|
|
54
|
+
sub.add_argument(
|
|
55
|
+
"--recipe", type=Path, help="local recipe submitted without editing it"
|
|
56
|
+
)
|
|
57
|
+
if verb != "cancel":
|
|
58
|
+
sub.add_argument("--version", dest="table_version_id")
|
|
59
|
+
if verb not in {"configure", "status", "build"}:
|
|
60
|
+
sub.add_argument("--revision", dest="search_revision_id")
|
|
61
|
+
if verb in {"sample", "values", "preview"}:
|
|
62
|
+
sub.add_argument("--limit", type=int, default=20)
|
|
63
|
+
if verb == "sample":
|
|
64
|
+
sub.add_argument("--columns", help="comma-separated projected columns")
|
|
65
|
+
if verb == "values":
|
|
66
|
+
sub.add_argument("--column", required=True)
|
|
67
|
+
sub.add_argument("--prefix")
|
|
68
|
+
if verb == "configure":
|
|
69
|
+
sub.add_argument("--spec", type=Path, required=True)
|
|
70
|
+
sub.add_argument("--expected-revision", required=True, help="revision ID or none")
|
|
71
|
+
if verb == "add-cases":
|
|
72
|
+
sub.add_argument("--cases", type=Path, required=True)
|
|
73
|
+
if verb in {"explain", "preview"}:
|
|
74
|
+
group = sub.add_mutually_exclusive_group(required=True)
|
|
75
|
+
group.add_argument("--query")
|
|
76
|
+
if verb == "preview":
|
|
77
|
+
group.add_argument("--plan", type=Path)
|
|
78
|
+
if verb == "evaluate":
|
|
79
|
+
sub.add_argument("--cases-revision", dest="cases_revision_id")
|
|
80
|
+
if verb == "status":
|
|
81
|
+
sub.add_argument("--job", dest="job_id")
|
|
82
|
+
if verb in {"activate", "rollback"}:
|
|
83
|
+
sub.add_argument("--generation", dest="generation_id")
|
|
84
|
+
sub.add_argument("--expected-active", required=True, help="active revision ID or none")
|
|
85
|
+
if verb in {
|
|
86
|
+
"configure",
|
|
87
|
+
"add-cases",
|
|
88
|
+
"evaluate",
|
|
89
|
+
"activate",
|
|
90
|
+
"rollback",
|
|
91
|
+
}:
|
|
92
|
+
sub.add_argument(
|
|
93
|
+
"--idempotency-key", help="reuse this key when retrying the same write"
|
|
94
|
+
)
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
def _required(value: Any, name: str) -> Any:
|
|
98
|
+
if value is None or value == "":
|
|
99
|
+
raise ThinLaneError("THIN_ARGUMENT_INVALID", f"search requires {name}")
|
|
100
|
+
return value
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
def search_exit_code(payload: dict[str, Any]) -> int:
|
|
104
|
+
"""Stable gate outcomes: 0 complete, 1 failed, 3 incomplete, 4 ambiguous."""
|
|
105
|
+
result = payload.get("result", {})
|
|
106
|
+
if not isinstance(result, dict):
|
|
107
|
+
return 1
|
|
108
|
+
if result.get("valid") is False or result.get("status") in {"failed", "cancelled", "invalid"}:
|
|
109
|
+
return 1
|
|
110
|
+
if result.get("status") in {"ambiguous", "clarification_required"}:
|
|
111
|
+
return 4
|
|
112
|
+
if result.get("status") in {
|
|
113
|
+
"queued",
|
|
114
|
+
"dispatched",
|
|
115
|
+
"running",
|
|
116
|
+
"pending",
|
|
117
|
+
"cancellation_requested",
|
|
118
|
+
}:
|
|
119
|
+
return 3
|
|
120
|
+
estimate = result.get("estimate")
|
|
121
|
+
plan = result.get("plan")
|
|
122
|
+
if estimate is not None and not isinstance(estimate, dict):
|
|
123
|
+
return 1
|
|
124
|
+
if plan is not None and not isinstance(plan, dict):
|
|
125
|
+
return 1
|
|
126
|
+
if isinstance(estimate, dict) and estimate.get("admitted") is False:
|
|
127
|
+
return 3
|
|
128
|
+
if isinstance(plan, dict) and plan.get("unresolved"):
|
|
129
|
+
return 4
|
|
130
|
+
return 0
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
SEARCH_JOB_SCHEMAS = {"table-search-job.v1", "table-search-job.v2"}
|
|
134
|
+
|
|
135
|
+
RECIPE_INSPECTION_PATH = "/v4/search/recipe-inspection"
|
|
136
|
+
TABLE_SEARCH_PATH = "/v4/tables/{table_id}/search"
|
|
137
|
+
TABLE_AUTHORING_PATHS = {
|
|
138
|
+
verb: TABLE_SEARCH_PATH + "/" + verb
|
|
139
|
+
for verb in ("inspect", "propose", "validate", "explain", "estimate")
|
|
140
|
+
}
|
|
141
|
+
TABLE_REVISIONS_PATH = TABLE_SEARCH_PATH + "/revisions"
|
|
142
|
+
TABLE_JOBS_PATH = TABLE_SEARCH_PATH + "/jobs"
|
|
143
|
+
JOB_STATUS_PATH = "/v4/search/jobs/{job_id}"
|
|
144
|
+
JOB_CANCEL_PATH = JOB_STATUS_PATH + "/cancel"
|
|
145
|
+
SEARCH_PATHS = frozenset(
|
|
146
|
+
{
|
|
147
|
+
RECIPE_INSPECTION_PATH,
|
|
148
|
+
TABLE_SEARCH_PATH,
|
|
149
|
+
TABLE_REVISIONS_PATH,
|
|
150
|
+
TABLE_JOBS_PATH,
|
|
151
|
+
JOB_STATUS_PATH,
|
|
152
|
+
JOB_CANCEL_PATH,
|
|
153
|
+
*TABLE_AUTHORING_PATHS.values(),
|
|
154
|
+
}
|
|
155
|
+
)
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
def search(args: argparse.Namespace, *, client: StudioV4Client | None = None) -> dict[str, Any]:
|
|
159
|
+
"""Forward bounded declared commands; never invent an index or successful capability."""
|
|
160
|
+
verb = args.search_operation
|
|
161
|
+
recipe = getattr(args, "recipe", None)
|
|
162
|
+
target = getattr(args, "target", None)
|
|
163
|
+
if recipe is not None:
|
|
164
|
+
if target is not None or any(
|
|
165
|
+
getattr(args, member, None) is not None
|
|
166
|
+
for member in ("table_version_id", "search_revision_id")
|
|
167
|
+
):
|
|
168
|
+
raise ThinLaneError(
|
|
169
|
+
"THIN_ARGUMENT_INVALID", "--recipe cannot be mixed with table coordinates"
|
|
170
|
+
)
|
|
171
|
+
document = read_document(recipe)
|
|
172
|
+
method, path = "POST", RECIPE_INSPECTION_PATH
|
|
173
|
+
body = {"operation": verb, "recipe": document}
|
|
174
|
+
expected = (200,)
|
|
175
|
+
headers = None
|
|
176
|
+
elif verb == "cancel" or (verb == "status" and getattr(args, "job_id", None)):
|
|
177
|
+
if verb == "status" and (target is not None or getattr(args, "table_version_id", None)):
|
|
178
|
+
raise ThinLaneError("THIN_ARGUMENT_INVALID", "--job cannot mix table coordinates")
|
|
179
|
+
job_id = identifier(
|
|
180
|
+
_required(target if verb == "cancel" else args.job_id, "job ID"), "job ID"
|
|
181
|
+
)
|
|
182
|
+
method = "POST" if verb == "cancel" else "GET"
|
|
183
|
+
path = (JOB_CANCEL_PATH if verb == "cancel" else JOB_STATUS_PATH).format(job_id=job_id)
|
|
184
|
+
body, headers, expected = {}, None, (200,)
|
|
185
|
+
else:
|
|
186
|
+
table_id = identifier(
|
|
187
|
+
_required(target, "a table identifier or --recipe"), "table identifier"
|
|
188
|
+
)
|
|
189
|
+
body = {}
|
|
190
|
+
for member in ("table_version_id", "search_revision_id"):
|
|
191
|
+
value = getattr(args, member, None)
|
|
192
|
+
if value is not None:
|
|
193
|
+
body[member] = identifier(value, member)
|
|
194
|
+
headers = None
|
|
195
|
+
expected = (200,)
|
|
196
|
+
method = "POST"
|
|
197
|
+
if verb in TABLE_AUTHORING_PATHS:
|
|
198
|
+
path = TABLE_AUTHORING_PATHS[verb].format(table_id=table_id)
|
|
199
|
+
if verb == "explain":
|
|
200
|
+
query = _required(getattr(args, "query", None), "--query")
|
|
201
|
+
if len(query) > 512:
|
|
202
|
+
raise ThinLaneError(
|
|
203
|
+
"THIN_ARGUMENT_INVALID", "search query exceeds 512 characters"
|
|
204
|
+
)
|
|
205
|
+
body["query"] = query
|
|
206
|
+
elif verb == "configure":
|
|
207
|
+
_required(body.get("table_version_id"), "--version")
|
|
208
|
+
body["spec"] = read_document(args.spec)
|
|
209
|
+
revision = args.expected_revision
|
|
210
|
+
body["expected_revision"] = (
|
|
211
|
+
None if revision == "none" else identifier(revision, "revision")
|
|
212
|
+
)
|
|
213
|
+
path = TABLE_REVISIONS_PATH.format(table_id=table_id)
|
|
214
|
+
headers = {"Idempotency-Key": getattr(args, "idempotency_key", None) or str(uuid4())}
|
|
215
|
+
expected = (201,)
|
|
216
|
+
elif verb == "build":
|
|
217
|
+
_required(body.get("table_version_id"), "--version")
|
|
218
|
+
path = TABLE_JOBS_PATH.format(table_id=table_id)
|
|
219
|
+
expected = (202,)
|
|
220
|
+
elif verb == "status":
|
|
221
|
+
method, path = "GET", TABLE_SEARCH_PATH.format(table_id=table_id)
|
|
222
|
+
else:
|
|
223
|
+
raise ThinLaneError(
|
|
224
|
+
"THIN_SEARCH_CAPABILITY_UNAVAILABLE", f"Studio does not yet provide search {verb}"
|
|
225
|
+
)
|
|
226
|
+
selected = client or StudioV4Client(open_studio_session(resolve_cloud_credentials()))
|
|
227
|
+
answer = selected._call(
|
|
228
|
+
method,
|
|
229
|
+
path,
|
|
230
|
+
body=body if method == "POST" else None,
|
|
231
|
+
query=body if method == "GET" else None,
|
|
232
|
+
extra_headers=headers,
|
|
233
|
+
expected=expected,
|
|
234
|
+
)
|
|
235
|
+
if recipe is not None and (
|
|
236
|
+
answer.get("scope") != "declared_schema"
|
|
237
|
+
or answer.get("schema_version") != "table-search-authoring.v1"
|
|
238
|
+
or type(answer.get("valid")) is not bool
|
|
239
|
+
):
|
|
240
|
+
raise ThinLaneError(
|
|
241
|
+
"THIN_RESPONSE_INVALID", "Studio returned invalid declared-search evidence"
|
|
242
|
+
)
|
|
243
|
+
job_operation = verb == "cancel" or (verb == "status" and getattr(args, "job_id", None))
|
|
244
|
+
if job_operation:
|
|
245
|
+
if (
|
|
246
|
+
answer.get("job_id") != job_id
|
|
247
|
+
or answer.get("status")
|
|
248
|
+
not in {"queued", "dispatched", "running", "succeeded", "failed", "cancelled"}
|
|
249
|
+
or (verb == "status" and answer.get("schema_version") not in SEARCH_JOB_SCHEMAS)
|
|
250
|
+
):
|
|
251
|
+
raise ThinLaneError(
|
|
252
|
+
"THIN_RESPONSE_INVALID", "Studio returned invalid search job coordinates"
|
|
253
|
+
)
|
|
254
|
+
if recipe is None and not job_operation:
|
|
255
|
+
wanted_schemas = (
|
|
256
|
+
{"table-search-revision.v1"}
|
|
257
|
+
if verb == "configure"
|
|
258
|
+
else SEARCH_JOB_SCHEMAS
|
|
259
|
+
if verb == "build"
|
|
260
|
+
else {"table-search-metadata.v1"}
|
|
261
|
+
)
|
|
262
|
+
if answer.get("schema_version") not in wanted_schemas or answer.get("table_id") != table_id:
|
|
263
|
+
raise ThinLaneError(
|
|
264
|
+
"THIN_RESPONSE_INVALID", "Studio returned invalid table-search coordinates"
|
|
265
|
+
)
|
|
266
|
+
for member in ("table_version_id", "search_revision_id"):
|
|
267
|
+
requested = body.get(member)
|
|
268
|
+
if requested is not None and answer.get(member) != requested:
|
|
269
|
+
raise ThinLaneError(
|
|
270
|
+
"THIN_RESPONSE_INVALID", "Studio returned mismatched search coordinates"
|
|
271
|
+
)
|
|
272
|
+
return {
|
|
273
|
+
"schema_version": f"{THIN_SCHEMA_PREFIX}-v4-search.v1",
|
|
274
|
+
"status": "search_result",
|
|
275
|
+
"headline": f"Search {verb} result.",
|
|
276
|
+
"lane": "hosted",
|
|
277
|
+
"operation": verb,
|
|
278
|
+
"result": answer,
|
|
279
|
+
}
|
{mostlyright_data-0.28.0 → mostlyright_data-0.29.0}/src/mostlyright/data_harness/thin/vocabulary.py
RENAMED
|
@@ -201,6 +201,11 @@ CLASSIFICATION: dict[str, Lane] = {
|
|
|
201
201
|
"surface the MCP anonymous tools call — search, show, tables, schema, sample, "
|
|
202
202
|
"lookup, fetch, query and download-url — with no device key and no Studio bearer",
|
|
203
203
|
),
|
|
204
|
+
"search": Lane(
|
|
205
|
+
HOSTED,
|
|
206
|
+
"it prepares and tests versioned search through Studio; index work runs in the hosted "
|
|
207
|
+
"engine, while draft configuration and activation remain server-authorized",
|
|
208
|
+
),
|
|
204
209
|
"query": Lane(
|
|
205
210
|
HOSTED,
|
|
206
211
|
"it asks one bounded read-only question of the table one run produced and prints the "
|
|
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.28.0 → mostlyright_data-0.29.0}/skills/mr-data-build/references/boundaries.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{mostlyright_data-0.28.0 → mostlyright_data-0.29.0}/skills/mr-data-build/references/live-run.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{mostlyright_data-0.28.0 → mostlyright_data-0.29.0}/skills/mr-data-build/references/one-install.md
RENAMED
|
File without changes
|
|
File without changes
|
{mostlyright_data-0.28.0 → mostlyright_data-0.29.0}/skills/mr-data-build/references/promote.md
RENAMED
|
File without changes
|
{mostlyright_data-0.28.0 → mostlyright_data-0.29.0}/skills/mr-data-build/references/readers.md
RENAMED
|
File without changes
|
{mostlyright_data-0.28.0 → mostlyright_data-0.29.0}/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.28.0 → mostlyright_data-0.29.0}/skills/mr-data-build/references/sources.md
RENAMED
|
File without changes
|
|
File without changes
|
{mostlyright_data-0.28.0 → mostlyright_data-0.29.0}/skills/mr-data-build/references/transforms.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{mostlyright_data-0.28.0 → mostlyright_data-0.29.0}/src/mostlyright/data_harness/__init__.py
RENAMED
|
File without changes
|
{mostlyright_data-0.28.0 → mostlyright_data-0.29.0}/src/mostlyright/data_harness/agent_protocol.py
RENAMED
|
File without changes
|
{mostlyright_data-0.28.0 → mostlyright_data-0.29.0}/src/mostlyright/data_harness/canonical.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{mostlyright_data-0.28.0 → mostlyright_data-0.29.0}/src/mostlyright/data_harness/key_seam.py
RENAMED
|
File without changes
|
{mostlyright_data-0.28.0 → mostlyright_data-0.29.0}/src/mostlyright/data_harness/page_coverage.py
RENAMED
|
File without changes
|
|
File without changes
|
{mostlyright_data-0.28.0 → mostlyright_data-0.29.0}/src/mostlyright/data_harness/session_probes.py
RENAMED
|
File without changes
|
{mostlyright_data-0.28.0 → mostlyright_data-0.29.0}/src/mostlyright/data_harness/skill_assets.py
RENAMED
|
File without changes
|
{mostlyright_data-0.28.0 → mostlyright_data-0.29.0}/src/mostlyright/data_harness/thin/__init__.py
RENAMED
|
File without changes
|
{mostlyright_data-0.28.0 → mostlyright_data-0.29.0}/src/mostlyright/data_harness/thin/acquire.py
RENAMED
|
File without changes
|
|
File without changes
|
{mostlyright_data-0.28.0 → mostlyright_data-0.29.0}/src/mostlyright/data_harness/thin/activity.py
RENAMED
|
File without changes
|
{mostlyright_data-0.28.0 → mostlyright_data-0.29.0}/src/mostlyright/data_harness/thin/approvals.py
RENAMED
|
File without changes
|
{mostlyright_data-0.28.0 → mostlyright_data-0.29.0}/src/mostlyright/data_harness/thin/categories.py
RENAMED
|
File without changes
|
{mostlyright_data-0.28.0 → mostlyright_data-0.29.0}/src/mostlyright/data_harness/thin/commands.py
RENAMED
|
File without changes
|
|
File without changes
|
{mostlyright_data-0.28.0 → mostlyright_data-0.29.0}/src/mostlyright/data_harness/thin/download.py
RENAMED
|
File without changes
|
|
File without changes
|
{mostlyright_data-0.28.0 → mostlyright_data-0.29.0}/src/mostlyright/data_harness/thin/narrative.py
RENAMED
|
File without changes
|
{mostlyright_data-0.28.0 → mostlyright_data-0.29.0}/src/mostlyright/data_harness/thin/parity.py
RENAMED
|
File without changes
|
{mostlyright_data-0.28.0 → mostlyright_data-0.29.0}/src/mostlyright/data_harness/thin/probe.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{mostlyright_data-0.28.0 → mostlyright_data-0.29.0}/src/mostlyright/data_harness/thin/propose.py
RENAMED
|
File without changes
|
{mostlyright_data-0.28.0 → mostlyright_data-0.29.0}/src/mostlyright/data_harness/thin/recipe.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{mostlyright_data-0.28.0 → mostlyright_data-0.29.0}/src/mostlyright/data_harness/thin/recipe_lint.py
RENAMED
|
File without changes
|
{mostlyright_data-0.28.0 → mostlyright_data-0.29.0}/src/mostlyright/data_harness/thin/research.py
RENAMED
|
File without changes
|
|
File without changes
|
{mostlyright_data-0.28.0 → mostlyright_data-0.29.0}/src/mostlyright/data_harness/thin/runs.py
RENAMED
|
File without changes
|
{mostlyright_data-0.28.0 → mostlyright_data-0.29.0}/src/mostlyright/data_harness/thin/session.py
RENAMED
|
File without changes
|
{mostlyright_data-0.28.0 → mostlyright_data-0.29.0}/src/mostlyright/data_harness/thin/stream.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{mostlyright_data-0.28.0 → mostlyright_data-0.29.0}/src/mostlyright/data_harness/thin/transport.py
RENAMED
|
File without changes
|
{mostlyright_data-0.28.0 → mostlyright_data-0.29.0}/src/mostlyright/data_harness/thin/user_agent.py
RENAMED
|
File without changes
|
|
File without changes
|
{mostlyright_data-0.28.0 → mostlyright_data-0.29.0}/src/mostlyright/data_harness/thin/v4_catalog.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{mostlyright_data-0.28.0 → mostlyright_data-0.29.0}/src/mostlyright/data_harness/thin/v4_datasets.py
RENAMED
|
File without changes
|
{mostlyright_data-0.28.0 → mostlyright_data-0.29.0}/src/mostlyright/data_harness/thin/v4_handoff.py
RENAMED
|
File without changes
|
|
File without changes
|
{mostlyright_data-0.28.0 → mostlyright_data-0.29.0}/src/mostlyright/data_harness/thin/v4_public.py
RENAMED
|
File without changes
|
{mostlyright_data-0.28.0 → mostlyright_data-0.29.0}/src/mostlyright/data_harness/thin/v4_query.py
RENAMED
|
File without changes
|
{mostlyright_data-0.28.0 → mostlyright_data-0.29.0}/src/mostlyright/data_harness/thin/v4_reader.py
RENAMED
|
File without changes
|
{mostlyright_data-0.28.0 → mostlyright_data-0.29.0}/src/mostlyright/data_harness/thin/v4_runs.py
RENAMED
|
File without changes
|
{mostlyright_data-0.28.0 → mostlyright_data-0.29.0}/src/mostlyright/data_harness/thin/v4_secrets.py
RENAMED
|
File without changes
|
{mostlyright_data-0.28.0 → mostlyright_data-0.29.0}/src/mostlyright/data_harness/thin/v4_stream.py
RENAMED
|
File without changes
|
{mostlyright_data-0.28.0 → mostlyright_data-0.29.0}/src/mostlyright/data_harness/thin/v4_tables.py
RENAMED
|
File without changes
|
{mostlyright_data-0.28.0 → mostlyright_data-0.29.0}/src/mostlyright/data_harness/ux/__init__.py
RENAMED
|
File without changes
|
{mostlyright_data-0.28.0 → mostlyright_data-0.29.0}/src/mostlyright/data_harness/ux/attendance.py
RENAMED
|
File without changes
|
{mostlyright_data-0.28.0 → mostlyright_data-0.29.0}/src/mostlyright/data_harness/ux/clarification.py
RENAMED
|
File without changes
|
{mostlyright_data-0.28.0 → mostlyright_data-0.29.0}/src/mostlyright/data_harness/ux/cloud_auth.py
RENAMED
|
File without changes
|
|
File without changes
|
{mostlyright_data-0.28.0 → mostlyright_data-0.29.0}/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.28.0 → mostlyright_data-0.29.0}/src/mostlyright/data_harness/ux/credentials.py
RENAMED
|
File without changes
|
{mostlyright_data-0.28.0 → mostlyright_data-0.29.0}/src/mostlyright/data_harness/ux/login.py
RENAMED
|
File without changes
|
{mostlyright_data-0.28.0 → mostlyright_data-0.29.0}/src/mostlyright/data_harness/ux/path_kind.py
RENAMED
|
File without changes
|
{mostlyright_data-0.28.0 → mostlyright_data-0.29.0}/src/mostlyright/data_harness/ux/plain_file.py
RENAMED
|
File without changes
|
{mostlyright_data-0.28.0 → mostlyright_data-0.29.0}/src/mostlyright/data_harness/ux/remediation.py
RENAMED
|
File without changes
|
{mostlyright_data-0.28.0 → mostlyright_data-0.29.0}/src/mostlyright/data_harness/ux/render.py
RENAMED
|
File without changes
|