cc-transcript 14.31.0__tar.gz → 14.32.0__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 (188) hide show
  1. {cc_transcript-14.31.0 → cc_transcript-14.32.0}/PKG-INFO +1 -1
  2. {cc_transcript-14.31.0 → cc_transcript-14.32.0}/pyproject.toml +1 -1
  3. {cc_transcript-14.31.0 → cc_transcript-14.32.0}/rust/crates/core/src/snapshot.rs +193 -40
  4. {cc_transcript-14.31.0 → cc_transcript-14.32.0}/rust/crates/core/src/snapshot_codec.rs +42 -0
  5. {cc_transcript-14.31.0 → cc_transcript-14.32.0}/rust/crates/core/src/snapshot_labels.rs +23 -1
  6. {cc_transcript-14.31.0 → cc_transcript-14.32.0}/rust/crates/core/src/snapshot_prepared_service.rs +27 -29
  7. {cc_transcript-14.31.0 → cc_transcript-14.32.0}/rust/crates/core/src/snapshot_projection.rs +27 -6
  8. {cc_transcript-14.31.0 → cc_transcript-14.32.0}/rust/crates/core/src/snapshot_root_warm.rs +59 -3
  9. {cc_transcript-14.31.0 → cc_transcript-14.32.0}/Cargo.lock +0 -0
  10. {cc_transcript-14.31.0 → cc_transcript-14.32.0}/Cargo.toml +0 -0
  11. {cc_transcript-14.31.0 → cc_transcript-14.32.0}/LICENSE +0 -0
  12. {cc_transcript-14.31.0 → cc_transcript-14.32.0}/README.md +0 -0
  13. {cc_transcript-14.31.0 → cc_transcript-14.32.0}/cc_transcript/__init__.py +0 -0
  14. {cc_transcript-14.31.0 → cc_transcript-14.32.0}/cc_transcript/__init__.pyi +0 -0
  15. {cc_transcript-14.31.0 → cc_transcript-14.32.0}/cc_transcript/_native.pyi +0 -0
  16. {cc_transcript-14.31.0 → cc_transcript-14.32.0}/cc_transcript/activity.py +0 -0
  17. {cc_transcript-14.31.0 → cc_transcript-14.32.0}/cc_transcript/activity_probe.py +0 -0
  18. {cc_transcript-14.31.0 → cc_transcript-14.32.0}/cc_transcript/builders.py +0 -0
  19. {cc_transcript-14.31.0 → cc_transcript-14.32.0}/cc_transcript/codex.py +0 -0
  20. {cc_transcript-14.31.0 → cc_transcript-14.32.0}/cc_transcript/command.py +0 -0
  21. {cc_transcript-14.31.0 → cc_transcript-14.32.0}/cc_transcript/context.py +0 -0
  22. {cc_transcript-14.31.0 → cc_transcript-14.32.0}/cc_transcript/corrections.py +0 -0
  23. {cc_transcript-14.31.0 → cc_transcript-14.32.0}/cc_transcript/cost.py +0 -0
  24. {cc_transcript-14.31.0 → cc_transcript-14.32.0}/cc_transcript/decision_store.py +0 -0
  25. {cc_transcript-14.31.0 → cc_transcript-14.32.0}/cc_transcript/decisions.py +0 -0
  26. {cc_transcript-14.31.0 → cc_transcript-14.32.0}/cc_transcript/discovery.py +0 -0
  27. {cc_transcript-14.31.0 → cc_transcript-14.32.0}/cc_transcript/disktruth.py +0 -0
  28. {cc_transcript-14.31.0 → cc_transcript-14.32.0}/cc_transcript/evidence.py +0 -0
  29. {cc_transcript-14.31.0 → cc_transcript-14.32.0}/cc_transcript/extract/__init__.py +0 -0
  30. {cc_transcript-14.31.0 → cc_transcript-14.32.0}/cc_transcript/extract/correct.py +0 -0
  31. {cc_transcript-14.31.0 → cc_transcript-14.32.0}/cc_transcript/facts.py +0 -0
  32. {cc_transcript-14.31.0 → cc_transcript-14.32.0}/cc_transcript/filterspec.py +0 -0
  33. {cc_transcript-14.31.0 → cc_transcript-14.32.0}/cc_transcript/heartbeats.py +0 -0
  34. {cc_transcript-14.31.0 → cc_transcript-14.32.0}/cc_transcript/ids.py +0 -0
  35. {cc_transcript-14.31.0 → cc_transcript-14.32.0}/cc_transcript/judge/__init__.py +0 -0
  36. {cc_transcript-14.31.0 → cc_transcript-14.32.0}/cc_transcript/judge/llm.py +0 -0
  37. {cc_transcript-14.31.0 → cc_transcript-14.32.0}/cc_transcript/judge/similar.py +0 -0
  38. {cc_transcript-14.31.0 → cc_transcript-14.32.0}/cc_transcript/judge/verdicts.py +0 -0
  39. {cc_transcript-14.31.0 → cc_transcript-14.32.0}/cc_transcript/ledger.py +0 -0
  40. {cc_transcript-14.31.0 → cc_transcript-14.32.0}/cc_transcript/literals.py +0 -0
  41. {cc_transcript-14.31.0 → cc_transcript-14.32.0}/cc_transcript/mining/__init__.py +0 -0
  42. {cc_transcript-14.31.0 → cc_transcript-14.32.0}/cc_transcript/mining/candidates.py +0 -0
  43. {cc_transcript-14.31.0 → cc_transcript-14.32.0}/cc_transcript/mining/confidence.py +0 -0
  44. {cc_transcript-14.31.0 → cc_transcript-14.32.0}/cc_transcript/mining/engine.py +0 -0
  45. {cc_transcript-14.31.0 → cc_transcript-14.32.0}/cc_transcript/mining/formats.py +0 -0
  46. {cc_transcript-14.31.0 → cc_transcript-14.32.0}/cc_transcript/mining/sampling.py +0 -0
  47. {cc_transcript-14.31.0 → cc_transcript-14.32.0}/cc_transcript/mining/signals.py +0 -0
  48. {cc_transcript-14.31.0 → cc_transcript-14.32.0}/cc_transcript/mining/sourcekind.py +0 -0
  49. {cc_transcript-14.31.0 → cc_transcript-14.32.0}/cc_transcript/mining/spec.py +0 -0
  50. {cc_transcript-14.31.0 → cc_transcript-14.32.0}/cc_transcript/mining/store.py +0 -0
  51. {cc_transcript-14.31.0 → cc_transcript-14.32.0}/cc_transcript/models.py +0 -0
  52. {cc_transcript-14.31.0 → cc_transcript-14.32.0}/cc_transcript/nlp.py +0 -0
  53. {cc_transcript-14.31.0 → cc_transcript-14.32.0}/cc_transcript/notifications.py +0 -0
  54. {cc_transcript-14.31.0 → cc_transcript-14.32.0}/cc_transcript/parser.py +0 -0
  55. {cc_transcript-14.31.0 → cc_transcript-14.32.0}/cc_transcript/py.typed +0 -0
  56. {cc_transcript-14.31.0 → cc_transcript-14.32.0}/cc_transcript/query.py +0 -0
  57. {cc_transcript-14.31.0 → cc_transcript-14.32.0}/cc_transcript/render.py +0 -0
  58. {cc_transcript-14.31.0 → cc_transcript-14.32.0}/cc_transcript/sentiment/__init__.py +0 -0
  59. {cc_transcript-14.31.0 → cc_transcript-14.32.0}/cc_transcript/sentiment/buckets.py +0 -0
  60. {cc_transcript-14.31.0 → cc_transcript-14.32.0}/cc_transcript/sentiment/data/afinn-en-165.tsv +0 -0
  61. {cc_transcript-14.31.0 → cc_transcript-14.32.0}/cc_transcript/sentiment/data/domain_overrides.tsv +0 -0
  62. {cc_transcript-14.31.0 → cc_transcript-14.32.0}/cc_transcript/sentiment/data/en-ewt.udpipe +0 -0
  63. {cc_transcript-14.31.0 → cc_transcript-14.32.0}/cc_transcript/sentiment/engine.py +0 -0
  64. {cc_transcript-14.31.0 → cc_transcript-14.32.0}/cc_transcript/sentiment/lexicon.py +0 -0
  65. {cc_transcript-14.31.0 → cc_transcript-14.32.0}/cc_transcript/sentiment/scorespec.py +0 -0
  66. {cc_transcript-14.31.0 → cc_transcript-14.32.0}/cc_transcript/snapshot_schema/config.schema.json +0 -0
  67. {cc_transcript-14.31.0 → cc_transcript-14.32.0}/cc_transcript/snapshot_schema/context.schema.json +0 -0
  68. {cc_transcript-14.31.0 → cc_transcript-14.32.0}/cc_transcript/snapshot_schema/request.schema.json +0 -0
  69. {cc_transcript-14.31.0 → cc_transcript-14.32.0}/cc_transcript/snapshot_schema/response.schema.json +0 -0
  70. {cc_transcript-14.31.0 → cc_transcript-14.32.0}/cc_transcript/snapshot_schema/tool_registry.schema.json +0 -0
  71. {cc_transcript-14.31.0 → cc_transcript-14.32.0}/cc_transcript/snapshots.py +0 -0
  72. {cc_transcript-14.31.0 → cc_transcript-14.32.0}/cc_transcript/synthetic.py +0 -0
  73. {cc_transcript-14.31.0 → cc_transcript-14.32.0}/cc_transcript/tools.py +0 -0
  74. {cc_transcript-14.31.0 → cc_transcript-14.32.0}/cc_transcript/watch.py +0 -0
  75. {cc_transcript-14.31.0 → cc_transcript-14.32.0}/rust/crates/cli/Cargo.toml +0 -0
  76. {cc_transcript-14.31.0 → cc_transcript-14.32.0}/rust/crates/cli/src/commands/blame.rs +0 -0
  77. {cc_transcript-14.31.0 → cc_transcript-14.32.0}/rust/crates/cli/src/commands/corpus.rs +0 -0
  78. {cc_transcript-14.31.0 → cc_transcript-14.32.0}/rust/crates/cli/src/commands/corrections.rs +0 -0
  79. {cc_transcript-14.31.0 → cc_transcript-14.32.0}/rust/crates/cli/src/commands/digest.rs +0 -0
  80. {cc_transcript-14.31.0 → cc_transcript-14.32.0}/rust/crates/cli/src/commands/facts.rs +0 -0
  81. {cc_transcript-14.31.0 → cc_transcript-14.32.0}/rust/crates/cli/src/commands/grep.rs +0 -0
  82. {cc_transcript-14.31.0 → cc_transcript-14.32.0}/rust/crates/cli/src/commands/list.rs +0 -0
  83. {cc_transcript-14.31.0 → cc_transcript-14.32.0}/rust/crates/cli/src/commands/mod.rs +0 -0
  84. {cc_transcript-14.31.0 → cc_transcript-14.32.0}/rust/crates/cli/src/commands/scratchpad.rs +0 -0
  85. {cc_transcript-14.31.0 → cc_transcript-14.32.0}/rust/crates/cli/src/commands/show.rs +0 -0
  86. {cc_transcript-14.31.0 → cc_transcript-14.32.0}/rust/crates/cli/src/commands/slice.rs +0 -0
  87. {cc_transcript-14.31.0 → cc_transcript-14.32.0}/rust/crates/cli/src/commands/stats.rs +0 -0
  88. {cc_transcript-14.31.0 → cc_transcript-14.32.0}/rust/crates/cli/src/commands/watch.rs +0 -0
  89. {cc_transcript-14.31.0 → cc_transcript-14.32.0}/rust/crates/cli/src/lib.rs +0 -0
  90. {cc_transcript-14.31.0 → cc_transcript-14.32.0}/rust/crates/cli/src/main.rs +0 -0
  91. {cc_transcript-14.31.0 → cc_transcript-14.32.0}/rust/crates/cli/src/output.rs +0 -0
  92. {cc_transcript-14.31.0 → cc_transcript-14.32.0}/rust/crates/cli/src/target.rs +0 -0
  93. {cc_transcript-14.31.0 → cc_transcript-14.32.0}/rust/crates/cli/src/timearg.rs +0 -0
  94. {cc_transcript-14.31.0 → cc_transcript-14.32.0}/rust/crates/core/Cargo.toml +0 -0
  95. {cc_transcript-14.31.0 → cc_transcript-14.32.0}/rust/crates/core/benches/parse.rs +0 -0
  96. {cc_transcript-14.31.0 → cc_transcript-14.32.0}/rust/crates/core/benches/render.rs +0 -0
  97. {cc_transcript-14.31.0 → cc_transcript-14.32.0}/rust/crates/core/benches/toolcall.rs +0 -0
  98. {cc_transcript-14.31.0 → cc_transcript-14.32.0}/rust/crates/core/src/activity.rs +0 -0
  99. {cc_transcript-14.31.0 → cc_transcript-14.32.0}/rust/crates/core/src/actor.rs +0 -0
  100. {cc_transcript-14.31.0 → cc_transcript-14.32.0}/rust/crates/core/src/blame.rs +0 -0
  101. {cc_transcript-14.31.0 → cc_transcript-14.32.0}/rust/crates/core/src/buckets.rs +0 -0
  102. {cc_transcript-14.31.0 → cc_transcript-14.32.0}/rust/crates/core/src/codex/discovery.rs +0 -0
  103. {cc_transcript-14.31.0 → cc_transcript-14.32.0}/rust/crates/core/src/codex/lower.rs +0 -0
  104. {cc_transcript-14.31.0 → cc_transcript-14.32.0}/rust/crates/core/src/codex/mod.rs +0 -0
  105. {cc_transcript-14.31.0 → cc_transcript-14.32.0}/rust/crates/core/src/codex/parse.rs +0 -0
  106. {cc_transcript-14.31.0 → cc_transcript-14.32.0}/rust/crates/core/src/codex/probe.rs +0 -0
  107. {cc_transcript-14.31.0 → cc_transcript-14.32.0}/rust/crates/core/src/codex/protocol.rs +0 -0
  108. {cc_transcript-14.31.0 → cc_transcript-14.32.0}/rust/crates/core/src/codex/types.rs +0 -0
  109. {cc_transcript-14.31.0 → cc_transcript-14.32.0}/rust/crates/core/src/command.rs +0 -0
  110. {cc_transcript-14.31.0 → cc_transcript-14.32.0}/rust/crates/core/src/context.rs +0 -0
  111. {cc_transcript-14.31.0 → cc_transcript-14.32.0}/rust/crates/core/src/corrections.rs +0 -0
  112. {cc_transcript-14.31.0 → cc_transcript-14.32.0}/rust/crates/core/src/cost.rs +0 -0
  113. {cc_transcript-14.31.0 → cc_transcript-14.32.0}/rust/crates/core/src/discovery.rs +0 -0
  114. {cc_transcript-14.31.0 → cc_transcript-14.32.0}/rust/crates/core/src/facts.rs +0 -0
  115. {cc_transcript-14.31.0 → cc_transcript-14.32.0}/rust/crates/core/src/feedback.rs +0 -0
  116. {cc_transcript-14.31.0 → cc_transcript-14.32.0}/rust/crates/core/src/filter.rs +0 -0
  117. {cc_transcript-14.31.0 → cc_transcript-14.32.0}/rust/crates/core/src/gateway.rs +0 -0
  118. {cc_transcript-14.31.0 → cc_transcript-14.32.0}/rust/crates/core/src/ids.rs +0 -0
  119. {cc_transcript-14.31.0 → cc_transcript-14.32.0}/rust/crates/core/src/judge.rs +0 -0
  120. {cc_transcript-14.31.0 → cc_transcript-14.32.0}/rust/crates/core/src/lib.rs +0 -0
  121. {cc_transcript-14.31.0 → cc_transcript-14.32.0}/rust/crates/core/src/literals/command.rs +0 -0
  122. {cc_transcript-14.31.0 → cc_transcript-14.32.0}/rust/crates/core/src/literals/corrections.rs +0 -0
  123. {cc_transcript-14.31.0 → cc_transcript-14.32.0}/rust/crates/core/src/literals/feedback.rs +0 -0
  124. {cc_transcript-14.31.0 → cc_transcript-14.32.0}/rust/crates/core/src/literals/mining.rs +0 -0
  125. {cc_transcript-14.31.0 → cc_transcript-14.32.0}/rust/crates/core/src/literals/mod.rs +0 -0
  126. {cc_transcript-14.31.0 → cc_transcript-14.32.0}/rust/crates/core/src/literals/protocol.rs +0 -0
  127. {cc_transcript-14.31.0 → cc_transcript-14.32.0}/rust/crates/core/src/notifications.rs +0 -0
  128. {cc_transcript-14.31.0 → cc_transcript-14.32.0}/rust/crates/core/src/parse.rs +0 -0
  129. {cc_transcript-14.31.0 → cc_transcript-14.32.0}/rust/crates/core/src/protocol.rs +0 -0
  130. {cc_transcript-14.31.0 → cc_transcript-14.32.0}/rust/crates/core/src/pystr.rs +0 -0
  131. {cc_transcript-14.31.0 → cc_transcript-14.32.0}/rust/crates/core/src/query.rs +0 -0
  132. {cc_transcript-14.31.0 → cc_transcript-14.32.0}/rust/crates/core/src/render.rs +0 -0
  133. {cc_transcript-14.31.0 → cc_transcript-14.32.0}/rust/crates/core/src/rng.rs +0 -0
  134. {cc_transcript-14.31.0 → cc_transcript-14.32.0}/rust/crates/core/src/scan.rs +0 -0
  135. {cc_transcript-14.31.0 → cc_transcript-14.32.0}/rust/crates/core/src/scan_grep.rs +0 -0
  136. {cc_transcript-14.31.0 → cc_transcript-14.32.0}/rust/crates/core/src/scan_regressions.rs +0 -0
  137. {cc_transcript-14.31.0 → cc_transcript-14.32.0}/rust/crates/core/src/schema.rs +0 -0
  138. {cc_transcript-14.31.0 → cc_transcript-14.32.0}/rust/crates/core/src/snapshot_activity.rs +0 -0
  139. {cc_transcript-14.31.0 → cc_transcript-14.32.0}/rust/crates/core/src/snapshot_codex_append.rs +0 -0
  140. {cc_transcript-14.31.0 → cc_transcript-14.32.0}/rust/crates/core/src/snapshot_memory.rs +0 -0
  141. {cc_transcript-14.31.0 → cc_transcript-14.32.0}/rust/crates/core/src/snapshot_owned.rs +0 -0
  142. {cc_transcript-14.31.0 → cc_transcript-14.32.0}/rust/crates/core/src/snapshot_prepared.rs +0 -0
  143. {cc_transcript-14.31.0 → cc_transcript-14.32.0}/rust/crates/core/src/snapshot_prepared_disk.rs +0 -0
  144. {cc_transcript-14.31.0 → cc_transcript-14.32.0}/rust/crates/core/src/snapshot_regressions.rs +0 -0
  145. {cc_transcript-14.31.0 → cc_transcript-14.32.0}/rust/crates/core/src/snapshot_text.rs +0 -0
  146. {cc_transcript-14.31.0 → cc_transcript-14.32.0}/rust/crates/core/src/sqlite.rs +0 -0
  147. {cc_transcript-14.31.0 → cc_transcript-14.32.0}/rust/crates/core/src/toolcall.rs +0 -0
  148. {cc_transcript-14.31.0 → cc_transcript-14.32.0}/rust/crates/core/src/types.rs +0 -0
  149. {cc_transcript-14.31.0 → cc_transcript-14.32.0}/rust/crates/core/src/value.rs +0 -0
  150. {cc_transcript-14.31.0 → cc_transcript-14.32.0}/rust/crates/core/src/watch.rs +0 -0
  151. {cc_transcript-14.31.0 → cc_transcript-14.32.0}/rust/crates/py/Cargo.toml +0 -0
  152. {cc_transcript-14.31.0 → cc_transcript-14.32.0}/rust/crates/py/build.rs +0 -0
  153. {cc_transcript-14.31.0 → cc_transcript-14.32.0}/rust/crates/py/data/command_prefix_pins.tsv +0 -0
  154. {cc_transcript-14.31.0 → cc_transcript-14.32.0}/rust/crates/py/src/actor_bridge.rs +0 -0
  155. {cc_transcript-14.31.0 → cc_transcript-14.32.0}/rust/crates/py/src/bin/stub_gen.rs +0 -0
  156. {cc_transcript-14.31.0 → cc_transcript-14.32.0}/rust/crates/py/src/codex.rs +0 -0
  157. {cc_transcript-14.31.0 → cc_transcript-14.32.0}/rust/crates/py/src/command.rs +0 -0
  158. {cc_transcript-14.31.0 → cc_transcript-14.32.0}/rust/crates/py/src/context.rs +0 -0
  159. {cc_transcript-14.31.0 → cc_transcript-14.32.0}/rust/crates/py/src/corrections.rs +0 -0
  160. {cc_transcript-14.31.0 → cc_transcript-14.32.0}/rust/crates/py/src/discovery.rs +0 -0
  161. {cc_transcript-14.31.0 → cc_transcript-14.32.0}/rust/crates/py/src/feedback.rs +0 -0
  162. {cc_transcript-14.31.0 → cc_transcript-14.32.0}/rust/crates/py/src/judge.rs +0 -0
  163. {cc_transcript-14.31.0 → cc_transcript-14.32.0}/rust/crates/py/src/lexicon.rs +0 -0
  164. {cc_transcript-14.31.0 → cc_transcript-14.32.0}/rust/crates/py/src/lib.rs +0 -0
  165. {cc_transcript-14.31.0 → cc_transcript-14.32.0}/rust/crates/py/src/mining.rs +0 -0
  166. {cc_transcript-14.31.0 → cc_transcript-14.32.0}/rust/crates/py/src/nlp.rs +0 -0
  167. {cc_transcript-14.31.0 → cc_transcript-14.32.0}/rust/crates/py/src/python.rs +0 -0
  168. {cc_transcript-14.31.0 → cc_transcript-14.32.0}/rust/crates/py/src/render.rs +0 -0
  169. {cc_transcript-14.31.0 → cc_transcript-14.32.0}/rust/crates/py/src/score.rs +0 -0
  170. {cc_transcript-14.31.0 → cc_transcript-14.32.0}/rust/crates/py/src/snapshot_decode.rs +0 -0
  171. {cc_transcript-14.31.0 → cc_transcript-14.32.0}/rust/crates/py/src/snapshots.rs +0 -0
  172. {cc_transcript-14.31.0 → cc_transcript-14.32.0}/rust/crates/py/src/sqlite.rs +0 -0
  173. {cc_transcript-14.31.0 → cc_transcript-14.32.0}/rust/crates/py/src/toolcall.rs +0 -0
  174. {cc_transcript-14.31.0 → cc_transcript-14.32.0}/rust/crates/py/src/views/attachment.rs +0 -0
  175. {cc_transcript-14.31.0 → cc_transcript-14.32.0}/rust/crates/py/src/views/blocks.rs +0 -0
  176. {cc_transcript-14.31.0 → cc_transcript-14.32.0}/rust/crates/py/src/views/command.rs +0 -0
  177. {cc_transcript-14.31.0 → cc_transcript-14.32.0}/rust/crates/py/src/views/convert.rs +0 -0
  178. {cc_transcript-14.31.0 → cc_transcript-14.32.0}/rust/crates/py/src/views/dunder.rs +0 -0
  179. {cc_transcript-14.31.0 → cc_transcript-14.32.0}/rust/crates/py/src/views/events.rs +0 -0
  180. {cc_transcript-14.31.0 → cc_transcript-14.32.0}/rust/crates/py/src/views/meta.rs +0 -0
  181. {cc_transcript-14.31.0 → cc_transcript-14.32.0}/rust/crates/py/src/views/mod.rs +0 -0
  182. {cc_transcript-14.31.0 → cc_transcript-14.32.0}/rust/crates/py/src/views/print.rs +0 -0
  183. {cc_transcript-14.31.0 → cc_transcript-14.32.0}/rust/crates/py/src/views/store.rs +0 -0
  184. {cc_transcript-14.31.0 → cc_transcript-14.32.0}/rust/crates/py/src/views/system.rs +0 -0
  185. {cc_transcript-14.31.0 → cc_transcript-14.32.0}/rust/crates/py/src/views/toolcall.rs +0 -0
  186. {cc_transcript-14.31.0 → cc_transcript-14.32.0}/rust/crates/py/src/views/toolresult.rs +0 -0
  187. {cc_transcript-14.31.0 → cc_transcript-14.32.0}/rust/crates/py/src/views/transcript.rs +0 -0
  188. {cc_transcript-14.31.0 → cc_transcript-14.32.0}/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.31.0
