straw-queue 0.1.5__tar.gz → 0.1.6__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 (382) hide show
  1. {straw_queue-0.1.5 → straw_queue-0.1.6}/.github/workflows/tests.yml +8 -0
  2. {straw_queue-0.1.5 → straw_queue-0.1.6}/CHANGELOG.md +6 -0
  3. {straw_queue-0.1.5 → straw_queue-0.1.6}/CHANGELOG_zh.md +6 -0
  4. {straw_queue-0.1.5 → straw_queue-0.1.6}/CONTRIBUTING.md +7 -0
  5. {straw_queue-0.1.5 → straw_queue-0.1.6}/CONTRIBUTING_zh.md +3 -0
  6. {straw_queue-0.1.5 → straw_queue-0.1.6}/Cargo.lock +1 -1
  7. {straw_queue-0.1.5 → straw_queue-0.1.6}/Cargo.toml +1 -1
  8. {straw_queue-0.1.5 → straw_queue-0.1.6}/PKG-INFO +1 -1
  9. {straw_queue-0.1.5 → straw_queue-0.1.6}/docs/BENCHMARKS.md +19 -0
  10. {straw_queue-0.1.5 → straw_queue-0.1.6}/docs/BENCHMARKS_zh.md +11 -0
  11. {straw_queue-0.1.5 → straw_queue-0.1.6}/docs/DESIGN.md +32 -10
  12. {straw_queue-0.1.5 → straw_queue-0.1.6}/docs/DESIGN_zh.md +21 -10
  13. {straw_queue-0.1.5 → straw_queue-0.1.6}/docs/USAGE.md +1 -1
  14. {straw_queue-0.1.5 → straw_queue-0.1.6}/docs/USAGE_zh.md +1 -1
  15. {straw_queue-0.1.5 → straw_queue-0.1.6}/pyproject.toml +1 -1
  16. {straw_queue-0.1.5 → straw_queue-0.1.6}/rust/catalog_runtime.rs +2 -0
  17. {straw_queue-0.1.5 → straw_queue-0.1.6}/rust/gc.rs +15 -30
  18. {straw_queue-0.1.5 → straw_queue-0.1.6}/rust/gc_batch.rs +16 -30
  19. {straw_queue-0.1.5 → straw_queue-0.1.6}/rust/gc_collection.rs +30 -21
  20. straw_queue-0.1.6/rust/gc_plan.rs +218 -0
  21. {straw_queue-0.1.5 → straw_queue-0.1.6}/rust/gc_writer.rs +2 -2
  22. {straw_queue-0.1.5 → straw_queue-0.1.6}/rust/lib.rs +0 -1
  23. {straw_queue-0.1.5 → straw_queue-0.1.6}/rust/protocol.rs +0 -51
  24. {straw_queue-0.1.5 → straw_queue-0.1.6}/rust/python.rs +3 -1
  25. {straw_queue-0.1.5 → straw_queue-0.1.6}/rust/record_index.rs +69 -16
  26. {straw_queue-0.1.5 → straw_queue-0.1.6}/rust/store.rs +79 -7
  27. {straw_queue-0.1.5 → straw_queue-0.1.6}/rust/writer_gate.rs +134 -15
  28. {straw_queue-0.1.5 → straw_queue-0.1.6}/rust/writer_registry.rs +64 -35
  29. {straw_queue-0.1.5 → straw_queue-0.1.6}/rust/writer_retirement.rs +4 -24
  30. {straw_queue-0.1.5 → straw_queue-0.1.6}/src/straw/store.py +3 -2
  31. straw_queue-0.1.6/tests/test_gc_concurrency.py +92 -0
  32. {straw_queue-0.1.5 → straw_queue-0.1.6}/tests/test_read_session.py +9 -1
  33. {straw_queue-0.1.5 → straw_queue-0.1.6}/verification/environment_contracts.json +30 -11
  34. straw_queue-0.1.6/verification/gc/tla/GCConcurrentDeletion.cfg +5 -0
  35. straw_queue-0.1.6/verification/gc/tla/GCConcurrentDeletion.tla +71 -0
  36. straw_queue-0.1.6/verification/runners/check_mutations.py +112 -0
  37. {straw_queue-0.1.5 → straw_queue-0.1.6}/verification/runners/check_tla.py +27 -0
  38. straw_queue-0.1.6/verification/storage/probes/metadata_scaling.py +98 -0
  39. {straw_queue-0.1.5 → straw_queue-0.1.6}/verification/storage/tla/DirectoryDurability.tla +21 -16
  40. {straw_queue-0.1.5 → straw_queue-0.1.6}/verification/wal/tla/CatalogReplay.cfg +1 -0
  41. {straw_queue-0.1.5 → straw_queue-0.1.6}/verification/wal/tla/CatalogReplay.tla +11 -6
  42. straw_queue-0.1.5/rust/catalog_gc.rs +0 -47
  43. {straw_queue-0.1.5 → straw_queue-0.1.6}/.agents/skills/straw-protocol-review/SKILL.md +0 -0
  44. {straw_queue-0.1.5 → straw_queue-0.1.6}/.agents/skills/straw-protocol-review/agents/openai.yaml +0 -0
  45. {straw_queue-0.1.5 → straw_queue-0.1.6}/.github/workflows/wheels.yml +0 -0
  46. {straw_queue-0.1.5 → straw_queue-0.1.6}/LICENSE +0 -0
  47. {straw_queue-0.1.5 → straw_queue-0.1.6}/README.md +0 -0
  48. {straw_queue-0.1.5 → straw_queue-0.1.6}/README_zh.md +0 -0
  49. {straw_queue-0.1.5 → straw_queue-0.1.6}/docs/FILESYSTEM.md +0 -0
  50. {straw_queue-0.1.5 → straw_queue-0.1.6}/docs/FILESYSTEM_zh.md +0 -0
  51. {straw_queue-0.1.5 → straw_queue-0.1.6}/docs/FORMAT.md +0 -0
  52. {straw_queue-0.1.5 → straw_queue-0.1.6}/docs/FORMAT_zh.md +0 -0
  53. {straw_queue-0.1.5 → straw_queue-0.1.6}/docs/README.md +0 -0
  54. {straw_queue-0.1.5 → straw_queue-0.1.6}/docs/README_zh.md +0 -0
  55. {straw_queue-0.1.5 → straw_queue-0.1.6}/examples/multiprocess.py +0 -0
  56. {straw_queue-0.1.5 → straw_queue-0.1.6}/examples/records.py +0 -0
  57. {straw_queue-0.1.5 → straw_queue-0.1.6}/examples/tensors.py +0 -0
  58. {straw_queue-0.1.5 → straw_queue-0.1.6}/examples/work_queue.py +0 -0
  59. {straw_queue-0.1.5 → straw_queue-0.1.6}/rust/access.rs +0 -0
  60. {straw_queue-0.1.5 → straw_queue-0.1.6}/rust/bounds.rs +0 -0
  61. {straw_queue-0.1.5 → straw_queue-0.1.6}/rust/catalog_append.rs +0 -0
  62. {straw_queue-0.1.5 → straw_queue-0.1.6}/rust/catalog_decode.rs +0 -0
  63. {straw_queue-0.1.5 → straw_queue-0.1.6}/rust/catalog_event.rs +0 -0
  64. {straw_queue-0.1.5 → straw_queue-0.1.6}/rust/catalog_frame.rs +0 -0
  65. {straw_queue-0.1.5 → straw_queue-0.1.6}/rust/catalog_json.rs +0 -0
  66. {straw_queue-0.1.5 → straw_queue-0.1.6}/rust/catalog_log.rs +0 -0
  67. {straw_queue-0.1.5 → straw_queue-0.1.6}/rust/catalog_namespace.rs +0 -0
  68. {straw_queue-0.1.5 → straw_queue-0.1.6}/rust/catalog_primitives.rs +0 -0
  69. {straw_queue-0.1.5 → straw_queue-0.1.6}/rust/catalog_state.rs +0 -0
  70. {straw_queue-0.1.5 → straw_queue-0.1.6}/rust/catalog_target.rs +0 -0
  71. {straw_queue-0.1.5 → straw_queue-0.1.6}/rust/catalog_transaction.rs +0 -0
  72. {straw_queue-0.1.5 → straw_queue-0.1.6}/rust/closure.rs +0 -0
  73. {straw_queue-0.1.5 → straw_queue-0.1.6}/rust/closure_node.rs +0 -0
  74. {straw_queue-0.1.5 → straw_queue-0.1.6}/rust/consumption.rs +0 -0
  75. {straw_queue-0.1.5 → straw_queue-0.1.6}/rust/coordinator.rs +0 -0
  76. {straw_queue-0.1.5 → straw_queue-0.1.6}/rust/directory.rs +0 -0
  77. {straw_queue-0.1.5 → straw_queue-0.1.6}/rust/directory_io.rs +0 -0
  78. {straw_queue-0.1.5 → straw_queue-0.1.6}/rust/discovery.rs +0 -0
  79. {straw_queue-0.1.5 → straw_queue-0.1.6}/rust/extent_retry.rs +0 -0
  80. {straw_queue-0.1.5 → straw_queue-0.1.6}/rust/file_adapter.rs +0 -0
  81. {straw_queue-0.1.5 → straw_queue-0.1.6}/rust/file_primitives.rs +0 -0
  82. {straw_queue-0.1.5 → straw_queue-0.1.6}/rust/finalization.rs +0 -0
  83. {straw_queue-0.1.5 → straw_queue-0.1.6}/rust/framing.rs +0 -0
  84. {straw_queue-0.1.5 → straw_queue-0.1.6}/rust/gc_io.rs +0 -0
  85. {straw_queue-0.1.5 → straw_queue-0.1.6}/rust/gc_mark.rs +0 -0
  86. {straw_queue-0.1.5 → straw_queue-0.1.6}/rust/gc_receipt.rs +0 -0
  87. {straw_queue-0.1.5 → straw_queue-0.1.6}/rust/holding.rs +0 -0
  88. {straw_queue-0.1.5 → straw_queue-0.1.6}/rust/identities.rs +0 -0
  89. {straw_queue-0.1.5 → straw_queue-0.1.6}/rust/incomplete.rs +0 -0
  90. {straw_queue-0.1.5 → straw_queue-0.1.6}/rust/journal.rs +0 -0
  91. {straw_queue-0.1.5 → straw_queue-0.1.6}/rust/journal_append.rs +0 -0
  92. {straw_queue-0.1.5 → straw_queue-0.1.6}/rust/journal_io.rs +0 -0
  93. {straw_queue-0.1.5 → straw_queue-0.1.6}/rust/journal_owner.rs +0 -0
  94. {straw_queue-0.1.5 → straw_queue-0.1.6}/rust/journal_primitives.rs +0 -0
  95. {straw_queue-0.1.5 → straw_queue-0.1.6}/rust/journal_recovery.rs +0 -0
  96. {straw_queue-0.1.5 → straw_queue-0.1.6}/rust/journal_state.rs +0 -0
  97. {straw_queue-0.1.5 → straw_queue-0.1.6}/rust/json_update.rs +0 -0
  98. {straw_queue-0.1.5 → straw_queue-0.1.6}/rust/namespace_identity.rs +0 -0
  99. {straw_queue-0.1.5 → straw_queue-0.1.6}/rust/namespace_step.rs +0 -0
  100. {straw_queue-0.1.5 → straw_queue-0.1.6}/rust/namespace_target.rs +0 -0
  101. {straw_queue-0.1.5 → straw_queue-0.1.6}/rust/payload.rs +0 -0
  102. {straw_queue-0.1.5 → straw_queue-0.1.6}/rust/pending.rs +0 -0
  103. {straw_queue-0.1.5 → straw_queue-0.1.6}/rust/queue_admin.rs +0 -0
  104. {straw_queue-0.1.5 → straw_queue-0.1.6}/rust/queue_application.rs +0 -0
  105. {straw_queue-0.1.5 → straw_queue-0.1.6}/rust/queue_commit.rs +0 -0
  106. {straw_queue-0.1.5 → straw_queue-0.1.6}/rust/queue_event.rs +0 -0
  107. {straw_queue-0.1.5 → straw_queue-0.1.6}/rust/queue_gc.rs +0 -0
  108. {straw_queue-0.1.5 → straw_queue-0.1.6}/rust/queue_gc_prepare.rs +0 -0
  109. {straw_queue-0.1.5 → straw_queue-0.1.6}/rust/queue_handoff.rs +0 -0
  110. {straw_queue-0.1.5 → straw_queue-0.1.6}/rust/queue_history.rs +0 -0
  111. {straw_queue-0.1.5 → straw_queue-0.1.6}/rust/queue_metadata.rs +0 -0
  112. {straw_queue-0.1.5 → straw_queue-0.1.6}/rust/queue_progress.rs +0 -0
  113. {straw_queue-0.1.5 → straw_queue-0.1.6}/rust/queue_reader.rs +0 -0
  114. {straw_queue-0.1.5 → straw_queue-0.1.6}/rust/queue_receipt.rs +0 -0
  115. {straw_queue-0.1.5 → straw_queue-0.1.6}/rust/queue_replay.rs +0 -0
  116. {straw_queue-0.1.5 → straw_queue-0.1.6}/rust/queue_retirement.rs +0 -0
  117. {straw_queue-0.1.5 → straw_queue-0.1.6}/rust/queue_roots.rs +0 -0
  118. {straw_queue-0.1.5 → straw_queue-0.1.6}/rust/queue_state.rs +0 -0
  119. {straw_queue-0.1.5 → straw_queue-0.1.6}/rust/queue_task.rs +0 -0
  120. {straw_queue-0.1.5 → straw_queue-0.1.6}/rust/queue_transition.rs +0 -0
  121. {straw_queue-0.1.5 → straw_queue-0.1.6}/rust/reclamation.rs +0 -0
  122. {straw_queue-0.1.5 → straw_queue-0.1.6}/rust/record_manifest.rs +0 -0
  123. {straw_queue-0.1.5 → straw_queue-0.1.6}/rust/reference_node.rs +0 -0
  124. {straw_queue-0.1.5 → straw_queue-0.1.6}/rust/reference_validation.rs +0 -0
  125. {straw_queue-0.1.5 → straw_queue-0.1.6}/rust/replay.rs +0 -0
  126. {straw_queue-0.1.5 → straw_queue-0.1.6}/rust/request.rs +0 -0
  127. {straw_queue-0.1.5 → straw_queue-0.1.6}/rust/selection.rs +0 -0
  128. {straw_queue-0.1.5 → straw_queue-0.1.6}/rust/staging_consumption.rs +0 -0
  129. {straw_queue-0.1.5 → straw_queue-0.1.6}/rust/stream.rs +0 -0
  130. {straw_queue-0.1.5 → straw_queue-0.1.6}/rust/traversal.rs +0 -0
  131. {straw_queue-0.1.5 → straw_queue-0.1.6}/rust/typed.rs +0 -0
  132. {straw_queue-0.1.5 → straw_queue-0.1.6}/rust/wal.rs +0 -0
  133. {straw_queue-0.1.5 → straw_queue-0.1.6}/rust/wal_append.rs +0 -0
  134. {straw_queue-0.1.5 → straw_queue-0.1.6}/rust/wal_device.rs +0 -0
  135. {straw_queue-0.1.5 → straw_queue-0.1.6}/rust/wal_file.rs +0 -0
  136. {straw_queue-0.1.5 → straw_queue-0.1.6}/rust/wal_recovery.rs +0 -0
  137. {straw_queue-0.1.5 → straw_queue-0.1.6}/rust/wal_sink.rs +0 -0
  138. {straw_queue-0.1.5 → straw_queue-0.1.6}/rust/wal_source.rs +0 -0
  139. {straw_queue-0.1.5 → straw_queue-0.1.6}/rust/writer_gate_flow.rs +0 -0
  140. {straw_queue-0.1.5 → straw_queue-0.1.6}/rust/writer_ownership.rs +0 -0
  141. {straw_queue-0.1.5 → straw_queue-0.1.6}/src/straw/__init__.py +0 -0
  142. {straw_queue-0.1.5 → straw_queue-0.1.6}/src/straw/backend.py +0 -0
  143. {straw_queue-0.1.5 → straw_queue-0.1.6}/src/straw/benchmark.py +0 -0
  144. {straw_queue-0.1.5 → straw_queue-0.1.6}/src/straw/coordinator.py +0 -0
  145. {straw_queue-0.1.5 → straw_queue-0.1.6}/src/straw/errors.py +0 -0
  146. {straw_queue-0.1.5 → straw_queue-0.1.6}/src/straw/inspect.py +0 -0
  147. {straw_queue-0.1.5 → straw_queue-0.1.6}/src/straw/journal.py +0 -0
  148. {straw_queue-0.1.5 → straw_queue-0.1.6}/src/straw/protocol.py +0 -0
  149. {straw_queue-0.1.5 → straw_queue-0.1.6}/src/straw/reporting.py +0 -0
  150. {straw_queue-0.1.5 → straw_queue-0.1.6}/src/straw/rpc.py +0 -0
  151. {straw_queue-0.1.5 → straw_queue-0.1.6}/src/straw/tensor.py +0 -0
  152. {straw_queue-0.1.5 → straw_queue-0.1.6}/src/straw/tracing.py +0 -0
  153. {straw_queue-0.1.5 → straw_queue-0.1.6}/tests/native.rs +0 -0
  154. {straw_queue-0.1.5 → straw_queue-0.1.6}/tests/test_artifact_privacy.py +0 -0
  155. {straw_queue-0.1.5 → straw_queue-0.1.6}/tests/test_benchmark_profile.py +0 -0
  156. {straw_queue-0.1.5 → straw_queue-0.1.6}/tests/test_catalog_encoding.py +0 -0
  157. {straw_queue-0.1.5 → straw_queue-0.1.6}/tests/test_commit_consumption.py +0 -0
  158. {straw_queue-0.1.5 → straw_queue-0.1.6}/tests/test_commit_protocol.py +0 -0
  159. {straw_queue-0.1.5 → straw_queue-0.1.6}/tests/test_consumer_rewind.py +0 -0
  160. {straw_queue-0.1.5 → straw_queue-0.1.6}/tests/test_dependency_traversal.py +0 -0
  161. {straw_queue-0.1.5 → straw_queue-0.1.6}/tests/test_durable_handoff.py +0 -0
  162. {straw_queue-0.1.5 → straw_queue-0.1.6}/tests/test_extent_bounds.py +0 -0
  163. {straw_queue-0.1.5 → straw_queue-0.1.6}/tests/test_extent_visibility.py +0 -0
  164. {straw_queue-0.1.5 → straw_queue-0.1.6}/tests/test_filesystem_queue.py +0 -0
  165. {straw_queue-0.1.5 → straw_queue-0.1.6}/tests/test_gc_batch.py +0 -0
  166. {straw_queue-0.1.5 → straw_queue-0.1.6}/tests/test_gc_extent_validation.py +0 -0
  167. {straw_queue-0.1.5 → straw_queue-0.1.6}/tests/test_gc_missing_parent.py +0 -0
  168. {straw_queue-0.1.5 → straw_queue-0.1.6}/tests/test_gc_receipts.py +0 -0
  169. {straw_queue-0.1.5 → straw_queue-0.1.6}/tests/test_incomplete_publication.py +0 -0
  170. {straw_queue-0.1.5 → straw_queue-0.1.6}/tests/test_journal_contract.py +0 -0
  171. {straw_queue-0.1.5 → straw_queue-0.1.6}/tests/test_json_roundtrip.py +0 -0
  172. {straw_queue-0.1.5 → straw_queue-0.1.6}/tests/test_lease_selection.py +0 -0
  173. {straw_queue-0.1.5 → straw_queue-0.1.6}/tests/test_metadata_recovery.py +0 -0
  174. {straw_queue-0.1.5 → straw_queue-0.1.6}/tests/test_offline_aliases.py +0 -0
  175. {straw_queue-0.1.5 → straw_queue-0.1.6}/tests/test_offline_inspection.py +0 -0
  176. {straw_queue-0.1.5 → straw_queue-0.1.6}/tests/test_offline_recovery.py +0 -0
  177. {straw_queue-0.1.5 → straw_queue-0.1.6}/tests/test_online_gc.py +0 -0
  178. {straw_queue-0.1.5 → straw_queue-0.1.6}/tests/test_packed_store.py +0 -0
  179. {straw_queue-0.1.5 → straw_queue-0.1.6}/tests/test_path_identity.py +0 -0
  180. {straw_queue-0.1.5 → straw_queue-0.1.6}/tests/test_pending_publication.py +0 -0
  181. {straw_queue-0.1.5 → straw_queue-0.1.6}/tests/test_provisional_holds.py +0 -0
  182. {straw_queue-0.1.5 → straw_queue-0.1.6}/tests/test_publication_handoff.py +0 -0
  183. {straw_queue-0.1.5 → straw_queue-0.1.6}/tests/test_publication_preparation.py +0 -0
  184. {straw_queue-0.1.5 → straw_queue-0.1.6}/tests/test_queue_gc_roots.py +0 -0
  185. {straw_queue-0.1.5 → straw_queue-0.1.6}/tests/test_request_replay.py +0 -0
  186. {straw_queue-0.1.5 → straw_queue-0.1.6}/tests/test_resume_workflow.py +0 -0
  187. {straw_queue-0.1.5 → straw_queue-0.1.6}/tests/test_staging_consumption.py +0 -0
  188. {straw_queue-0.1.5 → straw_queue-0.1.6}/tests/test_streaming_write.py +0 -0
  189. {straw_queue-0.1.5 → straw_queue-0.1.6}/tests/test_task_recovery.py +0 -0
  190. {straw_queue-0.1.5 → straw_queue-0.1.6}/tests/test_tensor.py +0 -0
  191. {straw_queue-0.1.5 → straw_queue-0.1.6}/tests/test_tensor_granularity.py +0 -0
  192. {straw_queue-0.1.5 → straw_queue-0.1.6}/tests/test_tensor_preflight.py +0 -0
  193. {straw_queue-0.1.5 → straw_queue-0.1.6}/tests/test_unlimited_capacity.py +0 -0
  194. {straw_queue-0.1.5 → straw_queue-0.1.6}/tests/test_verification_runner.py +0 -0
  195. {straw_queue-0.1.5 → straw_queue-0.1.6}/tests/test_visibility_probe.py +0 -0
  196. {straw_queue-0.1.5 → straw_queue-0.1.6}/tests/test_wal_recovery.py +0 -0
  197. {straw_queue-0.1.5 → straw_queue-0.1.6}/tests/test_writer_access.py +0 -0
  198. {straw_queue-0.1.5 → straw_queue-0.1.6}/tests/test_writer_retirement.py +0 -0
  199. {straw_queue-0.1.5 → straw_queue-0.1.6}/tools/check_artifact_privacy.py +0 -0
  200. {straw_queue-0.1.5 → straw_queue-0.1.6}/tools/check_wheel.py +0 -0
  201. {straw_queue-0.1.5 → straw_queue-0.1.6}/tools/release_build.py +0 -0
  202. {straw_queue-0.1.5 → straw_queue-0.1.6}/verification/README.md +0 -0
  203. {straw_queue-0.1.5 → straw_queue-0.1.6}/verification/README_zh.md +0 -0
  204. {straw_queue-0.1.5 → straw_queue-0.1.6}/verification/common/README.md +0 -0
  205. {straw_queue-0.1.5 → straw_queue-0.1.6}/verification/common/probes/runtime_performance.py +0 -0
  206. {straw_queue-0.1.5 → straw_queue-0.1.6}/verification/common/tla/EnvironmentCatalog.tla +0 -0
  207. {straw_queue-0.1.5 → straw_queue-0.1.6}/verification/common/tla/EnvironmentGraph.tla +0 -0
  208. {straw_queue-0.1.5 → straw_queue-0.1.6}/verification/common/tla/EnvironmentInputs.tla +0 -0
  209. {straw_queue-0.1.5 → straw_queue-0.1.6}/verification/common/tla/EnvironmentNamespace.tla +0 -0
  210. {straw_queue-0.1.5 → straw_queue-0.1.6}/verification/common/tla/EnvironmentPersistence.tla +0 -0
  211. {straw_queue-0.1.5 → straw_queue-0.1.6}/verification/common/tla/EnvironmentProgress.tla +0 -0
  212. {straw_queue-0.1.5 → straw_queue-0.1.6}/verification/common/tla/EnvironmentRead.tla +0 -0
  213. {straw_queue-0.1.5 → straw_queue-0.1.6}/verification/gc/README.md +0 -0
  214. {straw_queue-0.1.5 → straw_queue-0.1.6}/verification/gc/probes/catalog_discovery_fault.c +0 -0
  215. {straw_queue-0.1.5 → straw_queue-0.1.6}/verification/gc/probes/catalog_discovery_probe.py +0 -0
  216. {straw_queue-0.1.5 → straw_queue-0.1.6}/verification/gc/probes/gc_cross_client.py +0 -0
  217. {straw_queue-0.1.5 → straw_queue-0.1.6}/verification/gc/probes/gc_history_probe.py +0 -0
  218. {straw_queue-0.1.5 → straw_queue-0.1.6}/verification/gc/probes/gc_parent_fault.c +0 -0
  219. {straw_queue-0.1.5 → straw_queue-0.1.6}/verification/gc/probes/gc_parent_probe.py +0 -0
  220. {straw_queue-0.1.5 → straw_queue-0.1.6}/verification/gc/probes/gc_receipt_probe.py +0 -0
  221. {straw_queue-0.1.5 → straw_queue-0.1.6}/verification/gc/probes/gc_scale.py +0 -0
  222. {straw_queue-0.1.5 → straw_queue-0.1.6}/verification/gc/probes/gc_stat_fault.c +0 -0
  223. {straw_queue-0.1.5 → straw_queue-0.1.6}/verification/gc/probes/gc_stat_probe.py +0 -0
  224. {straw_queue-0.1.5 → straw_queue-0.1.6}/verification/gc/tla/EnvironmentParentRepair.tla +0 -0
  225. {straw_queue-0.1.5 → straw_queue-0.1.6}/verification/gc/tla/EnvironmentWriter.tla +0 -0
  226. {straw_queue-0.1.5 → straw_queue-0.1.6}/verification/gc/tla/EnvironmentWriterRetirement.tla +0 -0
  227. {straw_queue-0.1.5 → straw_queue-0.1.6}/verification/gc/tla/GCBatchDeletion.cfg +0 -0
  228. {straw_queue-0.1.5 → straw_queue-0.1.6}/verification/gc/tla/GCBatchDeletion.tla +0 -0
  229. {straw_queue-0.1.5 → straw_queue-0.1.6}/verification/gc/tla/GCDeletion.cfg +0 -0
  230. {straw_queue-0.1.5 → straw_queue-0.1.6}/verification/gc/tla/GCDeletion.tla +0 -0
  231. {straw_queue-0.1.5 → straw_queue-0.1.6}/verification/gc/tla/GCDiscovery.cfg +0 -0
  232. {straw_queue-0.1.5 → straw_queue-0.1.6}/verification/gc/tla/GCDiscovery.tla +0 -0
  233. {straw_queue-0.1.5 → straw_queue-0.1.6}/verification/gc/tla/GCParentRepair.cfg +0 -0
  234. {straw_queue-0.1.5 → straw_queue-0.1.6}/verification/gc/tla/GCParentRepair.tla +0 -0
  235. {straw_queue-0.1.5 → straw_queue-0.1.6}/verification/gc/tla/GCReceipt.cfg +0 -0
  236. {straw_queue-0.1.5 → straw_queue-0.1.6}/verification/gc/tla/GCReceipt.tla +0 -0
  237. {straw_queue-0.1.5 → straw_queue-0.1.6}/verification/gc/tla/WriterLifetime.cfg +0 -0
  238. {straw_queue-0.1.5 → straw_queue-0.1.6}/verification/gc/tla/WriterLifetime.tla +0 -0
  239. {straw_queue-0.1.5 → straw_queue-0.1.6}/verification/gc/tla/WriterRetirement.cfg +0 -0
  240. {straw_queue-0.1.5 → straw_queue-0.1.6}/verification/gc/tla/WriterRetirement.tla +0 -0
  241. {straw_queue-0.1.5 → straw_queue-0.1.6}/verification/measurements/20261026-release-100gb.json +0 -0
  242. {straw_queue-0.1.5 → straw_queue-0.1.6}/verification/measurements/20261026-release-comparison.json +0 -0
  243. {straw_queue-0.1.5 → straw_queue-0.1.6}/verification/measurements/20261026-release-visibility.json +0 -0
  244. {straw_queue-0.1.5 → straw_queue-0.1.6}/verification/offline/README.md +0 -0
  245. {straw_queue-0.1.5 → straw_queue-0.1.6}/verification/offline/probes/offline_alias_probe.py +0 -0
  246. {straw_queue-0.1.5 → straw_queue-0.1.6}/verification/offline/probes/offline_guard_fault.c +0 -0
  247. {straw_queue-0.1.5 → straw_queue-0.1.6}/verification/offline/probes/offline_guard_probe.py +0 -0
  248. {straw_queue-0.1.5 → straw_queue-0.1.6}/verification/offline/tla/EnvironmentBindings.tla +0 -0
  249. {straw_queue-0.1.5 → straw_queue-0.1.6}/verification/offline/tla/EnvironmentOffline.tla +0 -0
  250. {straw_queue-0.1.5 → straw_queue-0.1.6}/verification/offline/tla/OfflineAliases.cfg +0 -0
  251. {straw_queue-0.1.5 → straw_queue-0.1.6}/verification/offline/tla/OfflineAliases.tla +0 -0
  252. {straw_queue-0.1.5 → straw_queue-0.1.6}/verification/offline/tla/OfflineCleanup.cfg +0 -0
  253. {straw_queue-0.1.5 → straw_queue-0.1.6}/verification/offline/tla/OfflineCleanup.tla +0 -0
  254. {straw_queue-0.1.5 → straw_queue-0.1.6}/verification/offline/tla/OfflineRoots.cfg +0 -0
  255. {straw_queue-0.1.5 → straw_queue-0.1.6}/verification/offline/tla/OfflineRoots.tla +0 -0
  256. {straw_queue-0.1.5 → straw_queue-0.1.6}/verification/protocol/README.md +0 -0
  257. {straw_queue-0.1.5 → straw_queue-0.1.6}/verification/protocol/checks/ownership_model.py +0 -0
  258. {straw_queue-0.1.5 → straw_queue-0.1.6}/verification/protocol/probes/commit_cleanup_probe.py +0 -0
  259. {straw_queue-0.1.5 → straw_queue-0.1.6}/verification/protocol/probes/consumption_probe.py +0 -0
  260. {straw_queue-0.1.5 → straw_queue-0.1.6}/verification/protocol/probes/handoff_extent_probe.rs +0 -0
  261. {straw_queue-0.1.5 → straw_queue-0.1.6}/verification/protocol/probes/handoff_probe.py +0 -0
  262. {straw_queue-0.1.5 → straw_queue-0.1.6}/verification/protocol/probes/lease_selection_probe.py +0 -0
  263. {straw_queue-0.1.5 → straw_queue-0.1.6}/verification/protocol/probes/provisional_hold_probe.py +0 -0
  264. {straw_queue-0.1.5 → straw_queue-0.1.6}/verification/protocol/probes/queue_record_probe.rs +0 -0
  265. {straw_queue-0.1.5 → straw_queue-0.1.6}/verification/protocol/probes/reactivation_peer_probe.py +0 -0
  266. {straw_queue-0.1.5 → straw_queue-0.1.6}/verification/protocol/probes/reactivation_probe.rs +0 -0
  267. {straw_queue-0.1.5 → straw_queue-0.1.6}/verification/protocol/probes/workflow_extent_probe.rs +0 -0
  268. {straw_queue-0.1.5 → straw_queue-0.1.6}/verification/protocol/tla/CommitApplication.cfg +0 -0
  269. {straw_queue-0.1.5 → straw_queue-0.1.6}/verification/protocol/tla/CommitApplication.tla +0 -0
  270. {straw_queue-0.1.5 → straw_queue-0.1.6}/verification/protocol/tla/CommitCleanup.cfg +0 -0
  271. {straw_queue-0.1.5 → straw_queue-0.1.6}/verification/protocol/tla/CommitCleanup.tla +0 -0
  272. {straw_queue-0.1.5 → straw_queue-0.1.6}/verification/protocol/tla/Completion.cfg +0 -0
  273. {straw_queue-0.1.5 → straw_queue-0.1.6}/verification/protocol/tla/Completion.tla +0 -0
  274. {straw_queue-0.1.5 → straw_queue-0.1.6}/verification/protocol/tla/CrossLogComposition.cfg +0 -0
  275. {straw_queue-0.1.5 → straw_queue-0.1.6}/verification/protocol/tla/CrossLogComposition.tla +0 -0
  276. {straw_queue-0.1.5 → straw_queue-0.1.6}/verification/protocol/tla/DurableHandoff.cfg +0 -0
  277. {straw_queue-0.1.5 → straw_queue-0.1.6}/verification/protocol/tla/DurableHandoff.tla +0 -0
  278. {straw_queue-0.1.5 → straw_queue-0.1.6}/verification/protocol/tla/EnvironmentApplication.tla +0 -0
  279. {straw_queue-0.1.5 → straw_queue-0.1.6}/verification/protocol/tla/EnvironmentClock.tla +0 -0
  280. {straw_queue-0.1.5 → straw_queue-0.1.6}/verification/protocol/tla/EnvironmentCommitCleanup.tla +0 -0
  281. {straw_queue-0.1.5 → straw_queue-0.1.6}/verification/protocol/tla/EnvironmentConsumption.tla +0 -0
  282. {straw_queue-0.1.5 → straw_queue-0.1.6}/verification/protocol/tla/EnvironmentCrossComposition.tla +0 -0
  283. {straw_queue-0.1.5 → straw_queue-0.1.6}/verification/protocol/tla/EnvironmentCrossLog.tla +0 -0
  284. {straw_queue-0.1.5 → straw_queue-0.1.6}/verification/protocol/tla/EnvironmentHandoff.tla +0 -0
  285. {straw_queue-0.1.5 → straw_queue-0.1.6}/verification/protocol/tla/EnvironmentReaders.tla +0 -0
  286. {straw_queue-0.1.5 → straw_queue-0.1.6}/verification/protocol/tla/EnvironmentRequest.tla +0 -0
  287. {straw_queue-0.1.5 → straw_queue-0.1.6}/verification/protocol/tla/EnvironmentTraining.tla +0 -0
  288. {straw_queue-0.1.5 → straw_queue-0.1.6}/verification/protocol/tla/Ownership.cfg +0 -0
  289. {straw_queue-0.1.5 → straw_queue-0.1.6}/verification/protocol/tla/Ownership.tla +0 -0
  290. {straw_queue-0.1.5 → straw_queue-0.1.6}/verification/protocol/tla/ProvisionalHold.cfg +0 -0
  291. {straw_queue-0.1.5 → straw_queue-0.1.6}/verification/protocol/tla/ProvisionalHold.tla +0 -0
  292. {straw_queue-0.1.5 → straw_queue-0.1.6}/verification/protocol/tla/PublicationHandoff.cfg +0 -0
  293. {straw_queue-0.1.5 → straw_queue-0.1.6}/verification/protocol/tla/PublicationHandoff.tla +0 -0
  294. {straw_queue-0.1.5 → straw_queue-0.1.6}/verification/protocol/tla/QueueRecordWorkflow.cfg +0 -0
  295. {straw_queue-0.1.5 → straw_queue-0.1.6}/verification/protocol/tla/QueueRecordWorkflow.tla +0 -0
  296. {straw_queue-0.1.5 → straw_queue-0.1.6}/verification/protocol/tla/ReactivationRace.cfg +0 -0
  297. {straw_queue-0.1.5 → straw_queue-0.1.6}/verification/protocol/tla/ReactivationRace.tla +0 -0
  298. {straw_queue-0.1.5 → straw_queue-0.1.6}/verification/protocol/tla/ReactivationScan.cfg +0 -0
  299. {straw_queue-0.1.5 → straw_queue-0.1.6}/verification/protocol/tla/ReactivationScan.tla +0 -0
  300. {straw_queue-0.1.5 → straw_queue-0.1.6}/verification/protocol/tla/RequestReplay.cfg +0 -0
  301. {straw_queue-0.1.5 → straw_queue-0.1.6}/verification/protocol/tla/RequestReplay.tla +0 -0
  302. {straw_queue-0.1.5 → straw_queue-0.1.6}/verification/protocol/tla/SharedRecordWorkflow.cfg +0 -0
  303. {straw_queue-0.1.5 → straw_queue-0.1.6}/verification/protocol/tla/SharedRecordWorkflow.tla +0 -0
  304. {straw_queue-0.1.5 → straw_queue-0.1.6}/verification/protocol/tla/StagingConsumption.cfg +0 -0
  305. {straw_queue-0.1.5 → straw_queue-0.1.6}/verification/protocol/tla/StagingConsumption.tla +0 -0
  306. {straw_queue-0.1.5 → straw_queue-0.1.6}/verification/protocol/tla/TrainingResume.cfg +0 -0
  307. {straw_queue-0.1.5 → straw_queue-0.1.6}/verification/protocol/tla/TrainingResume.tla +0 -0
  308. {straw_queue-0.1.5 → straw_queue-0.1.6}/verification/runners/environment_manifest.py +0 -0
  309. {straw_queue-0.1.5 → straw_queue-0.1.6}/verification/storage/README.md +0 -0
  310. {straw_queue-0.1.5 → straw_queue-0.1.6}/verification/storage/probes/catalog_encoding_probe.py +0 -0
  311. {straw_queue-0.1.5 → straw_queue-0.1.6}/verification/storage/probes/dependency_probe.py +0 -0
  312. {straw_queue-0.1.5 → straw_queue-0.1.6}/verification/storage/probes/directory_sync_fault.c +0 -0
  313. {straw_queue-0.1.5 → straw_queue-0.1.6}/verification/storage/probes/directory_sync_probe.py +0 -0
  314. {straw_queue-0.1.5 → straw_queue-0.1.6}/verification/storage/probes/extent_visibility_probe.py +0 -0
  315. {straw_queue-0.1.5 → straw_queue-0.1.6}/verification/storage/probes/filesystem_bandwidth_probe.py +0 -0
  316. {straw_queue-0.1.5 → straw_queue-0.1.6}/verification/storage/probes/incomplete_cleanup_fault.c +0 -0
  317. {straw_queue-0.1.5 → straw_queue-0.1.6}/verification/storage/probes/incomplete_publication_probe.py +0 -0
  318. {straw_queue-0.1.5 → straw_queue-0.1.6}/verification/storage/probes/large_extent_probe.rs +0 -0
  319. {straw_queue-0.1.5 → straw_queue-0.1.6}/verification/storage/probes/namespace_lookup_count.c +0 -0
  320. {straw_queue-0.1.5 → straw_queue-0.1.6}/verification/storage/probes/path_identity_probe.py +0 -0
  321. {straw_queue-0.1.5 → straw_queue-0.1.6}/verification/storage/probes/pending_publication_probe.py +0 -0
  322. {straw_queue-0.1.5 → straw_queue-0.1.6}/verification/storage/probes/positioned_extent_probe.rs +0 -0
  323. {straw_queue-0.1.5 → straw_queue-0.1.6}/verification/storage/probes/preparation_fault.c +0 -0
  324. {straw_queue-0.1.5 → straw_queue-0.1.6}/verification/storage/probes/preparation_probe.py +0 -0
  325. {straw_queue-0.1.5 → straw_queue-0.1.6}/verification/storage/probes/publication_finalize_probe.py +0 -0
  326. {straw_queue-0.1.5 → straw_queue-0.1.6}/verification/storage/probes/publication_retry_probe.py +0 -0
  327. {straw_queue-0.1.5 → straw_queue-0.1.6}/verification/storage/probes/publication_sync_fault.c +0 -0
  328. {straw_queue-0.1.5 → straw_queue-0.1.6}/verification/storage/probes/read_latency_probe.py +0 -0
  329. {straw_queue-0.1.5 → straw_queue-0.1.6}/verification/storage/probes/read_latency_trace.c +0 -0
  330. {straw_queue-0.1.5 → straw_queue-0.1.6}/verification/storage/probes/read_lookup_fault.c +0 -0
  331. {straw_queue-0.1.5 → straw_queue-0.1.6}/verification/storage/probes/read_lookup_probe.py +0 -0
  332. {straw_queue-0.1.5 → straw_queue-0.1.6}/verification/storage/probes/standalone_extent_probe.rs +0 -0
  333. {straw_queue-0.1.5 → straw_queue-0.1.6}/verification/storage/probes/tensor_granularity_probe.py +0 -0
  334. {straw_queue-0.1.5 → straw_queue-0.1.6}/verification/storage/probes/typed_preflight_probe.py +0 -0
  335. {straw_queue-0.1.5 → straw_queue-0.1.6}/verification/storage/probes/writer_access_probe.py +0 -0
  336. {straw_queue-0.1.5 → straw_queue-0.1.6}/verification/storage/probes/writer_lifetime_probe.py +0 -0
  337. {straw_queue-0.1.5 → straw_queue-0.1.6}/verification/storage/tla/DependencyTraversal.cfg +0 -0
  338. {straw_queue-0.1.5 → straw_queue-0.1.6}/verification/storage/tla/DependencyTraversal.tla +0 -0
  339. {straw_queue-0.1.5 → straw_queue-0.1.6}/verification/storage/tla/DirectoryDurability.cfg +0 -0
  340. {straw_queue-0.1.5 → straw_queue-0.1.6}/verification/storage/tla/EnvironmentAuthentication.tla +0 -0
  341. {straw_queue-0.1.5 → straw_queue-0.1.6}/verification/storage/tla/EnvironmentIncomplete.tla +0 -0
  342. {straw_queue-0.1.5 → straw_queue-0.1.6}/verification/storage/tla/EnvironmentLocalAccess.tla +0 -0
  343. {straw_queue-0.1.5 → straw_queue-0.1.6}/verification/storage/tla/EnvironmentLookup.tla +0 -0
  344. {straw_queue-0.1.5 → straw_queue-0.1.6}/verification/storage/tla/EnvironmentPreparation.tla +0 -0
  345. {straw_queue-0.1.5 → straw_queue-0.1.6}/verification/storage/tla/EnvironmentTyped.tla +0 -0
  346. {straw_queue-0.1.5 → straw_queue-0.1.6}/verification/storage/tla/EnvironmentVisibility.tla +0 -0
  347. {straw_queue-0.1.5 → straw_queue-0.1.6}/verification/storage/tla/ExtentVisibility.cfg +0 -0
  348. {straw_queue-0.1.5 → straw_queue-0.1.6}/verification/storage/tla/ExtentVisibility.tla +0 -0
  349. {straw_queue-0.1.5 → straw_queue-0.1.6}/verification/storage/tla/IncompletePublication.cfg +0 -0
  350. {straw_queue-0.1.5 → straw_queue-0.1.6}/verification/storage/tla/IncompletePublication.tla +0 -0
  351. {straw_queue-0.1.5 → straw_queue-0.1.6}/verification/storage/tla/NamespaceIdentity.cfg +0 -0
  352. {straw_queue-0.1.5 → straw_queue-0.1.6}/verification/storage/tla/NamespaceIdentity.tla +0 -0
  353. {straw_queue-0.1.5 → straw_queue-0.1.6}/verification/storage/tla/PendingPublication.cfg +0 -0
  354. {straw_queue-0.1.5 → straw_queue-0.1.6}/verification/storage/tla/PendingPublication.tla +0 -0
  355. {straw_queue-0.1.5 → straw_queue-0.1.6}/verification/storage/tla/PublicationFinalization.cfg +0 -0
  356. {straw_queue-0.1.5 → straw_queue-0.1.6}/verification/storage/tla/PublicationFinalization.tla +0 -0
  357. {straw_queue-0.1.5 → straw_queue-0.1.6}/verification/storage/tla/PublicationPreparation.cfg +0 -0
  358. {straw_queue-0.1.5 → straw_queue-0.1.6}/verification/storage/tla/PublicationPreparation.tla +0 -0
  359. {straw_queue-0.1.5 → straw_queue-0.1.6}/verification/storage/tla/PublicationRetry.cfg +0 -0
  360. {straw_queue-0.1.5 → straw_queue-0.1.6}/verification/storage/tla/PublicationRetry.tla +0 -0
  361. {straw_queue-0.1.5 → straw_queue-0.1.6}/verification/storage/tla/RangeRead.cfg +0 -0
  362. {straw_queue-0.1.5 → straw_queue-0.1.6}/verification/storage/tla/RangeRead.tla +0 -0
  363. {straw_queue-0.1.5 → straw_queue-0.1.6}/verification/storage/tla/ReadAttempt.cfg +0 -0
  364. {straw_queue-0.1.5 → straw_queue-0.1.6}/verification/storage/tla/ReadAttempt.tla +0 -0
  365. {straw_queue-0.1.5 → straw_queue-0.1.6}/verification/storage/tla/ReadLookup.cfg +0 -0
  366. {straw_queue-0.1.5 → straw_queue-0.1.6}/verification/storage/tla/ReadLookup.tla +0 -0
  367. {straw_queue-0.1.5 → straw_queue-0.1.6}/verification/storage/tla/TypedRead.cfg +0 -0
  368. {straw_queue-0.1.5 → straw_queue-0.1.6}/verification/storage/tla/TypedRead.tla +0 -0
  369. {straw_queue-0.1.5 → straw_queue-0.1.6}/verification/storage/tla/WriterAccess.cfg +0 -0
  370. {straw_queue-0.1.5 → straw_queue-0.1.6}/verification/storage/tla/WriterAccess.tla +0 -0
  371. {straw_queue-0.1.5 → straw_queue-0.1.6}/verification/wal/README.md +0 -0
  372. {straw_queue-0.1.5 → straw_queue-0.1.6}/verification/wal/checks/crash_campaign.py +0 -0
  373. {straw_queue-0.1.5 → straw_queue-0.1.6}/verification/wal/probes/catalog_fsync_fault.c +0 -0
  374. {straw_queue-0.1.5 → straw_queue-0.1.6}/verification/wal/probes/catalog_history_probe.py +0 -0
  375. {straw_queue-0.1.5 → straw_queue-0.1.6}/verification/wal/probes/catalog_replay_probe.py +0 -0
  376. {straw_queue-0.1.5 → straw_queue-0.1.6}/verification/wal/tla/CatalogReadBuffer.cfg +0 -0
  377. {straw_queue-0.1.5 → straw_queue-0.1.6}/verification/wal/tla/CatalogReadBuffer.tla +0 -0
  378. {straw_queue-0.1.5 → straw_queue-0.1.6}/verification/wal/tla/CatalogTransaction.cfg +0 -0
  379. {straw_queue-0.1.5 → straw_queue-0.1.6}/verification/wal/tla/CatalogTransaction.tla +0 -0
  380. {straw_queue-0.1.5 → straw_queue-0.1.6}/verification/wal/tla/EnvironmentWal.tla +0 -0
  381. {straw_queue-0.1.5 → straw_queue-0.1.6}/verification/wal/tla/WalRecovery.cfg +0 -0
  382. {straw_queue-0.1.5 → straw_queue-0.1.6}/verification/wal/tla/WalRecovery.tla +0 -0
