mostlyright-data 0.30.2__tar.gz → 0.30.3__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.30.2 → mostlyright_data-0.30.3}/PKG-INFO +1 -1
- {mostlyright_data-0.30.2 → mostlyright_data-0.30.3}/skills/mr-data-build/SKILL.md +3 -0
- {mostlyright_data-0.30.2 → mostlyright_data-0.30.3}/src/mostlyright/data_harness/page_coverage.py +62 -2
- {mostlyright_data-0.30.2 → mostlyright_data-0.30.3}/src/mostlyright/data_harness/thin/v4_runs.py +108 -0
- {mostlyright_data-0.30.2 → mostlyright_data-0.30.3}/.gitignore +0 -0
- {mostlyright_data-0.30.2 → mostlyright_data-0.30.3}/README.md +0 -0
- {mostlyright_data-0.30.2 → mostlyright_data-0.30.3}/pyproject.toml +0 -0
- {mostlyright_data-0.30.2 → mostlyright_data-0.30.3}/scripts/hatch_build.py +0 -0
- {mostlyright_data-0.30.2 → mostlyright_data-0.30.3}/skills/mr-data-build/agents/openai.yaml +0 -0
- {mostlyright_data-0.30.2 → mostlyright_data-0.30.3}/skills/mr-data-build/references/1-open-the-page-and-the-link-to-it-in-the-first-message.md +0 -0
- {mostlyright_data-0.30.2 → mostlyright_data-0.30.3}/skills/mr-data-build/references/2-brief-two-to-four-questions-each-with-a-recommended-answer.md +0 -0
- {mostlyright_data-0.30.2 → mostlyright_data-0.30.3}/skills/mr-data-build/references/3-probe-read-a-source-before-committing-to-it.md +0 -0
- {mostlyright_data-0.30.2 → mostlyright_data-0.30.3}/skills/mr-data-build/references/4-decide-say-what-you-chose-what-you-refused-and-ask-one-question.md +0 -0
- {mostlyright_data-0.30.2 → mostlyright_data-0.30.3}/skills/mr-data-build/references/5-draft-one-recipe-document-one-call.md +0 -0
- {mostlyright_data-0.30.2 → mostlyright_data-0.30.3}/skills/mr-data-build/references/6-build-one-run-sized-to-acquire-every-measured-source-whole.md +0 -0
- {mostlyright_data-0.30.2 → mostlyright_data-0.30.3}/skills/mr-data-build/references/7-interrogate-ask-the-run-what-it-actually-delivered.md +0 -0
- {mostlyright_data-0.30.2 → mostlyright_data-0.30.3}/skills/mr-data-build/references/8-fix-revise-the-document-and-register-it-again.md +0 -0
- {mostlyright_data-0.30.2 → mostlyright_data-0.30.3}/skills/mr-data-build/references/9-present-only-what-survived-inspection-with-caveats.md +0 -0
- {mostlyright_data-0.30.2 → mostlyright_data-0.30.3}/skills/mr-data-build/references/agent-protocol.md +0 -0
- {mostlyright_data-0.30.2 → mostlyright_data-0.30.3}/skills/mr-data-build/references/autonomous-delivery.md +0 -0
- {mostlyright_data-0.30.2 → mostlyright_data-0.30.3}/skills/mr-data-build/references/before-the-first-tool-call.md +0 -0
- {mostlyright_data-0.30.2 → mostlyright_data-0.30.3}/skills/mr-data-build/references/boundaries.md +0 -0
- {mostlyright_data-0.30.2 → mostlyright_data-0.30.3}/skills/mr-data-build/references/cloud-authentication-preflight.md +0 -0
- {mostlyright_data-0.30.2 → mostlyright_data-0.30.3}/skills/mr-data-build/references/commands.md +0 -0
- {mostlyright_data-0.30.2 → mostlyright_data-0.30.3}/skills/mr-data-build/references/cross-repository-protocol-reference.md +0 -0
- {mostlyright_data-0.30.2 → mostlyright_data-0.30.3}/skills/mr-data-build/references/installation-parity.md +0 -0
- {mostlyright_data-0.30.2 → mostlyright_data-0.30.3}/skills/mr-data-build/references/live-run.md +0 -0
- {mostlyright_data-0.30.2 → mostlyright_data-0.30.3}/skills/mr-data-build/references/making-a-table-incremental.md +0 -0
- {mostlyright_data-0.30.2 → mostlyright_data-0.30.3}/skills/mr-data-build/references/narrating-the-run.md +0 -0
- {mostlyright_data-0.30.2 → mostlyright_data-0.30.3}/skills/mr-data-build/references/not-hosted-yet.md +0 -0
- {mostlyright_data-0.30.2 → mostlyright_data-0.30.3}/skills/mr-data-build/references/one-install.md +0 -0
- {mostlyright_data-0.30.2 → mostlyright_data-0.30.3}/skills/mr-data-build/references/patterns.md +0 -0
- {mostlyright_data-0.30.2 → mostlyright_data-0.30.3}/skills/mr-data-build/references/prediction-labels.md +0 -0
- {mostlyright_data-0.30.2 → mostlyright_data-0.30.3}/skills/mr-data-build/references/preparing-table-search.md +0 -0
- {mostlyright_data-0.30.2 → mostlyright_data-0.30.3}/skills/mr-data-build/references/promote.md +0 -0
- {mostlyright_data-0.30.2 → mostlyright_data-0.30.3}/skills/mr-data-build/references/readers.md +0 -0
- {mostlyright_data-0.30.2 → mostlyright_data-0.30.3}/skills/mr-data-build/references/receipts.md +0 -0
- {mostlyright_data-0.30.2 → mostlyright_data-0.30.3}/skills/mr-data-build/references/recipe-test.md +0 -0
- {mostlyright_data-0.30.2 → mostlyright_data-0.30.3}/skills/mr-data-build/references/recording-a-stream-venue.md +0 -0
- {mostlyright_data-0.30.2 → mostlyright_data-0.30.3}/skills/mr-data-build/references/recovering-an-import-failure.md +0 -0
- {mostlyright_data-0.30.2 → mostlyright_data-0.30.3}/skills/mr-data-build/references/reference-pages.md +0 -0
- {mostlyright_data-0.30.2 → mostlyright_data-0.30.3}/skills/mr-data-build/references/required-protocol.md +0 -0
- {mostlyright_data-0.30.2 → mostlyright_data-0.30.3}/skills/mr-data-build/references/source-credentials.md +0 -0
- {mostlyright_data-0.30.2 → mostlyright_data-0.30.3}/skills/mr-data-build/references/sources.md +0 -0
- {mostlyright_data-0.30.2 → mostlyright_data-0.30.3}/skills/mr-data-build/references/the-one-thing-to-say-about-the-skill-itself.md +0 -0
- {mostlyright_data-0.30.2 → mostlyright_data-0.30.3}/skills/mr-data-build/references/transforms.md +0 -0
- {mostlyright_data-0.30.2 → mostlyright_data-0.30.3}/skills/mr-data-build/references/user-communication-contract.md +0 -0
- {mostlyright_data-0.30.2 → mostlyright_data-0.30.3}/skills/mr-data-build/references/writing-a-decision-record.md +0 -0
- {mostlyright_data-0.30.2 → mostlyright_data-0.30.3}/skills/mr-data-build/scripts/write_research_notebook.py +0 -0
- {mostlyright_data-0.30.2 → mostlyright_data-0.30.3}/src/mostlyright/data_harness/__init__.py +0 -0
- {mostlyright_data-0.30.2 → mostlyright_data-0.30.3}/src/mostlyright/data_harness/agent_protocol.py +0 -0
- {mostlyright_data-0.30.2 → mostlyright_data-0.30.3}/src/mostlyright/data_harness/canonical.py +0 -0
- {mostlyright_data-0.30.2 → mostlyright_data-0.30.3}/src/mostlyright/data_harness/formats.py +0 -0
- {mostlyright_data-0.30.2 → mostlyright_data-0.30.3}/src/mostlyright/data_harness/hosted_crawler_protocol.py +0 -0
- {mostlyright_data-0.30.2 → mostlyright_data-0.30.3}/src/mostlyright/data_harness/key_seam.py +0 -0
- {mostlyright_data-0.30.2 → mostlyright_data-0.30.3}/src/mostlyright/data_harness/part_check_evidence.py +0 -0
- {mostlyright_data-0.30.2 → mostlyright_data-0.30.3}/src/mostlyright/data_harness/session_probes.py +0 -0
- {mostlyright_data-0.30.2 → mostlyright_data-0.30.3}/src/mostlyright/data_harness/skill_assets.py +0 -0
- {mostlyright_data-0.30.2 → mostlyright_data-0.30.3}/src/mostlyright/data_harness/table_manifest.py +0 -0
- {mostlyright_data-0.30.2 → mostlyright_data-0.30.3}/src/mostlyright/data_harness/thin/__init__.py +0 -0
- {mostlyright_data-0.30.2 → mostlyright_data-0.30.3}/src/mostlyright/data_harness/thin/acquire.py +0 -0
- {mostlyright_data-0.30.2 → mostlyright_data-0.30.3}/src/mostlyright/data_harness/thin/acquire_cancel.py +0 -0
- {mostlyright_data-0.30.2 → mostlyright_data-0.30.3}/src/mostlyright/data_harness/thin/activity.py +0 -0
- {mostlyright_data-0.30.2 → mostlyright_data-0.30.3}/src/mostlyright/data_harness/thin/approvals.py +0 -0
- {mostlyright_data-0.30.2 → mostlyright_data-0.30.3}/src/mostlyright/data_harness/thin/backoff.py +0 -0
- {mostlyright_data-0.30.2 → mostlyright_data-0.30.3}/src/mostlyright/data_harness/thin/categories.py +0 -0
- {mostlyright_data-0.30.2 → mostlyright_data-0.30.3}/src/mostlyright/data_harness/thin/commands.py +0 -0
- {mostlyright_data-0.30.2 → mostlyright_data-0.30.3}/src/mostlyright/data_harness/thin/dataset-categories-v1.json +0 -0
- {mostlyright_data-0.30.2 → mostlyright_data-0.30.3}/src/mostlyright/data_harness/thin/download.py +0 -0
- {mostlyright_data-0.30.2 → mostlyright_data-0.30.3}/src/mostlyright/data_harness/thin/fast_features.py +0 -0
- {mostlyright_data-0.30.2 → mostlyright_data-0.30.3}/src/mostlyright/data_harness/thin/narrative.py +0 -0
- {mostlyright_data-0.30.2 → mostlyright_data-0.30.3}/src/mostlyright/data_harness/thin/parity.py +0 -0
- {mostlyright_data-0.30.2 → mostlyright_data-0.30.3}/src/mostlyright/data_harness/thin/probe.py +0 -0
- {mostlyright_data-0.30.2 → mostlyright_data-0.30.3}/src/mostlyright/data_harness/thin/progress_rate.py +0 -0
- {mostlyright_data-0.30.2 → mostlyright_data-0.30.3}/src/mostlyright/data_harness/thin/progress_vocabulary.py +0 -0
- {mostlyright_data-0.30.2 → mostlyright_data-0.30.3}/src/mostlyright/data_harness/thin/propose.py +0 -0
- {mostlyright_data-0.30.2 → mostlyright_data-0.30.3}/src/mostlyright/data_harness/thin/recipe.py +0 -0
- {mostlyright_data-0.30.2 → mostlyright_data-0.30.3}/src/mostlyright/data_harness/thin/recipe_brief.py +0 -0
- {mostlyright_data-0.30.2 → mostlyright_data-0.30.3}/src/mostlyright/data_harness/thin/recipe_explain.py +0 -0
- {mostlyright_data-0.30.2 → mostlyright_data-0.30.3}/src/mostlyright/data_harness/thin/recipe_forecast.py +0 -0
- {mostlyright_data-0.30.2 → mostlyright_data-0.30.3}/src/mostlyright/data_harness/thin/recipe_lint.py +0 -0
- {mostlyright_data-0.30.2 → mostlyright_data-0.30.3}/src/mostlyright/data_harness/thin/recipe_test.py +0 -0
- {mostlyright_data-0.30.2 → mostlyright_data-0.30.3}/src/mostlyright/data_harness/thin/refresh_rehearsal.py +0 -0
- {mostlyright_data-0.30.2 → mostlyright_data-0.30.3}/src/mostlyright/data_harness/thin/release_check.py +0 -0
- {mostlyright_data-0.30.2 → mostlyright_data-0.30.3}/src/mostlyright/data_harness/thin/research.py +0 -0
- {mostlyright_data-0.30.2 → mostlyright_data-0.30.3}/src/mostlyright/data_harness/thin/router.py +0 -0
- {mostlyright_data-0.30.2 → mostlyright_data-0.30.3}/src/mostlyright/data_harness/thin/run_diagnose.py +0 -0
- {mostlyright_data-0.30.2 → mostlyright_data-0.30.3}/src/mostlyright/data_harness/thin/run_prefix.py +0 -0
- {mostlyright_data-0.30.2 → mostlyright_data-0.30.3}/src/mostlyright/data_harness/thin/runs.py +0 -0
- {mostlyright_data-0.30.2 → mostlyright_data-0.30.3}/src/mostlyright/data_harness/thin/session.py +0 -0
- {mostlyright_data-0.30.2 → mostlyright_data-0.30.3}/src/mostlyright/data_harness/thin/stream.py +0 -0
- {mostlyright_data-0.30.2 → mostlyright_data-0.30.3}/src/mostlyright/data_harness/thin/stream_venue.py +0 -0
- {mostlyright_data-0.30.2 → mostlyright_data-0.30.3}/src/mostlyright/data_harness/thin/studio_capabilities.py +0 -0
- {mostlyright_data-0.30.2 → mostlyright_data-0.30.3}/src/mostlyright/data_harness/thin/support.py +0 -0
- {mostlyright_data-0.30.2 → mostlyright_data-0.30.3}/src/mostlyright/data_harness/thin/table_search_contract.json +0 -0
- {mostlyright_data-0.30.2 → mostlyright_data-0.30.3}/src/mostlyright/data_harness/thin/transport.py +0 -0
- {mostlyright_data-0.30.2 → mostlyright_data-0.30.3}/src/mostlyright/data_harness/thin/user_agent.py +0 -0
- {mostlyright_data-0.30.2 → mostlyright_data-0.30.3}/src/mostlyright/data_harness/thin/v4.py +0 -0
- {mostlyright_data-0.30.2 → mostlyright_data-0.30.3}/src/mostlyright/data_harness/thin/v4_artifacts.py +0 -0
- {mostlyright_data-0.30.2 → mostlyright_data-0.30.3}/src/mostlyright/data_harness/thin/v4_catalog.py +0 -0
- {mostlyright_data-0.30.2 → mostlyright_data-0.30.3}/src/mostlyright/data_harness/thin/v4_connected.py +0 -0
- {mostlyright_data-0.30.2 → mostlyright_data-0.30.3}/src/mostlyright/data_harness/thin/v4_connections.py +0 -0
- {mostlyright_data-0.30.2 → mostlyright_data-0.30.3}/src/mostlyright/data_harness/thin/v4_dataset_covers.py +0 -0
- {mostlyright_data-0.30.2 → mostlyright_data-0.30.3}/src/mostlyright/data_harness/thin/v4_datasets.py +0 -0
- {mostlyright_data-0.30.2 → mostlyright_data-0.30.3}/src/mostlyright/data_harness/thin/v4_handoff.py +0 -0
- {mostlyright_data-0.30.2 → mostlyright_data-0.30.3}/src/mostlyright/data_harness/thin/v4_narrative.py +0 -0
- {mostlyright_data-0.30.2 → mostlyright_data-0.30.3}/src/mostlyright/data_harness/thin/v4_public.py +0 -0
- {mostlyright_data-0.30.2 → mostlyright_data-0.30.3}/src/mostlyright/data_harness/thin/v4_query.py +0 -0
- {mostlyright_data-0.30.2 → mostlyright_data-0.30.3}/src/mostlyright/data_harness/thin/v4_reader.py +0 -0
- {mostlyright_data-0.30.2 → mostlyright_data-0.30.3}/src/mostlyright/data_harness/thin/v4_search.py +0 -0
- {mostlyright_data-0.30.2 → mostlyright_data-0.30.3}/src/mostlyright/data_harness/thin/v4_search_contract.py +0 -0
- {mostlyright_data-0.30.2 → mostlyright_data-0.30.3}/src/mostlyright/data_harness/thin/v4_secrets.py +0 -0
- {mostlyright_data-0.30.2 → mostlyright_data-0.30.3}/src/mostlyright/data_harness/thin/v4_stream.py +0 -0
- {mostlyright_data-0.30.2 → mostlyright_data-0.30.3}/src/mostlyright/data_harness/thin/v4_tables.py +0 -0
- {mostlyright_data-0.30.2 → mostlyright_data-0.30.3}/src/mostlyright/data_harness/thin/vocabulary.py +0 -0
- {mostlyright_data-0.30.2 → mostlyright_data-0.30.3}/src/mostlyright/data_harness/ux/__init__.py +0 -0
- {mostlyright_data-0.30.2 → mostlyright_data-0.30.3}/src/mostlyright/data_harness/ux/attendance.py +0 -0
- {mostlyright_data-0.30.2 → mostlyright_data-0.30.3}/src/mostlyright/data_harness/ux/clarification.py +0 -0
- {mostlyright_data-0.30.2 → mostlyright_data-0.30.3}/src/mostlyright/data_harness/ux/cloud_auth.py +0 -0
- {mostlyright_data-0.30.2 → mostlyright_data-0.30.3}/src/mostlyright/data_harness/ux/commands/__init__.py +0 -0
- {mostlyright_data-0.30.2 → mostlyright_data-0.30.3}/src/mostlyright/data_harness/ux/commands/auth.py +0 -0
- {mostlyright_data-0.30.2 → mostlyright_data-0.30.3}/src/mostlyright/data_harness/ux/commands/clarify.py +0 -0
- {mostlyright_data-0.30.2 → mostlyright_data-0.30.3}/src/mostlyright/data_harness/ux/commands/login.py +0 -0
- {mostlyright_data-0.30.2 → mostlyright_data-0.30.3}/src/mostlyright/data_harness/ux/commands/whoami.py +0 -0
- {mostlyright_data-0.30.2 → mostlyright_data-0.30.3}/src/mostlyright/data_harness/ux/credential_native.py +0 -0
- {mostlyright_data-0.30.2 → mostlyright_data-0.30.3}/src/mostlyright/data_harness/ux/credential_store.py +0 -0
- {mostlyright_data-0.30.2 → mostlyright_data-0.30.3}/src/mostlyright/data_harness/ux/credentials.py +0 -0
- {mostlyright_data-0.30.2 → mostlyright_data-0.30.3}/src/mostlyright/data_harness/ux/login.py +0 -0
- {mostlyright_data-0.30.2 → mostlyright_data-0.30.3}/src/mostlyright/data_harness/ux/path_kind.py +0 -0
- {mostlyright_data-0.30.2 → mostlyright_data-0.30.3}/src/mostlyright/data_harness/ux/plain_file.py +0 -0
- {mostlyright_data-0.30.2 → mostlyright_data-0.30.3}/src/mostlyright/data_harness/ux/remediation.py +0 -0
- {mostlyright_data-0.30.2 → mostlyright_data-0.30.3}/src/mostlyright/data_harness/ux/render.py +0 -0
|
@@ -152,6 +152,9 @@ step 6. The stage 3 reference holds its rule. Gate 4 is step 6.
|
|
|
152
152
|
quality checks.
|
|
153
153
|
7. Follow the returned run with `mr-data watch RUN_ID --json`. Its `source_rates` and
|
|
154
154
|
`mr-data status RUN_ID --json` on a live run give each collection source's rate and time left.
|
|
155
|
+
On a queued or running run, `status` also gives `progress`: the current attempt, how many of
|
|
156
|
+
its sources it fetched of how many, the source it is on with its pages, and how the attempt
|
|
157
|
+
before it ended. A handed-back run's new attempt counts from zero.
|
|
155
158
|
Quote those numbers rather than doing the arithmetic. Read `run.status`: returning an existing
|
|
156
159
|
run does not mean new work was queued. Resume the known run after an interruption, using the
|
|
157
160
|
saved cursor where available. Read [run lifecycle](references/live-run.md) for holds and
|
{mostlyright_data-0.30.2 → mostlyright_data-0.30.3}/src/mostlyright/data_harness/page_coverage.py
RENAMED
|
@@ -20,6 +20,7 @@ __all__ = [
|
|
|
20
20
|
"PAGE_BUDGET_KINDS",
|
|
21
21
|
"PAGE_COVERAGE_COUNT_FIELDS",
|
|
22
22
|
"PAGE_COVERAGE_FIELDS",
|
|
23
|
+
"SOURCE_ROWS_INCOMPLETE",
|
|
23
24
|
"page_coverage_sentence",
|
|
24
25
|
]
|
|
25
26
|
|
|
@@ -42,6 +43,9 @@ __all__ = [
|
|
|
42
43
|
#: predecessor rows, but current collection refresh is refused before acquisition, except a
|
|
43
44
|
#: per-row request collection's, which refreshes with the direct request window it inherits and
|
|
44
45
|
#: asks again for a failed row whenever a refresh covers that row's partition.
|
|
46
|
+
#: A ``source_rows`` collection also states it on a full run, as ``SOURCE_ROWS_INCOMPLETE``, when
|
|
47
|
+
#: the upstream relation it lists from is incomplete: that is not a listing anybody failed to read
|
|
48
|
+
#: but a list that may be short by what the upstream source is missing, and the sentence says so.
|
|
45
49
|
PAGE_COVERAGE_FIELDS: tuple[str, ...] = (
|
|
46
50
|
"discovered",
|
|
47
51
|
"discovery_requests",
|
|
@@ -84,6 +88,46 @@ PAGE_COVERAGE_COUNT_FIELDS: tuple[str, ...] = (
|
|
|
84
88
|
)
|
|
85
89
|
|
|
86
90
|
|
|
91
|
+
#: The discovery failure a ``source_rows`` collection states when the upstream relation it lists
|
|
92
|
+
#: from is itself incomplete (failed, pending or unlisted members upstream). Nothing failed to be
|
|
93
|
+
#: LISTED: the list is built from rows another source did not finish delivering, so it may be
|
|
94
|
+
#: short by exactly what that source is missing. Said as what it is, never as an unreadable
|
|
95
|
+
#: listing, because a reader told "the listing could not be read" goes looking for an outage.
|
|
96
|
+
SOURCE_ROWS_INCOMPLETE = "SOURCE_ROWS_INCOMPLETE"
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
def _count(block: Mapping[str, Any], member: str) -> int | None:
|
|
100
|
+
value = block.get(member)
|
|
101
|
+
if isinstance(value, bool) or not isinstance(value, int) or value < 0:
|
|
102
|
+
return None
|
|
103
|
+
return value
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
def _pages_held(block: Mapping[str, Any]) -> int | None:
|
|
107
|
+
"""How many of the collection's members hold an answer, or ``None`` when the block cannot say.
|
|
108
|
+
|
|
109
|
+
MEMBERS, NOT CALLS. ``fetched_this_run`` counts the requests this run made: a per-row request
|
|
110
|
+
collection asks once for every member that renders the same request, a batch answers up to a
|
|
111
|
+
hundred members in one call, and a page kept from an earlier capture is not fetched again. So
|
|
112
|
+
``fetched_this_run`` over ``discovered`` divides calls by members, and a run that answered
|
|
113
|
+
every member it listed reads as half done (food run 23161446: "459,156 of 1,005,223" for a
|
|
114
|
+
run with 1,004,768 members answered and 455 failed). The members that hold an answer are the
|
|
115
|
+
ones the ledger knows that are neither still owed, nor failed, nor skipped -- the same count
|
|
116
|
+
the dataset page's sources card prints as fetched.
|
|
117
|
+
|
|
118
|
+
Read with ``get``: a record written before these members existed carries only the four the
|
|
119
|
+
sentence always needed, and says what it always said.
|
|
120
|
+
"""
|
|
121
|
+
|
|
122
|
+
known = _count(block, "known")
|
|
123
|
+
pending = _count(block, "pending")
|
|
124
|
+
if known is None or pending is None:
|
|
125
|
+
return None
|
|
126
|
+
failed = _count(block, "failed") or 0
|
|
127
|
+
skipped = _count(block, "skipped") or 0
|
|
128
|
+
return max(known - pending - failed - skipped, 0)
|
|
129
|
+
|
|
130
|
+
|
|
87
131
|
def page_coverage_sentence(block: Mapping[str, Any]) -> str:
|
|
88
132
|
"""The one sentence a person reads off a page collection's coverage.
|
|
89
133
|
|
|
@@ -96,13 +140,29 @@ def page_coverage_sentence(block: Mapping[str, Any]) -> str:
|
|
|
96
140
|
failed = int(block["failed"])
|
|
97
141
|
if block["complete"]:
|
|
98
142
|
return f"all {discovered:,} pages fetched"
|
|
99
|
-
|
|
143
|
+
held = _pages_held(block)
|
|
144
|
+
if held is None:
|
|
145
|
+
parts = [f"{fetched:,} of {discovered:,} pages fetched"]
|
|
146
|
+
else:
|
|
147
|
+
# A ledger can know pages its latest listing no longer names (a refresh keeps them), so
|
|
148
|
+
# the whole is the larger of the two and the sentence never says "more of fewer".
|
|
149
|
+
whole = max(discovered, _count(block, "known") or 0)
|
|
150
|
+
lead = f"{held:,} of {whole:,} pages fetched"
|
|
151
|
+
if fetched != held:
|
|
152
|
+
lead += f" ({fetched:,} requests this run)"
|
|
153
|
+
parts = [lead]
|
|
100
154
|
# READ WITH ``get``, AND ONLY THIS MEMBER. The block a run produces always carries it, and the
|
|
101
155
|
# block Studio hands back may not: it is optional on the run record, so a record written before
|
|
102
156
|
# the member existed is still one sentence rather than a KeyError this lane swallows whole.
|
|
103
157
|
listing = block.get("discovery_failure")
|
|
104
158
|
if isinstance(listing, Mapping):
|
|
105
|
-
|
|
159
|
+
if listing.get("code") == SOURCE_ROWS_INCOMPLETE:
|
|
160
|
+
parts.append(
|
|
161
|
+
"a page list built from another source's rows may be short, because that source "
|
|
162
|
+
f"is incomplete ({SOURCE_ROWS_INCOMPLETE})"
|
|
163
|
+
)
|
|
164
|
+
else:
|
|
165
|
+
parts.append(f"the page listing could not be read ({listing['code']})")
|
|
106
166
|
if failed:
|
|
107
167
|
parts.append(f"{failed:,} failed")
|
|
108
168
|
# The block does not say which kind of collection it counts, so the remedy names both. A
|
{mostlyright_data-0.30.2 → mostlyright_data-0.30.3}/src/mostlyright/data_harness/thin/v4_runs.py
RENAMED
|
@@ -2355,6 +2355,8 @@ def status(args: argparse.Namespace, *, client: StudioV4RunClient | None = None)
|
|
|
2355
2355
|
held = {member: run[member] for member in _PROJECTION_MEMBERS[1:] if member in run}
|
|
2356
2356
|
if held:
|
|
2357
2357
|
payload["projection"] = held
|
|
2358
|
+
if state in ATTEMPTING_RUN_STATUSES:
|
|
2359
|
+
payload.update(attempt_progress_members(selected, run_id))
|
|
2358
2360
|
if getattr(args, "rate", False) and state not in TERMINAL_RUN_STATUSES:
|
|
2359
2361
|
# Imported here: progress_rate reads the event stream, whose module imports this one.
|
|
2360
2362
|
from mostlyright.data_harness.thin import progress_rate
|
|
@@ -2378,6 +2380,112 @@ def status(args: argparse.Namespace, *, client: StudioV4RunClient | None = None)
|
|
|
2378
2380
|
return payload
|
|
2379
2381
|
|
|
2380
2382
|
|
|
2383
|
+
#: The states a run holds while it has, or is between, producer attempts. A run held at a spend
|
|
2384
|
+
#: or sample gate has never been claimed, so there is no attempt to read for it.
|
|
2385
|
+
ATTEMPTING_RUN_STATUSES: frozenset[str] = frozenset({"queued", "running"})
|
|
2386
|
+
|
|
2387
|
+
#: How each way an attempt can end reads in the progress sentence. The keys are
|
|
2388
|
+
#: ``run-attempts.schema.json``'s closed ``end`` vocabulary.
|
|
2389
|
+
_ATTEMPT_ENDS: dict[str, str] = {
|
|
2390
|
+
"running": "is still running",
|
|
2391
|
+
"completed": "completed",
|
|
2392
|
+
"requeued_by_worker": "was handed back by its own worker",
|
|
2393
|
+
"handed_back": "was handed back after its worker went silent",
|
|
2394
|
+
"failed": "failed",
|
|
2395
|
+
"lost": "went silent",
|
|
2396
|
+
}
|
|
2397
|
+
|
|
2398
|
+
|
|
2399
|
+
def attempt_progress_members(client: StudioV4RunClient, run_id: str) -> dict[str, Any]:
|
|
2400
|
+
"""The ``status`` members for a live run's current attempt and its sources, or why not.
|
|
2401
|
+
|
|
2402
|
+
Read off the attempt ledger (``GET /v4/runs/{run_id}/attempts``), which Studio folds from
|
|
2403
|
+
each progress tick as it arrives and never from the run log. So, unlike the rate, this does
|
|
2404
|
+
not depend on replaying the log in time, and an attempt that has run for hours still says
|
|
2405
|
+
how many of its sources it fetched. Counts are the current attempt's own: a run handed back
|
|
2406
|
+
walks its sources again from the first.
|
|
2407
|
+
|
|
2408
|
+
A Studio before 4.37.0 serves no per-source member, and then the attempt and how the one
|
|
2409
|
+
before it ended are still stated. A refused read is reported, never fatal: the run record
|
|
2410
|
+
has already been read.
|
|
2411
|
+
"""
|
|
2412
|
+
|
|
2413
|
+
try:
|
|
2414
|
+
answer = client.run_attempts(run_id)
|
|
2415
|
+
except ThinLaneError as refusal:
|
|
2416
|
+
return {"progress_unavailable": f"{refusal.code}: {refusal.detail}"}
|
|
2417
|
+
rows = answer.get("attempts") if isinstance(answer, Mapping) else None
|
|
2418
|
+
rows = [
|
|
2419
|
+
row for row in rows or () if isinstance(row, Mapping) and type(row.get("generation")) is int
|
|
2420
|
+
]
|
|
2421
|
+
if not rows:
|
|
2422
|
+
return {"progress_unavailable": "Studio lists no attempt of this run yet"}
|
|
2423
|
+
rows.sort(key=lambda row: row["generation"])
|
|
2424
|
+
current = rows[-1]
|
|
2425
|
+
sources = current.get("sources") if isinstance(current.get("sources"), Mapping) else None
|
|
2426
|
+
named = sources.get("current") if sources is not None else None
|
|
2427
|
+
progress: dict[str, Any] = {
|
|
2428
|
+
"attempt": current["generation"],
|
|
2429
|
+
"attempts": len(rows),
|
|
2430
|
+
"source_count": sources.get("source_count") if sources is not None else None,
|
|
2431
|
+
"sources_fetched": sources.get("fetched") if sources is not None else None,
|
|
2432
|
+
"sources_refused": sources.get("refused") if sources is not None else None,
|
|
2433
|
+
"counted_from_first_tick": (
|
|
2434
|
+
sources.get("counted_from_first_tick") if sources is not None else None
|
|
2435
|
+
),
|
|
2436
|
+
"current_source": dict(named) if isinstance(named, Mapping) else None,
|
|
2437
|
+
"previous_attempt": None,
|
|
2438
|
+
}
|
|
2439
|
+
if len(rows) > 1:
|
|
2440
|
+
previous = rows[-2]
|
|
2441
|
+
loss = previous.get("loss") if isinstance(previous.get("loss"), Mapping) else {}
|
|
2442
|
+
progress["previous_attempt"] = {
|
|
2443
|
+
"attempt": previous["generation"],
|
|
2444
|
+
"end": previous.get("end"),
|
|
2445
|
+
"ended_at": previous.get("ended_at"),
|
|
2446
|
+
"cause": loss.get("cause"),
|
|
2447
|
+
"cause_inferred": loss.get("inferred"),
|
|
2448
|
+
}
|
|
2449
|
+
return {"progress": progress, "progress_sentence": attempt_progress_sentence(progress)}
|
|
2450
|
+
|
|
2451
|
+
|
|
2452
|
+
def attempt_progress_sentence(progress: Mapping[str, Any]) -> str:
|
|
2453
|
+
"""``Attempt 4 of 4 has fetched 27 of 86 sources and is on ...``, from the members above."""
|
|
2454
|
+
|
|
2455
|
+
said = f"Attempt {progress['attempt']} of {progress['attempts']}"
|
|
2456
|
+
fetched, count = progress.get("sources_fetched"), progress.get("source_count")
|
|
2457
|
+
if fetched is None:
|
|
2458
|
+
said += "; this Studio reports no per-source progress for it."
|
|
2459
|
+
else:
|
|
2460
|
+
said += f" has fetched {fetched:,}"
|
|
2461
|
+
said += f" of {count:,} sources" if count is not None else " sources"
|
|
2462
|
+
if progress.get("counted_from_first_tick") is False:
|
|
2463
|
+
said += " (at least: counting began after the attempt started)"
|
|
2464
|
+
named = progress.get("current_source")
|
|
2465
|
+
if isinstance(named, Mapping):
|
|
2466
|
+
said += f" and is on {named.get('source_name')}"
|
|
2467
|
+
if named.get("source_index") is not None and count is not None:
|
|
2468
|
+
said += f", source {named['source_index']:,} of {count:,}"
|
|
2469
|
+
done, planned = named.get("pages_processed"), named.get("pages_planned")
|
|
2470
|
+
unit = "members" if named.get("pages_unit") == "member" else "pages"
|
|
2471
|
+
if done is not None and planned is not None and named.get("discovery_complete"):
|
|
2472
|
+
said += f": {done:,} of {planned:,} {unit}"
|
|
2473
|
+
elif done is not None:
|
|
2474
|
+
said += f": {done:,} {unit} so far"
|
|
2475
|
+
said += "."
|
|
2476
|
+
previous = progress.get("previous_attempt")
|
|
2477
|
+
if isinstance(previous, Mapping):
|
|
2478
|
+
end = _ATTEMPT_ENDS.get(str(previous.get("end")), f"ended {previous.get('end')}")
|
|
2479
|
+
said += f" Attempt {previous['attempt']} {end}"
|
|
2480
|
+
if previous.get("cause") is not None:
|
|
2481
|
+
said += (
|
|
2482
|
+
f"; {'inferred ' if previous.get('cause_inferred') else ''}cause: "
|
|
2483
|
+
f"{previous['cause']}"
|
|
2484
|
+
)
|
|
2485
|
+
said += "."
|
|
2486
|
+
return said
|
|
2487
|
+
|
|
2488
|
+
|
|
2381
2489
|
def status_exit_code(payload: Mapping[str, Any]) -> int:
|
|
2382
2490
|
"""A failed run exits non-zero, so a script gating on a build cannot read it as a success."""
|
|
2383
2491
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{mostlyright_data-0.30.2 → mostlyright_data-0.30.3}/skills/mr-data-build/references/boundaries.md
RENAMED
|
File without changes
|
|
File without changes
|
{mostlyright_data-0.30.2 → mostlyright_data-0.30.3}/skills/mr-data-build/references/commands.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{mostlyright_data-0.30.2 → mostlyright_data-0.30.3}/skills/mr-data-build/references/live-run.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{mostlyright_data-0.30.2 → mostlyright_data-0.30.3}/skills/mr-data-build/references/one-install.md
RENAMED
|
File without changes
|
{mostlyright_data-0.30.2 → mostlyright_data-0.30.3}/skills/mr-data-build/references/patterns.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{mostlyright_data-0.30.2 → mostlyright_data-0.30.3}/skills/mr-data-build/references/promote.md
RENAMED
|
File without changes
|
{mostlyright_data-0.30.2 → mostlyright_data-0.30.3}/skills/mr-data-build/references/readers.md
RENAMED
|
File without changes
|
{mostlyright_data-0.30.2 → mostlyright_data-0.30.3}/skills/mr-data-build/references/receipts.md
RENAMED
|
File without changes
|
{mostlyright_data-0.30.2 → mostlyright_data-0.30.3}/skills/mr-data-build/references/recipe-test.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{mostlyright_data-0.30.2 → mostlyright_data-0.30.3}/skills/mr-data-build/references/sources.md
RENAMED
|
File without changes
|
|
File without changes
|
{mostlyright_data-0.30.2 → mostlyright_data-0.30.3}/skills/mr-data-build/references/transforms.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{mostlyright_data-0.30.2 → mostlyright_data-0.30.3}/src/mostlyright/data_harness/__init__.py
RENAMED
|
File without changes
|
{mostlyright_data-0.30.2 → mostlyright_data-0.30.3}/src/mostlyright/data_harness/agent_protocol.py
RENAMED
|
File without changes
|
{mostlyright_data-0.30.2 → mostlyright_data-0.30.3}/src/mostlyright/data_harness/canonical.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{mostlyright_data-0.30.2 → mostlyright_data-0.30.3}/src/mostlyright/data_harness/key_seam.py
RENAMED
|
File without changes
|
|
File without changes
|
{mostlyright_data-0.30.2 → mostlyright_data-0.30.3}/src/mostlyright/data_harness/session_probes.py
RENAMED
|
File without changes
|
{mostlyright_data-0.30.2 → mostlyright_data-0.30.3}/src/mostlyright/data_harness/skill_assets.py
RENAMED
|
File without changes
|
{mostlyright_data-0.30.2 → mostlyright_data-0.30.3}/src/mostlyright/data_harness/table_manifest.py
RENAMED
|
File without changes
|
{mostlyright_data-0.30.2 → mostlyright_data-0.30.3}/src/mostlyright/data_harness/thin/__init__.py
RENAMED
|
File without changes
|
{mostlyright_data-0.30.2 → mostlyright_data-0.30.3}/src/mostlyright/data_harness/thin/acquire.py
RENAMED
|
File without changes
|
|
File without changes
|
{mostlyright_data-0.30.2 → mostlyright_data-0.30.3}/src/mostlyright/data_harness/thin/activity.py
RENAMED
|
File without changes
|
{mostlyright_data-0.30.2 → mostlyright_data-0.30.3}/src/mostlyright/data_harness/thin/approvals.py
RENAMED
|
File without changes
|
{mostlyright_data-0.30.2 → mostlyright_data-0.30.3}/src/mostlyright/data_harness/thin/backoff.py
RENAMED
|
File without changes
|
{mostlyright_data-0.30.2 → mostlyright_data-0.30.3}/src/mostlyright/data_harness/thin/categories.py
RENAMED
|
File without changes
|
{mostlyright_data-0.30.2 → mostlyright_data-0.30.3}/src/mostlyright/data_harness/thin/commands.py
RENAMED
|
File without changes
|
|
File without changes
|
{mostlyright_data-0.30.2 → mostlyright_data-0.30.3}/src/mostlyright/data_harness/thin/download.py
RENAMED
|
File without changes
|
|
File without changes
|
{mostlyright_data-0.30.2 → mostlyright_data-0.30.3}/src/mostlyright/data_harness/thin/narrative.py
RENAMED
|
File without changes
|
{mostlyright_data-0.30.2 → mostlyright_data-0.30.3}/src/mostlyright/data_harness/thin/parity.py
RENAMED
|
File without changes
|
{mostlyright_data-0.30.2 → mostlyright_data-0.30.3}/src/mostlyright/data_harness/thin/probe.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{mostlyright_data-0.30.2 → mostlyright_data-0.30.3}/src/mostlyright/data_harness/thin/propose.py
RENAMED
|
File without changes
|
{mostlyright_data-0.30.2 → mostlyright_data-0.30.3}/src/mostlyright/data_harness/thin/recipe.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{mostlyright_data-0.30.2 → mostlyright_data-0.30.3}/src/mostlyright/data_harness/thin/recipe_lint.py
RENAMED
|
File without changes
|
{mostlyright_data-0.30.2 → mostlyright_data-0.30.3}/src/mostlyright/data_harness/thin/recipe_test.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{mostlyright_data-0.30.2 → mostlyright_data-0.30.3}/src/mostlyright/data_harness/thin/research.py
RENAMED
|
File without changes
|
{mostlyright_data-0.30.2 → mostlyright_data-0.30.3}/src/mostlyright/data_harness/thin/router.py
RENAMED
|
File without changes
|
|
File without changes
|
{mostlyright_data-0.30.2 → mostlyright_data-0.30.3}/src/mostlyright/data_harness/thin/run_prefix.py
RENAMED
|
File without changes
|
{mostlyright_data-0.30.2 → mostlyright_data-0.30.3}/src/mostlyright/data_harness/thin/runs.py
RENAMED
|
File without changes
|
{mostlyright_data-0.30.2 → mostlyright_data-0.30.3}/src/mostlyright/data_harness/thin/session.py
RENAMED
|
File without changes
|
{mostlyright_data-0.30.2 → mostlyright_data-0.30.3}/src/mostlyright/data_harness/thin/stream.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{mostlyright_data-0.30.2 → mostlyright_data-0.30.3}/src/mostlyright/data_harness/thin/support.py
RENAMED
|
File without changes
|
|
File without changes
|
{mostlyright_data-0.30.2 → mostlyright_data-0.30.3}/src/mostlyright/data_harness/thin/transport.py
RENAMED
|
File without changes
|
{mostlyright_data-0.30.2 → mostlyright_data-0.30.3}/src/mostlyright/data_harness/thin/user_agent.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{mostlyright_data-0.30.2 → mostlyright_data-0.30.3}/src/mostlyright/data_harness/thin/v4_catalog.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{mostlyright_data-0.30.2 → mostlyright_data-0.30.3}/src/mostlyright/data_harness/thin/v4_datasets.py
RENAMED
|
File without changes
|
{mostlyright_data-0.30.2 → mostlyright_data-0.30.3}/src/mostlyright/data_harness/thin/v4_handoff.py
RENAMED
|
File without changes
|
|
File without changes
|
{mostlyright_data-0.30.2 → mostlyright_data-0.30.3}/src/mostlyright/data_harness/thin/v4_public.py
RENAMED
|
File without changes
|
{mostlyright_data-0.30.2 → mostlyright_data-0.30.3}/src/mostlyright/data_harness/thin/v4_query.py
RENAMED
|
File without changes
|
{mostlyright_data-0.30.2 → mostlyright_data-0.30.3}/src/mostlyright/data_harness/thin/v4_reader.py
RENAMED
|
File without changes
|
{mostlyright_data-0.30.2 → mostlyright_data-0.30.3}/src/mostlyright/data_harness/thin/v4_search.py
RENAMED
|
File without changes
|
|
File without changes
|
{mostlyright_data-0.30.2 → mostlyright_data-0.30.3}/src/mostlyright/data_harness/thin/v4_secrets.py
RENAMED
|
File without changes
|
{mostlyright_data-0.30.2 → mostlyright_data-0.30.3}/src/mostlyright/data_harness/thin/v4_stream.py
RENAMED
|
File without changes
|
{mostlyright_data-0.30.2 → mostlyright_data-0.30.3}/src/mostlyright/data_harness/thin/v4_tables.py
RENAMED
|
File without changes
|
{mostlyright_data-0.30.2 → mostlyright_data-0.30.3}/src/mostlyright/data_harness/thin/vocabulary.py
RENAMED
|
File without changes
|
{mostlyright_data-0.30.2 → mostlyright_data-0.30.3}/src/mostlyright/data_harness/ux/__init__.py
RENAMED
|
File without changes
|
{mostlyright_data-0.30.2 → mostlyright_data-0.30.3}/src/mostlyright/data_harness/ux/attendance.py
RENAMED
|
File without changes
|
{mostlyright_data-0.30.2 → mostlyright_data-0.30.3}/src/mostlyright/data_harness/ux/clarification.py
RENAMED
|
File without changes
|
{mostlyright_data-0.30.2 → mostlyright_data-0.30.3}/src/mostlyright/data_harness/ux/cloud_auth.py
RENAMED
|
File without changes
|
|
File without changes
|
{mostlyright_data-0.30.2 → mostlyright_data-0.30.3}/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.30.2 → mostlyright_data-0.30.3}/src/mostlyright/data_harness/ux/credentials.py
RENAMED
|
File without changes
|
{mostlyright_data-0.30.2 → mostlyright_data-0.30.3}/src/mostlyright/data_harness/ux/login.py
RENAMED
|
File without changes
|
{mostlyright_data-0.30.2 → mostlyright_data-0.30.3}/src/mostlyright/data_harness/ux/path_kind.py
RENAMED
|
File without changes
|
{mostlyright_data-0.30.2 → mostlyright_data-0.30.3}/src/mostlyright/data_harness/ux/plain_file.py
RENAMED
|
File without changes
|
{mostlyright_data-0.30.2 → mostlyright_data-0.30.3}/src/mostlyright/data_harness/ux/remediation.py
RENAMED
|
File without changes
|
{mostlyright_data-0.30.2 → mostlyright_data-0.30.3}/src/mostlyright/data_harness/ux/render.py
RENAMED
|
File without changes
|