mostlyright-data 0.30.1__tar.gz → 0.30.2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {mostlyright_data-0.30.1 → mostlyright_data-0.30.2}/PKG-INFO +1 -1
- {mostlyright_data-0.30.1 → mostlyright_data-0.30.2}/src/mostlyright/data_harness/thin/progress_rate.py +145 -29
- {mostlyright_data-0.30.1 → mostlyright_data-0.30.2}/src/mostlyright/data_harness/thin/v4_stream.py +10 -2
- {mostlyright_data-0.30.1 → mostlyright_data-0.30.2}/.gitignore +0 -0
- {mostlyright_data-0.30.1 → mostlyright_data-0.30.2}/README.md +0 -0
- {mostlyright_data-0.30.1 → mostlyright_data-0.30.2}/pyproject.toml +0 -0
- {mostlyright_data-0.30.1 → mostlyright_data-0.30.2}/scripts/hatch_build.py +0 -0
- {mostlyright_data-0.30.1 → mostlyright_data-0.30.2}/skills/mr-data-build/SKILL.md +0 -0
- {mostlyright_data-0.30.1 → mostlyright_data-0.30.2}/skills/mr-data-build/agents/openai.yaml +0 -0
- {mostlyright_data-0.30.1 → mostlyright_data-0.30.2}/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.1 → mostlyright_data-0.30.2}/skills/mr-data-build/references/2-brief-two-to-four-questions-each-with-a-recommended-answer.md +0 -0
- {mostlyright_data-0.30.1 → mostlyright_data-0.30.2}/skills/mr-data-build/references/3-probe-read-a-source-before-committing-to-it.md +0 -0
- {mostlyright_data-0.30.1 → mostlyright_data-0.30.2}/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.1 → mostlyright_data-0.30.2}/skills/mr-data-build/references/5-draft-one-recipe-document-one-call.md +0 -0
- {mostlyright_data-0.30.1 → mostlyright_data-0.30.2}/skills/mr-data-build/references/6-build-one-run-sized-to-acquire-every-measured-source-whole.md +0 -0
- {mostlyright_data-0.30.1 → mostlyright_data-0.30.2}/skills/mr-data-build/references/7-interrogate-ask-the-run-what-it-actually-delivered.md +0 -0
- {mostlyright_data-0.30.1 → mostlyright_data-0.30.2}/skills/mr-data-build/references/8-fix-revise-the-document-and-register-it-again.md +0 -0
- {mostlyright_data-0.30.1 → mostlyright_data-0.30.2}/skills/mr-data-build/references/9-present-only-what-survived-inspection-with-caveats.md +0 -0
- {mostlyright_data-0.30.1 → mostlyright_data-0.30.2}/skills/mr-data-build/references/agent-protocol.md +0 -0
- {mostlyright_data-0.30.1 → mostlyright_data-0.30.2}/skills/mr-data-build/references/autonomous-delivery.md +0 -0
- {mostlyright_data-0.30.1 → mostlyright_data-0.30.2}/skills/mr-data-build/references/before-the-first-tool-call.md +0 -0
- {mostlyright_data-0.30.1 → mostlyright_data-0.30.2}/skills/mr-data-build/references/boundaries.md +0 -0
- {mostlyright_data-0.30.1 → mostlyright_data-0.30.2}/skills/mr-data-build/references/cloud-authentication-preflight.md +0 -0
- {mostlyright_data-0.30.1 → mostlyright_data-0.30.2}/skills/mr-data-build/references/commands.md +0 -0
- {mostlyright_data-0.30.1 → mostlyright_data-0.30.2}/skills/mr-data-build/references/cross-repository-protocol-reference.md +0 -0
- {mostlyright_data-0.30.1 → mostlyright_data-0.30.2}/skills/mr-data-build/references/installation-parity.md +0 -0
- {mostlyright_data-0.30.1 → mostlyright_data-0.30.2}/skills/mr-data-build/references/live-run.md +0 -0
- {mostlyright_data-0.30.1 → mostlyright_data-0.30.2}/skills/mr-data-build/references/making-a-table-incremental.md +0 -0
- {mostlyright_data-0.30.1 → mostlyright_data-0.30.2}/skills/mr-data-build/references/narrating-the-run.md +0 -0
- {mostlyright_data-0.30.1 → mostlyright_data-0.30.2}/skills/mr-data-build/references/not-hosted-yet.md +0 -0
- {mostlyright_data-0.30.1 → mostlyright_data-0.30.2}/skills/mr-data-build/references/one-install.md +0 -0
- {mostlyright_data-0.30.1 → mostlyright_data-0.30.2}/skills/mr-data-build/references/patterns.md +0 -0
- {mostlyright_data-0.30.1 → mostlyright_data-0.30.2}/skills/mr-data-build/references/prediction-labels.md +0 -0
- {mostlyright_data-0.30.1 → mostlyright_data-0.30.2}/skills/mr-data-build/references/preparing-table-search.md +0 -0
- {mostlyright_data-0.30.1 → mostlyright_data-0.30.2}/skills/mr-data-build/references/promote.md +0 -0
- {mostlyright_data-0.30.1 → mostlyright_data-0.30.2}/skills/mr-data-build/references/readers.md +0 -0
- {mostlyright_data-0.30.1 → mostlyright_data-0.30.2}/skills/mr-data-build/references/receipts.md +0 -0
- {mostlyright_data-0.30.1 → mostlyright_data-0.30.2}/skills/mr-data-build/references/recipe-test.md +0 -0
- {mostlyright_data-0.30.1 → mostlyright_data-0.30.2}/skills/mr-data-build/references/recording-a-stream-venue.md +0 -0
- {mostlyright_data-0.30.1 → mostlyright_data-0.30.2}/skills/mr-data-build/references/recovering-an-import-failure.md +0 -0
- {mostlyright_data-0.30.1 → mostlyright_data-0.30.2}/skills/mr-data-build/references/reference-pages.md +0 -0
- {mostlyright_data-0.30.1 → mostlyright_data-0.30.2}/skills/mr-data-build/references/required-protocol.md +0 -0
- {mostlyright_data-0.30.1 → mostlyright_data-0.30.2}/skills/mr-data-build/references/source-credentials.md +0 -0
- {mostlyright_data-0.30.1 → mostlyright_data-0.30.2}/skills/mr-data-build/references/sources.md +0 -0
- {mostlyright_data-0.30.1 → mostlyright_data-0.30.2}/skills/mr-data-build/references/the-one-thing-to-say-about-the-skill-itself.md +0 -0
- {mostlyright_data-0.30.1 → mostlyright_data-0.30.2}/skills/mr-data-build/references/transforms.md +0 -0
- {mostlyright_data-0.30.1 → mostlyright_data-0.30.2}/skills/mr-data-build/references/user-communication-contract.md +0 -0
- {mostlyright_data-0.30.1 → mostlyright_data-0.30.2}/skills/mr-data-build/references/writing-a-decision-record.md +0 -0
- {mostlyright_data-0.30.1 → mostlyright_data-0.30.2}/skills/mr-data-build/scripts/write_research_notebook.py +0 -0
- {mostlyright_data-0.30.1 → mostlyright_data-0.30.2}/src/mostlyright/data_harness/__init__.py +0 -0
- {mostlyright_data-0.30.1 → mostlyright_data-0.30.2}/src/mostlyright/data_harness/agent_protocol.py +0 -0
- {mostlyright_data-0.30.1 → mostlyright_data-0.30.2}/src/mostlyright/data_harness/canonical.py +0 -0
- {mostlyright_data-0.30.1 → mostlyright_data-0.30.2}/src/mostlyright/data_harness/formats.py +0 -0
- {mostlyright_data-0.30.1 → mostlyright_data-0.30.2}/src/mostlyright/data_harness/hosted_crawler_protocol.py +0 -0
- {mostlyright_data-0.30.1 → mostlyright_data-0.30.2}/src/mostlyright/data_harness/key_seam.py +0 -0
- {mostlyright_data-0.30.1 → mostlyright_data-0.30.2}/src/mostlyright/data_harness/page_coverage.py +0 -0
- {mostlyright_data-0.30.1 → mostlyright_data-0.30.2}/src/mostlyright/data_harness/part_check_evidence.py +0 -0
- {mostlyright_data-0.30.1 → mostlyright_data-0.30.2}/src/mostlyright/data_harness/session_probes.py +0 -0
- {mostlyright_data-0.30.1 → mostlyright_data-0.30.2}/src/mostlyright/data_harness/skill_assets.py +0 -0
- {mostlyright_data-0.30.1 → mostlyright_data-0.30.2}/src/mostlyright/data_harness/table_manifest.py +0 -0
- {mostlyright_data-0.30.1 → mostlyright_data-0.30.2}/src/mostlyright/data_harness/thin/__init__.py +0 -0
- {mostlyright_data-0.30.1 → mostlyright_data-0.30.2}/src/mostlyright/data_harness/thin/acquire.py +0 -0
- {mostlyright_data-0.30.1 → mostlyright_data-0.30.2}/src/mostlyright/data_harness/thin/acquire_cancel.py +0 -0
- {mostlyright_data-0.30.1 → mostlyright_data-0.30.2}/src/mostlyright/data_harness/thin/activity.py +0 -0
- {mostlyright_data-0.30.1 → mostlyright_data-0.30.2}/src/mostlyright/data_harness/thin/approvals.py +0 -0
- {mostlyright_data-0.30.1 → mostlyright_data-0.30.2}/src/mostlyright/data_harness/thin/backoff.py +0 -0
- {mostlyright_data-0.30.1 → mostlyright_data-0.30.2}/src/mostlyright/data_harness/thin/categories.py +0 -0
- {mostlyright_data-0.30.1 → mostlyright_data-0.30.2}/src/mostlyright/data_harness/thin/commands.py +0 -0
- {mostlyright_data-0.30.1 → mostlyright_data-0.30.2}/src/mostlyright/data_harness/thin/dataset-categories-v1.json +0 -0
- {mostlyright_data-0.30.1 → mostlyright_data-0.30.2}/src/mostlyright/data_harness/thin/download.py +0 -0
- {mostlyright_data-0.30.1 → mostlyright_data-0.30.2}/src/mostlyright/data_harness/thin/fast_features.py +0 -0
- {mostlyright_data-0.30.1 → mostlyright_data-0.30.2}/src/mostlyright/data_harness/thin/narrative.py +0 -0
- {mostlyright_data-0.30.1 → mostlyright_data-0.30.2}/src/mostlyright/data_harness/thin/parity.py +0 -0
- {mostlyright_data-0.30.1 → mostlyright_data-0.30.2}/src/mostlyright/data_harness/thin/probe.py +0 -0
- {mostlyright_data-0.30.1 → mostlyright_data-0.30.2}/src/mostlyright/data_harness/thin/progress_vocabulary.py +0 -0
- {mostlyright_data-0.30.1 → mostlyright_data-0.30.2}/src/mostlyright/data_harness/thin/propose.py +0 -0
- {mostlyright_data-0.30.1 → mostlyright_data-0.30.2}/src/mostlyright/data_harness/thin/recipe.py +0 -0
- {mostlyright_data-0.30.1 → mostlyright_data-0.30.2}/src/mostlyright/data_harness/thin/recipe_brief.py +0 -0
- {mostlyright_data-0.30.1 → mostlyright_data-0.30.2}/src/mostlyright/data_harness/thin/recipe_explain.py +0 -0
- {mostlyright_data-0.30.1 → mostlyright_data-0.30.2}/src/mostlyright/data_harness/thin/recipe_forecast.py +0 -0
- {mostlyright_data-0.30.1 → mostlyright_data-0.30.2}/src/mostlyright/data_harness/thin/recipe_lint.py +0 -0
- {mostlyright_data-0.30.1 → mostlyright_data-0.30.2}/src/mostlyright/data_harness/thin/recipe_test.py +0 -0
- {mostlyright_data-0.30.1 → mostlyright_data-0.30.2}/src/mostlyright/data_harness/thin/refresh_rehearsal.py +0 -0
- {mostlyright_data-0.30.1 → mostlyright_data-0.30.2}/src/mostlyright/data_harness/thin/release_check.py +0 -0
- {mostlyright_data-0.30.1 → mostlyright_data-0.30.2}/src/mostlyright/data_harness/thin/research.py +0 -0
- {mostlyright_data-0.30.1 → mostlyright_data-0.30.2}/src/mostlyright/data_harness/thin/router.py +0 -0
- {mostlyright_data-0.30.1 → mostlyright_data-0.30.2}/src/mostlyright/data_harness/thin/run_diagnose.py +0 -0
- {mostlyright_data-0.30.1 → mostlyright_data-0.30.2}/src/mostlyright/data_harness/thin/run_prefix.py +0 -0
- {mostlyright_data-0.30.1 → mostlyright_data-0.30.2}/src/mostlyright/data_harness/thin/runs.py +0 -0
- {mostlyright_data-0.30.1 → mostlyright_data-0.30.2}/src/mostlyright/data_harness/thin/session.py +0 -0
- {mostlyright_data-0.30.1 → mostlyright_data-0.30.2}/src/mostlyright/data_harness/thin/stream.py +0 -0
- {mostlyright_data-0.30.1 → mostlyright_data-0.30.2}/src/mostlyright/data_harness/thin/stream_venue.py +0 -0
- {mostlyright_data-0.30.1 → mostlyright_data-0.30.2}/src/mostlyright/data_harness/thin/studio_capabilities.py +0 -0
- {mostlyright_data-0.30.1 → mostlyright_data-0.30.2}/src/mostlyright/data_harness/thin/support.py +0 -0
- {mostlyright_data-0.30.1 → mostlyright_data-0.30.2}/src/mostlyright/data_harness/thin/table_search_contract.json +0 -0
- {mostlyright_data-0.30.1 → mostlyright_data-0.30.2}/src/mostlyright/data_harness/thin/transport.py +0 -0
- {mostlyright_data-0.30.1 → mostlyright_data-0.30.2}/src/mostlyright/data_harness/thin/user_agent.py +0 -0
- {mostlyright_data-0.30.1 → mostlyright_data-0.30.2}/src/mostlyright/data_harness/thin/v4.py +0 -0
- {mostlyright_data-0.30.1 → mostlyright_data-0.30.2}/src/mostlyright/data_harness/thin/v4_artifacts.py +0 -0
- {mostlyright_data-0.30.1 → mostlyright_data-0.30.2}/src/mostlyright/data_harness/thin/v4_catalog.py +0 -0
- {mostlyright_data-0.30.1 → mostlyright_data-0.30.2}/src/mostlyright/data_harness/thin/v4_connected.py +0 -0
- {mostlyright_data-0.30.1 → mostlyright_data-0.30.2}/src/mostlyright/data_harness/thin/v4_connections.py +0 -0
- {mostlyright_data-0.30.1 → mostlyright_data-0.30.2}/src/mostlyright/data_harness/thin/v4_dataset_covers.py +0 -0
- {mostlyright_data-0.30.1 → mostlyright_data-0.30.2}/src/mostlyright/data_harness/thin/v4_datasets.py +0 -0
- {mostlyright_data-0.30.1 → mostlyright_data-0.30.2}/src/mostlyright/data_harness/thin/v4_handoff.py +0 -0
- {mostlyright_data-0.30.1 → mostlyright_data-0.30.2}/src/mostlyright/data_harness/thin/v4_narrative.py +0 -0
- {mostlyright_data-0.30.1 → mostlyright_data-0.30.2}/src/mostlyright/data_harness/thin/v4_public.py +0 -0
- {mostlyright_data-0.30.1 → mostlyright_data-0.30.2}/src/mostlyright/data_harness/thin/v4_query.py +0 -0
- {mostlyright_data-0.30.1 → mostlyright_data-0.30.2}/src/mostlyright/data_harness/thin/v4_reader.py +0 -0
- {mostlyright_data-0.30.1 → mostlyright_data-0.30.2}/src/mostlyright/data_harness/thin/v4_runs.py +0 -0
- {mostlyright_data-0.30.1 → mostlyright_data-0.30.2}/src/mostlyright/data_harness/thin/v4_search.py +0 -0
- {mostlyright_data-0.30.1 → mostlyright_data-0.30.2}/src/mostlyright/data_harness/thin/v4_search_contract.py +0 -0
- {mostlyright_data-0.30.1 → mostlyright_data-0.30.2}/src/mostlyright/data_harness/thin/v4_secrets.py +0 -0
- {mostlyright_data-0.30.1 → mostlyright_data-0.30.2}/src/mostlyright/data_harness/thin/v4_tables.py +0 -0
- {mostlyright_data-0.30.1 → mostlyright_data-0.30.2}/src/mostlyright/data_harness/thin/vocabulary.py +0 -0
- {mostlyright_data-0.30.1 → mostlyright_data-0.30.2}/src/mostlyright/data_harness/ux/__init__.py +0 -0
- {mostlyright_data-0.30.1 → mostlyright_data-0.30.2}/src/mostlyright/data_harness/ux/attendance.py +0 -0
- {mostlyright_data-0.30.1 → mostlyright_data-0.30.2}/src/mostlyright/data_harness/ux/clarification.py +0 -0
- {mostlyright_data-0.30.1 → mostlyright_data-0.30.2}/src/mostlyright/data_harness/ux/cloud_auth.py +0 -0
- {mostlyright_data-0.30.1 → mostlyright_data-0.30.2}/src/mostlyright/data_harness/ux/commands/__init__.py +0 -0
- {mostlyright_data-0.30.1 → mostlyright_data-0.30.2}/src/mostlyright/data_harness/ux/commands/auth.py +0 -0
- {mostlyright_data-0.30.1 → mostlyright_data-0.30.2}/src/mostlyright/data_harness/ux/commands/clarify.py +0 -0
- {mostlyright_data-0.30.1 → mostlyright_data-0.30.2}/src/mostlyright/data_harness/ux/commands/login.py +0 -0
- {mostlyright_data-0.30.1 → mostlyright_data-0.30.2}/src/mostlyright/data_harness/ux/commands/whoami.py +0 -0
- {mostlyright_data-0.30.1 → mostlyright_data-0.30.2}/src/mostlyright/data_harness/ux/credential_native.py +0 -0
- {mostlyright_data-0.30.1 → mostlyright_data-0.30.2}/src/mostlyright/data_harness/ux/credential_store.py +0 -0
- {mostlyright_data-0.30.1 → mostlyright_data-0.30.2}/src/mostlyright/data_harness/ux/credentials.py +0 -0
- {mostlyright_data-0.30.1 → mostlyright_data-0.30.2}/src/mostlyright/data_harness/ux/login.py +0 -0
- {mostlyright_data-0.30.1 → mostlyright_data-0.30.2}/src/mostlyright/data_harness/ux/path_kind.py +0 -0
- {mostlyright_data-0.30.1 → mostlyright_data-0.30.2}/src/mostlyright/data_harness/ux/plain_file.py +0 -0
- {mostlyright_data-0.30.1 → mostlyright_data-0.30.2}/src/mostlyright/data_harness/ux/remediation.py +0 -0
- {mostlyright_data-0.30.1 → mostlyright_data-0.30.2}/src/mostlyright/data_harness/ux/render.py +0 -0
|
@@ -6,10 +6,10 @@ Each tick also carries the time it happened. Two ticks of one source give a rate
|
|
|
6
6
|
count gives what is left. Nothing here is a new Studio fact: it is the arithmetic an agent used to
|
|
7
7
|
do by hand while polling.
|
|
8
8
|
|
|
9
|
-
``pages_processed``
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
9
|
+
``pages_processed`` combines saved answers replayed and requests sent. Its rate is therefore
|
|
10
|
+
source-member throughput, never publisher throughput or whole-run completion. Live status rates
|
|
11
|
+
require reaching the exact snapshot event, matching its attempt, and a fresh source observation.
|
|
12
|
+
Reaching that cursor does not establish complete source inventory or complete event history.
|
|
13
13
|
"""
|
|
14
14
|
|
|
15
15
|
from __future__ import annotations
|
|
@@ -19,7 +19,7 @@ import time
|
|
|
19
19
|
from collections import deque
|
|
20
20
|
from collections.abc import Callable, Mapping
|
|
21
21
|
from dataclasses import dataclass, field
|
|
22
|
-
from datetime import datetime
|
|
22
|
+
from datetime import UTC, datetime
|
|
23
23
|
from typing import Any
|
|
24
24
|
|
|
25
25
|
from mostlyright.data_harness.thin.stream import RunEventStream
|
|
@@ -32,6 +32,13 @@ TRAILING_WINDOW_SECONDS = 600.0
|
|
|
32
32
|
#: How often ``watch`` prints a rate line for one source, in seconds of event time.
|
|
33
33
|
RATE_LINE_EVERY_SECONDS = 60.0
|
|
34
34
|
|
|
35
|
+
#: A rate is a live estimate only while its own latest observation is this recent.
|
|
36
|
+
LIVE_FRESHNESS_SECONDS = 30.0
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def utc_now() -> datetime:
|
|
40
|
+
return datetime.now(UTC)
|
|
41
|
+
|
|
35
42
|
|
|
36
43
|
def parse_instant(value: Any) -> datetime | None:
|
|
37
44
|
"""An RFC 3339 instant as Studio stamps it, or ``None`` when it is absent or unreadable."""
|
|
@@ -74,16 +81,16 @@ class SourceRate:
|
|
|
74
81
|
planned: int | None = None
|
|
75
82
|
discovery_complete: bool = False
|
|
76
83
|
printed_at: datetime | None = None
|
|
84
|
+
unavailable_reason: str | None = None
|
|
77
85
|
|
|
78
|
-
def observe(self, at: datetime, done: int) ->
|
|
79
|
-
if self.ticks and done < self.ticks[-1][1]:
|
|
80
|
-
# The count went back, so this is a different acquisition. Start again.
|
|
81
|
-
self.ticks.clear()
|
|
82
|
-
self.first = None
|
|
86
|
+
def observe(self, at: datetime, done: int) -> bool:
|
|
83
87
|
if self.ticks and at <= self.ticks[-1][0]:
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
88
|
+
return False
|
|
89
|
+
if self.ticks and done < self.ticks[-1][1]:
|
|
90
|
+
# There is no batch identity on these counters. A decrease cannot establish one.
|
|
91
|
+
self.unavailable_reason = "counter_regressed_without_scope_change"
|
|
92
|
+
self.planned = None
|
|
93
|
+
self.discovery_complete = False
|
|
87
94
|
self.ticks.append((at, done))
|
|
88
95
|
if self.first is None:
|
|
89
96
|
self.first = (at, done)
|
|
@@ -92,6 +99,7 @@ class SourceRate:
|
|
|
92
99
|
and (at - self.ticks[1][0]).total_seconds() >= TRAILING_WINDOW_SECONDS
|
|
93
100
|
):
|
|
94
101
|
self.ticks.popleft()
|
|
102
|
+
return True
|
|
95
103
|
|
|
96
104
|
@property
|
|
97
105
|
def done(self) -> int | None:
|
|
@@ -100,7 +108,7 @@ class SourceRate:
|
|
|
100
108
|
def per_second(self) -> float | None:
|
|
101
109
|
"""The trailing rate, or ``None`` before two ticks with time between them."""
|
|
102
110
|
|
|
103
|
-
if len(self.ticks) < 2:
|
|
111
|
+
if self.unavailable_reason is not None or len(self.ticks) < 2:
|
|
104
112
|
return None
|
|
105
113
|
(start, start_done), (end, end_done) = self.ticks[0], self.ticks[-1]
|
|
106
114
|
elapsed = (end - start).total_seconds()
|
|
@@ -109,7 +117,7 @@ class SourceRate:
|
|
|
109
117
|
def average_per_second(self) -> float | None:
|
|
110
118
|
"""The rate from the first tick to the last, or ``None`` before two ticks."""
|
|
111
119
|
|
|
112
|
-
if self.first is None or not self.ticks:
|
|
120
|
+
if self.unavailable_reason is not None or self.first is None or not self.ticks:
|
|
113
121
|
return None
|
|
114
122
|
elapsed = (self.ticks[-1][0] - self.first[0]).total_seconds()
|
|
115
123
|
return (self.ticks[-1][1] - self.first[1]) / elapsed if elapsed > 0 else None
|
|
@@ -127,6 +135,7 @@ class SourceRate:
|
|
|
127
135
|
or done is None
|
|
128
136
|
or rate is None
|
|
129
137
|
or rate <= 0
|
|
138
|
+
or done > self.planned
|
|
130
139
|
):
|
|
131
140
|
return None
|
|
132
141
|
return max(0, self.planned - done) / rate
|
|
@@ -171,21 +180,46 @@ class RateTracker:
|
|
|
171
180
|
|
|
172
181
|
def __init__(self) -> None:
|
|
173
182
|
self.sources: dict[str, SourceRate] = {}
|
|
183
|
+
self.attempt_id: str | None = None
|
|
184
|
+
self.retired_attempts: set[str] = set()
|
|
185
|
+
self.last_sequence = 0
|
|
186
|
+
self.live_observation: dict[str, Any] | None = None
|
|
174
187
|
|
|
175
188
|
def observe(self, body: Mapping[str, Any]) -> SourceRate | None:
|
|
176
189
|
"""Fold one run event record, and answer the source it moved, or ``None``."""
|
|
177
190
|
|
|
191
|
+
sequence = _count(body.get("sequence"))
|
|
192
|
+
if sequence is None or sequence <= self.last_sequence:
|
|
193
|
+
return None
|
|
194
|
+
self.last_sequence = sequence
|
|
178
195
|
event_type = body.get("event_type")
|
|
179
|
-
if isinstance(event_type, str)
|
|
196
|
+
if not isinstance(event_type, str) or not event_type.startswith("run_progress_"):
|
|
180
197
|
return None
|
|
198
|
+
attempt = body.get("attempt_id")
|
|
199
|
+
if isinstance(attempt, str) and attempt:
|
|
200
|
+
if attempt in self.retired_attempts:
|
|
201
|
+
return None
|
|
202
|
+
if attempt != self.attempt_id:
|
|
203
|
+
if self.attempt_id is not None:
|
|
204
|
+
self.retired_attempts.add(self.attempt_id)
|
|
205
|
+
self.sources.clear()
|
|
206
|
+
self.attempt_id = attempt
|
|
181
207
|
facts = tick_facts(body)
|
|
182
208
|
at = parse_instant(body.get("occurred_at"))
|
|
183
209
|
done = _count(facts.get("pages_processed"))
|
|
184
210
|
name = facts.get("source_id") or facts.get("source_name")
|
|
185
|
-
if
|
|
211
|
+
if (
|
|
212
|
+
at is None
|
|
213
|
+
or done is None
|
|
214
|
+
or not isinstance(name, str)
|
|
215
|
+
or not name
|
|
216
|
+
or not isinstance(attempt, str)
|
|
217
|
+
or not attempt
|
|
218
|
+
):
|
|
186
219
|
return None
|
|
187
220
|
source = self.sources.setdefault(name, SourceRate(name))
|
|
188
|
-
source.observe(at, done)
|
|
221
|
+
if not source.observe(at, done) or source.unavailable_reason is not None:
|
|
222
|
+
return None
|
|
189
223
|
planned = _count(facts.get("pages_planned"))
|
|
190
224
|
if planned is not None:
|
|
191
225
|
source.planned = planned
|
|
@@ -193,12 +227,17 @@ class RateTracker:
|
|
|
193
227
|
source.discovery_complete = facts["discovery_complete"]
|
|
194
228
|
return source
|
|
195
229
|
|
|
196
|
-
def due_line(
|
|
230
|
+
def due_line(
|
|
231
|
+
self, source: SourceRate, *, wall_clock: Callable[[], datetime] = utc_now
|
|
232
|
+
) -> str | None:
|
|
197
233
|
"""The source's line when one is due, at most once a minute of event time per source."""
|
|
198
234
|
|
|
199
235
|
if not source.ticks:
|
|
200
236
|
return None
|
|
201
237
|
now = source.ticks[-1][0]
|
|
238
|
+
age = (wall_clock() - now).total_seconds()
|
|
239
|
+
if age < 0 or age > LIVE_FRESHNESS_SECONDS:
|
|
240
|
+
return None
|
|
202
241
|
if (
|
|
203
242
|
source.printed_at is not None
|
|
204
243
|
and (now - source.printed_at).total_seconds() < RATE_LINE_EVERY_SECONDS
|
|
@@ -265,7 +304,8 @@ def live_rates(
|
|
|
265
304
|
"""The rates of a live run, from the last ``tail`` records of its event log.
|
|
266
305
|
|
|
267
306
|
Reads the progress snapshot for the newest sequence, then replays the log from ``tail``
|
|
268
|
-
records before it and stops at that sequence.
|
|
307
|
+
records before it and stops at or beyond that sequence. Only observing the exact target
|
|
308
|
+
certifies completion of this bounded replay. Answers ``None`` when the run has reported no
|
|
269
309
|
progress yet. A refusal on the way is raised, and the caller decides what it costs.
|
|
270
310
|
"""
|
|
271
311
|
|
|
@@ -274,14 +314,51 @@ def live_rates(
|
|
|
274
314
|
if type(sequence) is not int or sequence < 1:
|
|
275
315
|
return None
|
|
276
316
|
tracker = RateTracker()
|
|
277
|
-
|
|
317
|
+
target_seen = False
|
|
318
|
+
target_attempt: str | None = None
|
|
319
|
+
observed_at: str | None = None
|
|
320
|
+
from_sequence = max(0, sequence - tail)
|
|
321
|
+
expected_sequence = from_sequence + 1
|
|
322
|
+
sequence_gap = False
|
|
323
|
+
|
|
324
|
+
def observe(body: Mapping[str, Any], _frame_name: str) -> bool:
|
|
325
|
+
nonlocal target_seen, target_attempt, observed_at, expected_sequence, sequence_gap
|
|
326
|
+
observed = _count(body.get("sequence"))
|
|
327
|
+
if observed is None:
|
|
328
|
+
return False
|
|
329
|
+
if observed != expected_sequence:
|
|
330
|
+
sequence_gap = True
|
|
331
|
+
expected_sequence = observed + 1
|
|
332
|
+
instant = parse_instant(body.get("occurred_at"))
|
|
333
|
+
observed_at = instant.isoformat() if instant is not None else None
|
|
334
|
+
if observed <= sequence:
|
|
335
|
+
tracker.observe(body)
|
|
336
|
+
if observed == sequence:
|
|
337
|
+
target_seen = True
|
|
338
|
+
attempt = body.get("attempt_id")
|
|
339
|
+
target_attempt = attempt if isinstance(attempt, str) and attempt else None
|
|
340
|
+
return observed >= sequence
|
|
341
|
+
|
|
342
|
+
followed = RunEventStream(
|
|
278
343
|
client.session, run_id, transport=client.transport, sleep=sleep, path=RUN_EVENTS_PATH
|
|
279
344
|
).follow(
|
|
280
|
-
from_seq=
|
|
281
|
-
observe=
|
|
345
|
+
from_seq=from_sequence,
|
|
346
|
+
observe=observe,
|
|
282
347
|
deadline=clock() + deadline_seconds,
|
|
283
348
|
clock=clock,
|
|
284
349
|
)
|
|
350
|
+
tracker.live_observation = {
|
|
351
|
+
"scope": "bounded_event_tail",
|
|
352
|
+
"from_sequence_exclusive": from_sequence,
|
|
353
|
+
"target_sequence": sequence,
|
|
354
|
+
"observed_sequence": followed.last_sequence,
|
|
355
|
+
"replay_complete": target_seen and not sequence_gap,
|
|
356
|
+
"sequence_gap": sequence_gap,
|
|
357
|
+
"observed_at": observed_at,
|
|
358
|
+
"attempt_id": target_attempt,
|
|
359
|
+
"deadline_expired": followed.expired,
|
|
360
|
+
"end_reason": followed.end_reason,
|
|
361
|
+
}
|
|
285
362
|
return tracker
|
|
286
363
|
|
|
287
364
|
|
|
@@ -314,19 +391,58 @@ def history_rates(
|
|
|
314
391
|
return tracker
|
|
315
392
|
|
|
316
393
|
|
|
317
|
-
def live_rate_members(
|
|
394
|
+
def live_rate_members(
|
|
395
|
+
client: Any, run_id: str, *, wall_clock: Callable[[], datetime] = utc_now, **kwargs: Any
|
|
396
|
+
) -> dict[str, Any]:
|
|
318
397
|
"""The ``status`` receipt members for a live run's rates, or why there are none."""
|
|
319
398
|
|
|
320
399
|
try:
|
|
321
400
|
tracker = live_rates(client, run_id, **kwargs)
|
|
322
401
|
except ThinLaneError as refusal:
|
|
323
402
|
return {"source_rates_unavailable": f"{refusal.code}: {refusal.detail}"}
|
|
324
|
-
if tracker is None
|
|
403
|
+
if tracker is None:
|
|
325
404
|
return {"source_rates_unavailable": "no collection source has reported two ticks yet"}
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
}
|
|
405
|
+
observation = dict(tracker.live_observation or {})
|
|
406
|
+
now = wall_clock()
|
|
407
|
+
observation["checked_at"] = now.isoformat()
|
|
408
|
+
result: dict[str, Any] = {"source_rate_observation": observation}
|
|
409
|
+
if not observation.get("replay_complete"):
|
|
410
|
+
result["source_rates_unavailable"] = (
|
|
411
|
+
"incomplete replay: event gap or snapshot event missing"
|
|
412
|
+
)
|
|
413
|
+
return result
|
|
414
|
+
if not observation.get("attempt_id") or observation["attempt_id"] != tracker.attempt_id:
|
|
415
|
+
result["source_rates_unavailable"] = "snapshot attempt could not be established"
|
|
416
|
+
return result
|
|
417
|
+
receipts, lines, unavailable = [], {}, {}
|
|
418
|
+
for source in tracker.sources.values():
|
|
419
|
+
at = source.ticks[-1][0] if source.ticks else None
|
|
420
|
+
age = (now - at).total_seconds() if at is not None else None
|
|
421
|
+
reason = source.unavailable_reason
|
|
422
|
+
if reason is None and (age is None or age < 0):
|
|
423
|
+
reason = "observation_time_unavailable_or_in_future"
|
|
424
|
+
if reason is None and age is not None and age > LIVE_FRESHNESS_SECONDS:
|
|
425
|
+
reason = "stale_observation"
|
|
426
|
+
if reason is None and source.per_second() is None:
|
|
427
|
+
reason = "insufficient_observations"
|
|
428
|
+
if reason is not None:
|
|
429
|
+
unavailable[source.name] = {
|
|
430
|
+
"reason": reason,
|
|
431
|
+
"observed_at": at.isoformat() if at else None,
|
|
432
|
+
"age_seconds": age,
|
|
433
|
+
}
|
|
434
|
+
continue
|
|
435
|
+
receipt = source.to_receipt()
|
|
436
|
+
receipt.update(observed_at=at.isoformat(), age_seconds=age, attempt_id=tracker.attempt_id)
|
|
437
|
+
receipts.append(receipt)
|
|
438
|
+
lines[f"source {len(lines) + 1}"] = source.line()
|
|
439
|
+
if unavailable:
|
|
440
|
+
result["source_rates_unavailable_by_source"] = unavailable
|
|
441
|
+
if receipts:
|
|
442
|
+
result.update(source_rates=receipts, rates=lines)
|
|
443
|
+
else:
|
|
444
|
+
result["source_rates_unavailable"] = "no fresh, same-attempt source rate is available"
|
|
445
|
+
return result
|
|
330
446
|
|
|
331
447
|
|
|
332
448
|
__all__ = [
|
{mostlyright_data-0.30.1 → mostlyright_data-0.30.2}/src/mostlyright/data_harness/thin/v4_stream.py
RENAMED
|
@@ -40,10 +40,11 @@ import argparse
|
|
|
40
40
|
import json
|
|
41
41
|
import time
|
|
42
42
|
from collections.abc import Callable, Mapping
|
|
43
|
+
from datetime import datetime
|
|
43
44
|
from typing import Any
|
|
44
45
|
|
|
45
46
|
from mostlyright.data_harness.thin import THIN_SCHEMA_PREFIX
|
|
46
|
-
from mostlyright.data_harness.thin.progress_rate import RateTracker
|
|
47
|
+
from mostlyright.data_harness.thin.progress_rate import RateTracker, utc_now
|
|
47
48
|
from mostlyright.data_harness.thin.session import (
|
|
48
49
|
StudioSession,
|
|
49
50
|
StudioSessionProvider,
|
|
@@ -216,6 +217,7 @@ def watch(
|
|
|
216
217
|
*,
|
|
217
218
|
client: StudioV4RunClient | None = None,
|
|
218
219
|
clock: Callable[[], float] = time.monotonic,
|
|
220
|
+
wall_clock: Callable[[], datetime] = utc_now,
|
|
219
221
|
sessions: StudioSessionProvider | None = None,
|
|
220
222
|
) -> dict[str, Any]:
|
|
221
223
|
"""``mr-data watch RUN``: the live timeline, and the record the run stopped on.
|
|
@@ -259,7 +261,7 @@ def watch(
|
|
|
259
261
|
print(render_v4_frame(body, frame_name), flush=True)
|
|
260
262
|
moved = rates.observe(body)
|
|
261
263
|
if moved is not None and announce:
|
|
262
|
-
line = rates.due_line(moved)
|
|
264
|
+
line = rates.due_line(moved, wall_clock=wall_clock)
|
|
263
265
|
if line is not None:
|
|
264
266
|
print(f" rate {line}", flush=True)
|
|
265
267
|
if body.get("event_type") in V4_TERMINAL_EVENT_TYPES:
|
|
@@ -334,6 +336,12 @@ def terminal_payload(
|
|
|
334
336
|
if measured:
|
|
335
337
|
# The last rate each collection source reached, from its own progress ticks.
|
|
336
338
|
payload["source_rates"] = measured
|
|
339
|
+
payload["source_rates_basis"] = "historical_last_observation_per_source"
|
|
340
|
+
payload["source_rate_observed_at"] = {
|
|
341
|
+
name: source.ticks[-1][0].isoformat()
|
|
342
|
+
for name, source in rates.sources.items()
|
|
343
|
+
if source.per_second() is not None
|
|
344
|
+
}
|
|
337
345
|
if event_type == "run_failed":
|
|
338
346
|
triple = failure_from(event_facts(terminal), subject="a run_failed event")
|
|
339
347
|
payload["failure"] = triple
|
|
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
|
|
File without changes
|
{mostlyright_data-0.30.1 → mostlyright_data-0.30.2}/skills/mr-data-build/references/boundaries.md
RENAMED
|
File without changes
|
|
File without changes
|
{mostlyright_data-0.30.1 → mostlyright_data-0.30.2}/skills/mr-data-build/references/commands.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{mostlyright_data-0.30.1 → mostlyright_data-0.30.2}/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.1 → mostlyright_data-0.30.2}/skills/mr-data-build/references/one-install.md
RENAMED
|
File without changes
|
{mostlyright_data-0.30.1 → mostlyright_data-0.30.2}/skills/mr-data-build/references/patterns.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{mostlyright_data-0.30.1 → mostlyright_data-0.30.2}/skills/mr-data-build/references/promote.md
RENAMED
|
File without changes
|
{mostlyright_data-0.30.1 → mostlyright_data-0.30.2}/skills/mr-data-build/references/readers.md
RENAMED
|
File without changes
|
{mostlyright_data-0.30.1 → mostlyright_data-0.30.2}/skills/mr-data-build/references/receipts.md
RENAMED
|
File without changes
|
{mostlyright_data-0.30.1 → mostlyright_data-0.30.2}/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.1 → mostlyright_data-0.30.2}/skills/mr-data-build/references/sources.md
RENAMED
|
File without changes
|
|
File without changes
|
{mostlyright_data-0.30.1 → mostlyright_data-0.30.2}/skills/mr-data-build/references/transforms.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{mostlyright_data-0.30.1 → mostlyright_data-0.30.2}/src/mostlyright/data_harness/__init__.py
RENAMED
|
File without changes
|
{mostlyright_data-0.30.1 → mostlyright_data-0.30.2}/src/mostlyright/data_harness/agent_protocol.py
RENAMED
|
File without changes
|
{mostlyright_data-0.30.1 → mostlyright_data-0.30.2}/src/mostlyright/data_harness/canonical.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{mostlyright_data-0.30.1 → mostlyright_data-0.30.2}/src/mostlyright/data_harness/key_seam.py
RENAMED
|
File without changes
|
{mostlyright_data-0.30.1 → mostlyright_data-0.30.2}/src/mostlyright/data_harness/page_coverage.py
RENAMED
|
File without changes
|
|
File without changes
|
{mostlyright_data-0.30.1 → mostlyright_data-0.30.2}/src/mostlyright/data_harness/session_probes.py
RENAMED
|
File without changes
|
{mostlyright_data-0.30.1 → mostlyright_data-0.30.2}/src/mostlyright/data_harness/skill_assets.py
RENAMED
|
File without changes
|
{mostlyright_data-0.30.1 → mostlyright_data-0.30.2}/src/mostlyright/data_harness/table_manifest.py
RENAMED
|
File without changes
|
{mostlyright_data-0.30.1 → mostlyright_data-0.30.2}/src/mostlyright/data_harness/thin/__init__.py
RENAMED
|
File without changes
|
{mostlyright_data-0.30.1 → mostlyright_data-0.30.2}/src/mostlyright/data_harness/thin/acquire.py
RENAMED
|
File without changes
|
|
File without changes
|
{mostlyright_data-0.30.1 → mostlyright_data-0.30.2}/src/mostlyright/data_harness/thin/activity.py
RENAMED
|
File without changes
|
{mostlyright_data-0.30.1 → mostlyright_data-0.30.2}/src/mostlyright/data_harness/thin/approvals.py
RENAMED
|
File without changes
|
{mostlyright_data-0.30.1 → mostlyright_data-0.30.2}/src/mostlyright/data_harness/thin/backoff.py
RENAMED
|
File without changes
|
{mostlyright_data-0.30.1 → mostlyright_data-0.30.2}/src/mostlyright/data_harness/thin/categories.py
RENAMED
|
File without changes
|
{mostlyright_data-0.30.1 → mostlyright_data-0.30.2}/src/mostlyright/data_harness/thin/commands.py
RENAMED
|
File without changes
|
|
File without changes
|
{mostlyright_data-0.30.1 → mostlyright_data-0.30.2}/src/mostlyright/data_harness/thin/download.py
RENAMED
|
File without changes
|
|
File without changes
|
{mostlyright_data-0.30.1 → mostlyright_data-0.30.2}/src/mostlyright/data_harness/thin/narrative.py
RENAMED
|
File without changes
|
{mostlyright_data-0.30.1 → mostlyright_data-0.30.2}/src/mostlyright/data_harness/thin/parity.py
RENAMED
|
File without changes
|
{mostlyright_data-0.30.1 → mostlyright_data-0.30.2}/src/mostlyright/data_harness/thin/probe.py
RENAMED
|
File without changes
|
|
File without changes
|
{mostlyright_data-0.30.1 → mostlyright_data-0.30.2}/src/mostlyright/data_harness/thin/propose.py
RENAMED
|
File without changes
|
{mostlyright_data-0.30.1 → mostlyright_data-0.30.2}/src/mostlyright/data_harness/thin/recipe.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{mostlyright_data-0.30.1 → mostlyright_data-0.30.2}/src/mostlyright/data_harness/thin/recipe_lint.py
RENAMED
|
File without changes
|
{mostlyright_data-0.30.1 → mostlyright_data-0.30.2}/src/mostlyright/data_harness/thin/recipe_test.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{mostlyright_data-0.30.1 → mostlyright_data-0.30.2}/src/mostlyright/data_harness/thin/research.py
RENAMED
|
File without changes
|
{mostlyright_data-0.30.1 → mostlyright_data-0.30.2}/src/mostlyright/data_harness/thin/router.py
RENAMED
|
File without changes
|
|
File without changes
|
{mostlyright_data-0.30.1 → mostlyright_data-0.30.2}/src/mostlyright/data_harness/thin/run_prefix.py
RENAMED
|
File without changes
|
{mostlyright_data-0.30.1 → mostlyright_data-0.30.2}/src/mostlyright/data_harness/thin/runs.py
RENAMED
|
File without changes
|
{mostlyright_data-0.30.1 → mostlyright_data-0.30.2}/src/mostlyright/data_harness/thin/session.py
RENAMED
|
File without changes
|
{mostlyright_data-0.30.1 → mostlyright_data-0.30.2}/src/mostlyright/data_harness/thin/stream.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{mostlyright_data-0.30.1 → mostlyright_data-0.30.2}/src/mostlyright/data_harness/thin/support.py
RENAMED
|
File without changes
|
|
File without changes
|
{mostlyright_data-0.30.1 → mostlyright_data-0.30.2}/src/mostlyright/data_harness/thin/transport.py
RENAMED
|
File without changes
|
{mostlyright_data-0.30.1 → mostlyright_data-0.30.2}/src/mostlyright/data_harness/thin/user_agent.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{mostlyright_data-0.30.1 → mostlyright_data-0.30.2}/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.1 → mostlyright_data-0.30.2}/src/mostlyright/data_harness/thin/v4_datasets.py
RENAMED
|
File without changes
|
{mostlyright_data-0.30.1 → mostlyright_data-0.30.2}/src/mostlyright/data_harness/thin/v4_handoff.py
RENAMED
|
File without changes
|
|
File without changes
|
{mostlyright_data-0.30.1 → mostlyright_data-0.30.2}/src/mostlyright/data_harness/thin/v4_public.py
RENAMED
|
File without changes
|
{mostlyright_data-0.30.1 → mostlyright_data-0.30.2}/src/mostlyright/data_harness/thin/v4_query.py
RENAMED
|
File without changes
|
{mostlyright_data-0.30.1 → mostlyright_data-0.30.2}/src/mostlyright/data_harness/thin/v4_reader.py
RENAMED
|
File without changes
|
{mostlyright_data-0.30.1 → mostlyright_data-0.30.2}/src/mostlyright/data_harness/thin/v4_runs.py
RENAMED
|
File without changes
|
{mostlyright_data-0.30.1 → mostlyright_data-0.30.2}/src/mostlyright/data_harness/thin/v4_search.py
RENAMED
|
File without changes
|
|
File without changes
|
{mostlyright_data-0.30.1 → mostlyright_data-0.30.2}/src/mostlyright/data_harness/thin/v4_secrets.py
RENAMED
|
File without changes
|
{mostlyright_data-0.30.1 → mostlyright_data-0.30.2}/src/mostlyright/data_harness/thin/v4_tables.py
RENAMED
|
File without changes
|
{mostlyright_data-0.30.1 → mostlyright_data-0.30.2}/src/mostlyright/data_harness/thin/vocabulary.py
RENAMED
|
File without changes
|
{mostlyright_data-0.30.1 → mostlyright_data-0.30.2}/src/mostlyright/data_harness/ux/__init__.py
RENAMED
|
File without changes
|
{mostlyright_data-0.30.1 → mostlyright_data-0.30.2}/src/mostlyright/data_harness/ux/attendance.py
RENAMED
|
File without changes
|
{mostlyright_data-0.30.1 → mostlyright_data-0.30.2}/src/mostlyright/data_harness/ux/clarification.py
RENAMED
|
File without changes
|
{mostlyright_data-0.30.1 → mostlyright_data-0.30.2}/src/mostlyright/data_harness/ux/cloud_auth.py
RENAMED
|
File without changes
|
|
File without changes
|
{mostlyright_data-0.30.1 → mostlyright_data-0.30.2}/src/mostlyright/data_harness/ux/commands/auth.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{mostlyright_data-0.30.1 → mostlyright_data-0.30.2}/src/mostlyright/data_harness/ux/credentials.py
RENAMED
|
File without changes
|
{mostlyright_data-0.30.1 → mostlyright_data-0.30.2}/src/mostlyright/data_harness/ux/login.py
RENAMED
|
File without changes
|
{mostlyright_data-0.30.1 → mostlyright_data-0.30.2}/src/mostlyright/data_harness/ux/path_kind.py
RENAMED
|
File without changes
|
{mostlyright_data-0.30.1 → mostlyright_data-0.30.2}/src/mostlyright/data_harness/ux/plain_file.py
RENAMED
|
File without changes
|
{mostlyright_data-0.30.1 → mostlyright_data-0.30.2}/src/mostlyright/data_harness/ux/remediation.py
RENAMED
|
File without changes
|
{mostlyright_data-0.30.1 → mostlyright_data-0.30.2}/src/mostlyright/data_harness/ux/render.py
RENAMED
|
File without changes
|