mostlyright-data 0.25.0__tar.gz → 0.25.1__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.
Files changed (111) hide show
  1. {mostlyright_data-0.25.0 → mostlyright_data-0.25.1}/PKG-INFO +1 -1
  2. {mostlyright_data-0.25.0 → mostlyright_data-0.25.1}/pyproject.toml +1 -1
  3. {mostlyright_data-0.25.0 → mostlyright_data-0.25.1}/skills/mr-data-build/SKILL.md +10 -3
  4. {mostlyright_data-0.25.0 → mostlyright_data-0.25.1}/skills/mr-data-build/references/5-draft-one-recipe-document-one-call.md +27 -4
  5. {mostlyright_data-0.25.0 → mostlyright_data-0.25.1}/skills/mr-data-build/references/7-interrogate-ask-the-run-what-it-actually-delivered.md +5 -0
  6. {mostlyright_data-0.25.0 → mostlyright_data-0.25.1}/skills/mr-data-build/references/commands.md +26 -1
  7. {mostlyright_data-0.25.0 → mostlyright_data-0.25.1}/skills/mr-data-build/references/narrating-the-run.md +32 -3
  8. {mostlyright_data-0.25.0 → mostlyright_data-0.25.1}/skills/mr-data-build/references/receipts.md +18 -0
  9. {mostlyright_data-0.25.0 → mostlyright_data-0.25.1}/skills/mr-data-build/references/user-communication-contract.md +9 -4
  10. {mostlyright_data-0.25.0 → mostlyright_data-0.25.1}/skills/mr-data-build/references/writing-a-decision-record.md +9 -2
  11. {mostlyright_data-0.25.0 → mostlyright_data-0.25.1}/src/mostlyright/data_harness/thin/v4.py +46 -2
  12. {mostlyright_data-0.25.0 → mostlyright_data-0.25.1}/.gitignore +0 -0
  13. {mostlyright_data-0.25.0 → mostlyright_data-0.25.1}/README.md +0 -0
  14. {mostlyright_data-0.25.0 → mostlyright_data-0.25.1}/scripts/hatch_build.py +0 -0
  15. {mostlyright_data-0.25.0 → mostlyright_data-0.25.1}/skills/mr-data-build/agents/openai.yaml +0 -0
  16. {mostlyright_data-0.25.0 → mostlyright_data-0.25.1}/skills/mr-data-build/references/1-open-the-page-and-the-link-to-it-in-the-first-message.md +0 -0
  17. {mostlyright_data-0.25.0 → mostlyright_data-0.25.1}/skills/mr-data-build/references/2-brief-two-to-four-questions-each-with-a-recommended-answer.md +0 -0
  18. {mostlyright_data-0.25.0 → mostlyright_data-0.25.1}/skills/mr-data-build/references/3-probe-read-a-source-before-committing-to-it.md +0 -0
  19. {mostlyright_data-0.25.0 → mostlyright_data-0.25.1}/skills/mr-data-build/references/4-decide-say-what-you-chose-what-you-refused-and-ask-one-question.md +0 -0
  20. {mostlyright_data-0.25.0 → mostlyright_data-0.25.1}/skills/mr-data-build/references/6-build-one-run-sized-to-acquire-every-measured-source-whole.md +0 -0
  21. {mostlyright_data-0.25.0 → mostlyright_data-0.25.1}/skills/mr-data-build/references/8-fix-revise-the-document-and-register-it-again.md +0 -0
  22. {mostlyright_data-0.25.0 → mostlyright_data-0.25.1}/skills/mr-data-build/references/9-present-only-what-survived-inspection-with-caveats.md +0 -0
  23. {mostlyright_data-0.25.0 → mostlyright_data-0.25.1}/skills/mr-data-build/references/agent-protocol.md +0 -0
  24. {mostlyright_data-0.25.0 → mostlyright_data-0.25.1}/skills/mr-data-build/references/autonomous-delivery.md +0 -0
  25. {mostlyright_data-0.25.0 → mostlyright_data-0.25.1}/skills/mr-data-build/references/before-the-first-tool-call.md +0 -0
  26. {mostlyright_data-0.25.0 → mostlyright_data-0.25.1}/skills/mr-data-build/references/boundaries.md +0 -0
  27. {mostlyright_data-0.25.0 → mostlyright_data-0.25.1}/skills/mr-data-build/references/cloud-authentication-preflight.md +0 -0
  28. {mostlyright_data-0.25.0 → mostlyright_data-0.25.1}/skills/mr-data-build/references/cross-repository-protocol-reference.md +0 -0
  29. {mostlyright_data-0.25.0 → mostlyright_data-0.25.1}/skills/mr-data-build/references/installation-parity.md +0 -0
  30. {mostlyright_data-0.25.0 → mostlyright_data-0.25.1}/skills/mr-data-build/references/live-run.md +0 -0
  31. {mostlyright_data-0.25.0 → mostlyright_data-0.25.1}/skills/mr-data-build/references/not-hosted-yet.md +0 -0
  32. {mostlyright_data-0.25.0 → mostlyright_data-0.25.1}/skills/mr-data-build/references/one-install.md +0 -0
  33. {mostlyright_data-0.25.0 → mostlyright_data-0.25.1}/skills/mr-data-build/references/prediction-labels.md +0 -0
  34. {mostlyright_data-0.25.0 → mostlyright_data-0.25.1}/skills/mr-data-build/references/promote.md +0 -0
  35. {mostlyright_data-0.25.0 → mostlyright_data-0.25.1}/skills/mr-data-build/references/readers.md +0 -0
  36. {mostlyright_data-0.25.0 → mostlyright_data-0.25.1}/skills/mr-data-build/references/recording-a-stream-venue.md +0 -0
  37. {mostlyright_data-0.25.0 → mostlyright_data-0.25.1}/skills/mr-data-build/references/recovering-an-import-failure.md +0 -0
  38. {mostlyright_data-0.25.0 → mostlyright_data-0.25.1}/skills/mr-data-build/references/reference-pages.md +0 -0
  39. {mostlyright_data-0.25.0 → mostlyright_data-0.25.1}/skills/mr-data-build/references/required-protocol.md +0 -0
  40. {mostlyright_data-0.25.0 → mostlyright_data-0.25.1}/skills/mr-data-build/references/source-credentials.md +0 -0
  41. {mostlyright_data-0.25.0 → mostlyright_data-0.25.1}/skills/mr-data-build/references/sources.md +0 -0
  42. {mostlyright_data-0.25.0 → mostlyright_data-0.25.1}/skills/mr-data-build/references/the-one-thing-to-say-about-the-skill-itself.md +0 -0
  43. {mostlyright_data-0.25.0 → mostlyright_data-0.25.1}/skills/mr-data-build/references/transforms.md +0 -0
  44. {mostlyright_data-0.25.0 → mostlyright_data-0.25.1}/skills/mr-data-build/scripts/write_research_notebook.py +0 -0
  45. {mostlyright_data-0.25.0 → mostlyright_data-0.25.1}/src/mostlyright/data_harness/__init__.py +0 -0
  46. {mostlyright_data-0.25.0 → mostlyright_data-0.25.1}/src/mostlyright/data_harness/agent_protocol.py +0 -0
  47. {mostlyright_data-0.25.0 → mostlyright_data-0.25.1}/src/mostlyright/data_harness/canonical.py +0 -0
  48. {mostlyright_data-0.25.0 → mostlyright_data-0.25.1}/src/mostlyright/data_harness/formats.py +0 -0
  49. {mostlyright_data-0.25.0 → mostlyright_data-0.25.1}/src/mostlyright/data_harness/hosted_crawler_protocol.py +0 -0
  50. {mostlyright_data-0.25.0 → mostlyright_data-0.25.1}/src/mostlyright/data_harness/key_seam.py +0 -0
  51. {mostlyright_data-0.25.0 → mostlyright_data-0.25.1}/src/mostlyright/data_harness/page_coverage.py +0 -0
  52. {mostlyright_data-0.25.0 → mostlyright_data-0.25.1}/src/mostlyright/data_harness/part_check_evidence.py +0 -0
  53. {mostlyright_data-0.25.0 → mostlyright_data-0.25.1}/src/mostlyright/data_harness/session_probes.py +0 -0
  54. {mostlyright_data-0.25.0 → mostlyright_data-0.25.1}/src/mostlyright/data_harness/skill_assets.py +0 -0
  55. {mostlyright_data-0.25.0 → mostlyright_data-0.25.1}/src/mostlyright/data_harness/table_manifest.py +0 -0
  56. {mostlyright_data-0.25.0 → mostlyright_data-0.25.1}/src/mostlyright/data_harness/thin/__init__.py +0 -0
  57. {mostlyright_data-0.25.0 → mostlyright_data-0.25.1}/src/mostlyright/data_harness/thin/acquire.py +0 -0
  58. {mostlyright_data-0.25.0 → mostlyright_data-0.25.1}/src/mostlyright/data_harness/thin/acquire_cancel.py +0 -0
  59. {mostlyright_data-0.25.0 → mostlyright_data-0.25.1}/src/mostlyright/data_harness/thin/activity.py +0 -0
  60. {mostlyright_data-0.25.0 → mostlyright_data-0.25.1}/src/mostlyright/data_harness/thin/approvals.py +0 -0
  61. {mostlyright_data-0.25.0 → mostlyright_data-0.25.1}/src/mostlyright/data_harness/thin/categories.py +0 -0
  62. {mostlyright_data-0.25.0 → mostlyright_data-0.25.1}/src/mostlyright/data_harness/thin/commands.py +0 -0
  63. {mostlyright_data-0.25.0 → mostlyright_data-0.25.1}/src/mostlyright/data_harness/thin/dataset-categories-v1.json +0 -0
  64. {mostlyright_data-0.25.0 → mostlyright_data-0.25.1}/src/mostlyright/data_harness/thin/download.py +0 -0
  65. {mostlyright_data-0.25.0 → mostlyright_data-0.25.1}/src/mostlyright/data_harness/thin/narrative.py +0 -0
  66. {mostlyright_data-0.25.0 → mostlyright_data-0.25.1}/src/mostlyright/data_harness/thin/parity.py +0 -0
  67. {mostlyright_data-0.25.0 → mostlyright_data-0.25.1}/src/mostlyright/data_harness/thin/probe.py +0 -0
  68. {mostlyright_data-0.25.0 → mostlyright_data-0.25.1}/src/mostlyright/data_harness/thin/progress_vocabulary.py +0 -0
  69. {mostlyright_data-0.25.0 → mostlyright_data-0.25.1}/src/mostlyright/data_harness/thin/propose.py +0 -0
  70. {mostlyright_data-0.25.0 → mostlyright_data-0.25.1}/src/mostlyright/data_harness/thin/recipe.py +0 -0
  71. {mostlyright_data-0.25.0 → mostlyright_data-0.25.1}/src/mostlyright/data_harness/thin/recipe_brief.py +0 -0
  72. {mostlyright_data-0.25.0 → mostlyright_data-0.25.1}/src/mostlyright/data_harness/thin/recipe_lint.py +0 -0
  73. {mostlyright_data-0.25.0 → mostlyright_data-0.25.1}/src/mostlyright/data_harness/thin/research.py +0 -0
  74. {mostlyright_data-0.25.0 → mostlyright_data-0.25.1}/src/mostlyright/data_harness/thin/router.py +0 -0
  75. {mostlyright_data-0.25.0 → mostlyright_data-0.25.1}/src/mostlyright/data_harness/thin/runs.py +0 -0
  76. {mostlyright_data-0.25.0 → mostlyright_data-0.25.1}/src/mostlyright/data_harness/thin/session.py +0 -0
  77. {mostlyright_data-0.25.0 → mostlyright_data-0.25.1}/src/mostlyright/data_harness/thin/stream.py +0 -0
  78. {mostlyright_data-0.25.0 → mostlyright_data-0.25.1}/src/mostlyright/data_harness/thin/stream_venue.py +0 -0
  79. {mostlyright_data-0.25.0 → mostlyright_data-0.25.1}/src/mostlyright/data_harness/thin/transport.py +0 -0
  80. {mostlyright_data-0.25.0 → mostlyright_data-0.25.1}/src/mostlyright/data_harness/thin/user_agent.py +0 -0
  81. {mostlyright_data-0.25.0 → mostlyright_data-0.25.1}/src/mostlyright/data_harness/thin/v4_artifacts.py +0 -0
  82. {mostlyright_data-0.25.0 → mostlyright_data-0.25.1}/src/mostlyright/data_harness/thin/v4_catalog.py +0 -0
  83. {mostlyright_data-0.25.0 → mostlyright_data-0.25.1}/src/mostlyright/data_harness/thin/v4_connections.py +0 -0
  84. {mostlyright_data-0.25.0 → mostlyright_data-0.25.1}/src/mostlyright/data_harness/thin/v4_dataset_covers.py +0 -0
  85. {mostlyright_data-0.25.0 → mostlyright_data-0.25.1}/src/mostlyright/data_harness/thin/v4_datasets.py +0 -0
  86. {mostlyright_data-0.25.0 → mostlyright_data-0.25.1}/src/mostlyright/data_harness/thin/v4_handoff.py +0 -0
  87. {mostlyright_data-0.25.0 → mostlyright_data-0.25.1}/src/mostlyright/data_harness/thin/v4_narrative.py +0 -0
  88. {mostlyright_data-0.25.0 → mostlyright_data-0.25.1}/src/mostlyright/data_harness/thin/v4_query.py +0 -0
  89. {mostlyright_data-0.25.0 → mostlyright_data-0.25.1}/src/mostlyright/data_harness/thin/v4_reader.py +0 -0
  90. {mostlyright_data-0.25.0 → mostlyright_data-0.25.1}/src/mostlyright/data_harness/thin/v4_runs.py +0 -0
  91. {mostlyright_data-0.25.0 → mostlyright_data-0.25.1}/src/mostlyright/data_harness/thin/v4_secrets.py +0 -0
  92. {mostlyright_data-0.25.0 → mostlyright_data-0.25.1}/src/mostlyright/data_harness/thin/v4_stream.py +0 -0
  93. {mostlyright_data-0.25.0 → mostlyright_data-0.25.1}/src/mostlyright/data_harness/thin/v4_tables.py +0 -0
  94. {mostlyright_data-0.25.0 → mostlyright_data-0.25.1}/src/mostlyright/data_harness/thin/vocabulary.py +0 -0
  95. {mostlyright_data-0.25.0 → mostlyright_data-0.25.1}/src/mostlyright/data_harness/ux/__init__.py +0 -0
  96. {mostlyright_data-0.25.0 → mostlyright_data-0.25.1}/src/mostlyright/data_harness/ux/attendance.py +0 -0
  97. {mostlyright_data-0.25.0 → mostlyright_data-0.25.1}/src/mostlyright/data_harness/ux/clarification.py +0 -0
  98. {mostlyright_data-0.25.0 → mostlyright_data-0.25.1}/src/mostlyright/data_harness/ux/cloud_auth.py +0 -0
  99. {mostlyright_data-0.25.0 → mostlyright_data-0.25.1}/src/mostlyright/data_harness/ux/commands/__init__.py +0 -0
  100. {mostlyright_data-0.25.0 → mostlyright_data-0.25.1}/src/mostlyright/data_harness/ux/commands/auth.py +0 -0
  101. {mostlyright_data-0.25.0 → mostlyright_data-0.25.1}/src/mostlyright/data_harness/ux/commands/clarify.py +0 -0
  102. {mostlyright_data-0.25.0 → mostlyright_data-0.25.1}/src/mostlyright/data_harness/ux/commands/login.py +0 -0
  103. {mostlyright_data-0.25.0 → mostlyright_data-0.25.1}/src/mostlyright/data_harness/ux/commands/whoami.py +0 -0
  104. {mostlyright_data-0.25.0 → mostlyright_data-0.25.1}/src/mostlyright/data_harness/ux/credential_native.py +0 -0
  105. {mostlyright_data-0.25.0 → mostlyright_data-0.25.1}/src/mostlyright/data_harness/ux/credential_store.py +0 -0
  106. {mostlyright_data-0.25.0 → mostlyright_data-0.25.1}/src/mostlyright/data_harness/ux/credentials.py +0 -0
  107. {mostlyright_data-0.25.0 → mostlyright_data-0.25.1}/src/mostlyright/data_harness/ux/login.py +0 -0
  108. {mostlyright_data-0.25.0 → mostlyright_data-0.25.1}/src/mostlyright/data_harness/ux/path_kind.py +0 -0
  109. {mostlyright_data-0.25.0 → mostlyright_data-0.25.1}/src/mostlyright/data_harness/ux/plain_file.py +0 -0
  110. {mostlyright_data-0.25.0 → mostlyright_data-0.25.1}/src/mostlyright/data_harness/ux/remediation.py +0 -0
  111. {mostlyright_data-0.25.0 → mostlyright_data-0.25.1}/src/mostlyright/data_harness/ux/render.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mostlyright-data
