deepstrike 0.2.75__tar.gz → 0.2.77__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 (268) hide show
  1. {deepstrike-0.2.75 → deepstrike-0.2.77}/Cargo.lock +6 -6
  2. {deepstrike-0.2.75 → deepstrike-0.2.77}/Cargo.toml +3 -3
  3. {deepstrike-0.2.75 → deepstrike-0.2.77}/PKG-INFO +1 -1
  4. {deepstrike-0.2.75 → deepstrike-0.2.77}/crates/deepstrike-core/src/context/manager.rs +24 -2
  5. {deepstrike-0.2.75 → deepstrike-0.2.77}/crates/deepstrike-core/src/context/renewal.rs +46 -25
  6. {deepstrike-0.2.75 → deepstrike-0.2.77}/crates/deepstrike-core/src/context/token_engine.rs +72 -5
  7. {deepstrike-0.2.75 → deepstrike-0.2.77}/crates/deepstrike-core/src/runtime/kernel/wire/driver/events.rs +1 -1
  8. {deepstrike-0.2.75 → deepstrike-0.2.77}/crates/deepstrike-core/src/runtime/kernel/wire/driver/provider.rs +3 -1
  9. {deepstrike-0.2.75 → deepstrike-0.2.77}/crates/deepstrike-core/src/runtime/kernel/wire/driver/syscall.rs +44 -3
  10. {deepstrike-0.2.75 → deepstrike-0.2.77}/crates/deepstrike-core/src/runtime/kernel/wire/driver/tests.rs +109 -0
  11. {deepstrike-0.2.75 → deepstrike-0.2.77}/crates/deepstrike-core/src/runtime/kernel/wire/driver.rs +25 -0
  12. {deepstrike-0.2.75 → deepstrike-0.2.77}/crates/deepstrike-core/src/scheduler/state_machine/mod.rs +19 -0
  13. {deepstrike-0.2.75 → deepstrike-0.2.77}/crates/deepstrike-core/src/scheduler/state_machine/tests.rs +29 -0
  14. {deepstrike-0.2.75 → deepstrike-0.2.77}/pyproject.toml +1 -1
  15. {deepstrike-0.2.75 → deepstrike-0.2.77}/LICENSE +0 -0
  16. {deepstrike-0.2.75 → deepstrike-0.2.77}/README.md +0 -0
  17. {deepstrike-0.2.75 → deepstrike-0.2.77}/crates/deepstrike-core/Cargo.toml +0 -0
  18. {deepstrike-0.2.75 → deepstrike-0.2.77}/crates/deepstrike-core/LICENSE +0 -0
  19. {deepstrike-0.2.75 → deepstrike-0.2.77}/crates/deepstrike-core/benches/kernel_baseline.rs +0 -0
  20. {deepstrike-0.2.75 → deepstrike-0.2.77}/crates/deepstrike-core/benches/verifiable_baseline.rs +0 -0
  21. {deepstrike-0.2.75 → deepstrike-0.2.77}/crates/deepstrike-core/benches/wait_index_baseline.rs +0 -0
  22. {deepstrike-0.2.75 → deepstrike-0.2.77}/crates/deepstrike-core/src/benchmark/mod.rs +0 -0
  23. {deepstrike-0.2.75 → deepstrike-0.2.77}/crates/deepstrike-core/src/bin/deepstrike.rs +0 -0
  24. {deepstrike-0.2.75 → deepstrike-0.2.77}/crates/deepstrike-core/src/bin/support/evidence_io.rs +0 -0
  25. {deepstrike-0.2.75 → deepstrike-0.2.77}/crates/deepstrike-core/src/context/compression.rs +0 -0
  26. {deepstrike-0.2.75 → deepstrike-0.2.77}/crates/deepstrike-core/src/context/config.rs +0 -0
  27. {deepstrike-0.2.75 → deepstrike-0.2.77}/crates/deepstrike-core/src/context/execution.rs +0 -0
  28. {deepstrike-0.2.75 → deepstrike-0.2.77}/crates/deepstrike-core/src/context/fault.rs +0 -0
  29. {deepstrike-0.2.75 → deepstrike-0.2.77}/crates/deepstrike-core/src/context/measurement.rs +0 -0
  30. {deepstrike-0.2.75 → deepstrike-0.2.77}/crates/deepstrike-core/src/context/mod.rs +0 -0
  31. {deepstrike-0.2.75 → deepstrike-0.2.77}/crates/deepstrike-core/src/context/partitions.rs +0 -0
  32. {deepstrike-0.2.75 → deepstrike-0.2.77}/crates/deepstrike-core/src/context/policy.rs +0 -0
  33. {deepstrike-0.2.75 → deepstrike-0.2.77}/crates/deepstrike-core/src/context/pressure.rs +0 -0
  34. {deepstrike-0.2.75 → deepstrike-0.2.77}/crates/deepstrike-core/src/context/renderer.rs +0 -0
  35. {deepstrike-0.2.75 → deepstrike-0.2.77}/crates/deepstrike-core/src/context/skill_catalog.rs +0 -0
  36. {deepstrike-0.2.75 → deepstrike-0.2.77}/crates/deepstrike-core/src/context/summarizer.rs +0 -0
  37. {deepstrike-0.2.75 → deepstrike-0.2.77}/crates/deepstrike-core/src/context/task_state.rs +0 -0
  38. {deepstrike-0.2.75 → deepstrike-0.2.77}/crates/deepstrike-core/src/context/text.rs +0 -0
  39. {deepstrike-0.2.75 → deepstrike-0.2.77}/crates/deepstrike-core/src/context/units.rs +0 -0
  40. {deepstrike-0.2.75 → deepstrike-0.2.77}/crates/deepstrike-core/src/context/utility.rs +0 -0
  41. {deepstrike-0.2.75 → deepstrike-0.2.77}/crates/deepstrike-core/src/evolution.rs +0 -0
  42. {deepstrike-0.2.75 → deepstrike-0.2.77}/crates/deepstrike-core/src/governance/constraint.rs +0 -0
  43. {deepstrike-0.2.75 → deepstrike-0.2.77}/crates/deepstrike-core/src/governance/mod.rs +0 -0
  44. {deepstrike-0.2.75 → deepstrike-0.2.77}/crates/deepstrike-core/src/governance/permission.rs +0 -0
  45. {deepstrike-0.2.75 → deepstrike-0.2.77}/crates/deepstrike-core/src/governance/pipeline.rs +0 -0
  46. {deepstrike-0.2.75 → deepstrike-0.2.77}/crates/deepstrike-core/src/governance/quota.rs +0 -0
  47. {deepstrike-0.2.75 → deepstrike-0.2.77}/crates/deepstrike-core/src/governance/rate_limit.rs +0 -0
  48. {deepstrike-0.2.75 → deepstrike-0.2.77}/crates/deepstrike-core/src/governance/repeat_fuse.rs +0 -0
  49. {deepstrike-0.2.75 → deepstrike-0.2.77}/crates/deepstrike-core/src/governance/veto.rs +0 -0
  50. {deepstrike-0.2.75 → deepstrike-0.2.77}/crates/deepstrike-core/src/harness/eval.rs +0 -0
  51. {deepstrike-0.2.75 → deepstrike-0.2.77}/crates/deepstrike-core/src/harness/mod.rs +0 -0
  52. {deepstrike-0.2.75 → deepstrike-0.2.77}/crates/deepstrike-core/src/lexical.rs +0 -0
  53. {deepstrike-0.2.75 → deepstrike-0.2.77}/crates/deepstrike-core/src/lib.rs +0 -0
  54. {deepstrike-0.2.75 → deepstrike-0.2.77}/crates/deepstrike-core/src/memory/curator.rs +0 -0
  55. {deepstrike-0.2.75 → deepstrike-0.2.77}/crates/deepstrike-core/src/memory/durable.rs +0 -0
  56. {deepstrike-0.2.75 → deepstrike-0.2.77}/crates/deepstrike-core/src/memory/mod.rs +0 -0
  57. {deepstrike-0.2.75 → deepstrike-0.2.77}/crates/deepstrike-core/src/mm/handle.rs +0 -0
  58. {deepstrike-0.2.75 → deepstrike-0.2.77}/crates/deepstrike-core/src/mm/memory.rs +0 -0
  59. {deepstrike-0.2.75 → deepstrike-0.2.77}/crates/deepstrike-core/src/mm/mod.rs +0 -0
  60. {deepstrike-0.2.75 → deepstrike-0.2.77}/crates/deepstrike-core/src/mm/value.rs +0 -0
  61. {deepstrike-0.2.75 → deepstrike-0.2.77}/crates/deepstrike-core/src/orchestration/mod.rs +0 -0
  62. {deepstrike-0.2.75 → deepstrike-0.2.77}/crates/deepstrike-core/src/orchestration/task_graph.rs +0 -0
  63. {deepstrike-0.2.75 → deepstrike-0.2.77}/crates/deepstrike-core/src/orchestration/tournament.rs +0 -0
  64. {deepstrike-0.2.75 → deepstrike-0.2.77}/crates/deepstrike-core/src/orchestration/workflow/mod.rs +0 -0
  65. {deepstrike-0.2.75 → deepstrike-0.2.77}/crates/deepstrike-core/src/orchestration/workflow/run.rs +0 -0
  66. {deepstrike-0.2.75 → deepstrike-0.2.77}/crates/deepstrike-core/src/proc/mod.rs +0 -0
  67. {deepstrike-0.2.75 → deepstrike-0.2.77}/crates/deepstrike-core/src/projection_pairs.rs +0 -0
  68. {deepstrike-0.2.75 → deepstrike-0.2.77}/crates/deepstrike-core/src/runtime/chain_validator/mod.rs +0 -0
  69. {deepstrike-0.2.75 → deepstrike-0.2.77}/crates/deepstrike-core/src/runtime/event_log.rs +0 -0
  70. {deepstrike-0.2.75 → deepstrike-0.2.77}/crates/deepstrike-core/src/runtime/kernel/observation.rs +0 -0
  71. {deepstrike-0.2.75 → deepstrike-0.2.77}/crates/deepstrike-core/src/runtime/kernel/wire/binding.rs +0 -0
  72. {deepstrike-0.2.75 → deepstrike-0.2.77}/crates/deepstrike-core/src/runtime/kernel/wire/checkpoint.rs +0 -0
  73. {deepstrike-0.2.75 → deepstrike-0.2.77}/crates/deepstrike-core/src/runtime/kernel/wire/command.rs +0 -0
  74. {deepstrike-0.2.75 → deepstrike-0.2.77}/crates/deepstrike-core/src/runtime/kernel/wire/config.rs +0 -0
  75. {deepstrike-0.2.75 → deepstrike-0.2.77}/crates/deepstrike-core/src/runtime/kernel/wire/crash_point.rs +0 -0
  76. {deepstrike-0.2.75 → deepstrike-0.2.77}/crates/deepstrike-core/src/runtime/kernel/wire/driver/continuation.rs +0 -0
  77. {deepstrike-0.2.75 → deepstrike-0.2.77}/crates/deepstrike-core/src/runtime/kernel/wire/driver/effects.rs +0 -0
  78. {deepstrike-0.2.75 → deepstrike-0.2.77}/crates/deepstrike-core/src/runtime/kernel/wire/driver/planning.rs +0 -0
  79. {deepstrike-0.2.75 → deepstrike-0.2.77}/crates/deepstrike-core/src/runtime/kernel/wire/driver/projection.rs +0 -0
  80. {deepstrike-0.2.75 → deepstrike-0.2.77}/crates/deepstrike-core/src/runtime/kernel/wire/effect.rs +0 -0
  81. {deepstrike-0.2.75 → deepstrike-0.2.77}/crates/deepstrike-core/src/runtime/kernel/wire/envelope.rs +0 -0
  82. {deepstrike-0.2.75 → deepstrike-0.2.77}/crates/deepstrike-core/src/runtime/kernel/wire/event.rs +0 -0
  83. {deepstrike-0.2.75 → deepstrike-0.2.77}/crates/deepstrike-core/src/runtime/kernel/wire/fault.rs +0 -0
  84. {deepstrike-0.2.75 → deepstrike-0.2.77}/crates/deepstrike-core/src/runtime/kernel/wire/memory_authority.rs +0 -0
  85. {deepstrike-0.2.75 → deepstrike-0.2.77}/crates/deepstrike-core/src/runtime/kernel/wire/projection.rs +0 -0
  86. {deepstrike-0.2.75 → deepstrike-0.2.77}/crates/deepstrike-core/src/runtime/kernel/wire/record.rs +0 -0
  87. {deepstrike-0.2.75 → deepstrike-0.2.77}/crates/deepstrike-core/src/runtime/kernel/wire/restore.rs +0 -0
  88. {deepstrike-0.2.75 → deepstrike-0.2.77}/crates/deepstrike-core/src/runtime/kernel/wire/root.rs +0 -0
  89. {deepstrike-0.2.75 → deepstrike-0.2.77}/crates/deepstrike-core/src/runtime/kernel/wire/scalar.rs +0 -0
  90. {deepstrike-0.2.75 → deepstrike-0.2.77}/crates/deepstrike-core/src/runtime/kernel/wire/syscall.rs +0 -0
  91. {deepstrike-0.2.75 → deepstrike-0.2.77}/crates/deepstrike-core/src/runtime/kernel/wire/terminal.rs +0 -0
  92. {deepstrike-0.2.75 → deepstrike-0.2.77}/crates/deepstrike-core/src/runtime/kernel/wire/tests.rs +0 -0
  93. {deepstrike-0.2.75 → deepstrike-0.2.77}/crates/deepstrike-core/src/runtime/kernel/wire/transaction.rs +0 -0
  94. {deepstrike-0.2.75 → deepstrike-0.2.77}/crates/deepstrike-core/src/runtime/kernel/wire.rs +0 -0
  95. {deepstrike-0.2.75 → deepstrike-0.2.77}/crates/deepstrike-core/src/runtime/kernel.rs +0 -0
  96. {deepstrike-0.2.75 → deepstrike-0.2.77}/crates/deepstrike-core/src/runtime/mod.rs +0 -0
  97. {deepstrike-0.2.75 → deepstrike-0.2.77}/crates/deepstrike-core/src/runtime/repair.rs +0 -0
  98. {deepstrike-0.2.75 → deepstrike-0.2.77}/crates/deepstrike-core/src/runtime/replay.rs +0 -0
  99. {deepstrike-0.2.75 → deepstrike-0.2.77}/crates/deepstrike-core/src/runtime/session.rs +0 -0
  100. {deepstrike-0.2.75 → deepstrike-0.2.77}/crates/deepstrike-core/src/runtime/verifiable.rs +0 -0
  101. {deepstrike-0.2.75 → deepstrike-0.2.77}/crates/deepstrike-core/src/scheduler/budget_grant.rs +0 -0
  102. {deepstrike-0.2.75 → deepstrike-0.2.77}/crates/deepstrike-core/src/scheduler/cross_operation.rs +0 -0
  103. {deepstrike-0.2.75 → deepstrike-0.2.77}/crates/deepstrike-core/src/scheduler/entropy.rs +0 -0
  104. {deepstrike-0.2.75 → deepstrike-0.2.77}/crates/deepstrike-core/src/scheduler/mailbox.rs +0 -0
  105. {deepstrike-0.2.75 → deepstrike-0.2.77}/crates/deepstrike-core/src/scheduler/milestone.rs +0 -0
  106. {deepstrike-0.2.75 → deepstrike-0.2.77}/crates/deepstrike-core/src/scheduler/mod.rs +0 -0
  107. {deepstrike-0.2.75 → deepstrike-0.2.77}/crates/deepstrike-core/src/scheduler/policy.rs +0 -0
  108. {deepstrike-0.2.75 → deepstrike-0.2.77}/crates/deepstrike-core/src/scheduler/rollback.rs +0 -0
  109. {deepstrike-0.2.75 → deepstrike-0.2.77}/crates/deepstrike-core/src/scheduler/runnable.rs +0 -0
  110. {deepstrike-0.2.75 → deepstrike-0.2.77}/crates/deepstrike-core/src/scheduler/state_machine/cancellation.rs +0 -0
  111. {deepstrike-0.2.75 → deepstrike-0.2.77}/crates/deepstrike-core/src/scheduler/state_machine/capability.rs +0 -0
  112. {deepstrike-0.2.75 → deepstrike-0.2.77}/crates/deepstrike-core/src/scheduler/state_machine/eviction.rs +0 -0
  113. {deepstrike-0.2.75 → deepstrike-0.2.77}/crates/deepstrike-core/src/scheduler/state_machine/gate.rs +0 -0
  114. {deepstrike-0.2.75 → deepstrike-0.2.77}/crates/deepstrike-core/src/scheduler/state_machine/milestone_exec.rs +0 -0
  115. {deepstrike-0.2.75 → deepstrike-0.2.77}/crates/deepstrike-core/src/scheduler/state_machine/process.rs +0 -0
  116. {deepstrike-0.2.75 → deepstrike-0.2.77}/crates/deepstrike-core/src/scheduler/state_machine/signal.rs +0 -0
  117. {deepstrike-0.2.75 → deepstrike-0.2.77}/crates/deepstrike-core/src/scheduler/state_machine/workflow.rs +0 -0
  118. {deepstrike-0.2.75 → deepstrike-0.2.77}/crates/deepstrike-core/src/scheduler/tcb.rs +0 -0
  119. {deepstrike-0.2.75 → deepstrike-0.2.77}/crates/deepstrike-core/src/scheduler/wait_index.rs +0 -0
  120. {deepstrike-0.2.75 → deepstrike-0.2.77}/crates/deepstrike-core/src/signals/attention.rs +0 -0
  121. {deepstrike-0.2.75 → deepstrike-0.2.77}/crates/deepstrike-core/src/signals/mod.rs +0 -0
  122. {deepstrike-0.2.75 → deepstrike-0.2.77}/crates/deepstrike-core/src/signals/queue.rs +0 -0
  123. {deepstrike-0.2.75 → deepstrike-0.2.77}/crates/deepstrike-core/src/signals/router.rs +0 -0
  124. {deepstrike-0.2.75 → deepstrike-0.2.77}/crates/deepstrike-core/src/syscall/mod.rs +0 -0
  125. {deepstrike-0.2.75 → deepstrike-0.2.77}/crates/deepstrike-core/src/types/agent.rs +0 -0
  126. {deepstrike-0.2.75 → deepstrike-0.2.77}/crates/deepstrike-core/src/types/capability.rs +0 -0
  127. {deepstrike-0.2.75 → deepstrike-0.2.77}/crates/deepstrike-core/src/types/contract.rs +0 -0
  128. {deepstrike-0.2.75 → deepstrike-0.2.77}/crates/deepstrike-core/src/types/durable_content.rs +0 -0
  129. {deepstrike-0.2.75 → deepstrike-0.2.77}/crates/deepstrike-core/src/types/error.rs +0 -0
  130. {deepstrike-0.2.75 → deepstrike-0.2.77}/crates/deepstrike-core/src/types/message.rs +0 -0
  131. {deepstrike-0.2.75 → deepstrike-0.2.77}/crates/deepstrike-core/src/types/milestone.rs +0 -0
  132. {deepstrike-0.2.75 → deepstrike-0.2.77}/crates/deepstrike-core/src/types/mod.rs +0 -0
  133. {deepstrike-0.2.75 → deepstrike-0.2.77}/crates/deepstrike-core/src/types/policy.rs +0 -0
  134. {deepstrike-0.2.75 → deepstrike-0.2.77}/crates/deepstrike-core/src/types/result.rs +0 -0
  135. {deepstrike-0.2.75 → deepstrike-0.2.77}/crates/deepstrike-core/src/types/signal.rs +0 -0
  136. {deepstrike-0.2.75 → deepstrike-0.2.77}/crates/deepstrike-core/src/types/skill.rs +0 -0
  137. {deepstrike-0.2.75 → deepstrike-0.2.77}/crates/deepstrike-core/src/types/task.rs +0 -0
  138. {deepstrike-0.2.75 → deepstrike-0.2.77}/crates/deepstrike-py/Cargo.toml +0 -0
  139. {deepstrike-0.2.75 → deepstrike-0.2.77}/crates/deepstrike-py/LICENSE +0 -0
  140. {deepstrike-0.2.75 → deepstrike-0.2.77}/crates/deepstrike-py/src/lib.rs +0 -0
  141. {deepstrike-0.2.75 → deepstrike-0.2.77}/crates/deepstrike-tokenizer/Cargo.toml +0 -0
  142. {deepstrike-0.2.75 → deepstrike-0.2.77}/crates/deepstrike-tokenizer/LICENSE +0 -0
  143. {deepstrike-0.2.75 → deepstrike-0.2.77}/crates/deepstrike-tokenizer/src/lib.rs +0 -0
  144. {deepstrike-0.2.75 → deepstrike-0.2.77}/deepstrike/__init__.py +0 -0
  145. {deepstrike-0.2.75 → deepstrike-0.2.77}/deepstrike/agent.py +0 -0
  146. {deepstrike-0.2.75 → deepstrike-0.2.77}/deepstrike/collaboration/__init__.py +0 -0
  147. {deepstrike-0.2.75 → deepstrike-0.2.77}/deepstrike/collaboration/contract.py +0 -0
  148. {deepstrike-0.2.75 → deepstrike-0.2.77}/deepstrike/collaboration/handoff.py +0 -0
  149. {deepstrike-0.2.75 → deepstrike-0.2.77}/deepstrike/collaboration/harness.py +0 -0
  150. {deepstrike-0.2.75 → deepstrike-0.2.77}/deepstrike/collaboration/modes.py +0 -0
  151. {deepstrike-0.2.75 → deepstrike-0.2.77}/deepstrike/collaboration/pool.py +0 -0
  152. {deepstrike-0.2.75 → deepstrike-0.2.77}/deepstrike/governance.py +0 -0
  153. {deepstrike-0.2.75 → deepstrike-0.2.77}/deepstrike/harness/__init__.py +0 -0
  154. {deepstrike-0.2.75 → deepstrike-0.2.77}/deepstrike/harness/harness.py +0 -0
  155. {deepstrike-0.2.75 → deepstrike-0.2.77}/deepstrike/harness/judge.py +0 -0
  156. {deepstrike-0.2.75 → deepstrike-0.2.77}/deepstrike/kernel/__init__.py +0 -0
  157. {deepstrike-0.2.75 → deepstrike-0.2.77}/deepstrike/kernel/canonical.py +0 -0
  158. {deepstrike-0.2.75 → deepstrike-0.2.77}/deepstrike/knowledge/__init__.py +0 -0
  159. {deepstrike-0.2.75 → deepstrike-0.2.77}/deepstrike/knowledge/source.py +0 -0
  160. {deepstrike-0.2.75 → deepstrike-0.2.77}/deepstrike/memory/__init__.py +0 -0
  161. {deepstrike-0.2.75 → deepstrike-0.2.77}/deepstrike/memory/agent.py +0 -0
  162. {deepstrike-0.2.75 → deepstrike-0.2.77}/deepstrike/memory/authority.py +0 -0
  163. {deepstrike-0.2.75 → deepstrike-0.2.77}/deepstrike/memory/durable.py +0 -0
  164. {deepstrike-0.2.75 → deepstrike-0.2.77}/deepstrike/memory/extraction.py +0 -0
  165. {deepstrike-0.2.75 → deepstrike-0.2.77}/deepstrike/memory/in_memory_store.py +0 -0
  166. {deepstrike-0.2.75 → deepstrike-0.2.77}/deepstrike/memory/protocols.py +0 -0
  167. {deepstrike-0.2.75 → deepstrike-0.2.77}/deepstrike/memory/ranking.py +0 -0
  168. {deepstrike-0.2.75 → deepstrike-0.2.77}/deepstrike/memory/retention.py +0 -0
  169. {deepstrike-0.2.75 → deepstrike-0.2.77}/deepstrike/memory/working.py +0 -0
  170. {deepstrike-0.2.75 → deepstrike-0.2.77}/deepstrike/providers/__init__.py +0 -0
  171. {deepstrike-0.2.75 → deepstrike-0.2.77}/deepstrike/providers/anthropic.py +0 -0
  172. {deepstrike-0.2.75 → deepstrike-0.2.77}/deepstrike/providers/anthropic_adapter.py +0 -0
  173. {deepstrike-0.2.75 → deepstrike-0.2.77}/deepstrike/providers/anthropic_compatible.py +0 -0
  174. {deepstrike-0.2.75 → deepstrike-0.2.77}/deepstrike/providers/base.py +0 -0
  175. {deepstrike-0.2.75 → deepstrike-0.2.77}/deepstrike/providers/capability_router.py +0 -0
  176. {deepstrike-0.2.75 → deepstrike-0.2.77}/deepstrike/providers/credentials.py +0 -0
  177. {deepstrike-0.2.75 → deepstrike-0.2.77}/deepstrike/providers/embedding.py +0 -0
  178. {deepstrike-0.2.75 → deepstrike-0.2.77}/deepstrike/providers/factories.py +0 -0
  179. {deepstrike-0.2.75 → deepstrike-0.2.77}/deepstrike/providers/fallback.py +0 -0
  180. {deepstrike-0.2.75 → deepstrike-0.2.77}/deepstrike/providers/gemini.py +0 -0
  181. {deepstrike-0.2.75 → deepstrike-0.2.77}/deepstrike/providers/gemini_adapter.py +0 -0
  182. {deepstrike-0.2.75 → deepstrike-0.2.77}/deepstrike/providers/model_catalog.py +0 -0
  183. {deepstrike-0.2.75 → deepstrike-0.2.77}/deepstrike/providers/model_registry.py +0 -0
  184. {deepstrike-0.2.75 → deepstrike-0.2.77}/deepstrike/providers/ollama.py +0 -0
  185. {deepstrike-0.2.75 → deepstrike-0.2.77}/deepstrike/providers/ollama_adapter.py +0 -0
  186. {deepstrike-0.2.75 → deepstrike-0.2.77}/deepstrike/providers/openai.py +0 -0
  187. {deepstrike-0.2.75 → deepstrike-0.2.77}/deepstrike/providers/openai_chat_adapter.py +0 -0
  188. {deepstrike-0.2.75 → deepstrike-0.2.77}/deepstrike/providers/openai_responses.py +0 -0
  189. {deepstrike-0.2.75 → deepstrike-0.2.77}/deepstrike/providers/prepared_request.py +0 -0
  190. {deepstrike-0.2.75 → deepstrike-0.2.77}/deepstrike/providers/protocol_adapter.py +0 -0
  191. {deepstrike-0.2.75 → deepstrike-0.2.77}/deepstrike/providers/protocols.py +0 -0
  192. {deepstrike-0.2.75 → deepstrike-0.2.77}/deepstrike/providers/provider_error.py +0 -0
  193. {deepstrike-0.2.75 → deepstrike-0.2.77}/deepstrike/providers/qwen.py +0 -0
  194. {deepstrike-0.2.75 → deepstrike-0.2.77}/deepstrike/providers/replay.py +0 -0
  195. {deepstrike-0.2.75 → deepstrike-0.2.77}/deepstrike/providers/replay_validator.py +0 -0
  196. {deepstrike-0.2.75 → deepstrike-0.2.77}/deepstrike/providers/request_plan.py +0 -0
  197. {deepstrike-0.2.75 → deepstrike-0.2.77}/deepstrike/providers/runtime_registry.py +0 -0
  198. {deepstrike-0.2.75 → deepstrike-0.2.77}/deepstrike/providers/stop_reason.py +0 -0
  199. {deepstrike-0.2.75 → deepstrike-0.2.77}/deepstrike/providers/stream.py +0 -0
  200. {deepstrike-0.2.75 → deepstrike-0.2.77}/deepstrike/providers/usage.py +0 -0
  201. {deepstrike-0.2.75 → deepstrike-0.2.77}/deepstrike/providers/vendor_profiles.py +0 -0
  202. {deepstrike-0.2.75 → deepstrike-0.2.77}/deepstrike/runtime/__init__.py +0 -0
  203. {deepstrike-0.2.75 → deepstrike-0.2.77}/deepstrike/runtime/agent_declaration.py +0 -0
  204. {deepstrike-0.2.75 → deepstrike-0.2.77}/deepstrike/runtime/archive.py +0 -0
  205. {deepstrike-0.2.75 → deepstrike-0.2.77}/deepstrike/runtime/canonical_kernel_step.py +0 -0
  206. {deepstrike-0.2.75 → deepstrike-0.2.77}/deepstrike/runtime/context.py +0 -0
  207. {deepstrike-0.2.75 → deepstrike-0.2.77}/deepstrike/runtime/context_policy.py +0 -0
  208. {deepstrike-0.2.75 → deepstrike-0.2.77}/deepstrike/runtime/credential_vault.py +0 -0
  209. {deepstrike-0.2.75 → deepstrike-0.2.77}/deepstrike/runtime/durable_content.py +0 -0
  210. {deepstrike-0.2.75 → deepstrike-0.2.77}/deepstrike/runtime/eval.py +0 -0
  211. {deepstrike-0.2.75 → deepstrike-0.2.77}/deepstrike/runtime/eval_dataset.py +0 -0
  212. {deepstrike-0.2.75 → deepstrike-0.2.77}/deepstrike/runtime/event_stream.py +0 -0
  213. {deepstrike-0.2.75 → deepstrike-0.2.77}/deepstrike/runtime/evolution.py +0 -0
  214. {deepstrike-0.2.75 → deepstrike-0.2.77}/deepstrike/runtime/execution_evidence.py +0 -0
  215. {deepstrike-0.2.75 → deepstrike-0.2.77}/deepstrike/runtime/execution_plane.py +0 -0
  216. {deepstrike-0.2.75 → deepstrike-0.2.77}/deepstrike/runtime/facade.py +0 -0
  217. {deepstrike-0.2.75 → deepstrike-0.2.77}/deepstrike/runtime/filtered_plane.py +0 -0
  218. {deepstrike-0.2.75 → deepstrike-0.2.77}/deepstrike/runtime/kernel_event_log.py +0 -0
  219. {deepstrike-0.2.75 → deepstrike-0.2.77}/deepstrike/runtime/kernel_journal.py +0 -0
  220. {deepstrike-0.2.75 → deepstrike-0.2.77}/deepstrike/runtime/kernel_step.py +0 -0
  221. {deepstrike-0.2.75 → deepstrike-0.2.77}/deepstrike/runtime/loop_driver.py +0 -0
  222. {deepstrike-0.2.75 → deepstrike-0.2.77}/deepstrike/runtime/mcp_proxy_plane.py +0 -0
  223. {deepstrike-0.2.75 → deepstrike-0.2.77}/deepstrike/runtime/os_profile.py +0 -0
  224. {deepstrike-0.2.75 → deepstrike-0.2.77}/deepstrike/runtime/os_snapshot.py +0 -0
  225. {deepstrike-0.2.75 → deepstrike-0.2.77}/deepstrike/runtime/output_schema.py +0 -0
  226. {deepstrike-0.2.75 → deepstrike-0.2.77}/deepstrike/runtime/payload_store.py +0 -0
  227. {deepstrike-0.2.75 → deepstrike-0.2.77}/deepstrike/runtime/process_sandbox_plane.py +0 -0
  228. {deepstrike-0.2.75 → deepstrike-0.2.77}/deepstrike/runtime/provider_replay.py +0 -0
  229. {deepstrike-0.2.75 → deepstrike-0.2.77}/deepstrike/runtime/reaction_checkpoint.py +0 -0
  230. {deepstrike-0.2.75 → deepstrike-0.2.77}/deepstrike/runtime/reactive_session.py +0 -0
  231. {deepstrike-0.2.75 → deepstrike-0.2.77}/deepstrike/runtime/reducers.py +0 -0
  232. {deepstrike-0.2.75 → deepstrike-0.2.77}/deepstrike/runtime/reliability.py +0 -0
  233. {deepstrike-0.2.75 → deepstrike-0.2.77}/deepstrike/runtime/remote_vpc_plane.py +0 -0
  234. {deepstrike-0.2.75 → deepstrike-0.2.77}/deepstrike/runtime/replay_fixture.py +0 -0
  235. {deepstrike-0.2.75 → deepstrike-0.2.77}/deepstrike/runtime/replay_provider.py +0 -0
  236. {deepstrike-0.2.75 → deepstrike-0.2.77}/deepstrike/runtime/replay_sanitize.py +0 -0
  237. {deepstrike-0.2.75 → deepstrike-0.2.77}/deepstrike/runtime/run_group.py +0 -0
  238. {deepstrike-0.2.75 → deepstrike-0.2.77}/deepstrike/runtime/runner.py +0 -0
  239. {deepstrike-0.2.75 → deepstrike-0.2.77}/deepstrike/runtime/session_log.py +0 -0
  240. {deepstrike-0.2.75 → deepstrike-0.2.77}/deepstrike/runtime/session_repair.py +0 -0
  241. {deepstrike-0.2.75 → deepstrike-0.2.77}/deepstrike/runtime/sub_agent_orchestrator.py +0 -0
  242. {deepstrike-0.2.75 → deepstrike-0.2.77}/deepstrike/runtime/tool_arguments.py +0 -0
  243. {deepstrike-0.2.75 → deepstrike-0.2.77}/deepstrike/runtime/turn_policy.py +0 -0
  244. {deepstrike-0.2.75 → deepstrike-0.2.77}/deepstrike/runtime/verifiable_report.py +0 -0
  245. {deepstrike-0.2.75 → deepstrike-0.2.77}/deepstrike/runtime/workflow_control_flow.py +0 -0
  246. {deepstrike-0.2.75 → deepstrike-0.2.77}/deepstrike/runtime/workflow_replay.py +0 -0
  247. {deepstrike-0.2.75 → deepstrike-0.2.77}/deepstrike/runtime/workflow_store.py +0 -0
  248. {deepstrike-0.2.75 → deepstrike-0.2.77}/deepstrike/runtime/worktree_plane.py +0 -0
  249. {deepstrike-0.2.75 → deepstrike-0.2.77}/deepstrike/safety/__init__.py +0 -0
  250. {deepstrike-0.2.75 → deepstrike-0.2.77}/deepstrike/safety/permissions.py +0 -0
  251. {deepstrike-0.2.75 → deepstrike-0.2.77}/deepstrike/signals/__init__.py +0 -0
  252. {deepstrike-0.2.75 → deepstrike-0.2.77}/deepstrike/signals/gateway.py +0 -0
  253. {deepstrike-0.2.75 → deepstrike-0.2.77}/deepstrike/signals/scheduled.py +0 -0
  254. {deepstrike-0.2.75 → deepstrike-0.2.77}/deepstrike/signals/types.py +0 -0
  255. {deepstrike-0.2.75 → deepstrike-0.2.77}/deepstrike/skills/__init__.py +0 -0
  256. {deepstrike-0.2.75 → deepstrike-0.2.77}/deepstrike/skills/loader.py +0 -0
  257. {deepstrike-0.2.75 → deepstrike-0.2.77}/deepstrike/skills/registry.py +0 -0
  258. {deepstrike-0.2.75 → deepstrike-0.2.77}/deepstrike/skills/watcher.py +0 -0
  259. {deepstrike-0.2.75 → deepstrike-0.2.77}/deepstrike/tools/__init__.py +0 -0
  260. {deepstrike-0.2.75 → deepstrike-0.2.77}/deepstrike/tools/builtin/__init__.py +0 -0
  261. {deepstrike-0.2.75 → deepstrike-0.2.77}/deepstrike/tools/builtin/read_file.py +0 -0
  262. {deepstrike-0.2.75 → deepstrike-0.2.77}/deepstrike/tools/errors.py +0 -0
  263. {deepstrike-0.2.75 → deepstrike-0.2.77}/deepstrike/tools/execution.py +0 -0
  264. {deepstrike-0.2.75 → deepstrike-0.2.77}/deepstrike/tools/registry.py +0 -0
  265. {deepstrike-0.2.75 → deepstrike-0.2.77}/deepstrike/types/__init__.py +0 -0
  266. {deepstrike-0.2.75 → deepstrike-0.2.77}/deepstrike/types/agent.py +0 -0
  267. {deepstrike-0.2.75 → deepstrike-0.2.77}/deepstrike/types/content.py +0 -0
  268. {deepstrike-0.2.75 → deepstrike-0.2.77}/deepstrike/types/content_policy.py +0 -0
