deepstrike 0.2.81__tar.gz → 0.2.83__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 (273) hide show
  1. {deepstrike-0.2.81 → deepstrike-0.2.83}/Cargo.lock +7 -7
  2. {deepstrike-0.2.81 → deepstrike-0.2.83}/Cargo.toml +3 -3
  3. {deepstrike-0.2.81 → deepstrike-0.2.83}/PKG-INFO +43 -2
  4. {deepstrike-0.2.81 → deepstrike-0.2.83}/README.md +42 -1
  5. deepstrike-0.2.83/crates/deepstrike-core/src/context/cache_ledger.rs +383 -0
  6. {deepstrike-0.2.81 → deepstrike-0.2.83}/crates/deepstrike-core/src/context/config.rs +5 -0
  7. {deepstrike-0.2.81 → deepstrike-0.2.83}/crates/deepstrike-core/src/context/fault.rs +2 -2
  8. {deepstrike-0.2.81 → deepstrike-0.2.83}/crates/deepstrike-core/src/context/item.rs +14 -1
  9. {deepstrike-0.2.81 → deepstrike-0.2.83}/crates/deepstrike-core/src/context/manager.rs +205 -1
  10. {deepstrike-0.2.81 → deepstrike-0.2.83}/crates/deepstrike-core/src/context/mod.rs +2 -0
  11. deepstrike-0.2.83/crates/deepstrike-core/src/context/notes.rs +442 -0
  12. {deepstrike-0.2.81 → deepstrike-0.2.83}/crates/deepstrike-core/src/context/policy.rs +9 -0
  13. {deepstrike-0.2.81 → deepstrike-0.2.83}/crates/deepstrike-core/src/context/renderer.rs +1 -1
  14. {deepstrike-0.2.81 → deepstrike-0.2.83}/crates/deepstrike-core/src/context/task_state.rs +98 -0
  15. {deepstrike-0.2.81 → deepstrike-0.2.83}/crates/deepstrike-core/src/runtime/kernel/observation.rs +18 -2
  16. {deepstrike-0.2.81 → deepstrike-0.2.83}/crates/deepstrike-core/src/runtime/kernel/wire/checkpoint.rs +32 -0
  17. {deepstrike-0.2.81 → deepstrike-0.2.83}/crates/deepstrike-core/src/runtime/kernel/wire/config.rs +12 -0
  18. {deepstrike-0.2.81 → deepstrike-0.2.83}/crates/deepstrike-core/src/runtime/kernel/wire/driver/projection.rs +1 -0
  19. {deepstrike-0.2.81 → deepstrike-0.2.83}/crates/deepstrike-core/src/runtime/kernel/wire/driver/syscall.rs +11 -0
  20. {deepstrike-0.2.81 → deepstrike-0.2.83}/crates/deepstrike-core/src/runtime/kernel/wire/driver/tests.rs +78 -0
  21. {deepstrike-0.2.81 → deepstrike-0.2.83}/crates/deepstrike-core/src/runtime/kernel/wire/driver.rs +47 -5
  22. {deepstrike-0.2.81 → deepstrike-0.2.83}/crates/deepstrike-core/src/runtime/kernel/wire/effect.rs +12 -1
  23. {deepstrike-0.2.81 → deepstrike-0.2.83}/crates/deepstrike-core/src/runtime/kernel/wire/syscall.rs +2 -0
  24. {deepstrike-0.2.81 → deepstrike-0.2.83}/crates/deepstrike-core/src/runtime/session.rs +15 -1
  25. {deepstrike-0.2.81 → deepstrike-0.2.83}/crates/deepstrike-core/src/scheduler/state_machine/mod.rs +6 -1
  26. {deepstrike-0.2.81 → deepstrike-0.2.83}/deepstrike/providers/ollama_adapter.py +13 -2
  27. {deepstrike-0.2.81 → deepstrike-0.2.83}/deepstrike/providers/openai_chat_adapter.py +74 -7
  28. {deepstrike-0.2.81 → deepstrike-0.2.83}/deepstrike/providers/runtime_registry.py +3 -0
  29. deepstrike-0.2.83/deepstrike/providers/text_tool_calls.py +103 -0
  30. {deepstrike-0.2.81 → deepstrike-0.2.83}/deepstrike/runtime/_session_event_registry.py +1 -1
  31. {deepstrike-0.2.81 → deepstrike-0.2.83}/deepstrike/runtime/context_policy.py +7 -0
  32. {deepstrike-0.2.81 → deepstrike-0.2.83}/deepstrike/runtime/filtered_plane.py +1 -1
  33. {deepstrike-0.2.81 → deepstrike-0.2.83}/deepstrike/runtime/kernel_event_log.py +3 -2
  34. {deepstrike-0.2.81 → deepstrike-0.2.83}/deepstrike/runtime/session_log.py +19 -1
  35. {deepstrike-0.2.81 → deepstrike-0.2.83}/pyproject.toml +1 -1
  36. {deepstrike-0.2.81 → deepstrike-0.2.83}/LICENSE +0 -0
  37. {deepstrike-0.2.81 → deepstrike-0.2.83}/crates/deepstrike-core/Cargo.toml +0 -0
  38. {deepstrike-0.2.81 → deepstrike-0.2.83}/crates/deepstrike-core/LICENSE +0 -0
  39. {deepstrike-0.2.81 → deepstrike-0.2.83}/crates/deepstrike-core/benches/kernel_baseline.rs +0 -0
  40. {deepstrike-0.2.81 → deepstrike-0.2.83}/crates/deepstrike-core/benches/wait_index_baseline.rs +0 -0
  41. {deepstrike-0.2.81 → deepstrike-0.2.83}/crates/deepstrike-core/src/benchmark/mod.rs +0 -0
  42. {deepstrike-0.2.81 → deepstrike-0.2.83}/crates/deepstrike-core/src/context/compression.rs +0 -0
  43. {deepstrike-0.2.81 → deepstrike-0.2.83}/crates/deepstrike-core/src/context/graph.rs +0 -0
  44. {deepstrike-0.2.81 → deepstrike-0.2.83}/crates/deepstrike-core/src/context/measurement.rs +0 -0
  45. {deepstrike-0.2.81 → deepstrike-0.2.83}/crates/deepstrike-core/src/context/partitions.rs +0 -0
  46. {deepstrike-0.2.81 → deepstrike-0.2.83}/crates/deepstrike-core/src/context/pressure.rs +0 -0
  47. {deepstrike-0.2.81 → deepstrike-0.2.83}/crates/deepstrike-core/src/context/renewal.rs +0 -0
  48. {deepstrike-0.2.81 → deepstrike-0.2.83}/crates/deepstrike-core/src/context/skill_catalog.rs +0 -0
  49. {deepstrike-0.2.81 → deepstrike-0.2.83}/crates/deepstrike-core/src/context/summarizer.rs +0 -0
  50. {deepstrike-0.2.81 → deepstrike-0.2.83}/crates/deepstrike-core/src/context/text.rs +0 -0
  51. {deepstrike-0.2.81 → deepstrike-0.2.83}/crates/deepstrike-core/src/context/token_engine.rs +0 -0
  52. {deepstrike-0.2.81 → deepstrike-0.2.83}/crates/deepstrike-core/src/context/units.rs +0 -0
  53. {deepstrike-0.2.81 → deepstrike-0.2.83}/crates/deepstrike-core/src/context/utility.rs +0 -0
  54. {deepstrike-0.2.81 → deepstrike-0.2.83}/crates/deepstrike-core/src/governance/constraint.rs +0 -0
  55. {deepstrike-0.2.81 → deepstrike-0.2.83}/crates/deepstrike-core/src/governance/mod.rs +0 -0
  56. {deepstrike-0.2.81 → deepstrike-0.2.83}/crates/deepstrike-core/src/governance/permission.rs +0 -0
  57. {deepstrike-0.2.81 → deepstrike-0.2.83}/crates/deepstrike-core/src/governance/pipeline.rs +0 -0
  58. {deepstrike-0.2.81 → deepstrike-0.2.83}/crates/deepstrike-core/src/governance/quota.rs +0 -0
  59. {deepstrike-0.2.81 → deepstrike-0.2.83}/crates/deepstrike-core/src/governance/rate_limit.rs +0 -0
  60. {deepstrike-0.2.81 → deepstrike-0.2.83}/crates/deepstrike-core/src/governance/repeat_fuse.rs +0 -0
  61. {deepstrike-0.2.81 → deepstrike-0.2.83}/crates/deepstrike-core/src/governance/veto.rs +0 -0
  62. {deepstrike-0.2.81 → deepstrike-0.2.83}/crates/deepstrike-core/src/harness/eval.rs +0 -0
  63. {deepstrike-0.2.81 → deepstrike-0.2.83}/crates/deepstrike-core/src/harness/mod.rs +0 -0
  64. {deepstrike-0.2.81 → deepstrike-0.2.83}/crates/deepstrike-core/src/lexical.rs +0 -0
  65. {deepstrike-0.2.81 → deepstrike-0.2.83}/crates/deepstrike-core/src/lib.rs +0 -0
  66. {deepstrike-0.2.81 → deepstrike-0.2.83}/crates/deepstrike-core/src/memory/curator.rs +0 -0
  67. {deepstrike-0.2.81 → deepstrike-0.2.83}/crates/deepstrike-core/src/memory/durable.rs +0 -0
  68. {deepstrike-0.2.81 → deepstrike-0.2.83}/crates/deepstrike-core/src/memory/mod.rs +0 -0
  69. {deepstrike-0.2.81 → deepstrike-0.2.83}/crates/deepstrike-core/src/mm/handle.rs +0 -0
  70. {deepstrike-0.2.81 → deepstrike-0.2.83}/crates/deepstrike-core/src/mm/memory.rs +0 -0
  71. {deepstrike-0.2.81 → deepstrike-0.2.83}/crates/deepstrike-core/src/mm/memory_candidate.rs +0 -0
  72. {deepstrike-0.2.81 → deepstrike-0.2.83}/crates/deepstrike-core/src/mm/mod.rs +0 -0
  73. {deepstrike-0.2.81 → deepstrike-0.2.83}/crates/deepstrike-core/src/mm/value.rs +0 -0
  74. {deepstrike-0.2.81 → deepstrike-0.2.83}/crates/deepstrike-core/src/orchestration/mod.rs +0 -0
  75. {deepstrike-0.2.81 → deepstrike-0.2.83}/crates/deepstrike-core/src/orchestration/task_graph.rs +0 -0
  76. {deepstrike-0.2.81 → deepstrike-0.2.83}/crates/deepstrike-core/src/orchestration/workflow/mod.rs +0 -0
  77. {deepstrike-0.2.81 → deepstrike-0.2.83}/crates/deepstrike-core/src/orchestration/workflow/run.rs +0 -0
  78. {deepstrike-0.2.81 → deepstrike-0.2.83}/crates/deepstrike-core/src/proc/mod.rs +0 -0
  79. {deepstrike-0.2.81 → deepstrike-0.2.83}/crates/deepstrike-core/src/projection_pairs.rs +0 -0
  80. {deepstrike-0.2.81 → deepstrike-0.2.83}/crates/deepstrike-core/src/runtime/event_log.rs +0 -0
  81. {deepstrike-0.2.81 → deepstrike-0.2.83}/crates/deepstrike-core/src/runtime/kernel/wire/binding.rs +0 -0
  82. {deepstrike-0.2.81 → deepstrike-0.2.83}/crates/deepstrike-core/src/runtime/kernel/wire/command.rs +0 -0
  83. {deepstrike-0.2.81 → deepstrike-0.2.83}/crates/deepstrike-core/src/runtime/kernel/wire/crash_point.rs +0 -0
  84. {deepstrike-0.2.81 → deepstrike-0.2.83}/crates/deepstrike-core/src/runtime/kernel/wire/driver/continuation.rs +0 -0
  85. {deepstrike-0.2.81 → deepstrike-0.2.83}/crates/deepstrike-core/src/runtime/kernel/wire/driver/effects.rs +0 -0
  86. {deepstrike-0.2.81 → deepstrike-0.2.83}/crates/deepstrike-core/src/runtime/kernel/wire/driver/events.rs +0 -0
  87. {deepstrike-0.2.81 → deepstrike-0.2.83}/crates/deepstrike-core/src/runtime/kernel/wire/driver/planning.rs +0 -0
  88. {deepstrike-0.2.81 → deepstrike-0.2.83}/crates/deepstrike-core/src/runtime/kernel/wire/driver/provider.rs +0 -0
  89. {deepstrike-0.2.81 → deepstrike-0.2.83}/crates/deepstrike-core/src/runtime/kernel/wire/envelope.rs +0 -0
  90. {deepstrike-0.2.81 → deepstrike-0.2.83}/crates/deepstrike-core/src/runtime/kernel/wire/event.rs +0 -0
  91. {deepstrike-0.2.81 → deepstrike-0.2.83}/crates/deepstrike-core/src/runtime/kernel/wire/fault.rs +0 -0
  92. {deepstrike-0.2.81 → deepstrike-0.2.83}/crates/deepstrike-core/src/runtime/kernel/wire/memory_authority.rs +0 -0
  93. {deepstrike-0.2.81 → deepstrike-0.2.83}/crates/deepstrike-core/src/runtime/kernel/wire/projection.rs +0 -0
  94. {deepstrike-0.2.81 → deepstrike-0.2.83}/crates/deepstrike-core/src/runtime/kernel/wire/record.rs +0 -0
  95. {deepstrike-0.2.81 → deepstrike-0.2.83}/crates/deepstrike-core/src/runtime/kernel/wire/restore.rs +0 -0
  96. {deepstrike-0.2.81 → deepstrike-0.2.83}/crates/deepstrike-core/src/runtime/kernel/wire/root.rs +0 -0
  97. {deepstrike-0.2.81 → deepstrike-0.2.83}/crates/deepstrike-core/src/runtime/kernel/wire/scalar.rs +0 -0
  98. {deepstrike-0.2.81 → deepstrike-0.2.83}/crates/deepstrike-core/src/runtime/kernel/wire/terminal.rs +0 -0
  99. {deepstrike-0.2.81 → deepstrike-0.2.83}/crates/deepstrike-core/src/runtime/kernel/wire/tests.rs +0 -0
  100. {deepstrike-0.2.81 → deepstrike-0.2.83}/crates/deepstrike-core/src/runtime/kernel/wire/transaction.rs +0 -0
  101. {deepstrike-0.2.81 → deepstrike-0.2.83}/crates/deepstrike-core/src/runtime/kernel/wire.rs +0 -0
  102. {deepstrike-0.2.81 → deepstrike-0.2.83}/crates/deepstrike-core/src/runtime/kernel.rs +0 -0
  103. {deepstrike-0.2.81 → deepstrike-0.2.83}/crates/deepstrike-core/src/runtime/mod.rs +0 -0
  104. {deepstrike-0.2.81 → deepstrike-0.2.83}/crates/deepstrike-core/src/runtime/repair.rs +0 -0
  105. {deepstrike-0.2.81 → deepstrike-0.2.83}/crates/deepstrike-core/src/runtime/replay.rs +0 -0
  106. {deepstrike-0.2.81 → deepstrike-0.2.83}/crates/deepstrike-core/src/runtime/session_registry_tests.rs +0 -0
  107. {deepstrike-0.2.81 → deepstrike-0.2.83}/crates/deepstrike-core/src/runtime/session_wire.rs +0 -0
  108. {deepstrike-0.2.81 → deepstrike-0.2.83}/crates/deepstrike-core/src/scheduler/budget_grant.rs +0 -0
  109. {deepstrike-0.2.81 → deepstrike-0.2.83}/crates/deepstrike-core/src/scheduler/cross_operation.rs +0 -0
  110. {deepstrike-0.2.81 → deepstrike-0.2.83}/crates/deepstrike-core/src/scheduler/entropy.rs +0 -0
  111. {deepstrike-0.2.81 → deepstrike-0.2.83}/crates/deepstrike-core/src/scheduler/mailbox.rs +0 -0
  112. {deepstrike-0.2.81 → deepstrike-0.2.83}/crates/deepstrike-core/src/scheduler/milestone.rs +0 -0
  113. {deepstrike-0.2.81 → deepstrike-0.2.83}/crates/deepstrike-core/src/scheduler/mod.rs +0 -0
  114. {deepstrike-0.2.81 → deepstrike-0.2.83}/crates/deepstrike-core/src/scheduler/policy.rs +0 -0
  115. {deepstrike-0.2.81 → deepstrike-0.2.83}/crates/deepstrike-core/src/scheduler/rollback.rs +0 -0
  116. {deepstrike-0.2.81 → deepstrike-0.2.83}/crates/deepstrike-core/src/scheduler/runnable.rs +0 -0
  117. {deepstrike-0.2.81 → deepstrike-0.2.83}/crates/deepstrike-core/src/scheduler/state_machine/cancellation.rs +0 -0
  118. {deepstrike-0.2.81 → deepstrike-0.2.83}/crates/deepstrike-core/src/scheduler/state_machine/capability.rs +0 -0
  119. {deepstrike-0.2.81 → deepstrike-0.2.83}/crates/deepstrike-core/src/scheduler/state_machine/eviction.rs +0 -0
  120. {deepstrike-0.2.81 → deepstrike-0.2.83}/crates/deepstrike-core/src/scheduler/state_machine/gate.rs +0 -0
  121. {deepstrike-0.2.81 → deepstrike-0.2.83}/crates/deepstrike-core/src/scheduler/state_machine/milestone_exec.rs +0 -0
  122. {deepstrike-0.2.81 → deepstrike-0.2.83}/crates/deepstrike-core/src/scheduler/state_machine/process.rs +0 -0
  123. {deepstrike-0.2.81 → deepstrike-0.2.83}/crates/deepstrike-core/src/scheduler/state_machine/signal.rs +0 -0
  124. {deepstrike-0.2.81 → deepstrike-0.2.83}/crates/deepstrike-core/src/scheduler/state_machine/tests.rs +0 -0
  125. {deepstrike-0.2.81 → deepstrike-0.2.83}/crates/deepstrike-core/src/scheduler/state_machine/workflow.rs +0 -0
  126. {deepstrike-0.2.81 → deepstrike-0.2.83}/crates/deepstrike-core/src/scheduler/tcb.rs +0 -0
  127. {deepstrike-0.2.81 → deepstrike-0.2.83}/crates/deepstrike-core/src/scheduler/wait_index.rs +0 -0
  128. {deepstrike-0.2.81 → deepstrike-0.2.83}/crates/deepstrike-core/src/signals/attention.rs +0 -0
  129. {deepstrike-0.2.81 → deepstrike-0.2.83}/crates/deepstrike-core/src/signals/mod.rs +0 -0
  130. {deepstrike-0.2.81 → deepstrike-0.2.83}/crates/deepstrike-core/src/signals/queue.rs +0 -0
  131. {deepstrike-0.2.81 → deepstrike-0.2.83}/crates/deepstrike-core/src/signals/router.rs +0 -0
  132. {deepstrike-0.2.81 → deepstrike-0.2.83}/crates/deepstrike-core/src/syscall/mod.rs +0 -0
  133. {deepstrike-0.2.81 → deepstrike-0.2.83}/crates/deepstrike-core/src/types/agent.rs +0 -0
  134. {deepstrike-0.2.81 → deepstrike-0.2.83}/crates/deepstrike-core/src/types/capability.rs +0 -0
  135. {deepstrike-0.2.81 → deepstrike-0.2.83}/crates/deepstrike-core/src/types/contract.rs +0 -0
  136. {deepstrike-0.2.81 → deepstrike-0.2.83}/crates/deepstrike-core/src/types/durable_content.rs +0 -0
  137. {deepstrike-0.2.81 → deepstrike-0.2.83}/crates/deepstrike-core/src/types/error.rs +0 -0
  138. {deepstrike-0.2.81 → deepstrike-0.2.83}/crates/deepstrike-core/src/types/message.rs +0 -0
  139. {deepstrike-0.2.81 → deepstrike-0.2.83}/crates/deepstrike-core/src/types/milestone.rs +0 -0
  140. {deepstrike-0.2.81 → deepstrike-0.2.83}/crates/deepstrike-core/src/types/mod.rs +0 -0
  141. {deepstrike-0.2.81 → deepstrike-0.2.83}/crates/deepstrike-core/src/types/policy.rs +0 -0
  142. {deepstrike-0.2.81 → deepstrike-0.2.83}/crates/deepstrike-core/src/types/result.rs +0 -0
  143. {deepstrike-0.2.81 → deepstrike-0.2.83}/crates/deepstrike-core/src/types/signal.rs +0 -0
  144. {deepstrike-0.2.81 → deepstrike-0.2.83}/crates/deepstrike-core/src/types/skill.rs +0 -0
  145. {deepstrike-0.2.81 → deepstrike-0.2.83}/crates/deepstrike-core/src/types/task.rs +0 -0
  146. {deepstrike-0.2.81 → deepstrike-0.2.83}/crates/deepstrike-py/Cargo.toml +0 -0
  147. {deepstrike-0.2.81 → deepstrike-0.2.83}/crates/deepstrike-py/LICENSE +0 -0
  148. {deepstrike-0.2.81 → deepstrike-0.2.83}/crates/deepstrike-py/src/lib.rs +0 -0
  149. {deepstrike-0.2.81 → deepstrike-0.2.83}/crates/deepstrike-tokenizer/Cargo.toml +0 -0
  150. {deepstrike-0.2.81 → deepstrike-0.2.83}/crates/deepstrike-tokenizer/LICENSE +0 -0
  151. {deepstrike-0.2.81 → deepstrike-0.2.83}/crates/deepstrike-tokenizer/src/lib.rs +0 -0
  152. {deepstrike-0.2.81 → deepstrike-0.2.83}/deepstrike/__init__.py +0 -0
  153. {deepstrike-0.2.81 → deepstrike-0.2.83}/deepstrike/agent.py +0 -0
  154. {deepstrike-0.2.81 → deepstrike-0.2.83}/deepstrike/collaboration/__init__.py +0 -0
  155. {deepstrike-0.2.81 → deepstrike-0.2.83}/deepstrike/collaboration/contract.py +0 -0
  156. {deepstrike-0.2.81 → deepstrike-0.2.83}/deepstrike/collaboration/handoff.py +0 -0
  157. {deepstrike-0.2.81 → deepstrike-0.2.83}/deepstrike/collaboration/harness.py +0 -0
  158. {deepstrike-0.2.81 → deepstrike-0.2.83}/deepstrike/collaboration/modes.py +0 -0
  159. {deepstrike-0.2.81 → deepstrike-0.2.83}/deepstrike/collaboration/pool.py +0 -0
  160. {deepstrike-0.2.81 → deepstrike-0.2.83}/deepstrike/governance.py +0 -0
  161. {deepstrike-0.2.81 → deepstrike-0.2.83}/deepstrike/harness/__init__.py +0 -0
  162. {deepstrike-0.2.81 → deepstrike-0.2.83}/deepstrike/harness/harness.py +0 -0
  163. {deepstrike-0.2.81 → deepstrike-0.2.83}/deepstrike/harness/judge.py +0 -0
  164. {deepstrike-0.2.81 → deepstrike-0.2.83}/deepstrike/kernel/__init__.py +0 -0
  165. {deepstrike-0.2.81 → deepstrike-0.2.83}/deepstrike/kernel/canonical.py +0 -0
  166. {deepstrike-0.2.81 → deepstrike-0.2.83}/deepstrike/knowledge/__init__.py +0 -0
  167. {deepstrike-0.2.81 → deepstrike-0.2.83}/deepstrike/knowledge/source.py +0 -0
  168. {deepstrike-0.2.81 → deepstrike-0.2.83}/deepstrike/memory/__init__.py +0 -0
  169. {deepstrike-0.2.81 → deepstrike-0.2.83}/deepstrike/memory/agent.py +0 -0
  170. {deepstrike-0.2.81 → deepstrike-0.2.83}/deepstrike/memory/attestation.py +0 -0
  171. {deepstrike-0.2.81 → deepstrike-0.2.83}/deepstrike/memory/authority.py +0 -0
  172. {deepstrike-0.2.81 → deepstrike-0.2.83}/deepstrike/memory/candidate_sink.py +0 -0
  173. {deepstrike-0.2.81 → deepstrike-0.2.83}/deepstrike/memory/durable.py +0 -0
  174. {deepstrike-0.2.81 → deepstrike-0.2.83}/deepstrike/memory/durable_candidate_sink.py +0 -0
  175. {deepstrike-0.2.81 → deepstrike-0.2.83}/deepstrike/memory/durable_lifecycle_store.py +0 -0
  176. {deepstrike-0.2.81 → deepstrike-0.2.83}/deepstrike/memory/in_memory_store.py +0 -0
  177. {deepstrike-0.2.81 → deepstrike-0.2.83}/deepstrike/memory/lifecycle.py +0 -0
  178. {deepstrike-0.2.81 → deepstrike-0.2.83}/deepstrike/memory/protocols.py +0 -0
  179. {deepstrike-0.2.81 → deepstrike-0.2.83}/deepstrike/memory/ranking.py +0 -0
  180. {deepstrike-0.2.81 → deepstrike-0.2.83}/deepstrike/memory/recall_projection.py +0 -0
  181. {deepstrike-0.2.81 → deepstrike-0.2.83}/deepstrike/memory/retention.py +0 -0
  182. {deepstrike-0.2.81 → deepstrike-0.2.83}/deepstrike/memory/runtime_policy.py +0 -0
  183. {deepstrike-0.2.81 → deepstrike-0.2.83}/deepstrike/memory/working.py +0 -0
  184. {deepstrike-0.2.81 → deepstrike-0.2.83}/deepstrike/memory/writer.py +0 -0
  185. {deepstrike-0.2.81 → deepstrike-0.2.83}/deepstrike/providers/__init__.py +0 -0
  186. {deepstrike-0.2.81 → deepstrike-0.2.83}/deepstrike/providers/anthropic.py +0 -0
  187. {deepstrike-0.2.81 → deepstrike-0.2.83}/deepstrike/providers/anthropic_adapter.py +0 -0
  188. {deepstrike-0.2.81 → deepstrike-0.2.83}/deepstrike/providers/anthropic_compaction.py +0 -0
  189. {deepstrike-0.2.81 → deepstrike-0.2.83}/deepstrike/providers/anthropic_compatible.py +0 -0
  190. {deepstrike-0.2.81 → deepstrike-0.2.83}/deepstrike/providers/base.py +0 -0
  191. {deepstrike-0.2.81 → deepstrike-0.2.83}/deepstrike/providers/capability_router.py +0 -0
  192. {deepstrike-0.2.81 → deepstrike-0.2.83}/deepstrike/providers/credentials.py +0 -0
  193. {deepstrike-0.2.81 → deepstrike-0.2.83}/deepstrike/providers/embedding.py +0 -0
  194. {deepstrike-0.2.81 → deepstrike-0.2.83}/deepstrike/providers/factories.py +0 -0
  195. {deepstrike-0.2.81 → deepstrike-0.2.83}/deepstrike/providers/fallback.py +0 -0
  196. {deepstrike-0.2.81 → deepstrike-0.2.83}/deepstrike/providers/gemini.py +0 -0
  197. {deepstrike-0.2.81 → deepstrike-0.2.83}/deepstrike/providers/gemini_adapter.py +0 -0
  198. {deepstrike-0.2.81 → deepstrike-0.2.83}/deepstrike/providers/model_catalog.py +0 -0
  199. {deepstrike-0.2.81 → deepstrike-0.2.83}/deepstrike/providers/model_registry.py +0 -0
  200. {deepstrike-0.2.81 → deepstrike-0.2.83}/deepstrike/providers/ollama.py +0 -0
  201. {deepstrike-0.2.81 → deepstrike-0.2.83}/deepstrike/providers/openai.py +0 -0
  202. {deepstrike-0.2.81 → deepstrike-0.2.83}/deepstrike/providers/openai_responses.py +0 -0
  203. {deepstrike-0.2.81 → deepstrike-0.2.83}/deepstrike/providers/prepared_request.py +0 -0
  204. {deepstrike-0.2.81 → deepstrike-0.2.83}/deepstrike/providers/protocol_adapter.py +0 -0
  205. {deepstrike-0.2.81 → deepstrike-0.2.83}/deepstrike/providers/protocols.py +0 -0
  206. {deepstrike-0.2.81 → deepstrike-0.2.83}/deepstrike/providers/provider_error.py +0 -0
  207. {deepstrike-0.2.81 → deepstrike-0.2.83}/deepstrike/providers/qwen.py +0 -0
  208. {deepstrike-0.2.81 → deepstrike-0.2.83}/deepstrike/providers/replay.py +0 -0
  209. {deepstrike-0.2.81 → deepstrike-0.2.83}/deepstrike/providers/replay_validator.py +0 -0
  210. {deepstrike-0.2.81 → deepstrike-0.2.83}/deepstrike/providers/request_plan.py +0 -0
  211. {deepstrike-0.2.81 → deepstrike-0.2.83}/deepstrike/providers/stop_reason.py +0 -0
  212. {deepstrike-0.2.81 → deepstrike-0.2.83}/deepstrike/providers/stream.py +0 -0
  213. {deepstrike-0.2.81 → deepstrike-0.2.83}/deepstrike/providers/usage.py +0 -0
  214. {deepstrike-0.2.81 → deepstrike-0.2.83}/deepstrike/providers/vendor_profiles.py +0 -0
  215. {deepstrike-0.2.81 → deepstrike-0.2.83}/deepstrike/runtime/__init__.py +0 -0
  216. {deepstrike-0.2.81 → deepstrike-0.2.83}/deepstrike/runtime/agent_declaration.py +0 -0
  217. {deepstrike-0.2.81 → deepstrike-0.2.83}/deepstrike/runtime/archive.py +0 -0
  218. {deepstrike-0.2.81 → deepstrike-0.2.83}/deepstrike/runtime/canonical_kernel_step.py +0 -0
  219. {deepstrike-0.2.81 → deepstrike-0.2.83}/deepstrike/runtime/credential_vault.py +0 -0
  220. {deepstrike-0.2.81 → deepstrike-0.2.83}/deepstrike/runtime/durable_content.py +0 -0
  221. {deepstrike-0.2.81 → deepstrike-0.2.83}/deepstrike/runtime/dynamic_workflow.py +0 -0
  222. {deepstrike-0.2.81 → deepstrike-0.2.83}/deepstrike/runtime/eval.py +0 -0
  223. {deepstrike-0.2.81 → deepstrike-0.2.83}/deepstrike/runtime/eval_dataset.py +0 -0
  224. {deepstrike-0.2.81 → deepstrike-0.2.83}/deepstrike/runtime/event_stream.py +0 -0
  225. {deepstrike-0.2.81 → deepstrike-0.2.83}/deepstrike/runtime/execution_evidence.py +0 -0
  226. {deepstrike-0.2.81 → deepstrike-0.2.83}/deepstrike/runtime/execution_plane.py +0 -0
  227. {deepstrike-0.2.81 → deepstrike-0.2.83}/deepstrike/runtime/facade.py +0 -0
  228. {deepstrike-0.2.81 → deepstrike-0.2.83}/deepstrike/runtime/kernel_journal.py +0 -0
  229. {deepstrike-0.2.81 → deepstrike-0.2.83}/deepstrike/runtime/kernel_step.py +0 -0
  230. {deepstrike-0.2.81 → deepstrike-0.2.83}/deepstrike/runtime/loop_driver.py +0 -0
  231. {deepstrike-0.2.81 → deepstrike-0.2.83}/deepstrike/runtime/mcp_proxy_plane.py +0 -0
  232. {deepstrike-0.2.81 → deepstrike-0.2.83}/deepstrike/runtime/os_profile.py +0 -0
  233. {deepstrike-0.2.81 → deepstrike-0.2.83}/deepstrike/runtime/os_snapshot.py +0 -0
  234. {deepstrike-0.2.81 → deepstrike-0.2.83}/deepstrike/runtime/output_schema.py +0 -0
  235. {deepstrike-0.2.81 → deepstrike-0.2.83}/deepstrike/runtime/payload_store.py +0 -0
  236. {deepstrike-0.2.81 → deepstrike-0.2.83}/deepstrike/runtime/process_sandbox_plane.py +0 -0
  237. {deepstrike-0.2.81 → deepstrike-0.2.83}/deepstrike/runtime/provider_replay.py +0 -0
  238. {deepstrike-0.2.81 → deepstrike-0.2.83}/deepstrike/runtime/reaction_checkpoint.py +0 -0
  239. {deepstrike-0.2.81 → deepstrike-0.2.83}/deepstrike/runtime/reactive_session.py +0 -0
  240. {deepstrike-0.2.81 → deepstrike-0.2.83}/deepstrike/runtime/reliability.py +0 -0
  241. {deepstrike-0.2.81 → deepstrike-0.2.83}/deepstrike/runtime/remote_vpc_plane.py +0 -0
  242. {deepstrike-0.2.81 → deepstrike-0.2.83}/deepstrike/runtime/replay_fixture.py +0 -0
  243. {deepstrike-0.2.81 → deepstrike-0.2.83}/deepstrike/runtime/replay_provider.py +0 -0
  244. {deepstrike-0.2.81 → deepstrike-0.2.83}/deepstrike/runtime/replay_sanitize.py +0 -0
  245. {deepstrike-0.2.81 → deepstrike-0.2.83}/deepstrike/runtime/run_group.py +0 -0
  246. {deepstrike-0.2.81 → deepstrike-0.2.83}/deepstrike/runtime/runner.py +0 -0
  247. {deepstrike-0.2.81 → deepstrike-0.2.83}/deepstrike/runtime/session_repair.py +0 -0
  248. {deepstrike-0.2.81 → deepstrike-0.2.83}/deepstrike/runtime/sub_agent_orchestrator.py +0 -0
  249. {deepstrike-0.2.81 → deepstrike-0.2.83}/deepstrike/runtime/tool_arguments.py +0 -0
  250. {deepstrike-0.2.81 → deepstrike-0.2.83}/deepstrike/runtime/turn_policy.py +0 -0
  251. {deepstrike-0.2.81 → deepstrike-0.2.83}/deepstrike/runtime/workflow_replay.py +0 -0
  252. {deepstrike-0.2.81 → deepstrike-0.2.83}/deepstrike/runtime/workflow_store.py +0 -0
  253. {deepstrike-0.2.81 → deepstrike-0.2.83}/deepstrike/runtime/worktree_plane.py +0 -0
  254. {deepstrike-0.2.81 → deepstrike-0.2.83}/deepstrike/safety/__init__.py +0 -0
  255. {deepstrike-0.2.81 → deepstrike-0.2.83}/deepstrike/safety/permissions.py +0 -0
  256. {deepstrike-0.2.81 → deepstrike-0.2.83}/deepstrike/signals/__init__.py +0 -0
  257. {deepstrike-0.2.81 → deepstrike-0.2.83}/deepstrike/signals/gateway.py +0 -0
  258. {deepstrike-0.2.81 → deepstrike-0.2.83}/deepstrike/signals/scheduled.py +0 -0
  259. {deepstrike-0.2.81 → deepstrike-0.2.83}/deepstrike/signals/types.py +0 -0
  260. {deepstrike-0.2.81 → deepstrike-0.2.83}/deepstrike/skills/__init__.py +0 -0
  261. {deepstrike-0.2.81 → deepstrike-0.2.83}/deepstrike/skills/loader.py +0 -0
  262. {deepstrike-0.2.81 → deepstrike-0.2.83}/deepstrike/skills/registry.py +0 -0
  263. {deepstrike-0.2.81 → deepstrike-0.2.83}/deepstrike/skills/watcher.py +0 -0
  264. {deepstrike-0.2.81 → deepstrike-0.2.83}/deepstrike/tools/__init__.py +0 -0
  265. {deepstrike-0.2.81 → deepstrike-0.2.83}/deepstrike/tools/builtin/__init__.py +0 -0
  266. {deepstrike-0.2.81 → deepstrike-0.2.83}/deepstrike/tools/builtin/read_file.py +0 -0
  267. {deepstrike-0.2.81 → deepstrike-0.2.83}/deepstrike/tools/errors.py +0 -0
  268. {deepstrike-0.2.81 → deepstrike-0.2.83}/deepstrike/tools/execution.py +0 -0
  269. {deepstrike-0.2.81 → deepstrike-0.2.83}/deepstrike/tools/registry.py +0 -0
  270. {deepstrike-0.2.81 → deepstrike-0.2.83}/deepstrike/types/__init__.py +0 -0
  271. {deepstrike-0.2.81 → deepstrike-0.2.83}/deepstrike/types/agent.py +0 -0
  272. {deepstrike-0.2.81 → deepstrike-0.2.83}/deepstrike/types/content.py +0 -0
  273. {deepstrike-0.2.81 → deepstrike-0.2.83}/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.81"
296
+ version = "0.2.83"
297
297
  dependencies = [
298
298
  "compact_str",
299
299
  "deepstrike-tokenizer",
@@ -307,7 +307,7 @@ dependencies = [
307
307
 
308
308
  [[package]]
309
309
  name = "deepstrike-lab"
310
- version = "0.2.81"
310
+ version = "0.2.83"
311
311
  dependencies = [
312
312
  "serde",
313
313
  "serde_json",
@@ -315,7 +315,7 @@ dependencies = [
315
315
 
316
316
  [[package]]
317
317
  name = "deepstrike-node"
318
- version = "0.2.81"
318
+ version = "0.2.83"
319
319
  dependencies = [
320
320
  "compact_str",
321
321
  "deepstrike-core",
@@ -327,7 +327,7 @@ dependencies = [
327
327
 
328
328
  [[package]]
329
329
  name = "deepstrike-py"
330
- version = "0.2.81"
330
+ version = "0.2.83"
331
331
  dependencies = [
332
332
  "compact_str",
333
333
  "deepstrike-core",
@@ -338,7 +338,7 @@ dependencies = [
338
338
 
339
339
  [[package]]
340
340
  name = "deepstrike-sdk"
341
- version = "0.2.81"
341
+ version = "0.2.83"
342
342
  dependencies = [
343
343
  "async-stream",
344
344
  "async-trait",
@@ -376,7 +376,7 @@ dependencies = [
376
376
 
377
377
  [[package]]
378
378
  name = "deepstrike-tokenizer"
379
- version = "0.2.81"
379
+ version = "0.2.83"
380
380
  dependencies = [
381
381
  "pretty_assertions",
382
382
  "tiktoken-rs",
@@ -384,7 +384,7 @@ dependencies = [
384
384
 
385
385
  [[package]]
386
386
  name = "deepstrike-wasm"
387
- version = "0.2.81"
387
+ version = "0.2.83"
388
388
  dependencies = [
389
389
  "compact_str",
390
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.81"
6
+ version = "0.2.83"
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.81" }
12
- deepstrike-tokenizer = { path = "crates/deepstrike-tokenizer", version = "0.2.81" }
11
+ deepstrike-core = { path = "crates/deepstrike-core", version = "0.2.83" }
12
+ deepstrike-tokenizer = { path = "crates/deepstrike-tokenizer", version = "0.2.83" }
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.81
3
+ Version: 0.2.83
4
4
  Requires-Dist: httpx>=0.27
5
5
  Requires-Dist: pyyaml>=6.0
6
6
  Requires-Dist: anyio>=4.0
@@ -250,7 +250,7 @@ The kernel renders context as four LLM API slots — only **history** is compres
250
250
  |------|--------|------|
251
251
  | `system_stable` | system partition | Identity, rules — never changes within a run |
252
252
  | `system_knowledge` | knowledge partition | Preloaded memory, skill defs — low frequency |
253
- | `turns[0]` | `task_state` + signals | Goal, plan, progress, compression log, runtime signals |
253
+ | `turns[0]` | `task_state` + signals | Goal, plan, progress, the model's notes, compression log, runtime signals |
254
254
  | `turns[1..N]` | history | Conversation transcript |
255
255
 
256
256
  ```python
@@ -268,6 +268,47 @@ Full reference: [docs/concepts/context-slots-compression.md](../docs/concepts/co
268
268
 
269
269
  ---
270
270
 
271
+ ## Notes and model-proposed memory (0.2.82)
272
+
273
+ The model decides what is worth keeping; the kernel keeps it.
274
+
275
+ - **Notes.** Every request carries a `note` tool. The model writes, rewrites and retires notes — a
276
+ running count, what is done, a rule it learned. Notes render in the state turn (`notes:`), and no
277
+ compaction tier or renewal touches them. Over the budget (default 600 tokens) the kernel refuses
278
+ the write instead of deleting for the model. Each note is a context-graph item with
279
+ `derived_from` edges to the tool results it came from.
280
+ - **Memory the model proposes.** With a candidate sink, the model calls `propose_memory` for what
281
+ should outlive the task; the proposal goes through the attested candidate ledger, and later
282
+ sessions recall it as an index line.
283
+
284
+ ```python
285
+ RuntimeOptions(..., context_policy={"notes_budget_tokens": 600}) # default; 0 turns notes off
286
+ ```
287
+
288
+ ```python
289
+ RuntimeOptions(
290
+ ...,
291
+ memory_candidate_sink=sink,
292
+ memory_runtime_policy={"retrieval": "host", "model_writes": "candidate_sink"},
293
+ )
294
+ ```
295
+
296
+ Measured on DeepSeek `deepseek-flash`, paired against the same tasks without the mechanism
297
+ (cost is price-weighted, per correct answer):
298
+
299
+ | Scenario | Without | With | Cost per correct answer |
300
+ |---|---|---|---|
301
+ | long-horizon (30 pairs) | 15/30 | **20/30** with notes | **−43%** |
302
+ | ledger (30 pairs) | 25/30 | **30/30** with notes | −3% |
303
+ | multi-session (48 pairs) | 9/48, no memory | **33/48** with notes + `propose_memory` | **−68%** |
304
+
305
+ The kernel never initiates a model call to manage context: kernel-side summaries, cache-account
306
+ compaction, note diagnostics and a post-session consolidation run were measured and deleted. Why,
307
+ and how a mechanism earns its place: [DEC-13: Model-Led Context](https://github.com/kongusen/deepstrike/blob/main/docs/en/decisions/013-model-led-context.md). Details:
308
+ [Context Engineering — notes](https://github.com/kongusen/deepstrike/blob/main/docs/en/guides/context-engineering.md).
309
+
310
+ ---
311
+
271
312
  ## Runtime options
272
313
 
273
314
  ```python
@@ -235,7 +235,7 @@ The kernel renders context as four LLM API slots — only **history** is compres
235
235
  |------|--------|------|
236
236
  | `system_stable` | system partition | Identity, rules — never changes within a run |
237
237
  | `system_knowledge` | knowledge partition | Preloaded memory, skill defs — low frequency |
238
- | `turns[0]` | `task_state` + signals | Goal, plan, progress, compression log, runtime signals |
238
+ | `turns[0]` | `task_state` + signals | Goal, plan, progress, the model's notes, compression log, runtime signals |
239
239
  | `turns[1..N]` | history | Conversation transcript |
240
240
 
241
241
  ```python
@@ -253,6 +253,47 @@ Full reference: [docs/concepts/context-slots-compression.md](../docs/concepts/co
253
253
 
254
254
  ---
255
255
 
256
+ ## Notes and model-proposed memory (0.2.82)
257
+
258
+ The model decides what is worth keeping; the kernel keeps it.
259
+
260
+ - **Notes.** Every request carries a `note` tool. The model writes, rewrites and retires notes — a
261
+ running count, what is done, a rule it learned. Notes render in the state turn (`notes:`), and no
262
+ compaction tier or renewal touches them. Over the budget (default 600 tokens) the kernel refuses
263
+ the write instead of deleting for the model. Each note is a context-graph item with
264
+ `derived_from` edges to the tool results it came from.
265
+ - **Memory the model proposes.** With a candidate sink, the model calls `propose_memory` for what
266
+ should outlive the task; the proposal goes through the attested candidate ledger, and later
267
+ sessions recall it as an index line.
268
+
269
+ ```python
270
+ RuntimeOptions(..., context_policy={"notes_budget_tokens": 600}) # default; 0 turns notes off
271
+ ```
272
+
273
+ ```python
274
+ RuntimeOptions(
275
+ ...,
276
+ memory_candidate_sink=sink,
277
+ memory_runtime_policy={"retrieval": "host", "model_writes": "candidate_sink"},
278
+ )
279
+ ```
280
+
281
+ Measured on DeepSeek `deepseek-flash`, paired against the same tasks without the mechanism
282
+ (cost is price-weighted, per correct answer):
283
+
284
+ | Scenario | Without | With | Cost per correct answer |
285
+ |---|---|---|---|
286
+ | long-horizon (30 pairs) | 15/30 | **20/30** with notes | **−43%** |
287
+ | ledger (30 pairs) | 25/30 | **30/30** with notes | −3% |
288
+ | multi-session (48 pairs) | 9/48, no memory | **33/48** with notes + `propose_memory` | **−68%** |
289
+
290
+ The kernel never initiates a model call to manage context: kernel-side summaries, cache-account
291
+ compaction, note diagnostics and a post-session consolidation run were measured and deleted. Why,
292
+ and how a mechanism earns its place: [DEC-13: Model-Led Context](https://github.com/kongusen/deepstrike/blob/main/docs/en/decisions/013-model-led-context.md). Details:
293
+ [Context Engineering — notes](https://github.com/kongusen/deepstrike/blob/main/docs/en/guides/context-engineering.md).
294
+
295
+ ---
296
+
256
297
  ## Runtime options
257
298
 
258
299
  ```python
@@ -0,0 +1,383 @@
1
+ //! Plan task 8.0 · the cache ledger: where each provider request broke the previous request's
2
+ //! cacheable prefix, how many tokens that cost, and why.
3
+ //!
4
+ //! A provider caches a request as one prefix: tool schemas, then system[0], system[1], then the
5
+ //! history turns. The volatile state turn is the uncached tail and is left out. Every time a
6
+ //! request goes out the kernel fingerprints that prefix segment by segment and compares it with the
7
+ //! previous request. The first segment that differs is a **prefix break**: every token the previous
8
+ //! request held after it has to be sent uncached again. The ledger records the break (turn, cause,
9
+ //! tokens kept before it, tokens lost after it) and sums the losses into the lifecycle report's
10
+ //! `cache_loss_tokens`.
11
+ //!
12
+ //! The cause comes from the change that made the break. Compaction, renewal, provider rewrites,
13
+ //! tool-result collapse and knowledge promotion announce themselves ([`CacheLedger::note_cause`]);
14
+ //! an unannounced break is classified from the render itself: a dropped item is a budget drop, an
15
+ //! item re-rendered as the narration stub is narration collapse, and a different toolset is a
16
+ //! toolset change.
17
+ //!
18
+ //! The state turn after the history is rebuilt every request, so the previous request's state turn
19
+ //! is never reusable: that is not a break, but a provider's count of uncached input includes it.
20
+ //! The ledger sums it separately as `tail_tokens`, so measured cache loss can be compared with the
21
+ //! kernel's.
22
+ //!
23
+ //! Everything here is derived from the rendered request, so a replay rebuilds the same ledger; it
24
+ //! travels in the checkpoint so a restored run keeps comparing against the request it last sent.
25
+
26
+ use std::collections::VecDeque;
27
+
28
+ use serde::{Deserialize, Serialize};
29
+
30
+ use crate::context::fault::stable_hash;
31
+ use crate::context::item::{HISTORY_ITEM_DETAIL_CAP, ItemId};
32
+
33
+ /// Prefix breaks the ledger lists one by one; older ones are only counted.
34
+ pub const PREFIX_BREAK_DETAIL_CAP: usize = HISTORY_ITEM_DETAIL_CAP;
35
+
36
+ /// Why a request's cacheable prefix differs from the previous request's.
37
+ #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
38
+ #[serde(rename_all = "snake_case")]
39
+ pub enum BreakCause {
40
+ /// The tool schemas changed (a skill narrowed or widened the toolset, a meta tool appeared).
41
+ Toolset,
42
+ /// system[0] changed.
43
+ System,
44
+ /// system[1] changed outside a compaction: staged knowledge promoted, or a boundary sweep.
45
+ Promotion,
46
+ /// Older tool results collapsed to previews under pressure.
47
+ Collapse,
48
+ /// An item re-rendered in place without an announced cause (a page-in, a page-out).
49
+ Reprojection,
50
+ /// Old assistant narration left the protected window and rendered as the narration stub.
51
+ Narration,
52
+ /// The renderer dropped the oldest history over the input budget.
53
+ BudgetDrop,
54
+ Snip,
55
+ Micro,
56
+ Auto,
57
+ Renewal,
58
+ /// The provider compacted or cleared context server-side.
59
+ Provider,
60
+ /// History rolled back, or anything else.
61
+ Other,
62
+ }
63
+
64
+ impl BreakCause {
65
+ /// The cause a compaction tier announces.
66
+ pub fn of_compaction(action: crate::context::pressure::PressureAction) -> Self {
67
+ use crate::context::pressure::PressureAction;
68
+ match action {
69
+ PressureAction::SnipCompact => Self::Snip,
70
+ PressureAction::MicroCompact => Self::Micro,
71
+ PressureAction::ContextCollapse => Self::Collapse,
72
+ PressureAction::AutoCompact => Self::Auto,
73
+ PressureAction::None => Self::Other,
74
+ }
75
+ }
76
+ }
77
+
78
+ /// One prefix break, attributed.
79
+ #[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
80
+ pub struct PrefixBreak {
81
+ /// The turn of the request that broke the prefix.
82
+ pub turn: u32,
83
+ pub cause: BreakCause,
84
+ /// Tokens of the previous request's prefix still byte-identical (still cacheable).
85
+ pub kept_tokens: u32,
86
+ /// Tokens of the previous request's prefix after the break: sent uncached again.
87
+ pub lost_tokens: u32,
88
+ }
89
+
90
+ /// The fingerprint and size of one prefix segment.
91
+ #[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)]
92
+ pub struct Segment {
93
+ /// FNV-1a 64 of the segment's wire material, as 16 hex digits (a string, so a JSON host that
94
+ /// reads numbers as doubles cannot round it).
95
+ pub hash: String,
96
+ pub tokens: u32,
97
+ }
98
+
99
+ impl Segment {
100
+ pub fn of(material: &[u8], tokens: u32) -> Self {
101
+ Self {
102
+ hash: format!("{:016x}", stable_hash(material)),
103
+ tokens,
104
+ }
105
+ }
106
+ }
107
+
108
+ /// One history turn of a sent request.
109
+ #[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)]
110
+ pub struct SentTurn {
111
+ #[serde(flatten)]
112
+ pub segment: Segment,
113
+ /// The history item the turn rendered; 0 for a synthetic turn.
114
+ #[serde(default)]
115
+ pub item: ItemId,
116
+ /// The turn rendered as the narration stub.
117
+ #[serde(default, skip_serializing_if = "std::ops::Not::not")]
118
+ pub stub: bool,
119
+ }
120
+
121
+ /// The cacheable prefix of one sent request.
122
+ #[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)]
123
+ pub struct SentPrefix {
124
+ pub tools: Segment,
125
+ pub system: Segment,
126
+ pub knowledge: Segment,
127
+ #[serde(default)]
128
+ pub turns: Vec<SentTurn>,
129
+ /// The uncached state turn after the turns.
130
+ #[serde(default, skip_serializing_if = "crate::context::item::is_zero_u32")]
131
+ pub tail: u32,
132
+ }
133
+
134
+ impl SentPrefix {
135
+ fn header_tokens(&self) -> u32 {
136
+ self.tools
137
+ .tokens
138
+ .saturating_add(self.system.tokens)
139
+ .saturating_add(self.knowledge.tokens)
140
+ }
141
+
142
+ fn total_tokens(&self) -> u32 {
143
+ self.turns
144
+ .iter()
145
+ .fold(self.header_tokens(), |sum, turn| sum.saturating_add(turn.segment.tokens))
146
+ }
147
+
148
+ /// The tokens a turn with this hash had in this request, to avoid recounting it.
149
+ pub fn tokens_of(&self, hash: &str) -> Option<u32> {
150
+ self.turns
151
+ .iter()
152
+ .find(|turn| turn.segment.hash == hash)
153
+ .map(|turn| turn.segment.tokens)
154
+ }
155
+ }
156
+
157
+ #[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)]
158
+ #[serde(deny_unknown_fields)]
159
+ pub struct CacheLedger {
160
+ /// The prefix of the last request sent.
161
+ #[serde(default, skip_serializing_if = "Option::is_none")]
162
+ pub sent: Option<SentPrefix>,
163
+ /// The announced cause of a rewrite since the last request.
164
+ #[serde(default, skip_serializing_if = "Option::is_none")]
165
+ pub pending: Option<BreakCause>,
166
+ /// The latest breaks, oldest first.
167
+ #[serde(default, skip_serializing_if = "VecDeque::is_empty")]
168
+ pub breaks: VecDeque<PrefixBreak>,
169
+ #[serde(default, skip_serializing_if = "crate::context::item::is_zero_u32")]
170
+ pub breaks_omitted: u32,
171
+ /// Lost tokens summed over every break of the run.
172
+ #[serde(default, skip_serializing_if = "crate::context::item::is_zero_u64")]
173
+ pub lost_tokens: u64,
174
+ /// The state-turn tokens of every request a later request followed: never reusable, so not a
175
+ /// break, but part of what a provider counts as uncached.
176
+ #[serde(default, skip_serializing_if = "crate::context::item::is_zero_u64")]
177
+ pub tail_tokens: u64,
178
+ }
179
+
180
+ impl CacheLedger {
181
+ /// A rewrite with `cause` happened; the next request's break, if it has one, is attributed to
182
+ /// it. The first cause announced since the last request is kept: later rewrites in the same
183
+ /// interval (a boundary sweep a compaction triggered) follow from it.
184
+ pub fn note_cause(&mut self, cause: BreakCause) {
185
+ self.pending.get_or_insert(cause);
186
+ }
187
+
188
+ /// The request with prefix `next` is being sent on `turn`. Compares it with the last request,
189
+ /// records the break if there is one, and returns it.
190
+ pub fn observe(&mut self, turn: u32, next: SentPrefix) -> Option<PrefixBreak> {
191
+ let pending = self.pending.take();
192
+ self.tail_tokens += self.sent.as_ref().map_or(0, |prev| u64::from(prev.tail));
193
+ let found = self.sent.as_ref().and_then(|prev| find_break(prev, &next, pending));
194
+ self.sent = Some(next);
195
+ let found = found.map(|(cause, kept_tokens, lost_tokens)| PrefixBreak {
196
+ turn,
197
+ cause,
198
+ kept_tokens,
199
+ lost_tokens,
200
+ })?;
201
+ self.lost_tokens += u64::from(found.lost_tokens);
202
+ self.breaks.push_back(found);
203
+ if self.breaks.len() > PREFIX_BREAK_DETAIL_CAP {
204
+ self.breaks.pop_front();
205
+ self.breaks_omitted += 1;
206
+ }
207
+ Some(found)
208
+ }
209
+ }
210
+
211
+ /// Where `next` stops reusing `prev`, why, and the (kept, lost) tokens of `prev`'s prefix.
212
+ fn find_break(
213
+ prev: &SentPrefix,
214
+ next: &SentPrefix,
215
+ pending: Option<BreakCause>,
216
+ ) -> Option<(BreakCause, u32, u32)> {
217
+ let total = prev.total_tokens();
218
+ let lost = |kept: u32| total.saturating_sub(kept);
219
+ if prev.tools.hash != next.tools.hash {
220
+ return Some((BreakCause::Toolset, 0, total)).filter(|_| total > 0);
221
+ }
222
+ if prev.system.hash != next.system.hash {
223
+ let kept = prev.tools.tokens;
224
+ return Some((pending.unwrap_or(BreakCause::System), kept, lost(kept)));
225
+ }
226
+ if prev.knowledge.hash != next.knowledge.hash {
227
+ let kept = prev.tools.tokens.saturating_add(prev.system.tokens);
228
+ return Some((pending.unwrap_or(BreakCause::Promotion), kept, lost(kept)));
229
+ }
230
+ let same = prev
231
+ .turns
232
+ .iter()
233
+ .zip(&next.turns)
234
+ .take_while(|(a, b)| a.segment.hash == b.segment.hash)
235
+ .count();
236
+ if same == prev.turns.len() {
237
+ return None;
238
+ }
239
+ let kept = prev.turns[..same]
240
+ .iter()
241
+ .fold(prev.header_tokens(), |sum, turn| sum.saturating_add(turn.segment.tokens));
242
+ let lost = lost(kept);
243
+ if lost == 0 {
244
+ return None;
245
+ }
246
+ let cause = pending.unwrap_or_else(|| classify(&prev.turns[same], next, same));
247
+ Some((cause, kept, lost))
248
+ }
249
+
250
+ /// An unannounced turn break: what happened to the first turn that no longer matches.
251
+ fn classify(prev: &SentTurn, next: &SentPrefix, at: usize) -> BreakCause {
252
+ if prev.item != 0 && !next.turns.iter().any(|turn| turn.item == prev.item) {
253
+ return BreakCause::BudgetDrop;
254
+ }
255
+ match next.turns.get(at) {
256
+ Some(turn) if turn.item == prev.item && turn.stub && !prev.stub => BreakCause::Narration,
257
+ Some(turn) if turn.item == prev.item && turn.item != 0 => BreakCause::Reprojection,
258
+ _ => BreakCause::Other,
259
+ }
260
+ }
261
+
262
+ #[cfg(test)]
263
+ mod tests {
264
+ use super::*;
265
+
266
+ fn seg(name: &str, tokens: u32) -> Segment {
267
+ Segment::of(name.as_bytes(), tokens)
268
+ }
269
+
270
+ fn turn(name: &str, item: ItemId, tokens: u32) -> SentTurn {
271
+ SentTurn {
272
+ segment: seg(name, tokens),
273
+ item,
274
+ stub: false,
275
+ }
276
+ }
277
+
278
+ fn prefix(turns: Vec<SentTurn>) -> SentPrefix {
279
+ SentPrefix {
280
+ tools: seg("tools", 100),
281
+ system: seg("system", 50),
282
+ knowledge: seg("knowledge", 20),
283
+ turns,
284
+ tail: 7,
285
+ }
286
+ }
287
+
288
+ #[test]
289
+ fn an_appended_request_breaks_nothing() {
290
+ let mut ledger = CacheLedger::default();
291
+ assert_eq!(ledger.observe(1, prefix(vec![turn("a", 1, 10)])), None);
292
+ let next = prefix(vec![turn("a", 1, 10), turn("b", 2, 30)]);
293
+ assert_eq!(ledger.observe(2, next), None);
294
+ assert_eq!(ledger.lost_tokens, 0);
295
+ assert_eq!(ledger.tail_tokens, 7, "the first request's state turn was not reusable");
296
+ }
297
+
298
+ #[test]
299
+ fn a_dropped_oldest_turn_is_a_budget_drop() {
300
+ let mut ledger = CacheLedger::default();
301
+ ledger.observe(1, prefix(vec![turn("a", 1, 10), turn("b", 2, 30)]));
302
+ let found = ledger.observe(2, prefix(vec![turn("b", 2, 30), turn("c", 3, 5)]));
303
+ assert_eq!(
304
+ found,
305
+ Some(PrefixBreak {
306
+ turn: 2,
307
+ cause: BreakCause::BudgetDrop,
308
+ kept_tokens: 170,
309
+ lost_tokens: 40,
310
+ })
311
+ );
312
+ assert_eq!(ledger.lost_tokens, 40);
313
+ }
314
+
315
+ #[test]
316
+ fn a_turn_rendered_as_the_stub_is_narration() {
317
+ let mut ledger = CacheLedger::default();
318
+ ledger.observe(1, prefix(vec![turn("a", 1, 10), turn("b", 2, 30)]));
319
+ let mut stub = turn("stub", 1, 4);
320
+ stub.stub = true;
321
+ let found = ledger.observe(2, prefix(vec![stub, turn("b", 2, 30)])).unwrap();
322
+ assert_eq!(found.cause, BreakCause::Narration);
323
+ assert_eq!((found.kept_tokens, found.lost_tokens), (170, 40));
324
+ }
325
+
326
+ #[test]
327
+ fn an_announced_cause_wins_and_is_spent_by_one_request() {
328
+ let mut ledger = CacheLedger::default();
329
+ ledger.observe(1, prefix(vec![turn("a", 1, 10)]));
330
+ ledger.note_cause(BreakCause::Auto);
331
+ ledger.note_cause(BreakCause::Promotion);
332
+ let found = ledger.observe(2, prefix(vec![turn("summary", 5, 3)])).unwrap();
333
+ assert_eq!(found.cause, BreakCause::Auto);
334
+ // A compaction that broke nothing leaves no cause behind for a later break.
335
+ ledger.note_cause(BreakCause::Snip);
336
+ assert_eq!(ledger.observe(3, prefix(vec![turn("summary", 5, 3)])), None);
337
+ assert_eq!(ledger.pending, None);
338
+ }
339
+
340
+ #[test]
341
+ fn a_new_toolset_loses_the_whole_prefix() {
342
+ let mut ledger = CacheLedger::default();
343
+ ledger.observe(1, prefix(vec![turn("a", 1, 10)]));
344
+ let mut next = prefix(vec![turn("a", 1, 10)]);
345
+ next.tools = seg("narrowed", 60);
346
+ let found = ledger.observe(2, next).unwrap();
347
+ assert_eq!(found.cause, BreakCause::Toolset);
348
+ assert_eq!((found.kept_tokens, found.lost_tokens), (0, 180));
349
+ }
350
+
351
+ #[test]
352
+ fn changed_knowledge_is_a_promotion_unless_announced() {
353
+ let mut ledger = CacheLedger::default();
354
+ ledger.observe(1, prefix(vec![turn("a", 1, 10)]));
355
+ let mut next = prefix(vec![turn("a", 1, 10)]);
356
+ next.knowledge = seg("promoted", 40);
357
+ let found = ledger.observe(2, next).unwrap();
358
+ assert_eq!(found.cause, BreakCause::Promotion);
359
+ assert_eq!((found.kept_tokens, found.lost_tokens), (150, 30));
360
+ }
361
+
362
+ #[test]
363
+ fn the_detail_is_capped_but_the_total_is_not() {
364
+ let mut ledger = CacheLedger::default();
365
+ for round in 0..(PREFIX_BREAK_DETAIL_CAP as u32 + 3) {
366
+ let name = format!("t{round}");
367
+ ledger.observe(round, prefix(vec![turn(&name, u64::from(round) + 1, 10)]));
368
+ }
369
+ assert_eq!(ledger.breaks.len(), PREFIX_BREAK_DETAIL_CAP);
370
+ assert_eq!(ledger.breaks_omitted, 2);
371
+ assert_eq!(ledger.lost_tokens, 10 * (PREFIX_BREAK_DETAIL_CAP as u64 + 2));
372
+ }
373
+
374
+ #[test]
375
+ fn the_ledger_round_trips_through_json() {
376
+ let mut ledger = CacheLedger::default();
377
+ ledger.observe(1, prefix(vec![turn("a", 1, 10)]));
378
+ ledger.observe(2, prefix(vec![turn("b", 2, 10)]));
379
+ ledger.note_cause(BreakCause::Renewal);
380
+ let json = serde_json::to_string(&ledger).unwrap();
381
+ assert_eq!(serde_json::from_str::<CacheLedger>(&json).unwrap(), ledger);
382
+ }
383
+ }
@@ -103,6 +103,10 @@ pub struct ContextConfig {
103
103
  /// The provider compacts natively, so the kernel runs neither context collapse nor auto-compact.
104
104
  /// Renewal is never delegated: it is decided on the full local history and stays the safety net.
105
105
  pub delegate_compaction: bool,
106
+
107
+ // ── Notes (plan task 9.1) ───────────────────────────────────────────────
108
+ /// Tokens the model's notes may hold in the state turn. `0` turns the `note` tool off.
109
+ pub notes_budget_tokens: u32,
106
110
  }
107
111
 
108
112
  impl Default for ContextConfig {
@@ -127,6 +131,7 @@ impl Default for ContextConfig {
127
131
  knowledge_budget_ratio: 0.25,
128
132
  delegate_tool_result_clearing: false,
129
133
  delegate_compaction: false,
134
+ notes_budget_tokens: 0,
130
135
  }
131
136
  }
132
137
  }
@@ -11,8 +11,8 @@ pub enum ContextFault {
11
11
  InvalidReplay { turn: u32, reason: String },
12
12
  }
13
13
 
14
- /// FNV-1a 64-bit — the render layer's cache-stability test fingerprint dialect.
15
- #[cfg(test)]
14
+ /// FNV-1a 64-bit — the render layer's cache-stability fingerprint dialect (the render tests and
15
+ /// the plan task 8.0 cache ledger).
16
16
  pub(crate) fn stable_hash(bytes: &[u8]) -> u64 {
17
17
  let mut hash = 0xcbf29ce484222325u64;
18
18
  for byte in bytes {
@@ -40,6 +40,12 @@ pub enum Relation {
40
40
  InheritedFrom,
41
41
  /// Plan task 7.4 · the item that read a dependency output back → the run that produced it.
42
42
  DependsOn,
43
+ /// Plan task 9.1 · a note the model wrote → the evidence it came from.
44
+ DerivedFrom,
45
+ /// Plan task 9.1 · a note → another note it names.
46
+ LinksTo,
47
+ /// Plan task 9.1 · a note → the note it replaced.
48
+ Supersedes,
43
49
  }
44
50
 
45
51
  impl Relation {
@@ -53,6 +59,9 @@ impl Relation {
53
59
  Self::Expands => "expands",
54
60
  Self::InheritedFrom => "inherited_from",
55
61
  Self::DependsOn => "depends_on",
62
+ Self::DerivedFrom => "derived_from",
63
+ Self::LinksTo => "links_to",
64
+ Self::Supersedes => "supersedes",
56
65
  }
57
66
  }
58
67
  }
@@ -138,7 +147,7 @@ pub(crate) fn is_zero_u32(value: &u32) -> bool {
138
147
  *value == 0
139
148
  }
140
149
 
141
- fn is_zero_u64(value: &u64) -> bool {
150
+ pub fn is_zero_u64(value: &u64) -> bool {
142
151
  *value == 0
143
152
  }
144
153
 
@@ -163,6 +172,8 @@ pub enum ItemOrigin {
163
172
  TaskState,
164
173
  Signal,
165
174
  ProviderSummary,
175
+ /// Plan task 9.1 · a note the model wrote with the `note` tool.
176
+ Note,
166
177
  }
167
178
 
168
179
  impl ItemOrigin {
@@ -200,6 +211,7 @@ impl ItemOrigin {
200
211
  Self::TaskState => "task_state",
201
212
  Self::Signal => "signal",
202
213
  Self::ProviderSummary => "provider_summary",
214
+ Self::Note => "note",
203
215
  }
204
216
  }
205
217
 
@@ -224,6 +236,7 @@ impl ItemOrigin {
224
236
  Self::TaskState => (S::Task, F::Structured, L::Permanent, A::Kernel),
225
237
  Self::Signal => (S::Operation, F::Full, L::SingleUse, A::Host),
226
238
  Self::ProviderSummary => (S::Operation, F::Full, L::Permanent, A::Provider),
239
+ Self::Note => (S::Task, F::Full, L::Permanent, A::Model),
227
240
  };
228
241
  ItemDefaults { scope, fidelity, lease, authority }
229
242
  }