deepstrike 0.2.79__tar.gz → 0.2.80__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 (269) hide show
  1. {deepstrike-0.2.79 → deepstrike-0.2.80}/Cargo.lock +14 -6
  2. {deepstrike-0.2.79 → deepstrike-0.2.80}/Cargo.toml +3 -3
  3. {deepstrike-0.2.79 → deepstrike-0.2.80}/PKG-INFO +1 -1
  4. {deepstrike-0.2.79 → deepstrike-0.2.80}/crates/deepstrike-core/src/context/item.rs +21 -1
  5. {deepstrike-0.2.79 → deepstrike-0.2.80}/crates/deepstrike-core/src/context/manager.rs +351 -3
  6. {deepstrike-0.2.79 → deepstrike-0.2.80}/crates/deepstrike-core/src/context/partitions.rs +116 -16
  7. {deepstrike-0.2.79 → deepstrike-0.2.80}/crates/deepstrike-core/src/context/renderer.rs +18 -0
  8. {deepstrike-0.2.79 → deepstrike-0.2.80}/crates/deepstrike-core/src/runtime/kernel/wire/checkpoint.rs +24 -0
  9. {deepstrike-0.2.79 → deepstrike-0.2.80}/crates/deepstrike-core/src/runtime/kernel/wire/crash_point.rs +8 -0
  10. {deepstrike-0.2.79 → deepstrike-0.2.80}/crates/deepstrike-core/src/runtime/kernel/wire/driver/effects.rs +6 -2
  11. {deepstrike-0.2.79 → deepstrike-0.2.80}/crates/deepstrike-core/src/runtime/kernel/wire/driver/projection.rs +23 -0
  12. {deepstrike-0.2.79 → deepstrike-0.2.80}/crates/deepstrike-core/src/runtime/kernel/wire/driver/provider.rs +21 -0
  13. {deepstrike-0.2.79 → deepstrike-0.2.80}/crates/deepstrike-core/src/runtime/kernel/wire/driver/tests.rs +105 -7
  14. {deepstrike-0.2.79 → deepstrike-0.2.80}/crates/deepstrike-core/src/runtime/kernel/wire/driver.rs +37 -1
  15. {deepstrike-0.2.79 → deepstrike-0.2.80}/crates/deepstrike-core/src/runtime/kernel/wire/effect.rs +42 -0
  16. {deepstrike-0.2.79 → deepstrike-0.2.80}/crates/deepstrike-core/src/scheduler/state_machine/mod.rs +19 -0
  17. {deepstrike-0.2.79 → deepstrike-0.2.80}/crates/deepstrike-py/src/lib.rs +8 -1
  18. {deepstrike-0.2.79 → deepstrike-0.2.80}/deepstrike/__init__.py +16 -0
  19. {deepstrike-0.2.79 → deepstrike-0.2.80}/deepstrike/providers/base.py +6 -0
  20. {deepstrike-0.2.79 → deepstrike-0.2.80}/deepstrike/runtime/canonical_kernel_step.py +33 -0
  21. deepstrike-0.2.80/deepstrike/runtime/dynamic_workflow.py +279 -0
  22. {deepstrike-0.2.79 → deepstrike-0.2.80}/deepstrike/runtime/kernel_step.py +6 -0
  23. {deepstrike-0.2.79 → deepstrike-0.2.80}/deepstrike/runtime/runner.py +152 -0
  24. {deepstrike-0.2.79 → deepstrike-0.2.80}/deepstrike/types/content.py +1 -0
  25. {deepstrike-0.2.79 → deepstrike-0.2.80}/pyproject.toml +1 -1
  26. {deepstrike-0.2.79 → deepstrike-0.2.80}/LICENSE +0 -0
  27. {deepstrike-0.2.79 → deepstrike-0.2.80}/README.md +0 -0
  28. {deepstrike-0.2.79 → deepstrike-0.2.80}/crates/deepstrike-core/Cargo.toml +0 -0
  29. {deepstrike-0.2.79 → deepstrike-0.2.80}/crates/deepstrike-core/LICENSE +0 -0
  30. {deepstrike-0.2.79 → deepstrike-0.2.80}/crates/deepstrike-core/benches/kernel_baseline.rs +0 -0
  31. {deepstrike-0.2.79 → deepstrike-0.2.80}/crates/deepstrike-core/benches/wait_index_baseline.rs +0 -0
  32. {deepstrike-0.2.79 → deepstrike-0.2.80}/crates/deepstrike-core/src/benchmark/mod.rs +0 -0
  33. {deepstrike-0.2.79 → deepstrike-0.2.80}/crates/deepstrike-core/src/context/compression.rs +0 -0
  34. {deepstrike-0.2.79 → deepstrike-0.2.80}/crates/deepstrike-core/src/context/config.rs +0 -0
  35. {deepstrike-0.2.79 → deepstrike-0.2.80}/crates/deepstrike-core/src/context/fault.rs +0 -0
  36. {deepstrike-0.2.79 → deepstrike-0.2.80}/crates/deepstrike-core/src/context/measurement.rs +0 -0
  37. {deepstrike-0.2.79 → deepstrike-0.2.80}/crates/deepstrike-core/src/context/mod.rs +0 -0
  38. {deepstrike-0.2.79 → deepstrike-0.2.80}/crates/deepstrike-core/src/context/policy.rs +0 -0
  39. {deepstrike-0.2.79 → deepstrike-0.2.80}/crates/deepstrike-core/src/context/pressure.rs +0 -0
  40. {deepstrike-0.2.79 → deepstrike-0.2.80}/crates/deepstrike-core/src/context/renewal.rs +0 -0
  41. {deepstrike-0.2.79 → deepstrike-0.2.80}/crates/deepstrike-core/src/context/skill_catalog.rs +0 -0
  42. {deepstrike-0.2.79 → deepstrike-0.2.80}/crates/deepstrike-core/src/context/summarizer.rs +0 -0
  43. {deepstrike-0.2.79 → deepstrike-0.2.80}/crates/deepstrike-core/src/context/task_state.rs +0 -0
  44. {deepstrike-0.2.79 → deepstrike-0.2.80}/crates/deepstrike-core/src/context/text.rs +0 -0
  45. {deepstrike-0.2.79 → deepstrike-0.2.80}/crates/deepstrike-core/src/context/token_engine.rs +0 -0
  46. {deepstrike-0.2.79 → deepstrike-0.2.80}/crates/deepstrike-core/src/context/units.rs +0 -0
  47. {deepstrike-0.2.79 → deepstrike-0.2.80}/crates/deepstrike-core/src/context/utility.rs +0 -0
  48. {deepstrike-0.2.79 → deepstrike-0.2.80}/crates/deepstrike-core/src/governance/constraint.rs +0 -0
  49. {deepstrike-0.2.79 → deepstrike-0.2.80}/crates/deepstrike-core/src/governance/mod.rs +0 -0
  50. {deepstrike-0.2.79 → deepstrike-0.2.80}/crates/deepstrike-core/src/governance/permission.rs +0 -0
  51. {deepstrike-0.2.79 → deepstrike-0.2.80}/crates/deepstrike-core/src/governance/pipeline.rs +0 -0
  52. {deepstrike-0.2.79 → deepstrike-0.2.80}/crates/deepstrike-core/src/governance/quota.rs +0 -0
  53. {deepstrike-0.2.79 → deepstrike-0.2.80}/crates/deepstrike-core/src/governance/rate_limit.rs +0 -0
  54. {deepstrike-0.2.79 → deepstrike-0.2.80}/crates/deepstrike-core/src/governance/repeat_fuse.rs +0 -0
  55. {deepstrike-0.2.79 → deepstrike-0.2.80}/crates/deepstrike-core/src/governance/veto.rs +0 -0
  56. {deepstrike-0.2.79 → deepstrike-0.2.80}/crates/deepstrike-core/src/harness/eval.rs +0 -0
  57. {deepstrike-0.2.79 → deepstrike-0.2.80}/crates/deepstrike-core/src/harness/mod.rs +0 -0
  58. {deepstrike-0.2.79 → deepstrike-0.2.80}/crates/deepstrike-core/src/lexical.rs +0 -0
  59. {deepstrike-0.2.79 → deepstrike-0.2.80}/crates/deepstrike-core/src/lib.rs +0 -0
  60. {deepstrike-0.2.79 → deepstrike-0.2.80}/crates/deepstrike-core/src/memory/curator.rs +0 -0
  61. {deepstrike-0.2.79 → deepstrike-0.2.80}/crates/deepstrike-core/src/memory/durable.rs +0 -0
  62. {deepstrike-0.2.79 → deepstrike-0.2.80}/crates/deepstrike-core/src/memory/mod.rs +0 -0
  63. {deepstrike-0.2.79 → deepstrike-0.2.80}/crates/deepstrike-core/src/mm/handle.rs +0 -0
  64. {deepstrike-0.2.79 → deepstrike-0.2.80}/crates/deepstrike-core/src/mm/memory.rs +0 -0
  65. {deepstrike-0.2.79 → deepstrike-0.2.80}/crates/deepstrike-core/src/mm/memory_candidate.rs +0 -0
  66. {deepstrike-0.2.79 → deepstrike-0.2.80}/crates/deepstrike-core/src/mm/mod.rs +0 -0
  67. {deepstrike-0.2.79 → deepstrike-0.2.80}/crates/deepstrike-core/src/mm/value.rs +0 -0
  68. {deepstrike-0.2.79 → deepstrike-0.2.80}/crates/deepstrike-core/src/orchestration/mod.rs +0 -0
  69. {deepstrike-0.2.79 → deepstrike-0.2.80}/crates/deepstrike-core/src/orchestration/task_graph.rs +0 -0
  70. {deepstrike-0.2.79 → deepstrike-0.2.80}/crates/deepstrike-core/src/orchestration/workflow/mod.rs +0 -0
  71. {deepstrike-0.2.79 → deepstrike-0.2.80}/crates/deepstrike-core/src/orchestration/workflow/run.rs +0 -0
  72. {deepstrike-0.2.79 → deepstrike-0.2.80}/crates/deepstrike-core/src/proc/mod.rs +0 -0
  73. {deepstrike-0.2.79 → deepstrike-0.2.80}/crates/deepstrike-core/src/projection_pairs.rs +0 -0
  74. {deepstrike-0.2.79 → deepstrike-0.2.80}/crates/deepstrike-core/src/runtime/event_log.rs +0 -0
  75. {deepstrike-0.2.79 → deepstrike-0.2.80}/crates/deepstrike-core/src/runtime/kernel/observation.rs +0 -0
  76. {deepstrike-0.2.79 → deepstrike-0.2.80}/crates/deepstrike-core/src/runtime/kernel/wire/binding.rs +0 -0
  77. {deepstrike-0.2.79 → deepstrike-0.2.80}/crates/deepstrike-core/src/runtime/kernel/wire/command.rs +0 -0
  78. {deepstrike-0.2.79 → deepstrike-0.2.80}/crates/deepstrike-core/src/runtime/kernel/wire/config.rs +0 -0
  79. {deepstrike-0.2.79 → deepstrike-0.2.80}/crates/deepstrike-core/src/runtime/kernel/wire/driver/continuation.rs +0 -0
  80. {deepstrike-0.2.79 → deepstrike-0.2.80}/crates/deepstrike-core/src/runtime/kernel/wire/driver/events.rs +0 -0
  81. {deepstrike-0.2.79 → deepstrike-0.2.80}/crates/deepstrike-core/src/runtime/kernel/wire/driver/planning.rs +0 -0
  82. {deepstrike-0.2.79 → deepstrike-0.2.80}/crates/deepstrike-core/src/runtime/kernel/wire/driver/syscall.rs +0 -0
  83. {deepstrike-0.2.79 → deepstrike-0.2.80}/crates/deepstrike-core/src/runtime/kernel/wire/envelope.rs +0 -0
  84. {deepstrike-0.2.79 → deepstrike-0.2.80}/crates/deepstrike-core/src/runtime/kernel/wire/event.rs +0 -0
  85. {deepstrike-0.2.79 → deepstrike-0.2.80}/crates/deepstrike-core/src/runtime/kernel/wire/fault.rs +0 -0
  86. {deepstrike-0.2.79 → deepstrike-0.2.80}/crates/deepstrike-core/src/runtime/kernel/wire/memory_authority.rs +0 -0
  87. {deepstrike-0.2.79 → deepstrike-0.2.80}/crates/deepstrike-core/src/runtime/kernel/wire/projection.rs +0 -0
  88. {deepstrike-0.2.79 → deepstrike-0.2.80}/crates/deepstrike-core/src/runtime/kernel/wire/record.rs +0 -0
  89. {deepstrike-0.2.79 → deepstrike-0.2.80}/crates/deepstrike-core/src/runtime/kernel/wire/restore.rs +0 -0
  90. {deepstrike-0.2.79 → deepstrike-0.2.80}/crates/deepstrike-core/src/runtime/kernel/wire/root.rs +0 -0
  91. {deepstrike-0.2.79 → deepstrike-0.2.80}/crates/deepstrike-core/src/runtime/kernel/wire/scalar.rs +0 -0
  92. {deepstrike-0.2.79 → deepstrike-0.2.80}/crates/deepstrike-core/src/runtime/kernel/wire/syscall.rs +0 -0
  93. {deepstrike-0.2.79 → deepstrike-0.2.80}/crates/deepstrike-core/src/runtime/kernel/wire/terminal.rs +0 -0
  94. {deepstrike-0.2.79 → deepstrike-0.2.80}/crates/deepstrike-core/src/runtime/kernel/wire/tests.rs +0 -0
  95. {deepstrike-0.2.79 → deepstrike-0.2.80}/crates/deepstrike-core/src/runtime/kernel/wire/transaction.rs +0 -0
  96. {deepstrike-0.2.79 → deepstrike-0.2.80}/crates/deepstrike-core/src/runtime/kernel/wire.rs +0 -0
  97. {deepstrike-0.2.79 → deepstrike-0.2.80}/crates/deepstrike-core/src/runtime/kernel.rs +0 -0
  98. {deepstrike-0.2.79 → deepstrike-0.2.80}/crates/deepstrike-core/src/runtime/mod.rs +0 -0
  99. {deepstrike-0.2.79 → deepstrike-0.2.80}/crates/deepstrike-core/src/runtime/repair.rs +0 -0
  100. {deepstrike-0.2.79 → deepstrike-0.2.80}/crates/deepstrike-core/src/runtime/replay.rs +0 -0
  101. {deepstrike-0.2.79 → deepstrike-0.2.80}/crates/deepstrike-core/src/runtime/session.rs +0 -0
  102. {deepstrike-0.2.79 → deepstrike-0.2.80}/crates/deepstrike-core/src/runtime/session_registry_tests.rs +0 -0
  103. {deepstrike-0.2.79 → deepstrike-0.2.80}/crates/deepstrike-core/src/runtime/session_wire.rs +0 -0
  104. {deepstrike-0.2.79 → deepstrike-0.2.80}/crates/deepstrike-core/src/scheduler/budget_grant.rs +0 -0
  105. {deepstrike-0.2.79 → deepstrike-0.2.80}/crates/deepstrike-core/src/scheduler/cross_operation.rs +0 -0
  106. {deepstrike-0.2.79 → deepstrike-0.2.80}/crates/deepstrike-core/src/scheduler/entropy.rs +0 -0
  107. {deepstrike-0.2.79 → deepstrike-0.2.80}/crates/deepstrike-core/src/scheduler/mailbox.rs +0 -0
  108. {deepstrike-0.2.79 → deepstrike-0.2.80}/crates/deepstrike-core/src/scheduler/milestone.rs +0 -0
  109. {deepstrike-0.2.79 → deepstrike-0.2.80}/crates/deepstrike-core/src/scheduler/mod.rs +0 -0
  110. {deepstrike-0.2.79 → deepstrike-0.2.80}/crates/deepstrike-core/src/scheduler/policy.rs +0 -0
  111. {deepstrike-0.2.79 → deepstrike-0.2.80}/crates/deepstrike-core/src/scheduler/rollback.rs +0 -0
  112. {deepstrike-0.2.79 → deepstrike-0.2.80}/crates/deepstrike-core/src/scheduler/runnable.rs +0 -0
  113. {deepstrike-0.2.79 → deepstrike-0.2.80}/crates/deepstrike-core/src/scheduler/state_machine/cancellation.rs +0 -0
  114. {deepstrike-0.2.79 → deepstrike-0.2.80}/crates/deepstrike-core/src/scheduler/state_machine/capability.rs +0 -0
  115. {deepstrike-0.2.79 → deepstrike-0.2.80}/crates/deepstrike-core/src/scheduler/state_machine/eviction.rs +0 -0
  116. {deepstrike-0.2.79 → deepstrike-0.2.80}/crates/deepstrike-core/src/scheduler/state_machine/gate.rs +0 -0
  117. {deepstrike-0.2.79 → deepstrike-0.2.80}/crates/deepstrike-core/src/scheduler/state_machine/milestone_exec.rs +0 -0
  118. {deepstrike-0.2.79 → deepstrike-0.2.80}/crates/deepstrike-core/src/scheduler/state_machine/process.rs +0 -0
  119. {deepstrike-0.2.79 → deepstrike-0.2.80}/crates/deepstrike-core/src/scheduler/state_machine/signal.rs +0 -0
  120. {deepstrike-0.2.79 → deepstrike-0.2.80}/crates/deepstrike-core/src/scheduler/state_machine/tests.rs +0 -0
  121. {deepstrike-0.2.79 → deepstrike-0.2.80}/crates/deepstrike-core/src/scheduler/state_machine/workflow.rs +0 -0
  122. {deepstrike-0.2.79 → deepstrike-0.2.80}/crates/deepstrike-core/src/scheduler/tcb.rs +0 -0
  123. {deepstrike-0.2.79 → deepstrike-0.2.80}/crates/deepstrike-core/src/scheduler/wait_index.rs +0 -0
  124. {deepstrike-0.2.79 → deepstrike-0.2.80}/crates/deepstrike-core/src/signals/attention.rs +0 -0
  125. {deepstrike-0.2.79 → deepstrike-0.2.80}/crates/deepstrike-core/src/signals/mod.rs +0 -0
  126. {deepstrike-0.2.79 → deepstrike-0.2.80}/crates/deepstrike-core/src/signals/queue.rs +0 -0
  127. {deepstrike-0.2.79 → deepstrike-0.2.80}/crates/deepstrike-core/src/signals/router.rs +0 -0
  128. {deepstrike-0.2.79 → deepstrike-0.2.80}/crates/deepstrike-core/src/syscall/mod.rs +0 -0
  129. {deepstrike-0.2.79 → deepstrike-0.2.80}/crates/deepstrike-core/src/types/agent.rs +0 -0
  130. {deepstrike-0.2.79 → deepstrike-0.2.80}/crates/deepstrike-core/src/types/capability.rs +0 -0
  131. {deepstrike-0.2.79 → deepstrike-0.2.80}/crates/deepstrike-core/src/types/contract.rs +0 -0
  132. {deepstrike-0.2.79 → deepstrike-0.2.80}/crates/deepstrike-core/src/types/durable_content.rs +0 -0
  133. {deepstrike-0.2.79 → deepstrike-0.2.80}/crates/deepstrike-core/src/types/error.rs +0 -0
  134. {deepstrike-0.2.79 → deepstrike-0.2.80}/crates/deepstrike-core/src/types/message.rs +0 -0
  135. {deepstrike-0.2.79 → deepstrike-0.2.80}/crates/deepstrike-core/src/types/milestone.rs +0 -0
  136. {deepstrike-0.2.79 → deepstrike-0.2.80}/crates/deepstrike-core/src/types/mod.rs +0 -0
  137. {deepstrike-0.2.79 → deepstrike-0.2.80}/crates/deepstrike-core/src/types/policy.rs +0 -0
  138. {deepstrike-0.2.79 → deepstrike-0.2.80}/crates/deepstrike-core/src/types/result.rs +0 -0
  139. {deepstrike-0.2.79 → deepstrike-0.2.80}/crates/deepstrike-core/src/types/signal.rs +0 -0
  140. {deepstrike-0.2.79 → deepstrike-0.2.80}/crates/deepstrike-core/src/types/skill.rs +0 -0
  141. {deepstrike-0.2.79 → deepstrike-0.2.80}/crates/deepstrike-core/src/types/task.rs +0 -0
  142. {deepstrike-0.2.79 → deepstrike-0.2.80}/crates/deepstrike-py/Cargo.toml +0 -0
  143. {deepstrike-0.2.79 → deepstrike-0.2.80}/crates/deepstrike-py/LICENSE +0 -0
  144. {deepstrike-0.2.79 → deepstrike-0.2.80}/crates/deepstrike-tokenizer/Cargo.toml +0 -0
  145. {deepstrike-0.2.79 → deepstrike-0.2.80}/crates/deepstrike-tokenizer/LICENSE +0 -0
  146. {deepstrike-0.2.79 → deepstrike-0.2.80}/crates/deepstrike-tokenizer/src/lib.rs +0 -0
  147. {deepstrike-0.2.79 → deepstrike-0.2.80}/deepstrike/agent.py +0 -0
  148. {deepstrike-0.2.79 → deepstrike-0.2.80}/deepstrike/collaboration/__init__.py +0 -0
  149. {deepstrike-0.2.79 → deepstrike-0.2.80}/deepstrike/collaboration/contract.py +0 -0
  150. {deepstrike-0.2.79 → deepstrike-0.2.80}/deepstrike/collaboration/handoff.py +0 -0
  151. {deepstrike-0.2.79 → deepstrike-0.2.80}/deepstrike/collaboration/harness.py +0 -0
  152. {deepstrike-0.2.79 → deepstrike-0.2.80}/deepstrike/collaboration/modes.py +0 -0
  153. {deepstrike-0.2.79 → deepstrike-0.2.80}/deepstrike/collaboration/pool.py +0 -0
  154. {deepstrike-0.2.79 → deepstrike-0.2.80}/deepstrike/governance.py +0 -0
  155. {deepstrike-0.2.79 → deepstrike-0.2.80}/deepstrike/harness/__init__.py +0 -0
  156. {deepstrike-0.2.79 → deepstrike-0.2.80}/deepstrike/harness/harness.py +0 -0
  157. {deepstrike-0.2.79 → deepstrike-0.2.80}/deepstrike/harness/judge.py +0 -0
  158. {deepstrike-0.2.79 → deepstrike-0.2.80}/deepstrike/kernel/__init__.py +0 -0
  159. {deepstrike-0.2.79 → deepstrike-0.2.80}/deepstrike/kernel/canonical.py +0 -0
  160. {deepstrike-0.2.79 → deepstrike-0.2.80}/deepstrike/knowledge/__init__.py +0 -0
  161. {deepstrike-0.2.79 → deepstrike-0.2.80}/deepstrike/knowledge/source.py +0 -0
  162. {deepstrike-0.2.79 → deepstrike-0.2.80}/deepstrike/memory/__init__.py +0 -0
  163. {deepstrike-0.2.79 → deepstrike-0.2.80}/deepstrike/memory/agent.py +0 -0
  164. {deepstrike-0.2.79 → deepstrike-0.2.80}/deepstrike/memory/attestation.py +0 -0
  165. {deepstrike-0.2.79 → deepstrike-0.2.80}/deepstrike/memory/authority.py +0 -0
  166. {deepstrike-0.2.79 → deepstrike-0.2.80}/deepstrike/memory/candidate_sink.py +0 -0
  167. {deepstrike-0.2.79 → deepstrike-0.2.80}/deepstrike/memory/durable.py +0 -0
  168. {deepstrike-0.2.79 → deepstrike-0.2.80}/deepstrike/memory/durable_candidate_sink.py +0 -0
  169. {deepstrike-0.2.79 → deepstrike-0.2.80}/deepstrike/memory/durable_lifecycle_store.py +0 -0
  170. {deepstrike-0.2.79 → deepstrike-0.2.80}/deepstrike/memory/in_memory_store.py +0 -0
  171. {deepstrike-0.2.79 → deepstrike-0.2.80}/deepstrike/memory/lifecycle.py +0 -0
  172. {deepstrike-0.2.79 → deepstrike-0.2.80}/deepstrike/memory/protocols.py +0 -0
  173. {deepstrike-0.2.79 → deepstrike-0.2.80}/deepstrike/memory/ranking.py +0 -0
  174. {deepstrike-0.2.79 → deepstrike-0.2.80}/deepstrike/memory/recall_projection.py +0 -0
  175. {deepstrike-0.2.79 → deepstrike-0.2.80}/deepstrike/memory/retention.py +0 -0
  176. {deepstrike-0.2.79 → deepstrike-0.2.80}/deepstrike/memory/runtime_policy.py +0 -0
  177. {deepstrike-0.2.79 → deepstrike-0.2.80}/deepstrike/memory/working.py +0 -0
  178. {deepstrike-0.2.79 → deepstrike-0.2.80}/deepstrike/memory/writer.py +0 -0
  179. {deepstrike-0.2.79 → deepstrike-0.2.80}/deepstrike/providers/__init__.py +0 -0
  180. {deepstrike-0.2.79 → deepstrike-0.2.80}/deepstrike/providers/anthropic.py +0 -0
  181. {deepstrike-0.2.79 → deepstrike-0.2.80}/deepstrike/providers/anthropic_adapter.py +0 -0
  182. {deepstrike-0.2.79 → deepstrike-0.2.80}/deepstrike/providers/anthropic_compaction.py +0 -0
  183. {deepstrike-0.2.79 → deepstrike-0.2.80}/deepstrike/providers/anthropic_compatible.py +0 -0
  184. {deepstrike-0.2.79 → deepstrike-0.2.80}/deepstrike/providers/capability_router.py +0 -0
  185. {deepstrike-0.2.79 → deepstrike-0.2.80}/deepstrike/providers/credentials.py +0 -0
  186. {deepstrike-0.2.79 → deepstrike-0.2.80}/deepstrike/providers/embedding.py +0 -0
  187. {deepstrike-0.2.79 → deepstrike-0.2.80}/deepstrike/providers/factories.py +0 -0
  188. {deepstrike-0.2.79 → deepstrike-0.2.80}/deepstrike/providers/fallback.py +0 -0
  189. {deepstrike-0.2.79 → deepstrike-0.2.80}/deepstrike/providers/gemini.py +0 -0
  190. {deepstrike-0.2.79 → deepstrike-0.2.80}/deepstrike/providers/gemini_adapter.py +0 -0
  191. {deepstrike-0.2.79 → deepstrike-0.2.80}/deepstrike/providers/model_catalog.py +0 -0
  192. {deepstrike-0.2.79 → deepstrike-0.2.80}/deepstrike/providers/model_registry.py +0 -0
  193. {deepstrike-0.2.79 → deepstrike-0.2.80}/deepstrike/providers/ollama.py +0 -0
  194. {deepstrike-0.2.79 → deepstrike-0.2.80}/deepstrike/providers/ollama_adapter.py +0 -0
  195. {deepstrike-0.2.79 → deepstrike-0.2.80}/deepstrike/providers/openai.py +0 -0
  196. {deepstrike-0.2.79 → deepstrike-0.2.80}/deepstrike/providers/openai_chat_adapter.py +0 -0
  197. {deepstrike-0.2.79 → deepstrike-0.2.80}/deepstrike/providers/openai_responses.py +0 -0
  198. {deepstrike-0.2.79 → deepstrike-0.2.80}/deepstrike/providers/prepared_request.py +0 -0
  199. {deepstrike-0.2.79 → deepstrike-0.2.80}/deepstrike/providers/protocol_adapter.py +0 -0
  200. {deepstrike-0.2.79 → deepstrike-0.2.80}/deepstrike/providers/protocols.py +0 -0
  201. {deepstrike-0.2.79 → deepstrike-0.2.80}/deepstrike/providers/provider_error.py +0 -0
  202. {deepstrike-0.2.79 → deepstrike-0.2.80}/deepstrike/providers/qwen.py +0 -0
  203. {deepstrike-0.2.79 → deepstrike-0.2.80}/deepstrike/providers/replay.py +0 -0
  204. {deepstrike-0.2.79 → deepstrike-0.2.80}/deepstrike/providers/replay_validator.py +0 -0
  205. {deepstrike-0.2.79 → deepstrike-0.2.80}/deepstrike/providers/request_plan.py +0 -0
  206. {deepstrike-0.2.79 → deepstrike-0.2.80}/deepstrike/providers/runtime_registry.py +0 -0
  207. {deepstrike-0.2.79 → deepstrike-0.2.80}/deepstrike/providers/stop_reason.py +0 -0
  208. {deepstrike-0.2.79 → deepstrike-0.2.80}/deepstrike/providers/stream.py +0 -0
  209. {deepstrike-0.2.79 → deepstrike-0.2.80}/deepstrike/providers/usage.py +0 -0
  210. {deepstrike-0.2.79 → deepstrike-0.2.80}/deepstrike/providers/vendor_profiles.py +0 -0
  211. {deepstrike-0.2.79 → deepstrike-0.2.80}/deepstrike/runtime/__init__.py +0 -0
  212. {deepstrike-0.2.79 → deepstrike-0.2.80}/deepstrike/runtime/_session_event_registry.py +0 -0
  213. {deepstrike-0.2.79 → deepstrike-0.2.80}/deepstrike/runtime/agent_declaration.py +0 -0
  214. {deepstrike-0.2.79 → deepstrike-0.2.80}/deepstrike/runtime/archive.py +0 -0
  215. {deepstrike-0.2.79 → deepstrike-0.2.80}/deepstrike/runtime/context_policy.py +0 -0
  216. {deepstrike-0.2.79 → deepstrike-0.2.80}/deepstrike/runtime/credential_vault.py +0 -0
  217. {deepstrike-0.2.79 → deepstrike-0.2.80}/deepstrike/runtime/durable_content.py +0 -0
  218. {deepstrike-0.2.79 → deepstrike-0.2.80}/deepstrike/runtime/eval.py +0 -0
  219. {deepstrike-0.2.79 → deepstrike-0.2.80}/deepstrike/runtime/eval_dataset.py +0 -0
  220. {deepstrike-0.2.79 → deepstrike-0.2.80}/deepstrike/runtime/event_stream.py +0 -0
  221. {deepstrike-0.2.79 → deepstrike-0.2.80}/deepstrike/runtime/execution_evidence.py +0 -0
  222. {deepstrike-0.2.79 → deepstrike-0.2.80}/deepstrike/runtime/execution_plane.py +0 -0
  223. {deepstrike-0.2.79 → deepstrike-0.2.80}/deepstrike/runtime/facade.py +0 -0
  224. {deepstrike-0.2.79 → deepstrike-0.2.80}/deepstrike/runtime/filtered_plane.py +0 -0
  225. {deepstrike-0.2.79 → deepstrike-0.2.80}/deepstrike/runtime/kernel_event_log.py +0 -0
  226. {deepstrike-0.2.79 → deepstrike-0.2.80}/deepstrike/runtime/kernel_journal.py +0 -0
  227. {deepstrike-0.2.79 → deepstrike-0.2.80}/deepstrike/runtime/loop_driver.py +0 -0
  228. {deepstrike-0.2.79 → deepstrike-0.2.80}/deepstrike/runtime/mcp_proxy_plane.py +0 -0
  229. {deepstrike-0.2.79 → deepstrike-0.2.80}/deepstrike/runtime/os_profile.py +0 -0
  230. {deepstrike-0.2.79 → deepstrike-0.2.80}/deepstrike/runtime/os_snapshot.py +0 -0
  231. {deepstrike-0.2.79 → deepstrike-0.2.80}/deepstrike/runtime/output_schema.py +0 -0
  232. {deepstrike-0.2.79 → deepstrike-0.2.80}/deepstrike/runtime/payload_store.py +0 -0
  233. {deepstrike-0.2.79 → deepstrike-0.2.80}/deepstrike/runtime/process_sandbox_plane.py +0 -0
  234. {deepstrike-0.2.79 → deepstrike-0.2.80}/deepstrike/runtime/provider_replay.py +0 -0
  235. {deepstrike-0.2.79 → deepstrike-0.2.80}/deepstrike/runtime/reaction_checkpoint.py +0 -0
  236. {deepstrike-0.2.79 → deepstrike-0.2.80}/deepstrike/runtime/reactive_session.py +0 -0
  237. {deepstrike-0.2.79 → deepstrike-0.2.80}/deepstrike/runtime/reliability.py +0 -0
  238. {deepstrike-0.2.79 → deepstrike-0.2.80}/deepstrike/runtime/remote_vpc_plane.py +0 -0
  239. {deepstrike-0.2.79 → deepstrike-0.2.80}/deepstrike/runtime/replay_fixture.py +0 -0
  240. {deepstrike-0.2.79 → deepstrike-0.2.80}/deepstrike/runtime/replay_provider.py +0 -0
  241. {deepstrike-0.2.79 → deepstrike-0.2.80}/deepstrike/runtime/replay_sanitize.py +0 -0
  242. {deepstrike-0.2.79 → deepstrike-0.2.80}/deepstrike/runtime/run_group.py +0 -0
  243. {deepstrike-0.2.79 → deepstrike-0.2.80}/deepstrike/runtime/session_log.py +0 -0
  244. {deepstrike-0.2.79 → deepstrike-0.2.80}/deepstrike/runtime/session_repair.py +0 -0
  245. {deepstrike-0.2.79 → deepstrike-0.2.80}/deepstrike/runtime/sub_agent_orchestrator.py +0 -0
  246. {deepstrike-0.2.79 → deepstrike-0.2.80}/deepstrike/runtime/tool_arguments.py +0 -0
  247. {deepstrike-0.2.79 → deepstrike-0.2.80}/deepstrike/runtime/turn_policy.py +0 -0
  248. {deepstrike-0.2.79 → deepstrike-0.2.80}/deepstrike/runtime/workflow_replay.py +0 -0
  249. {deepstrike-0.2.79 → deepstrike-0.2.80}/deepstrike/runtime/workflow_store.py +0 -0
  250. {deepstrike-0.2.79 → deepstrike-0.2.80}/deepstrike/runtime/worktree_plane.py +0 -0
  251. {deepstrike-0.2.79 → deepstrike-0.2.80}/deepstrike/safety/__init__.py +0 -0
  252. {deepstrike-0.2.79 → deepstrike-0.2.80}/deepstrike/safety/permissions.py +0 -0
  253. {deepstrike-0.2.79 → deepstrike-0.2.80}/deepstrike/signals/__init__.py +0 -0
  254. {deepstrike-0.2.79 → deepstrike-0.2.80}/deepstrike/signals/gateway.py +0 -0
  255. {deepstrike-0.2.79 → deepstrike-0.2.80}/deepstrike/signals/scheduled.py +0 -0
  256. {deepstrike-0.2.79 → deepstrike-0.2.80}/deepstrike/signals/types.py +0 -0
  257. {deepstrike-0.2.79 → deepstrike-0.2.80}/deepstrike/skills/__init__.py +0 -0
  258. {deepstrike-0.2.79 → deepstrike-0.2.80}/deepstrike/skills/loader.py +0 -0
  259. {deepstrike-0.2.79 → deepstrike-0.2.80}/deepstrike/skills/registry.py +0 -0
  260. {deepstrike-0.2.79 → deepstrike-0.2.80}/deepstrike/skills/watcher.py +0 -0
  261. {deepstrike-0.2.79 → deepstrike-0.2.80}/deepstrike/tools/__init__.py +0 -0
  262. {deepstrike-0.2.79 → deepstrike-0.2.80}/deepstrike/tools/builtin/__init__.py +0 -0
  263. {deepstrike-0.2.79 → deepstrike-0.2.80}/deepstrike/tools/builtin/read_file.py +0 -0
  264. {deepstrike-0.2.79 → deepstrike-0.2.80}/deepstrike/tools/errors.py +0 -0
  265. {deepstrike-0.2.79 → deepstrike-0.2.80}/deepstrike/tools/execution.py +0 -0
  266. {deepstrike-0.2.79 → deepstrike-0.2.80}/deepstrike/tools/registry.py +0 -0
  267. {deepstrike-0.2.79 → deepstrike-0.2.80}/deepstrike/types/__init__.py +0 -0
  268. {deepstrike-0.2.79 → deepstrike-0.2.80}/deepstrike/types/agent.py +0 -0
  269. {deepstrike-0.2.79 → deepstrike-0.2.80}/deepstrike/types/content_policy.py +0 -0
