execweave 0.8.4__tar.gz → 0.8.5__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 (482) hide show
  1. {execweave-0.8.4 → execweave-0.8.5}/PKG-INFO +2 -2
  2. {execweave-0.8.4 → execweave-0.8.5}/README.de.md +1 -1
  3. {execweave-0.8.4 → execweave-0.8.5}/README.fr.md +1 -1
  4. {execweave-0.8.4 → execweave-0.8.5}/README.ja.md +1 -1
  5. {execweave-0.8.4 → execweave-0.8.5}/README.ko.md +1 -1
  6. {execweave-0.8.4 → execweave-0.8.5}/README.md +1 -1
  7. {execweave-0.8.4 → execweave-0.8.5}/README.ru.md +1 -1
  8. {execweave-0.8.4 → execweave-0.8.5}/README.zh-CN.md +1 -1
  9. {execweave-0.8.4 → execweave-0.8.5}/README.zh-TW.md +1 -1
  10. {execweave-0.8.4 → execweave-0.8.5}/pyproject.toml +2 -2
  11. {execweave-0.8.4 → execweave-0.8.5}/src/execweave/__init__.py +1 -1
  12. {execweave-0.8.4 → execweave-0.8.5}/src/execweave/antigravity_full_fidelity_base.py +16 -4
  13. {execweave-0.8.4 → execweave-0.8.5}/src/execweave/auto_specialized.py +50 -0
  14. {execweave-0.8.4 → execweave-0.8.5}/src/execweave/collector.py +19 -12
  15. {execweave-0.8.4 → execweave-0.8.5}/src/execweave/conversation_preview.py +76 -17
  16. {execweave-0.8.4 → execweave-0.8.5}/src/execweave/conversation_records.py +179 -13
  17. {execweave-0.8.4 → execweave-0.8.5}/src/execweave/model_runtime_full_fidelity.py +3 -0
  18. {execweave-0.8.4 → execweave-0.8.5}/src/execweave/strace_backend.py +8 -1
  19. {execweave-0.8.4 → execweave-0.8.5}/src/execweave/viewer_agent_panel.py +27 -2
  20. {execweave-0.8.4 → execweave-0.8.5}/src/execweave/viewer_dashboard_focus.py +20 -3
  21. execweave-0.8.5/tests/test_provider_conversation_history_integrity.py +335 -0
  22. {execweave-0.8.4 → execweave-0.8.5}/tests/test_v069_dashboard_release.py +3 -3
  23. {execweave-0.8.4 → execweave-0.8.5}/.github/workflows/ci.yml +0 -0
  24. {execweave-0.8.4 → execweave-0.8.5}/.github/workflows/cleanup-workflow-history.yml +0 -0
  25. {execweave-0.8.4 → execweave-0.8.5}/.github/workflows/i18n.yml +0 -0
  26. {execweave-0.8.4 → execweave-0.8.5}/.github/workflows/package-benchmark.yml +0 -0
  27. {execweave-0.8.4 → execweave-0.8.5}/.github/workflows/package-smoke.yml +0 -0
  28. {execweave-0.8.4 → execweave-0.8.5}/.github/workflows/provider-capability-stage-integrity.yml +0 -0
  29. {execweave-0.8.4 → execweave-0.8.5}/.github/workflows/publish.yml +0 -0
  30. {execweave-0.8.4 → execweave-0.8.5}/.github/workflows/scalability.yml +0 -0
  31. {execweave-0.8.4 → execweave-0.8.5}/.github/workflows/viewer-agent-isolation.yml +0 -0
  32. {execweave-0.8.4 → execweave-0.8.5}/.github/workflows/wheel-smoke.yml +0 -0
  33. {execweave-0.8.4 → execweave-0.8.5}/.github/workflows/windows-launcher.yml +0 -0
  34. {execweave-0.8.4 → execweave-0.8.5}/.gitignore +0 -0
  35. {execweave-0.8.4 → execweave-0.8.5}/LICENSE +0 -0
  36. {execweave-0.8.4 → execweave-0.8.5}/RELEASE-PLAN-0.8.0.md +0 -0
  37. {execweave-0.8.4 → execweave-0.8.5}/benchmarks/phase1_overhead.py +0 -0
  38. {execweave-0.8.4 → execweave-0.8.5}/docs/antigravity-hooks.md +0 -0
  39. {execweave-0.8.4 → execweave-0.8.5}/docs/assets/codex.gif +0 -0
  40. {execweave-0.8.4 → execweave-0.8.5}/docs/benchmarks/README.md +0 -0
  41. {execweave-0.8.4 → execweave-0.8.5}/docs/benchmarks/v0.6.0-github-actions.json +0 -0
  42. {execweave-0.8.4 → execweave-0.8.5}/docs/benchmarks/v0.6.0-github-actions.svg +0 -0
  43. {execweave-0.8.4 → execweave-0.8.5}/docs/claude-code-hooks.de.md +0 -0
  44. {execweave-0.8.4 → execweave-0.8.5}/docs/claude-code-hooks.fr.md +0 -0
  45. {execweave-0.8.4 → execweave-0.8.5}/docs/claude-code-hooks.ja.md +0 -0
  46. {execweave-0.8.4 → execweave-0.8.5}/docs/claude-code-hooks.ko.md +0 -0
  47. {execweave-0.8.4 → execweave-0.8.5}/docs/claude-code-hooks.md +0 -0
  48. {execweave-0.8.4 → execweave-0.8.5}/docs/claude-code-hooks.ru.md +0 -0
  49. {execweave-0.8.4 → execweave-0.8.5}/docs/claude-code-hooks.zh-CN.md +0 -0
  50. {execweave-0.8.4 → execweave-0.8.5}/docs/claude-code-hooks.zh-TW.md +0 -0
  51. {execweave-0.8.4 → execweave-0.8.5}/docs/codex-hooks.de.md +0 -0
  52. {execweave-0.8.4 → execweave-0.8.5}/docs/codex-hooks.fr.md +0 -0
  53. {execweave-0.8.4 → execweave-0.8.5}/docs/codex-hooks.ja.md +0 -0
  54. {execweave-0.8.4 → execweave-0.8.5}/docs/codex-hooks.ko.md +0 -0
  55. {execweave-0.8.4 → execweave-0.8.5}/docs/codex-hooks.md +0 -0
  56. {execweave-0.8.4 → execweave-0.8.5}/docs/codex-hooks.ru.md +0 -0
  57. {execweave-0.8.4 → execweave-0.8.5}/docs/codex-hooks.zh-CN.md +0 -0
  58. {execweave-0.8.4 → execweave-0.8.5}/docs/codex-hooks.zh-TW.md +0 -0
  59. {execweave-0.8.4 → execweave-0.8.5}/docs/cursor-hooks.de.md +0 -0
  60. {execweave-0.8.4 → execweave-0.8.5}/docs/cursor-hooks.fr.md +0 -0
  61. {execweave-0.8.4 → execweave-0.8.5}/docs/cursor-hooks.ja.md +0 -0
  62. {execweave-0.8.4 → execweave-0.8.5}/docs/cursor-hooks.ko.md +0 -0
  63. {execweave-0.8.4 → execweave-0.8.5}/docs/cursor-hooks.md +0 -0
  64. {execweave-0.8.4 → execweave-0.8.5}/docs/cursor-hooks.ru.md +0 -0
  65. {execweave-0.8.4 → execweave-0.8.5}/docs/cursor-hooks.zh-CN.md +0 -0
  66. {execweave-0.8.4 → execweave-0.8.5}/docs/cursor-hooks.zh-TW.md +0 -0
  67. {execweave-0.8.4 → execweave-0.8.5}/docs/evidence-grades.de.md +0 -0
  68. {execweave-0.8.4 → execweave-0.8.5}/docs/evidence-grades.fr.md +0 -0
  69. {execweave-0.8.4 → execweave-0.8.5}/docs/evidence-grades.ja.md +0 -0
  70. {execweave-0.8.4 → execweave-0.8.5}/docs/evidence-grades.ko.md +0 -0
  71. {execweave-0.8.4 → execweave-0.8.5}/docs/evidence-grades.md +0 -0
  72. {execweave-0.8.4 → execweave-0.8.5}/docs/evidence-grades.ru.md +0 -0
  73. {execweave-0.8.4 → execweave-0.8.5}/docs/evidence-grades.zh-CN.md +0 -0
  74. {execweave-0.8.4 → execweave-0.8.5}/docs/evidence-grades.zh-TW.md +0 -0
  75. {execweave-0.8.4 → execweave-0.8.5}/docs/gemini-hooks.de.md +0 -0
  76. {execweave-0.8.4 → execweave-0.8.5}/docs/gemini-hooks.fr.md +0 -0
  77. {execweave-0.8.4 → execweave-0.8.5}/docs/gemini-hooks.ja.md +0 -0
  78. {execweave-0.8.4 → execweave-0.8.5}/docs/gemini-hooks.ko.md +0 -0
  79. {execweave-0.8.4 → execweave-0.8.5}/docs/gemini-hooks.md +0 -0
  80. {execweave-0.8.4 → execweave-0.8.5}/docs/gemini-hooks.ru.md +0 -0
  81. {execweave-0.8.4 → execweave-0.8.5}/docs/gemini-hooks.zh-CN.md +0 -0
  82. {execweave-0.8.4 → execweave-0.8.5}/docs/gemini-hooks.zh-TW.md +0 -0
  83. {execweave-0.8.4 → execweave-0.8.5}/docs/inference-gateway.de.md +0 -0
  84. {execweave-0.8.4 → execweave-0.8.5}/docs/inference-gateway.fr.md +0 -0
  85. {execweave-0.8.4 → execweave-0.8.5}/docs/inference-gateway.ja.md +0 -0
  86. {execweave-0.8.4 → execweave-0.8.5}/docs/inference-gateway.ko.md +0 -0
  87. {execweave-0.8.4 → execweave-0.8.5}/docs/inference-gateway.md +0 -0
  88. {execweave-0.8.4 → execweave-0.8.5}/docs/inference-gateway.ru.md +0 -0
  89. {execweave-0.8.4 → execweave-0.8.5}/docs/inference-gateway.zh-CN.md +0 -0
  90. {execweave-0.8.4 → execweave-0.8.5}/docs/inference-gateway.zh-TW.md +0 -0
  91. {execweave-0.8.4 → execweave-0.8.5}/docs/internal/provider-capability-matrix.md +0 -0
  92. {execweave-0.8.4 → execweave-0.8.5}/docs/live-graph.de.md +0 -0
  93. {execweave-0.8.4 → execweave-0.8.5}/docs/live-graph.fr.md +0 -0
  94. {execweave-0.8.4 → execweave-0.8.5}/docs/live-graph.ja.md +0 -0
  95. {execweave-0.8.4 → execweave-0.8.5}/docs/live-graph.ko.md +0 -0
  96. {execweave-0.8.4 → execweave-0.8.5}/docs/live-graph.md +0 -0
  97. {execweave-0.8.4 → execweave-0.8.5}/docs/live-graph.ru.md +0 -0
  98. {execweave-0.8.4 → execweave-0.8.5}/docs/live-graph.zh-CN.md +0 -0
  99. {execweave-0.8.4 → execweave-0.8.5}/docs/live-graph.zh-TW.md +0 -0
  100. {execweave-0.8.4 → execweave-0.8.5}/docs/model-runtime.de.md +0 -0
  101. {execweave-0.8.4 → execweave-0.8.5}/docs/model-runtime.fr.md +0 -0
  102. {execweave-0.8.4 → execweave-0.8.5}/docs/model-runtime.ja.md +0 -0
  103. {execweave-0.8.4 → execweave-0.8.5}/docs/model-runtime.ko.md +0 -0
  104. {execweave-0.8.4 → execweave-0.8.5}/docs/model-runtime.md +0 -0
  105. {execweave-0.8.4 → execweave-0.8.5}/docs/model-runtime.ru.md +0 -0
  106. {execweave-0.8.4 → execweave-0.8.5}/docs/model-runtime.zh-CN.md +0 -0
  107. {execweave-0.8.4 → execweave-0.8.5}/docs/model-runtime.zh-TW.md +0 -0
  108. {execweave-0.8.4 → execweave-0.8.5}/docs/opencode-plugin.de.md +0 -0
  109. {execweave-0.8.4 → execweave-0.8.5}/docs/opencode-plugin.fr.md +0 -0
  110. {execweave-0.8.4 → execweave-0.8.5}/docs/opencode-plugin.ja.md +0 -0
  111. {execweave-0.8.4 → execweave-0.8.5}/docs/opencode-plugin.ko.md +0 -0
  112. {execweave-0.8.4 → execweave-0.8.5}/docs/opencode-plugin.md +0 -0
  113. {execweave-0.8.4 → execweave-0.8.5}/docs/opencode-plugin.ru.md +0 -0
  114. {execweave-0.8.4 → execweave-0.8.5}/docs/opencode-plugin.zh-CN.md +0 -0
  115. {execweave-0.8.4 → execweave-0.8.5}/docs/opencode-plugin.zh-TW.md +0 -0
  116. {execweave-0.8.4 → execweave-0.8.5}/docs/phase-1-runtime-collection.de.md +0 -0
  117. {execweave-0.8.4 → execweave-0.8.5}/docs/phase-1-runtime-collection.fr.md +0 -0
  118. {execweave-0.8.4 → execweave-0.8.5}/docs/phase-1-runtime-collection.ja.md +0 -0
  119. {execweave-0.8.4 → execweave-0.8.5}/docs/phase-1-runtime-collection.ko.md +0 -0
  120. {execweave-0.8.4 → execweave-0.8.5}/docs/phase-1-runtime-collection.md +0 -0
  121. {execweave-0.8.4 → execweave-0.8.5}/docs/phase-1-runtime-collection.ru.md +0 -0
  122. {execweave-0.8.4 → execweave-0.8.5}/docs/phase-1-runtime-collection.zh-CN.md +0 -0
  123. {execweave-0.8.4 → execweave-0.8.5}/docs/phase-1-runtime-collection.zh-TW.md +0 -0
  124. {execweave-0.8.4 → execweave-0.8.5}/docs/phase-2-execution-graph.de.md +0 -0
  125. {execweave-0.8.4 → execweave-0.8.5}/docs/phase-2-execution-graph.fr.md +0 -0
  126. {execweave-0.8.4 → execweave-0.8.5}/docs/phase-2-execution-graph.ja.md +0 -0
  127. {execweave-0.8.4 → execweave-0.8.5}/docs/phase-2-execution-graph.ko.md +0 -0
  128. {execweave-0.8.4 → execweave-0.8.5}/docs/phase-2-execution-graph.md +0 -0
  129. {execweave-0.8.4 → execweave-0.8.5}/docs/phase-2-execution-graph.ru.md +0 -0
  130. {execweave-0.8.4 → execweave-0.8.5}/docs/phase-2-execution-graph.zh-CN.md +0 -0
  131. {execweave-0.8.4 → execweave-0.8.5}/docs/phase-2-execution-graph.zh-TW.md +0 -0
  132. {execweave-0.8.4 → execweave-0.8.5}/docs/rule-packs.de.md +0 -0
  133. {execweave-0.8.4 → execweave-0.8.5}/docs/rule-packs.fr.md +0 -0
  134. {execweave-0.8.4 → execweave-0.8.5}/docs/rule-packs.ja.md +0 -0
  135. {execweave-0.8.4 → execweave-0.8.5}/docs/rule-packs.ko.md +0 -0
  136. {execweave-0.8.4 → execweave-0.8.5}/docs/rule-packs.md +0 -0
  137. {execweave-0.8.4 → execweave-0.8.5}/docs/rule-packs.ru.md +0 -0
  138. {execweave-0.8.4 → execweave-0.8.5}/docs/rule-packs.zh-CN.md +0 -0
  139. {execweave-0.8.4 → execweave-0.8.5}/docs/rule-packs.zh-TW.md +0 -0
  140. {execweave-0.8.4 → execweave-0.8.5}/docs/run-integrity.de.md +0 -0
  141. {execweave-0.8.4 → execweave-0.8.5}/docs/run-integrity.fr.md +0 -0
  142. {execweave-0.8.4 → execweave-0.8.5}/docs/run-integrity.ja.md +0 -0
  143. {execweave-0.8.4 → execweave-0.8.5}/docs/run-integrity.ko.md +0 -0
  144. {execweave-0.8.4 → execweave-0.8.5}/docs/run-integrity.md +0 -0
  145. {execweave-0.8.4 → execweave-0.8.5}/docs/run-integrity.ru.md +0 -0
  146. {execweave-0.8.4 → execweave-0.8.5}/docs/run-integrity.zh-CN.md +0 -0
  147. {execweave-0.8.4 → execweave-0.8.5}/docs/run-integrity.zh-TW.md +0 -0
  148. {execweave-0.8.4 → execweave-0.8.5}/docs/runtime-threat-model.de.md +0 -0
  149. {execweave-0.8.4 → execweave-0.8.5}/docs/runtime-threat-model.fr.md +0 -0
  150. {execweave-0.8.4 → execweave-0.8.5}/docs/runtime-threat-model.ja.md +0 -0
  151. {execweave-0.8.4 → execweave-0.8.5}/docs/runtime-threat-model.ko.md +0 -0
  152. {execweave-0.8.4 → execweave-0.8.5}/docs/runtime-threat-model.md +0 -0
  153. {execweave-0.8.4 → execweave-0.8.5}/docs/runtime-threat-model.ru.md +0 -0
  154. {execweave-0.8.4 → execweave-0.8.5}/docs/runtime-threat-model.zh-CN.md +0 -0
  155. {execweave-0.8.4 → execweave-0.8.5}/docs/runtime-threat-model.zh-TW.md +0 -0
  156. {execweave-0.8.4 → execweave-0.8.5}/docs/security-analysis.de.md +0 -0
  157. {execweave-0.8.4 → execweave-0.8.5}/docs/security-analysis.fr.md +0 -0
  158. {execweave-0.8.4 → execweave-0.8.5}/docs/security-analysis.ja.md +0 -0
  159. {execweave-0.8.4 → execweave-0.8.5}/docs/security-analysis.ko.md +0 -0
  160. {execweave-0.8.4 → execweave-0.8.5}/docs/security-analysis.md +0 -0
  161. {execweave-0.8.4 → execweave-0.8.5}/docs/security-analysis.ru.md +0 -0
  162. {execweave-0.8.4 → execweave-0.8.5}/docs/security-analysis.zh-CN.md +0 -0
  163. {execweave-0.8.4 → execweave-0.8.5}/docs/security-analysis.zh-TW.md +0 -0
  164. {execweave-0.8.4 → execweave-0.8.5}/docs/semantic-telemetry.de.md +0 -0
  165. {execweave-0.8.4 → execweave-0.8.5}/docs/semantic-telemetry.fr.md +0 -0
  166. {execweave-0.8.4 → execweave-0.8.5}/docs/semantic-telemetry.ja.md +0 -0
  167. {execweave-0.8.4 → execweave-0.8.5}/docs/semantic-telemetry.ko.md +0 -0
  168. {execweave-0.8.4 → execweave-0.8.5}/docs/semantic-telemetry.md +0 -0
  169. {execweave-0.8.4 → execweave-0.8.5}/docs/semantic-telemetry.ru.md +0 -0
  170. {execweave-0.8.4 → execweave-0.8.5}/docs/semantic-telemetry.zh-CN.md +0 -0
  171. {execweave-0.8.4 → execweave-0.8.5}/docs/semantic-telemetry.zh-TW.md +0 -0
  172. {execweave-0.8.4 → execweave-0.8.5}/docs/v0.6.5-hardening-decisions.md +0 -0
  173. {execweave-0.8.4 → execweave-0.8.5}/docs/v0.8.3-graph-ergonomics.md +0 -0
  174. {execweave-0.8.4 → execweave-0.8.5}/scripts/audit_i18n_parity.py +0 -0
  175. {execweave-0.8.4 → execweave-0.8.5}/scripts/check_claude_hook.py +0 -0
  176. {execweave-0.8.4 → execweave-0.8.5}/scripts/check_claude_record_graph.py +0 -0
  177. {execweave-0.8.4 → execweave-0.8.5}/scripts/check_codex_hook.py +0 -0
  178. {execweave-0.8.4 → execweave-0.8.5}/scripts/check_conversation_records.py +0 -0
  179. {execweave-0.8.4 → execweave-0.8.5}/scripts/check_correlation_graph.py +0 -0
  180. {execweave-0.8.4 → execweave-0.8.5}/scripts/check_inference_gateway_cli.py +0 -0
  181. {execweave-0.8.4 → execweave-0.8.5}/scripts/check_model_runtime_cli.py +0 -0
  182. {execweave-0.8.4 → execweave-0.8.5}/scripts/check_openai_compatible_cli.py +0 -0
  183. {execweave-0.8.4 → execweave-0.8.5}/scripts/check_release_stage_integrity.py +0 -0
  184. {execweave-0.8.4 → execweave-0.8.5}/scripts/check_semantic_graph.py +0 -0
  185. {execweave-0.8.4 → execweave-0.8.5}/scripts/check_viewer_js.py +0 -0
  186. {execweave-0.8.4 → execweave-0.8.5}/scripts/check_wheel_install.py +0 -0
  187. {execweave-0.8.4 → execweave-0.8.5}/scripts/check_windows_launchers.py +0 -0
  188. {execweave-0.8.4 → execweave-0.8.5}/scripts/emit_claude_hook_smoke.py +0 -0
  189. {execweave-0.8.4 → execweave-0.8.5}/scripts/emit_codex_hook_smoke.py +0 -0
  190. {execweave-0.8.4 → execweave-0.8.5}/scripts/emit_cursor_hook_smoke.py +0 -0
  191. {execweave-0.8.4 → execweave-0.8.5}/scripts/emit_gemini_hook_smoke.py +0 -0
  192. {execweave-0.8.4 → execweave-0.8.5}/scripts/emit_opencode_plugin_smoke.py +0 -0
  193. {execweave-0.8.4 → execweave-0.8.5}/scripts/make_semantic_smoke.py +0 -0
  194. {execweave-0.8.4 → execweave-0.8.5}/scripts/probe_provider_capability.py +0 -0
  195. {execweave-0.8.4 → execweave-0.8.5}/scripts/sync_i18n_nav.py +0 -0
  196. {execweave-0.8.4 → execweave-0.8.5}/src/execweave/__main__.py +0 -0
  197. {execweave-0.8.4 → execweave-0.8.5}/src/execweave/_conversation_records_core.py +0 -0
  198. {execweave-0.8.4 → execweave-0.8.5}/src/execweave/agent_bootstrap.py +0 -0
  199. {execweave-0.8.4 → execweave-0.8.5}/src/execweave/agent_topology.py +0 -0
  200. {execweave-0.8.4 → execweave-0.8.5}/src/execweave/agent_trace.py +0 -0
  201. {execweave-0.8.4 → execweave-0.8.5}/src/execweave/analysis.py +0 -0
  202. {execweave-0.8.4 → execweave-0.8.5}/src/execweave/anthropic.py +0 -0
  203. {execweave-0.8.4 → execweave-0.8.5}/src/execweave/anthropic_cli.py +0 -0
  204. {execweave-0.8.4 → execweave-0.8.5}/src/execweave/anthropic_full_fidelity.py +0 -0
  205. {execweave-0.8.4 → execweave-0.8.5}/src/execweave/antigravity_adapter.py +0 -0
  206. {execweave-0.8.4 → execweave-0.8.5}/src/execweave/antigravity_adapter_base.py +0 -0
  207. {execweave-0.8.4 → execweave-0.8.5}/src/execweave/antigravity_full_fidelity.py +0 -0
  208. {execweave-0.8.4 → execweave-0.8.5}/src/execweave/antigravity_full_fidelity_collaboration_base.py +0 -0
  209. {execweave-0.8.4 → execweave-0.8.5}/src/execweave/antigravity_hook_cli.py +0 -0
  210. {execweave-0.8.4 → execweave-0.8.5}/src/execweave/antigravity_record.py +0 -0
  211. {execweave-0.8.4 → execweave-0.8.5}/src/execweave/antigravity_subagent_linkage.py +0 -0
  212. {execweave-0.8.4 → execweave-0.8.5}/src/execweave/antigravity_trace_capability.py +0 -0
  213. {execweave-0.8.4 → execweave-0.8.5}/src/execweave/backends.py +0 -0
  214. {execweave-0.8.4 → execweave-0.8.5}/src/execweave/benchmark.py +0 -0
  215. {execweave-0.8.4 → execweave-0.8.5}/src/execweave/claude_adapter.py +0 -0
  216. {execweave-0.8.4 → execweave-0.8.5}/src/execweave/claude_delegation.py +0 -0
  217. {execweave-0.8.4 → execweave-0.8.5}/src/execweave/claude_full_fidelity.py +0 -0
  218. {execweave-0.8.4 → execweave-0.8.5}/src/execweave/claude_hook_cli.py +0 -0
  219. {execweave-0.8.4 → execweave-0.8.5}/src/execweave/claude_hook_contract.py +0 -0
  220. {execweave-0.8.4 → execweave-0.8.5}/src/execweave/claude_model_observer.py +0 -0
  221. {execweave-0.8.4 → execweave-0.8.5}/src/execweave/claude_record.py +0 -0
  222. {execweave-0.8.4 → execweave-0.8.5}/src/execweave/cli.py +0 -0
  223. {execweave-0.8.4 → execweave-0.8.5}/src/execweave/codex_adapter.py +0 -0
  224. {execweave-0.8.4 → execweave-0.8.5}/src/execweave/codex_conversation.py +0 -0
  225. {execweave-0.8.4 → execweave-0.8.5}/src/execweave/codex_full_fidelity.py +0 -0
  226. {execweave-0.8.4 → execweave-0.8.5}/src/execweave/codex_hook_cli.py +0 -0
  227. {execweave-0.8.4 → execweave-0.8.5}/src/execweave/codex_hook_lifecycle.py +0 -0
  228. {execweave-0.8.4 → execweave-0.8.5}/src/execweave/codex_message_diagnostics.py +0 -0
  229. {execweave-0.8.4 → execweave-0.8.5}/src/execweave/codex_message_transport_diagnostics.py +0 -0
  230. {execweave-0.8.4 → execweave-0.8.5}/src/execweave/codex_record.py +0 -0
  231. {execweave-0.8.4 → execweave-0.8.5}/src/execweave/codex_rollout_structures.py +0 -0
  232. {execweave-0.8.4 → execweave-0.8.5}/src/execweave/codex_rollout_trace.py +0 -0
  233. {execweave-0.8.4 → execweave-0.8.5}/src/execweave/codex_rollout_trace_base.py +0 -0
  234. {execweave-0.8.4 → execweave-0.8.5}/src/execweave/command.py +0 -0
  235. {execweave-0.8.4 → execweave-0.8.5}/src/execweave/content_evidence.py +0 -0
  236. {execweave-0.8.4 → execweave-0.8.5}/src/execweave/content_store.py +0 -0
  237. {execweave-0.8.4 → execweave-0.8.5}/src/execweave/conversation_archive.py +0 -0
  238. {execweave-0.8.4 → execweave-0.8.5}/src/execweave/conversation_message_identity.py +0 -0
  239. {execweave-0.8.4 → execweave-0.8.5}/src/execweave/correlation.py +0 -0
  240. {execweave-0.8.4 → execweave-0.8.5}/src/execweave/cursor_adapter.py +0 -0
  241. {execweave-0.8.4 → execweave-0.8.5}/src/execweave/cursor_delegation.py +0 -0
  242. {execweave-0.8.4 → execweave-0.8.5}/src/execweave/cursor_delegation_base.py +0 -0
  243. {execweave-0.8.4 → execweave-0.8.5}/src/execweave/cursor_full_fidelity.py +0 -0
  244. {execweave-0.8.4 → execweave-0.8.5}/src/execweave/cursor_hook_cli.py +0 -0
  245. {execweave-0.8.4 → execweave-0.8.5}/src/execweave/cursor_hook_contract.py +0 -0
  246. {execweave-0.8.4 → execweave-0.8.5}/src/execweave/cursor_record.py +0 -0
  247. {execweave-0.8.4 → execweave-0.8.5}/src/execweave/dashboard_shell.py +0 -0
  248. {execweave-0.8.4 → execweave-0.8.5}/src/execweave/entry.py +0 -0
  249. {execweave-0.8.4 → execweave-0.8.5}/src/execweave/evidence_availability.py +0 -0
  250. {execweave-0.8.4 → execweave-0.8.5}/src/execweave/evidence_grade.py +0 -0
  251. {execweave-0.8.4 → execweave-0.8.5}/src/execweave/fidelity.py +0 -0
  252. {execweave-0.8.4 → execweave-0.8.5}/src/execweave/filesystem.py +0 -0
  253. {execweave-0.8.4 → execweave-0.8.5}/src/execweave/focus.py +0 -0
  254. {execweave-0.8.4 → execweave-0.8.5}/src/execweave/gemini_adapter.py +0 -0
  255. {execweave-0.8.4 → execweave-0.8.5}/src/execweave/gemini_full_fidelity.py +0 -0
  256. {execweave-0.8.4 → execweave-0.8.5}/src/execweave/gemini_hook_cli.py +0 -0
  257. {execweave-0.8.4 → execweave-0.8.5}/src/execweave/gemini_hook_contract.py +0 -0
  258. {execweave-0.8.4 → execweave-0.8.5}/src/execweave/gemini_record.py +0 -0
  259. {execweave-0.8.4 → execweave-0.8.5}/src/execweave/graph.py +0 -0
  260. {execweave-0.8.4 → execweave-0.8.5}/src/execweave/graph_ops.py +0 -0
  261. {execweave-0.8.4 → execweave-0.8.5}/src/execweave/http_proxy.py +0 -0
  262. {execweave-0.8.4 → execweave-0.8.5}/src/execweave/http_proxy_cli.py +0 -0
  263. {execweave-0.8.4 → execweave-0.8.5}/src/execweave/inference_gateway.py +0 -0
  264. {execweave-0.8.4 → execweave-0.8.5}/src/execweave/inference_gateway_cli.py +0 -0
  265. {execweave-0.8.4 → execweave-0.8.5}/src/execweave/inference_gateway_full_fidelity.py +0 -0
  266. {execweave-0.8.4 → execweave-0.8.5}/src/execweave/inference_identity.py +0 -0
  267. {execweave-0.8.4 → execweave-0.8.5}/src/execweave/inference_identity_cli.py +0 -0
  268. {execweave-0.8.4 → execweave-0.8.5}/src/execweave/integrity.py +0 -0
  269. {execweave-0.8.4 → execweave-0.8.5}/src/execweave/integrity_cli.py +0 -0
  270. {execweave-0.8.4 → execweave-0.8.5}/src/execweave/litellm_callback.py +0 -0
  271. {execweave-0.8.4 → execweave-0.8.5}/src/execweave/litellm_callback_cli.py +0 -0
  272. {execweave-0.8.4 → execweave-0.8.5}/src/execweave/live.py +0 -0
  273. {execweave-0.8.4 → execweave-0.8.5}/src/execweave/live_core.py +0 -0
  274. {execweave-0.8.4 → execweave-0.8.5}/src/execweave/live_view.py +0 -0
  275. {execweave-0.8.4 → execweave-0.8.5}/src/execweave/live_view_extra_style.py +0 -0
  276. {execweave-0.8.4 → execweave-0.8.5}/src/execweave/live_view_markup.py +0 -0
  277. {execweave-0.8.4 → execweave-0.8.5}/src/execweave/live_view_readability.py +0 -0
  278. {execweave-0.8.4 → execweave-0.8.5}/src/execweave/live_view_script_a.py +0 -0
  279. {execweave-0.8.4 → execweave-0.8.5}/src/execweave/live_view_script_b.py +0 -0
  280. {execweave-0.8.4 → execweave-0.8.5}/src/execweave/live_view_script_c.py +0 -0
  281. {execweave-0.8.4 → execweave-0.8.5}/src/execweave/live_view_script_d.py +0 -0
  282. {execweave-0.8.4 → execweave-0.8.5}/src/execweave/live_view_style.py +0 -0
  283. {execweave-0.8.4 → execweave-0.8.5}/src/execweave/model_runtime.py +0 -0
  284. {execweave-0.8.4 → execweave-0.8.5}/src/execweave/model_runtime_cli.py +0 -0
  285. {execweave-0.8.4 → execweave-0.8.5}/src/execweave/openai_compatible.py +0 -0
  286. {execweave-0.8.4 → execweave-0.8.5}/src/execweave/openai_compatible_cli.py +0 -0
  287. {execweave-0.8.4 → execweave-0.8.5}/src/execweave/openai_compatible_full_fidelity.py +0 -0
  288. {execweave-0.8.4 → execweave-0.8.5}/src/execweave/opencode_adapter.py +0 -0
  289. {execweave-0.8.4 → execweave-0.8.5}/src/execweave/opencode_event_contract.py +0 -0
  290. {execweave-0.8.4 → execweave-0.8.5}/src/execweave/opencode_full_fidelity.py +0 -0
  291. {execweave-0.8.4 → execweave-0.8.5}/src/execweave/opencode_hook_cli.py +0 -0
  292. {execweave-0.8.4 → execweave-0.8.5}/src/execweave/opencode_plugin_cli.py +0 -0
  293. {execweave-0.8.4 → execweave-0.8.5}/src/execweave/opencode_record.py +0 -0
  294. {execweave-0.8.4 → execweave-0.8.5}/src/execweave/opencode_task_linkage.py +0 -0
  295. {execweave-0.8.4 → execweave-0.8.5}/src/execweave/overhead_benchmark.py +0 -0
  296. {execweave-0.8.4 → execweave-0.8.5}/src/execweave/provider_capability.py +0 -0
  297. {execweave-0.8.4 → execweave-0.8.5}/src/execweave/provider_lifecycle.py +0 -0
  298. {execweave-0.8.4 → execweave-0.8.5}/src/execweave/provider_record.py +0 -0
  299. {execweave-0.8.4 → execweave-0.8.5}/src/execweave/rule_pack.py +0 -0
  300. {execweave-0.8.4 → execweave-0.8.5}/src/execweave/rule_pack_cli.py +0 -0
  301. {execweave-0.8.4 → execweave-0.8.5}/src/execweave/scalability_benchmark.py +0 -0
  302. {execweave-0.8.4 → execweave-0.8.5}/src/execweave/schema.py +0 -0
  303. {execweave-0.8.4 → execweave-0.8.5}/src/execweave/scope.py +0 -0
  304. {execweave-0.8.4 → execweave-0.8.5}/src/execweave/semantic.py +0 -0
  305. {execweave-0.8.4 → execweave-0.8.5}/src/execweave/sink.py +0 -0
  306. {execweave-0.8.4 → execweave-0.8.5}/src/execweave/stream_assembly.py +0 -0
  307. {execweave-0.8.4 → execweave-0.8.5}/src/execweave/theme.py +0 -0
  308. {execweave-0.8.4 → execweave-0.8.5}/src/execweave/top.py +0 -0
  309. {execweave-0.8.4 → execweave-0.8.5}/src/execweave/top_cli.py +0 -0
  310. {execweave-0.8.4 → execweave-0.8.5}/src/execweave/validate.py +0 -0
  311. {execweave-0.8.4 → execweave-0.8.5}/src/execweave/view_cli.py +0 -0
  312. {execweave-0.8.4 → execweave-0.8.5}/src/execweave/viewer.py +0 -0
  313. {execweave-0.8.4 → execweave-0.8.5}/src/execweave/viewer_content_inspector.py +0 -0
  314. {execweave-0.8.4 → execweave-0.8.5}/src/execweave/viewer_dashboard_clean.py +0 -0
  315. {execweave-0.8.4 → execweave-0.8.5}/src/execweave/viewer_dashboard_hardening.py +0 -0
  316. {execweave-0.8.4 → execweave-0.8.5}/src/execweave/viewer_dashboard_hardening_v2.py +0 -0
  317. {execweave-0.8.4 → execweave-0.8.5}/src/execweave/viewer_live_layout.py +0 -0
  318. {execweave-0.8.4 → execweave-0.8.5}/src/execweave/viewer_projection.py +0 -0
  319. {execweave-0.8.4 → execweave-0.8.5}/src/execweave/viewer_projection_base.py +0 -0
  320. {execweave-0.8.4 → execweave-0.8.5}/src/execweave/workflow.py +0 -0
  321. {execweave-0.8.4 → execweave-0.8.5}/tests/dashboard_readability_fixture.py +0 -0
  322. {execweave-0.8.4 → execweave-0.8.5}/tests/fixtures/codex_multi_agent/PROVENANCE.md +0 -0
  323. {execweave-0.8.4 → execweave-0.8.5}/tests/fixtures/codex_multi_agent/hook-payloads.json +0 -0
  324. {execweave-0.8.4 → execweave-0.8.5}/tests/fixtures/codex_multi_agent/rollout-main.jsonl +0 -0
  325. {execweave-0.8.4 → execweave-0.8.5}/tests/fixtures/hooks/README.md +0 -0
  326. {execweave-0.8.4 → execweave-0.8.5}/tests/fixtures/hooks/claude.json +0 -0
  327. {execweave-0.8.4 → execweave-0.8.5}/tests/fixtures/hooks/codex.json +0 -0
  328. {execweave-0.8.4 → execweave-0.8.5}/tests/fixtures/hooks/cursor.json +0 -0
  329. {execweave-0.8.4 → execweave-0.8.5}/tests/fixtures/hooks/gemini.json +0 -0
  330. {execweave-0.8.4 → execweave-0.8.5}/tests/fixtures/hooks/manifest.json +0 -0
  331. {execweave-0.8.4 → execweave-0.8.5}/tests/fixtures/hooks/opencode.json +0 -0
  332. {execweave-0.8.4 → execweave-0.8.5}/tests/multi_agent_run_fixture.py +0 -0
  333. {execweave-0.8.4 → execweave-0.8.5}/tests/test_agent_bootstrap.py +0 -0
  334. {execweave-0.8.4 → execweave-0.8.5}/tests/test_agent_message_viewer.py +0 -0
  335. {execweave-0.8.4 → execweave-0.8.5}/tests/test_agent_node_labels.py +0 -0
  336. {execweave-0.8.4 → execweave-0.8.5}/tests/test_agent_said_panel.py +0 -0
  337. {execweave-0.8.4 → execweave-0.8.5}/tests/test_agent_topology_evidence.py +0 -0
  338. {execweave-0.8.4 → execweave-0.8.5}/tests/test_agent_trace_lifecycle.py +0 -0
  339. {execweave-0.8.4 → execweave-0.8.5}/tests/test_agent_trace_viewer_visibility.py +0 -0
  340. {execweave-0.8.4 → execweave-0.8.5}/tests/test_analysis.py +0 -0
  341. {execweave-0.8.4 → execweave-0.8.5}/tests/test_anthropic.py +0 -0
  342. {execweave-0.8.4 → execweave-0.8.5}/tests/test_antigravity_agent_collaboration.py +0 -0
  343. {execweave-0.8.4 → execweave-0.8.5}/tests/test_antigravity_cursor_launch.py +0 -0
  344. {execweave-0.8.4 → execweave-0.8.5}/tests/test_antigravity_history_replay.py +0 -0
  345. {execweave-0.8.4 → execweave-0.8.5}/tests/test_antigravity_identity_topology.py +0 -0
  346. {execweave-0.8.4 → execweave-0.8.5}/tests/test_antigravity_lifecycle.py +0 -0
  347. {execweave-0.8.4 → execweave-0.8.5}/tests/test_antigravity_linkage_projection.py +0 -0
  348. {execweave-0.8.4 → execweave-0.8.5}/tests/test_antigravity_multi_conversation_isolation.py +0 -0
  349. {execweave-0.8.4 → execweave-0.8.5}/tests/test_antigravity_official_contract.py +0 -0
  350. {execweave-0.8.4 → execweave-0.8.5}/tests/test_antigravity_subagent_transcript_linkage.py +0 -0
  351. {execweave-0.8.4 → execweave-0.8.5}/tests/test_antigravity_trace_capability_cli.py +0 -0
  352. {execweave-0.8.4 → execweave-0.8.5}/tests/test_auto_specialized.py +0 -0
  353. {execweave-0.8.4 → execweave-0.8.5}/tests/test_backends.py +0 -0
  354. {execweave-0.8.4 → execweave-0.8.5}/tests/test_claude_adapter.py +0 -0
  355. {execweave-0.8.4 → execweave-0.8.5}/tests/test_claude_delegation.py +0 -0
  356. {execweave-0.8.4 → execweave-0.8.5}/tests/test_claude_full_fidelity.py +0 -0
  357. {execweave-0.8.4 → execweave-0.8.5}/tests/test_claude_hook_contract.py +0 -0
  358. {execweave-0.8.4 → execweave-0.8.5}/tests/test_claude_hook_metadata.py +0 -0
  359. {execweave-0.8.4 → execweave-0.8.5}/tests/test_claude_hook_viewer.py +0 -0
  360. {execweave-0.8.4 → execweave-0.8.5}/tests/test_claude_model_observer.py +0 -0
  361. {execweave-0.8.4 → execweave-0.8.5}/tests/test_claude_record.py +0 -0
  362. {execweave-0.8.4 → execweave-0.8.5}/tests/test_codex_adapter.py +0 -0
  363. {execweave-0.8.4 → execweave-0.8.5}/tests/test_codex_archive_full_fidelity.py +0 -0
  364. {execweave-0.8.4 → execweave-0.8.5}/tests/test_codex_conversation_isolation.py +0 -0
  365. {execweave-0.8.4 → execweave-0.8.5}/tests/test_codex_full_fidelity.py +0 -0
  366. {execweave-0.8.4 → execweave-0.8.5}/tests/test_codex_hook_lifecycle.py +0 -0
  367. {execweave-0.8.4 → execweave-0.8.5}/tests/test_codex_hook_partial_capture.py +0 -0
  368. {execweave-0.8.4 → execweave-0.8.5}/tests/test_codex_message_diagnostics.py +0 -0
  369. {execweave-0.8.4 → execweave-0.8.5}/tests/test_codex_message_transport_diagnostics.py +0 -0
  370. {execweave-0.8.4 → execweave-0.8.5}/tests/test_codex_plain_routed_agent_message.py +0 -0
  371. {execweave-0.8.4 → execweave-0.8.5}/tests/test_codex_real_multi_agent_conversation.py +0 -0
  372. {execweave-0.8.4 → execweave-0.8.5}/tests/test_codex_record.py +0 -0
  373. {execweave-0.8.4 → execweave-0.8.5}/tests/test_codex_reducer_command.py +0 -0
  374. {execweave-0.8.4 → execweave-0.8.5}/tests/test_codex_rollout_structures.py +0 -0
  375. {execweave-0.8.4 → execweave-0.8.5}/tests/test_codex_rollout_trace.py +0 -0
  376. {execweave-0.8.4 → execweave-0.8.5}/tests/test_codex_routing_native_identity.py +0 -0
  377. {execweave-0.8.4 → execweave-0.8.5}/tests/test_collector.py +0 -0
  378. {execweave-0.8.4 → execweave-0.8.5}/tests/test_command.py +0 -0
  379. {execweave-0.8.4 → execweave-0.8.5}/tests/test_condense.py +0 -0
  380. {execweave-0.8.4 → execweave-0.8.5}/tests/test_conversation_access.py +0 -0
  381. {execweave-0.8.4 → execweave-0.8.5}/tests/test_conversation_agent_focus.py +0 -0
  382. {execweave-0.8.4 → execweave-0.8.5}/tests/test_conversation_agent_isolation.py +0 -0
  383. {execweave-0.8.4 → execweave-0.8.5}/tests/test_conversation_identity_merge.py +0 -0
  384. {execweave-0.8.4 → execweave-0.8.5}/tests/test_conversation_message_observation_dedupe.py +0 -0
  385. {execweave-0.8.4 → execweave-0.8.5}/tests/test_conversation_provider_parity.py +0 -0
  386. {execweave-0.8.4 → execweave-0.8.5}/tests/test_conversation_root_authority.py +0 -0
  387. {execweave-0.8.4 → execweave-0.8.5}/tests/test_correlation.py +0 -0
  388. {execweave-0.8.4 → execweave-0.8.5}/tests/test_correlation_canonical_path.py +0 -0
  389. {execweave-0.8.4 → execweave-0.8.5}/tests/test_correlation_checker.py +0 -0
  390. {execweave-0.8.4 → execweave-0.8.5}/tests/test_correlation_process_exe.py +0 -0
  391. {execweave-0.8.4 → execweave-0.8.5}/tests/test_cross_provider_agent_trace.py +0 -0
  392. {execweave-0.8.4 → execweave-0.8.5}/tests/test_cursor_adapter.py +0 -0
  393. {execweave-0.8.4 → execweave-0.8.5}/tests/test_cursor_delegation.py +0 -0
  394. {execweave-0.8.4 → execweave-0.8.5}/tests/test_cursor_full_fidelity.py +0 -0
  395. {execweave-0.8.4 → execweave-0.8.5}/tests/test_cursor_hook_contract.py +0 -0
  396. {execweave-0.8.4 → execweave-0.8.5}/tests/test_cursor_hook_fail_open.py +0 -0
  397. {execweave-0.8.4 → execweave-0.8.5}/tests/test_cursor_record.py +0 -0
  398. {execweave-0.8.4 → execweave-0.8.5}/tests/test_cursor_task_linkage.py +0 -0
  399. {execweave-0.8.4 → execweave-0.8.5}/tests/test_dashboard_information_architecture.py +0 -0
  400. {execweave-0.8.4 → execweave-0.8.5}/tests/test_dashboard_readability_e2e.py +0 -0
  401. {execweave-0.8.4 → execweave-0.8.5}/tests/test_dashboard_round_fold_state_e2e.py +0 -0
  402. {execweave-0.8.4 → execweave-0.8.5}/tests/test_dashboard_simplification.py +0 -0
  403. {execweave-0.8.4 → execweave-0.8.5}/tests/test_dashboard_ux_and_hook_projection.py +0 -0
  404. {execweave-0.8.4 → execweave-0.8.5}/tests/test_delegation_viewer.py +0 -0
  405. {execweave-0.8.4 → execweave-0.8.5}/tests/test_evidence_grade.py +0 -0
  406. {execweave-0.8.4 → execweave-0.8.5}/tests/test_execution_viewer.py +0 -0
  407. {execweave-0.8.4 → execweave-0.8.5}/tests/test_fidelity.py +0 -0
  408. {execweave-0.8.4 → execweave-0.8.5}/tests/test_filesystem_resilience.py +0 -0
  409. {execweave-0.8.4 → execweave-0.8.5}/tests/test_focus.py +0 -0
  410. {execweave-0.8.4 → execweave-0.8.5}/tests/test_fold_budget_setting.py +0 -0
  411. {execweave-0.8.4 → execweave-0.8.5}/tests/test_full_fidelity.py +0 -0
  412. {execweave-0.8.4 → execweave-0.8.5}/tests/test_gemini_adapter.py +0 -0
  413. {execweave-0.8.4 → execweave-0.8.5}/tests/test_gemini_full_fidelity.py +0 -0
  414. {execweave-0.8.4 → execweave-0.8.5}/tests/test_gemini_hook_contract.py +0 -0
  415. {execweave-0.8.4 → execweave-0.8.5}/tests/test_gemini_lifecycle.py +0 -0
  416. {execweave-0.8.4 → execweave-0.8.5}/tests/test_gemini_record.py +0 -0
  417. {execweave-0.8.4 → execweave-0.8.5}/tests/test_graph.py +0 -0
  418. {execweave-0.8.4 → execweave-0.8.5}/tests/test_graph_clear_focus_e2e.py +0 -0
  419. {execweave-0.8.4 → execweave-0.8.5}/tests/test_graph_edge_routing_e2e.py +0 -0
  420. {execweave-0.8.4 → execweave-0.8.5}/tests/test_graph_lane_separation_e2e.py +0 -0
  421. {execweave-0.8.4 → execweave-0.8.5}/tests/test_graph_node_sizing_e2e.py +0 -0
  422. {execweave-0.8.4 → execweave-0.8.5}/tests/test_graph_ops.py +0 -0
  423. {execweave-0.8.4 → execweave-0.8.5}/tests/test_hook_fixture_corpus.py +0 -0
  424. {execweave-0.8.4 → execweave-0.8.5}/tests/test_http_proxy.py +0 -0
  425. {execweave-0.8.4 → execweave-0.8.5}/tests/test_inference_endpoint_identity.py +0 -0
  426. {execweave-0.8.4 → execweave-0.8.5}/tests/test_inference_gateway.py +0 -0
  427. {execweave-0.8.4 → execweave-0.8.5}/tests/test_inference_gateway_full_fidelity.py +0 -0
  428. {execweave-0.8.4 → execweave-0.8.5}/tests/test_inference_identity.py +0 -0
  429. {execweave-0.8.4 → execweave-0.8.5}/tests/test_integrity.py +0 -0
  430. {execweave-0.8.4 → execweave-0.8.5}/tests/test_litellm_callback.py +0 -0
  431. {execweave-0.8.4 → execweave-0.8.5}/tests/test_live.py +0 -0
  432. {execweave-0.8.4 → execweave-0.8.5}/tests/test_live_auth.py +0 -0
  433. {execweave-0.8.4 → execweave-0.8.5}/tests/test_live_dashboard.py +0 -0
  434. {execweave-0.8.4 → execweave-0.8.5}/tests/test_live_dashboard_js.py +0 -0
  435. {execweave-0.8.4 → execweave-0.8.5}/tests/test_live_delta.py +0 -0
  436. {execweave-0.8.4 → execweave-0.8.5}/tests/test_live_logs_export.py +0 -0
  437. {execweave-0.8.4 → execweave-0.8.5}/tests/test_live_theme.py +0 -0
  438. {execweave-0.8.4 → execweave-0.8.5}/tests/test_lmstudio_auto_specialized.py +0 -0
  439. {execweave-0.8.4 → execweave-0.8.5}/tests/test_local_runtime_live_capture.py +0 -0
  440. {execweave-0.8.4 → execweave-0.8.5}/tests/test_model_runtime.py +0 -0
  441. {execweave-0.8.4 → execweave-0.8.5}/tests/test_model_runtime_full_fidelity.py +0 -0
  442. {execweave-0.8.4 → execweave-0.8.5}/tests/test_openai_compatible.py +0 -0
  443. {execweave-0.8.4 → execweave-0.8.5}/tests/test_opencode_adapter.py +0 -0
  444. {execweave-0.8.4 → execweave-0.8.5}/tests/test_opencode_event_contract.py +0 -0
  445. {execweave-0.8.4 → execweave-0.8.5}/tests/test_opencode_event_lifecycle.py +0 -0
  446. {execweave-0.8.4 → execweave-0.8.5}/tests/test_opencode_full_fidelity.py +0 -0
  447. {execweave-0.8.4 → execweave-0.8.5}/tests/test_opencode_identity_unification.py +0 -0
  448. {execweave-0.8.4 → execweave-0.8.5}/tests/test_opencode_plugin.py +0 -0
  449. {execweave-0.8.4 → execweave-0.8.5}/tests/test_opencode_record.py +0 -0
  450. {execweave-0.8.4 → execweave-0.8.5}/tests/test_opencode_task_session_linkage.py +0 -0
  451. {execweave-0.8.4 → execweave-0.8.5}/tests/test_overhead_benchmark.py +0 -0
  452. {execweave-0.8.4 → execweave-0.8.5}/tests/test_per_agent_conversation_default.py +0 -0
  453. {execweave-0.8.4 → execweave-0.8.5}/tests/test_pr25_premerge_hardening_contract.py +0 -0
  454. {execweave-0.8.4 → execweave-0.8.5}/tests/test_pr25_premerge_hardening_e2e.py +0 -0
  455. {execweave-0.8.4 → execweave-0.8.5}/tests/test_provider_capability.py +0 -0
  456. {execweave-0.8.4 → execweave-0.8.5}/tests/test_provider_conversation_evidence.py +0 -0
  457. {execweave-0.8.4 → execweave-0.8.5}/tests/test_provider_lifecycle.py +0 -0
  458. {execweave-0.8.4 → execweave-0.8.5}/tests/test_release_stage_integrity_version_guard.py +0 -0
  459. {execweave-0.8.4 → execweave-0.8.5}/tests/test_rule_pack.py +0 -0
  460. {execweave-0.8.4 → execweave-0.8.5}/tests/test_schema.py +0 -0
  461. {execweave-0.8.4 → execweave-0.8.5}/tests/test_scope.py +0 -0
  462. {execweave-0.8.4 → execweave-0.8.5}/tests/test_semantic.py +0 -0
  463. {execweave-0.8.4 → execweave-0.8.5}/tests/test_shared_injected_context_scope.py +0 -0
  464. {execweave-0.8.4 → execweave-0.8.5}/tests/test_strace_backend.py +0 -0
  465. {execweave-0.8.4 → execweave-0.8.5}/tests/test_stream_assembly.py +0 -0
  466. {execweave-0.8.4 → execweave-0.8.5}/tests/test_threat_model.py +0 -0
  467. {execweave-0.8.4 → execweave-0.8.5}/tests/test_tool_traffic_e2e.py +0 -0
  468. {execweave-0.8.4 → execweave-0.8.5}/tests/test_top_detached.py +0 -0
  469. {execweave-0.8.4 → execweave-0.8.5}/tests/test_v063_features.py +0 -0
  470. {execweave-0.8.4 → execweave-0.8.5}/tests/test_v064_live_auto_integrations.py +0 -0
  471. {execweave-0.8.4 → execweave-0.8.5}/tests/test_v064_live_evidence.py +0 -0
  472. {execweave-0.8.4 → execweave-0.8.5}/tests/test_v079_review_e2e.py +0 -0
  473. {execweave-0.8.4 → execweave-0.8.5}/tests/test_v079_review_regressions.py +0 -0
  474. {execweave-0.8.4 → execweave-0.8.5}/tests/test_v083_release_gate_p2.py +0 -0
  475. {execweave-0.8.4 → execweave-0.8.5}/tests/test_validate.py +0 -0
  476. {execweave-0.8.4 → execweave-0.8.5}/tests/test_version.py +0 -0
  477. {execweave-0.8.4 → execweave-0.8.5}/tests/test_viewer.py +0 -0
  478. {execweave-0.8.4 → execweave-0.8.5}/tests/test_viewer_agent_isolation_e2e.py +0 -0
  479. {execweave-0.8.4 → execweave-0.8.5}/tests/test_viewer_child_authority.py +0 -0
  480. {execweave-0.8.4 → execweave-0.8.5}/tests/test_viewer_content_inspector.py +0 -0
  481. {execweave-0.8.4 → execweave-0.8.5}/tests/test_viewer_projection.py +0 -0
  482. {execweave-0.8.4 → execweave-0.8.5}/tests/test_workflow.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: execweave
