straw-queue 0.1.6__tar.gz → 0.1.7__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 (388) hide show
  1. {straw_queue-0.1.6 → straw_queue-0.1.7}/CHANGELOG.md +34 -0
  2. {straw_queue-0.1.6 → straw_queue-0.1.7}/CHANGELOG_zh.md +14 -0
  3. {straw_queue-0.1.6 → straw_queue-0.1.7}/Cargo.lock +2 -1
  4. {straw_queue-0.1.6 → straw_queue-0.1.7}/Cargo.toml +4 -1
  5. {straw_queue-0.1.6 → straw_queue-0.1.7}/PKG-INFO +1 -1
  6. {straw_queue-0.1.6 → straw_queue-0.1.7}/docs/USAGE.md +20 -0
  7. {straw_queue-0.1.6 → straw_queue-0.1.7}/docs/USAGE_zh.md +16 -0
  8. {straw_queue-0.1.6 → straw_queue-0.1.7}/pyproject.toml +1 -1
  9. {straw_queue-0.1.6 → straw_queue-0.1.7}/rust/coordinator.rs +123 -40
  10. {straw_queue-0.1.6 → straw_queue-0.1.7}/rust/gc.rs +157 -18
  11. straw_queue-0.1.7/rust/graph_proof_tests.rs +210 -0
  12. {straw_queue-0.1.6 → straw_queue-0.1.7}/rust/lib.rs +3 -0
  13. {straw_queue-0.1.6 → straw_queue-0.1.7}/rust/python.rs +193 -17
  14. straw_queue-0.1.7/rust/read_window.rs +154 -0
  15. {straw_queue-0.1.6 → straw_queue-0.1.7}/rust/reference_node.rs +0 -27
  16. {straw_queue-0.1.6 → straw_queue-0.1.7}/rust/store.rs +715 -31
  17. {straw_queue-0.1.6 → straw_queue-0.1.7}/src/straw/coordinator.py +34 -1
  18. {straw_queue-0.1.6 → straw_queue-0.1.7}/src/straw/store.py +74 -0
  19. {straw_queue-0.1.6 → straw_queue-0.1.7}/src/straw/tensor.py +66 -4
  20. {straw_queue-0.1.6 → straw_queue-0.1.7}/tests/native.rs +102 -0
  21. straw_queue-0.1.7/tests/test_confined_open.py +51 -0
  22. {straw_queue-0.1.6 → straw_queue-0.1.7}/tests/test_dependency_traversal.py +6 -2
  23. straw_queue-0.1.7/tests/test_graph_proof_operations.py +71 -0
  24. straw_queue-0.1.7/tests/test_parallel_validation.py +72 -0
  25. {straw_queue-0.1.6 → straw_queue-0.1.7}/tests/test_read_session.py +48 -2
  26. straw_queue-0.1.7/tests/test_ready_validation_scope.py +212 -0
  27. straw_queue-0.1.7/tests/test_tensor_batch_reads.py +124 -0
  28. {straw_queue-0.1.6 → straw_queue-0.1.7}/verification/storage/probes/dependency_probe.py +33 -9
  29. {straw_queue-0.1.6 → straw_queue-0.1.7}/.agents/skills/straw-protocol-review/SKILL.md +0 -0
  30. {straw_queue-0.1.6 → straw_queue-0.1.7}/.agents/skills/straw-protocol-review/agents/openai.yaml +0 -0
  31. {straw_queue-0.1.6 → straw_queue-0.1.7}/.github/workflows/tests.yml +0 -0
  32. {straw_queue-0.1.6 → straw_queue-0.1.7}/.github/workflows/wheels.yml +0 -0
  33. {straw_queue-0.1.6 → straw_queue-0.1.7}/CONTRIBUTING.md +0 -0
  34. {straw_queue-0.1.6 → straw_queue-0.1.7}/CONTRIBUTING_zh.md +0 -0
  35. {straw_queue-0.1.6 → straw_queue-0.1.7}/LICENSE +0 -0
  36. {straw_queue-0.1.6 → straw_queue-0.1.7}/README.md +0 -0
  37. {straw_queue-0.1.6 → straw_queue-0.1.7}/README_zh.md +0 -0
  38. {straw_queue-0.1.6 → straw_queue-0.1.7}/docs/BENCHMARKS.md +0 -0
  39. {straw_queue-0.1.6 → straw_queue-0.1.7}/docs/BENCHMARKS_zh.md +0 -0
  40. {straw_queue-0.1.6 → straw_queue-0.1.7}/docs/DESIGN.md +0 -0
  41. {straw_queue-0.1.6 → straw_queue-0.1.7}/docs/DESIGN_zh.md +0 -0
  42. {straw_queue-0.1.6 → straw_queue-0.1.7}/docs/FILESYSTEM.md +0 -0
  43. {straw_queue-0.1.6 → straw_queue-0.1.7}/docs/FILESYSTEM_zh.md +0 -0
  44. {straw_queue-0.1.6 → straw_queue-0.1.7}/docs/FORMAT.md +0 -0
  45. {straw_queue-0.1.6 → straw_queue-0.1.7}/docs/FORMAT_zh.md +0 -0
  46. {straw_queue-0.1.6 → straw_queue-0.1.7}/docs/README.md +0 -0
  47. {straw_queue-0.1.6 → straw_queue-0.1.7}/docs/README_zh.md +0 -0
  48. {straw_queue-0.1.6 → straw_queue-0.1.7}/examples/multiprocess.py +0 -0
  49. {straw_queue-0.1.6 → straw_queue-0.1.7}/examples/records.py +0 -0
  50. {straw_queue-0.1.6 → straw_queue-0.1.7}/examples/tensors.py +0 -0
  51. {straw_queue-0.1.6 → straw_queue-0.1.7}/examples/work_queue.py +0 -0
  52. {straw_queue-0.1.6 → straw_queue-0.1.7}/rust/access.rs +0 -0
  53. {straw_queue-0.1.6 → straw_queue-0.1.7}/rust/bounds.rs +0 -0
  54. {straw_queue-0.1.6 → straw_queue-0.1.7}/rust/catalog_append.rs +0 -0
  55. {straw_queue-0.1.6 → straw_queue-0.1.7}/rust/catalog_decode.rs +0 -0
  56. {straw_queue-0.1.6 → straw_queue-0.1.7}/rust/catalog_event.rs +0 -0
  57. {straw_queue-0.1.6 → straw_queue-0.1.7}/rust/catalog_frame.rs +0 -0
  58. {straw_queue-0.1.6 → straw_queue-0.1.7}/rust/catalog_json.rs +0 -0
  59. {straw_queue-0.1.6 → straw_queue-0.1.7}/rust/catalog_log.rs +0 -0
  60. {straw_queue-0.1.6 → straw_queue-0.1.7}/rust/catalog_namespace.rs +0 -0
  61. {straw_queue-0.1.6 → straw_queue-0.1.7}/rust/catalog_primitives.rs +0 -0
  62. {straw_queue-0.1.6 → straw_queue-0.1.7}/rust/catalog_runtime.rs +0 -0
  63. {straw_queue-0.1.6 → straw_queue-0.1.7}/rust/catalog_state.rs +0 -0
  64. {straw_queue-0.1.6 → straw_queue-0.1.7}/rust/catalog_target.rs +0 -0
  65. {straw_queue-0.1.6 → straw_queue-0.1.7}/rust/catalog_transaction.rs +0 -0
  66. {straw_queue-0.1.6 → straw_queue-0.1.7}/rust/closure.rs +0 -0
  67. {straw_queue-0.1.6 → straw_queue-0.1.7}/rust/closure_node.rs +0 -0
  68. {straw_queue-0.1.6 → straw_queue-0.1.7}/rust/consumption.rs +0 -0
  69. {straw_queue-0.1.6 → straw_queue-0.1.7}/rust/directory.rs +0 -0
  70. {straw_queue-0.1.6 → straw_queue-0.1.7}/rust/directory_io.rs +0 -0
  71. {straw_queue-0.1.6 → straw_queue-0.1.7}/rust/discovery.rs +0 -0
  72. {straw_queue-0.1.6 → straw_queue-0.1.7}/rust/extent_retry.rs +0 -0
  73. {straw_queue-0.1.6 → straw_queue-0.1.7}/rust/file_adapter.rs +0 -0
  74. {straw_queue-0.1.6 → straw_queue-0.1.7}/rust/file_primitives.rs +0 -0
  75. {straw_queue-0.1.6 → straw_queue-0.1.7}/rust/finalization.rs +0 -0
  76. {straw_queue-0.1.6 → straw_queue-0.1.7}/rust/framing.rs +0 -0
  77. {straw_queue-0.1.6 → straw_queue-0.1.7}/rust/gc_batch.rs +0 -0
  78. {straw_queue-0.1.6 → straw_queue-0.1.7}/rust/gc_collection.rs +0 -0
  79. {straw_queue-0.1.6 → straw_queue-0.1.7}/rust/gc_io.rs +0 -0
  80. {straw_queue-0.1.6 → straw_queue-0.1.7}/rust/gc_mark.rs +0 -0
  81. {straw_queue-0.1.6 → straw_queue-0.1.7}/rust/gc_plan.rs +0 -0
  82. {straw_queue-0.1.6 → straw_queue-0.1.7}/rust/gc_receipt.rs +0 -0
  83. {straw_queue-0.1.6 → straw_queue-0.1.7}/rust/gc_writer.rs +0 -0
  84. {straw_queue-0.1.6 → straw_queue-0.1.7}/rust/holding.rs +0 -0
  85. {straw_queue-0.1.6 → straw_queue-0.1.7}/rust/identities.rs +0 -0
  86. {straw_queue-0.1.6 → straw_queue-0.1.7}/rust/incomplete.rs +0 -0
  87. {straw_queue-0.1.6 → straw_queue-0.1.7}/rust/journal.rs +0 -0
  88. {straw_queue-0.1.6 → straw_queue-0.1.7}/rust/journal_append.rs +0 -0
  89. {straw_queue-0.1.6 → straw_queue-0.1.7}/rust/journal_io.rs +0 -0
  90. {straw_queue-0.1.6 → straw_queue-0.1.7}/rust/journal_owner.rs +0 -0
  91. {straw_queue-0.1.6 → straw_queue-0.1.7}/rust/journal_primitives.rs +0 -0
  92. {straw_queue-0.1.6 → straw_queue-0.1.7}/rust/journal_recovery.rs +0 -0
  93. {straw_queue-0.1.6 → straw_queue-0.1.7}/rust/journal_state.rs +0 -0
  94. {straw_queue-0.1.6 → straw_queue-0.1.7}/rust/json_update.rs +0 -0
  95. {straw_queue-0.1.6 → straw_queue-0.1.7}/rust/namespace_identity.rs +0 -0
  96. {straw_queue-0.1.6 → straw_queue-0.1.7}/rust/namespace_step.rs +0 -0
  97. {straw_queue-0.1.6 → straw_queue-0.1.7}/rust/namespace_target.rs +0 -0
  98. {straw_queue-0.1.6 → straw_queue-0.1.7}/rust/payload.rs +0 -0
  99. {straw_queue-0.1.6 → straw_queue-0.1.7}/rust/pending.rs +0 -0
  100. {straw_queue-0.1.6 → straw_queue-0.1.7}/rust/protocol.rs +0 -0
  101. {straw_queue-0.1.6 → straw_queue-0.1.7}/rust/queue_admin.rs +0 -0
  102. {straw_queue-0.1.6 → straw_queue-0.1.7}/rust/queue_application.rs +0 -0
  103. {straw_queue-0.1.6 → straw_queue-0.1.7}/rust/queue_commit.rs +0 -0
  104. {straw_queue-0.1.6 → straw_queue-0.1.7}/rust/queue_event.rs +0 -0
  105. {straw_queue-0.1.6 → straw_queue-0.1.7}/rust/queue_gc.rs +0 -0
  106. {straw_queue-0.1.6 → straw_queue-0.1.7}/rust/queue_gc_prepare.rs +0 -0
  107. {straw_queue-0.1.6 → straw_queue-0.1.7}/rust/queue_handoff.rs +0 -0
  108. {straw_queue-0.1.6 → straw_queue-0.1.7}/rust/queue_history.rs +0 -0
  109. {straw_queue-0.1.6 → straw_queue-0.1.7}/rust/queue_metadata.rs +0 -0
  110. {straw_queue-0.1.6 → straw_queue-0.1.7}/rust/queue_progress.rs +0 -0
  111. {straw_queue-0.1.6 → straw_queue-0.1.7}/rust/queue_reader.rs +0 -0
  112. {straw_queue-0.1.6 → straw_queue-0.1.7}/rust/queue_receipt.rs +0 -0
  113. {straw_queue-0.1.6 → straw_queue-0.1.7}/rust/queue_replay.rs +0 -0
  114. {straw_queue-0.1.6 → straw_queue-0.1.7}/rust/queue_retirement.rs +0 -0
  115. {straw_queue-0.1.6 → straw_queue-0.1.7}/rust/queue_roots.rs +0 -0
  116. {straw_queue-0.1.6 → straw_queue-0.1.7}/rust/queue_state.rs +0 -0
  117. {straw_queue-0.1.6 → straw_queue-0.1.7}/rust/queue_task.rs +0 -0
  118. {straw_queue-0.1.6 → straw_queue-0.1.7}/rust/queue_transition.rs +0 -0
  119. {straw_queue-0.1.6 → straw_queue-0.1.7}/rust/reclamation.rs +0 -0
  120. {straw_queue-0.1.6 → straw_queue-0.1.7}/rust/record_index.rs +0 -0
  121. {straw_queue-0.1.6 → straw_queue-0.1.7}/rust/record_manifest.rs +0 -0
  122. {straw_queue-0.1.6 → straw_queue-0.1.7}/rust/reference_validation.rs +0 -0
  123. {straw_queue-0.1.6 → straw_queue-0.1.7}/rust/replay.rs +0 -0
  124. {straw_queue-0.1.6 → straw_queue-0.1.7}/rust/request.rs +0 -0
  125. {straw_queue-0.1.6 → straw_queue-0.1.7}/rust/selection.rs +0 -0
  126. {straw_queue-0.1.6 → straw_queue-0.1.7}/rust/staging_consumption.rs +0 -0
  127. {straw_queue-0.1.6 → straw_queue-0.1.7}/rust/stream.rs +0 -0
  128. {straw_queue-0.1.6 → straw_queue-0.1.7}/rust/traversal.rs +0 -0
  129. {straw_queue-0.1.6 → straw_queue-0.1.7}/rust/typed.rs +0 -0
  130. {straw_queue-0.1.6 → straw_queue-0.1.7}/rust/wal.rs +0 -0
  131. {straw_queue-0.1.6 → straw_queue-0.1.7}/rust/wal_append.rs +0 -0
  132. {straw_queue-0.1.6 → straw_queue-0.1.7}/rust/wal_device.rs +0 -0
  133. {straw_queue-0.1.6 → straw_queue-0.1.7}/rust/wal_file.rs +0 -0
  134. {straw_queue-0.1.6 → straw_queue-0.1.7}/rust/wal_recovery.rs +0 -0
  135. {straw_queue-0.1.6 → straw_queue-0.1.7}/rust/wal_sink.rs +0 -0
  136. {straw_queue-0.1.6 → straw_queue-0.1.7}/rust/wal_source.rs +0 -0
  137. {straw_queue-0.1.6 → straw_queue-0.1.7}/rust/writer_gate.rs +0 -0
  138. {straw_queue-0.1.6 → straw_queue-0.1.7}/rust/writer_gate_flow.rs +0 -0
  139. {straw_queue-0.1.6 → straw_queue-0.1.7}/rust/writer_ownership.rs +0 -0
  140. {straw_queue-0.1.6 → straw_queue-0.1.7}/rust/writer_registry.rs +0 -0
  141. {straw_queue-0.1.6 → straw_queue-0.1.7}/rust/writer_retirement.rs +0 -0
  142. {straw_queue-0.1.6 → straw_queue-0.1.7}/src/straw/__init__.py +0 -0
  143. {straw_queue-0.1.6 → straw_queue-0.1.7}/src/straw/backend.py +0 -0
  144. {straw_queue-0.1.6 → straw_queue-0.1.7}/src/straw/benchmark.py +0 -0
  145. {straw_queue-0.1.6 → straw_queue-0.1.7}/src/straw/errors.py +0 -0
  146. {straw_queue-0.1.6 → straw_queue-0.1.7}/src/straw/inspect.py +0 -0
  147. {straw_queue-0.1.6 → straw_queue-0.1.7}/src/straw/journal.py +0 -0
  148. {straw_queue-0.1.6 → straw_queue-0.1.7}/src/straw/protocol.py +0 -0
  149. {straw_queue-0.1.6 → straw_queue-0.1.7}/src/straw/reporting.py +0 -0
  150. {straw_queue-0.1.6 → straw_queue-0.1.7}/src/straw/rpc.py +0 -0
  151. {straw_queue-0.1.6 → straw_queue-0.1.7}/src/straw/tracing.py +0 -0
  152. {straw_queue-0.1.6 → straw_queue-0.1.7}/tests/test_artifact_privacy.py +0 -0
  153. {straw_queue-0.1.6 → straw_queue-0.1.7}/tests/test_benchmark_profile.py +0 -0
  154. {straw_queue-0.1.6 → straw_queue-0.1.7}/tests/test_catalog_encoding.py +0 -0
  155. {straw_queue-0.1.6 → straw_queue-0.1.7}/tests/test_commit_consumption.py +0 -0
  156. {straw_queue-0.1.6 → straw_queue-0.1.7}/tests/test_commit_protocol.py +0 -0
  157. {straw_queue-0.1.6 → straw_queue-0.1.7}/tests/test_consumer_rewind.py +0 -0
  158. {straw_queue-0.1.6 → straw_queue-0.1.7}/tests/test_durable_handoff.py +0 -0
  159. {straw_queue-0.1.6 → straw_queue-0.1.7}/tests/test_extent_bounds.py +0 -0
  160. {straw_queue-0.1.6 → straw_queue-0.1.7}/tests/test_extent_visibility.py +0 -0
  161. {straw_queue-0.1.6 → straw_queue-0.1.7}/tests/test_filesystem_queue.py +0 -0
  162. {straw_queue-0.1.6 → straw_queue-0.1.7}/tests/test_gc_batch.py +0 -0
  163. {straw_queue-0.1.6 → straw_queue-0.1.7}/tests/test_gc_concurrency.py +0 -0
  164. {straw_queue-0.1.6 → straw_queue-0.1.7}/tests/test_gc_extent_validation.py +0 -0
  165. {straw_queue-0.1.6 → straw_queue-0.1.7}/tests/test_gc_missing_parent.py +0 -0
  166. {straw_queue-0.1.6 → straw_queue-0.1.7}/tests/test_gc_receipts.py +0 -0
  167. {straw_queue-0.1.6 → straw_queue-0.1.7}/tests/test_incomplete_publication.py +0 -0
  168. {straw_queue-0.1.6 → straw_queue-0.1.7}/tests/test_journal_contract.py +0 -0
  169. {straw_queue-0.1.6 → straw_queue-0.1.7}/tests/test_json_roundtrip.py +0 -0
  170. {straw_queue-0.1.6 → straw_queue-0.1.7}/tests/test_lease_selection.py +0 -0
  171. {straw_queue-0.1.6 → straw_queue-0.1.7}/tests/test_metadata_recovery.py +0 -0
  172. {straw_queue-0.1.6 → straw_queue-0.1.7}/tests/test_offline_aliases.py +0 -0
  173. {straw_queue-0.1.6 → straw_queue-0.1.7}/tests/test_offline_inspection.py +0 -0
  174. {straw_queue-0.1.6 → straw_queue-0.1.7}/tests/test_offline_recovery.py +0 -0
  175. {straw_queue-0.1.6 → straw_queue-0.1.7}/tests/test_online_gc.py +0 -0
  176. {straw_queue-0.1.6 → straw_queue-0.1.7}/tests/test_packed_store.py +0 -0
  177. {straw_queue-0.1.6 → straw_queue-0.1.7}/tests/test_path_identity.py +0 -0
  178. {straw_queue-0.1.6 → straw_queue-0.1.7}/tests/test_pending_publication.py +0 -0
  179. {straw_queue-0.1.6 → straw_queue-0.1.7}/tests/test_provisional_holds.py +0 -0
  180. {straw_queue-0.1.6 → straw_queue-0.1.7}/tests/test_publication_handoff.py +0 -0
  181. {straw_queue-0.1.6 → straw_queue-0.1.7}/tests/test_publication_preparation.py +0 -0
  182. {straw_queue-0.1.6 → straw_queue-0.1.7}/tests/test_queue_gc_roots.py +0 -0
  183. {straw_queue-0.1.6 → straw_queue-0.1.7}/tests/test_request_replay.py +0 -0
  184. {straw_queue-0.1.6 → straw_queue-0.1.7}/tests/test_resume_workflow.py +0 -0
  185. {straw_queue-0.1.6 → straw_queue-0.1.7}/tests/test_staging_consumption.py +0 -0
  186. {straw_queue-0.1.6 → straw_queue-0.1.7}/tests/test_streaming_write.py +0 -0
  187. {straw_queue-0.1.6 → straw_queue-0.1.7}/tests/test_task_recovery.py +0 -0
  188. {straw_queue-0.1.6 → straw_queue-0.1.7}/tests/test_tensor.py +0 -0
  189. {straw_queue-0.1.6 → straw_queue-0.1.7}/tests/test_tensor_granularity.py +0 -0
  190. {straw_queue-0.1.6 → straw_queue-0.1.7}/tests/test_tensor_preflight.py +0 -0
  191. {straw_queue-0.1.6 → straw_queue-0.1.7}/tests/test_unlimited_capacity.py +0 -0
  192. {straw_queue-0.1.6 → straw_queue-0.1.7}/tests/test_verification_runner.py +0 -0
  193. {straw_queue-0.1.6 → straw_queue-0.1.7}/tests/test_visibility_probe.py +0 -0
  194. {straw_queue-0.1.6 → straw_queue-0.1.7}/tests/test_wal_recovery.py +0 -0
  195. {straw_queue-0.1.6 → straw_queue-0.1.7}/tests/test_writer_access.py +0 -0
  196. {straw_queue-0.1.6 → straw_queue-0.1.7}/tests/test_writer_retirement.py +0 -0
  197. {straw_queue-0.1.6 → straw_queue-0.1.7}/tools/check_artifact_privacy.py +0 -0
  198. {straw_queue-0.1.6 → straw_queue-0.1.7}/tools/check_wheel.py +0 -0
  199. {straw_queue-0.1.6 → straw_queue-0.1.7}/tools/release_build.py +0 -0
  200. {straw_queue-0.1.6 → straw_queue-0.1.7}/verification/README.md +0 -0
  201. {straw_queue-0.1.6 → straw_queue-0.1.7}/verification/README_zh.md +0 -0
  202. {straw_queue-0.1.6 → straw_queue-0.1.7}/verification/common/README.md +0 -0
  203. {straw_queue-0.1.6 → straw_queue-0.1.7}/verification/common/probes/runtime_performance.py +0 -0
  204. {straw_queue-0.1.6 → straw_queue-0.1.7}/verification/common/tla/EnvironmentCatalog.tla +0 -0
  205. {straw_queue-0.1.6 → straw_queue-0.1.7}/verification/common/tla/EnvironmentGraph.tla +0 -0
  206. {straw_queue-0.1.6 → straw_queue-0.1.7}/verification/common/tla/EnvironmentInputs.tla +0 -0
  207. {straw_queue-0.1.6 → straw_queue-0.1.7}/verification/common/tla/EnvironmentNamespace.tla +0 -0
  208. {straw_queue-0.1.6 → straw_queue-0.1.7}/verification/common/tla/EnvironmentPersistence.tla +0 -0
  209. {straw_queue-0.1.6 → straw_queue-0.1.7}/verification/common/tla/EnvironmentProgress.tla +0 -0
  210. {straw_queue-0.1.6 → straw_queue-0.1.7}/verification/common/tla/EnvironmentRead.tla +0 -0
  211. {straw_queue-0.1.6 → straw_queue-0.1.7}/verification/environment_contracts.json +0 -0
  212. {straw_queue-0.1.6 → straw_queue-0.1.7}/verification/gc/README.md +0 -0
  213. {straw_queue-0.1.6 → straw_queue-0.1.7}/verification/gc/probes/catalog_discovery_fault.c +0 -0
  214. {straw_queue-0.1.6 → straw_queue-0.1.7}/verification/gc/probes/catalog_discovery_probe.py +0 -0
  215. {straw_queue-0.1.6 → straw_queue-0.1.7}/verification/gc/probes/gc_cross_client.py +0 -0
  216. {straw_queue-0.1.6 → straw_queue-0.1.7}/verification/gc/probes/gc_history_probe.py +0 -0
  217. {straw_queue-0.1.6 → straw_queue-0.1.7}/verification/gc/probes/gc_parent_fault.c +0 -0
  218. {straw_queue-0.1.6 → straw_queue-0.1.7}/verification/gc/probes/gc_parent_probe.py +0 -0
  219. {straw_queue-0.1.6 → straw_queue-0.1.7}/verification/gc/probes/gc_receipt_probe.py +0 -0
  220. {straw_queue-0.1.6 → straw_queue-0.1.7}/verification/gc/probes/gc_scale.py +0 -0
  221. {straw_queue-0.1.6 → straw_queue-0.1.7}/verification/gc/probes/gc_stat_fault.c +0 -0
  222. {straw_queue-0.1.6 → straw_queue-0.1.7}/verification/gc/probes/gc_stat_probe.py +0 -0
  223. {straw_queue-0.1.6 → straw_queue-0.1.7}/verification/gc/tla/EnvironmentParentRepair.tla +0 -0
  224. {straw_queue-0.1.6 → straw_queue-0.1.7}/verification/gc/tla/EnvironmentWriter.tla +0 -0
  225. {straw_queue-0.1.6 → straw_queue-0.1.7}/verification/gc/tla/EnvironmentWriterRetirement.tla +0 -0
  226. {straw_queue-0.1.6 → straw_queue-0.1.7}/verification/gc/tla/GCBatchDeletion.cfg +0 -0
  227. {straw_queue-0.1.6 → straw_queue-0.1.7}/verification/gc/tla/GCBatchDeletion.tla +0 -0
  228. {straw_queue-0.1.6 → straw_queue-0.1.7}/verification/gc/tla/GCConcurrentDeletion.cfg +0 -0
  229. {straw_queue-0.1.6 → straw_queue-0.1.7}/verification/gc/tla/GCConcurrentDeletion.tla +0 -0
  230. {straw_queue-0.1.6 → straw_queue-0.1.7}/verification/gc/tla/GCDeletion.cfg +0 -0
  231. {straw_queue-0.1.6 → straw_queue-0.1.7}/verification/gc/tla/GCDeletion.tla +0 -0
  232. {straw_queue-0.1.6 → straw_queue-0.1.7}/verification/gc/tla/GCDiscovery.cfg +0 -0
  233. {straw_queue-0.1.6 → straw_queue-0.1.7}/verification/gc/tla/GCDiscovery.tla +0 -0
  234. {straw_queue-0.1.6 → straw_queue-0.1.7}/verification/gc/tla/GCParentRepair.cfg +0 -0
  235. {straw_queue-0.1.6 → straw_queue-0.1.7}/verification/gc/tla/GCParentRepair.tla +0 -0
  236. {straw_queue-0.1.6 → straw_queue-0.1.7}/verification/gc/tla/GCReceipt.cfg +0 -0
  237. {straw_queue-0.1.6 → straw_queue-0.1.7}/verification/gc/tla/GCReceipt.tla +0 -0
  238. {straw_queue-0.1.6 → straw_queue-0.1.7}/verification/gc/tla/WriterLifetime.cfg +0 -0
  239. {straw_queue-0.1.6 → straw_queue-0.1.7}/verification/gc/tla/WriterLifetime.tla +0 -0
  240. {straw_queue-0.1.6 → straw_queue-0.1.7}/verification/gc/tla/WriterRetirement.cfg +0 -0
  241. {straw_queue-0.1.6 → straw_queue-0.1.7}/verification/gc/tla/WriterRetirement.tla +0 -0
  242. {straw_queue-0.1.6 → straw_queue-0.1.7}/verification/measurements/20261026-release-100gb.json +0 -0
  243. {straw_queue-0.1.6 → straw_queue-0.1.7}/verification/measurements/20261026-release-comparison.json +0 -0
  244. {straw_queue-0.1.6 → straw_queue-0.1.7}/verification/measurements/20261026-release-visibility.json +0 -0
  245. {straw_queue-0.1.6 → straw_queue-0.1.7}/verification/offline/README.md +0 -0
  246. {straw_queue-0.1.6 → straw_queue-0.1.7}/verification/offline/probes/offline_alias_probe.py +0 -0
  247. {straw_queue-0.1.6 → straw_queue-0.1.7}/verification/offline/probes/offline_guard_fault.c +0 -0
  248. {straw_queue-0.1.6 → straw_queue-0.1.7}/verification/offline/probes/offline_guard_probe.py +0 -0
  249. {straw_queue-0.1.6 → straw_queue-0.1.7}/verification/offline/tla/EnvironmentBindings.tla +0 -0
  250. {straw_queue-0.1.6 → straw_queue-0.1.7}/verification/offline/tla/EnvironmentOffline.tla +0 -0
  251. {straw_queue-0.1.6 → straw_queue-0.1.7}/verification/offline/tla/OfflineAliases.cfg +0 -0
  252. {straw_queue-0.1.6 → straw_queue-0.1.7}/verification/offline/tla/OfflineAliases.tla +0 -0
  253. {straw_queue-0.1.6 → straw_queue-0.1.7}/verification/offline/tla/OfflineCleanup.cfg +0 -0
  254. {straw_queue-0.1.6 → straw_queue-0.1.7}/verification/offline/tla/OfflineCleanup.tla +0 -0
  255. {straw_queue-0.1.6 → straw_queue-0.1.7}/verification/offline/tla/OfflineRoots.cfg +0 -0
  256. {straw_queue-0.1.6 → straw_queue-0.1.7}/verification/offline/tla/OfflineRoots.tla +0 -0
  257. {straw_queue-0.1.6 → straw_queue-0.1.7}/verification/protocol/README.md +0 -0
  258. {straw_queue-0.1.6 → straw_queue-0.1.7}/verification/protocol/checks/ownership_model.py +0 -0
  259. {straw_queue-0.1.6 → straw_queue-0.1.7}/verification/protocol/probes/commit_cleanup_probe.py +0 -0
  260. {straw_queue-0.1.6 → straw_queue-0.1.7}/verification/protocol/probes/consumption_probe.py +0 -0
  261. {straw_queue-0.1.6 → straw_queue-0.1.7}/verification/protocol/probes/handoff_extent_probe.rs +0 -0
  262. {straw_queue-0.1.6 → straw_queue-0.1.7}/verification/protocol/probes/handoff_probe.py +0 -0
  263. {straw_queue-0.1.6 → straw_queue-0.1.7}/verification/protocol/probes/lease_selection_probe.py +0 -0
  264. {straw_queue-0.1.6 → straw_queue-0.1.7}/verification/protocol/probes/provisional_hold_probe.py +0 -0
  265. {straw_queue-0.1.6 → straw_queue-0.1.7}/verification/protocol/probes/queue_record_probe.rs +0 -0
  266. {straw_queue-0.1.6 → straw_queue-0.1.7}/verification/protocol/probes/reactivation_peer_probe.py +0 -0
  267. {straw_queue-0.1.6 → straw_queue-0.1.7}/verification/protocol/probes/reactivation_probe.rs +0 -0
  268. {straw_queue-0.1.6 → straw_queue-0.1.7}/verification/protocol/probes/workflow_extent_probe.rs +0 -0
  269. {straw_queue-0.1.6 → straw_queue-0.1.7}/verification/protocol/tla/CommitApplication.cfg +0 -0
  270. {straw_queue-0.1.6 → straw_queue-0.1.7}/verification/protocol/tla/CommitApplication.tla +0 -0
  271. {straw_queue-0.1.6 → straw_queue-0.1.7}/verification/protocol/tla/CommitCleanup.cfg +0 -0
  272. {straw_queue-0.1.6 → straw_queue-0.1.7}/verification/protocol/tla/CommitCleanup.tla +0 -0
  273. {straw_queue-0.1.6 → straw_queue-0.1.7}/verification/protocol/tla/Completion.cfg +0 -0
  274. {straw_queue-0.1.6 → straw_queue-0.1.7}/verification/protocol/tla/Completion.tla +0 -0
  275. {straw_queue-0.1.6 → straw_queue-0.1.7}/verification/protocol/tla/CrossLogComposition.cfg +0 -0
  276. {straw_queue-0.1.6 → straw_queue-0.1.7}/verification/protocol/tla/CrossLogComposition.tla +0 -0
  277. {straw_queue-0.1.6 → straw_queue-0.1.7}/verification/protocol/tla/DurableHandoff.cfg +0 -0
  278. {straw_queue-0.1.6 → straw_queue-0.1.7}/verification/protocol/tla/DurableHandoff.tla +0 -0
  279. {straw_queue-0.1.6 → straw_queue-0.1.7}/verification/protocol/tla/EnvironmentApplication.tla +0 -0
  280. {straw_queue-0.1.6 → straw_queue-0.1.7}/verification/protocol/tla/EnvironmentClock.tla +0 -0
  281. {straw_queue-0.1.6 → straw_queue-0.1.7}/verification/protocol/tla/EnvironmentCommitCleanup.tla +0 -0
  282. {straw_queue-0.1.6 → straw_queue-0.1.7}/verification/protocol/tla/EnvironmentConsumption.tla +0 -0
  283. {straw_queue-0.1.6 → straw_queue-0.1.7}/verification/protocol/tla/EnvironmentCrossComposition.tla +0 -0
  284. {straw_queue-0.1.6 → straw_queue-0.1.7}/verification/protocol/tla/EnvironmentCrossLog.tla +0 -0
  285. {straw_queue-0.1.6 → straw_queue-0.1.7}/verification/protocol/tla/EnvironmentHandoff.tla +0 -0
  286. {straw_queue-0.1.6 → straw_queue-0.1.7}/verification/protocol/tla/EnvironmentReaders.tla +0 -0
  287. {straw_queue-0.1.6 → straw_queue-0.1.7}/verification/protocol/tla/EnvironmentRequest.tla +0 -0
  288. {straw_queue-0.1.6 → straw_queue-0.1.7}/verification/protocol/tla/EnvironmentTraining.tla +0 -0
  289. {straw_queue-0.1.6 → straw_queue-0.1.7}/verification/protocol/tla/Ownership.cfg +0 -0
  290. {straw_queue-0.1.6 → straw_queue-0.1.7}/verification/protocol/tla/Ownership.tla +0 -0
  291. {straw_queue-0.1.6 → straw_queue-0.1.7}/verification/protocol/tla/ProvisionalHold.cfg +0 -0
  292. {straw_queue-0.1.6 → straw_queue-0.1.7}/verification/protocol/tla/ProvisionalHold.tla +0 -0
  293. {straw_queue-0.1.6 → straw_queue-0.1.7}/verification/protocol/tla/PublicationHandoff.cfg +0 -0
  294. {straw_queue-0.1.6 → straw_queue-0.1.7}/verification/protocol/tla/PublicationHandoff.tla +0 -0
  295. {straw_queue-0.1.6 → straw_queue-0.1.7}/verification/protocol/tla/QueueRecordWorkflow.cfg +0 -0
  296. {straw_queue-0.1.6 → straw_queue-0.1.7}/verification/protocol/tla/QueueRecordWorkflow.tla +0 -0
  297. {straw_queue-0.1.6 → straw_queue-0.1.7}/verification/protocol/tla/ReactivationRace.cfg +0 -0
  298. {straw_queue-0.1.6 → straw_queue-0.1.7}/verification/protocol/tla/ReactivationRace.tla +0 -0
  299. {straw_queue-0.1.6 → straw_queue-0.1.7}/verification/protocol/tla/ReactivationScan.cfg +0 -0
  300. {straw_queue-0.1.6 → straw_queue-0.1.7}/verification/protocol/tla/ReactivationScan.tla +0 -0
  301. {straw_queue-0.1.6 → straw_queue-0.1.7}/verification/protocol/tla/RequestReplay.cfg +0 -0
  302. {straw_queue-0.1.6 → straw_queue-0.1.7}/verification/protocol/tla/RequestReplay.tla +0 -0
  303. {straw_queue-0.1.6 → straw_queue-0.1.7}/verification/protocol/tla/SharedRecordWorkflow.cfg +0 -0
  304. {straw_queue-0.1.6 → straw_queue-0.1.7}/verification/protocol/tla/SharedRecordWorkflow.tla +0 -0
  305. {straw_queue-0.1.6 → straw_queue-0.1.7}/verification/protocol/tla/StagingConsumption.cfg +0 -0
  306. {straw_queue-0.1.6 → straw_queue-0.1.7}/verification/protocol/tla/StagingConsumption.tla +0 -0
  307. {straw_queue-0.1.6 → straw_queue-0.1.7}/verification/protocol/tla/TrainingResume.cfg +0 -0
  308. {straw_queue-0.1.6 → straw_queue-0.1.7}/verification/protocol/tla/TrainingResume.tla +0 -0
  309. {straw_queue-0.1.6 → straw_queue-0.1.7}/verification/runners/check_mutations.py +0 -0
  310. {straw_queue-0.1.6 → straw_queue-0.1.7}/verification/runners/check_tla.py +0 -0
  311. {straw_queue-0.1.6 → straw_queue-0.1.7}/verification/runners/environment_manifest.py +0 -0
  312. {straw_queue-0.1.6 → straw_queue-0.1.7}/verification/storage/README.md +0 -0
  313. {straw_queue-0.1.6 → straw_queue-0.1.7}/verification/storage/probes/catalog_encoding_probe.py +0 -0
  314. {straw_queue-0.1.6 → straw_queue-0.1.7}/verification/storage/probes/directory_sync_fault.c +0 -0
  315. {straw_queue-0.1.6 → straw_queue-0.1.7}/verification/storage/probes/directory_sync_probe.py +0 -0
  316. {straw_queue-0.1.6 → straw_queue-0.1.7}/verification/storage/probes/extent_visibility_probe.py +0 -0
  317. {straw_queue-0.1.6 → straw_queue-0.1.7}/verification/storage/probes/filesystem_bandwidth_probe.py +0 -0
  318. {straw_queue-0.1.6 → straw_queue-0.1.7}/verification/storage/probes/incomplete_cleanup_fault.c +0 -0
  319. {straw_queue-0.1.6 → straw_queue-0.1.7}/verification/storage/probes/incomplete_publication_probe.py +0 -0
  320. {straw_queue-0.1.6 → straw_queue-0.1.7}/verification/storage/probes/large_extent_probe.rs +0 -0
  321. {straw_queue-0.1.6 → straw_queue-0.1.7}/verification/storage/probes/metadata_scaling.py +0 -0
  322. {straw_queue-0.1.6 → straw_queue-0.1.7}/verification/storage/probes/namespace_lookup_count.c +0 -0
  323. {straw_queue-0.1.6 → straw_queue-0.1.7}/verification/storage/probes/path_identity_probe.py +0 -0
  324. {straw_queue-0.1.6 → straw_queue-0.1.7}/verification/storage/probes/pending_publication_probe.py +0 -0
  325. {straw_queue-0.1.6 → straw_queue-0.1.7}/verification/storage/probes/positioned_extent_probe.rs +0 -0
  326. {straw_queue-0.1.6 → straw_queue-0.1.7}/verification/storage/probes/preparation_fault.c +0 -0
  327. {straw_queue-0.1.6 → straw_queue-0.1.7}/verification/storage/probes/preparation_probe.py +0 -0
  328. {straw_queue-0.1.6 → straw_queue-0.1.7}/verification/storage/probes/publication_finalize_probe.py +0 -0
  329. {straw_queue-0.1.6 → straw_queue-0.1.7}/verification/storage/probes/publication_retry_probe.py +0 -0
  330. {straw_queue-0.1.6 → straw_queue-0.1.7}/verification/storage/probes/publication_sync_fault.c +0 -0
  331. {straw_queue-0.1.6 → straw_queue-0.1.7}/verification/storage/probes/read_latency_probe.py +0 -0
  332. {straw_queue-0.1.6 → straw_queue-0.1.7}/verification/storage/probes/read_latency_trace.c +0 -0
  333. {straw_queue-0.1.6 → straw_queue-0.1.7}/verification/storage/probes/read_lookup_fault.c +0 -0
  334. {straw_queue-0.1.6 → straw_queue-0.1.7}/verification/storage/probes/read_lookup_probe.py +0 -0
  335. {straw_queue-0.1.6 → straw_queue-0.1.7}/verification/storage/probes/standalone_extent_probe.rs +0 -0
  336. {straw_queue-0.1.6 → straw_queue-0.1.7}/verification/storage/probes/tensor_granularity_probe.py +0 -0
  337. {straw_queue-0.1.6 → straw_queue-0.1.7}/verification/storage/probes/typed_preflight_probe.py +0 -0
  338. {straw_queue-0.1.6 → straw_queue-0.1.7}/verification/storage/probes/writer_access_probe.py +0 -0
  339. {straw_queue-0.1.6 → straw_queue-0.1.7}/verification/storage/probes/writer_lifetime_probe.py +0 -0
  340. {straw_queue-0.1.6 → straw_queue-0.1.7}/verification/storage/tla/DependencyTraversal.cfg +0 -0
  341. {straw_queue-0.1.6 → straw_queue-0.1.7}/verification/storage/tla/DependencyTraversal.tla +0 -0
  342. {straw_queue-0.1.6 → straw_queue-0.1.7}/verification/storage/tla/DirectoryDurability.cfg +0 -0
  343. {straw_queue-0.1.6 → straw_queue-0.1.7}/verification/storage/tla/DirectoryDurability.tla +0 -0
  344. {straw_queue-0.1.6 → straw_queue-0.1.7}/verification/storage/tla/EnvironmentAuthentication.tla +0 -0
  345. {straw_queue-0.1.6 → straw_queue-0.1.7}/verification/storage/tla/EnvironmentIncomplete.tla +0 -0
  346. {straw_queue-0.1.6 → straw_queue-0.1.7}/verification/storage/tla/EnvironmentLocalAccess.tla +0 -0
  347. {straw_queue-0.1.6 → straw_queue-0.1.7}/verification/storage/tla/EnvironmentLookup.tla +0 -0
  348. {straw_queue-0.1.6 → straw_queue-0.1.7}/verification/storage/tla/EnvironmentPreparation.tla +0 -0
  349. {straw_queue-0.1.6 → straw_queue-0.1.7}/verification/storage/tla/EnvironmentTyped.tla +0 -0
  350. {straw_queue-0.1.6 → straw_queue-0.1.7}/verification/storage/tla/EnvironmentVisibility.tla +0 -0
  351. {straw_queue-0.1.6 → straw_queue-0.1.7}/verification/storage/tla/ExtentVisibility.cfg +0 -0
  352. {straw_queue-0.1.6 → straw_queue-0.1.7}/verification/storage/tla/ExtentVisibility.tla +0 -0
  353. {straw_queue-0.1.6 → straw_queue-0.1.7}/verification/storage/tla/IncompletePublication.cfg +0 -0
  354. {straw_queue-0.1.6 → straw_queue-0.1.7}/verification/storage/tla/IncompletePublication.tla +0 -0
  355. {straw_queue-0.1.6 → straw_queue-0.1.7}/verification/storage/tla/NamespaceIdentity.cfg +0 -0
  356. {straw_queue-0.1.6 → straw_queue-0.1.7}/verification/storage/tla/NamespaceIdentity.tla +0 -0
  357. {straw_queue-0.1.6 → straw_queue-0.1.7}/verification/storage/tla/PendingPublication.cfg +0 -0
  358. {straw_queue-0.1.6 → straw_queue-0.1.7}/verification/storage/tla/PendingPublication.tla +0 -0
  359. {straw_queue-0.1.6 → straw_queue-0.1.7}/verification/storage/tla/PublicationFinalization.cfg +0 -0
  360. {straw_queue-0.1.6 → straw_queue-0.1.7}/verification/storage/tla/PublicationFinalization.tla +0 -0
  361. {straw_queue-0.1.6 → straw_queue-0.1.7}/verification/storage/tla/PublicationPreparation.cfg +0 -0
  362. {straw_queue-0.1.6 → straw_queue-0.1.7}/verification/storage/tla/PublicationPreparation.tla +0 -0
  363. {straw_queue-0.1.6 → straw_queue-0.1.7}/verification/storage/tla/PublicationRetry.cfg +0 -0
  364. {straw_queue-0.1.6 → straw_queue-0.1.7}/verification/storage/tla/PublicationRetry.tla +0 -0
  365. {straw_queue-0.1.6 → straw_queue-0.1.7}/verification/storage/tla/RangeRead.cfg +0 -0
  366. {straw_queue-0.1.6 → straw_queue-0.1.7}/verification/storage/tla/RangeRead.tla +0 -0
  367. {straw_queue-0.1.6 → straw_queue-0.1.7}/verification/storage/tla/ReadAttempt.cfg +0 -0
  368. {straw_queue-0.1.6 → straw_queue-0.1.7}/verification/storage/tla/ReadAttempt.tla +0 -0
  369. {straw_queue-0.1.6 → straw_queue-0.1.7}/verification/storage/tla/ReadLookup.cfg +0 -0
  370. {straw_queue-0.1.6 → straw_queue-0.1.7}/verification/storage/tla/ReadLookup.tla +0 -0
  371. {straw_queue-0.1.6 → straw_queue-0.1.7}/verification/storage/tla/TypedRead.cfg +0 -0
  372. {straw_queue-0.1.6 → straw_queue-0.1.7}/verification/storage/tla/TypedRead.tla +0 -0
  373. {straw_queue-0.1.6 → straw_queue-0.1.7}/verification/storage/tla/WriterAccess.cfg +0 -0
  374. {straw_queue-0.1.6 → straw_queue-0.1.7}/verification/storage/tla/WriterAccess.tla +0 -0
  375. {straw_queue-0.1.6 → straw_queue-0.1.7}/verification/wal/README.md +0 -0
  376. {straw_queue-0.1.6 → straw_queue-0.1.7}/verification/wal/checks/crash_campaign.py +0 -0
  377. {straw_queue-0.1.6 → straw_queue-0.1.7}/verification/wal/probes/catalog_fsync_fault.c +0 -0
  378. {straw_queue-0.1.6 → straw_queue-0.1.7}/verification/wal/probes/catalog_history_probe.py +0 -0
  379. {straw_queue-0.1.6 → straw_queue-0.1.7}/verification/wal/probes/catalog_replay_probe.py +0 -0
  380. {straw_queue-0.1.6 → straw_queue-0.1.7}/verification/wal/tla/CatalogReadBuffer.cfg +0 -0
  381. {straw_queue-0.1.6 → straw_queue-0.1.7}/verification/wal/tla/CatalogReadBuffer.tla +0 -0
  382. {straw_queue-0.1.6 → straw_queue-0.1.7}/verification/wal/tla/CatalogReplay.cfg +0 -0
  383. {straw_queue-0.1.6 → straw_queue-0.1.7}/verification/wal/tla/CatalogReplay.tla +0 -0
  384. {straw_queue-0.1.6 → straw_queue-0.1.7}/verification/wal/tla/CatalogTransaction.cfg +0 -0
  385. {straw_queue-0.1.6 → straw_queue-0.1.7}/verification/wal/tla/CatalogTransaction.tla +0 -0
  386. {straw_queue-0.1.6 → straw_queue-0.1.7}/verification/wal/tla/EnvironmentWal.tla +0 -0
  387. {straw_queue-0.1.6 → straw_queue-0.1.7}/verification/wal/tla/WalRecovery.cfg +0 -0
  388. {straw_queue-0.1.6 → straw_queue-0.1.7}/verification/wal/tla/WalRecovery.tla +0 -0
