cc-transcript 14.45.10__tar.gz → 14.45.12__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 (198) hide show
  1. {cc_transcript-14.45.10 → cc_transcript-14.45.12}/PKG-INFO +1 -1
  2. {cc_transcript-14.45.10 → cc_transcript-14.45.12}/pyproject.toml +1 -1
  3. {cc_transcript-14.45.10 → cc_transcript-14.45.12}/rust/crates/core/src/snapshot.rs +194 -0
  4. {cc_transcript-14.45.10 → cc_transcript-14.45.12}/rust/crates/core/src/snapshot_prepared_disk.rs +214 -7
  5. {cc_transcript-14.45.10 → cc_transcript-14.45.12}/rust/crates/core/src/snapshot_prepared_service.rs +28 -8
  6. {cc_transcript-14.45.10 → cc_transcript-14.45.12}/Cargo.lock +0 -0
  7. {cc_transcript-14.45.10 → cc_transcript-14.45.12}/Cargo.toml +0 -0
  8. {cc_transcript-14.45.10 → cc_transcript-14.45.12}/LICENSE +0 -0
  9. {cc_transcript-14.45.10 → cc_transcript-14.45.12}/README.md +0 -0
  10. {cc_transcript-14.45.10 → cc_transcript-14.45.12}/cc_transcript/__init__.py +0 -0
  11. {cc_transcript-14.45.10 → cc_transcript-14.45.12}/cc_transcript/__init__.pyi +0 -0
  12. {cc_transcript-14.45.10 → cc_transcript-14.45.12}/cc_transcript/_native.pyi +0 -0
  13. {cc_transcript-14.45.10 → cc_transcript-14.45.12}/cc_transcript/activity.py +0 -0
  14. {cc_transcript-14.45.10 → cc_transcript-14.45.12}/cc_transcript/activity_probe.py +0 -0
  15. {cc_transcript-14.45.10 → cc_transcript-14.45.12}/cc_transcript/builders.py +0 -0
  16. {cc_transcript-14.45.10 → cc_transcript-14.45.12}/cc_transcript/codex.py +0 -0
  17. {cc_transcript-14.45.10 → cc_transcript-14.45.12}/cc_transcript/command.py +0 -0
  18. {cc_transcript-14.45.10 → cc_transcript-14.45.12}/cc_transcript/context.py +0 -0
  19. {cc_transcript-14.45.10 → cc_transcript-14.45.12}/cc_transcript/corrections.py +0 -0
  20. {cc_transcript-14.45.10 → cc_transcript-14.45.12}/cc_transcript/cost.py +0 -0
  21. {cc_transcript-14.45.10 → cc_transcript-14.45.12}/cc_transcript/decision_store.py +0 -0
  22. {cc_transcript-14.45.10 → cc_transcript-14.45.12}/cc_transcript/decisions.py +0 -0
  23. {cc_transcript-14.45.10 → cc_transcript-14.45.12}/cc_transcript/discovery.py +0 -0
  24. {cc_transcript-14.45.10 → cc_transcript-14.45.12}/cc_transcript/disktruth.py +0 -0
  25. {cc_transcript-14.45.10 → cc_transcript-14.45.12}/cc_transcript/evidence.py +0 -0
  26. {cc_transcript-14.45.10 → cc_transcript-14.45.12}/cc_transcript/extract/__init__.py +0 -0
  27. {cc_transcript-14.45.10 → cc_transcript-14.45.12}/cc_transcript/extract/correct.py +0 -0
  28. {cc_transcript-14.45.10 → cc_transcript-14.45.12}/cc_transcript/facts.py +0 -0
  29. {cc_transcript-14.45.10 → cc_transcript-14.45.12}/cc_transcript/filterspec.py +0 -0
  30. {cc_transcript-14.45.10 → cc_transcript-14.45.12}/cc_transcript/heartbeats.py +0 -0
  31. {cc_transcript-14.45.10 → cc_transcript-14.45.12}/cc_transcript/ids.py +0 -0
  32. {cc_transcript-14.45.10 → cc_transcript-14.45.12}/cc_transcript/judge/__init__.py +0 -0
  33. {cc_transcript-14.45.10 → cc_transcript-14.45.12}/cc_transcript/judge/llm.py +0 -0
  34. {cc_transcript-14.45.10 → cc_transcript-14.45.12}/cc_transcript/judge/similar.py +0 -0
  35. {cc_transcript-14.45.10 → cc_transcript-14.45.12}/cc_transcript/judge/verdicts.py +0 -0
  36. {cc_transcript-14.45.10 → cc_transcript-14.45.12}/cc_transcript/ledger.py +0 -0
  37. {cc_transcript-14.45.10 → cc_transcript-14.45.12}/cc_transcript/literals.py +0 -0
  38. {cc_transcript-14.45.10 → cc_transcript-14.45.12}/cc_transcript/mining/__init__.py +0 -0
  39. {cc_transcript-14.45.10 → cc_transcript-14.45.12}/cc_transcript/mining/candidates.py +0 -0
  40. {cc_transcript-14.45.10 → cc_transcript-14.45.12}/cc_transcript/mining/confidence.py +0 -0
  41. {cc_transcript-14.45.10 → cc_transcript-14.45.12}/cc_transcript/mining/engine.py +0 -0
  42. {cc_transcript-14.45.10 → cc_transcript-14.45.12}/cc_transcript/mining/formats.py +0 -0
  43. {cc_transcript-14.45.10 → cc_transcript-14.45.12}/cc_transcript/mining/sampling.py +0 -0
  44. {cc_transcript-14.45.10 → cc_transcript-14.45.12}/cc_transcript/mining/signals.py +0 -0
  45. {cc_transcript-14.45.10 → cc_transcript-14.45.12}/cc_transcript/mining/sourcekind.py +0 -0
  46. {cc_transcript-14.45.10 → cc_transcript-14.45.12}/cc_transcript/mining/spec.py +0 -0
  47. {cc_transcript-14.45.10 → cc_transcript-14.45.12}/cc_transcript/mining/store.py +0 -0
  48. {cc_transcript-14.45.10 → cc_transcript-14.45.12}/cc_transcript/models.py +0 -0
  49. {cc_transcript-14.45.10 → cc_transcript-14.45.12}/cc_transcript/nlp.py +0 -0
  50. {cc_transcript-14.45.10 → cc_transcript-14.45.12}/cc_transcript/notifications.py +0 -0
  51. {cc_transcript-14.45.10 → cc_transcript-14.45.12}/cc_transcript/parser.py +0 -0
  52. {cc_transcript-14.45.10 → cc_transcript-14.45.12}/cc_transcript/py.typed +0 -0
  53. {cc_transcript-14.45.10 → cc_transcript-14.45.12}/cc_transcript/query.py +0 -0
  54. {cc_transcript-14.45.10 → cc_transcript-14.45.12}/cc_transcript/render.py +0 -0
  55. {cc_transcript-14.45.10 → cc_transcript-14.45.12}/cc_transcript/sentiment/__init__.py +0 -0
  56. {cc_transcript-14.45.10 → cc_transcript-14.45.12}/cc_transcript/sentiment/buckets.py +0 -0
  57. {cc_transcript-14.45.10 → cc_transcript-14.45.12}/cc_transcript/sentiment/data/afinn-en-165.tsv +0 -0
  58. {cc_transcript-14.45.10 → cc_transcript-14.45.12}/cc_transcript/sentiment/data/domain_overrides.tsv +0 -0
  59. {cc_transcript-14.45.10 → cc_transcript-14.45.12}/cc_transcript/sentiment/data/en-ewt.udpipe +0 -0
  60. {cc_transcript-14.45.10 → cc_transcript-14.45.12}/cc_transcript/sentiment/engine.py +0 -0
  61. {cc_transcript-14.45.10 → cc_transcript-14.45.12}/cc_transcript/sentiment/lexicon.py +0 -0
  62. {cc_transcript-14.45.10 → cc_transcript-14.45.12}/cc_transcript/sentiment/scorespec.py +0 -0
  63. {cc_transcript-14.45.10 → cc_transcript-14.45.12}/cc_transcript/snapshot_schema/config.schema.json +0 -0
  64. {cc_transcript-14.45.10 → cc_transcript-14.45.12}/cc_transcript/snapshot_schema/context.schema.json +0 -0
  65. {cc_transcript-14.45.10 → cc_transcript-14.45.12}/cc_transcript/snapshot_schema/request.schema.json +0 -0
  66. {cc_transcript-14.45.10 → cc_transcript-14.45.12}/cc_transcript/snapshot_schema/response.schema.json +0 -0
  67. {cc_transcript-14.45.10 → cc_transcript-14.45.12}/cc_transcript/snapshot_schema/tool_registry.schema.json +0 -0
  68. {cc_transcript-14.45.10 → cc_transcript-14.45.12}/cc_transcript/snapshots.py +0 -0
  69. {cc_transcript-14.45.10 → cc_transcript-14.45.12}/cc_transcript/synthetic.py +0 -0
  70. {cc_transcript-14.45.10 → cc_transcript-14.45.12}/cc_transcript/tools.py +0 -0
  71. {cc_transcript-14.45.10 → cc_transcript-14.45.12}/cc_transcript/watch.py +0 -0
  72. {cc_transcript-14.45.10 → cc_transcript-14.45.12}/rust/crates/cli/Cargo.toml +0 -0
  73. {cc_transcript-14.45.10 → cc_transcript-14.45.12}/rust/crates/cli/src/commands/blame.rs +0 -0
  74. {cc_transcript-14.45.10 → cc_transcript-14.45.12}/rust/crates/cli/src/commands/corpus.rs +0 -0
  75. {cc_transcript-14.45.10 → cc_transcript-14.45.12}/rust/crates/cli/src/commands/corrections.rs +0 -0
  76. {cc_transcript-14.45.10 → cc_transcript-14.45.12}/rust/crates/cli/src/commands/digest.rs +0 -0
  77. {cc_transcript-14.45.10 → cc_transcript-14.45.12}/rust/crates/cli/src/commands/facts.rs +0 -0
  78. {cc_transcript-14.45.10 → cc_transcript-14.45.12}/rust/crates/cli/src/commands/grep.rs +0 -0
  79. {cc_transcript-14.45.10 → cc_transcript-14.45.12}/rust/crates/cli/src/commands/list.rs +0 -0
  80. {cc_transcript-14.45.10 → cc_transcript-14.45.12}/rust/crates/cli/src/commands/mod.rs +0 -0
  81. {cc_transcript-14.45.10 → cc_transcript-14.45.12}/rust/crates/cli/src/commands/scratchpad.rs +0 -0
  82. {cc_transcript-14.45.10 → cc_transcript-14.45.12}/rust/crates/cli/src/commands/show.rs +0 -0
  83. {cc_transcript-14.45.10 → cc_transcript-14.45.12}/rust/crates/cli/src/commands/slice.rs +0 -0
  84. {cc_transcript-14.45.10 → cc_transcript-14.45.12}/rust/crates/cli/src/commands/stats.rs +0 -0
  85. {cc_transcript-14.45.10 → cc_transcript-14.45.12}/rust/crates/cli/src/commands/watch.rs +0 -0
  86. {cc_transcript-14.45.10 → cc_transcript-14.45.12}/rust/crates/cli/src/lib.rs +0 -0
  87. {cc_transcript-14.45.10 → cc_transcript-14.45.12}/rust/crates/cli/src/output.rs +0 -0
  88. {cc_transcript-14.45.10 → cc_transcript-14.45.12}/rust/crates/cli/src/target.rs +0 -0
  89. {cc_transcript-14.45.10 → cc_transcript-14.45.12}/rust/crates/cli/src/timearg.rs +0 -0
  90. {cc_transcript-14.45.10 → cc_transcript-14.45.12}/rust/crates/core/Cargo.toml +0 -0
  91. {cc_transcript-14.45.10 → cc_transcript-14.45.12}/rust/crates/core/benches/parse.rs +0 -0
  92. {cc_transcript-14.45.10 → cc_transcript-14.45.12}/rust/crates/core/benches/render.rs +0 -0
  93. {cc_transcript-14.45.10 → cc_transcript-14.45.12}/rust/crates/core/benches/toolcall.rs +0 -0
  94. {cc_transcript-14.45.10 → cc_transcript-14.45.12}/rust/crates/core/build.rs +0 -0
  95. {cc_transcript-14.45.10 → cc_transcript-14.45.12}/rust/crates/core/src/activity.rs +0 -0
  96. {cc_transcript-14.45.10 → cc_transcript-14.45.12}/rust/crates/core/src/actor.rs +0 -0
  97. {cc_transcript-14.45.10 → cc_transcript-14.45.12}/rust/crates/core/src/blame.rs +0 -0
  98. {cc_transcript-14.45.10 → cc_transcript-14.45.12}/rust/crates/core/src/buckets.rs +0 -0
  99. {cc_transcript-14.45.10 → cc_transcript-14.45.12}/rust/crates/core/src/codex/discovery.rs +0 -0
  100. {cc_transcript-14.45.10 → cc_transcript-14.45.12}/rust/crates/core/src/codex/lower.rs +0 -0
  101. {cc_transcript-14.45.10 → cc_transcript-14.45.12}/rust/crates/core/src/codex/mod.rs +0 -0
  102. {cc_transcript-14.45.10 → cc_transcript-14.45.12}/rust/crates/core/src/codex/parse.rs +0 -0
  103. {cc_transcript-14.45.10 → cc_transcript-14.45.12}/rust/crates/core/src/codex/probe.rs +0 -0
  104. {cc_transcript-14.45.10 → cc_transcript-14.45.12}/rust/crates/core/src/codex/protocol.rs +0 -0
  105. {cc_transcript-14.45.10 → cc_transcript-14.45.12}/rust/crates/core/src/codex/types.rs +0 -0
  106. {cc_transcript-14.45.10 → cc_transcript-14.45.12}/rust/crates/core/src/command.rs +0 -0
  107. {cc_transcript-14.45.10 → cc_transcript-14.45.12}/rust/crates/core/src/context.rs +0 -0
  108. {cc_transcript-14.45.10 → cc_transcript-14.45.12}/rust/crates/core/src/corrections.rs +0 -0
  109. {cc_transcript-14.45.10 → cc_transcript-14.45.12}/rust/crates/core/src/cost.rs +0 -0
  110. {cc_transcript-14.45.10 → cc_transcript-14.45.12}/rust/crates/core/src/discovery.rs +0 -0
  111. {cc_transcript-14.45.10 → cc_transcript-14.45.12}/rust/crates/core/src/facts.rs +0 -0
  112. {cc_transcript-14.45.10 → cc_transcript-14.45.12}/rust/crates/core/src/feedback.rs +0 -0
  113. {cc_transcript-14.45.10 → cc_transcript-14.45.12}/rust/crates/core/src/filter.rs +0 -0
  114. {cc_transcript-14.45.10 → cc_transcript-14.45.12}/rust/crates/core/src/gateway.rs +0 -0
  115. {cc_transcript-14.45.10 → cc_transcript-14.45.12}/rust/crates/core/src/ids.rs +0 -0
  116. {cc_transcript-14.45.10 → cc_transcript-14.45.12}/rust/crates/core/src/judge.rs +0 -0
  117. {cc_transcript-14.45.10 → cc_transcript-14.45.12}/rust/crates/core/src/lib.rs +0 -0
  118. {cc_transcript-14.45.10 → cc_transcript-14.45.12}/rust/crates/core/src/literals/command.rs +0 -0
  119. {cc_transcript-14.45.10 → cc_transcript-14.45.12}/rust/crates/core/src/literals/corrections.rs +0 -0
  120. {cc_transcript-14.45.10 → cc_transcript-14.45.12}/rust/crates/core/src/literals/feedback.rs +0 -0
  121. {cc_transcript-14.45.10 → cc_transcript-14.45.12}/rust/crates/core/src/literals/mining.rs +0 -0
  122. {cc_transcript-14.45.10 → cc_transcript-14.45.12}/rust/crates/core/src/literals/mod.rs +0 -0
  123. {cc_transcript-14.45.10 → cc_transcript-14.45.12}/rust/crates/core/src/literals/protocol.rs +0 -0
  124. {cc_transcript-14.45.10 → cc_transcript-14.45.12}/rust/crates/core/src/notifications.rs +0 -0
  125. {cc_transcript-14.45.10 → cc_transcript-14.45.12}/rust/crates/core/src/parse.rs +0 -0
  126. {cc_transcript-14.45.10 → cc_transcript-14.45.12}/rust/crates/core/src/protocol.rs +0 -0
  127. {cc_transcript-14.45.10 → cc_transcript-14.45.12}/rust/crates/core/src/pystr.rs +0 -0
  128. {cc_transcript-14.45.10 → cc_transcript-14.45.12}/rust/crates/core/src/query.rs +0 -0
  129. {cc_transcript-14.45.10 → cc_transcript-14.45.12}/rust/crates/core/src/render.rs +0 -0
  130. {cc_transcript-14.45.10 → cc_transcript-14.45.12}/rust/crates/core/src/rng.rs +0 -0
  131. {cc_transcript-14.45.10 → cc_transcript-14.45.12}/rust/crates/core/src/scan.rs +0 -0
  132. {cc_transcript-14.45.10 → cc_transcript-14.45.12}/rust/crates/core/src/scan_checkpoint.rs +0 -0
  133. {cc_transcript-14.45.10 → cc_transcript-14.45.12}/rust/crates/core/src/scan_grep.rs +0 -0
  134. {cc_transcript-14.45.10 → cc_transcript-14.45.12}/rust/crates/core/src/scan_grep_stream.rs +0 -0
  135. {cc_transcript-14.45.10 → cc_transcript-14.45.12}/rust/crates/core/src/scan_grep_stream_tests.rs +0 -0
  136. {cc_transcript-14.45.10 → cc_transcript-14.45.12}/rust/crates/core/src/scan_index.rs +0 -0
  137. {cc_transcript-14.45.10 → cc_transcript-14.45.12}/rust/crates/core/src/scan_projection.rs +0 -0
  138. {cc_transcript-14.45.10 → cc_transcript-14.45.12}/rust/crates/core/src/scan_regressions.rs +0 -0
  139. {cc_transcript-14.45.10 → cc_transcript-14.45.12}/rust/crates/core/src/scan_stream.rs +0 -0
  140. {cc_transcript-14.45.10 → cc_transcript-14.45.12}/rust/crates/core/src/schema.rs +0 -0
  141. {cc_transcript-14.45.10 → cc_transcript-14.45.12}/rust/crates/core/src/snapshot_activity.rs +0 -0
  142. {cc_transcript-14.45.10 → cc_transcript-14.45.12}/rust/crates/core/src/snapshot_codec.rs +0 -0
  143. {cc_transcript-14.45.10 → cc_transcript-14.45.12}/rust/crates/core/src/snapshot_codex_append.rs +0 -0
  144. {cc_transcript-14.45.10 → cc_transcript-14.45.12}/rust/crates/core/src/snapshot_labels.rs +0 -0
  145. {cc_transcript-14.45.10 → cc_transcript-14.45.12}/rust/crates/core/src/snapshot_ledger.rs +0 -0
  146. {cc_transcript-14.45.10 → cc_transcript-14.45.12}/rust/crates/core/src/snapshot_ledger_tests.rs +0 -0
  147. {cc_transcript-14.45.10 → cc_transcript-14.45.12}/rust/crates/core/src/snapshot_memory.rs +0 -0
  148. {cc_transcript-14.45.10 → cc_transcript-14.45.12}/rust/crates/core/src/snapshot_owned.rs +0 -0
  149. {cc_transcript-14.45.10 → cc_transcript-14.45.12}/rust/crates/core/src/snapshot_prepared.rs +0 -0
  150. {cc_transcript-14.45.10 → cc_transcript-14.45.12}/rust/crates/core/src/snapshot_projection.rs +0 -0
  151. {cc_transcript-14.45.10 → cc_transcript-14.45.12}/rust/crates/core/src/snapshot_regressions.rs +0 -0
  152. {cc_transcript-14.45.10 → cc_transcript-14.45.12}/rust/crates/core/src/snapshot_root_warm.rs +0 -0
  153. {cc_transcript-14.45.10 → cc_transcript-14.45.12}/rust/crates/core/src/snapshot_text.rs +0 -0
  154. {cc_transcript-14.45.10 → cc_transcript-14.45.12}/rust/crates/core/src/sqlite.rs +0 -0
  155. {cc_transcript-14.45.10 → cc_transcript-14.45.12}/rust/crates/core/src/toolcall.rs +0 -0
  156. {cc_transcript-14.45.10 → cc_transcript-14.45.12}/rust/crates/core/src/types.rs +0 -0
  157. {cc_transcript-14.45.10 → cc_transcript-14.45.12}/rust/crates/core/src/value.rs +0 -0
  158. {cc_transcript-14.45.10 → cc_transcript-14.45.12}/rust/crates/core/src/watch.rs +0 -0
  159. {cc_transcript-14.45.10 → cc_transcript-14.45.12}/rust/crates/core/tests/sonic_arena_model.rs +0 -0
  160. {cc_transcript-14.45.10 → cc_transcript-14.45.12}/rust/crates/core/tests/std_allocation_model.rs +0 -0
  161. {cc_transcript-14.45.10 → cc_transcript-14.45.12}/rust/crates/py/Cargo.toml +0 -0
  162. {cc_transcript-14.45.10 → cc_transcript-14.45.12}/rust/crates/py/build.rs +0 -0
  163. {cc_transcript-14.45.10 → cc_transcript-14.45.12}/rust/crates/py/data/command_prefix_pins.tsv +0 -0
  164. {cc_transcript-14.45.10 → cc_transcript-14.45.12}/rust/crates/py/src/actor_bridge.rs +0 -0
  165. {cc_transcript-14.45.10 → cc_transcript-14.45.12}/rust/crates/py/src/bin/stub_gen.rs +0 -0
  166. {cc_transcript-14.45.10 → cc_transcript-14.45.12}/rust/crates/py/src/codex.rs +0 -0
  167. {cc_transcript-14.45.10 → cc_transcript-14.45.12}/rust/crates/py/src/command.rs +0 -0
  168. {cc_transcript-14.45.10 → cc_transcript-14.45.12}/rust/crates/py/src/context.rs +0 -0
  169. {cc_transcript-14.45.10 → cc_transcript-14.45.12}/rust/crates/py/src/corrections.rs +0 -0
  170. {cc_transcript-14.45.10 → cc_transcript-14.45.12}/rust/crates/py/src/discovery.rs +0 -0
  171. {cc_transcript-14.45.10 → cc_transcript-14.45.12}/rust/crates/py/src/feedback.rs +0 -0
  172. {cc_transcript-14.45.10 → cc_transcript-14.45.12}/rust/crates/py/src/judge.rs +0 -0
  173. {cc_transcript-14.45.10 → cc_transcript-14.45.12}/rust/crates/py/src/lexicon.rs +0 -0
  174. {cc_transcript-14.45.10 → cc_transcript-14.45.12}/rust/crates/py/src/lib.rs +0 -0
  175. {cc_transcript-14.45.10 → cc_transcript-14.45.12}/rust/crates/py/src/mining.rs +0 -0
  176. {cc_transcript-14.45.10 → cc_transcript-14.45.12}/rust/crates/py/src/nlp.rs +0 -0
  177. {cc_transcript-14.45.10 → cc_transcript-14.45.12}/rust/crates/py/src/python.rs +0 -0
  178. {cc_transcript-14.45.10 → cc_transcript-14.45.12}/rust/crates/py/src/render.rs +0 -0
  179. {cc_transcript-14.45.10 → cc_transcript-14.45.12}/rust/crates/py/src/score.rs +0 -0
  180. {cc_transcript-14.45.10 → cc_transcript-14.45.12}/rust/crates/py/src/snapshot_decode.rs +0 -0
  181. {cc_transcript-14.45.10 → cc_transcript-14.45.12}/rust/crates/py/src/snapshots.rs +0 -0
  182. {cc_transcript-14.45.10 → cc_transcript-14.45.12}/rust/crates/py/src/sqlite.rs +0 -0
  183. {cc_transcript-14.45.10 → cc_transcript-14.45.12}/rust/crates/py/src/toolcall.rs +0 -0
  184. {cc_transcript-14.45.10 → cc_transcript-14.45.12}/rust/crates/py/src/views/attachment.rs +0 -0
  185. {cc_transcript-14.45.10 → cc_transcript-14.45.12}/rust/crates/py/src/views/blocks.rs +0 -0
  186. {cc_transcript-14.45.10 → cc_transcript-14.45.12}/rust/crates/py/src/views/command.rs +0 -0
  187. {cc_transcript-14.45.10 → cc_transcript-14.45.12}/rust/crates/py/src/views/convert.rs +0 -0
  188. {cc_transcript-14.45.10 → cc_transcript-14.45.12}/rust/crates/py/src/views/dunder.rs +0 -0
  189. {cc_transcript-14.45.10 → cc_transcript-14.45.12}/rust/crates/py/src/views/events.rs +0 -0
  190. {cc_transcript-14.45.10 → cc_transcript-14.45.12}/rust/crates/py/src/views/meta.rs +0 -0
  191. {cc_transcript-14.45.10 → cc_transcript-14.45.12}/rust/crates/py/src/views/mod.rs +0 -0
  192. {cc_transcript-14.45.10 → cc_transcript-14.45.12}/rust/crates/py/src/views/print.rs +0 -0
  193. {cc_transcript-14.45.10 → cc_transcript-14.45.12}/rust/crates/py/src/views/store.rs +0 -0
  194. {cc_transcript-14.45.10 → cc_transcript-14.45.12}/rust/crates/py/src/views/system.rs +0 -0
  195. {cc_transcript-14.45.10 → cc_transcript-14.45.12}/rust/crates/py/src/views/toolcall.rs +0 -0
  196. {cc_transcript-14.45.10 → cc_transcript-14.45.12}/rust/crates/py/src/views/toolresult.rs +0 -0
  197. {cc_transcript-14.45.10 → cc_transcript-14.45.12}/rust/crates/py/src/views/transcript.rs +0 -0
  198. {cc_transcript-14.45.10 → cc_transcript-14.45.12}/rust/crates/py/src/watch.rs +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: cc-transcript