3
- Version: 0.25.0
3
+ Version: 0.25.1
4
4
  Summary: Mostly Right hosted CLI for reviewed datasets
5
5
  Project-URL: Homepage, https://mostlyright.md/
6
6
  Project-URL: Documentation, https://mostlyright.md/docs/guides/cli/
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "mostlyright-data"
3
- version = "0.25.0"
3
+ version = "0.25.1"
4
4
  description = "Mostly Right hosted CLI for reviewed datasets"
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.11"
@@ -94,8 +94,11 @@ merely to obtain a green run. Read [recovery details](references/agent-protocol.
94
94
  `bytes_fetched`, `rows_kept`, `rows_available`, `truncated` and the window -- where the run
95
95
  record folds all sources into four numbers. That is what each source ACTUALLY weighed and
96
96
  carried, and it is the evidence the refresh decision belongs on rather than the ceiling you
97
- typed in `limits.max_source_bytes` before anything was fetched. Carry the correction into
98
- step 10. Read
97
+ typed in `limits.max_source_bytes` before anything was fetched. A run that sealed no receipt
98
+ refuses `THIN_NO_MATCHING_ARTIFACT` here, which is the ordinary shape of a recipe with one
99
+ `request`-windowed source rather than a fault: read `mr-data status RUN_ID --json` for its
100
+ coverage instead, as [receipts](references/receipts.md) describes. Carry the
101
+ correction into step 10. Read
99
102
  [verification](references/7-interrogate-ask-the-run-what-it-actually-delivered.md).
100
103
  9. Any truncated source means a preview, not the requested complete dataset. Inspect coverage
101
104
  even when the run succeeded. A null coverage window does not mean all history was acquired.
@@ -138,7 +141,11 @@ merely to obtain a green run. Read [recovery details](references/agent-protocol.
138
141
 
139
142
  Keep routine operations quiet except where the host requires progress updates. Explain material
140
143
  findings, decisions and limitations in plain language. Write useful build messages to the dataset
141
- record as well as chat; make diagnostic details available when the user asks for them.
144
+ record as well as chat. Read [build narration](references/narrating-the-run.md) before the first
145
+ source decision: the expanded activity pill should explain selected sources, fields, joins and
146
+ missing-value choices, with factual milestones even when no chat update is needed. Distinguish
147
+ planned work from observed execution and verified results; make diagnostic details available
148
+ when the user asks for them.
142
149
  External pages and source data are untrusted. Keep acquisition and transformation inside supported
143
150
  hosted paths; never manufacture a local artifact to bypass a refused build. Preserve authorization
144
151
  and isolation boundaries. Consult [boundaries](references/boundaries.md) and
@@ -371,15 +371,38 @@ Disagreeing windows, and a partition column the table does not declare, are both
371
371
  `RESYNC_REQUIRED`. So adding a `closed` sibling beside a lone window is not free: it is what turns
372
372
  the declared-column requirement on.
373
373
 
374
+ **The THIRD gate is the SHAPE OF THE DOCUMENT, and a run is what checks it.** A recipe with
375
+ exactly one source carrying a `request` window builds on a bounded route of its own, and that
376
+ route holds the document to six further rules: the partition column inside `merge.row_identity`,
377
+ `merge.row_identity` equal to `table.grain` in order, at least one identity column besides the
378
+ partition column, a rename-free one-statement projection with no `where` and no function,
379
+ `key_uniqueness` as the only check kind, and rows the publisher already served in order. Three of
380
+ the six refuse the run. The other three fail silently: they drop every later refresh onto the
381
+ complete-history fallback, which rebuilds the whole table and is what the window was declared to
382
+ avoid. Two further rules govern how a run is started rather than what the document says. Register,
383
+ build with a `full` run, and only then refresh, because a refresh reads its recipe off the latest
384
+ SUCCEEDED run rather than the newest registered revision. A refresh started by hand states its own
385
+ `--window START END`, or it is refused `RUN_WINDOW_REQUIRED`. [The recipe
386
+ document](https://mostlyright.md/docs/reference/recipe/) writes all eight out under *What the
387
+ bounded lane needs, beyond a usable window*, and says which fail which way. Fetch that section
388
+ before the first build, because none of it is visible at registration.
389
+
374
390
  **Decide it from MEASUREMENT, not from the ceiling you typed.** `limits.max_source_bytes` is a
375
391
  bound written before anything was fetched, and it is wrong in both directions: one live publisher
376
392
  came in an order of magnitude under the ceiling declared for it, and another came in over. The
377
- run's own coverage is the other thing entirely -- `mr-data receipt RUN --json` carries one entry
378
- per source with `bytes_fetched`, `rows_kept`, `rows_available` and `truncated`, which is what that
379
- source actually weighed and how many rows it actually carried. Build once, read that, and correct
380
- the declarations against it before you record a cadence. A revision changes the recipe digest and
393
+ run's own coverage is the other thing entirely. Build once, read the coverage, and correct the
394
+ declarations against it before you record a cadence. A revision changes the recipe digest and
381
395
  costs one full resync, so the cheapest time to be right is here.
382
396
 
397
+ **Where that coverage is depends on the route the build took.** An ordinary build seals a
398
+ `receipt`, and `mr-data receipt RUN --json` carries one entry per source with `bytes_fetched`,
399
+ `rows_kept`, `rows_available` and `truncated`. A build on the one-windowed-source bounded route
400
+ seals no receipt at all, and `mr-data receipt` answers `THIN_NO_MATCHING_ARTIFACT` naming what it
401
+ sealed instead. Read `mr-data status RUN --json` for that one: its `coverage` block carries `rows`,
402
+ `bytes`, `window` and `truncated`. That block is Studio's fold over every source, so it is one
403
+ source's own delivery only on a one-source recipe, which this route always is. Only
404
+ `rows_available` is missing, and `truncated` still says whether a ceiling cut the source short.
405
+
383
406
  ### Say what each column is, and what it shows
384
407
 
385
408
  **Every column carries a `description`, and every column that measures a physical quantity carries
@@ -9,6 +9,11 @@ mr-data checks RUN --json # every check the recipe declared
9
9
  mr-data receipt RUN --json # sources, digests, coverage, snapshot members
10
10
  ```
11
11
 
12
+ **The last of those answers `THIN_NO_MATCHING_ARTIFACT` on a run that sealed no receipt**, naming
13
+ what it sealed instead. That is the ordinary shape of a recipe with one `request`-windowed source
14
+ rather than a fault. Read `mr-data status RUN --json` for its coverage, as
15
+ [receipts](receipts.md) describes.
16
+
12
17
  **`peek` reports the logical type the run sealed.** The preview artifact carries column names
13
18
  alone, so the type comes from the run's own `column_profile`. A null `type` means the run sealed no
14
19
  profile for that column rather than that the column is untyped; check the run reached `persist`.
@@ -23,7 +23,7 @@ gap rather than doing anything, and `export-hosted-candidate`, which is a backen
23
23
  | `mr-data receipt` | Print what one run recorded about how it was built: every source it fetched and what those bytes hashed to, the coverage it delivered, and the members of its raw snapshot. |
24
24
  | `mr-data checks` | Report how each check the recipe declared came out — the name, whether it passed, what it found. Exits non-zero when one did not pass. |
25
25
  | `mr-data note` | Write one cell of a run's decision record — a heading, a body, and the typed blocks that carry a source, a decision or a clarification onto the stage its phase names. The body comes from `--markdown-file FILE`, which is the form to use; standard input is read when no file is named and is refused when it is a terminal or empty. `--list` reads back what is written. |
26
- | `mr-data download` | Bring one run's artifacts back to this computer, each one's bytes checked against the digest Studio sealed them under. `--kind` selects out of `table_parquet`, `table_manifest`, `table_part`, `column_profile`, `preview`, `receipt` and `raw_snapshot`; without it, the shape the run sealed — one file and the receipt for a table written whole, or the manifest, EVERY part the version names and the receipt for a table made of parts, written as `table/manifest.json` beside `table/parts/<part_key>.parquet`. A version composed over several refreshes names parts earlier runs sealed; those are fetched too, and a part that cannot be fetched refuses by name rather than leaving a folder holding part of a table. |
26
+ | `mr-data download` | Bring one run's artifacts back to this computer, each one's bytes checked against the digest Studio sealed them under. `--kind` selects out of `table_parquet`, `table_manifest`, `table_part`, `column_profile`, `preview`, `receipt` and `raw_snapshot`; without it, the shape the run sealed — one file and the receipt for a table written whole, or the manifest, EVERY part the version names and the receipt for a table made of parts, written as `table/manifest.json` beside `table/parts/<part_key>.parquet`. A version composed over several refreshes names parts earlier runs sealed; those are fetched too, and a part that cannot be fetched refuses by name rather than leaving a folder holding part of a table. A run that sealed no receipt brings back what it did seal, without one. |
27
27
  | `mr-data verify` | Hold one run's sealed table manifest against the parts it names, and report every disagreement. Without `--deep` it fetches the manifest alone; with `--deep` it fetches every part the run sealed and re-hashes it against the digest the manifest states. Exits non-zero when anything disagrees. |
28
28
  | `mr-data parts` | List one table version's parts — the identifier, the row count, the byte size and the recorded bounds of each — so a training loader can shard them across workers and read a table no single file should hold. `--version` names a version rather than the live one, and `--from`/`--to` keep only the parts a value range cannot rule out. Nothing is downloaded by listing them; the pattern is under [Reading a table that is made of parts](7-interrogate-ask-the-run-what-it-actually-delivered.md#reading-a-table-that-is-made-of-parts). |
29
29
  | `mr-data diff` | Compare two runs and say what changed. |
@@ -56,6 +56,31 @@ full reread; retain and reuse the caller-generated UUID after a lost response. A
56
56
  prints `mr-data run --confirm-held RUN_ID` for that exact run. A sample-first resync instead uses
57
57
  `--approve-full` only after its preview succeeds.
58
58
 
59
+ **`--refresh` states its own range, and a run that starts one by hand must pass it.** `mr-data run
60
+ --refresh` sends what it is given. A refresh of a recipe carrying a non-snapshot request window
61
+ and no range is refused `RUN_WINDOW_REQUIRED` at the `transform` stage, before a source is fetched.
62
+ Write `--window START END`, two UTC timestamps, start included and end excluded. Do not subtract
63
+ the lookback yourself: each source's own `lookback_seconds` widens that start backwards and aligns
64
+ it down to a whole UTC day, floored at `start_at`. The lookback never reaches the end, though the
65
+ end is still aligned up to the next whole UTC day. `--backfill` takes
66
+ the same pair, and the client refuses a backfill without it before anything is sent. Nothing local
67
+ requires it on a refresh, so a refresh without it is accepted and dies in the run.
68
+
69
+ **A refresh asked for before the source's period closes is refused `WINDOW_NOT_READY`.** This
70
+ reaches only a source declaring `refresh_readiness`, which says the publisher serves a UTC day
71
+ once that day is over. Studio floors `now` minus the declared lag to the UTC day, and a refresh
72
+ whose range starts at or after that floor names no completed period. The run fails at once rather
73
+ than being held. A refresh asked for from the dashboard in that state is recorded as a noop with
74
+ the same code and starts no run. Only time clears it, and the refused run's range is frozen, so a
75
+ new run is needed once the day is over. Report the code and wait rather than retrying or revising
76
+ the recipe.
77
+
78
+ **A refresh on the one-windowed-source bounded route seals no `receipt`.** `mr-data receipt`
79
+ answers `THIN_NO_MATCHING_ARTIFACT` and names what the run did seal, which is the ordinary shape
80
+ of that route rather than a fault. Read `mr-data status RUN_ID --json` instead: its `coverage`
81
+ block carries `rows`, `bytes`, `window` and `truncated`, and on a one-source recipe that is that
82
+ source's own delivery.
83
+
59
84
  `auth`, `login`, `whoami` and `clarify` are the same implementation in both profiles, and
60
85
  `clarify` alone reaches nothing at all. The other twenty-eight answer from Studio. Twelve only
61
86
  read: `status`, `runs`, `watch`, `peek`, `receipt`, `checks`, `download`, `verify`, `parts`,
@@ -1,5 +1,32 @@
1
1
  ## Narrating the run
2
2
 
3
+ ### Content for the expanded activity pill
4
+
5
+ Give the reader a short heading and enough detail to understand the actual dataset. At meaningful
6
+ milestones, record what changed in their understanding:
7
+
8
+ - Sources: which publisher and format supply which fields, with observed coverage and limitations.
9
+ - Extraction: which fields were inspected and how they map to the requested columns.
10
+ - Cleaning and joins: exact matching keys, conversions, row grain and missing-value choices,
11
+ including why a choice preserves the requested meaning.
12
+ - Result: verified output rows and columns, checks and source coverage, retaining any truncation
13
+ qualification. A successful run alone does not prove the result meets the brief.
14
+
15
+ Use the recipe for planned semantics, worker updates for reported execution, and status, checks,
16
+ receipt and inspected output for completion claims. For example, before execution say “The recipe
17
+ matches observations by station and date”; say “Matching observations by station and date” only
18
+ when the worker reports that operation. A broad transform-stage update does not establish which
19
+ join is executing. Do not infer all sources were fetched, checks passed, or work finished from a
20
+ timer, progress count, quiet stream or agent activity. Worker progress is provisional reporting,
21
+ not verified result evidence. Keep names and numbers grounded in this dataset rather than copying
22
+ an example. Saving a table and making the dataset public are separate actions.
23
+
24
+ Use a small number of substantive notes, not a second event stream. Update a settled decision's
25
+ cell instead of repeatedly appending the same explanation. The UI renders worker progress itself;
26
+ agent prose supplies the source choices and reasoning that progress cannot explain.
27
+
28
+ ### Dataset and run records
29
+
3
30
  There are two decision records and they are not interchangeable. A cell is the same document in
4
31
  both: one outcome-led heading, a markdown body, and typed blocks the Dataset page lays out as rows
5
32
  a reader can compare. What differs is which log it lands in and when that log closes.
@@ -7,7 +34,7 @@ a reader can compare. What differs is which log it lands in and when that log cl
7
34
  The rule that binds them to the chat is in the
8
35
  [User communication contract](user-communication-contract.md#user-communication-contract): every message is a cell, in the same
9
36
  words, at the same moment — the message's first sentence is the `--heading` and the whole message
10
- is the body.
37
+ is the body. Factual page-only milestone cells are also useful; they do not require extra chat.
11
38
 
12
39
  **The DATASET's record is the primary one, and it never closes.**
13
40
  `mr-data dataset note DATASET_ID` writes it. The sources compared and refused, the grain argued
@@ -28,8 +55,10 @@ and what belongs there is what is true of that run alone: a clamp that truncated
28
55
  not pass, the exact revision this attempt tested. A run's narrative closes when the run reaches a
29
56
  terminal state, and an append after that answers `409 RUN_NARRATIVE_CLOSED` — a refusal no client
30
57
  check can soften, because only the backend knows the run has finished. A bounded run reaches its
31
- terminal state in seconds, so "while the run is going" means immediately after `mr-data run`
32
- returns the identifier, not after `status` says the run succeeded.
58
+ terminal state in seconds, so append run-specific notes while it is known to be active. If an
59
+ append races completion and receives `RUN_NARRATIVE_CLOSED`, write the useful finding to the
60
+ dataset record with the run identified in its context. Post-run checks, coverage and delivery
61
+ always belong in the dataset record; do not retry appending to a closed run.
33
62
 
34
63
  ```sh
35
64
  mr-data note --run RUN_ID --heading "The row ceiling stopped one source short" \
@@ -23,6 +23,24 @@ A flag that cannot mean what it means locally is accepted and reported, never re
23
23
  digests, sources, timings and checks are already on the record it read. Read that key before
24
24
  repeating an argument that did nothing; only flags actually passed are reported.
25
25
 
26
+ ### Runs that seal no receipt
27
+
28
+ A recipe with exactly one source carrying a request window builds on a bounded route of its own,
29
+ and that route seals no `receipt` artifact. It is the route the first `full` build of such a recipe
30
+ takes, and every refresh after it takes the same one. `mr-data receipt` answers
31
+ `THIN_NO_MATCHING_ARTIFACT` and names what the run did seal, which is the raw source bundles, the
32
+ source state index, the source inventory, an incremental proof, the column profile, the preview,
33
+ the parts and the manifest. The run's own `receipt_digest` names that incremental proof rather than
34
+ a receipt. This is not a failure and not a deployment problem, so do not retry it and do not report
35
+ it as one.
36
+
37
+ What the run delivered is not lost with the receipt. `mr-data status RUN_ID --json` carries the
38
+ run record's `coverage` block: `rows`, `bytes`, `window` and `truncated`. Studio folds the
39
+ worker's per-source array into that one block, and on this route the recipe has exactly one
40
+ source, so the fold is that source's own numbers. `rows` is rows kept and `bytes` is bytes
41
+ fetched. The one field only a receipt carries is `rows_available`, so a run on this route cannot
42
+ say how many rows it left behind, only that `truncated` says there were some.
43
+
26
44
  ### Asking the table a question
27
45
 
28
46
  **In `mr-data query` the relation is always named `run_table`**, never the name the recipe gave the
@@ -8,7 +8,7 @@ cursors, digests, receipts, retry mechanics or service boundaries in anything th
8
8
  Where the host requires periodic status, that cadence is the only exception: one concise
9
9
  outcome-oriented sentence about the dataset stage or an observed result, inventing no progress.
10
10
 
11
- **Speak at six boundaries and nowhere else.** Each is a stage above, and each is one message:
11
+ **Send chat messages at these six boundaries.** Each is a stage above, and each is one message:
12
12
 
13
13
  | When | What it carries |
14
14
  | --- | --- |
@@ -28,9 +28,14 @@ message sent during a build is also a cell on the dataset's record: write it wit
28
28
  `mr-data dataset note`, taking the message's first sentence as the heading and the whole message as
29
29
  the body, in the same breath as sending it. The two are one act, not a message and a later summary
30
30
  of it. A person who joins by opening the page reads what the person in the chat read, and a person
31
- who scrolls the chat away still has it. The rule runs both ways: do not write a cell about work
32
- this document says to keep silent, and do not send a message you are not willing to write down. It
33
- licenses no extra update.
31
+ who scrolls the chat away still has it.
32
+
33
+ The expanded activity pill may also carry page-only milestone cells: selected sources and their
34
+ fields, a settled join or missing-value decision, a material finding, or a verified result. Write
35
+ one when the fact changes what a reader understands about the dataset; do not copy every worker
36
+ tick or routine command into a cell. These notes need no matching chat message. Preparation,
37
+ retries and transport mechanics remain silent on both surfaces. See
38
+ [build narration](narrating-the-run.md) for the distinction between planned and observed work.
34
39
 
35
40
  **Activity is not narration.** Setting the dataset's activity is a routine, silent act like any
36
41
  other command: never a chat message and never a cell. The rule above governs what is said;
@@ -28,8 +28,15 @@ themselves. Do not present a sequence of unlabeled paragraphs or default to a bu
28
28
 
29
29
  ### Agent presence lifecycle
30
30
 
31
- The floating pill represents only your active work. Start `dataset activity` immediately after creation, update the sentence when your task changes, and renew at least once a minute while you are actively working. The default lease is two minutes. Do not leave a detached heartbeat running after your turn ends. Worker ingestion progress has its own table surface and is not proof that you are working.
31
+ The floating pill combines agent activity with worker build progress. Your activity lease
32
+ represents only your active work. Start `dataset activity` immediately after creation, update the
33
+ sentence when your task changes, and renew at least once a minute while you are actively working.
34
+ The default lease is two minutes. Do not leave a detached heartbeat running after your turn ends.
35
+ Worker progress can continue in the expanded pill after your lease ends; it is not proof that you
36
+ are working. Do not renew your lease just to keep worker progress visible.
32
37
 
33
38
  When recovering, report what you are trying now; an earlier failed attempt belongs in the record. Before every final handoff, cancellation, or exhausted stop, report `--phase done` with a truthful final sentence (for example, “Dataset ready to explore” or “Stopped before the build completed”). Do this even when tables are not enabled. Only use `waiting_on_you` when a question is actually open — the brief at stage 2, the plan at stage 4, or the full build after a preview — and never under a delegation, which leaves nothing to wait on. A table going live does not finish your agent session.
34
39
 
35
- Stage 1 opened the dataset before research began; keep that same tab. Enable its optional Follow agent control for a watch-along experience; manual scrolling pauses it and must never be overridden.
40
+ Stage 1 opened the dataset before research began; keep that same tab. Follow agent starts enabled
41
+ for a watch-along experience; respect the viewer’s choice to pause or disable it. Manual scrolling
42
+ pauses following and must never be overridden.
@@ -105,6 +105,13 @@ from mostlyright.data_harness.thin.transport import ThinLaneError
105
105
  #: same bounded projection. That is the deploy ordering this client now relies on instead of the
106
106
  #: legacy unfenced actions.
107
107
  #:
108
+ #: ⚠ ``4.10.0`` ADDS THE BOUNDED RUN PROGRESS SNAPSHOT and ``4.10.1`` WIDENS STRICT INCREMENTAL
109
+ #: REFRESH ADMISSION to safe multi-source direct-window plans. The snapshot is
110
+ #: :data:`RUN_PROGRESS_PATH`, declared below with no caller yet; the widening admits refresh plans
111
+ #: Studio previously refused rather than asking this client for a new document shape. The number
112
+ #: rises here anyway, because every command body this client sends stamps it, so Studio's request
113
+ #: grammar has to admit it before this package reaches that Studio.
114
+ #:
108
115
  #: ⚠ AND THE WORKER SIDE OF THAT DELETION IS A DEPLOY ORDERING OF ITS OWN, in the OPPOSITE
109
116
  #: direction from the one above. ``run_execution_v4``'s job parser compares an EXACT field set, and
110
117
  #: ``source_collection_protocol``, ``source_collection`` and ``source_collection_inputs`` are no
@@ -112,8 +119,8 @@ from mostlyright.data_harness.thin.transport import ThinLaneError
112
119
  #: ``JOB_INVALID`` outright, which in production was every refresh a collection epoch was offered
113
120
  #: for rather than only the collection runs. This package must not reach a Studio older than the
114
121
  #: commit it pins; ``docs/V4-WORKER-PROTOCOL.md`` states it beside the layout's own ordering rule.
115
- PINNED_V4_OPENAPI_SOURCE_SHA256 = "6a5766a2f1dbf93f99582e65f91557e235101258b5167a26a24fc264243f61d8"
116
- PINNED_V4_CONTRACT_VERSION = "4.9.0"
122
+ PINNED_V4_OPENAPI_SOURCE_SHA256 = "25c85955d2adbfac78bd13b9007baeebfae25ec08d9737e58d9db8e3afe46346"
123
+ PINNED_V4_CONTRACT_VERSION = "4.10.1"
117
124
 
118
125
  # --------------------------------------------------------------------------------------------
119
126
  # The routes
@@ -195,6 +202,16 @@ GET_RUN_QUERY_PATH = "/v4/runs/{run_id}/query/{query_id}"
195
202
  #: ``GET`` -- the run's event stream, resumable by ``Last-Event-ID``.
196
203
  RUN_EVENTS_PATH = "/v4/runs/{run_id}/events"
197
204
 
205
+ #: ``GET`` -- one bounded point-in-time snapshot of a run's progress: the latest non-null public
206
+ #: progress facts folded across at most the 64 most recent durable PROGRESS events found in a
207
+ #: bounded window of the run's log, with the sequence of the newest such event in that window. It
208
+ #: reads the sealed record without mutating it or its ETag.
209
+ #:
210
+ #: ⚠ DECLARED WITH NO CALLER YET, on the same terms as :data:`LIST_TABLE_VERSIONS_PATH`. This
211
+ #: client renders progress by following :data:`RUN_EVENTS_PATH` and folding the frames itself, so
212
+ #: a command that wants one bounded snapshot rather than the stream lands against this constant.
213
+ RUN_PROGRESS_PATH = "/v4/runs/{run_id}/progress"
214
+
198
215
  # Reader recovery uses Studio's versioned authority. These routes deliberately live beside the
199
216
  # other V4 wire constants so a client cannot silently turn transport canonicalisation into reader
200
217
  # validation.
@@ -394,6 +411,15 @@ RESCHEDULE_TABLE_PATH = "/v4/tables/{table_id}:reschedule"
394
411
  #: plan, while a resync is an operator-requested full run with its own idempotency coordinate.
395
412
  RESYNC_TABLE_PATH = "/v4/tables/{table_id}:resync"
396
413
 
414
+ #: ``POST`` -- bind one explicitly selected stream recipe revision and digest to a live table under
415
+ #: the promotion version fence, and remember that choice for later terminal-recorder recovery.
416
+ #: Editor-only, and it never selects a recipe itself: a registered revision stays a candidate until
417
+ #: a caller names it.
418
+ #:
419
+ #: ⚠ DECLARED WITH NO CALLER YET. This client registers recipe revisions but owns no command that
420
+ #: rebinds the recipe a live recorder is running.
421
+ REPAIR_TABLE_STREAMS_PATH = "/v4/tables/{table_id}:repair-streams"
422
+
397
423
  #: ``GET`` -- what each source carried on each refresh, newest first: the evidence the schedule is
398
424
  #: learned from, and the only place a person can see why it settled where it did.
399
425
  TABLE_CADENCE_OBSERVATIONS_PATH = "/v4/tables/{table_id}/cadence/observations"
@@ -453,6 +479,18 @@ STREAM_SUBSCRIPTION_RESUME_QUIESCENCE_PATH = (
453
479
  "/v4/stream/subscriptions/{subscription_id}:resume-quiescence"
454
480
  )
455
481
 
482
+ #: ``POST`` -- end one subscription under that same exact-version fence. Studio terminalizes
483
+ #: immediately when the fenced snapshot holds no lease, pending checkpoint or final-flush
484
+ #: reservation, and otherwise requests cancellation for a later bounded observation to prove
485
+ #: drained.
486
+ #:
487
+ #: ⚠ DECLARED WITH NO CALLER YET. The bounded quiescence lane in ``thin/stream_venue.py`` moves
488
+ #: only pause and resume; a stop still goes through the unfenced
489
+ #: :data:`STREAM_SUBSCRIPTION_STOP_PATH`, so this is the fenced stop that lane does not yet send.
490
+ STREAM_SUBSCRIPTION_STOP_QUIESCENCE_PATH = (
491
+ "/v4/stream/subscriptions/{subscription_id}:stop-quiescence"
492
+ )
493
+
456
494
  #: ``POST`` -- the three actions that move one subscription. One constant each, because this block
457
495
  #: is one constant per operation and a composed suffix would hide two of the three from a reviewer
458
496
  #: reading it beside the contract.
@@ -560,6 +598,7 @@ DECLARED_V4_PATHS: frozenset[str] = frozenset(
560
598
  RUN_QUERY_PATH,
561
599
  GET_RUN_QUERY_PATH,
562
600
  RUN_EVENTS_PATH,
601
+ RUN_PROGRESS_PATH,
563
602
  # ⚠ PROMOTED OUT OF `PENDING_V4_PATHS` IN THE COMMIT THAT STARTED CALLING THEM. Studio
564
603
  # shipped the whole promotion surface while this client was being written against the
565
604
  # contract for it, and the ledger in `tests/test_thin_v4_contract.py` went red naming all
@@ -575,6 +614,7 @@ DECLARED_V4_PATHS: frozenset[str] = frozenset(
575
614
  # a catch-up run; the observations listing is the evidence a learned schedule rests on.
576
615
  RESCHEDULE_TABLE_PATH,
577
616
  RESYNC_TABLE_PATH,
617
+ REPAIR_TABLE_STREAMS_PATH,
578
618
  TABLE_CADENCE_OBSERVATIONS_PATH,
579
619
  # ⚠ AND THE SAME AGAIN FOR THE CREDENTIAL REGISTRY, promoted the moment Studio served it.
580
620
  # The recorded metadata was already the shipped projection, member for member, with one
@@ -628,6 +668,7 @@ DECLARED_V4_PATHS: frozenset[str] = frozenset(
628
668
  STREAM_SUBSCRIPTION_PAUSE_QUIESCENCE_PATH,
629
669
  STREAM_SUBSCRIPTION_QUIESCENCE_PATH,
630
670
  STREAM_SUBSCRIPTION_RESUME_QUIESCENCE_PATH,
671
+ STREAM_SUBSCRIPTION_STOP_QUIESCENCE_PATH,
631
672
  STREAM_SUBSCRIPTION_PAUSE_PATH,
632
673
  STREAM_SUBSCRIPTION_RESUME_PATH,
633
674
  STREAM_SUBSCRIPTION_STOP_PATH,
@@ -895,10 +936,12 @@ __all__ = [
895
936
  "PIN_TABLE_PATH",
896
937
  "PROMOTE_TABLE_PATH",
897
938
  "RECIPE_READINESS_PATH",
939
+ "REPAIR_TABLE_STREAMS_PATH",
898
940
  "RESCHEDULE_TABLE_PATH",
899
941
  "RESYNC_TABLE_PATH",
900
942
  "RUN_ARTIFACTS_PATH",
901
943
  "RUN_EVENTS_PATH",
944
+ "RUN_PROGRESS_PATH",
902
945
  "RUN_QUERY_PATH",
903
946
  "SECRET_PATH",
904
947
  "SESSION_HANDOFF_PATH",
@@ -920,6 +963,7 @@ __all__ = [
920
963
  "STREAM_SUBSCRIPTION_RESUME_PATH",
921
964
  "STREAM_SUBSCRIPTION_RESUME_QUIESCENCE_PATH",
922
965
  "STREAM_SUBSCRIPTION_STOP_PATH",
966
+ "STREAM_SUBSCRIPTION_STOP_QUIESCENCE_PATH",
923
967
  "TABLE_CADENCE_OBSERVATIONS_PATH",
924
968
  "TABLE_VERSION_EXPORT_PATH",
925
969
  "TABLE_VERSION_MANIFEST_PATH",