@@ -2,6 +2,40 @@
2
2
 
3
3
  [中文版](CHANGELOG_zh.md)
4
4
 
5
+ ## 0.1.7
6
+
7
+ ### Batched reads and validation
8
+
9
+ - Add `TensorRef.load_many(..., reader=reader, workers=4)` for caller-bounded,
10
+ ordered tensor batches. Native workers reuse extent handles and coalesce nearby
11
+ reads in bounded windows (1 MiB by default, at most 8 MiB per worker), avoiding
12
+ read-ahead across gaps larger than 4 KiB. Each result has independent writable
13
+ storage; typed layout, selected frames and touched checksum chunks remain
14
+ authenticated. Failed attempts discard handles and windows before retrying.
15
+ - Read tensor member envelopes through one native call and reuse canonical path
16
+ information within a publication, reducing Python/native transitions and
17
+ repeated shared-filesystem path resolution.
18
+ - Add `store.validation_scope(coordinator)` to reuse immutable dependency proofs
19
+ during one local publication/queue handoff. New roots still check descriptors
20
+ and task/attempt identity; catalog changes still check ownership, namespace
21
+ and tombstones under lock. Scopes are thread-local, do not pin data, and close
22
+ on exit or participating errors. Explicit validation and payload reads retain
23
+ their normal checks.
24
+ - Sample the coordinator lease clock after acquiring its call lock, so queued
25
+ calls do not submit stale timestamps. Log slow calls with separate lock-wait
26
+ and operation times.
27
+
28
+ ### Compatibility and limits
29
+
30
+ - Existing Python call signatures and stored WAL/packed-record formats remain
31
+ compatible; the new batch and scope APIs require 0.1.7. Keep input owners alive
32
+ throughout reads and validation scopes. Callers must bound the total payload
33
+ bytes returned by a batch; the read-ahead limit only bounds worker scratch.
34
+ - These changes reduce small-read calls and repeated immutable-graph work.
35
+ Throughput depends on request locality, cache state and storage; they do not
36
+ establish a shared-filesystem bandwidth guarantee or change GC durability
37
+ requirements.
38
+
5
39
  ## 0.1.6