@@ -254,7 +254,7 @@ dependencies = [
254
254
 
255
255
  [[package]]
256
256
  name = "deepstrike-core"
257
- version = "0.2.75"
257
+ version = "0.2.77"
258
258
  dependencies = [
259
259
  "compact_str",
260
260
  "deepstrike-tokenizer",
@@ -268,7 +268,7 @@ dependencies = [
268
268
 
269
269
  [[package]]
270
270
  name = "deepstrike-node"
271
- version = "0.2.75"
271
+ version = "0.2.77"
272
272
  dependencies = [
273
273
  "compact_str",
274
274
  "deepstrike-core",
@@ -280,7 +280,7 @@ dependencies = [
280
280
 
281
281
  [[package]]
282
282
  name = "deepstrike-py"
283
- version = "0.2.75"
283
+ version = "0.2.77"
284
284
  dependencies = [
285
285
  "compact_str",
286
286
  "deepstrike-core",
@@ -291,7 +291,7 @@ dependencies = [
291
291
 
292
292
  [[package]]
293
293
  name = "deepstrike-sdk"
294
- version = "0.2.75"
294
+ version = "0.2.77"
295
295
  dependencies = [
296
296
  "async-stream",
297
297
  "async-trait",
@@ -328,7 +328,7 @@ dependencies = [
328
328
 
329
329
  [[package]]
330
330
  name = "deepstrike-tokenizer"
331
- version = "0.2.75"
331
+ version = "0.2.77"
332
332
  dependencies = [
333
333
  "pretty_assertions",
334
334
  "tiktoken-rs",
@@ -336,7 +336,7 @@ dependencies = [
336
336
 
337
337
  [[package]]
338
338
  name = "deepstrike-wasm"
339
- version = "0.2.75"
339
+ version = "0.2.77"
340
340
  dependencies = [
341
341
  "compact_str",
342
342
  "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.75"
6
+ version = "0.2.77"
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.75" }
12
- deepstrike-tokenizer = { path = "crates/deepstrike-tokenizer", version = "0.2.75" }
11
+ deepstrike-core = { path = "crates/deepstrike-core", version = "0.2.77" }
12
+ deepstrike-tokenizer = { path = "crates/deepstrike-tokenizer", version = "0.2.77" }
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.75
3
+ Version: 0.2.77
4
4
  Requires-Dist: httpx>=0.27
5
5
  Requires-Dist: pyyaml>=6.0
6
6
  Requires-Dist: anyio>=4.0
@@ -367,11 +367,14 @@ impl ContextManager {
367
367
  /// from *this* value, so it must NOT discount paged content (else collapse → rho drops →
368
368
  /// un-collapse would oscillate).
369
369
  pub fn rho(&self) -> f64 {
370
- self.pressure.pressure(
370
+ let observed = self.pressure.pressure(
371
371
  &self.partitions,
372
372
  &self.engine,
373
373
  self.last_observed_prompt_tokens,
374
- )
374
+ );
375
+ // A provider sees a selected projection, not the entire resident history. Its smaller
376
+ // count must not suppress compaction while the unselected history still triggers renewal.
377
+ observed.max(self.pressure.pressure(&self.partitions, &self.engine, None))
375
378
  }
376
379
 
377
380
  pub fn set_observed_prompt_tokens(&mut self, tokens: u32) {
@@ -427,6 +430,10 @@ impl ContextManager {
427
430
  target_tokens,
428
431
  &self.engine,
429
432
  );
433
+ if result.0 > 0 || !result.2.is_empty() {
434
+ // The measurement describes the request before this rewrite, not the new context.
435
+ self.last_observed_prompt_tokens = None;
436
+ }
430
437
  if let Some(ts) = now_ms {
431
438
  self.last_compact_ms = Some(ts);
432
439
  }
@@ -475,6 +482,7 @@ impl ContextManager {
475
482
  .renewal
476
483
  .renew(&self.partitions, self.max_tokens, &self.engine);
477
484
  self.sprint += 1;
485
+ self.last_observed_prompt_tokens = None;
478
486
  // History was rebuilt wholesale — drop handles anchored to messages it no longer carries,
479
487
  // and start a fresh collapse generation (P0-C) since the whole prefix changed.
480
488
  self.prune_orphaned_handles();
@@ -1250,6 +1258,20 @@ mod tests {
1250
1258
  use crate::types::message::CoreMessage;
1251
1259
  use crate::types::skill::SkillMetadata;
1252
1260
 
1261
+ #[test]
1262
+ fn low_provider_usage_does_not_hide_resident_history_pressure() {
1263
+ let mut mgr = ContextManager::with_config(
1264
+ 1_000,
1265
+ ContextConfig::default(),
1266
+ ContextTokenEngine::char_approx(),
1267
+ );
1268
+ mgr.push_history(CoreMessage::user("large history"), 1_100);
1269
+ mgr.set_observed_prompt_tokens(10);
1270
+ assert_eq!(mgr.should_compress(), PressureAction::AutoCompact);
1271
+ mgr.compress(PressureAction::AutoCompact);
1272
+ assert!(!mgr.should_renew());
1273
+ }
1274
+
1253
1275
  #[test]
1254
1276
  fn preparation_freezes_state_plan_and_render_identity() {
1255
1277
  let mut mgr = ContextManager::new(100_000);
@@ -61,31 +61,25 @@ impl RenewalPolicy {
61
61
  // History: carry recent turns up to carryover budget.
62
62
  let carryover_budget = config.carryover_tokens(max_tokens);
63
63
  let mut remaining = carryover_budget;
64
- let mut carried: Vec<_> = partitions
65
- .history
66
- .messages
67
- .iter()
68
- .enumerate()
69
- .rev()
70
- .take_while(|(index, _msg)| {
71
- let t = partitions.history.measured_tokens(*index, engine);
72
- if t <= remaining {
73
- remaining = remaining.saturating_sub(t);
74
- true
75
- } else {
76
- false
77
- }
78
- })
79
- .map(|(index, msg)| {
80
- (
81
- msg.clone(),
82
- partitions.history.measured_tokens(index, engine),
83
- )
84
- })
85
- .collect();
86
- carried.reverse();
87
- for (msg, t) in carried {
88
- renewed.history.push(msg, t);
64
+ let messages = &partitions.history.messages;
65
+ let mut start = messages.len();
66
+ // Carry whole conversational transactions, so a budget boundary cannot strand a result
67
+ // without its assistant call (or omit one result of a parallel call batch).
68
+ for unit in super::units::unit_boundaries(messages).into_iter().rev() {
69
+ let tokens = unit.clone().fold(0u32, |sum, index| {
70
+ sum.saturating_add(partitions.history.measured_tokens(index, engine))
71
+ });
72
+ if tokens > remaining {
73
+ break;
74
+ }
75
+ remaining = remaining.saturating_sub(tokens);
76
+ start = unit.start;
77
+ }
78
+ for (index, msg) in messages.iter().enumerate().skip(start) {
79
+ renewed.history.push(
80
+ msg.clone(),
81
+ partitions.history.measured_tokens(index, engine),
82
+ );
89
83
  }
90
84
 
91
85
  renewed
@@ -147,6 +141,33 @@ mod tests {
147
141
  assert!(renewed.history.token_count <= 100);
148
142
  }
149
143
 
144
+ #[test]
145
+ fn renewal_never_carries_a_tool_result_without_its_call() {
146
+ use crate::types::message::{ContentPart, ToolCall};
147
+ let mut ctx = ContextPartitions::new(&ContextConfig::default());
148
+ ctx.history.push(CoreMessage::user("read"), 10);
149
+ let mut call = CoreMessage::assistant("");
150
+ call.tool_calls.push(ToolCall {
151
+ id: "call-1".into(),
152
+ name: "read".into(),
153
+ arguments: serde_json::json!({}),
154
+ });
155
+ ctx.history.push(call, 80);
156
+ ctx.history.push(
157
+ CoreMessage::tool(vec![ContentPart::ToolResult {
158
+ call_id: "call-1".into(),
159
+ output: "result".into(),
160
+ is_error: false,
161
+ durable_content: None,
162
+ }]),
163
+ 40,
164
+ );
165
+ let renewed = make_policy(0.1).renew(&ctx, 1_000, &ContextTokenEngine::char_approx());
166
+ assert!(crate::context::units::strict_tool_pairing_is_valid(
167
+ &renewed.history.messages
168
+ ));
169
+ }
170
+
150
171
  #[test]
151
172
  fn renewal_clears_task_scratchpad_keeps_goal() {
152
173
  let cfg = ContextConfig::default();
@@ -44,7 +44,7 @@ impl TokenCounter for CharApproxCounter {
44
44
  /// implementation applies the same 0.25 tokens/char divisor to every script). This wraps
45
45
  /// `deepstrike-tokenizer`'s real cl100k BPE tokenizer (previously an orphaned crate — not a
46
46
  /// workspace member, zero call sites anywhere) and adds a fixed margin on top. That only
47
- /// guarantees a value above the selected `cl100k_base` estimate; it does not prove that the
47
+ /// guarantees a value above its chunked `cl100k_base` estimate; it does not prove that the
48
48
  /// result is conservative for every provider model. Native Anthropic/Gemini token counts take
49
49
  /// precedence where callers explicitly request them.
50
50
  pub struct FallbackEstimator {
@@ -69,17 +69,54 @@ impl Default for FallbackEstimator {
69
69
  }
70
70
  }
71
71
 
72
+ /// Bound BPE merge work for long unbroken tool output. Chunk boundaries are UTF-8-safe and
73
+ /// deterministic; boundary merges are deliberately sacrificed by this heuristic estimator.
74
+ fn estimation_chunks(mut text: &str) -> impl Iterator<Item = &str> {
75
+ std::iter::from_fn(move || {
76
+ if text.is_empty() {
77
+ return None;
78
+ }
79
+ let mut end = text.len().min(1_024);
80
+ while !text.is_char_boundary(end) {
81
+ end -= 1;
82
+ }
83
+ let (chunk, rest) = text.split_at(end);
84
+ text = rest;
85
+ Some(chunk)
86
+ })
87
+ }
88
+
72
89
  impl TokenCounter for FallbackEstimator {
73
90
  fn count(&self, text: &str) -> u32 {
74
- let raw = self.tokenizer.count(text) as f64;
75
- ((raw * self.safety_margin).ceil() as u32).max(1)
91
+ let raw = estimation_chunks(text).fold(0u32, |sum, chunk| {
92
+ sum.saturating_add(self.tokenizer.count(chunk))
93
+ });
94
+ ((raw as f64 * self.safety_margin).ceil() as u32).max(1)
76
95
  }
77
96
 
78
97
  fn truncate<'a>(&self, text: &'a str, max_tokens: u32) -> &'a str {
79
98
  // Budget in *raw* BPE tokens so that, after the margin is applied by `count`, the
80
99
  // truncated text's reported count still fits within `max_tokens`.
81
100
  let raw_budget = ((max_tokens as f64) / self.safety_margin).floor() as u32;
82
- self.tokenizer.truncate(text, raw_budget)
101
+ let mut remaining = raw_budget;
102
+ let mut end = 0;
103
+ for chunk in estimation_chunks(text) {
104
+ let tokens = self.tokenizer.count(chunk);
105
+ if tokens <= remaining {
106
+ remaining -= tokens;
107
+ end += chunk.len();
108
+ } else {
109
+ let mut prefix_end = self.tokenizer.truncate(chunk, remaining).len();
110
+ // Retokenizing a prefix can change its last merge. Enforce the same count budget
111
+ // on the returned prefix, without ever processing another unbounded string.
112
+ while prefix_end > 0 && self.tokenizer.count(&chunk[..prefix_end]) > remaining {
113
+ prefix_end = chunk[..prefix_end].char_indices().next_back().unwrap().0;
114
+ }
115
+ end += prefix_end;
116
+ break;
117
+ }
118
+ }
119
+ &text[..end]
83
120
  }
84
121
  }
85
122
 
@@ -101,7 +138,12 @@ impl ContextTokenEngine {
101
138
  /// [`FallbackEstimator`]), replacing the previous `char_approx()` default that
102
139
  /// underestimated CJK-heavy text by 40-70%.
103
140
  pub fn fallback_estimator() -> Self {
104
- Self(Arc::new(FallbackEstimator::default()))
141
+ static COUNTER: std::sync::OnceLock<Arc<dyn TokenCounter>> = std::sync::OnceLock::new();
142
+ Self(
143
+ COUNTER
144
+ .get_or_init(|| Arc::new(FallbackEstimator::default()))
145
+ .clone(),
146
+ )
105
147
  }
106
148
 
107
149
  pub fn count(&self, text: &str) -> u32 {
@@ -186,6 +228,31 @@ fn modality_estimate_tokens(part: &ContentPart) -> Option<u32> {
186
228
  #[cfg(test)]
187
229
  mod tests {
188
230
  use super::*;
231
+
232
+ #[test]
233
+ fn default_engines_share_the_immutable_bpe_tables() {
234
+ let first = ContextTokenEngine::fallback_estimator();
235
+ let second = ContextTokenEngine::fallback_estimator();
236
+ assert!(
237
+ Arc::ptr_eq(&first.0, &second.0),
238
+ "starting or restoring an operation must not reload the tokenizer tables"
239
+ );
240
+ }
241
+
242
+ #[test]
243
+ fn large_unbroken_estimates_are_bounded_and_truncation_remains_utf8_safe() {
244
+ let estimator = FallbackEstimator::default();
245
+ let started = std::time::Instant::now();
246
+ assert!(estimator.count(&"y".repeat(100 * 1024)) > 20_000);
247
+ assert!(
248
+ started.elapsed() < std::time::Duration::from_secs(10),
249
+ "100 KiB of unbroken tool output must not stall the host for tens of seconds"
250
+ );
251
+ let text = "核实需求与运行结果🙂".repeat(2_000);
252
+ let truncated = estimator.truncate(&text, 2_000);
253
+ assert!(text.starts_with(truncated));
254
+ assert!(estimator.count(truncated) <= 2_000);
255
+ }
189
256
  use crate::types::message::{ContentPart, CoreMessage};
190
257
 
191
258
  fn engine() -> ContextTokenEngine {
@@ -325,7 +325,7 @@ impl CanonicalOperationDriver {
325
325
  attempt_id: completed.attempt_id.clone(),
326
326
  request_seq: seq as u32,
327
327
  });
328
- match self.apply_syscall(context, &causation, request, &mut index) {
328
+ match self.apply_syscall(context, &causation, request, &mut index, &effects) {
329
329
  Ok(outcome) => effects.extend(outcome.effects),
330
330
  Err(SyscallRefusal::Fault(fault)) => self.note_rejection(
331
331
  SyscallRejection::new(
@@ -118,7 +118,9 @@ impl CanonicalOperationDriver {
118
118
  let mut round_caller: Option<TaskId> = None;
119
119
  for (causation, call) in &derived {
120
120
  let outcome = match decode_syscall(call) {
121
- Ok(request) => self.apply_syscall(context, causation, &request, &mut index),
121
+ Ok(request) => {
122
+ self.apply_syscall(context, causation, &request, &mut index, &effects)
123
+ }
122
124
  Err(rejection) => Err(SyscallRefusal::Rejected(rejection)),
123
125
  };
124
126
  match outcome {
@@ -9,6 +9,7 @@ impl CanonicalOperationDriver {
9
9
  causation: &SyscallCausation,
10
10
  request: &SyscallRequest,
11
11
  effect_index: &mut u32,
12
+ planned_effects: &[KernelEffect],
12
13
  ) -> Result<SyscallOutcome, SyscallRefusal> {
13
14
  let caller = causation_task(causation);
14
15
  let quarantined = self
@@ -53,6 +54,17 @@ impl CanonicalOperationDriver {
53
54
  )
54
55
  } else {
55
56
  self.enter_nested_workflow(context, &submit.spec, effect_index)
57
+ .map_err(|refusal| match refusal {
58
+ SyscallRefusal::Fault(fault)
59
+ if fault.code == KernelFaultCode::InvalidAuthority =>
60
+ {
61
+ SyscallRefusal::Rejected(SyscallRejection::new(
62
+ "start_workflow",
63
+ fault.message,
64
+ ))
65
+ }
66
+ other => other,
67
+ })
56
68
  }
57
69
  }
58
70
  SyscallRequest::AppendWorkflowNodes(append) => {
@@ -99,9 +111,13 @@ impl CanonicalOperationDriver {
99
111
  SyscallRequest::RequestMemoryWrite(write) => {
100
112
  self.plan_memory_write(context, causation, &write.proposal, effect_index)
101
113
  }
102
- SyscallRequest::RequestMemoryQuery(query) => {
103
- self.plan_memory_query(context, causation, &query.query, effect_index)
104
- }
114
+ SyscallRequest::RequestMemoryQuery(query) => self.plan_memory_query(
115
+ context,
116
+ causation,
117
+ &query.query,
118
+ effect_index,
119
+ planned_effects,
120
+ ),
105
121
  SyscallRequest::PageIn(page_in) => {
106
122
  self.plan_page_in(context, &caller, &page_in.handle_id, effect_index)
107
123
  }
@@ -450,6 +466,7 @@ impl CanonicalOperationDriver {
450
466
  causation: &SyscallCausation,
451
467
  proposal: &super::super::syscall::MemoryQueryProposal,
452
468
  effect_index: &mut u32,
469
+ planned_effects: &[KernelEffect],
453
470
  ) -> Result<SyscallOutcome, SyscallRefusal> {
454
471
  let Some(binding) = context.config.memory_access.clone() else {
455
472
  return Err(SyscallRefusal::Rejected(SyscallRejection::new(
@@ -469,6 +486,30 @@ impl CanonicalOperationDriver {
469
486
  // and a model cannot widen it by asking for more.
470
487
  let ceiling = context.config.memory_policy.retrieval_top_k;
471
488
  let requested_k = proposal.limit.unwrap_or(ceiling).clamp(1, ceiling);
489
+ if let Some(pending) = context
490
+ .pending
491
+ .iter()
492
+ .chain(planned_effects)
493
+ .find_map(|effect| match &effect.effect {
494
+ EffectKind::QueryMemory(query) => Some(query),
495
+ _ => None,
496
+ })
497
+ {
498
+ if pending.binding == binding
499
+ && pending.query.text == proposal.text
500
+ && pending.query.kinds == proposal.kinds
501
+ && pending.requested_k == requested_k
502
+ {
503
+ return Ok(SyscallOutcome {
504
+ ack: Some("Reusing the identical pending memory query; its results will arrive before the next turn.".into()),
505
+ ..Default::default()
506
+ });
507
+ }
508
+ return Err(SyscallRefusal::Rejected(SyscallRejection::new(
509
+ "query_memory",
510
+ "A different memory query is already pending. Retry this query after its result arrives.",
511
+ )));
512
+ }
472
513
  let authored = AuthoredMemoryQuery {
473
514
  binding_id: binding.binding_id.clone(),
474
515
  text: proposal.text.clone(),
@@ -41,6 +41,32 @@ use crate::scheduler::tcb::TaskLifecycle;
41
41
 
42
42
  const OPERATION: &str = "op-driver-1";
43
43
 
44
+ #[test]
45
+ fn resolved_context_policy_reaches_the_semantic_engine() {
46
+ let mut config = ConfigDefaults::default().baseline;
47
+ config.execution_policy.max_context_tokens = 1_000;
48
+ config.context_policy.target_after_compress_ppm = Ppm::new(500_000).unwrap();
49
+ config.context_policy.renewal_carryover_ppm = Ppm::new(400_000).unwrap();
50
+ config.context_policy.preserve_recent_turns = 5;
51
+ config.context_policy.idle_micro_compact_minutes = 17;
52
+ let mut engine = build_engine(&config);
53
+ assert_eq!(engine.ctx.config.target_after_compress, 0.5);
54
+ assert_eq!(engine.ctx.config.carryover_ratio, 0.4);
55
+ assert_eq!(engine.ctx.plan_compaction_params().1, 5);
56
+ assert_eq!(engine.ctx.config.micro_compact_idle_minutes, 17);
57
+ for i in 0..6 {
58
+ engine
59
+ .ctx
60
+ .push_history(CoreMessage::user(format!("turn {i}")), 100);
61
+ }
62
+ engine.ctx.renew();
63
+ assert_eq!(
64
+ engine.ctx.partitions.history.messages.len(),
65
+ 4,
66
+ "the renewal component must use the installed 40% policy rather than its 5% default"
67
+ );
68
+ }
69
+
44
70
  // -----------------------------------------------------------------------------------------
45
71
  // §8.2 host loop: prepare → (CAS append) → commit → fold
46
72
  // -----------------------------------------------------------------------------------------
@@ -2826,6 +2852,89 @@ fn a_memory_query_is_clamped_to_the_operations_retrieval_policy() {
2826
2852
  assert_eq!(effect.binding.binding_id.as_str(), "mem-binding-1");
2827
2853
  }
2828
2854
 
2855
+ #[test]
2856
+ fn parallel_memory_queries_reuse_or_refuse_without_terminating_the_turn() {
2857
+ for duplicate in [true, false] {
2858
+ let (mut runtime, provider) = agent_awaiting_provider();
2859
+ let queried = runtime.submit(&provider_result(
2860
+ "in-parallel-recall",
2861
+ 1_700_000_002_000,
2862
+ &provider,
2863
+ vec![
2864
+ tool_call("call-1", "memory", json!({"query": "past briefs"})),
2865
+ tool_call(
2866
+ "call-2",
2867
+ "memory",
2868
+ json!({"query": if duplicate { "past briefs" } else { "other projects" }}),
2869
+ ),
2870
+ ],
2871
+ ));
2872
+ assert_eq!(kinds(&queried), vec![EffectKindTag::QueryMemory]);
2873
+ assert!(runtime.tx.terminal().is_none());
2874
+ let history = &runtime
2875
+ .driver
2876
+ .engine()
2877
+ .unwrap()
2878
+ .ctx
2879
+ .partitions
2880
+ .history
2881
+ .messages;
2882
+ let result = history.iter().find_map(|message| {
2883
+ let Content::Parts(parts) = &message.content else {
2884
+ return None;
2885
+ };
2886
+ parts.iter().find_map(|part| match part {
2887
+ ContentPart::ToolResult {
2888
+ call_id, is_error, ..
2889
+ } if call_id == "call-2" => Some(*is_error),
2890
+ _ => None,
2891
+ })
2892
+ });
2893
+ assert_eq!(result, Some(!duplicate));
2894
+ assert!(crate::context::units::strict_tool_pairing_is_valid(history));
2895
+ let restored = Runtime::restore_with(None, &runtime.journal);
2896
+ assert_eq!(
2897
+ restored.pending_effect_kinds(),
2898
+ vec![EffectKindTag::QueryMemory]
2899
+ );
2900
+ let resumed = runtime.submit(&resolved(
2901
+ "in-recall-done",
2902
+ 1_700_000_003_000,
2903
+ &sole_effect(&queried).effect_id,
2904
+ EffectSuccess::MemoryQueried(MemoryQueriedSuccess { recalls: vec![] }),
2905
+ ));
2906
+ assert_eq!(kinds(&resumed), vec![EffectKindTag::CallProvider]);
2907
+ }
2908
+ }
2909
+
2910
+ #[test]
2911
+ fn workflow_focus_refusal_is_answered_to_the_model() {
2912
+ let (mut runtime, provider) = agent_awaiting_provider();
2913
+ // Exercise the focus guard independently of the active-DAG flatten path. A stale focus
2914
+ // must produce a model-visible denial rather than poison the whole provider resolution.
2915
+ runtime.driver.focus = Some(ExecutionFocus::workflow_controller(
2916
+ WorkflowId::new("existing-workflow").unwrap(),
2917
+ Some(root_task_id()),
2918
+ ));
2919
+ let resumed = runtime.submit(&provider_result(
2920
+ "in-second-workflow",
2921
+ 1_700_000_002_000,
2922
+ &provider,
2923
+ vec![tool_call(
2924
+ "call-1",
2925
+ "start_workflow",
2926
+ serde_json::to_value(two_node_spec()).unwrap(),
2927
+ )],
2928
+ ));
2929
+ assert_eq!(kinds(&resumed), vec![EffectKindTag::CallProvider]);
2930
+ assert!(runtime.tx.terminal().is_none());
2931
+ assert!(
2932
+ history_text(&runtime)
2933
+ .iter()
2934
+ .any(|text| text.contains("workflows do not stack"))
2935
+ );
2936
+ }
2937
+
2829
2938
  /// §7.6 + §15.3 · a provider turn that mixes an effect-publishing syscall (`memory`) with host
2830
2939
  /// tool calls publishes BOTH effects in one step — different kinds, so DEC-3 admits them
2831
2940
  /// together — and the host consumes them one pending effect at a time. Resolving the syscall's
@@ -3037,6 +3037,31 @@ fn build_engine(config: &ResolvedOperationConfig) -> LoopStateMachine {
3037
3037
  max_total_tokens: execution.max_total_tokens.get(),
3038
3038
  max_wall_ms: execution.max_wall_ms.map(WireU64::get),
3039
3039
  });
3040
+ let context = &config.context_policy;
3041
+ let thresholds = &context.pressure_thresholds_ppm;
3042
+ engine
3043
+ .ctx
3044
+ .apply_context_policy(&crate::context::policy::ContextPolicy {
3045
+ pressure_thresholds_ppm: crate::context::policy::PressureThresholdsPpm {
3046
+ snip: thresholds.snip.get(),
3047
+ micro: thresholds.micro.get(),
3048
+ collapse: thresholds.collapse.get(),
3049
+ auto: thresholds.auto.get(),
3050
+ renewal: thresholds.renewal.get(),
3051
+ },
3052
+ target_after_compress_ppm: context.target_after_compress_ppm.get(),
3053
+ preserve_recent_turns: context.preserve_recent_turns,
3054
+ renewal_carryover_ppm: context.renewal_carryover_ppm.get(),
3055
+ collapse_old_assistant_narration: context.collapse_old_assistant_narration,
3056
+ idle_micro_compact_minutes: context.idle_micro_compact_minutes,
3057
+ });
3058
+ engine
3059
+ .ctx
3060
+ .set_prompt_budget(crate::context::config::PromptBudgetConfig {
3061
+ prompt_overhead_tokens: context.prompt_budget.prompt_overhead_tokens,
3062
+ output_reserve_tokens: context.prompt_budget.output_reserve_tokens,
3063
+ safety_margin_tokens: context.prompt_budget.safety_margin_tokens,
3064
+ });
3040
3065
  if let Some(grant) = config.budget_grant.clone() {
3041
3066
  engine.set_budget_grant(grant);
3042
3067
  }
@@ -1152,6 +1152,25 @@ impl LoopStateMachine {
1152
1152
  );
1153
1153
  }
1154
1154
 
1155
+ // Preloaded transcripts are already durable in the host's session log. Compact them
1156
+ // before the first render instead of selecting a nearly full prompt while retaining the
1157
+ // entire oversized history internally. No archive effect may precede an agent's first
1158
+ // provider effect; the summary and the retained history are part of this atomic start.
1159
+ if self.session_history_baseline > 0 && self.ctx.rho() > self.ctx.config.snip_threshold {
1160
+ let action = crate::context::pressure::PressureAction::ContextCollapse;
1161
+ let (saved, summary, archived, invalidates_prefix_at) = self.ctx.compress(action);
1162
+ if saved > 0 || summary.is_some() {
1163
+ self.observations.push(KernelObservation::Compressed {
1164
+ turn: self.turn,
1165
+ action: action.into(),
1166
+ rho_after: self.ctx.rho(),
1167
+ summary,
1168
+ archived_count: archived.len() as u32,
1169
+ invalidates_prefix_at,
1170
+ });
1171
+ }
1172
+ self.session_history_baseline = self.ctx.partitions.history.messages.len();
1173
+ }
1155
1174
  let user_msg = "Proceed with the task described in [TASK STATE].".to_string();
1156
1175
 
1157
1176
  // User message goes into history so it appears at the correct chronological
@@ -6759,3 +6759,32 @@ fn spc_005_06_three_layer_grant_invariant_operation_to_a_to_a1_a2() {
6759
6759
  })
6760
6760
  );
6761
6761
  }
6762
+ #[test]
6763
+ fn preloaded_history_leaves_headroom_for_the_new_run() {
6764
+ let mut sm = LoopStateMachine::new(SchedulerBudget {
6765
+ max_tokens: 2_000,
6766
+ max_turns: 10,
6767
+ max_total_tokens: 100_000,
6768
+ max_wall_ms: None,
6769
+ });
6770
+ sm.ctx = crate::context::manager::ContextManager::with_config(
6771
+ 2_000,
6772
+ crate::context::config::ContextConfig::default(),
6773
+ crate::context::token_engine::ContextTokenEngine::char_approx(),
6774
+ );
6775
+ let messages = (0..40)
6776
+ .map(|i| CoreMessage::user(format!("turn {i}: {}", "detail ".repeat(40))))
6777
+ .collect();
6778
+ sm.preload_history(messages);
6779
+ let task = RuntimeTask::new("continue");
6780
+ sm.start(task);
6781
+ assert!(
6782
+ sm.ctx.partitions.total_tokens(&sm.ctx.engine) < 1_500,
6783
+ "preloaded history should compact toward 65%, not fill the next prompt"
6784
+ );
6785
+ assert!(
6786
+ sm.observations
6787
+ .iter()
6788
+ .any(|obs| matches!(obs, KernelObservation::Compressed { .. }))
6789
+ );
6790
+ }
@@ -4,7 +4,7 @@ build-backend = "maturin"
4
4
 
5
5
  [project]
6
6
  name = "deepstrike"
7
- version = "0.2.75"
7
+ version = "0.2.77"
8
8
  requires-python = ">=3.10"
9
9
  readme = "README.md"
10
10
  license = {file = "LICENSE"}
File without changes
File without changes