3
- Version: 0.8.4
3
+ Version: 0.8.5
4
4
  Summary: Turn AI-agent runtime behavior into a local interactive execution graph.
5
5
  Project-URL: Homepage, https://github.com/Irish-kw/ExecWeave
6
6
  Project-URL: Repository, https://github.com/Irish-kw/ExecWeave
@@ -83,7 +83,7 @@ ExecWeave is a source-available, local-first observability project that turns AI
83
83
  <img src="docs/assets/codex.gif" alt="ExecWeave animated live demo" width="100%">
84
84
  </p>
85
85
 
86
- This README documents **v0.8.4**.
86
+ This README documents **v0.8.5**.
87
87
 
88
88
  ## Why ExecWeave
89
89
 
@@ -30,7 +30,7 @@ ExecWeave ist ein source-available, local-first Observability-Projekt, das Aktiv
30
30
  <img src="docs/assets/codex.gif" alt="ExecWeave animated live demo" width="100%">
31
31
  </p>
32
32
 
33
- Dieses README dokumentiert **v0.8.4**.
33
+ Dieses README dokumentiert **v0.8.5**.
34
34
 
35
35
  ## Warum ExecWeave
36
36
 
@@ -30,7 +30,7 @@ ExecWeave est un projet d’observabilité source-available et local-first qui t
30
30
  <img src="docs/assets/codex.gif" alt="ExecWeave animated live demo" width="100%">