6
40
 
7
41
  - Reuse confirmed writer-registry state and index operation lookup; rebuild after uncertain outcomes. Cache only successfully synchronized writer directories with pinned inode identity. Keep existing publication WAL barriers and wire formats.
@@ -2,6 +2,20 @@
2
2
 
3
3
  [English](CHANGELOG.md)
4
4
 
5
+ ## 0.1.7
6
+
7
+ ### 批量读取与校验
8
+
9
+ - 新增 `TensorRef.load_many(..., reader=reader, workers=4)`,按调用方限定的批量大小并行读取 tensor,并保持输入顺序。Native worker 复用 extent 句柄,在有界窗口中合并相邻读取(默认每个 worker 1 MiB,最多 8 MiB),不跨越大于 4 KiB 的空隙预读。每个结果拥有独立可写存储;typed layout、选中的 frame 和触及的 checksum chunk 仍需认证。失败尝试在重试前丢弃句柄和窗口。
10
+ - 通过一次 native 调用读取 tensor 成员 envelope,并在同一 publication 内复用规范路径信息,减少 Python/native 边界调用和共享文件系统路径解析。
11
+ - 新增 `store.validation_scope(coordinator)`,在一次本地 publication/queue 交接中复用不可变依赖证明。新根仍核对 descriptor 和 task/attempt 身份;catalog 变更仍在锁内检查所有权、namespace 和 tombstone。Scope 按线程隔离、不负责 pin 数据,并在退出或参与操作报错时关闭。显式 validate 和 payload 读取保留原有检查。
12
+ - Coordinator 在取得调用锁后才读取 lease 时钟,避免排队调用提交过时的时间戳。慢调用日志分别记录锁等待与实际操作耗时。
13
+
14
+ ### 兼容与限制
15
+
16
+ - 现有 Python 调用签名及已存储 WAL/packed-record 格式保持兼容;新增批量与 scope API 需要 0.1.7。读取和 validation scope 期间仍须保留输入 owner。调用方需限制 batch 返回的 payload 总字节数;预读上限只约束 worker 临时缓冲区。
17
+ - 本版减少小读取调用和重复不可变图处理。吞吐仍取决于请求局部性、缓存状态和存储环境,不构成共享文件系统带宽保证,也不改变 GC 持久化要求。
18
+
5
19
  ## 0.1.6