3
- Version: 14.45.10
3
+ Version: 14.45.12
4
4
  Classifier: Development Status :: 3 - Alpha
5
5
  Classifier: Environment :: Console
6
6
  Classifier: Intended Audience :: Developers
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "cc-transcript"
3
- version = "14.45.10" # informational — releases stamp the version from the git tag
3
+ version = "14.45.12" # informational — releases stamp the version from the git tag
4
4
  description = "Grep every Claude Code session you've ever run."
5
5
  readme = "README.md"
6
6
  license = "PolyForm-Noncommercial-1.0.0"
@@ -14565,6 +14565,74 @@ mod tests {
14565
14565
  assert!(validate().unwrap_err().status == Status::PermissionDenied);
14566
14566
  }
14567
14567
 
14568
+ #[test]
14569
+ fn source_validation_skips_its_parent_hold_once_cancelled_or_past_its_deadline() {
14570
+ let source = Source::new(&format!("{}\n", user("root")));
14571
+ let sources = canonical_members(&source.directory.join("members"), &["a", "b"], "");
14572
+ let store = store();
14573
+ let owner = context("a");
14574
+ let validate = |cancel: &Cancellation, deadline: u64| {
14575
+ let before = store.source_resolutions.load(Ordering::Relaxed);
14576
+ let validated = store
14577
+ .validate_source_stamps(&sources, &owner, cancel, deadline)
14578
+ .map_err(|error| error.status);
14579
+ (
14580
+ validated,
14581
+ store.source_resolutions.load(Ordering::Relaxed) - before,
14582
+ )
14583
+ };
14584
+ assert_eq!(
14585
+ validate(&Cancellation::default(), now_ms() + 30_000),
14586
+ (Ok(true), 2)
14587
+ );
14588
+ for (cancels, status) in [(true, Status::Cancelled), (false, Status::Deadline)] {
14589
+ let cancel = Cancellation::default();
14590
+ let deadline = now_ms() + 1_000;
14591
+ *store.resolve_hook.lock().unwrap() = Some(Arc::new({
14592
+ let (cancel, last) = (cancel.clone(), sources[1].path.clone());
14593
+ move |path: &Path| {
14594
+ if path != last {
14595
+ return;
14596
+ }
14597
+ if cancels {
14598
+ cancel.cancel();
14599
+ } else {
14600
+ while now_ms() <= deadline {
14601
+ std::thread::sleep(std::time::Duration::from_millis(5));
14602
+ }
14603
+ }
14604
+ }
14605
+ }));
14606
+ assert_eq!(validate(&cancel, deadline), (Err(status), 1));
14607
+ }
14608
+ }
14609
+
14610
+ #[test]
14611
+ fn empty_membership_validation_reports_cancellation_and_an_expired_deadline() {
14612
+ let store = store();
14613
+ let owner = context("a");
14614
+ let cancelled = Cancellation::default();
14615
+ cancelled.cancel();
14616
+ for (cancel, deadline, status) in [
14617
+ (Cancellation::default(), now_ms(), Status::Deadline),
14618
+ (cancelled, now_ms() + 30_000, Status::Cancelled),
14619
+ ] {
14620
+ let before = store.source_resolutions.load(Ordering::Relaxed);
14621
+ assert_eq!(
14622
+ (
14623
+ store
14624
+ .validate_source_stamps(&[], &owner, &cancel, deadline)
14625
+ .map_err(|error| error.status),
14626
+ store
14627
+ .validate_sidechain_dirs(&[], &owner, &cancel, deadline)
14628
+ .map_err(|error| error.status),
14629
+ ),
14630
+ (Err(status), Err(status))
14631
+ );
14632
+ assert_eq!(store.source_resolutions.load(Ordering::Relaxed), before);
14633
+ }
14634
+ }
14635
+
14568
14636
  #[test]