31
31
  </p>
32
32
 
33
- Ce README décrit **v0.8.4**.
33
+ Ce README décrit **v0.8.5**.
34
34
 
35
35
  ## Pourquoi ExecWeave
36
36
 
@@ -30,7 +30,7 @@ ExecWeave は source-available / local-first の observability プロジェク
30
30
  <img src="docs/assets/codex.gif" alt="ExecWeave animated live demo" width="100%">
31
31
  </p>
32
32
 
33
- この README は **v0.8.4** を説明します。
33
+ この README は **v0.8.5** を説明します。
34
34
 
35
35
  ## ExecWeave を使う理由
36
36
 
@@ -30,7 +30,7 @@ ExecWeave는 source-available, local-first observability 프로젝트입니다.
30
30
  <img src="docs/assets/codex.gif" alt="ExecWeave animated live demo" width="100%">
31
31
  </p>
32
32
 
33
- 이 README는 **v0.8.4**을 설명합니다.
33
+ 이 README는 **v0.8.5**을 설명합니다.
34
34
 
35
35
  ## 왜 ExecWeave인가
36
36
 
@@ -30,7 +30,7 @@ ExecWeave is a source-available, local-first observability project that turns AI
30
30
  <img src="docs/assets/codex.gif" alt="ExecWeave animated live demo" width="100%">