6
20
 
7
21
  - 复用已确认的 writer registry 状态并为操作查找建立索引;不确定结果后重建。只缓存完整同步成功的 writer 目录,并保持 inode 身份。保留既有 publication WAL 屏障与 wire format。
@@ -370,8 +370,9 @@ checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5"
370
370
 
371
371
  [[package]]
372
372
  name = "straw"
373
- version = "0.1.6"
373
+ version = "0.1.7"
374
374
  dependencies = [
375
+ "libc",
375
376
  "pyo3",
376
377
  "serde",
377
378
  "serde_json",
@@ -1,6 +1,6 @@
1
1
  [package]
2
2
  name = "straw"
3
- version = "0.1.6"
3
+ version = "0.1.7"
4
4
  edition = "2024"
5
5
  rust-version = "1.89"
6
6
  license = "MIT"
@@ -31,6 +31,9 @@ sha2 = "0.10"
31
31
  uuid = { version = "1.23", features = ["v4"] }
32
32
  pyo3 = { version = "0.23.5", optional = true }
33
33
 
34
+ [target.'cfg(target_os = "linux")'.dependencies]
35
+ libc = "0.2"
36
+
34
37
  [dev-dependencies]
35
38
  tempfile = "3.27"
36
39
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: straw-queue
3
- Version: 0.1.6
3
+ Version: 0.1.7
4
4
  Classifier: Development Status :: 3 - Alpha
5
5
  Classifier: Operating System :: POSIX :: Linux
6
6
  Classifier: Programming Language :: Python :: 3
@@ -354,6 +354,26 @@ On recovery, first restore the chosen checkpoint's model/optimizer/RNG and its m
354
354
 
355
355
  ## Scoped batch reads
356
356
 
357
+ `TensorRef.load_many(refs, reader=reader, workers=4)` loads a caller-bounded batch
358
+ in its original order. Bound the total requested payload bytes before calling;
359
+ each returned tensor has independent writable storage. Native workers sort
360
+ requests by pack/extent/ordinal, reuse the extent handle and combine nearby reads
361
+ in a window of at most 1 MiB per worker. Gaps larger than 4 KiB are not prefetched.
362
+ Every selected frame, typed layout and touched checksum chunk is still checked.
363
+ Failed attempts discard both the handle and window before the ordinary bounded
364
+ visibility retry; windows are discarded at batch exit. The lower-level
365
+ `reader.read_tensor_ranges(..., read_ahead_bytes=0)` disables read-ahead for
366
+ comparisons (the maximum supported setting is 8 MiB per worker).
367
+
368
+ For one publish/queue handoff, `with store.validation_scope(coordinator):` reuses
369
+ successful immutable dependency proofs across participating operations in the
370
+ current thread. Each new root still checks its descriptor and task/attempt;
371
+ catalog transfers still check namespace identity, ownership authorization and
372
+ tombstones under the catalog lock. The scope never pins data, never crosses
373
+ storage identity, closes on exit, and is invalidated by any participating error.
374
+ Keep input owners alive throughout it. Explicit `store.validate` and later
375
+ operations still revalidate; the scope does not cache payload read results.
376
+
357
377
  Use one `with store.read_session() as reader:` block for adjacent immutable publications. The reader provides `validate`, `manifest`, `read`, `read_record`, `envelope`, and checked tensor reads. Pass it to `TensorRef.from_record_set_many(store, publication, reader=reader)` and `tensor.load(reader=reader)` to avoid repeatedly parsing a shared extent index.
358
378
 
359
379
  The Rust reader caches up to eight authenticated indexes using an LRU keyed by the complete extent descriptor, with an 8 MiB encoded-metadata budget. A single oversized active index evicts all other entries. Each manifest and record read still authenticates its frame and payload; tensor reads authenticate touched chunks. `validate` rechecks logical descriptors and task/attempt authorization on every call. Index authentication runs again on a cache miss or in a new session. Calls within one session serialize; use independent sessions for parallel reads. Keep a durable owner or `store.pin` for the entire operation: a read session is not an ownership pin. Sessions close on context exit and reject all inherited operations after fork.
@@ -193,6 +193,22 @@ b.submit_tasks("b-1", [TaskSpec("task-b", input_ref=dependency)])
193
193
 
194
194
  ## 批量读取会话
195
195
 
196
+ `TensorRef.load_many(refs, reader=reader, workers=4)` 按原顺序读取调用方限定的批次。
197
+ 调用前应限制请求载荷的总字节数;返回张量各自拥有可写存储。
198
+ Native worker 按 pack/extent/ordinal 排序,复用 extent 句柄,以每个 worker
199
+ 最多 1 MiB 的窗口合并邻近读取,不预读超过 4 KiB 的间隙。
200
+ 每个选中 frame、typed layout 和触及的 checksum chunk 仍逐一检查。
201
+ 读取失败后,先丢弃句柄和窗口,再执行原有有限可见性重试;批次结束也丢弃窗口。
202
+ 底层 `reader.read_tensor_ranges(..., read_ahead_bytes=0)` 可关闭预读用于对照,
203
+ 该参数最大为每个 worker 8 MiB。
204
+
205
+ 单次发布/队列交接可用 `with store.validation_scope(coordinator):`,
206
+ 在当前线程的参与操作之间复用成功的不可变依赖校验证据。
207
+ 新根仍检查描述符和 task/attempt;catalog 转移仍在锁内检查 namespace 身份、
208
+ 所有权授权和 tombstone。Scope 不保留数据所有权,不跨存储身份,退出时关闭,
209
+ 任意参与操作失败立即使其失效。整个操作期间仍须保持输入 owner。
210
+ 显式 `store.validate` 和后续操作仍重新校验;scope 不缓存载荷读取结果。
211
+
196
212
  连续读取不可变 publication 时,可共用一个 `with store.read_session() as reader:`。Reader 提供 `validate`、`manifest`、`read`、`read_record`、`envelope` 和带校验的张量读取。将它传给 `TensorRef.from_record_set_many(store, publication, reader=reader)` 与 `tensor.load(reader=reader)`,可避免重复解析同一 extent 的索引。
197
213
 
198
214
  Rust reader 使用最多八条已认证索引的 LRU,以完整 extent 描述符区分身份,编码元数据预算为 8 MiB;一个超大活动 index 会淘汰其他条目。每次 manifest/record 读取仍校验 frame 和载荷;张量读取仍校验触及的 chunk。每次 `validate` 都重新检查逻辑描述符与 task/attempt 权限。缓存未命中或开启新会话后重新认证索引。同一会话的调用串行,并行读取应使用独立会话。整个读取过程必须由持久 owner 或 `store.pin` 保护:读取会话本身不保留存储所有权。退出上下文会关闭会话,fork 后继承的会话拒绝所有操作。
@@ -4,7 +4,7 @@ build-backend = "maturin"
4
4
 
5
5
  [project]
6
6
  name = "straw-queue"
7
- version = "0.1.6"
7
+ version = "0.1.7"
8
8
  description = "Rust durable queues for AI tensors and large immutable records"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.10"
@@ -1,7 +1,7 @@
1
1
  //! Single-owner durable scheduling and accepted-result state machine.
2
2
  use crate::journal::Journal;
3
3
  use crate::queue_state;
4
- use crate::store::{Config, Reader, Record, Store, mkdir, sync, sync_dir};
4
+ use crate::store::{Config, GraphProof, Reader, Record, Store, mkdir, sync, sync_dir};
5
5
  use crate::{Error, Fault, Result, array, bytes, checked_sum, digest, fail, field, number, uid};
6
6
  use serde_json::{Value, json};
7
7
  use std::{
@@ -96,12 +96,13 @@ fn retain_commit(
96
96
  roots: &[(String, Vec<Value>)],
97
97
  storage_failed: &mut bool,
98
98
  fault: &mut Fault<'_>,
99
+ graph: Option<&GraphProof>,
99
100
  ) -> Result<()> {
100
101
  let retained = (|| {
101
102
  let verified = config.verify_queue_reactivation(storage_prefix, reactivated, fault)?;
102
103
  config.catalog(|catalog| {
103
104
  catalog.retain_queue_verified(config, storage_prefix, &verified, fault)?;
104
- catalog.retain_queue_many(config, storage_prefix, roots, fault)
105
+ catalog.retain_queue_many_with_graph(config, storage_prefix, roots, graph, fault)
105
106
  })
106
107
  })();
107
108
  if retained
@@ -500,7 +501,15 @@ impl Coordinator {
500
501
  result.recovery_seconds = started.elapsed().as_secs_f64();
501
502
  Ok(result)
502
503
  }
503
- fn commit(&mut self, mut events: Value, fault: &mut Fault<'_>) -> Result<()> {
504
+ fn commit(&mut self, events: Value, fault: &mut Fault<'_>) -> Result<()> {
505
+ self.commit_with_graph(events, fault, None)
506
+ }
507
+ fn commit_with_graph(
508
+ &mut self,
509
+ mut events: Value,
510
+ fault: &mut Fault<'_>,
511
+ graph: Option<&GraphProof>,
512
+ ) -> Result<()> {
504
513
  // No newer commit/GC may abandon the owner that protects an unfinished
505
514
  // staging handoff. Recovery also reaches this barrier before its epoch.
506
515
  self.finish_consumption(fault)?;
@@ -549,6 +558,7 @@ impl Coordinator {
549
558
  &roots,
550
559
  &mut self.storage_failed,
551
560
  fault,
561
+ graph,
552
562
  )?;
553
563
  crate::queue_commit::persist_and_apply::<_, crate::wal_file::NativeLibrary, _, _>(
554
564
  &mut self.journal,
@@ -570,7 +580,13 @@ impl Coordinator {
570
580
  )
571
581
  .map_err(|error| commit_error(error, &events))?;
572
582
  fault("before_staging_consume")?;
573
- self.finish_consumption(fault)
583
+ finish_consumption_with_graph(
584
+ &self.store.config,
585
+ &self.storage_prefix,
586
+ &mut self.pending_consumption,
587
+ fault,
588
+ graph,
589
+ )
574
590
  }
575
591
  fn finish_consumption(&mut self, fault: &mut Fault<'_>) -> Result<()> {
576
592
  finish_consumption(
@@ -641,16 +657,19 @@ impl Coordinator {
641
657
  fn count(&mut self, key: &str) {
642
658
  self.counters[key] = json!(number(&self.counters, key) + 1);
643
659
  }
644
- fn validate(
660
+ fn validate_graph(
645
661
  &mut self,
646
662
  reference: &Value,
647
663
  task: Option<&str>,
648
664
  attempt: Option<&str>,
665
+ graph: &mut GraphProof,
649
666
  ) -> Result<Vec<Value>> {
650
- let result = self.store.config.validate(reference, task, attempt);
667
+ let mut reader = Reader::new(self.store.config.clone());
668
+ let result =
669
+ reader.validate_with_graph(reference, task, attempt, &mut graph.validated(), graph);
651
670
  if result
652
671
  .as_ref()
653
- .is_err_and(|e| e.kind == "StorageUnavailable")
672
+ .is_err_and(|error| error.kind == "StorageUnavailable")
654
673
  {
655
674
  self.storage_failed = true;
656
675
  }
@@ -677,6 +696,19 @@ impl Coordinator {
677
696
  &mut self.progress_cache,
678
697
  &mut ProgressReader {
679
698
  config: &self.store.config,
699
+ validated_members: None,
700
+ storage_failed: &mut self.storage_failed,
701
+ },
702
+ reference,
703
+ )
704
+ .map_err(progress_error)
705
+ }
706
+ fn progress_from_members(&mut self, reference: &Value, members: &[Value]) -> Result<Value> {
707
+ crate::queue_progress::load(
708
+ &mut self.progress_cache,
709
+ &mut ProgressReader {
710
+ config: &self.store.config,
711
+ validated_members: Some(members),
680
712
  storage_failed: &mut self.storage_failed,
681
713
  },
682
714
  reference,
@@ -769,11 +801,11 @@ impl Coordinator {
769
801
  }
770
802
  Ok(state)
771
803
  }
772
- fn validate_consumer_state(&mut self, state: &Value) -> Result<()> {
773
- self.validate(&state["state_ref"], None, None)?;
804
+ fn validate_consumer_state(&mut self, state: &Value, graph: &mut GraphProof) -> Result<()> {
805
+ self.validate_graph(&state["state_ref"], None, None, graph)?;
774
806
  if !state["progress_ref"].is_null() {
775
- self.validate(&state["progress_ref"], None, None)?;
776
- let progress = self.progress(&state["progress_ref"])?;
807
+ let members = self.validate_graph(&state["progress_ref"], None, None, graph)?;
808
+ let progress = self.progress_from_members(&state["progress_ref"], &members)?;
777
809
  let processed = number(state, "processed_cursor");
778
810
  let fetched = number(state, "fetch_cursor");
779
811
  if array(&progress, "processed_positions")?
@@ -798,6 +830,19 @@ impl Coordinator {
798
830
  now: f64,
799
831
  fault: &mut Fault<'_>,
800
832
  ) -> Result<Value> {
833
+ self.call_with_graph(method, args, now, fault, None)
834
+ }
835
+ pub(crate) fn call_with_graph(
836
+ &mut self,
837
+ method: &str,
838
+ args: &Value,
839
+ now: f64,
840
+ fault: &mut Fault<'_>,
841
+ graph: Option<&mut GraphProof>,
842
+ ) -> Result<Value> {
843
+ let mut local_graph = GraphProof::new(&self.store.config);
844
+ let graph = graph.unwrap_or(&mut local_graph);
845
+ graph.check_storage(&self.store.config)?;
801
846
  if !crate::queue_application::permitted(&self.journal, self.journal.closed(), method) {
802
847
  return fail(
803
848
  "UnsafeRecovery",
@@ -815,15 +860,16 @@ impl Coordinator {
815
860
  return fail("StaleAttempt", "Reader lease identity mismatch");
816
861
  }
817
862
  }
818
- self.commit(
863
+ self.commit_with_graph(
819
864
  json!([{"type":"ReaderDone","leases":args["leases"]}]),
820
865
  fault,
866
+ Some(graph),
821
867
  )?;
822
868
  Ok(Value::Null)
823
869
  }
824
870
  "collect_garbage" => self.collect_garbage(fault),
825
871
  "release_checkpoint" => {
826
- self.commit(json!([{"type":"CheckpointReleased","checkpoint_id":field(args,"checkpoint_id")?}]), fault)?;
872
+ self.commit_with_graph(json!([{"type":"CheckpointReleased","checkpoint_id":field(args,"checkpoint_id")?}]), fault, Some(graph))?;
827
873
  Ok(Value::Null)
828
874
  }
829
875
  "submit_tasks" => {
@@ -874,11 +920,11 @@ impl Coordinator {
874
920
  };
875
921
  }
876
922
  if !t["input_ref"].is_null() {
877
- self.validate(&t["input_ref"], None, None)?;
923
+ self.validate_graph(&t["input_ref"], None, None, graph)?;
878
924
  }
879
925
  ids.push(json!(id));
880
926
  }
881
- self.commit(json!([Self::event("Submitted",&request,json!(ids),json!({"tasks":tasks,"producer_id":producer,"producer_state":args["producer_state"]}))]),fault)?;
927
+ self.commit_with_graph(json!([Self::event("Submitted",&request,json!(ids),json!({"tasks":tasks,"producer_id":producer,"producer_state":args["producer_state"]}))]),fault, Some(graph))?;
882
928
  Ok(json!(ids))
883
929
  }
884
930
  "acquire" => {
@@ -894,7 +940,11 @@ impl Coordinator {
894
940
  .map(|(id, _)| json!(id))
895
941
  .collect::<Vec<_>>();
896
942
  if !expired.is_empty() {
897
- self.commit(json!([{"type":"Expired","task_ids":expired}]), fault)?;
943
+ self.commit_with_graph(
944
+ json!([{"type":"Expired","task_ids":expired}]),
945
+ fault,
946
+ Some(graph),
947
+ )?;
898
948
  self.counters["expired_leases"] =
899
949
  json!(number(&self.counters, "expired_leases") + expired.len() as u64);
900
950
  }
@@ -963,7 +1013,11 @@ impl Coordinator {
963
1013
  .iter()
964
1014
  .map(|a| a["lease"].clone())
965
1015
  .collect::<Vec<_>>();
966
- self.commit(json!([{"type":"Leased","leases":leases}]), fault)?;
1016
+ self.commit_with_graph(
1017
+ json!([{"type":"Leased","leases":leases}]),
1018
+ fault,
1019
+ Some(graph),
1020
+ )?;
967
1021
  for lease in leases {
968
1022
  self.deadlines
969
1023
  .insert(field(&lease, "task_id")?.into(), now + self.lease_seconds);
@@ -1027,7 +1081,7 @@ impl Coordinator {
1027
1081
  last["request_digest"] = json!(request.1);
1028
1082
  let response = json!(if yielding { "pending" } else { "saved" });
1029
1083
  last["response"] = response.clone();
1030
- self.commit(json!(events), fault)?;
1084
+ self.commit_with_graph(json!(events), fault, Some(graph))?;
1031
1085
  Ok(response)
1032
1086
  }
1033
1087
  "release_tasks" => {
@@ -1062,7 +1116,7 @@ impl Coordinator {
1062
1116
  last["request_key"] = json!(request.0);
1063
1117
  last["request_digest"] = json!(request.1);
1064
1118
  last["response"] = json!(response);
1065
- self.commit(json!(events), fault)?;
1119
+ self.commit_with_graph(json!(events), fault, Some(graph))?;
1066
1120
  }
1067
1121
  Ok(json!(response))
1068
1122
  }
@@ -1115,15 +1169,17 @@ impl Coordinator {
1115
1169
  if number(reference, "records") == 0 && !boolean(&task["spec"], "allow_empty") {
1116
1170
  return fail("InvalidReference", "Task does not allow empty output");
1117
1171
  }
1118
- self.validate(
1172
+ self.validate_graph(
1119
1173
  reference,
1120
1174
  Some(field(lease, "task_id")?),
1121
1175
  Some(field(lease, "attempt_id")?),
1176
+ graph,
1122
1177
  )?;
1123
1178
  let receipt = json!({"commit_id":uid(),"task_id":lease["task_id"],"submission_id":id,"digest":content,"position":array(&self.state,"commits")?.len(),"result_ref":reference});
1124
- self.commit(
1179
+ self.commit_with_graph(
1125
1180
  json!([{"type":"Completed","receipt":receipt,"lease":lease}]),
1126
1181
  fault,
1182
+ Some(graph),
1127
1183
  )?;
1128
1184
  fault("before_complete_reply")?;
1129
1185
  self.complete_seconds.push(started.elapsed().as_secs_f64());
@@ -1149,7 +1205,7 @@ impl Coordinator {
1149
1205
  } else {
1150
1206
  "failed"
1151
1207
  });
1152
- self.commit(json!([Self::event("Failed",&request,response.clone(),json!({"task_ids":[lease["task_id"]],"failure":failure,"retryable":retryable}))]),fault)?;
1208
+ self.commit_with_graph(json!([Self::event("Failed",&request,response.clone(),json!({"task_ids":[lease["task_id"]],"failure":failure,"retryable":retryable}))]),fault, Some(graph))?;
1153
1209
  if matches!(
1154
1210
  failure["category"].as_str(),
1155
1211
  Some("QuotaExceeded" | "StorageUnavailable")
@@ -1173,9 +1229,9 @@ impl Coordinator {
1173
1229
  if yielding && !crate::queue_admin::has_capacity(self.next_pending_order, 1) {
1174
1230
  return fail("ValueError", "Queue scheduling order is exhausted");
1175
1231
  }
1176
- self.validate(&args["input_ref"], None, None)?;
1232
+ self.validate_graph(&args["input_ref"], None, None, graph)?;
1177
1233
  let response = json!(if yielding { "pending" } else { "saved" });
1178
- self.commit(
1234
+ self.commit_with_graph(
1179
1235
  json!([Self::event(
1180
1236
  if yielding { "Yielded" } else { "TaskProgress" },
1181
1237
  &request,
@@ -1183,6 +1239,7 @@ impl Coordinator {
1183
1239
  json!({"task_id":args["lease"]["task_id"],"input_ref":args["input_ref"]})
1184
1240
  )]),
1185
1241
  fault,
1242
+ Some(graph),
1186
1243
  )?;
1187
1244
  Ok(response)
1188
1245
  }
@@ -1195,7 +1252,7 @@ impl Coordinator {
1195
1252
  if terminal(&self.state["tasks"][id]["state"]) {
1196
1253
  return fail("ValueError", "Cannot cancel terminal task");
1197
1254
  };
1198
- self.commit(
1255
+ self.commit_with_graph(
1199
1256
  json!([Self::event(
1200
1257
  "Cancelled",
1201
1258
  &request,
@@ -1203,15 +1260,17 @@ impl Coordinator {
1203
1260
  json!({"task_id":id})
1204
1261
  )]),
1205
1262
  fault,
1263
+ Some(graph),
1206
1264
  )?;
1207
1265
  Ok(json!("cancelled"))
1208
1266
  }
1209
1267
  "seal_input" => {
1210
1268
  let request = self.request("seal", field(args, "request_id")?, &Value::Null)?;
1211
1269
  if request.2.is_none() {
1212
- self.commit(
1270
+ self.commit_with_graph(
1213
1271
  json!([Self::event("Sealed", &request, json!("sealed"), json!({}))]),
1214
1272
  fault,
1273
+ Some(graph),
1215
1274
  )?;
1216
1275
  }
1217
1276
  Ok(json!("sealed"))
@@ -1275,15 +1334,20 @@ impl Coordinator {
1275
1334
  match self.call("fail_task", &call, now, fault) {
1276
1335
  Ok(_) => {}
1277
1336
  Err(e) if e.kind == "LeaseExpired" => {
1278
- self.commit(
1337
+ self.commit_with_graph(
1279
1338
  json!([{"type":"Expired","task_ids":[lease["task_id"]]}]),
1280
1339
  fault,
1340
+ Some(graph),
1281
1341
  )?;
1282
1342
  }
1283
1343
  Err(e) => return Err(e),
1284
1344
  }
1285
1345
  }
1286
- self.commit(json!([{"type":"ReaderRetired","worker_id":worker}]), fault)?;
1346
+ self.commit_with_graph(
1347
+ json!([{"type":"ReaderRetired","worker_id":worker}]),
1348
+ fault,
1349
+ Some(graph),
1350
+ )?;
1287
1351
  Ok(json!(array(&self.state,"commits")?.iter().filter(|r|self.state["tasks"][r["task_id"].as_str().unwrap_or("")]["lease"]["worker_id"]==worker).cloned().collect::<Vec<_>>()))
1288
1352
  }
1289
1353
  "open_consumer" => {
@@ -1325,8 +1389,8 @@ impl Coordinator {
1325
1389
  if let Some(response) = request.2 {
1326
1390
  return Ok(response);
1327
1391
  };
1328
- self.validate_consumer_state(&state)?;
1329
- self.commit(
1392
+ self.validate_consumer_state(&state, graph)?;
1393
+ self.commit_with_graph(
1330
1394
  json!([Self::event(
1331
1395
  "ConsumerState",
1332
1396
  &request,
@@ -1334,6 +1398,7 @@ impl Coordinator {
1334
1398
  json!({"consumer_id":id,"state":state})
1335
1399
  )]),
1336
1400
  fault,
1401
+ Some(graph),
1337
1402
  )?;
1338
1403
  Ok(state)
1339
1404
  }
@@ -1357,8 +1422,8 @@ impl Coordinator {
1357
1422
  if request.2.is_some() {
1358
1423
  return Ok(self.state["batches"][batch_id].clone());
1359
1424
  };
1360
- self.validate(&args["plan_ref"], None, None)?;
1361
- self.commit(
1425
+ self.validate_graph(&args["plan_ref"], None, None, graph)?;
1426
+ self.commit_with_graph(
1362
1427
  json!([Self::event(
1363
1428
  "BatchPlanned",
1364
1429
  &request,
@@ -1366,6 +1431,7 @@ impl Coordinator {
1366
1431
  json!({"batch_id":batch_id,"batch":batch})
1367
1432
  )]),
1368
1433
  fault,
1434
+ Some(graph),
1369
1435
  )?;
1370
1436
  Ok(batch)
1371
1437
  }
@@ -1382,9 +1448,9 @@ impl Coordinator {
1382
1448
  if let Some(response) = request.2 {
1383
1449
  return Ok(response);
1384
1450
  };
1385
- self.validate(&args["ready_ref"], None, None)?;
1386
- self.validate_consumer_state(&state)?;
1387
- self.commit(json!([Self::event("BatchReady",&request,content.clone(),json!({"consumer_id":id,"batch_id":batch,"ready_ref":args["ready_ref"],"state":state}))]),fault)?;
1451
+ self.validate_graph(&args["ready_ref"], None, None, graph)?;
1452
+ self.validate_consumer_state(&state, graph)?;
1453
+ self.commit_with_graph(json!([Self::event("BatchReady",&request,content.clone(),json!({"consumer_id":id,"batch_id":batch,"ready_ref":args["ready_ref"],"state":state}))]),fault, Some(graph))?;
1388
1454
  Ok(content)
1389
1455
  }
1390
1456
  "get_batch" => Ok(self.state["batches"][field(args, "batch_id")?].clone()),
@@ -1409,7 +1475,7 @@ impl Coordinator {
1409
1475
  }
1410
1476
  return fail("UnsafeRecovery", "Checkpoint receipt disappeared");
1411
1477
  }
1412
- let members = self.validate(reference, None, None)?;
1478
+ let members = self.validate_graph(reference, None, None, graph)?;
1413
1479
  if members.len() != 1 {
1414
1480
  return fail("InvalidReference", "Expected one JSON checkpoint record");
1415
1481
  };
@@ -1421,7 +1487,7 @@ impl Coordinator {
1421
1487
  if checkpoint["version"] != 1 || checkpoint["checkpoint_id"] != id {
1422
1488
  return fail("InvalidReference", "Checkpoint identity/schema mismatch");
1423
1489
  };
1424
- self.validate(&checkpoint["consumer_state"], None, None)?;
1490
+ self.validate_graph(&checkpoint["consumer_state"], None, None, graph)?;
1425
1491
  if array(&checkpoint, "batch_ids")?
1426
1492
  .iter()
1427
1493
  .any(|id| !boolean(&self.state["batches"][id.as_str().unwrap_or("")], "ready"))
@@ -1445,7 +1511,7 @@ impl Coordinator {
1445
1511
  content["checkpoint_ref"] = reference.clone();
1446
1512
  let request = self.request("checkpoint", id, &content)?;
1447
1513
  if request.2.is_none() {
1448
- self.commit(
1514
+ self.commit_with_graph(
1449
1515
  json!([Self::event(
1450
1516
  "Checkpoint",
1451
1517
  &request,
@@ -1453,6 +1519,7 @@ impl Coordinator {
1453
1519
  json!({"checkpoint_id":id,"checkpoint":content})
1454
1520
  )]),
1455
1521
  fault,
1522
+ Some(graph),
1456
1523
  )?;
1457
1524
  }
1458
1525
  Ok(content)
@@ -1582,12 +1649,16 @@ fn recovered_consumption(
1582
1649
 
1583
1650
  struct ProgressReader<'a> {
1584
1651
  config: &'a Config,
1652
+ validated_members: Option<&'a [Value]>,
1585
1653
  storage_failed: &'a mut bool,
1586
1654
  }
1587
1655
  impl crate::queue_progress::Reader for ProgressReader<'_> {
1588
1656
  type Error = Error;
1589
1657
  fn members(&mut self, reference: &Value) -> Result<Vec<Value>> {
1590
- let result = self.config.validate(reference, None, None);
1658
+ let result = match self.validated_members {
1659
+ Some(members) => Ok(members.to_vec()),
1660
+ None => self.config.validate(reference, None, None),
1661
+ };
1591
1662
  if result
1592
1663
  .as_ref()
1593
1664
  .is_err_and(|error| error.kind == "StorageUnavailable")
@@ -1643,6 +1714,7 @@ impl crate::queue_progress::Reader for GcPreflight<'_, '_> {
1643
1714
  crate::queue_progress::Reader::members(
1644
1715
  &mut ProgressReader {
1645
1716
  config: self.config,
1717
+ validated_members: None,
1646
1718
  storage_failed: self.storage_failed,
1647
1719
  },
1648
1720
  reference,
@@ -1652,6 +1724,7 @@ impl crate::queue_progress::Reader for GcPreflight<'_, '_> {
1652
1724
  crate::queue_progress::Reader::read(
1653
1725
  &mut ProgressReader {
1654
1726
  config: self.config,
1727
+ validated_members: None,
1655
1728
  storage_failed: self.storage_failed,
1656
1729
  },
1657
1730
  reference,
@@ -1663,6 +1736,16 @@ fn finish_consumption(
1663
1736
  prefix: &str,
1664
1737
  pending: &mut Vec<(String, Vec<Value>)>,
1665
1738
  fault: &mut Fault<'_>,
1739
+ ) -> Result<()> {
1740
+ finish_consumption_with_graph(config, prefix, pending, fault, None)
1741
+ }
1742
+
1743
+ fn finish_consumption_with_graph(
1744
+ config: &Config,
1745
+ prefix: &str,
1746
+ pending: &mut Vec<(String, Vec<Value>)>,
1747
+ fault: &mut Fault<'_>,
1748
+ graph: Option<&GraphProof>,
1666
1749
  ) -> Result<()> {
1667
1750
  if pending.is_empty() {
1668
1751
  return Ok(());
@@ -1680,7 +1763,7 @@ fn finish_consumption(
1680
1763
  .collect::<Result<HashSet<_>>>()?;
1681
1764
  catalog.require_retained(&owners)?;
1682
1765
  }
1683
- let outcome = catalog.consume_once(config, id, roots, fault);
1766
+ let outcome = catalog.consume_once_with_graph(config, id, roots, graph, fault);
1684
1767
  crate::consumption::pop_completed(pending, outcome.is_ok());
1685
1768
  outcome?;
1686
1769
  }