@@ -293,7 +293,7 @@ dependencies = [
293
293
 
294
294
  [[package]]
295
295
  name = "deepstrike-core"
296
- version = "0.2.79"
296
+ version = "0.2.80"
297
297
  dependencies = [
298
298
  "compact_str",
299
299
  "deepstrike-tokenizer",
@@ -305,9 +305,17 @@ dependencies = [
305
305
  "uuid",
306
306
  ]
307
307
 
308
+ [[package]]
309
+ name = "deepstrike-lab"
310
+ version = "0.2.80"
311
+ dependencies = [
312
+ "serde",
313
+ "serde_json",
314
+ ]
315
+
308
316
  [[package]]
309
317
  name = "deepstrike-node"
310
- version = "0.2.79"
318
+ version = "0.2.80"
311
319
  dependencies = [
312
320
  "compact_str",
313
321
  "deepstrike-core",
@@ -319,7 +327,7 @@ dependencies = [
319
327
 
320
328
  [[package]]
321
329
  name = "deepstrike-py"
322
- version = "0.2.79"
330
+ version = "0.2.80"
323
331
  dependencies = [
324
332
  "compact_str",
325
333
  "deepstrike-core",
@@ -330,7 +338,7 @@ dependencies = [
330
338
 
331
339
  [[package]]
332
340
  name = "deepstrike-sdk"
333
- version = "0.2.79"
341
+ version = "0.2.80"
334
342
  dependencies = [
335
343
  "async-stream",
336
344
  "async-trait",
@@ -368,7 +376,7 @@ dependencies = [
368
376
 
369
377
  [[package]]
370
378
  name = "deepstrike-tokenizer"
371
- version = "0.2.79"
379
+ version = "0.2.80"
372
380
  dependencies = [
373
381
  "pretty_assertions",
374
382
  "tiktoken-rs",
@@ -376,7 +384,7 @@ dependencies = [
376
384
 
377
385
  [[package]]
378
386
  name = "deepstrike-wasm"
379
- version = "0.2.79"
387
+ version = "0.2.80"
380
388
  dependencies = [
381
389
  "compact_str",
382
390
  "deepstrike-core",
@@ -3,13 +3,13 @@ resolver = "2"
3
3
  members = ["crates/deepstrike-core", "crates/deepstrike-tokenizer", "crates/deepstrike-py"]
4
4
 
5
5
  [workspace.package]
6
- version = "0.2.79"
6
+ version = "0.2.80"
7
7
  edition = "2024"
8
8
  repository = "https://github.com/kongusen/deepstrike"
9
9
 
10
10
  [workspace.dependencies]
11
- deepstrike-core = { path = "crates/deepstrike-core", version = "0.2.79" }
12
- deepstrike-tokenizer = { path = "crates/deepstrike-tokenizer", version = "0.2.79" }
11
+ deepstrike-core = { path = "crates/deepstrike-core", version = "0.2.80" }
12
+ deepstrike-tokenizer = { path = "crates/deepstrike-tokenizer", version = "0.2.80" }
13
13
  notify = "6"
14
14
  serde = { version = "1", features = ["derive"] }
15
15
  serde_json = "1"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: deepstrike
3
- Version: 0.2.79
3
+ Version: 0.2.80
4
4
  Requires-Dist: httpx>=0.27
5
5
  Requires-Dist: pyyaml>=6.0
6
6
  Requires-Dist: anyio>=4.0
@@ -80,6 +80,8 @@ pub enum ItemOrigin {
80
80
  MemoryRecall,
81
81
  /// Reference material the host seeded or pinned.
82
82
  Reference,
83
+ /// Shared state a workflow program wrote for the agents it runs (`blackboard:<key>`).
84
+ Blackboard,
83
85
  ToolResult,
84
86
  DependencyOutput,
85
87
  User,
@@ -105,6 +107,7 @@ impl ItemOrigin {
105
107
  pub fn for_host_key(key: Option<&str>) -> Self {
106
108
  match key {
107
109
  Some(key) if key.starts_with("skill:") => Self::Skill,
110
+ Some(key) if key.starts_with("blackboard:") => Self::Blackboard,
108
111
  _ => Self::Reference,
109
112
  }
110
113
  }
@@ -115,6 +118,7 @@ impl ItemOrigin {
115
118
  Self::Skill => "skill",
116
119
  Self::MemoryRecall => "memory_recall",
117
120
  Self::Reference => "reference",
121
+ Self::Blackboard => "blackboard",
118
122
  Self::ToolResult => "tool_result",
119
123
  Self::DependencyOutput => "dependency_output",
120
124
  Self::User => "user",
@@ -138,6 +142,7 @@ impl ItemOrigin {
138
142
  Self::Skill => (S::Task, F::Full, L::Until(LeaseEvent::SkillDeactivated), A::Model),
139
143
  Self::MemoryRecall => (S::Session, F::Handle, L::Turns(RECALL_LEASE_TURNS), A::Host),
140
144
  Self::Reference => (S::Operation, F::Full, L::Permanent, A::Host),
145
+ Self::Blackboard => (S::Workflow, F::Full, L::Permanent, A::Host),
141
146
  Self::ToolResult => (S::Task, F::Full, L::Permanent, A::Host),
142
147
  Self::DependencyOutput => (S::Edge, F::Handle, L::Permanent, A::Kernel),
143
148
  Self::User => (S::Operation, F::Full, L::Permanent, A::Host),
@@ -164,6 +169,9 @@ pub enum ItemScope {
164
169
  Session,
165
170
  /// The agent's identity, whatever it works on.
166
171
  Agent,
172
+ /// A workflow run: every agent it spawns reads it, whatever its context inheritance —
173
+ /// shared state the program hands its agents on purpose, not the parent's transcript.
174
+ Workflow,
167
175
  }
168
176
 
169
177
  impl ItemScope {
@@ -180,6 +188,7 @@ impl ItemScope {
180
188
  pub fn inherited_by(self, inheritance: crate::types::agent::ContextInheritance) -> bool {
181
189
  use crate::types::agent::ContextInheritance as I;
182
190
  match (self, inheritance) {
191
+ (Self::Workflow, _) => true,
183
192
  (Self::Edge, _) | (_, I::None) => false,
184
193
  (Self::Agent, I::SystemOnly) => true,
185
194
  (_, I::SystemOnly) => false,
@@ -350,9 +359,16 @@ pub struct ItemValue {
350
359
  /// Turn the item arrived (or was last renewed by a fresh recall or upsert).
351
360
  #[serde(default)]
352
361
  pub injected_turn: u32,
353
- /// Committed history messages that referenced it.
362
+ /// Committed history messages that referenced it, by any evidence.
354
363
  #[serde(default)]
355
364
  pub ref_count: u64,
365
+ /// Plan task 4.2 · references by strong evidence: the model asked for the item
366
+ /// (`memory(record_id)`), passed its key or record id in a tool call, or named its key.
367
+ #[serde(default, skip_serializing_if = "is_zero_u64")]
368
+ pub strong_refs: u64,
369
+ /// References by lexical overlap only: the conversation shares the item's distinctive terms.
370
+ #[serde(default, skip_serializing_if = "is_zero_u64")]
371
+ pub lexical_refs: u64,
356
372
  /// Reference step (history position) of the last reference; the retention score's recency.
357
373
  #[serde(default, skip_serializing_if = "Option::is_none")]
358
374
  pub last_referenced_step: Option<u64>,
@@ -501,6 +517,10 @@ mod tests {
501
517
  assert!(scope.survives_renewal(), "{scope:?}");
502
518
  }
503
519
  assert!(!ItemScope::Edge.inherited_by(I::Full));
520
+ for inheritance in [I::None, I::SystemOnly, I::Full] {
521
+ assert!(ItemScope::Workflow.inherited_by(inheritance));
522
+ }
523
+ assert_eq!(ItemOrigin::for_host_key(Some("blackboard:plan")), ItemOrigin::Blackboard);
504
524
  assert!(!ItemScope::Edge.survives_renewal());
505
525
  }
506
526
 
@@ -76,6 +76,9 @@ pub(crate) fn is_exposure_exempt_meta_tool(name: &str) -> bool {
76
76
  EXPOSURE_EXEMPT_META_TOOLS.contains(&name)
77
77
  }
78
78
 
79
+ /// How many recent (estimate, provider count) pairs the calibration is fitted on.
80
+ pub const ESTIMATE_CALIBRATION_SAMPLES: usize = 8;
81
+
79
82
  /// End-of-run context lifecycle metrics (plan task 4.1).
80
83
  #[derive(Debug, Clone, Default, PartialEq, Eq)]
81
84
  pub struct LifecycleMetrics {
@@ -132,6 +135,14 @@ pub struct ContextManager {
132
135
  pub knowledge_enabled: bool,
133
136
  pub plan_tool_enabled: bool,
134
137
  last_observed_prompt_tokens: Option<u32>,
138
+ /// Plan task 5.1 · the uncalibrated estimate of the last provider request, and the factor (in
139
+ /// parts per million) that brings an estimate to what the provider counted. Both move only on
140
+ /// recorded inputs (the provider's observed count), so replay reproduces them.
141
+ pub(crate) last_request_estimate: u32,
142
+ /// The last few (uncalibrated estimate, provider count) pairs. A provider's count differs
143
+ /// from the kernel's by a roughly fixed overhead (message framing, tool templates) plus a
144
+ /// proportional tokenizer gap, so the calibration is the least-squares line through them.
145
+ pub(crate) estimate_samples: std::collections::VecDeque<(u32, u32)>,
135
146
  compression: CompressionPipeline,
136
147
  pressure: PressureMonitor,
137
148
  renewal: RenewalPolicy,
@@ -191,6 +202,16 @@ pub struct ContextManager {
191
202
  pub(crate) retired_history: std::collections::VecDeque<HistoryItemRecord>,
192
203
  /// Retired history items dropped from `retired_history` by the cap.
193
204
  pub(crate) retired_history_omitted: u32,
205
+ /// Messages that arrived while the history tail still waited for tool results (a memory hit
206
+ /// resolving before a sibling tool in the same batch). A provider requires a call's results to
207
+ /// follow it directly, so these wait until the last result lands.
208
+ pub(crate) held_history: Vec<(CoreMessage, u32)>,
209
+ /// Plan task 1.1c · provider replay state kept with assistant history items, by item id.
210
+ /// Each with the tokens it adds to a request: replay is sent back with its turn, so it
211
+ /// occupies the model's context like the turn's own text.
212
+ pub(crate) item_replays: std::collections::BTreeMap<ItemId, (serde_json::Value, u32)>,
213
+ /// Replay for the assistant message being admitted now (set around one provider completion).
214
+ pub(crate) pending_assistant_replay: Option<serde_json::Value>,
194
215
  }
195
216
 
196
217
  impl ContextManager {
@@ -225,6 +246,8 @@ impl ContextManager {
225
246
  knowledge_enabled: false,
226
247
  plan_tool_enabled: false,
227
248
  last_observed_prompt_tokens: None,
249
+ last_request_estimate: 0,
250
+ estimate_samples: std::collections::VecDeque::new(),
228
251
  compression,
229
252
  pressure,
230
253
  renewal,
@@ -245,6 +268,9 @@ impl ContextManager {
245
268
  history_tally: std::collections::BTreeMap::new(),
246
269
  retired_history: std::collections::VecDeque::new(),
247
270
  retired_history_omitted: 0,
271
+ held_history: Vec::new(),
272
+ item_replays: std::collections::BTreeMap::new(),
273
+ pending_assistant_replay: None,
248
274
  }
249
275
  }
250
276
 
@@ -488,11 +514,65 @@ impl ContextManager {
488
514
  );
489
515
  // A provider sees a selected projection, not the entire resident history. Its smaller
490
516
  // count must not suppress compaction while the unselected history still triggers renewal.
491
- observed.max(self.pressure.pressure(&self.partitions, &self.engine, None))
517
+ // Calibration may raise the estimate (the provider counts more than the kernel does, as
518
+ // for CJK text or tool templates) but never lowers it: a provider or proxy reporting too
519
+ // little must not delay compaction past the point the kernel's own count calls for.
520
+ let max_tokens = f64::from(self.max_tokens.max(1));
521
+ let raw = self
522
+ .partitions
523
+ .total_tokens(&self.engine)
524
+ .saturating_add(self.replay_tokens());
525
+ let estimated = if self.max_tokens == 0 {
526
+ 0.0
527
+ } else {
528
+ f64::from(self.calibrated(raw).max(raw)) / max_tokens
529
+ };
530
+ observed.max(estimated)
492
531
  }
493
532
 
494
533
  pub fn set_observed_prompt_tokens(&mut self, tokens: u32) {
495
534
  self.last_observed_prompt_tokens = Some(tokens);
535
+ if self.last_request_estimate > 0 {
536
+ if self.estimate_samples.len() == ESTIMATE_CALIBRATION_SAMPLES {
537
+ self.estimate_samples.pop_front();
538
+ }
539
+ self.estimate_samples.push_back((self.last_request_estimate, tokens));
540
+ self.last_request_estimate = 0;
541
+ }
542
+ }
543
+
544
+ /// Remember `raw`, the uncalibrated estimate of the request about to be sent, and return it
545
+ /// calibrated.
546
+ pub fn note_request_estimate(&mut self, raw: u32) -> u32 {
547
+ self.last_request_estimate = raw;
548
+ self.calibrated(raw)
549
+ }
550
+
551
+ /// `tokens` (an uncalibrated estimate) as the provider would count it: through the
552
+ /// least-squares line of the recent samples; with one sample (or samples of one size) by
553
+ /// their mean offset, the gap being mostly fixed overhead; unchanged with none. Integer arithmetic, so replay reproduces
554
+ /// it; bounded to 1/2..4x of the estimate.
555
+ fn calibrated(&self, tokens: u32) -> u32 {
556
+ let n = self.estimate_samples.len() as i128;
557
+ if n == 0 || tokens == 0 {
558
+ return tokens;
559
+ }
560
+ let (mut sx, mut sy, mut sxx, mut sxy) = (0i128, 0i128, 0i128, 0i128);
561
+ for &(x, y) in &self.estimate_samples {
562
+ let (x, y) = (i128::from(x), i128::from(y));
563
+ sx += x;
564
+ sy += y;
565
+ sxx += x * x;
566
+ sxy += x * y;
567
+ }
568
+ let x = i128::from(tokens);
569
+ let denominator = n * sxx - sx * sx;
570
+ let fitted = if n >= 2 && denominator > 0 {
571
+ (sy * sxx - sx * sxy + x * (n * sxy - sx * sy)) / denominator
572
+ } else {
573
+ x + (sy - sx) / n
574
+ };
575
+ fitted.clamp(x / 2, x * 4).clamp(0, i128::from(u32::MAX)) as u32
496
576
  }
497
577
 
498
578
  pub fn should_compress(&self) -> PressureAction {
@@ -587,6 +667,7 @@ impl ContextManager {
587
667
  // Archived messages have left history — drop their now-orphaned handles (bounds the table).
588
668
  if !archived.is_empty() {
589
669
  self.prune_orphaned_handles();
670
+ self.prune_item_replays();
590
671
  // Compaction rewrote the history prefix — start a fresh collapse generation so
591
672
  // surviving handles re-evaluate from Resident (P0-C: the one cache-free un-collapse point).
592
673
  self.reset_collapse_generation();
@@ -650,6 +731,7 @@ impl ContextManager {
650
731
  // History was rebuilt wholesale — drop handles anchored to messages it no longer carries,
651
732
  // and start a fresh collapse generation (P0-C) since the whole prefix changed.
652
733
  self.prune_orphaned_handles();
734
+ self.prune_item_replays();
653
735
  self.reset_collapse_generation();
654
736
  // K1: renewal is a boundary — apply deferred knowledge upserts/removals now.
655
737
  self.sweep_knowledge_at_boundary();
@@ -669,7 +751,7 @@ impl ContextManager {
669
751
  }
670
752
 
671
753
  pub fn render(&self) -> InternalRenderedContext {
672
- super::renderer::render_projected(
754
+ let mut rendered = super::renderer::render_projected(
673
755
  &self.partitions,
674
756
  self.available_input_tokens(),
675
757
  &self.engine,
@@ -677,12 +759,174 @@ impl ContextManager {
677
759
  &self.handles,
678
760
  self.frozen_history_len,
679
761
  self.config.collapse_assistant_narration,
680
- )
762
+ );
763
+ if !self.item_replays.is_empty() {
764
+ let replay_tokens: u32 = rendered
765
+ .turn_items
766
+ .iter()
767
+ .filter_map(|id| self.item_replays.get(id).map(|(_, tokens)| *tokens))
768
+ .sum();
769
+ rendered.estimated_tokens = rendered.estimated_tokens.saturating_add(replay_tokens);
770
+ rendered.turn_replays = rendered
771
+ .turn_items
772
+ .iter()
773
+ .map(|id| self.item_replays.get(id).map(|(replay, _)| replay.clone()))
774
+ .collect();
775
+ }
776
+ rendered
681
777
  }
682
778
 
683
779
  // ── History / Knowledge ───────────────────────────────────────────────────
684
780
 
781
+ /// Plan task 5.1 · the provider summarized history through item `through` server-side. The
782
+ /// covered items leave as compacted (extended to the end of a tool transaction, never split),
783
+ /// and one `provider_summary` item heads history in their place, rendering `replay` (the
784
+ /// provider's block) — so pressure, renewal and the next render see what the model sees.
785
+ /// Returns whether `through` named a history item.
786
+ pub fn absorb_provider_compaction(
787
+ &mut self,
788
+ through: ItemId,
789
+ replay: serde_json::Value,
790
+ summary_tokens: u32,
791
+ ) -> bool {
792
+ let history = &self.partitions.history;
793
+ let Some(position) = history.tags().iter().position(|tag| tag.id == through) else {
794
+ return false;
795
+ };
796
+ let end = super::units::unit_boundaries(history.messages())
797
+ .into_iter()
798
+ .find(|unit| unit.contains(&position))
799
+ .map_or(position + 1, |unit| unit.end);
800
+ let covered_tokens: u32 = (0..end)
801
+ .map(|index| history.measured_tokens(index, &self.engine))
802
+ .sum();
803
+ let retained = history.token_count().saturating_sub(covered_tokens);
804
+ let covered: std::collections::BTreeSet<usize> = (0..end).collect();
805
+ let rows = self.partitions.history.take_rows(&covered, retained);
806
+ for row in &rows {
807
+ let record = HistoryItemRecord::of(
808
+ row.tag,
809
+ row.measurement.tokens,
810
+ row.tag.fidelity,
811
+ Some(ItemEnd::Compacted),
812
+ );
813
+ self.retire_history_item(record);
814
+ }
815
+ self.last_item_id += 1;
816
+ let tag = ItemTag::new(
817
+ self.last_item_id,
818
+ ItemOrigin::ProviderSummary,
819
+ self.partitions.knowledge.turn,
820
+ );
821
+ let message = CoreMessage::assistant("[earlier conversation summarized by the provider]");
822
+ let tally = self.tally(ItemOrigin::ProviderSummary);
823
+ tally.items += 1;
824
+ tally.tokens += u64::from(summary_tokens);
825
+ self.partitions.history.prepend_row(super::partitions::PartitionRow {
826
+ tag,
827
+ measurement: super::measurement::TokenMeasurement::for_message(&message, summary_tokens),
828
+ message,
829
+ });
830
+ self.keep_item_replay(tag.id, replay);
831
+ self.prune_orphaned_handles();
832
+ self.prune_item_replays();
833
+ self.reset_collapse_generation();
834
+ self.sweep_knowledge_at_boundary();
835
+ self.frozen_history_len = self.partitions.history.len();
836
+ true
837
+ }
838
+
839
+ /// Plan task 5.1 · the provider cleared these tool results server-side: render them as
840
+ /// handles, as the model now sees them.
841
+ pub fn absorb_cleared_tool_results<'a>(&mut self, call_ids: impl IntoIterator<Item = &'a str>) {
842
+ let cleared: std::collections::HashSet<&str> = call_ids.into_iter().collect();
843
+ for handle in self.handles.tool_result_handles_mut() {
844
+ if handle.source.as_deref().is_some_and(|source| cleared.contains(source))
845
+ && matches!(handle.residency, Residency::Resident)
846
+ {
847
+ handle.residency = Residency::Collapsed;
848
+ }
849
+ }
850
+ }
851
+
852
+ /// Keep `replay` with item `id`, counting what it adds to a request.
853
+ pub(crate) fn keep_item_replay(&mut self, id: ItemId, replay: serde_json::Value) {
854
+ let tokens = self.engine.count(&replay.to_string());
855
+ self.item_replays.insert(id, (replay, tokens));
856
+ }
857
+
858
+ /// Tokens the replay of every item still in history adds to a request.
859
+ fn replay_tokens(&self) -> u32 {
860
+ self.item_replays.values().map(|(_, tokens)| *tokens).sum()
861
+ }
862
+
863
+ /// Drop replay state whose item left history.
864
+ fn prune_item_replays(&mut self) {
865
+ if self.item_replays.is_empty() {
866
+ return;
867
+ }
868
+ let live: std::collections::HashSet<ItemId> =
869
+ self.partitions.history.tags().iter().map(|tag| tag.id).collect();
870
+ self.item_replays.retain(|id, _| live.contains(id));
871
+ }
872
+
873
+ /// Append `msg` to history after the tool results the last assistant turn still waits for.
874
+ /// Used for content an effect delivers mid-batch (a memory hit that resolves before a sibling
875
+ /// tool): placed now, it would split the batch's results, which a provider rejects.
876
+ pub fn push_history_after_tool_results(&mut self, msg: CoreMessage, tokens: u32) {
877
+ if self.awaits_tool_results() {
878
+ self.held_history.push((msg, tokens));
879
+ } else {
880
+ self.push_history(msg, tokens);
881
+ }
882
+ }
883
+
884
+ /// Append whatever is still held, whether or not the batch completed. Called before a provider
885
+ /// call, so held content is never lost to a batch whose results never all arrived.
886
+ pub fn release_held_history(&mut self) {
887
+ for (held, tokens) in std::mem::take(&mut self.held_history) {
888
+ self.admit_history(held, tokens);
889
+ }
890
+ }
891
+
685
892
  pub fn push_history(&mut self, msg: CoreMessage, tokens: u32) {
893
+ let is_tool = msg.role == crate::types::message::Role::Tool;
894
+ self.admit_history(msg, tokens);
895
+ if is_tool && !self.held_history.is_empty() && !self.awaits_tool_results() {
896
+ for (held, tokens) in std::mem::take(&mut self.held_history) {
897
+ self.admit_history(held, tokens);
898
+ }
899
+ }
900
+ }
901
+
902
+ /// Whether the last assistant message in history asked for a call whose result is not in
903
+ /// history yet.
904
+ fn awaits_tool_results(&self) -> bool {
905
+ let mut answered = std::collections::HashSet::new();
906
+ for message in self.partitions.history.messages().iter().rev() {
907
+ match message.role {
908
+ crate::types::message::Role::Tool => {
909
+ if let Content::Parts(parts) = &message.content {
910
+ for part in parts {
911
+ if let ContentPart::ToolResult { call_id, .. } = part {
912
+ answered.insert(call_id.as_str());
913
+ }
914
+ }
915
+ }
916
+ }
917
+ crate::types::message::Role::Assistant => {
918
+ return message
919
+ .tool_calls
920
+ .iter()
921
+ .any(|call| !answered.contains(call.id.as_str()));
922
+ }
923
+ _ => return false,
924
+ }
925
+ }
926
+ false
927
+ }
928
+
929
+ fn admit_history(&mut self, msg: CoreMessage, tokens: u32) {
686
930
  self.knowledge_reference_step = self.knowledge_reference_step.saturating_add(1);
687
931
  self.partitions
688
932
  .knowledge
@@ -715,11 +959,18 @@ impl ContextManager {
715
959
  let tally = self.tally(tag.origin);
716
960
  tally.items += 1;
717
961
  tally.tokens += u64::from(tokens);
962
+ if tag.origin == ItemOrigin::Assistant {
963
+ if let Some(replay) = self.pending_assistant_replay.take() {
964
+ self.keep_item_replay(tag.id, replay);
965
+ }
966
+ }
718
967
  self.partitions.history.push_tagged(msg, tokens, tag);
719
968
  }
720
969
 
721
970
  /// Drop history from `len` on (a rolled-back turn); its items leave as removed.
722
971
  pub fn truncate_history(&mut self, len: usize) {
972
+ // Held messages belong to the turn being rolled back.
973
+ self.held_history.clear();
723
974
  for index in len..self.partitions.history.len() {
724
975
  let tag = self.partitions.history.tag(index);
725
976
  let tokens = self.partitions.history.measured_tokens(index, &self.engine);
@@ -732,6 +983,7 @@ impl ContextManager {
732
983
  ));
733
984
  }
734
985
  self.partitions.history.truncate(len);
986
+ self.prune_item_replays();
735
987
  }
736
988
 
737
989
  fn retire_history_item(&mut self, record: HistoryItemRecord) {
@@ -1754,6 +2006,102 @@ mod tests {
1754
2006
  assert_eq!(metrics.history_items.last().unwrap().id, (HISTORY_ITEM_DETAIL_CAP + 10) as u64);
1755
2007
  }
1756
2008
 
2009
+ #[test]
2010
+ fn the_estimate_calibrates_toward_what_the_provider_counts() {
2011
+ let mut mgr = ContextManager::new(100_000);
2012
+ assert_eq!(mgr.note_request_estimate(600), 600, "uncalibrated before any count");
2013
+ mgr.set_observed_prompt_tokens(810);
2014
+ assert_eq!(mgr.note_request_estimate(1_200), 1_410, "one sample: its offset");
2015
+ mgr.set_observed_prompt_tokens(1_470);
2016
+ // A fixed overhead plus a proportional gap (count = 1.1 x estimate + 150) is fitted
2017
+ // exactly once there are two sizes.
2018
+ for raw in [2_000u32, 2_800] {
2019
+ mgr.note_request_estimate(raw);
2020
+ mgr.set_observed_prompt_tokens(raw * 11 / 10 + 150);
2021
+ }
2022
+ assert_eq!(mgr.note_request_estimate(3_600), 4_110);
2023
+ // An observation with no estimate pending (a restore, a test) adds no sample.
2024
+ let samples = mgr.estimate_samples.len();
2025
+ mgr.last_request_estimate = 0;
2026
+ mgr.set_observed_prompt_tokens(50);
2027
+ assert_eq!(mgr.estimate_samples.len(), samples);
2028
+ // Only the most recent samples count.
2029
+ for _ in 0..ESTIMATE_CALIBRATION_SAMPLES {
2030
+ mgr.note_request_estimate(1_000);
2031
+ mgr.set_observed_prompt_tokens(1_000);
2032
+ }
2033
+ assert_eq!(mgr.note_request_estimate(5_000), 5_000);
2034
+ }
2035
+
2036
+ #[test]
2037
+ fn replay_sent_back_with_a_turn_counts_toward_the_estimate() {
2038
+ let mut mgr = ContextManager::new(100_000);
2039
+ mgr.push_history(CoreMessage::user("question"), 5);
2040
+ let before = (mgr.render().estimated_tokens, mgr.rho());
2041
+ mgr.pending_assistant_replay =
2042
+ Some(serde_json::json!({ "reasoning_content": "step ".repeat(400) }));
2043
+ mgr.push_history(CoreMessage::assistant("answer"), 5);
2044
+ let (estimate, rho) = (mgr.render().estimated_tokens, mgr.rho());
2045
+ assert!(estimate >= before.0 + 5 + 300, "{estimate} vs {}", before.0);
2046
+ assert!(rho > before.1);
2047
+ }
2048
+
2049
+ #[test]
2050
+ fn calibration_raises_pressure_but_never_lowers_it() {
2051
+ let mut mgr = ContextManager::new(1_000);
2052
+ mgr.push_history(CoreMessage::user("x".repeat(400)), 400);
2053
+ let raw = mgr.pressure.pressure(&mgr.partitions, &mgr.engine, None);
2054
+ mgr.estimate_samples = [(1_000, 500)].into();
2055
+ assert!((mgr.rho() - raw).abs() < 1e-9, "a low count does not delay compaction");
2056
+ mgr.estimate_samples = [(1_000, 1_200)].into();
2057
+ assert!((mgr.rho() - (raw + 0.2)).abs() < 1e-3, "an undercount raises pressure");
2058
+ }
2059
+
2060
+ #[test]
2061
+ fn a_provider_summary_replaces_the_items_it_covered() {
2062
+ use crate::types::message::ToolCall;
2063
+ let mut mgr = ContextManager::new(100_000);
2064
+ mgr.push_history(CoreMessage::user("question"), 50);
2065
+ let mut call = CoreMessage::assistant("reading");
2066
+ call.tool_calls = vec![ToolCall {
2067
+ id: "c1".into(),
2068
+ name: "read".into(),
2069
+ arguments: serde_json::json!({}),
2070
+ }];
2071
+ mgr.push_history(call, 20);
2072
+ mgr.push_history(tool_result_msg("c1", &"body ".repeat(200)), 400);
2073
+ mgr.push_history(CoreMessage::user("next question"), 10);
2074
+ let (assistant, tool) = (mgr.partitions.history.tag(1).id, mgr.partitions.history.tag(2).id);
2075
+
2076
+ let block = serde_json::json!({ "protocol": "anthropic-messages", "native_blocks": [{ "type": "compaction" }] });
2077
+ // Covering through the call extends to its result: a transaction is never split.
2078
+ assert!(mgr.absorb_provider_compaction(assistant, block.clone(), 30));
2079
+ let tags = mgr.partitions.history.tags();
2080
+ assert_eq!(tags[0].origin, ItemOrigin::ProviderSummary);
2081
+ assert_eq!(tags.len(), 2, "summary + the uncovered question");
2082
+ assert!(tags.iter().all(|tag| tag.id != tool));
2083
+ assert_eq!(mgr.partitions.history.token_count(), 30 + 10);
2084
+ assert!(mgr.handles.residency_for_source("c1").is_none(), "the covered result's handle left");
2085
+
2086
+ let rendered = mgr.render();
2087
+ let summary = rendered.turn_items.iter().position(|id| *id == tags[0].id).unwrap();
2088
+ assert_eq!(rendered.turn_replays[summary], Some(block));
2089
+ let ends: Vec<_> = mgr.lifecycle_metrics().history_items.iter().map(|item| item.end).collect();
2090
+ assert_eq!(ends.iter().filter(|end| **end == Some(ItemEnd::Compacted)).count(), 3);
2091
+ assert!(!mgr.absorb_provider_compaction(9_999, serde_json::json!({}), 1), "unknown item");
2092
+ }
2093
+
2094
+ #[test]
2095
+ fn tool_results_the_provider_cleared_render_as_handles() {
2096
+ let mut mgr = ContextManager::new(100_000);
2097
+ mgr.push_history(tool_result_msg("c1", "first"), 5);
2098
+ mgr.push_history(tool_result_msg("c2", "second"), 5);
2099
+ mgr.absorb_cleared_tool_results(["c1"]);
2100
+ assert_eq!(mgr.handles.residency_for_source("c1"), Some(&Residency::Collapsed));
2101
+ assert_eq!(mgr.handles.residency_for_source("c2"), Some(&Residency::Resident));
2102
+ assert_eq!(mgr.history_fidelity(0), crate::context::item::Fidelity::Handle);
2103
+ }
2104
+
1757
2105
  #[test]
1758
2106
  fn history_messages_are_items_whose_identity_survives_renewal() {
1759
2107
  let mut mgr = ContextManager::new(100_000);