31
31
  </p>
32
32
 
33
- This README documents **v0.8.4**.
33
+ This README documents **v0.8.5**.
34
34
 
35
35
  ## Why ExecWeave
36
36
 
@@ -30,7 +30,7 @@ ExecWeave — source-available, local-first проект наблюдаемос
30
30
  <img src="docs/assets/codex.gif" alt="ExecWeave animated live demo" width="100%">
31
31
  </p>
32
32
 
33
- Этот README описывает **v0.8.4**.
33
+ Этот README описывает **v0.8.5**.
34
34
 
35
35
  ## Почему ExecWeave
36
36
 
@@ -30,7 +30,7 @@ ExecWeave 是一个 source-available、local-first 的可观测性项目,把 A
30
30
  <img src="docs/assets/codex.gif" alt="ExecWeave animated live demo" width="100%">
31
31
  </p>
32
32
 
33
- 本 README 对应 **v0.8.4**。
33
+ 本 README 对应 **v0.8.5**。
34
34
 
35
35
  ## 为什么是 ExecWeave
36
36
 
@@ -30,7 +30,7 @@ ExecWeave 是一個 source-available、local-first 的可觀測性專案,會
30
30
  <img src="docs/assets/codex.gif" alt="ExecWeave animated live demo" width="100%">