14569
14637
  fn early_positive_query_rejects_a_parent_retargeted_during_its_page() {
14570
14638
  let source = Source::new(&format!("{}\n", user("root")));
@@ -15423,6 +15491,58 @@ mod tests {
15423
15491
  store.assert_conserved();
15424
15492
  }
15425
15493
 
15494
+ #[test]
15495
+ fn a_stopped_fact_read_keeps_the_entry_for_the_next_member_reader() {
15496
+ for (expected, cancels) in [("cancelled", true), ("deadline", false)] {
15497
+ let EvictedMembers {
15498
+ source,
15499
+ members,
15500
+ store,
15501
+ owner,
15502
+ indexed,
15503
+ ..
15504
+ } = evicted_members(&["thread-a"]);
15505
+ let key = fact_entry_key(&members[0], &owner);
15506
+ let cancellation = Cancellation::default();
15507
+ let stop = cancellation.clone();
15508
+ let deadline = now_ms() + if cancels { 30_000 } else { 1_500 };
15509
+ store.prepared_disk.set_read_hook(Some(Box::new(move || {
15510
+ if cancels {
15511
+ stop.cancel();
15512
+ } else {
15513
+ while now_ms() < deadline {
15514
+ std::thread::sleep(Duration::from_millis(5));
15515
+ }
15516
+ }
15517
+ })));
15518
+ let stopped = store.request(
15519
+ &warm_request(&source, &["thread-a"], deadline),
15520
+ &owner,
15521
+ &cancellation,
15522
+ );
15523
+ store.prepared_disk.set_read_hook(None);
15524
+ assert_eq!(stopped["status"].as_str(), Some(expected), "{stopped:?}");
15525
+ assert_eq!(cache_reads(&stopped), (Some(0), Some(0), Some(0)));
15526
+ assert_eq!(store.fact_lookups.load(Ordering::Relaxed), 1);
15527
+ assert!(store.prepared_disk.has_entry(&key).unwrap());
15528
+ assert!(!store.lock_state().fact_read_in_flight);
15529
+ store.assert_conserved();
15530
+ let reused = store.request(
15531
+ &warm_request(&source, &["thread-a"], now_ms() + 30_000),
15532
+ &owner,
15533
+ &Cancellation::default(),
15534
+ );
15535
+ assert_eq!(reused["status"].as_str(), Some("ok"), "{reused:?}");
15536
+ assert_eq!(reused["data"]["complete"].as_bool(), Some(true));
15537
+ assert_eq!(cache_reads(&reused), (Some(1), Some(indexed), Some(0)));
15538
+ assert_eq!(store.fact_lookups.load(Ordering::Relaxed), 2);
15539
+ assert!(resident_member_facts(&store, &members)
15540
+ .iter()
15541
+ .all(Option::is_some));
15542
+ store.assert_conserved();
15543
+ }
15544
+ }
15545
+
15426
15546
  fn user_text(id: &str, text: &str) -> String {
15427
15547
  format!(
15428
15548
  r#"{{"type":"user","uuid":"{id}","sessionId":"s","timestamp":"2026-01-02T03:04:05Z","message":{{"content":"{text}"}}}}"#
@@ -16447,6 +16567,54 @@ mod tests {
16447
16567
  store.assert_conserved();
16448
16568
  }
16449
16569
 
16570
+ #[test]
16571
+ fn a_cancelled_root_fact_read_keeps_the_entry_and_builds_nothing() {
16572
+ let source = Source::new(&format!("{}\n{}\n", user("root"), user("child")));
16573
+ let store = fact_budget_store(16 * 1024 * 1024);
16574
+ let owner = context("a");
16575
+ let bounds = limits(&acquire(&source.path)).unwrap();
16576
+ let root = pinned_root(&store, &source, &owner);
16577
+ assert_eq!(root_facts_read(&store, &root, &owner, &bounds).1, 0);
16578
+ assert_eq!(
16579
+ store
16580
+ .lock_state()
16581
+ .remove_identity_facts(root.stamp.identity),
16582
+ 1
16583
+ );
16584
+ let key = fact_entry_key(&source.path, &owner);
16585
+ let builds = store.fact_builds.load(Ordering::Relaxed);
16586
+ let cancellation = Cancellation::default();
16587
+ let stop = cancellation.clone();
16588
+ store
16589
+ .prepared_disk
16590
+ .set_read_hook(Some(Box::new(move || stop.cancel())));
16591
+ let mut usage = [0u64; 20];
16592
+ let stopped = store
16593
+ .prepared_root_facts(
16594
+ &root,
16595
+ &json!({"id":"native","version":"1"}),
16596
+ &owner,
16597
+ &bounds,
16598
+ PreparedCacheReads::Unmetered,
16599
+ &cancellation,
16600
+ &mut usage,
16601
+ FactsNeed::Index,
16602
+ )
16603
+ .err()
16604
+ .map(|error| error.status);
16605
+ store.prepared_disk.set_read_hook(None);
16606
+ assert_eq!(stopped, Some(Status::Cancelled));
16607
+ assert_eq!((usage[18], usage[19]), (0, 0));
16608
+ assert_eq!(store.fact_lookups.load(Ordering::Relaxed), 1);
16609
+ assert_eq!(store.fact_builds.load(Ordering::Relaxed), builds);
16610
+ assert!(store.prepared_disk.has_entry(&key).unwrap());
16611
+ assert!(!store.lock_state().fact_read_in_flight);
16612
+ store.assert_conserved();
16613
+ assert_eq!(root_facts_read(&store, &root, &owner, &bounds).1, 1);
16614
+ assert_eq!(store.fact_builds.load(Ordering::Relaxed), builds);
16615
+ store.assert_conserved();
16616
+ }
16617
+
16450
16618
  #[test]
16451
16619
  fn waiting_reader_with_a_different_binding_never_reuses_the_published_facts() {
16452
16620
  let source = Source::new(&format!("{}\n{}\n", user("root"), user("child")));
@@ -17846,6 +18014,32 @@ mod tests {
17846
18014
  );
17847
18015
  }
17848
18016
 
18017
+ #[test]
18018
+ fn registered_warmer_cancelled_on_its_last_step_fails_its_final_hold() {
18019
+ let (source, store, owner, mut request) = registered_warming(300);
18020
+ registered_pages(&store, &owner, &request);
18021
+ std::fs::OpenOptions::new()
18022
+ .append(true)
18023
+ .open(source.directory.join("thread-0255.jsonl"))
18024
+ .unwrap()
18025
+ .write_all(format!("{}\n", user("appended")).as_bytes())
18026
+ .unwrap();
18027
+ let cancel = Cancellation::default();
18028
+ *store.built_facts_hook.lock().unwrap() = Some(Arc::new({
18029
+ let cancel = cancel.clone();
18030
+ move |_: &Arc<crate::snapshot_prepared::PreparedFacts>| cancel.cancel()
18031
+ }));
18032
+ let builds = store.fact_builds.load(Ordering::Relaxed);
18033
+ request.insert("deadline_unix_ms", json!(now_ms() + 120_000));
18034
+ let cancelled = store.request(&request, &owner, &cancel);
18035
+ assert_eq!(
18036
+ cancelled["status"].as_str(),
18037
+ Some("cancelled"),
18038
+ "{cancelled:?}"
18039
+ );
18040
+ assert_eq!(store.fact_builds.load(Ordering::Relaxed) - builds, 1);
18041
+ }
18042
+
17849
18043
  #[test]
17850
18044
  fn disk_facts_complete_queries_when_memory_fact_budget_is_smaller() {
17851
18045
  let source = Source::new(&format!("{}\n", user("root")));
@@ -13,7 +13,9 @@ use std::sync::{LazyLock, Mutex};
13
13
  use sha2::{Digest, Sha256};
14
14
  use sonic_rs::{json, JsonValueTrait, Value};
15
15
 
16
- use crate::snapshot::{SnapshotError, SourceIdentity, SourceStamp, Status, PARSER_VERSION};
16
+ use crate::snapshot::{
17
+ Cancellation, SnapshotError, SourceIdentity, SourceStamp, Status, PARSER_VERSION,
18
+ };
17
19
  #[cfg(test)]
18
20
  use crate::snapshot_ledger::Reserved;
19
21
  use crate::snapshot_ledger::{Table, Work};
@@ -45,6 +47,7 @@ const ROOM_SWEEP_NAMES: usize = 256;
45
47
  const ENTRY_NAME_BYTES: usize = 166;
46
48
  const LEGACY_ENTRY_NAME_BYTES: [usize; 2] = [150, 118];
47
49
  const MAX_STRANDED_OWNED: usize = 64;
50
+ const READ_CHUNK_BYTES: usize = 64 * 1024;
48
51
 
49
52
  static ACTIVE_OWNERS: LazyLock<Mutex<HashSet<String>>> =
50
53
  LazyLock::new(|| Mutex::new(HashSet::new()));
@@ -164,6 +167,24 @@ fn probed_read_bytes(stored: usize) -> usize {
164
167
  stored.saturating_add(1)
165
168
  }
166
169
 
170
+ fn read_chunks(
171
+ file: &std::fs::File,
172
+ wanted: usize,
173
+ bytes: &mut Vec<u8>,
174
+ mut checkpoint: impl FnMut() -> Result<(), SnapshotError>,
175
+ ) -> Result<(), SnapshotError> {
176
+ let mut unread = file.take(wanted as u64);
177
+ while (&mut unread)
178
+ .take(READ_CHUNK_BYTES as u64)
179
+ .read_to_end(bytes)
180
+ .map_err(disk_error)?
181
+ == READ_CHUNK_BYTES
182
+ {
183
+ checkpoint()?;
184
+ }
185
+ Ok(())
186
+ }
187
+
167
188
  fn openat_file(dir_fd: libc::c_int, name: &CStr, flags: libc::c_int) -> io::Result<std::fs::File> {
168
189
  let fd = unsafe {
169
190
  libc::openat(
@@ -1591,9 +1612,13 @@ impl PreparedDiskCache {
1591
1612
  read: &mut DiskRead,
1592
1613
  need: FactsNeed,
1593
1614
  admitted: usize,
1615
+ cancel: &Cancellation,
1616
+ deadline_unix_ms: u64,
1594
1617
  ) -> Result<DiskLookup, SnapshotError> {
1618
+ cancel.check(deadline_unix_ms)?;
1595
1619
  self.check_dir()?;
1596
1620
  let mut state = self.state.lock().expect("prepared facts disk state");
1621
+ cancel.check(deadline_unix_ms)?;
1597
1622
  let Some(entry) = state.entries.get(&key.name) else {
1598
1623
  return Ok(DiskLookup::Miss);
1599
1624
  };
@@ -1623,18 +1648,23 @@ impl PreparedDiskCache {
1623
1648
  {
1624
1649
  return Err(incomplete("prepared facts cache entry changed"));
1625
1650
  }
1626
- #[cfg(test)]
1627
- run_read_hook(&self.owner_name);
1651
+ let checkpoint = || {
1652
+ #[cfg(test)]
1653
+ run_read_hook(&self.owner_name);
1654
+ cancel.check(deadline_unix_ms)
1655
+ };
1656
+ checkpoint()?;
1628
1657
  let mut bytes = Vec::with_capacity(wanted.min(expected));
1629
1658
  read.operations += 1;
1630
- let finished = (&file).take(wanted as u64).read_to_end(&mut bytes);
1659
+ let finished = read_chunks(&file, wanted, &mut bytes, checkpoint);
1631
1660
  read.bytes += bytes.len() as u64;
1632
- finished.map_err(disk_error)?;
1661
+ finished?;
1633
1662
  if need == FactsNeed::Index
1634
1663
  && file.metadata().map_err(disk_error)?.len() != expected as u64
1635
1664
  {
1636
1665
  return Err(incomplete("prepared facts cache entry changed"));
1637
1666
  }
1667
+ cancel.check(deadline_unix_ms)?;
1638
1668
  let index_end = HEADER_BYTES + index_bytes;
1639
1669
  let verified = bytes
1640
1670
  .get(..HEADER_BYTES)
@@ -1668,11 +1698,13 @@ impl PreparedDiskCache {
1668
1698
  if !verified {
1669
1699
  return Err(incomplete("prepared facts cache integrity check failed"));
1670
1700
  }
1701
+ cancel.check(deadline_unix_ms)?;
1671
1702
  let index: DecodedIndexSection = sonic_rs::from_slice(&bytes[HEADER_BYTES..index_end])
1672
1703
  .map_err(|_| incomplete("prepared facts cache payload invalid"))?;
1673
1704
  let overrides = match served {
1674
1705
  FactsNeed::Index => OverrideFacts::Unloaded,
1675
1706
  FactsNeed::Full => {
1707
+ cancel.check(deadline_unix_ms)?;
1676
1708
  let section: Option<Vec<OverrideEvent>> =
1677
1709
  sonic_rs::from_slice(&bytes[index_end..])
1678
1710
  .map_err(|_| incomplete("prepared facts cache payload invalid"))?;
@@ -1680,6 +1712,7 @@ impl PreparedDiskCache {
1680
1712
  }
1681
1713
  };
1682
1714
  let facts = PreparedFacts::from_sections(index, overrides);
1715
+ cancel.check(deadline_unix_ms)?;
1683
1716
  if inherited {
1684
1717
  if facts.accounted_bytes() > accounted_bound {
1685
1718
  return Err(incomplete("prepared facts cache accounting exceeded"));
@@ -1714,6 +1747,9 @@ impl PreparedDiskCache {
1714
1747
  DiskLookup::IndexOnly(facts)
1715
1748
  })
1716
1749
  }
1750
+ Err(error) if matches!(error.status, Status::Cancelled | Status::Deadline) => {
1751
+ Err(error)
1752
+ }
1717
1753
  Err(_) => {
1718
1754
  self.retire(&mut state, key.name)?;
1719
1755
  Ok(if inherited {
@@ -2202,7 +2238,14 @@ mod tests {
2202
2238
  read: &mut DiskRead,
2203
2239
  need: FactsNeed,
2204
2240
  ) -> Result<DiskLookup, SnapshotError> {
2205
- cache.lookup(key, read, need, cache.decoded_bytes(key, need).unwrap_or(0))
2241
+ cache.lookup(
2242
+ key,
2243
+ read,
2244
+ need,
2245
+ cache.decoded_bytes(key, need).unwrap_or(0),
2246
+ &Cancellation::default(),
2247
+ u64::MAX,
2248
+ )
2206
2249
  }
2207
2250
 
2208
2251
  fn cache(cap: usize) -> PreparedDiskCache {
@@ -2956,6 +2999,163 @@ mod tests {
2956
2999
  assert_eq!(cache.stats().entries, 0);
2957
3000
  }
2958
3001
 
3002
+ fn chunked_facts() -> PreparedFacts {
3003
+ let mut facts = PreparedFacts {
3004
+ inputs: json!({
3005
+ "calls": [["Read", ["/repo/file.rs"]]],
3006
+ "commands": [],
3007
+ "edited_files": [],
3008
+ "skills": [],
3009
+ }),
3010
+ has_error: false,
3011
+ overrides: OverrideFacts::Loaded(vec![OverrideEvent {
3012
+ text: "x".repeat(3 * READ_CHUNK_BYTES),
3013
+ tools: vec!["Read".to_owned()],
3014
+ }]),
3015
+ accounted: 0,
3016
+ };
3017
+ facts.refresh_accounted();
3018
+ facts
3019
+ }
3020
+
3021
+ #[test]
3022
+ fn a_stopped_lookup_reads_no_further_and_keeps_the_entry() {
3023
+ let cache = cache(2 * 1024 * 1024);
3024
+ let entry = revision(1);
3025
+ let built = chunked_facts();
3026
+ assert!(cache
3027
+ .insert(&entry, &built, |_| true, |_| true)
3028
+ .unwrap()
3029
+ .serves());
3030
+ let path = cache.entry_path(entry.digest);
3031
+ let stored = fs::read(&path).unwrap();
3032
+ assert!(
3033
+ stored.len() > 2 * READ_CHUNK_BYTES,
3034
+ "entry {}",
3035
+ stored.len()
3036
+ );
3037
+ let admitted = cache.decoded_bytes(&entry, FactsNeed::Full).unwrap();
3038
+ for (site, cancelled, cancelled_at_read, deadline_unix_ms, status, counted) in [
3039
+ (
3040
+ "before the first read",
3041
+ false,
3042
+ Some(1),
3043
+ u64::MAX,
3044
+ Status::Cancelled,
3045
+ (0, 0),
3046
+ ),
3047
+ (
3048
+ "at a chunk boundary",
3049
+ false,
3050
+ Some(2),
3051
+ u64::MAX,
3052
+ Status::Cancelled,
3053
+ (1, READ_CHUNK_BYTES as u64),
3054
+ ),
3055
+ (
3056
+ "past the deadline",
3057
+ false,
3058
+ None,
3059
+ 0,
3060
+ Status::Deadline,
3061
+ (0, 0),
3062
+ ),
3063
+ (
3064
+ "cancelled past the deadline",
3065
+ true,
3066
+ None,
3067
+ 0,
3068
+ Status::Cancelled,
3069
+ (0, 0),
3070
+ ),
3071
+ ] {
3072
+ let cancel = Cancellation::default();
3073
+ if cancelled {
3074
+ cancel.cancel();
3075
+ }
3076
+ let stop = cancel.clone();
3077
+ let mut reads = 0;
3078
+ cache.set_read_hook(Some(Box::new(move || {
3079
+ reads += 1;
3080
+ if Some(reads) == cancelled_at_read {
3081
+ stop.cancel();
3082
+ }
3083
+ })));
3084
+ let mut read = DiskRead::default();
3085
+ let stopped = cache
3086
+ .lookup(
3087
+ &entry,
3088
+ &mut read,
3089
+ FactsNeed::Full,
3090
+ admitted,
3091
+ &cancel,
3092
+ deadline_unix_ms,
3093
+ )
3094
+ .err()
3095
+ .map(|error| error.status);
3096
+ cache.set_read_hook(None);
3097
+ assert_eq!(stopped, Some(status), "{site}");
3098
+ assert_eq!((read.operations, read.bytes), counted, "{site}");
3099
+ assert_eq!(fs::read(&path).unwrap(), stored, "{site}");
3100
+ assert_eq!(cache.stats().entries, 1, "{site}");
3101
+ }
3102
+ let mut read = DiskRead::default();
3103
+ let DiskLookup::Hit(loaded) = lookup(&cache, &entry, &mut read, FactsNeed::Full).unwrap()
3104
+ else {
3105
+ panic!("expected the kept entry to serve");
3106
+ };
3107
+ assert_eq!((read.operations, read.bytes), (1, stored.len() as u64));
3108
+ assert_eq!(
3109
+ loaded.text_section().unwrap()[0].text,
3110
+ built.text_section().unwrap()[0].text
3111
+ );
3112
+ }
3113
+
3114
+ #[test]
3115
+ fn a_stopped_inherited_lookup_leaves_the_entry_unadopted() {
3116
+ let namespace = isolated_namespace();
3117
+ let built = pushed_facts(5, 5);
3118
+ let entry = revision(1);
3119
+ let left = left_behind(&namespace, &entry, &built);
3120
+ let stored = fs::metadata(&left).unwrap().len();
3121
+ let successor = reuse_cache(&namespace, 64 * 1024);
3122
+ let inherited = budget(&successor);
3123
+ assert_eq!(inherited, (1, 0, stored as usize, 0));
3124
+ let admitted = successor.decoded_bytes(&entry, FactsNeed::Full).unwrap();
3125
+ let cancel = Cancellation::default();
3126
+ let stop = cancel.clone();
3127
+ successor.set_read_hook(Some(Box::new(move || stop.cancel())));
3128
+ let mut read = DiskRead::default();
3129
+ let stopped = successor
3130
+ .lookup(
3131
+ &entry,
3132
+ &mut read,
3133
+ FactsNeed::Full,
3134
+ admitted,
3135
+ &cancel,
3136
+ u64::MAX,
3137
+ )
3138
+ .err()
3139
+ .map(|error| error.status);
3140
+ successor.set_read_hook(None);
3141
+ assert_eq!(stopped, Some(Status::Cancelled));
3142
+ assert_eq!((read.operations, read.bytes), (0, 0));
3143
+ assert_eq!(budget(&successor), inherited);
3144
+ assert!(left.exists());
3145
+ assert!(!successor.has_entry(&entry).unwrap());
3146
+ let DiskLookup::Hit(loaded) =
3147
+ lookup(&successor, &entry, &mut read, FactsNeed::Full).unwrap()
3148
+ else {
3149
+ panic!("expected the inherited entry to serve");
3150
+ };
3151
+ assert_eq!(loaded.inputs, built.inputs);
3152
+ assert_eq!((read.operations, read.bytes), (1, stored));
3153
+ assert_eq!(budget(&successor), (1, stored as usize, 0, 0));
3154
+ assert!(!left.exists());
3155
+ drop(successor);
3156
+ fs::remove_dir_all(namespace).unwrap();
3157
+ }
3158
+
2959
3159
  fn pushed_facts(events: usize, tools: usize) -> PreparedFacts {
2960
3160
  let mut override_events = Vec::new();
2961
3161
  for event in 0..events {
@@ -4767,7 +4967,14 @@ mod tests {
4767
4967
  let mut read = DiskRead::default();
4768
4968
  assert!(matches!(
4769
4969
  cache
4770
- .lookup(&entry, &mut read, FactsNeed::Full, admitted)
4970
+ .lookup(
4971
+ &entry,
4972
+ &mut read,
4973
+ FactsNeed::Full,
4974
+ admitted,
4975
+ &Cancellation::default(),
4976
+ u64::MAX,
4977
+ )
4771
4978
  .unwrap(),
4772
4979
  DiskLookup::Changed
4773
4980
  ));
@@ -358,7 +358,14 @@ impl NativeStore {
358
358
  #[cfg(test)]
359
359
  self.fact_lookups.fetch_add(1, Ordering::Relaxed);
360
360
  let mut read = crate::snapshot_prepared_disk::DiskRead::default();
361
- let lookup = self.prepared_disk.lookup(&key, &mut read, need, decoded);
361
+ let lookup = self.prepared_disk.lookup(
362
+ &key,
363
+ &mut read,
364
+ need,
365
+ decoded,
366
+ cancel,
367
+ remaining.deadline_unix_ms,
368
+ );
362
369
  usage[18] += read.operations;
363
370
  usage[19] += read.bytes;
364
371
  match lookup? {
@@ -584,7 +591,14 @@ impl NativeStore {
584
591
  #[cfg(test)]
585
592
  self.fact_lookups.fetch_add(1, Ordering::Relaxed);
586
593
  let mut read = crate::snapshot_prepared_disk::DiskRead::default();
587
- let lookup = self.prepared_disk.lookup(&key, &mut read, need, decoded);
594
+ let lookup = self.prepared_disk.lookup(
595
+ &key,
596
+ &mut read,
597
+ need,
598
+ decoded,
599
+ cancel,
600
+ remaining.deadline_unix_ms,
601
+ );
588
602
  usage[18] += read.operations;
589
603
  usage[19] += read.bytes;
590
604
  if let PreparedCacheReads::Warming(..) = cache_reads {
@@ -904,7 +918,7 @@ impl NativeStore {
904
918
  return Ok(false);
905
919
  }
906
920
  }
907
- dirs.hold()
921
+ dirs.hold(|| cancel.check(deadline))
908
922
  }
909
923
 
910
924
  fn validate_sidechain_dirs(
@@ -935,7 +949,7 @@ impl NativeStore {
935
949
  return Ok(false);
936
950
  }
937
951
  }
938
- dirs.hold()
952
+ dirs.hold(|| cancel.check(deadline))
939
953
  }
940
954
 
941
955
  fn prepare_graph(
@@ -1670,7 +1684,7 @@ impl NativeStore {
1670
1684
  });
1671
1685
  }
1672
1686
  let since = active_since_ns(request)?;
1673
- if !dirs.hold()?
1687
+ if !dirs.hold(|| cancel.check(remaining.deadline_unix_ms))?
1674
1688
  || members
1675
1689
  .iter()
1676
1690
  .filter(|member| active(member, since))
@@ -2146,7 +2160,10 @@ impl NativeStore {
2146
2160
  steps += 1;
2147
2161
  uncached_steps += usize::from(!cached);
2148
2162
  }
2149
- if !dirs.hold()? {
2163
+ if !dirs.hold(|| match cancel.check(remaining.deadline_unix_ms) {
2164
+ Err(error) if error.status == Status::Deadline => Ok(()),
2165
+ checked => checked,
2166
+ })? {
2150
2167
  return Err(SnapshotError::new(
2151
2168
  Status::Changed,
2152
2169
  "registered source changed",
@@ -2253,7 +2270,7 @@ impl NativeStore {
2253
2270
  let page = self
2254
2271
  .prepared_query_steps(&mut cursor, &mut dirs, context, reservation, cancel, usage)
2255
2272
  .and_then(|page| {
2256
- if dirs.hold()? {
2273
+ if dirs.hold(|| cancel.check(cursor.remaining.deadline_unix_ms))? {
2257
2274
  Ok(page)
2258
2275
  } else {
2259
2276
  Err(SnapshotError::new(
@@ -3075,8 +3092,10 @@ impl<'a> ResolvedDirs<'a> {
3075
3092
  Ok(canonical)
3076
3093
  }
3077
3094
 
3078
- fn hold(&self) -> Result<bool, SnapshotError> {
3095
+ fn hold(&self, check: impl Fn() -> Result<(), SnapshotError>) -> Result<bool, SnapshotError> {
3096
+ check()?;
3079
3097
  for (directory, canonical) in &self.dirs {
3098
+ check()?;
3080
3099
  match self.store.canonical_path(directory) {
3081
3100
  Ok(current) if current == *canonical => {}
3082
3101
  Ok(_) => return Ok(false),
@@ -3084,6 +3103,7 @@ impl<'a> ResolvedDirs<'a> {
3084
3103
  Err(error) => return Err(io_error(error)),
3085
3104
  }
3086
3105
  }
3106
+ check()?;
3087
3107
  Ok(true)
3088
3108
  }
3089
3109
  }