3
+ Version: 14.32.0
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.31.0" # informational — releases stamp the version from the git tag
3
+ version = "14.32.0" # 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"
@@ -423,6 +423,7 @@ struct Waiter {
423
423
  used_source_bytes: usize,
424
424
  used_events: usize,
425
425
  stage: Option<Arc<ClassifierSlot>>,
426
+ windowed: bool,
426
427
  busy: bool,
427
428
  }
428
429
 
@@ -688,7 +689,7 @@ struct PreparedQueryCursor {
688
689
  graph_id: String,
689
690
  query: Value,
690
691
  pending: Option<PendingPreparedSource>,
691
- root_record: Option<String>,
692
+ input_records: Option<VecDeque<String>>,
692
693
  next: usize,
693
694
  page_output_bytes: usize,
694
695
  remaining: WorkLimits,
@@ -763,7 +764,7 @@ struct GraphCursor {
763
764
  prepared: bool,
764
765
  root_checked: bool,
765
766
  projection_at: usize,
766
- pending_record: Option<(usize, String)>,
767
+ pending_records: VecDeque<(usize, String)>,
767
768
  published_members: Vec<usize>,
768
769
  expires: u64,
769
770
  accounted: usize,
@@ -2507,7 +2508,10 @@ impl NativeStore {
2507
2508
  .values()
2508
2509
  .map(|cursor| {
2509
2510
  size_of::<PreparedQueryCursor>()
2510
- + cursor.root_record.as_ref().map_or(0, String::capacity)
2511
+ + cursor
2512
+ .input_records
2513
+ .as_ref()
2514
+ .map_or(0, |records| records.iter().map(String::capacity).sum())
2511
2515
  + crate::snapshot_memory::value_charge(&cursor.query).owned_capacity_bytes
2512
2516
  })
2513
2517
  .sum::<usize>()
@@ -4154,6 +4158,7 @@ impl NativeStore {
4154
4158
  used_source_bytes: 0,
4155
4159
  used_events: 0,
4156
4160
  stage: None,
4161
+ windowed: window.is_some(),
4157
4162
  busy: false,
4158
4163
  };
4159
4164
  state.waiters.insert(cursor.clone(), waiter.clone());
@@ -4409,6 +4414,14 @@ impl NativeStore {
4409
4414
  if let Some(snapshot) = &load.result {
4410
4415
  let snapshot = Arc::clone(snapshot);
4411
4416
  drop(load);
4417
+ if waiter.windowed && snapshot.provider == Provider::Codex {
4418
+ self.state
4419
+ .lock()
4420
+ .expect("snapshot state")
4421
+ .waiters
4422
+ .remove(token);
4423
+ return Err(invalid("tail_bytes requires a Claude source"));
4424
+ }
4412
4425
  let mut state = self.state.lock().expect("snapshot state");
4413
4426
  if !state
4414
4427
  .latest
@@ -5039,7 +5052,7 @@ impl NativeStore {
5039
5052
  depth: 1,
5040
5053
  });
5041
5054
  }
5042
- let identity = root.stamp.identity;
5055
+ let identity = root.stamp.identity.file();
5043
5056
  let graph = GraphCursor {
5044
5057
  claimant: str_field(context, "claimant")?.to_owned(),
5045
5058
  context: context.clone(),
@@ -5061,7 +5074,7 @@ impl NativeStore {
5061
5074
  prepared: false,
5062
5075
  root_checked: false,
5063
5076
  projection_at: 0,
5064
- pending_record: None,
5077
+ pending_records: VecDeque::new(),
5065
5078
  published_members: Vec::new(),
5066
5079
  expires: (now_ms() + self.config.ttl).min(bounds.deadline_unix_ms),
5067
5080
  accounted: 0,
@@ -5142,9 +5155,10 @@ impl NativeStore {
5142
5155
  .sum::<usize>()
5143
5156
  + graph.tasks.capacity() * size_of::<GraphTask>()
5144
5157
  + graph
5145
- .pending_record
5146
- .as_ref()
5147
- .map_or(0, |(_, record)| record.capacity())
5158
+ .pending_records
5159
+ .iter()
5160
+ .map(|(_, record)| record.capacity())
5161
+ .sum::<usize>()
5148
5162
  + graph.listing.as_ref().map_or(0, |listing| {
5149
5163
  listing
5150
5164
  .children
@@ -5199,7 +5213,7 @@ impl NativeStore {
5199
5213
  &graph.context,
5200
5214
  graph.remaining.deadline_unix_ms,
5201
5215
  )?;
5202
- let identity = snapshot.stamp.identity;
5216
+ let identity = snapshot.stamp.identity.file();
5203
5217
  if !graph.seen.insert(identity)
5204
5218
  && graph.request["query"]["kind"].as_str() != Some("direct_sidechains")
5205
5219
  {
@@ -5556,7 +5570,7 @@ impl NativeStore {
5556
5570
  let mut output_bytes = 128usize;
5557
5571
  let page_limit = self.config.page_items.min(graph.remaining.max_items);
5558
5572
  let mut projected = 0usize;
5559
- while graph.projection_at < total || graph.pending_record.is_some() {
5573
+ while graph.projection_at < total || !graph.pending_records.is_empty() {
5560
5574
  cancel.check(graph.remaining.deadline_unix_ms)?;
5561
5575
  if boolean && projected >= self.config.page_items {
5562
5576
  return Ok(GraphYield::Pending(Value::new_null()));
@@ -5564,7 +5578,7 @@ impl NativeStore {
5564
5578
  if records.len() >= page_limit {
5565
5579
  break;
5566
5580
  }
5567
- let (index, record) = if let Some(pending) = graph.pending_record.take() {
5581
+ let (index, record) = if let Some(pending) = graph.pending_records.pop_front() {
5568
5582
  pending
5569
5583
  } else {
5570
5584
  let position = if reverse {
@@ -5597,27 +5611,27 @@ impl NativeStore {
5597
5611
  let mut bounds = graph.remaining;
5598
5612
  bounds.max_items = 1;
5599
5613
  bounds.max_output_bytes = bounds.max_output_bytes.min(MAX_DATA_BYTES);
5600
- let projection = crate::snapshot_projection::project(
5601
- &node.snapshot,
5602
- &request,
5603
- &bounds,
5604
- cancel,
5605
- 0,
5606
- )?;
5607
- graph.remaining.max_read_bytes = graph
5608
- .remaining
5609
- .max_read_bytes
5610
- .saturating_sub(projection.read_bytes);
5611
- graph.remaining.max_events =
5612
- graph.remaining.max_events.saturating_sub(projection.events);
5613
- if !projection.complete {
5614
- return Err(SnapshotError::new(
5615
- Status::Incomplete,
5616
- "graph member projection incomplete",
5617
- ));
5618
- }
5619
- graph.projection_at += 1;
5620
5614
  if boolean {
5615
+ let projection = crate::snapshot_projection::project(
5616
+ &node.snapshot,
5617
+ &request,
5618
+ &bounds,
5619
+ cancel,
5620
+ 0,
5621
+ )?;
5622
+ graph.remaining.max_read_bytes = graph
5623
+ .remaining
5624
+ .max_read_bytes
5625
+ .saturating_sub(projection.read_bytes);
5626
+ graph.remaining.max_events =
5627
+ graph.remaining.max_events.saturating_sub(projection.events);
5628
+ if !projection.complete {
5629
+ return Err(SnapshotError::new(
5630
+ Status::Incomplete,
5631
+ "graph member projection incomplete",
5632
+ ));
5633
+ }
5634
+ graph.projection_at += 1;
5621
5635
  projected += 1;
5622
5636
  if projection.data["value"].as_bool() == Some(true) {
5623
5637
  return Ok(GraphYield::Complete(projection.data));
@@ -5627,20 +5641,29 @@ impl NativeStore {
5627
5641
  }
5628
5642
  continue;
5629
5643
  }
5630
- (
5631
- index,
5632
- projection.data["records_json"][0]
5633
- .as_str()
5634
- .ok_or_else(|| invalid("predicate member returned no record"))?
5635
- .to_owned(),
5636
- )
5644
+ let (member_records, read_bytes, events) =
5645
+ crate::snapshot_projection::predicate_input_records(
5646
+ &node.snapshot,
5647
+ &request["view"]["selectors"],
5648
+ &bounds,
5649
+ cancel,
5650
+ )?;
5651
+ graph.remaining.max_read_bytes =
5652
+ graph.remaining.max_read_bytes.saturating_sub(read_bytes);
5653
+ graph.remaining.max_events = graph.remaining.max_events.saturating_sub(events);
5654
+ graph.projection_at += 1;
5655
+ let mut member_records =
5656
+ member_records.into_iter().map(|record| (index, record));
5657
+ let first = member_records.next().expect("predicate member record");
5658
+ graph.pending_records.extend(member_records);
5659
+ first
5637
5660
  }
5638
5661
  };
5639
5662
  let record_bytes = encoded_size(&json!(&record), MAX_DATA_BYTES)?;
5640
5663
  if output_bytes.saturating_add(record_bytes)
5641
5664
  > graph.remaining.max_output_bytes.min(MAX_DATA_BYTES)
5642
5665
  {
5643
- graph.pending_record = Some((index, record));
5666
+ graph.pending_records.push_front((index, record));
5644
5667
  if records.is_empty() {
5645
5668
  return Err(SnapshotError::new(
5646
5669
  Status::OutputLimit,
@@ -5664,7 +5687,7 @@ impl NativeStore {
5664
5687
  .remaining
5665
5688
  .max_items
5666
5689
  .saturating_sub(data["records_json"].as_array().expect("records").len());
5667
- if graph.projection_at >= total && graph.pending_record.is_none() {
5690
+ if graph.projection_at >= total && graph.pending_records.is_empty() {
5668
5691
  Ok(GraphYield::Complete(data))
5669
5692
  } else if graph.remaining.max_items == 0 {
5670
5693
  Err(SnapshotError::new(
@@ -8235,6 +8258,64 @@ mod tests {
8235
8258
  &Cancellation::default(),
8236
8259
  );
8237
8260
  assert_eq!(zero["status"].as_str(), Some("invalid_request"));
8261
+ let size = std::fs::metadata(&codex.path).unwrap().len();
8262
+ for tail_bytes in [size, size - 1, 1024 * 1024] {
8263
+ let covered = finish(
8264
+ &store,
8265
+ store.request(
8266
+ &windowed_acquire(&codex.path, tail_bytes),
8267
+ &owner,
8268
+ &Cancellation::default(),
8269
+ ),
8270
+ &owner,
8271
+ );
8272
+ assert_eq!(
8273
+ covered["reason"].as_str(),
8274
+ Some("tail_bytes requires a Claude source"),
8275
+ "{tail_bytes}: {covered:?}"
8276
+ );
8277
+ }
8278
+ let whole = finish(
8279
+ &store,
8280
+ store.request(&acquire(&codex.path), &owner, &Cancellation::default()),
8281
+ &owner,
8282
+ );
8283
+ assert_eq!(whole["status"].as_str(), Some("ok"), "{whole:?}");
8284
+ let cached = finish(
8285
+ &store,
8286
+ store.request(
8287
+ &windowed_acquire(&codex.path, 1024 * 1024),
8288
+ &owner,
8289
+ &Cancellation::default(),
8290
+ ),
8291
+ &owner,
8292
+ );
8293
+ assert_eq!(cached["status"].as_str(), Some("invalid_request"));
8294
+ assert_eq!(
8295
+ cached["reason"].as_str(),
8296
+ Some("tail_bytes requires a Claude source")
8297
+ );
8298
+ }
8299
+
8300
+ #[test]
8301
+ fn windowed_root_attached_to_itself_is_not_its_own_child() {
8302
+ let source = Source::new(&users(0..200));
8303
+ let store = windowed_store();
8304
+ let owner = context("a");
8305
+ let root = windowed(&store, &source.path, 4096, &owner);
8306
+ let (_, _, first) = expected_window(&source.path, 4096);
8307
+ assert!(first > 0);
8308
+ let records = graph_records(
8309
+ &store,
8310
+ &graph_request(
8311
+ &root,
8312
+ json!({"kind":"sidechain_membership","order":"forward"}),
8313
+ vec![source.path.to_string_lossy().into_owned()],
8314
+ json!([]),
8315
+ ),
8316
+ &owner,
8317
+ );
8318
+ assert!(records.is_empty(), "{records:?}");
8238
8319
  }
8239
8320
 
8240
8321
  #[test]
@@ -9183,6 +9264,78 @@ mod tests {
9183
9264
  assert_eq!(after[15], after_first[15]);
9184
9265
  }
9185
9266
 
9267
+ #[test]
9268
+ fn deep_predicate_inputs_split_a_window_over_the_record_bound() {
9269
+ let commands: Vec<String> = (0..48)
9270
+ .map(|index| format!("echo {index:02} {}", "x".repeat(32 * 1024)))
9271
+ .collect();
9272
+ let tools: String = commands
9273
+ .iter()
9274
+ .enumerate()
9275
+ .map(|(index, command)| format!(
9276
+ "{}\n",
9277
+ format_args!(r#"{{"type":"assistant","uuid":"tool-{index}","sessionId":"s","timestamp":"2026-01-02T03:04:06Z","message":{{"model":"test","content":[{{"type":"tool_use","id":"bash-{index}","name":"Bash","input":{{"command":"{command}"}}}}]}}}}"#)
9278
+ ))
9279
+ .collect();
9280
+ let source = Source::new(&format!("{}\n{tools}", user("root")));
9281
+ let store = NativeStore::new(&json!({"max_read_bytes_per_step":4*1024*1024,"max_events_per_step":256,"max_entry_bytes":64*1024,"max_retained_bytes":64*1024*1024,"reserved_hook_accounted_bytes":4096,"max_leases":16,"reserved_hook_leases":1})).unwrap();
9282
+ let owner = context("a");
9283
+ let mut template = acquire(&source.path);
9284
+ template["limits"].insert("max_read_bytes", json!(64 * 1024 * 1024));
9285
+ template["limits"].insert("max_source_read_bytes", json!(64 * 1024 * 1024));
9286
+ template["limits"].insert("max_output_bytes", json!(16 * 1024 * 1024));
9287
+ let root = finish(
9288
+ &store,
9289
+ store.request(&template, &owner, &Cancellation::default()),
9290
+ &owner,
9291
+ );
9292
+ let commands_of = |records: &[String]| -> Vec<String> {
9293
+ assert!(records.len() > 1, "{} records", records.len());
9294
+ for record in records {
9295
+ assert!(record.len() <= crate::snapshot_codec::MAX_RECORD_BYTES);
9296
+ }
9297
+ crate::snapshot_codec::decode_predicate_inputs(
9298
+ records,
9299
+ crate::snapshot_codec::MAX_PAGE_BYTES,
9300
+ )
9301
+ .unwrap()
9302
+ .into_iter()
9303
+ .flat_map(|record| record.commands)
9304
+ .collect()
9305
+ };
9306
+ let pages = |mut page: Value| -> Vec<String> {
9307
+ let mut records = Vec::new();
9308
+ for _ in 0..64 {
9309
+ records.extend(
9310
+ page["data"]["records_json"]
9311
+ .as_array()
9312
+ .unwrap_or_else(|| panic!("{page:?}"))
9313
+ .iter()
9314
+ .map(|item| item.as_str().unwrap().to_owned()),
9315
+ );
9316
+ if page["status"].as_str() == Some("ok") {
9317
+ return records;
9318
+ }
9319
+ assert_eq!(page["status"].as_str(), Some("incomplete"), "{page:?}");
9320
+ page = store.request(&json!({"schema":SCHEMA,"id":"resume","operation":"resume","cursor":page["cursor"]}), &owner, &Cancellation::default());
9321
+ }
9322
+ panic!("deep predicate inputs did not finish");
9323
+ };
9324
+ let mut query = graph_request(
9325
+ &root,
9326
+ json!({"kind":"deep_predicate_inputs","order":"forward"}),
9327
+ Vec::new(),
9328
+ json!([]),
9329
+ );
9330
+ query["limits"] = template["limits"].clone();
9331
+ let lease = pages(store.request(&query, &owner, &Cancellation::default()));
9332
+ assert_eq!(commands_of(&lease), commands);
9333
+ let prepare = finish_prepared(&store, store.request(&json!({"schema":SCHEMA,"id":"prepare","operation":"prepare_graph","view":{"handle":handle(&root),"classifier":{"id":"native","version":"1"},"selectors":[],"attachments":[]},"thread_ids":[],"roots":[],"direct_paths":[],"deadline_unix_ms":template["deadline_unix_ms"],"limits":template["limits"]}), &owner, &Cancellation::default()), &owner);
9334
+ assert_eq!(prepare["status"].as_str(), Some("ok"), "{prepare:?}");
9335
+ let prepared = pages(store.request(&json!({"schema":SCHEMA,"id":"inputs","operation":"query_graph","handle":prepare["data"]["handle"],"selectors":[],"query":{"kind":"deep_predicate_inputs","order":"forward"},"deadline_unix_ms":template["deadline_unix_ms"],"limits":template["limits"]}), &owner, &Cancellation::default()));
9336
+ assert_eq!(commands_of(&prepared), commands);
9337
+ }
9338
+
9186
9339
  #[test]
9187
9340
  fn expired_prepared_query_reports_deadline_after_pruning() {
9188
9341
  let source = Source::new(&format!("{}\n", user("root")));
@@ -144,6 +144,48 @@ pub struct PredicateInputsRecord {
144
144
  pub skills: Vec<String>,
145
145
  }
146
146
 
147
+ pub const PREDICATE_INPUT_CHUNK_BYTES: usize = 256 * 1024;
148
+
149
+ pub fn predicate_input_records(inputs: &sonic_rs::Value) -> Result<Vec<String>, SnapshotError> {
150
+ use sonic_rs::JsonContainerTrait;
151
+
152
+ let mut records = Vec::new();
153
+ let mut fields: [Vec<String>; 4] = Default::default();
154
+ let mut bytes = 0usize;
155
+ for (slot, name) in ["calls", "commands", "edited_files", "skills"]
156
+ .into_iter()
157
+ .enumerate()
158
+ {
159
+ for item in inputs[name]
160
+ .as_array()
161
+ .expect("predicate input field")
162
+ .iter()
163
+ {
164
+ let item = encode(item, MAX_RECORD_BYTES)?;
165
+ let cost = encoded_size(item.as_str(), MAX_RECORD_BYTES)? + 1;
166
+ if bytes > 0 && bytes + cost > PREDICATE_INPUT_CHUNK_BYTES {
167
+ records.push(predicate_input_record(&fields));
168
+ fields = Default::default();
169
+ bytes = 0;
170
+ }
171
+ bytes += cost;
172
+ fields[slot].push(item);
173
+ }
174
+ }
175
+ records.push(predicate_input_record(&fields));
176
+ Ok(records)
177
+ }
178
+
179
+ fn predicate_input_record([calls, commands, edited_files, skills]: &[Vec<String>; 4]) -> String {
180
+ format!(
181
+ r#"{{"calls":[{}],"commands":[{}],"edited_files":[{}],"skills":[{}]}}"#,
182
+ calls.join(","),
183
+ commands.join(","),
184
+ edited_files.join(","),
185
+ skills.join(",")
186
+ )
187
+ }
188
+
147
189
  #[derive(Debug, Serialize, Deserialize)]
148
190
  #[serde(deny_unknown_fields)]
149
191
  pub struct SidechainRecord {
@@ -470,7 +470,7 @@ impl LabelPreparation {
470
470
  session_id: self.source.session_id.clone(),
471
471
  chunks: self.source.chunks.clone(),
472
472
  activity: Arc::new(self.activity),
473
- window_start: 0,
473
+ window_start: self.source.window_start,
474
474
  committed_bytes: self.source.committed_bytes,
475
475
  provisional_tail: self.source.provisional_tail,
476
476
  fence: self.source.fence.clone(),
@@ -1042,4 +1042,26 @@ mod tests {
1042
1042
  "labels:execution"
1043
1043
  );
1044
1044
  }
1045
+
1046
+ #[test]
1047
+ fn finish_keeps_the_source_window_start() {
1048
+ let mut snapshot = source(vec![user(0, "prompt"), user(1, "later")]);
1049
+ {
1050
+ let windowed = Arc::get_mut(&mut snapshot).unwrap();
1051
+ windowed.window_start = 1000;
1052
+ windowed.stamp.identity.window_base = 1024;
1053
+ }
1054
+ let binding = binding("execution");
1055
+ let cancel = Cancellation::default();
1056
+ let mut stage =
1057
+ LabelPreparation::new(snapshot, binding.clone(), limits(), 8 * PAGE_BYTES, None)
1058
+ .unwrap();
1059
+ stage.next_page("page1".into(), &binding, &cancel).unwrap();
1060
+ assert!(stage
1061
+ .submit("page1", &[true, false], &binding, &cancel)
1062
+ .unwrap());
1063
+ let derived = stage.finish(&binding, &cancel).unwrap().0;
1064
+ assert_eq!(derived.window_start, 1000);
1065
+ assert_eq!(derived.stamp.identity.window_base, 1024);
1066
+ }
1045
1067
  }
@@ -1465,8 +1465,8 @@ impl NativeStore {
1465
1465
  }
1466
1466
  (graph.sources.clone(), graph.sidechain_dirs.clone())
1467
1467
  };
1468
- let inputs = cursor.root_record.is_some();
1469
- let total = sources.len() + usize::from(inputs);
1468
+ let inputs = cursor.input_records.is_some();
1469
+ let total = sources.len();
1470
1470
  let mut records = Vec::new();
1471
1471
  let mut bytes = 128usize;
1472
1472
  let mut steps = 0usize;
@@ -1483,27 +1483,30 @@ impl NativeStore {
1483
1483
  "prepared query output budget exhausted",
1484
1484
  ));
1485
1485
  }
1486
- while cursor.next < total
1486
+ while (cursor.next < total
1487
+ || cursor.input_records.as_ref().is_some_and(|records| !records.is_empty()))
1487
1488
  && steps < page_steps
1488
1489
  && uncached_steps < 8
1489
1490
  && (!inputs || records.len() < page_items)
1490
1491
  {
1491
1492
  cancel.check(cursor.remaining.deadline_unix_ms)?;
1492
- if inputs && cursor.next == 0 {
1493
- let record = cursor.root_record.as_ref().expect("input root record").clone();
1493
+ if let Some(record) = cursor.input_records.as_mut().and_then(VecDeque::pop_front) {
1494
1494
  let record_bytes = encoded_size(&json!(&record), MAX_DATA_BYTES)? + 1;
1495
1495
  if bytes + record_bytes > output_limit {
1496
- return Err(SnapshotError::new(
1497
- Status::OutputLimit,
1498
- "prepared input record exceeds page bound",
1499
- ));
1496
+ if records.is_empty() {
1497
+ return Err(SnapshotError::new(
1498
+ Status::OutputLimit,
1499
+ "prepared input record exceeds page bound",
1500
+ ));
1501
+ }
1502
+ cursor.input_records.as_mut().expect("input records").push_front(record);
1503
+ break;
1500
1504
  }
1501
1505
  bytes += record_bytes;
1502
1506
  records.push(record);
1503
- cursor.next += 1;
1504
1507
  continue;
1505
1508
  }
1506
- let source = &sources[cursor.next - usize::from(inputs)];
1509
+ let source = &sources[cursor.next];
1507
1510
  self.authority(context, Some(&source.path))?;
1508
1511
  let metadata = std::fs::metadata(&source.path).map_err(io_error)?;
1509
1512
  if SourceStamp::of(&metadata) != source.stamp {
@@ -1576,20 +1579,11 @@ impl NativeStore {
1576
1579
  ));
1577
1580
  }
1578
1581
  if inputs {
1579
- let record = sonic_rs::to_string(&facts.inputs)
1580
- .map_err(|error| invalid(error.to_string()))?;
1581
- let record_bytes = encoded_size(&json!(&record), MAX_DATA_BYTES)? + 1;
1582
- if bytes + record_bytes > output_limit {
1583
- if records.is_empty() {
1584
- return Err(SnapshotError::new(
1585
- Status::OutputLimit,
1586
- "prepared input record exceeds page bound",
1587
- ));
1588
- }
1589
- break;
1590
- }
1591
- bytes += record_bytes;
1592
- records.push(record);
1582
+ cursor
1583
+ .input_records
1584
+ .as_mut()
1585
+ .expect("input records")
1586
+ .extend(crate::snapshot_codec::predicate_input_records(&facts.inputs)?);
1593
1587
  } else if facts.query(&cursor.query)?["value"].as_bool() == Some(true) {
1594
1588
  let data = json!({"kind":"scalar","value":true});
1595
1589
  encoded_size(&data, output_limit)?;
@@ -1599,7 +1593,9 @@ impl NativeStore {
1599
1593
  steps += 1;
1600
1594
  uncached_steps += usize::from(!cached);
1601
1595
  }
1602
- if cursor.next == total {
1596
+ if cursor.next == total
1597
+ && cursor.input_records.as_ref().is_none_or(VecDeque::is_empty)
1598
+ {
1603
1599
  if !self.validate_source_stamps(
1604
1600
  &sources,
1605
1601
  context,
@@ -1781,8 +1777,10 @@ impl NativeStore {
1781
1777
  encoded_size(&data, bounds.max_output_bytes)?;
1782
1778
  return Ok((data, None, None));
1783
1779
  }
1784
- let root_record = if kind == "deep_predicate_inputs" {
1785
- Some(sonic_rs::to_string(&root_facts.inputs).map_err(|error| invalid(error.to_string()))?)
1780
+ let input_records = if kind == "deep_predicate_inputs" {
1781
+ Some(VecDeque::from(crate::snapshot_codec::predicate_input_records(
1782
+ &root_facts.inputs,
1783
+ )?))
1786
1784
  } else {
1787
1785
  None
1788
1786
  };
@@ -1791,7 +1789,7 @@ impl NativeStore {
1791
1789
  graph_id: token.to_owned(),
1792
1790
  query: query.clone(),
1793
1791
  pending: None,
1794
- root_record,
1792
+ input_records,
1795
1793
  next: 0,
1796
1794
  page_output_bytes: bounds.max_output_bytes.min(MAX_DATA_BYTES),
1797
1795
  remaining: bounds,
@@ -1456,6 +1456,31 @@ fn predicate_inputs_query(
1456
1456
  next: usize,
1457
1457
  work: &Work,
1458
1458
  ) -> Result<Projection, SnapshotError> {
1459
+ record_page(
1460
+ predicate_records(session)?.into_iter().map(Ok),
1461
+ "cc-transcript.predicate-inputs/1",
1462
+ next,
1463
+ false,
1464
+ work,
1465
+ )
1466
+ }
1467
+
1468
+ pub fn predicate_input_records(
1469
+ snapshot: &TranscriptSnapshot,
1470
+ selectors: &Value,
1471
+ limits: &WorkLimits,
1472
+ cancel: &Cancellation,
1473
+ ) -> Result<(Vec<String>, usize, usize), SnapshotError> {
1474
+ let request = json!({"view":{"attachments":[],"selectors":selectors}});
1475
+ let mut work = Work::new(snapshot, limits, cancel);
1476
+ let range = selected_range(&mut work, &request)?;
1477
+ work.charge_range(range.clone())?;
1478
+ let lift = lift_range(&mut work, &range, None)?;
1479
+ let records = predicate_records(&view(&lift, &range, snapshot))?;
1480
+ Ok((records, work.bytes, work.events))
1481
+ }
1482
+
1483
+ fn predicate_records(session: &Session) -> Result<Vec<String>, SnapshotError> {
1459
1484
  let calls = session.tool_calls().items();
1460
1485
  let wire = PredicateInputWire {
1461
1486
  calls: calls
@@ -1482,12 +1507,8 @@ fn predicate_inputs_query(
1482
1507
  })
1483
1508
  .collect(),
1484
1509
  };
1485
- record_page(
1486
- std::iter::once(snapshot_codec::encode(&wire, work.limits.max_output_bytes)),
1487
- "cc-transcript.predicate-inputs/1",
1488
- next,
1489
- false,
1490
- work,
1510
+ snapshot_codec::predicate_input_records(
1511
+ &sonic_rs::to_value(&wire).map_err(|error| invalid(error.to_string()))?,
1491
1512
  )
1492
1513
  }
1493
1514