31
31
  </p>
32
32
 
33
- 本 README 對應 **v0.8.4**。
33
+ 本 README 對應 **v0.8.5**。
34
34
 
35
35
  ## 為什麼是 ExecWeave
36
36
 
@@ -4,8 +4,8 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "execweave"
7
- # ExecWeave v0.8.4 release metadata
8
- version = "0.8.4"
7
+ # ExecWeave v0.8.5 release metadata
8
+ version = "0.8.5"
9
9
  description = "Turn AI-agent runtime behavior into a local interactive execution graph."
10
10
  readme = "README.md"
11
11
  requires-python = ">=3.10"
@@ -1,3 +1,3 @@
1
1
  """ExecWeave runtime graph package."""
2
2
 
3
- __version__ = "0.8.4"
3
+ __version__ = "0.8.5"
@@ -11,12 +11,24 @@ def _now() -> str:
11
11
  return datetime.now(timezone.utc).isoformat().replace("+00:00", "Z")
12
12
 
13
13
 
14
- def _agent() -> dict[str, Any]:
14
+ def _agent(payload: dict[str, Any]) -> dict[str, Any]:
15
+ conversation_id = payload.get("conversationId")
16
+ if isinstance(conversation_id, str) and conversation_id:
17
+ return {
18
+ "type": "agent",
19
+ "id": f"agent:antigravity:conversation:{conversation_id}",
20
+ "name": "Antigravity conversation",
21
+ "attributes": {
22
+ "provider": "antigravity",
23
+ "conversation_id": conversation_id,
24
+ "identity_semantics": "provider_conversation_id",
25
+ },
26
+ }
15
27
  return {
16
28
  "type": "agent",
17
29
  "id": "agent:Antigravity",
18
30
  "name": "Antigravity",
19
- "attributes": {},
31
+ "attributes": {"provider": "antigravity"},
20
32
  }