@@ -71,6 +71,14 @@ jobs:
71
71
  cargo clippy --locked --all-targets --features python -- -D warnings
72
72
  - name: Run Rust tests
73
73
  run: cargo test --locked
74
+ - name: Check concrete protocol mutation regressions
75
+ run: python verification/runners/check_mutations.py
76
+ - uses: actions/upload-artifact@v4
77
+ if: always()
78
+ with:
79
+ name: implementation-mutations
80
+ path: target/implementation-mutations/
81
+ if-no-files-found: warn
74
82
 
75
83
  python:
76
84
  name: Full suite / Python ${{ matrix.python }}
@@ -2,6 +2,12 @@
2
2
 
3
3
  [中文版](CHANGELOG_zh.md)
4
4
 
5
+ ## 0.1.6
6
+
7
+ - 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.
8
+ - Move physical GC deletion and directory synchronization outside the pool catalog lock. Bind receipts to the completed plan and support overlapping collectors without consuming newly added pending work.
9
+ - Cache up to eight authenticated extent indexes for alternating reads. Extend protocol models and concrete regressions; add real Rust mutation checks to CI and a reproducible metadata-scaling probe. Metadata history/receipt retirement and compaction remain out of scope.
10
+
5
11
  ## 0.1.5
6
12
 
7
13
  ### Ownership safety
@@ -2,6 +2,12 @@
2
2
 
3
3
  [English](CHANGELOG.md)
4
4
 
5
+ ## 0.1.6
6
+
7
+ - 复用已确认的 writer registry 状态并为操作查找建立索引;不确定结果后重建。只缓存完整同步成功的 writer 目录,并保持 inode 身份。保留既有 publication WAL 屏障与 wire format。
8
+ - 将 GC 物理删除与目录同步移到 pool catalog 锁外;回执绑定本轮完成的计划,允许 collector 重叠执行且不消费新加入的 pending 工作。
9
+ - 为交替读取缓存最多八条已认证 extent 索引。扩展协议模型与实际回归,将真实 Rust 代码变异检查加入 CI,新增可重放的元数据开销探针。暂不实现元数据历史/回执退休和压缩。
10
+
5
11
  ## 0.1.5
6
12
 
7
13
  ### 所有权安全
@@ -40,6 +40,7 @@ cargo test --locked
40
40
  python -m pytest
41
41
  python verification/runners/environment_manifest.py --check
42
42
  python verification/runners/check_tla.py
43
+ python verification/runners/check_mutations.py
43
44
  python verification/protocol/checks/ownership_model.py --output /tmp/straw-ownership.json
44
45
  python verification/wal/checks/crash_campaign.py --output /tmp/straw-crashes.json
45
46
  ```
@@ -53,6 +54,12 @@ Logs, configs and counterexamples default to `target/tla/`. Positives must pass;
53
54
  negatives must fail the named invariant/temporal property. Parse errors, timeouts
54
55
  and launch failures never count as semantic rejection.
55
56
 
57
+ The implementation mutation runner first passes an unmodified regression baseline,
58
+ then edits isolated Rust copies to reuse uncertain registry state, cache a directory
59
+ before its barriers, and skip GC parent barriers. Each must fail its named runtime
60
+ test; compilation failures, missing tests and timeouts do not count. Reports default
61
+ to `target/implementation-mutations/` and are retained by CI.
62
+
56
63
  The inventory checks declared IDs, paths and environment imports. The independent
57
64
  ownership model explores a bounded abstraction; the crash campaign checks byte
58
65
  prefixes/corruption and process exits. None certifies storage-service or power-loss
@@ -25,6 +25,7 @@ cargo test --locked
25
25
  python -m pytest
26
26
  python verification/runners/environment_manifest.py --check
27
27
  python verification/runners/check_tla.py
28
+ python verification/runners/check_mutations.py
28
29
  python verification/protocol/checks/ownership_model.py --output /tmp/straw-ownership.json
29
30
  python verification/wal/checks/crash_campaign.py --output /tmp/straw-crashes.json
30
31
  ```
@@ -33,6 +34,8 @@ Rust 修改后先重新构建/安装 native 扩展,再跑 Python 测试。
33
34
 
34
35
  环境登记检查核对声明的 ID、路径与模块导入。独立所有权模型探索有限抽象;crash campaign 检查逐字节前缀/损坏和进程退出,都不认证存储服务故障或掉电行为。多客户端验证见[部署指南](docs/FILESYSTEM_zh.md#qualification)。
35
36
 
37
+ 实现 mutation runner 先通过未修改的回归基线,再在隔离 Rust 副本中复用不确定 registry 状态、提前缓存目录、跳过 GC 父目录屏障。每项必须使指定运行时测试失败;编译错误、缺失测试和超时不算检出。报告默认保存在 `target/implementation-mutations/`,由 CI 留存。
38
+
36
39
  <a id="build"></a>
37
40
 
38
41
  ## 构建与检查发行包
@@ -370,7 +370,7 @@ checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5"
370
370
 
371
371
  [[package]]
372
372
  name = "straw"
373
- version = "0.1.5"
373
+ version = "0.1.6"
374
374
  dependencies = [
375
375
  "pyo3",
376
376
  "serde",
@@ -1,6 +1,6 @@
1
1
  [package]
2
2
  name = "straw"
3
- version = "0.1.5"
3
+ version = "0.1.6"
4
4
  edition = "2024"
5
5
  rust-version = "1.89"
6
6
  license = "MIT"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: straw-queue
3
- Version: 0.1.5
3
+ Version: 0.1.6
4
4
  Classifier: Development Status :: 3 - Alpha
5
5
  Classifier: Operating System :: POSIX :: Linux
6
6
  Classifier: Programming Language :: Python :: 3
@@ -124,6 +124,25 @@ dead. Failed runs, including capacity exhaustion, retain their root for inspecti
124
124
  the benchmark does not reset the queue, raise limits or restart automatically.
125
125
  Root budgets do not apply to the external report/trace directory.
126
126
 
127
+ ## Metadata and small reads
128
+
129
+ Run the same probe against each installed wheel to measure the cost of writer
130
+ history and alternating extent reads:
131
+
132
+ ```sh
133
+ python verification/storage/probes/metadata_scaling.py \
134
+ --count 1000 --output /tmp/straw-metadata.json
135
+ ```
136
+
137
+ Use `--parent` to select a filesystem and `--online-gc` to include catalog work.
138
+ The probe uses a private temporary root, closes its stores before removal, and
139
+ records the native binary hash. It reports recent write medians, registry size,
140
+ Linux process logical read bytes, sync hooks and 400 checked reads alternating
141
+ between four extents. Journal/file sync hooks can name the same barrier; do not
142
+ add them twice. Logical reads may hit caches and are not device/network traffic.
143
+ Keep workload, mount, interpreter and GC mode fixed across comparisons; these
144
+ small tests do not establish production throughput or tail-latency bounds.
145
+
127
146
  <a id="published-results"></a>
128
147
 
129
148
  ## Selected public measurements
@@ -72,6 +72,17 @@ Trace 写入统计带 framing 的 extent 字节,同时单独报告 payload 字
72
72
 
73
73
  `--max-files`、`--max-gib` 限制有限测试的规模。Benchmark 在临时 root 外保存 JSON 报告、不含载荷的 `.logs.tar.gz` 以及 `.cleanup.json`。成功结束时先确认自有 worker 已停止,再删除 root;SSH 断开并不能证明远端进程已退出。失败的测试(包括容量用尽)会保留 root 供检查,不自动重置队列、提高上限或重新启动。无法检查或停止远端机器时同样保留 root。确认 worker 死亡前不要删除。Root 预算不覆盖外部报告/trace 目录。
74
74
 
75
+ ## 元数据与小范围读取
76
+
77
+ 对每个已安装 wheel 运行同一探针,测量 writer 历史和交替 extent 读取的开销:
78
+
79
+ ```sh
80
+ python verification/storage/probes/metadata_scaling.py \
81
+ --count 1000 --output /tmp/straw-metadata.json
82
+ ```
83
+
84
+ `--parent` 选择文件系统,`--online-gc` 纳入 catalog 工作。探针使用私有临时 root,关闭 store 后清理,并记录原生二进制哈希。结果包括最近写入中位数、registry 大小、Linux 进程逻辑读取量、同步 hook,以及在四个 extent 之间交替进行的 400 次认证读取。Journal/file sync hook 可能指向同一次屏障,不应重复相加。逻辑读取可能命中缓存,不是设备/网络流量。对照应保持负载、挂载、解释器和 GC 模式一致;这些小型测试不代表生产吞吐或尾延迟上界。
85
+
75
86
  <a id="published-results"></a>
76
87
 
77
88
  ## 精选公开基准
@@ -158,6 +158,11 @@ and seeks to the valid end. Rebuild business indexes, receipts and derived cache
158
158
  from that same prefix before reuse. Never lose an acknowledged prefix. A complete
159
159
  uncertain frame may survive; its retry must not produce a second acceptance.
160
160
 
161
+ An exclusively owned writer registry may reuse its confirmed, fully applied
162
+ prefix and operation indexes after reacquiring the exact gate and checking the
163
+ fresh log's inode and length. An uncertain append or application invalidates that
164
+ cache and requires replay. This does not compact history or remove receipts.
165
+
161
166
  <a id="r1"></a>
162
167
 
163
168
  **R1 — Preparation and durability.** Use a fresh non-reused pack name. Register it
@@ -166,6 +171,10 @@ manifest. Capture the old append boundary before writing; incomplete cleanup mus
166
171
  never truncate an acknowledged prefix. Keep unresolved setup/cleanup state across
167
172
  errors. Synchronize data and required directory names, persist staging protection,
168
173
  then release preparation holds. Seal only after pending cleanup is resolved.
174
+ Within one writer incarnation, a successfully synchronized ancestor chain may be
175
+ reused while its directory inode stays pinned and matches the named directory.
176
+ Failed initialization establishes no cache entry. New file names and payloads
177
+ still require their own barriers; GC parent repair does not use this cache.
169
178
 
170
179
  <a id="r2"></a>
171
180
 
@@ -184,6 +193,10 @@ reference. Check extent bounds and selected frame/index agreement, authenticate
184
193
  the envelope and requested payload/checksum chunks, and bind tensor dtype/shape/
185
194
  length before returning or allocating payload. A cached index never skips
186
195
  record/envelope/payload validation. Empty typed ranges still validate layout.
196
+ The session uses an LRU of at most eight indexes and an 8 MiB encoded-metadata
197
+ budget; one oversized active index evicts all others. A miss authenticates before
198
+ admission. A failed miss cannot select an unrelated cached index. Each session
199
+ serializes its calls; independent sessions can read concurrently.
187
200
 
188
201
  <a id="r4"></a>
189
202
 
@@ -201,7 +214,7 @@ implementations remain external to finite protocol model checking.
201
214
 
202
215
  | Rule | TLA+ actions / properties | Deliberate abstraction |
203
216
  |---|---|---|
204
- | C3 | `WalRecovery`: Write/Fail/Scan/Truncate/RecoverSync, AcknowledgedSurvives, ReadyDurable. `CatalogTransaction`: BoundCaller, CacheMatchesPrefix, NoCachedAfterError. `CommitApplication`: Begin/Hook/Recover, AcceptedDataPresent | Frame parts abstract bytes; hashes/parser and lock service are external. Actual callbacks and all public guards need implementation review. |
217
+ | C3 | `WalRecovery`: Write/Fail/Scan/Truncate/RecoverSync, AcknowledgedSurvives, ReadyDurable. `CatalogTransaction`: BoundCaller, CacheMatchesPrefix, NoCachedAfterError; `CatalogReplay`: CoherentReady, confirmed-prefix reuse and dirty-cache rejection. `CommitApplication`: Begin/Hook/Recover, AcceptedDataPresent | Frame parts abstract bytes; hashes/parser and lock service are external. Actual callbacks and all public guards need implementation review. |
205
218
  | R1 | `PublicationPreparation`, `IncompletePublication`, `DirectoryDurability`, `ProvisionalHold`, `PublicationFinalization`: reservation, rollback, directory barriers, staging, sealing | Unique immutable names and truthful filesystem barriers; a live writer owns rollback authority. |
206
219
  | R2 | `PendingPublication`: OneCompletedFile, WriterFenced, DurableVerifiedReturn. `PublicationHandoff`: NoForgottenUnreturnedFile, CompletedHandoff. `StagingConsumption`: receipt/graph recovery | Failed responses can leave effects. Different API/request/content must not consume or overwrite unresolved output. |
207
220
  | R3 | `ReadAttempt`: Index/Frame/Envelope/Payload, NoUnverifiedReturn. `RangeRead`/`TypedRead`: authenticated ranges and layout. `NamespaceIdentity`: canonical bindings | Distinct wire/index/frame/envelope faults remain distinguishable. Warm caches authorize only an exact previously authenticated index, not record bytes. |
@@ -209,8 +222,8 @@ implementations remain external to finite protocol model checking.
209
222
 
210
223
  | Rules | Actual caller chain | Regression / counterexample entry |
211
224
  |---|---|---|
212
- | C3 | `journal_owner::{open,append_with,recover_with}` → `journal_io` → `journal_state`, `wal_append`, `wal_recovery`, `wal_source/sink`, `file_adapter`, `file_primitives`; `catalog_runtime::Transaction` → `catalog_transaction::execute`, `catalog_log`; `queue_application::{arm,apply,confirm,restore,permitted}` | `tests/test_wal_recovery.py`, `test_task_recovery.py`; native `gc` replacement-inode, nested-entry, caught-unwind, dirty-cache tests; `queue_application` callback/partial-body tests; byte-prefix/XOR and process-exit crash campaign |
213
- | R1–R2 | `Store::finish/publish_attempt/close`, `Config::finalize_publication` → `incomplete`, `pending`, `finalization`, `holding`; `gc::consume_once` → `staging_consumption` | `tests/test_publication_preparation.py`, `test_pending_publication.py`, `test_provisional_holds.py`, `test_commit_consumption.py`, `test_packed_store.py`; native streamed callback tests |
225
+ | C3 | `journal_owner::{open,append_with,recover_with}` → `journal_io` → `journal_state`, `wal_append`, `wal_recovery`, `wal_source/sink`, `file_adapter`, `file_primitives`; `catalog_runtime::Transaction` → `catalog_transaction::execute`, `catalog_log`; `Store::enter_writer` → `writer_gate::{Permit::registry,Registry::append}`; `queue_application::{arm,apply,confirm,restore,permitted}` | `tests/test_wal_recovery.py`, `test_task_recovery.py`; native `gc` and `writer_gate` identity, caught-unwind and dirty-cache tests; `queue_application` callback/partial-body tests; byte-prefix/XOR and process-exit crash campaign |
226
+ | R1–R2 | `Store::finish/publish_attempt/close/prepare_directory`, `Config::finalize_publication` → `incomplete`, `pending`, `finalization`, `holding`; `gc::consume_once` → `staging_consumption` | `tests/test_publication_preparation.py`, `test_pending_publication.py`, `test_provisional_holds.py`, `test_commit_consumption.py`, `test_packed_store.py`; native streamed callback and directory-cache failure/identity tests |
214
227
  | R3–R4 | `Reader` and read session in `rust/store.rs` → `record_index::Cache/Attempt`, `reference_node`, `extent_retry::run`, `bounds::frame_position/authenticated_span`, native read/hash operations | `tests/test_extent_visibility.py`, `test_read_session.py`, `test_extent_bounds.py`, `test_tensor_preflight.py`, `test_tensor_granularity.py`; TLC cold/warm cache, independent visibility, wrong index/frame/envelope/cache, payload corruption and stalled retry controls |
215
228
 
216
229
  </details>
@@ -241,20 +254,26 @@ compatibility API can perform authentication while already holding the lock.
241
254
  <a id="g3"></a>
242
255
 
243
256
  **G3 — Reclamation.** After C1's durable history retirement, prune only the current
244
- queue's obsolete owners. Under the catalog lock:
257
+ queue's obsolete owners. The public store/coordinator collection path orders:
245
258
 
246
259
  ```
247
- discover sealed packs not reachable from any owner
248
- append permanent tombstones; sync catalog
249
- unlink every pending target (including those advisory stat calls missing)
260
+ under the catalog lock: discover sealed unowned packs; mark and sync tombstones
261
+ capture the exact pending target set and catalog identity; release lock and mutex
262
+ unlink every captured target (including those advisory stat calls missing)
250
263
  sync every affected parent; repair/sync missing ancestor names if needed
251
- append reclamation receipts; sync catalog
264
+ reacquire and refresh the same catalog; receipt only completed targets still pending
265
+ sync the receipt before returning
252
266
  ```
253
267
 
254
268
  Unlink `NotFound` is idempotent absence, not durable deletion. Even an absent
255
269
  pending file needs its parent barrier. Other errors propagate and keep pending
256
270
  work. A receipt stops repeated deletion/accounting but retains the permanent
257
271
  tombstone; late retain cannot revive that path. Live extents protect whole packs.
272
+ Collectors may overlap: unlink is idempotent, and every collector completes its
273
+ own parent barriers. Never include targets added after this attempt's snapshot
274
+ in its receipt. A failed attempt leaves durable pending work for a later call.
275
+ The lower `LockedCatalog::collect` compatibility API retains its enclosing lock;
276
+ one coordinator's own calls also remain serialized.
258
277
  Offline cleanup requires stopped clients, no shared catalog/queue markers, a
259
278
  complete accepted-root/path-binding trace and a fresh unchanged inspection.
260
279
 
@@ -281,13 +300,13 @@ latency bound or automatic background collector follows from this rule.
281
300
  |---|---|---|
282
301
  | G1 | `Ownership`: ReaderProtection, CheckpointProtection, NoDanglingReferences. `DurableHandoff`: ReadersProtected; independent reader/checkpoint/peer cases | Complete application roots must be supplied by straw callers; reference possession is not a root. Permanent-owner cases check safety without assuming release. |
283
302
  | G2 | `ReactivationRace`: Prepare/Verify/Recheck/Append; AuthenticatedRoot, CompleteAuthorizedClosure, NoDanglingRestore. `DependencyTraversal`: CompleteClosure | A complete authenticated graph is the lower read boundary. Cache context mismatches cause fresh authentication; owner/root mismatch rejects before any owner append. |
284
- | G3 | `GCDiscovery`, `GCBatchDeletion`, `GCParentRepair`, `GCReceipt`: discovery, mark, unlink, shared-parent/ancestor barriers, receipt; DurableCompletion, ReceiptIsSafe, ReceiptKeepsFence | Multi-parent and missing-parent obligations remain separate; stat is advisory. `OfflineRoots`/`OfflineAliases` add stopped-client and binding roots, not permission for concurrent cleanup. |
303
+ | G3 | `GCConcurrentDeletion`: PlanFenced, ReceiptScoped, OwnedPresent; `GCDiscovery`, `GCBatchDeletion`, `GCParentRepair`, `GCReceipt`: discovery, mark, unlink, shared-parent/ancestor barriers, receipt; DurableCompletion, ReceiptIsSafe, ReceiptKeepsFence | Multi-parent and missing-parent obligations remain separate; stat is advisory. `OfflineRoots`/`OfflineAliases` add stopped-client and binding roots, not permission for concurrent cleanup. The concurrent model checks safety; retry/progress obligations remain in the lower GC models. |
285
304
  | G4 | `WriterRetirement`: register/hold/submit/finish, fence/drain/authenticate/recover/release/settle/seal/receipt; AuthenticatedRecovery, ReceiptSound, RequiredProgress. `WriterLifetime`: in-flight work. `DurableHandoff`: EventuallyReclaimed | Gate handoff must finish/cancel old remote I/O. Release and registry settlement are distinct crash steps. Liveness needs stabilization, scheduling and actual caller retries. |
286
305
 
287
306
  | Rules | Actual caller chain | Regression / counterexample entry |
288
307
  |---|---|---|
289
308
  | G1–G2 | `queue_roots::collect`, `queue_reader`, `queue_gc::prepare/require`; `gc::VerifiedReactivation::verify`, `check_reactivation_owners`, `retain_verified_inner`, `closure_inner` → `closure::collect`, `reference_node`, `record_index` | `tests/test_online_gc.py`, `test_queue_gc_roots.py`, `test_path_identity.py`; `tests/native.rs` reactivation pool/run, missing-source and owner-replacement races; TLC stale snapshot, wrong context/root and missing dependency controls |
290
- | G3 | `Coordinator` collection → `queue_retirement`, `queue_gc_prepare`, `gc_collection::Batch::run` → `gc_mark`, `gc_batch`, `gc_io`, `directory_io`, `gc_receipt` | `tests/test_gc_batch.py`, `test_gc_receipts.py`, `test_gc_missing_parent.py`, `test_offline_aliases.py`; native absent-file/failed-barrier and shared-parent tests; TLC early receipt, lost tombstone, missing parent controls |
309
+ | G3 | `Coordinator` collection → `queue_retirement`, `queue_gc_prepare`, `gc_plan::{plan_collection,Plan::execute,complete_collection}` → `gc_mark`, `gc_batch`, `gc_io`, `directory_io`, `gc_receipt` | `tests/test_gc_concurrency.py`, `test_gc_batch.py`, `test_gc_receipts.py`, `test_gc_missing_parent.py`, `test_offline_aliases.py`; native absent-file/failed-barrier and shared-parent tests; TLC early receipt, lost tombstone, missing parent controls |
291
310
  | G4 | `Store` mutation → `writer_gate_flow`, `writer_gate::Registry`; `Config::retire_writer` → `writer_retirement::execute`, `gc_writer::Retirement/Recovery`, `writer_registry::reconcile_registered`, `writer_ownership::authenticate_all` | `tests/test_writer_retirement.py`; native `gc_writer` corruption, recover/abandon and registered-owner tests; TLC death-unlock, skip registry/authentication, early release/receipt and conditional progress |
292
311
 
293
312
  </details>
@@ -314,6 +333,9 @@ reader/queue-checkpoint roots, receipts before directory sync and existing owner
314
333
  protecting the wrong root. The tables locate actual callers; public `checkpoint:*`
315
334
  owners and queue checkpoints require different tests. Run the checks in
316
335
  [contributing](../CONTRIBUTING.md#checks) and report current inputs and results.
336
+ `check_mutations.py` also checks selected concrete Rust faults against named
337
+ runtime regressions; compilation errors, missing tests and timeouts do not count
338
+ as detections.
317
339
 
318
340
  Finite models, concrete execution tests and source review are complementary;
319
341
  they do not establish complete Rust/Python/FFI equivalence, unbounded theorems or
@@ -104,10 +104,14 @@ Catalog 与队列日志独立。步骤之间崩溃可以多保留保护,不能
104
104
 
105
105
  恢复认证 framing 和精确哈希范围,按序重放完整事务,拒绝完整损坏 frame,只截断不完整残尾,完成同步并定位到有效末尾。业务索引、回执和派生缓存必须从同一前缀重建后才能复用。不得丢失已确认前缀。完整的不确定 frame 可以存活;重试不得产生第二次接受。
106
106
 
107
+ 独占 writer registry 可以在重新取得准确 gate、核对新打开日志的 inode 和长度后,复用已确认且完整应用的前缀及操作索引。不确定追加或应用会使缓存失效,必须重放。该优化不压缩历史,也不删除回执。
108
+
107
109
  <a id="r1"></a>
108
110
 
109
111
  **R1 — 准备与持久化。** 使用新且不复用的 pack 名称。数据 I/O 前登记为 open,写 manifest 前 retain 依赖准备 owner。写入前捕获旧追加边界;不完整清理不得截断已确认前缀。错误后保留未完成的准备/清理状态。同步数据及必要目录名称,持久化 staging 保护,之后才释放准备持有者。解决待清理状态后才能 seal。
110
112
 
113
+ 同一 writer incarnation 内,完整同步成功的祖先链可以复用,但必须保持目录 inode 打开并核对当前名称仍指向它。初始化失败不能建立缓存。新文件名称和 payload 仍需各自屏障;GC 修复父目录不使用这个缓存。
114
+
111
115
  <a id="r2"></a>
112
116
 
113
117
  **R2 — 发布重试。** 未决输出绑定准确 API、请求和内容。可能结果不明的同步之前先保存描述。拒绝冲突操作;正确重试重复未知屏障、认证原字节之后才返回。关闭或轮换不能丢掉已完成但尚未返回的描述。Staging 只交给准确的完成 handoff;旧交接完成后可以开始新的 staging 生命周期。
@@ -116,6 +120,8 @@ Catalog 与队列日志独立。步骤之间崩溃可以多保留保护,不能
116
120
 
117
121
  **R3 — 认证读取。** 调用者必须有 G1 保护。引用绑定 pool/run 和 namespace;index 缓存命中要求准确的不可变引用。检查 extent 边界及所选 frame 与 index 的一致性,认证 envelope 和请求 payload/checksum chunk,并在返回或分配 payload 前绑定 tensor dtype/shape/length。缓存 index 不得跳过 record/envelope/payload 校验。空 typed 区间仍需校验 layout。
118
122
 
123
+ 会话使用最多八条 index、8 MiB 编码元数据预算的 LRU;一个超大活动 index 会淘汰其他条目。未命中时先认证再缓存;失败不能选中无关的旧 index。同一会话的调用串行,独立会话可以并行读取。
124
+
119
125
  <a id="r4"></a>
120
126
 
121
127
  **R4 — 可见性与失败。** 文件长度、header、footer/index、envelope 和 payload 可以独立变得可见。只在共享有限预算内重试可识别的可见性失败;每次关闭失败句柄并重新打开。名称 `NotFound` 有独立有限查找预算;无关 I/O 错误停止。持久损坏必须耗尽/拒绝,不能返回未认证字节。最终可见性是部署前提,不是测得的 p99,也不保证任何输入都会成功。哈希、解析器、分配器和文件系统实现不在有限协议模型检查范围内。
@@ -125,7 +131,7 @@ Catalog 与队列日志独立。步骤之间崩溃可以多保留保护,不能
125
131
 
126
132
  | 规则 | TLA+ 动作/性质 | 有意保留的抽象差异 |
127
133
  |---|---|---|
128
- | C3 | `WalRecovery`:Write/Fail/Scan/Truncate/RecoverSync、AcknowledgedSurvives、ReadyDurable。`CatalogTransaction`:BoundCaller、CacheMatchesPrefix、NoCachedAfterError。`CommitApplication`:Begin/Hook/Recover、AcceptedDataPresent | frame 段抽象字节;哈希/解析器和锁服务外置。实际 callback 和全部公开入口 guard 仍需实现审查。 |
134
+ | C3 | `WalRecovery`:Write/Fail/Scan/Truncate/RecoverSync、AcknowledgedSurvives、ReadyDurable。`CatalogTransaction`:BoundCaller、CacheMatchesPrefix、NoCachedAfterError;`CatalogReplay`:CoherentReady、已确认前缀复用与 dirty cache 拒绝。`CommitApplication`:Begin/Hook/Recover、AcceptedDataPresent | frame 段抽象字节;哈希/解析器和锁服务外置。实际 callback 和全部公开入口 guard 仍需实现审查。 |
129
135
  | R1 | `PublicationPreparation`、`IncompletePublication`、`DirectoryDurability`、`ProvisionalHold`、`PublicationFinalization`:预留、回滚、目录屏障、staging、sealing | 唯一不可变名称及真实文件系统屏障;存活 writer 拥有回滚资格。 |
130
136
  | R2 | `PendingPublication`:OneCompletedFile、WriterFenced、DurableVerifiedReturn。`PublicationHandoff`:NoForgottenUnreturnedFile、CompletedHandoff。`StagingConsumption`:回执/图恢复 | 失败响应可留下效果;不同 API/请求/内容不能消费或覆盖未决输出。 |
131
137
  | R3 | `ReadAttempt`:Index/Frame/Envelope/Payload、NoUnverifiedReturn。`RangeRead`/`TypedRead`:认证区间及 layout。`NamespaceIdentity`:规范绑定 | wire/index/frame/envelope 错误分别建模;热缓存只授权准确的已认证 index,不授权 record 字节。 |
@@ -133,8 +139,8 @@ Catalog 与队列日志独立。步骤之间崩溃可以多保留保护,不能
133
139
 
134
140
  | 规则 | 实际调用链 | 回归/反例入口 |
135
141
  |---|---|---|
136
- | C3 | `journal_owner::{open,append_with,recover_with}` → `journal_io` → `journal_state`、`wal_append/recovery/source/sink`、`file_adapter/primitives`;`catalog_runtime::Transaction` → `catalog_transaction::execute`、`catalog_log`;`queue_application::{arm,apply,confirm,restore,permitted}` | `tests/test_wal_recovery.py`、`test_task_recovery.py`;原生 gc 的 inode 替换、嵌套入口、捕获 unwind、dirty cache;queue_application 的 callback/部分应用;逐字节残尾/XOR 与进程退出实验 |
137
- | R1–R2 | `Store::finish/publish_attempt/close`、`Config::finalize_publication` → `incomplete`、`pending`、`finalization`、`holding`;`gc::consume_once` → `staging_consumption` | `tests/test_publication_preparation.py`、`test_pending_publication.py`、`test_provisional_holds.py`、`test_commit_consumption.py`、`test_packed_store.py`;原生 stream callback 回归 |
142
+ | C3 | `journal_owner::{open,append_with,recover_with}` → `journal_io` → `journal_state`、`wal_append/recovery/source/sink`、`file_adapter/primitives`;`catalog_runtime::Transaction` → `catalog_transaction::execute`、`catalog_log`;`Store::enter_writer` → `writer_gate::{Permit::registry,Registry::append}`;`queue_application::{arm,apply,confirm,restore,permitted}` | `tests/test_wal_recovery.py`、`test_task_recovery.py`;原生 gc/writer_gate 的身份替换、捕获 unwind、dirty cache;queue_application 的 callback/部分应用;逐字节残尾/XOR 与进程退出实验 |
143
+ | R1–R2 | `Store::finish/publish_attempt/close/prepare_directory`、`Config::finalize_publication` → `incomplete`、`pending`、`finalization`、`holding`;`gc::consume_once` → `staging_consumption` | `tests/test_publication_preparation.py`、`test_pending_publication.py`、`test_provisional_holds.py`、`test_commit_consumption.py`、`test_packed_store.py`;原生 stream callback 与目录缓存失败/身份回归 |
138
144
  | R3–R4 | `rust/store.rs` 的 Reader/read session → `record_index::Cache/Attempt`、`reference_node`、`extent_retry::run`、`bounds::frame_position/authenticated_span`、实际 read/hash | `tests/test_extent_visibility.py`、`test_read_session.py`、`test_extent_bounds.py`、`test_tensor_preflight.py`、`test_tensor_granularity.py`;TLC 冷/热缓存、区域可见性、index/frame/envelope/cache 错误、payload 损坏、重试停滞 |
139
145
 
140
146
  </details>
@@ -153,18 +159,21 @@ Catalog 与队列日志独立。步骤之间崩溃可以多保留保护,不能
153
159
 
154
160
  <a id="g3"></a>
155
161
 
156
- **G3 — 回收。** C1 的历史退休持久化后,只裁剪当前队列的旧 owner。持 catalog 锁执行:
162
+ **G3 — 回收。** C1 的历史退休持久化后,只裁剪当前队列的旧 owner。公开 store/coordinator 回收路径按序执行:
157
163
 
158
164
  ```
159
- 发现 sealed 且不可从任何 owner 到达的 pack
160
- 追加永久 tombstone;同步 catalog
161
- unlink 全部 pending 目标(包括 advisory stat 声称不存在的目标)
165
+ 持 catalog 锁发现 sealed 且无主的 pack;追加永久 tombstone 并同步
166
+ 保存准确 pending 目标集合和 catalog 身份;释放文件锁与 mutex
167
+ unlink 本轮全部目标(包括 advisory stat 声称不存在的目标)
162
168
  同步全部受影响父目录;必要时修复并同步缺失祖先名称
163
- 追加回收回执;同步 catalog
169
+ 重新持锁恢复同一 catalog;只为本轮已完成且仍 pending 的目标记回执
170
+ 同步回执后返回
164
171
  ```
165
172
 
166
173
  Unlink `NotFound` 是幂等缺失,不是持久删除。已经缺失的 pending 文件仍需父目录屏障。其他错误上报并保留待办。回执停止重复删除/计数,但保留永久 tombstone;迟到 retain 不得复活路径。存活 extent 保护整个 pack。离线清理要求客户端停止、无共享 catalog/queue 标记、完整接受根及路径绑定追踪,以及新的未变化检查结果。
167
174
 
175
+ 多个 collector 可以重叠执行:unlink 幂等,各自完成自己目标的父目录屏障。回执不能包含本轮快照之后加入的目标。失败后持久 pending 留给后续调用处理。底层 `LockedCatalog::collect` 兼容 API 仍持有外层锁;同一个 coordinator 自身的调用也仍然串行。
176
+
168
177
  <a id="g4"></a>
169
178
 
170
179
  **G4 — Writer 退休与进展。** 每次 writer 修改持有准确 incarnation 的 gate 并检查持久 fence。产生效果前先登记操作身份、准备 owner 和依赖。退休获取相同 gate,持久化 fence,排空旧 I/O,对账已登记操作,然后释放准备 owner、记录结算、seal 预留文件、持久化退休回执。Recover 在释放前认证完整结果并 staging;abandon 不声称结果可读。重试可能重复任意已生效步骤。PID、年龄和超时都不能证明退休安全。
@@ -178,13 +187,13 @@ Owner 持续存在或错误反复发生时,安全性仍须成立。最终回
178
187
  |---|---|---|
179
188
  | G1 | `Ownership`:ReaderProtection、CheckpointProtection、NoDanglingReferences。`DurableHandoff`:ReadersProtected;独立 reader/checkpoint/peer 场景 | 完整应用根由 straw 调用者建立;持有引用不等于 owner。永久持有者场景不假定释放。 |
180
189
  | G2 | `ReactivationRace`:Prepare/Verify/Recheck/Append;AuthenticatedRoot、CompleteAuthorizedClosure、NoDanglingRestore。`DependencyTraversal`:CompleteClosure | 完整认证图是下层读取边界;缓存上下文不匹配必须重新认证,owner/root 不匹配必须在任何 owner 追加前拒绝。 |
181
- | G3 | `GCDiscovery`、`GCBatchDeletion`、`GCParentRepair`、`GCReceipt`:发现、mark、unlink、共享父目录/祖先屏障、回执;DurableCompletion、ReceiptIsSafe、ReceiptKeepsFence | 多父目录和缺失父目录义务独立,stat 仅供参考。`OfflineRoots`/`OfflineAliases` 增加停机及路径绑定根,不授权并发清理。 |
190
+ | G3 | `GCConcurrentDeletion`:PlanFenced、ReceiptScoped、OwnedPresent;`GCDiscovery`、`GCBatchDeletion`、`GCParentRepair`、`GCReceipt`:发现、mark、unlink、共享父目录/祖先屏障、回执;DurableCompletion、ReceiptIsSafe、ReceiptKeepsFence | 多父目录和缺失父目录义务独立,stat 仅供参考。`OfflineRoots`/`OfflineAliases` 增加停机及路径绑定根,不授权并发清理。并发模型检查安全性;重试/进展义务仍由下层 GC 模型检查。 |
182
191
  | G4 | `WriterRetirement`:register/hold/submit/finish、fence/drain/authenticate/recover/release/settle/seal/receipt;AuthenticatedRecovery、ReceiptSound、RequiredProgress。`WriterLifetime`:在途工作。`DurableHandoff`:EventuallyReclaimed | Gate 交接必须完成/取消旧远程 I/O;release 与 registry settlement 是独立崩溃点。活性需要稳定、公平调度和真实调用者重试。 |
183
192
 
184
193
  | 规则 | 实际调用链 | 回归/反例入口 |
185
194
  |---|---|---|
186
195
  | G1–G2 | `queue_roots::collect`、`queue_reader`、`queue_gc::prepare/require`;`gc::VerifiedReactivation::verify`、`check_reactivation_owners`、`retain_verified_inner`、`closure_inner` → `closure::collect`、`reference_node`、`record_index` | `tests/test_online_gc.py`、`test_queue_gc_roots.py`、`test_path_identity.py`;`tests/native.rs` 的 pool/run、source 丢失和 owner 替换竞态;TLC 旧快照、错误上下文/根、遗漏依赖 |
187
- | G3 | Coordinator collection → `queue_retirement`、`queue_gc_prepare`、`gc_collection::Batch::run` → `gc_mark`、`gc_batch`、`gc_io`、`directory_io`、`gc_receipt` | `tests/test_gc_batch.py`、`test_gc_receipts.py`、`test_gc_missing_parent.py`、`test_offline_aliases.py`;原生缺失文件/失败屏障/共享父目录;TLC 提前回执、丢失 tombstone、遗漏父目录 |
196
+ | G3 | Coordinator collection → `queue_retirement`、`queue_gc_prepare`、`gc_plan::{plan_collection,Plan::execute,complete_collection}` → `gc_mark`、`gc_batch`、`gc_io`、`directory_io`、`gc_receipt` | `tests/test_gc_concurrency.py`、 `test_gc_batch.py`、`test_gc_receipts.py`、`test_gc_missing_parent.py`、`test_offline_aliases.py`;原生缺失文件/失败屏障/共享父目录;TLC 提前回执、丢失 tombstone、遗漏父目录 |
188
197
  | G4 | Store 修改 → `writer_gate_flow`、`writer_gate::Registry`;`Config::retire_writer` → `writer_retirement::execute`、`gc_writer::Retirement/Recovery`、`writer_registry::reconcile_registered`、`writer_ownership::authenticate_all` | `tests/test_writer_retirement.py`;原生 gc_writer 的损坏、recover/abandon、已登记 owner;TLC death-unlock、跳过 registry/认证、提前 release/receipt 及条件进展 |
189
198
 
190
199
  </details>
@@ -199,4 +208,6 @@ Owner 持续存在或错误反复发生时,安全性仍须成立。最终回
199
208
 
200
209
  回归重点包括 WAL 前释放 staging、错误后复用部分状态、漏掉 reader/队列 checkpoint 根、目录同步前写回执,以及既有 owner 保护错误根。它们对应上表的真实调用点;公共 `checkpoint:*` owner 与队列 checkpoint 不能相互替代测试。按[贡献指南](../CONTRIBUTING_zh.md#checks)运行检查,报告当前输入和实际结果。
201
210
 
211
+ `check_mutations.py` 还对实际 Rust 代码注入选定故障,要求指定运行时回归失败;编译错误、缺失测试和超时均不算检出。
212
+
202
213
  有限模型、具体执行回归与源码审查提供互补证据,不构成完整 Rust/Python/FFI 等价证明、无界定理或文件系统掉电认证。进程退出保留内核和存储服务;不能据此推断真实存储服务故障行为。变更规则时同步模型、调用者、环境登记和中英文正文;验证日志保存在 CI artifacts 或忽略目录中,不追加成规格正文。
@@ -356,7 +356,7 @@ On recovery, first restore the chosen checkpoint's model/optimizer/RNG and its m
356
356
 
357
357
  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
358
 
359
- The Rust reader retains only the last authenticated index, keyed by the complete extent descriptor. 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 after an extent switch or in a new session. 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.
359
+ 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.
360
360
 
361
361
  Publication dependency validation, continuation batches, consumer snapshots and GC traversal use the same bounded native reader internally. Formats, WAL commit ordering, owner-release rules remain unchanged; logical capacity quotas are no longer enforced.
362
362
 
@@ -195,7 +195,7 @@ b.submit_tasks("b-1", [TaskSpec("task-b", input_ref=dependency)])
195
195
 
196
196
  连续读取不可变 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
197
 
198
- Rust reader 只保留最后一个已认证索引,以完整 extent 描述符区分身份。每次 manifest/record 读取仍校验 frame 和载荷;张量读取仍校验触及的 chunk。每次 `validate` 都重新检查逻辑描述符与 task/attempt 权限。切换 extent 或开启新会话后重新认证索引。整个读取过程必须由持久 owner 或 `store.pin` 保护:读取会话本身不保留存储所有权。退出上下文会关闭会话,fork 后继承的会话拒绝所有操作。
198
+ Rust reader 使用最多八条已认证索引的 LRU,以完整 extent 描述符区分身份,编码元数据预算为 8 MiB;一个超大活动 index 会淘汰其他条目。每次 manifest/record 读取仍校验 frame 和载荷;张量读取仍校验触及的 chunk。每次 `validate` 都重新检查逻辑描述符与 task/attempt 权限。缓存未命中或开启新会话后重新认证索引。同一会话的调用串行,并行读取应使用独立会话。整个读取过程必须由持久 owner 或 `store.pin` 保护:读取会话本身不保留存储所有权。退出上下文会关闭会话,fork 后继承的会话拒绝所有操作。
199
199
 
200
200
  发布依赖校验、批量续跑进度、消费者快照及 GC 遍历在 Rust 内部也复用这种有界 reader。文件格式、WAL 提交顺序、容量限制和所有权释放规则均未改变。
201
201
 
@@ -4,7 +4,7 @@ build-backend = "maturin"
4
4
 
5
5
  [project]
6
6
  name = "straw-queue"
7
- version = "0.1.5"
7
+ version = "0.1.6"
8
8
  description = "Rust durable queues for AI tensors and large immutable records"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.10"
@@ -13,6 +13,7 @@ pub type CollectionResult<E> = Result<
13
13
  crate::gc_collection::Collected,
14
14
  crate::gc_batch::Failure<crate::gc_collection::Error<E, E, E>>,
15
15
  >;
16
+ #[cfg(test)]
16
17
  pub type QueueCollectionResult<E> =
17
18
  Result<crate::gc_collection::Collected, crate::gc_collection::QueueFailure<E, E, E>>;
18
19
 
@@ -309,6 +310,7 @@ impl<S: Source> Catalog<S> {
309
310
  }
310
311
 
311
312
  impl<S: Source> Catalog<S> {
313
+ #[cfg(test)]
312
314
  pub(crate) fn collect_queue_native<L, H, P>(
313
315
  &mut self,
314
316
  prepared: crate::queue_gc::Prepared<'_>,
@@ -21,6 +21,9 @@ use std::fs::File;
21
21
  use std::io::Write;
22
22
  use std::path::{Path, PathBuf};
23
23
 
24
+ #[path = "gc_plan.rs"]
25
+ mod collection;
26
+
24
27
  fn catalog_append_error(error: crate::catalog_append::Error<Error, Error>) -> Error {
25
28
  match error {
26
29
  crate::catalog_append::Error::Decode(error) => catalog_decode_error(error),
@@ -60,11 +63,20 @@ fn collection_error(
60
63
  }
61
64
  }
62
65
 
66
+ #[cfg(test)]
63
67
  fn queue_collection_error(error: crate::gc_collection::QueueFailure<Error, Error, Error>) -> Error {
64
68
  match error {
65
69
  crate::gc_collection::QueueFailure::Collect(error) => collection_error(error),
66
- crate::gc_collection::QueueFailure::Prune(error) => catalog_append_error(error),
67
- crate::gc_collection::QueueFailure::Ownership(error) => match error {
70
+ crate::gc_collection::QueueFailure::Preparation(error) => queue_preparation_error(error),
71
+ }
72
+ }
73
+
74
+ fn queue_preparation_error(
75
+ error: crate::gc_collection::QueuePreparationFailure<Error, Error>,
76
+ ) -> Error {
77
+ match error {
78
+ crate::gc_collection::QueuePreparationFailure::Prune(error) => catalog_append_error(error),
79
+ crate::gc_collection::QueuePreparationFailure::Ownership(error) => match error {
68
80
  crate::queue_gc::OwnershipError::Missing => Error::new(
69
81
  "UnsafeRecovery",
70
82
  "Live queue root has no durable storage owner",
@@ -74,7 +86,7 @@ fn queue_collection_error(error: crate::gc_collection::QueueFailure<Error, Error
74
86
  "Live queue root has invalid storage ownership",
75
87
  ),
76
88
  },
77
- crate::gc_collection::QueueFailure::Reserved => Error::new(
89
+ crate::gc_collection::QueuePreparationFailure::Reserved => Error::new(
78
90
  "ValueError",
79
91
  "publication: is reserved for durable writer operations",
80
92
  ),
@@ -622,11 +634,6 @@ impl<T, F: FnOnce(&mut LockedCatalog<'_>) -> Result<T>>
622
634
  (self.0)(&mut LockedCatalog { catalog })
623
635
  }
624
636
  }
625
- impl crate::catalog_gc::Library for crate::wal_file::NativeLibrary {
626
- fn queue_error(error: crate::gc_collection::QueueFailure<Error, Error, Error>) -> Error {
627
- queue_collection_error(error)
628
- }
629
- }
630
637
  impl crate::catalog_runtime::Library for crate::wal_file::NativeLibrary {
631
638
  fn binding_error() -> Error {
632
639
  Error::new(
@@ -1330,28 +1337,6 @@ impl Catalog {
1330
1337
  Ok(self.collection_summary(result))
1331
1338
  }
1332
1339
 
1333
- pub(crate) fn collect_queue_transaction(
1334
- &mut self,
1335
- config: &Config,
1336
- prepared: crate::queue_gc::Prepared<'_>,
1337
- fault: &mut Fault<'_>,
1338
- ) -> Result<Value> {
1339
- let call = crate::catalog_gc::Queue::<crate::wal_file::NativeLibrary, _, _>::new(
1340
- prepared,
1341
- crate::wal_file::NativeHooks(fault),
1342
- PhysicalIo {
1343
- config,
1344
- stat: |path: &Path| std::fs::metadata(path),
1345
- },
1346
- );
1347
- let result = self.execute::<crate::wal_file::NativeLibrary, _>(
1348
- config.root.to_str(),
1349
- &config.run_id,
1350
- call,
1351
- );
1352
- Ok(self.collection_summary(transaction_result(result)?))
1353
- }
1354
-
1355
1340
  fn collection_summary(&self, result: crate::gc_collection::Collected) -> Value {
1356
1341
  json!({"reclaimed_files":result.statistics.files,"reclaimed_bytes":result.statistics.bytes,"owners":self.log.indexes().owners.len(),
1357
1342
  "open_packs":self.log.indexes().packs.iter().filter(|(p,s)| !**s && !self.log.indexes().deleted.contains(*p)).count(),
@@ -1,6 +1,6 @@
1
1
  //! The production batch deletion dispatch. Native effects must bind each index
2
2
  //! to its durable tombstone and stable parent directory; errors may have effects.
3
- use crate::protocol::{self, DeleteEffect, ReclaimEffect};
3
+ use crate::protocol::{self, DeleteEffect};
4
4
  use std::collections::BTreeSet;
5
5
 
6
6
  pub trait BatchModel {
@@ -42,6 +42,15 @@ pub trait Effects: BatchModel {
42
42
  /// Already-absent names still contribute their parent; a receipt may survive
43
43
  /// an error response, so its precondition requires durable absence already.
44
44
  pub fn collect<E: Effects>(effects: &mut E) -> Result<Statistics, Failure<E::Error>> {
45
+ let statistics = delete(effects)?;
46
+ effects.receipt().map_err(Failure::Effect)?;
47
+ Ok(statistics)
48
+ }
49
+
50
+ /// Physical half of collection. A caller may release the catalog lock only
51
+ /// after durably marking these exact immutable names. Returning this result
52
+ /// authorizes a later receipt, never an earlier one.
53
+ pub fn delete<E: Effects>(effects: &mut E) -> Result<Statistics, Failure<E::Error>> {
45
54
  let count = effects.target_count();
46
55
  let mut parents = BTreeSet::new();
47
56
  let mut pending = Vec::new();
@@ -75,34 +84,11 @@ pub fn collect<E: Effects>(effects: &mut E) -> Result<Statistics, Failure<E::Err
75
84
  index += 1;
76
85
  }
77
86
 
78
- let mut state = protocol::reclaim_start();
79
-
80
- loop {
81
- let effect = match protocol::reclaim_next(&state) {
82
- Some(effect) => effect,
83
- None => {
84
- if !protocol::reclaim_finished(&state) {
85
- return Err(Failure::Protocol);
86
- }
87
- return Ok(Statistics { files, bytes });
88
- }
89
- };
90
- match effect {
91
- ReclaimEffect::SyncParents => {
92
- for parent in &parents {
93
- effects.sync_parent(parent).map_err(Failure::Effect)?;
94
- }
95
-
96
- if !protocol::delete_batch_finished(&pending, true) {
97
- return Err(Failure::Protocol);
98
- }
99
- }
100
- ReclaimEffect::RecordReceipt => {
101
- if let Err(error) = effects.receipt() {
102
- return Err(Failure::Effect(error));
103
- }
104
- }
105
- }
106
- state = protocol::reclaim_advance(state, true);
87
+ for parent in &parents {
88
+ effects.sync_parent(parent).map_err(Failure::Effect)?;
89
+ }
90
+ if !protocol::delete_batch_finished(&pending, true) {
91
+ return Err(Failure::Protocol);
107
92
  }
93
+ Ok(Statistics { files, bytes })
108
94
  }