21
33
 
22
34
 
@@ -70,7 +82,7 @@ def antigravity_hook_to_content_events(
70
82
  content_observation_event(
71
83
  timestamp=observed_at,
72
84
  provider="antigravity",
73
- source=_agent(),
85
+ source=_agent(payload),
74
86
  reference=reference,
75
87
  relation="OBSERVED_PROVIDER_METADATA",
76
88
  observed_field="hook_metadata",
@@ -122,7 +134,7 @@ def antigravity_hook_to_content_events(
122
134
  content_observation_event(
123
135
  timestamp=observed_at,
124
136
  provider="antigravity",
125
- source=_agent(),
137
+ source=_agent(payload),
126
138
  reference=reference,
127
139
  relation="OBSERVED_TOOL_ERROR",
128
140
  observed_field="error",
@@ -54,6 +54,14 @@ def _is_ollama_serve(command: list[str]) -> bool:
54
54
  )
55
55
 
56
56
 
57
+ def _is_ollama_run(command: list[str]) -> bool:
58
+ return (
59
+ len(command) >= 2
60
+ and _command_name(command[0]) == "ollama"
61
+ and command[1].lower() == "run"
62
+ )
63
+
64
+
57
65
  def _is_llamacpp_server(command: list[str]) -> bool:
58
66
  return bool(command) and _command_name(command[0]) == "llama-server"
59
67
 
@@ -284,6 +292,48 @@ def run_post_command_specialized_probe(
284
292
  time.sleep(_POST_PROBE_RETRY_SECONDS)
285
293
 
286
294
 
295
+
296
+ @contextmanager
297
+ def auto_specialized_launch(command: list[str]) -> Iterator[dict[str, str]]:
298
+ """Prepare child-only launch wiring for supported transparent local integrations."""
299
+ environment = dict(os.environ)
300
+ configured_sidecar = os.environ.get(_SEMANTIC_ENV)
301
+ if not configured_sidecar or not _is_ollama_run(command):
302
+ yield environment
303
+ return
304
+ upstream = _ollama_endpoint_from_environment()
305
+ if upstream is None:
306
+ yield environment
307
+ return
308
+
309
+ from .http_proxy import ExecWeaveHTTPProxyServer, ProxyConfig
310
+
311
+ sidecar = Path(configured_sidecar).expanduser().resolve()
312
+ try:
313
+ server = ExecWeaveHTTPProxyServer(
314
+ ("127.0.0.1", 0),
315
+ ProxyConfig(upstream=upstream, sidecar=sidecar, mode="ollama"),
316
+ )
317
+ except OSError:
318
+ yield environment
319
+ return
320
+ thread = threading.Thread(
321
+ target=server.serve_forever,
322
+ kwargs={"poll_interval": 0.05},
323
+ name="execweave-ollama-run-relay",
324
+ daemon=True,
325
+ )
326
+ thread.start()
327
+ host, port = server.server_address[:2]
328
+ environment["OLLAMA_HOST"] = f"http://{host}:{port}"
329
+ try:
330
+ yield environment
331
+ finally:
332
+ server.shutdown()
333
+ server.server_close()
334
+ thread.join(timeout=2.0)
335
+
336
+
287
337
  @contextmanager
288
338
  def auto_specialized_probe(command: list[str]) -> Iterator[None]:
289
339
  """Run supported local specialized probes without affecting command execution.
@@ -10,6 +10,7 @@ from typing import Iterable
10
10
  import psutil
11
11
 
12
12
  from .auto_specialized import (
13
+ auto_specialized_launch,
13
14
  auto_specialized_probe,
14
15
  prepare_post_command_specialized_probe,
15
16
  run_post_command_specialized_probe,
@@ -95,6 +96,7 @@ def infer_agent_name(command: Iterable[str]) -> str:
95
96
  "gemini": "Gemini CLI",
96
97
  "cursor": "Cursor",
97
98
  "opencode": "OpenCode",
99
+ "ollama": "Ollama",
98
100
  }
99
101
  return known.get(executable, basename)
100
102
 
@@ -167,20 +169,25 @@ class RuntimeCollector:
167
169
  return_code = 1
168
170
  post_command_probe = prepare_post_command_specialized_probe(command)
169
171
  try:
170
- process = subprocess.Popen(launch_command, cwd=str(self.watch_root))
171
- root = psutil.Process(process.pid)
172
- snapshot = _safe_process_snapshot(root)
173
- if snapshot is not None:
174
- self._record_process_start(snapshot, parent=session, relation="LAUNCHED")
172
+ with auto_specialized_launch(command) as launch_environment:
173
+ process = subprocess.Popen(
174
+ launch_command,
175
+ cwd=str(self.watch_root),
176
+ env=launch_environment,
177
+ )
178
+ root = psutil.Process(process.pid)
179
+ snapshot = _safe_process_snapshot(root)
180
+ if snapshot is not None:
181
+ self._record_process_start(snapshot, parent=session, relation="LAUNCHED")
175
182
 
176
- with auto_specialized_probe(command):
177
- while process.poll() is None:
178
- self._sample_process_tree(root)
179
- time.sleep(self.poll_interval)
183
+ with auto_specialized_probe(command):
184
+ while process.poll() is None:
185
+ self._sample_process_tree(root)
186
+ time.sleep(self.poll_interval)
180
187
 
181
- self._sample_process_tree(root)
182
- self._mark_disappeared_processes(set())
183
- return_code = int(process.returncode or 0)
188
+ self._sample_process_tree(root)
189
+ self._mark_disappeared_processes(set())
190
+ return_code = int(process.returncode or 0)
184
191
  run_post_command_specialized_probe(
185
192
  post_command_probe,
186
193
  return_code=return_code,
@@ -1,6 +1,7 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  import json
4
+ import re
4
5
  from pathlib import Path
5
6
  from typing import Any
6
7
 
@@ -269,6 +270,18 @@ def _structured_messages(
269
270
  return messages
270
271
 
271
272
 
273
+ _ANTIGRAVITY_USER_REQUEST_RE = re.compile(
274
+ r"<USER_REQUEST>\s*(?P<body>.*?)\s*</USER_REQUEST>",
275
+ re.DOTALL,
276
+ )
277
+
278
+
279
+ def _antigravity_user_text(text: str) -> str:
280
+ """Return the actual user request, excluding Antigravity's metadata envelope."""
281
+ match = _ANTIGRAVITY_USER_REQUEST_RE.search(text)
282
+ return match.group("body").strip() if match is not None else text.strip()
283
+
284
+
272
285
  def _line_transcript_messages(
273
286
  path: Path,
274
287
  *,
@@ -291,26 +304,71 @@ def _line_transcript_messages(
291
304
  continue
292
305
  if not isinstance(record, dict):
293
306
  continue
307
+
308
+ if antigravity:
309
+ role = str(record.get("source") or "").strip().lower()
310
+ record_type = str(record.get("type") or "").strip().lower()
311
+ text = _text_parts(record.get("content") or record.get("text"))
312
+ record_timestamp = record.get("created_at") or record.get("timestamp") or timestamp
313
+ step_index = record.get("step_index")
314
+ record_ordinal = (
315
+ step_index
316
+ if isinstance(step_index, int) and not isinstance(step_index, bool)
317
+ else (ordinal if isinstance(ordinal, int) else 0) + index
318
+ )
319
+
320
+ # Current Antigravity uses USER_EXPLICIT / USER_INPUT for real user turns.
321
+ # Keep the older USER/HUMAN spelling for archived compatibility.
322
+ if role in {"user_explicit", "user", "human"} and record_type in {
323
+ "user_input",
324
+ "user_message",
325
+ "",
326
+ }:
327
+ if text:
328
+ messages.append(
329
+ _message(
330
+ timestamp=record_timestamp,
331
+ ordinal=record_ordinal,
332
+ kind="user_message",
333
+ sender="user",
334
+ recipient=agent_path,
335
+ text=_antigravity_user_text(text),
336
+ )
337
+ )
338
+ continue
339
+
340
+ # PLANNER_RESPONSE is Antigravity's user-visible model surface. GENERIC
341
+ # records are tool/runtime results (define_subagent, manage_subagents,
342
+ # schedule, send_message acknowledgements, ...), so they must never be
343
+ # eligible for the conversation Final response card.
344
+ if role in {"model", "assistant"} and record_type == "planner_response":
345
+ if text:
346
+ messages.append(
347
+ _message(
348
+ timestamp=record_timestamp,
349
+ ordinal=record_ordinal,
350
+ kind="assistant_message",
351
+ sender=agent_path,
352
+ recipient=None,
353
+ text=text,
354
+ phase="planner_response",
355
+ )
356
+ )
357
+ continue
358
+ continue
359
+
294
360
  record_timestamp = record.get("timestamp") or timestamp
295
361
  record_ordinal = record.get("ordinal")
296
362
  if not isinstance(record_ordinal, int):
297
363
  record_ordinal = (ordinal if isinstance(ordinal, int) else 0) + index
298
-
299
- if antigravity:
300
- role = str(record.get("source") or "").lower()
301
- text = _text_parts(record.get("content") or record.get("text"))
302
- phase = str(record.get("type") or "").lower() or "response"
364
+ record_type = str(record.get("type") or "").lower()
365
+ payload = record.get("message")
366
+ if isinstance(payload, dict):
367
+ role = str(payload.get("role") or record_type).lower()
368
+ text = _text_parts(payload.get("content"))
303
369
  else:
304
- record_type = str(record.get("type") or "").lower()
305
- payload = record.get("message")
306
- if isinstance(payload, dict):
307
- role = str(payload.get("role") or record_type).lower()
308
- text = _text_parts(payload.get("content"))
309
- else:
310
- role = record_type
311
- text = _text_parts(record.get("content") or record.get("text"))
312
- phase = "response"
313
-
370
+ role = record_type
371
+ text = _text_parts(record.get("content") or record.get("text"))
314
372
  if not text:
315
373
  continue
316
374
  if role in {"user", "human"}:
@@ -333,7 +391,7 @@ def _line_transcript_messages(
333
391
  sender=agent_path,
334
392
  recipient=None,
335
393
  text=text,
336
- phase=phase,
394
+ phase="response",
337
395
  )
338
396
  )
339
397
  return messages
@@ -722,7 +780,8 @@ def conversation_preview(
722
780
 
723
781
  if not messages:
724
782
  return None
725
- truncated = len(messages) > _MAX_PREVIEW_MESSAGES
783
+ preserve_history = content_kind.startswith("antigravity.conversation_transcript")
784
+ truncated = not preserve_history and len(messages) > _MAX_PREVIEW_MESSAGES
726
785
  if truncated:
727
786
  messages = messages[:10] + messages[-(_MAX_PREVIEW_MESSAGES - 10) :]
728
787
  return {
@@ -15,14 +15,7 @@ _core_merge_conversation_previews = _core._merge_conversation_previews
15
15
 
16
16
 
17
17
  def _antigravity_step_ordinals(path: str | Path) -> list[int | None]:
18
- """Recover stable provider record positions for visible Antigravity messages.
19
-
20
- Antigravity Stop archives are cumulative snapshots of the same transcript. The
21
- archive edge sequence therefore changes between snapshots and cannot identify a
22
- transcript record. Live-verified transcript records expose ``step_index``; use it
23
- when an explicit ``ordinal`` is absent so old turns keep the same identity across
24
- repeated Stop archives.
25
- """
18
+ """Recover stable step indexes for user-visible Antigravity transcript records."""
26
19
  source_path = Path(path).expanduser().resolve(strict=False)
27
20
  try:
28
21
  lines = source_path.read_text(encoding="utf-8").splitlines()
@@ -39,13 +32,17 @@ def _antigravity_step_ordinals(path: str | Path) -> list[int | None]:
39
32
  continue
40
33
  if not isinstance(record, dict):
41
34
  continue
42
- role = str(record.get("source") or "").lower()
43
- if role not in {"user", "human", "assistant", "model"}:
44
- continue
35
+ role = str(record.get("source") or "").strip().lower()
36
+ record_type = str(record.get("type") or "").strip().lower()
45
37
  text = _preview_module._text_parts(record.get("content") or record.get("text"))
46
- if not text:
38
+ visible_user = role in {"user_explicit", "user", "human"} and record_type in {
39
+ "user_input",
40
+ "user_message",
41
+ "",
42
+ }
43
+ visible_assistant = role in {"model", "assistant"} and record_type == "planner_response"
44
+ if not text or not (visible_user or visible_assistant):
47
45
  continue
48
-
49
46
  record_ordinal = record.get("ordinal")
50
47
  if isinstance(record_ordinal, int) and not isinstance(record_ordinal, bool):
51
48
  ordinals.append(record_ordinal)
@@ -224,6 +221,112 @@ def _same_merged_execution(
224
221
  return isinstance(observed_thread, str) and observed_thread in evidence_thread_ids
225
222
 
226
223
 
224
+
225
+ def _history_message_key(message: dict[str, Any]) -> tuple[object, ...]:
226
+ return (
227
+ message.get("ordinal"),
228
+ message.get("kind"),
229
+ message.get("sender"),
230
+ message.get("recipient"),
231
+ message.get("text"),
232
+ message.get("content_state"),
233
+ message.get("phase"),
234
+ message.get("task_name"),
235
+ )
236
+
237
+
238
+ def _restore_complete_histories(
239
+ entries: list[dict[str, Any]],
240
+ snapshots: list[tuple[dict[str, Any], dict[str, Any]]],
241
+ ) -> None:
242
+ """Never silently drop middle rounds for providers whose history is user-facing."""
243
+ for entry in entries:
244
+ provider = str(entry.get("provider") or "").lower()
245
+ if provider not in {"antigravity", "ollama"}:
246
+ continue
247
+ merged = entry.get("conversation_preview")
248
+ source_id = entry.get("source_id")
249
+ if not isinstance(merged, dict) or not isinstance(source_id, str) or not source_id:
250
+ continue
251
+ observed: list[dict[str, Any]] = []
252
+ for observed_entry, observed_preview in snapshots:
253
+ if str(observed_entry.get("provider") or "").lower() != provider:
254
+ continue
255
+ if observed_entry.get("source_id") != source_id:
256
+ continue
257
+ for message in observed_preview.get("messages") or []:
258
+ if isinstance(message, dict):
259
+ observed.append(dict(message))
260
+ if not observed:
261
+ continue
262
+ if provider == "ollama" and not any(
263
+ message.get("content_role")
264
+ in {"ollama_request_surface", "ollama_response_surface"}
265
+ for message in observed
266
+ ):
267
+ # Legacy/provider-neutral root records have no wire-surface provenance.
268
+ # Leave the core incremental merge untouched instead of applying the
269
+ # Ollama cumulative-history repair to unrelated synthetic/root records.
270
+ continue
271
+ indexed = list(enumerate(observed))
272
+ indexed.sort(
273
+ key=lambda pair: (
274
+ str(pair[1].get("timestamp") or ""),
275
+ pair[1].get("ordinal")
276
+ if isinstance(pair[1].get("ordinal"), int)
277
+ else 2**63 - 1,
278
+ pair[0],
279
+ )
280
+ )
281
+ seen: set[tuple[object, ...]] = set()
282
+ messages: list[dict[str, Any]] = []
283
+ for _, message in indexed:
284
+ key = _history_message_key(message)
285
+ if key in seen:
286
+ continue
287
+ seen.add(key)
288
+ messages.append(message)
289
+ merged["message_count"] = len(messages)
290
+ merged["messages_truncated"] = False
291
+ merged["messages"] = messages
292
+
293
+
294
+ def _ollama_current_turn(preview: dict[str, Any]) -> None:
295
+ """Reduce a cumulative Ollama chat request to the exact turn this exchange created."""
296
+ messages = [message for message in preview.get("messages") or [] if isinstance(message, dict)]
297
+ users = [
298
+ message
299
+ for message in messages
300
+ if message.get("sender") == "user"
301
+ and message.get("content_role") == "ollama_request_surface"
302
+ ]
303
+ response_assistants = [
304
+ message
305
+ for message in messages
306
+ if message.get("content_role") == "ollama_response_surface"
307
+ and str(message.get("kind") or "").startswith("assistant")
308
+ ]
309
+ if not users:
310
+ return
311
+ current = [users[-1]]
312
+ if response_assistants:
313
+ current.append(response_assistants[-1])
314
+ preview["message_count"] = len(current)
315
+ preview["messages_truncated"] = False
316
+ preview["messages"] = current
317
+
318
+
319
+ def _ollama_root_agent_id(graph: dict[str, Any]) -> str | None:
320
+ candidates = []
321
+ for node in graph.get("nodes", []):
322
+ if not isinstance(node, dict) or node.get("type") != "agent":
323
+ continue
324
+ node_id = node.get("id")
325
+ if isinstance(node_id, str) and node_id.lower() == "agent:ollama":
326
+ candidates.append(node_id)
327
+ return candidates[0] if len(candidates) == 1 else None
328
+
329
+
227
330
  def _merge_conversation_previews(entries: list[dict[str, Any]]) -> None:
228
331
  """Merge execution identity first, then reconcile duplicate Codex observations.
229
332
 
@@ -232,6 +335,28 @@ def _merge_conversation_previews(entries: list[dict[str, Any]]) -> None:
232
335
  aliases that changed during publication, then lets complementary Codex observations
233
336
  render once while retaining provenance. Raw evidence entries are never removed.
234
337
  """
338
+ # Preserve which side of an Ollama exchange produced each visible message.
339
+ # Cumulative request.messages can contain historical assistant text, so publication
340
+ # must select the assistant observed on the response surface rather than guessing
341
+ # from list position.
342
+ for entry in entries:
343
+ if str(entry.get("provider") or "").lower() != "ollama":
344
+ continue
345
+ preview = entry.get("conversation_preview")
346
+ if not isinstance(preview, dict):
347
+ continue
348
+ kind = str(entry.get("content_kind") or "").lower()
349
+ relation = str(entry.get("relation") or "").upper()
350
+ if "assistant_messages" in kind or relation == "OBSERVED_ASSISTANT_MESSAGES":
351
+ role = "ollama_response_surface"
352
+ elif "request_messages" in kind or "request_prompt" in kind or "request_input" in kind:
353
+ role = "ollama_request_surface"
354
+ else:
355
+ continue
356
+ for message in preview.get("messages") or []:
357
+ if isinstance(message, dict):
358
+ message["content_role"] = role
359
+
235
360
  snapshots: list[tuple[dict[str, Any], dict[str, Any]]] = []
236
361
  for entry in entries:
237
362
  preview = entry.get("conversation_preview")
@@ -253,6 +378,7 @@ def _merge_conversation_previews(entries: list[dict[str, Any]]) -> None:
253
378
 
254
379
  _core_merge_conversation_previews(entries)
255
380
  _repair_parent_thread_aliases(entries)
381
+ _restore_complete_histories(entries, snapshots)
256
382
 
257
383
  for entry in entries:
258
384
  if str(entry.get("provider") or "").lower() != "codex":
@@ -294,8 +420,48 @@ def _merge_conversation_previews(entries: list[dict[str, Any]]) -> None:
294
420
  merged_preview["messages"] = messages
295
421
 
296
422
 
423
+
424
+ _core_conversation_record_entries = _core.conversation_record_entries
425
+
426
+
427
+ def conversation_record_entries(
428
+ graph: dict[str, Any],
429
+ run_root: str | Path | None = None,
430
+ ) -> list[dict[str, Any]]:
431
+ """Publish root-only Ollama turns under the one run root without changing raw evidence."""
432
+ entries = _core_conversation_record_entries(graph, run_root)
433
+ root_id = _ollama_root_agent_id(graph)
434
+ if root_id is None:
435
+ return entries
436
+
437
+ normalized = False
438
+ for entry in entries:
439
+ if str(entry.get("provider") or "").lower() != "ollama":
440
+ continue
441
+ preview = entry.get("conversation_preview")
442
+ if not isinstance(preview, dict) or preview.get("is_root") is not True:
443
+ continue
444
+ if entry.get("source_type") != "inference_request":
445
+ continue
446
+ _ollama_current_turn(preview)
447
+ preview["provider_native_id"] = root_id
448
+ original_source_id = entry.get("source_id")
449
+ if isinstance(original_source_id, str) and original_source_id != root_id:
450
+ entry["evidence_source_id"] = original_source_id
451
+ entry["evidence_source_type"] = entry.get("source_type")
452
+ entry["source_id"] = root_id
453
+ entry["source_name"] = "Ollama"
454
+ entry["source_type"] = "agent"
455
+ normalized = True
456
+
457
+ if normalized:
458
+ _merge_conversation_previews(entries)
459
+ return entries
460
+
461
+
297
462
  # Functions defined in the core module resolve these globals at call time. Rebinding
298
463
  # keeps the public API stable while tightening identity before the observation stage.
299
464
  _core.conversation_preview = _conversation_preview
300
465
  _core._conversation_identity_keys = _conversation_identity_keys
301
466
  _core._merge_conversation_previews = _merge_conversation_previews
467
+ _core.conversation_record_entries = conversation_record_entries
@@ -157,6 +157,9 @@ def _assistant_messages(response: object) -> list[Any]:
157
157
  native = response.get("message")
158
158
  if isinstance(native, dict):
159
159
  messages.append(native)
160
+ generated = response.get("response")
161
+ if isinstance(generated, str) and generated:
162
+ messages.append({"role": "assistant", "content": generated})
160
163
  choices = response.get("choices")
161
164
  if isinstance(choices, list):
162
165
  for choice in choices: