execweave 0.7.2__tar.gz → 0.7.3__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 (438) hide show
  1. {execweave-0.7.2 → execweave-0.7.3}/.github/workflows/ci.yml +52 -0
  2. {execweave-0.7.2 → execweave-0.7.3}/.github/workflows/publish.yml +11 -3
  3. execweave-0.7.3/.github/workflows/repair-v073.yml +173 -0
  4. {execweave-0.7.2 → execweave-0.7.3}/PKG-INFO +1 -1
  5. {execweave-0.7.2 → execweave-0.7.3}/docs/codex-hooks.de.md +0 -1
  6. {execweave-0.7.2 → execweave-0.7.3}/docs/codex-hooks.fr.md +0 -1
  7. {execweave-0.7.2 → execweave-0.7.3}/docs/codex-hooks.ja.md +0 -1
  8. {execweave-0.7.2 → execweave-0.7.3}/docs/codex-hooks.ko.md +0 -1
  9. {execweave-0.7.2 → execweave-0.7.3}/docs/codex-hooks.md +0 -1
  10. {execweave-0.7.2 → execweave-0.7.3}/docs/codex-hooks.ru.md +0 -1
  11. {execweave-0.7.2 → execweave-0.7.3}/docs/codex-hooks.zh-CN.md +0 -1
  12. {execweave-0.7.2 → execweave-0.7.3}/docs/codex-hooks.zh-TW.md +0 -1
  13. {execweave-0.7.2 → execweave-0.7.3}/pyproject.toml +2 -2
  14. {execweave-0.7.2 → execweave-0.7.3}/scripts/check_codex_hook.py +9 -15
  15. execweave-0.7.3/scripts/check_conversation_records.py +215 -0
  16. {execweave-0.7.2 → execweave-0.7.3}/scripts/emit_claude_hook_smoke.py +16 -6
  17. execweave-0.7.3/scripts/emit_codex_hook_smoke.py +201 -0
  18. {execweave-0.7.2 → execweave-0.7.3}/scripts/emit_cursor_hook_smoke.py +3 -0
  19. {execweave-0.7.2 → execweave-0.7.3}/scripts/emit_gemini_hook_smoke.py +2 -0
  20. {execweave-0.7.2 → execweave-0.7.3}/scripts/emit_opencode_plugin_smoke.py +9 -0
  21. {execweave-0.7.2 → execweave-0.7.3}/src/execweave/__init__.py +1 -1
  22. execweave-0.7.2/src/execweave/conversation_records.py → execweave-0.7.3/src/execweave/_conversation_records_core.py +247 -55
  23. execweave-0.7.3/src/execweave/agent_topology.py +313 -0
  24. {execweave-0.7.2 → execweave-0.7.3}/src/execweave/agent_trace.py +7 -0
  25. {execweave-0.7.2 → execweave-0.7.3}/src/execweave/claude_adapter.py +10 -1
  26. {execweave-0.7.2 → execweave-0.7.3}/src/execweave/claude_delegation.py +5 -0
  27. {execweave-0.7.2 → execweave-0.7.3}/src/execweave/claude_full_fidelity.py +10 -1
  28. {execweave-0.7.2 → execweave-0.7.3}/src/execweave/claude_hook_contract.py +5 -0
  29. {execweave-0.7.2 → execweave-0.7.3}/src/execweave/codex_adapter.py +10 -1
  30. {execweave-0.7.2 → execweave-0.7.3}/src/execweave/codex_conversation.py +243 -28
  31. {execweave-0.7.2 → execweave-0.7.3}/src/execweave/codex_full_fidelity.py +43 -8
  32. {execweave-0.7.2 → execweave-0.7.3}/src/execweave/codex_hook_cli.py +102 -10
  33. {execweave-0.7.2 → execweave-0.7.3}/src/execweave/conversation_archive.py +24 -5
  34. execweave-0.7.3/src/execweave/conversation_message_identity.py +264 -0
  35. {execweave-0.7.2 → execweave-0.7.3}/src/execweave/conversation_preview.py +106 -57
  36. execweave-0.7.3/src/execweave/conversation_records.py +115 -0
  37. {execweave-0.7.2 → execweave-0.7.3}/src/execweave/cursor_full_fidelity.py +5 -0
  38. {execweave-0.7.2 → execweave-0.7.3}/src/execweave/graph.py +7 -1
  39. {execweave-0.7.2 → execweave-0.7.3}/src/execweave/opencode_event_contract.py +2 -0
  40. {execweave-0.7.2 → execweave-0.7.3}/src/execweave/opencode_full_fidelity.py +2 -0
  41. {execweave-0.7.2 → execweave-0.7.3}/src/execweave/opencode_task_linkage.py +23 -2
  42. {execweave-0.7.2 → execweave-0.7.3}/src/execweave/viewer_conversation_tree.py +4 -4
  43. execweave-0.7.3/tests/fixtures/codex_multi_agent/PROVENANCE.md +38 -0
  44. execweave-0.7.3/tests/fixtures/codex_multi_agent/hook-payloads.json +105 -0
  45. execweave-0.7.3/tests/fixtures/codex_multi_agent/rollout-main.jsonl +77 -0
  46. execweave-0.7.3/tests/test_agent_topology_evidence.py +499 -0
  47. execweave-0.7.3/tests/test_codex_hook_partial_capture.py +248 -0
  48. execweave-0.7.3/tests/test_codex_real_multi_agent_conversation.py +475 -0
  49. execweave-0.7.3/tests/test_codex_routing_native_identity.py +44 -0
  50. execweave-0.7.3/tests/test_conversation_identity_merge.py +440 -0
  51. execweave-0.7.3/tests/test_conversation_message_observation_dedupe.py +346 -0
  52. {execweave-0.7.2 → execweave-0.7.3}/tests/test_conversation_provider_parity.py +13 -8
  53. {execweave-0.7.2 → execweave-0.7.3}/tests/test_v069_dashboard_release.py +4 -4
  54. {execweave-0.7.2 → execweave-0.7.3}/.github/workflows/cleanup-workflow-history.yml +0 -0
  55. {execweave-0.7.2 → execweave-0.7.3}/.github/workflows/i18n.yml +0 -0
  56. {execweave-0.7.2 → execweave-0.7.3}/.github/workflows/package-benchmark.yml +0 -0
  57. {execweave-0.7.2 → execweave-0.7.3}/.github/workflows/package-smoke.yml +0 -0
  58. {execweave-0.7.2 → execweave-0.7.3}/.github/workflows/scalability.yml +0 -0
  59. {execweave-0.7.2 → execweave-0.7.3}/.github/workflows/wheel-smoke.yml +0 -0
  60. {execweave-0.7.2 → execweave-0.7.3}/.github/workflows/windows-launcher.yml +0 -0
  61. {execweave-0.7.2 → execweave-0.7.3}/.gitignore +0 -0
  62. {execweave-0.7.2 → execweave-0.7.3}/LICENSE +0 -0
  63. {execweave-0.7.2 → execweave-0.7.3}/README.de.md +0 -0
  64. {execweave-0.7.2 → execweave-0.7.3}/README.fr.md +0 -0
  65. {execweave-0.7.2 → execweave-0.7.3}/README.ja.md +0 -0
  66. {execweave-0.7.2 → execweave-0.7.3}/README.ko.md +0 -0
  67. {execweave-0.7.2 → execweave-0.7.3}/README.md +0 -0
  68. {execweave-0.7.2 → execweave-0.7.3}/README.ru.md +0 -0
  69. {execweave-0.7.2 → execweave-0.7.3}/README.zh-CN.md +0 -0
  70. {execweave-0.7.2 → execweave-0.7.3}/README.zh-TW.md +0 -0
  71. {execweave-0.7.2 → execweave-0.7.3}/benchmarks/phase1_overhead.py +0 -0
  72. {execweave-0.7.2 → execweave-0.7.3}/docs/antigravity-hooks.md +0 -0
  73. {execweave-0.7.2 → execweave-0.7.3}/docs/assets/codex.gif +0 -0
  74. {execweave-0.7.2 → execweave-0.7.3}/docs/benchmarks/README.md +0 -0
  75. {execweave-0.7.2 → execweave-0.7.3}/docs/benchmarks/v0.6.0-github-actions.json +0 -0
  76. {execweave-0.7.2 → execweave-0.7.3}/docs/benchmarks/v0.6.0-github-actions.svg +0 -0
  77. {execweave-0.7.2 → execweave-0.7.3}/docs/claude-code-hooks.de.md +0 -0
  78. {execweave-0.7.2 → execweave-0.7.3}/docs/claude-code-hooks.fr.md +0 -0
  79. {execweave-0.7.2 → execweave-0.7.3}/docs/claude-code-hooks.ja.md +0 -0
  80. {execweave-0.7.2 → execweave-0.7.3}/docs/claude-code-hooks.ko.md +0 -0
  81. {execweave-0.7.2 → execweave-0.7.3}/docs/claude-code-hooks.md +0 -0
  82. {execweave-0.7.2 → execweave-0.7.3}/docs/claude-code-hooks.ru.md +0 -0
  83. {execweave-0.7.2 → execweave-0.7.3}/docs/claude-code-hooks.zh-CN.md +0 -0
  84. {execweave-0.7.2 → execweave-0.7.3}/docs/claude-code-hooks.zh-TW.md +0 -0
  85. {execweave-0.7.2 → execweave-0.7.3}/docs/cursor-hooks.de.md +0 -0
  86. {execweave-0.7.2 → execweave-0.7.3}/docs/cursor-hooks.fr.md +0 -0
  87. {execweave-0.7.2 → execweave-0.7.3}/docs/cursor-hooks.ja.md +0 -0
  88. {execweave-0.7.2 → execweave-0.7.3}/docs/cursor-hooks.ko.md +0 -0
  89. {execweave-0.7.2 → execweave-0.7.3}/docs/cursor-hooks.md +0 -0
  90. {execweave-0.7.2 → execweave-0.7.3}/docs/cursor-hooks.ru.md +0 -0
  91. {execweave-0.7.2 → execweave-0.7.3}/docs/cursor-hooks.zh-CN.md +0 -0
  92. {execweave-0.7.2 → execweave-0.7.3}/docs/cursor-hooks.zh-TW.md +0 -0
  93. {execweave-0.7.2 → execweave-0.7.3}/docs/evidence-grades.de.md +0 -0
  94. {execweave-0.7.2 → execweave-0.7.3}/docs/evidence-grades.fr.md +0 -0
  95. {execweave-0.7.2 → execweave-0.7.3}/docs/evidence-grades.ja.md +0 -0
  96. {execweave-0.7.2 → execweave-0.7.3}/docs/evidence-grades.ko.md +0 -0
  97. {execweave-0.7.2 → execweave-0.7.3}/docs/evidence-grades.md +0 -0
  98. {execweave-0.7.2 → execweave-0.7.3}/docs/evidence-grades.ru.md +0 -0
  99. {execweave-0.7.2 → execweave-0.7.3}/docs/evidence-grades.zh-CN.md +0 -0
  100. {execweave-0.7.2 → execweave-0.7.3}/docs/evidence-grades.zh-TW.md +0 -0
  101. {execweave-0.7.2 → execweave-0.7.3}/docs/gemini-hooks.de.md +0 -0
  102. {execweave-0.7.2 → execweave-0.7.3}/docs/gemini-hooks.fr.md +0 -0
  103. {execweave-0.7.2 → execweave-0.7.3}/docs/gemini-hooks.ja.md +0 -0
  104. {execweave-0.7.2 → execweave-0.7.3}/docs/gemini-hooks.ko.md +0 -0
  105. {execweave-0.7.2 → execweave-0.7.3}/docs/gemini-hooks.md +0 -0
  106. {execweave-0.7.2 → execweave-0.7.3}/docs/gemini-hooks.ru.md +0 -0
  107. {execweave-0.7.2 → execweave-0.7.3}/docs/gemini-hooks.zh-CN.md +0 -0
  108. {execweave-0.7.2 → execweave-0.7.3}/docs/gemini-hooks.zh-TW.md +0 -0
  109. {execweave-0.7.2 → execweave-0.7.3}/docs/inference-gateway.de.md +0 -0
  110. {execweave-0.7.2 → execweave-0.7.3}/docs/inference-gateway.fr.md +0 -0
  111. {execweave-0.7.2 → execweave-0.7.3}/docs/inference-gateway.ja.md +0 -0
  112. {execweave-0.7.2 → execweave-0.7.3}/docs/inference-gateway.ko.md +0 -0
  113. {execweave-0.7.2 → execweave-0.7.3}/docs/inference-gateway.md +0 -0
  114. {execweave-0.7.2 → execweave-0.7.3}/docs/inference-gateway.ru.md +0 -0
  115. {execweave-0.7.2 → execweave-0.7.3}/docs/inference-gateway.zh-CN.md +0 -0
  116. {execweave-0.7.2 → execweave-0.7.3}/docs/inference-gateway.zh-TW.md +0 -0
  117. {execweave-0.7.2 → execweave-0.7.3}/docs/live-graph.de.md +0 -0
  118. {execweave-0.7.2 → execweave-0.7.3}/docs/live-graph.fr.md +0 -0
  119. {execweave-0.7.2 → execweave-0.7.3}/docs/live-graph.ja.md +0 -0
  120. {execweave-0.7.2 → execweave-0.7.3}/docs/live-graph.ko.md +0 -0
  121. {execweave-0.7.2 → execweave-0.7.3}/docs/live-graph.md +0 -0
  122. {execweave-0.7.2 → execweave-0.7.3}/docs/live-graph.ru.md +0 -0
  123. {execweave-0.7.2 → execweave-0.7.3}/docs/live-graph.zh-CN.md +0 -0
  124. {execweave-0.7.2 → execweave-0.7.3}/docs/live-graph.zh-TW.md +0 -0
  125. {execweave-0.7.2 → execweave-0.7.3}/docs/model-runtime.de.md +0 -0
  126. {execweave-0.7.2 → execweave-0.7.3}/docs/model-runtime.fr.md +0 -0
  127. {execweave-0.7.2 → execweave-0.7.3}/docs/model-runtime.ja.md +0 -0
  128. {execweave-0.7.2 → execweave-0.7.3}/docs/model-runtime.ko.md +0 -0
  129. {execweave-0.7.2 → execweave-0.7.3}/docs/model-runtime.md +0 -0
  130. {execweave-0.7.2 → execweave-0.7.3}/docs/model-runtime.ru.md +0 -0
  131. {execweave-0.7.2 → execweave-0.7.3}/docs/model-runtime.zh-CN.md +0 -0
  132. {execweave-0.7.2 → execweave-0.7.3}/docs/model-runtime.zh-TW.md +0 -0
  133. {execweave-0.7.2 → execweave-0.7.3}/docs/opencode-plugin.de.md +0 -0
  134. {execweave-0.7.2 → execweave-0.7.3}/docs/opencode-plugin.fr.md +0 -0
  135. {execweave-0.7.2 → execweave-0.7.3}/docs/opencode-plugin.ja.md +0 -0
  136. {execweave-0.7.2 → execweave-0.7.3}/docs/opencode-plugin.ko.md +0 -0
  137. {execweave-0.7.2 → execweave-0.7.3}/docs/opencode-plugin.md +0 -0
  138. {execweave-0.7.2 → execweave-0.7.3}/docs/opencode-plugin.ru.md +0 -0
  139. {execweave-0.7.2 → execweave-0.7.3}/docs/opencode-plugin.zh-CN.md +0 -0
  140. {execweave-0.7.2 → execweave-0.7.3}/docs/opencode-plugin.zh-TW.md +0 -0
  141. {execweave-0.7.2 → execweave-0.7.3}/docs/phase-1-runtime-collection.de.md +0 -0
  142. {execweave-0.7.2 → execweave-0.7.3}/docs/phase-1-runtime-collection.fr.md +0 -0
  143. {execweave-0.7.2 → execweave-0.7.3}/docs/phase-1-runtime-collection.ja.md +0 -0
  144. {execweave-0.7.2 → execweave-0.7.3}/docs/phase-1-runtime-collection.ko.md +0 -0
  145. {execweave-0.7.2 → execweave-0.7.3}/docs/phase-1-runtime-collection.md +0 -0
  146. {execweave-0.7.2 → execweave-0.7.3}/docs/phase-1-runtime-collection.ru.md +0 -0
  147. {execweave-0.7.2 → execweave-0.7.3}/docs/phase-1-runtime-collection.zh-CN.md +0 -0
  148. {execweave-0.7.2 → execweave-0.7.3}/docs/phase-1-runtime-collection.zh-TW.md +0 -0
  149. {execweave-0.7.2 → execweave-0.7.3}/docs/phase-2-execution-graph.de.md +0 -0
  150. {execweave-0.7.2 → execweave-0.7.3}/docs/phase-2-execution-graph.fr.md +0 -0
  151. {execweave-0.7.2 → execweave-0.7.3}/docs/phase-2-execution-graph.ja.md +0 -0
  152. {execweave-0.7.2 → execweave-0.7.3}/docs/phase-2-execution-graph.ko.md +0 -0
  153. {execweave-0.7.2 → execweave-0.7.3}/docs/phase-2-execution-graph.md +0 -0
  154. {execweave-0.7.2 → execweave-0.7.3}/docs/phase-2-execution-graph.ru.md +0 -0
  155. {execweave-0.7.2 → execweave-0.7.3}/docs/phase-2-execution-graph.zh-CN.md +0 -0
  156. {execweave-0.7.2 → execweave-0.7.3}/docs/phase-2-execution-graph.zh-TW.md +0 -0
  157. {execweave-0.7.2 → execweave-0.7.3}/docs/rule-packs.de.md +0 -0
  158. {execweave-0.7.2 → execweave-0.7.3}/docs/rule-packs.fr.md +0 -0
  159. {execweave-0.7.2 → execweave-0.7.3}/docs/rule-packs.ja.md +0 -0
  160. {execweave-0.7.2 → execweave-0.7.3}/docs/rule-packs.ko.md +0 -0
  161. {execweave-0.7.2 → execweave-0.7.3}/docs/rule-packs.md +0 -0
  162. {execweave-0.7.2 → execweave-0.7.3}/docs/rule-packs.ru.md +0 -0
  163. {execweave-0.7.2 → execweave-0.7.3}/docs/rule-packs.zh-CN.md +0 -0
  164. {execweave-0.7.2 → execweave-0.7.3}/docs/rule-packs.zh-TW.md +0 -0
  165. {execweave-0.7.2 → execweave-0.7.3}/docs/run-integrity.de.md +0 -0
  166. {execweave-0.7.2 → execweave-0.7.3}/docs/run-integrity.fr.md +0 -0
  167. {execweave-0.7.2 → execweave-0.7.3}/docs/run-integrity.ja.md +0 -0
  168. {execweave-0.7.2 → execweave-0.7.3}/docs/run-integrity.ko.md +0 -0
  169. {execweave-0.7.2 → execweave-0.7.3}/docs/run-integrity.md +0 -0
  170. {execweave-0.7.2 → execweave-0.7.3}/docs/run-integrity.ru.md +0 -0
  171. {execweave-0.7.2 → execweave-0.7.3}/docs/run-integrity.zh-CN.md +0 -0
  172. {execweave-0.7.2 → execweave-0.7.3}/docs/run-integrity.zh-TW.md +0 -0
  173. {execweave-0.7.2 → execweave-0.7.3}/docs/runtime-threat-model.de.md +0 -0
  174. {execweave-0.7.2 → execweave-0.7.3}/docs/runtime-threat-model.fr.md +0 -0
  175. {execweave-0.7.2 → execweave-0.7.3}/docs/runtime-threat-model.ja.md +0 -0
  176. {execweave-0.7.2 → execweave-0.7.3}/docs/runtime-threat-model.ko.md +0 -0
  177. {execweave-0.7.2 → execweave-0.7.3}/docs/runtime-threat-model.md +0 -0
  178. {execweave-0.7.2 → execweave-0.7.3}/docs/runtime-threat-model.ru.md +0 -0
  179. {execweave-0.7.2 → execweave-0.7.3}/docs/runtime-threat-model.zh-CN.md +0 -0
  180. {execweave-0.7.2 → execweave-0.7.3}/docs/runtime-threat-model.zh-TW.md +0 -0
  181. {execweave-0.7.2 → execweave-0.7.3}/docs/security-analysis.de.md +0 -0
  182. {execweave-0.7.2 → execweave-0.7.3}/docs/security-analysis.fr.md +0 -0
  183. {execweave-0.7.2 → execweave-0.7.3}/docs/security-analysis.ja.md +0 -0
  184. {execweave-0.7.2 → execweave-0.7.3}/docs/security-analysis.ko.md +0 -0
  185. {execweave-0.7.2 → execweave-0.7.3}/docs/security-analysis.md +0 -0
  186. {execweave-0.7.2 → execweave-0.7.3}/docs/security-analysis.ru.md +0 -0
  187. {execweave-0.7.2 → execweave-0.7.3}/docs/security-analysis.zh-CN.md +0 -0
  188. {execweave-0.7.2 → execweave-0.7.3}/docs/security-analysis.zh-TW.md +0 -0
  189. {execweave-0.7.2 → execweave-0.7.3}/docs/semantic-telemetry.de.md +0 -0
  190. {execweave-0.7.2 → execweave-0.7.3}/docs/semantic-telemetry.fr.md +0 -0
  191. {execweave-0.7.2 → execweave-0.7.3}/docs/semantic-telemetry.ja.md +0 -0
  192. {execweave-0.7.2 → execweave-0.7.3}/docs/semantic-telemetry.ko.md +0 -0
  193. {execweave-0.7.2 → execweave-0.7.3}/docs/semantic-telemetry.md +0 -0
  194. {execweave-0.7.2 → execweave-0.7.3}/docs/semantic-telemetry.ru.md +0 -0
  195. {execweave-0.7.2 → execweave-0.7.3}/docs/semantic-telemetry.zh-CN.md +0 -0
  196. {execweave-0.7.2 → execweave-0.7.3}/docs/semantic-telemetry.zh-TW.md +0 -0
  197. {execweave-0.7.2 → execweave-0.7.3}/docs/v0.6.5-hardening-decisions.md +0 -0
  198. {execweave-0.7.2 → execweave-0.7.3}/scripts/audit_i18n_parity.py +0 -0
  199. {execweave-0.7.2 → execweave-0.7.3}/scripts/check_claude_hook.py +0 -0
  200. {execweave-0.7.2 → execweave-0.7.3}/scripts/check_claude_record_graph.py +0 -0
  201. {execweave-0.7.2 → execweave-0.7.3}/scripts/check_correlation_graph.py +0 -0
  202. {execweave-0.7.2 → execweave-0.7.3}/scripts/check_inference_gateway_cli.py +0 -0
  203. {execweave-0.7.2 → execweave-0.7.3}/scripts/check_model_runtime_cli.py +0 -0
  204. {execweave-0.7.2 → execweave-0.7.3}/scripts/check_openai_compatible_cli.py +0 -0
  205. {execweave-0.7.2 → execweave-0.7.3}/scripts/check_semantic_graph.py +0 -0
  206. {execweave-0.7.2 → execweave-0.7.3}/scripts/check_viewer_js.py +0 -0
  207. {execweave-0.7.2 → execweave-0.7.3}/scripts/check_wheel_install.py +0 -0
  208. {execweave-0.7.2 → execweave-0.7.3}/scripts/check_windows_launchers.py +0 -0
  209. {execweave-0.7.2 → execweave-0.7.3}/scripts/make_semantic_smoke.py +0 -0
  210. {execweave-0.7.2 → execweave-0.7.3}/scripts/sync_i18n_nav.py +0 -0
  211. {execweave-0.7.2 → execweave-0.7.3}/src/execweave/__main__.py +0 -0
  212. {execweave-0.7.2 → execweave-0.7.3}/src/execweave/agent_bootstrap.py +0 -0
  213. {execweave-0.7.2 → execweave-0.7.3}/src/execweave/analysis.py +0 -0
  214. {execweave-0.7.2 → execweave-0.7.3}/src/execweave/anthropic.py +0 -0
  215. {execweave-0.7.2 → execweave-0.7.3}/src/execweave/anthropic_cli.py +0 -0
  216. {execweave-0.7.2 → execweave-0.7.3}/src/execweave/anthropic_full_fidelity.py +0 -0
  217. {execweave-0.7.2 → execweave-0.7.3}/src/execweave/antigravity_adapter.py +0 -0
  218. {execweave-0.7.2 → execweave-0.7.3}/src/execweave/antigravity_adapter_base.py +0 -0
  219. {execweave-0.7.2 → execweave-0.7.3}/src/execweave/antigravity_full_fidelity.py +0 -0
  220. {execweave-0.7.2 → execweave-0.7.3}/src/execweave/antigravity_full_fidelity_base.py +0 -0
  221. {execweave-0.7.2 → execweave-0.7.3}/src/execweave/antigravity_full_fidelity_collaboration_base.py +0 -0
  222. {execweave-0.7.2 → execweave-0.7.3}/src/execweave/antigravity_hook_cli.py +0 -0
  223. {execweave-0.7.2 → execweave-0.7.3}/src/execweave/antigravity_record.py +0 -0
  224. {execweave-0.7.2 → execweave-0.7.3}/src/execweave/antigravity_subagent_linkage.py +0 -0
  225. {execweave-0.7.2 → execweave-0.7.3}/src/execweave/antigravity_trace_capability.py +0 -0
  226. {execweave-0.7.2 → execweave-0.7.3}/src/execweave/auto_specialized.py +0 -0
  227. {execweave-0.7.2 → execweave-0.7.3}/src/execweave/backends.py +0 -0
  228. {execweave-0.7.2 → execweave-0.7.3}/src/execweave/benchmark.py +0 -0
  229. {execweave-0.7.2 → execweave-0.7.3}/src/execweave/claude_hook_cli.py +0 -0
  230. {execweave-0.7.2 → execweave-0.7.3}/src/execweave/claude_model_observer.py +0 -0
  231. {execweave-0.7.2 → execweave-0.7.3}/src/execweave/claude_record.py +0 -0
  232. {execweave-0.7.2 → execweave-0.7.3}/src/execweave/cli.py +0 -0
  233. {execweave-0.7.2 → execweave-0.7.3}/src/execweave/codex_hook_lifecycle.py +0 -0
  234. {execweave-0.7.2 → execweave-0.7.3}/src/execweave/codex_message_diagnostics.py +0 -0
  235. {execweave-0.7.2 → execweave-0.7.3}/src/execweave/codex_message_transport_diagnostics.py +0 -0
  236. {execweave-0.7.2 → execweave-0.7.3}/src/execweave/codex_record.py +0 -0
  237. {execweave-0.7.2 → execweave-0.7.3}/src/execweave/codex_rollout_structures.py +0 -0
  238. {execweave-0.7.2 → execweave-0.7.3}/src/execweave/codex_rollout_trace.py +0 -0
  239. {execweave-0.7.2 → execweave-0.7.3}/src/execweave/codex_rollout_trace_base.py +0 -0
  240. {execweave-0.7.2 → execweave-0.7.3}/src/execweave/collector.py +0 -0
  241. {execweave-0.7.2 → execweave-0.7.3}/src/execweave/command.py +0 -0
  242. {execweave-0.7.2 → execweave-0.7.3}/src/execweave/content_evidence.py +0 -0
  243. {execweave-0.7.2 → execweave-0.7.3}/src/execweave/content_store.py +0 -0
  244. {execweave-0.7.2 → execweave-0.7.3}/src/execweave/correlation.py +0 -0
  245. {execweave-0.7.2 → execweave-0.7.3}/src/execweave/cursor_adapter.py +0 -0
  246. {execweave-0.7.2 → execweave-0.7.3}/src/execweave/cursor_delegation.py +0 -0
  247. {execweave-0.7.2 → execweave-0.7.3}/src/execweave/cursor_delegation_base.py +0 -0
  248. {execweave-0.7.2 → execweave-0.7.3}/src/execweave/cursor_hook_cli.py +0 -0
  249. {execweave-0.7.2 → execweave-0.7.3}/src/execweave/cursor_hook_contract.py +0 -0
  250. {execweave-0.7.2 → execweave-0.7.3}/src/execweave/cursor_record.py +0 -0
  251. {execweave-0.7.2 → execweave-0.7.3}/src/execweave/entry.py +0 -0
  252. {execweave-0.7.2 → execweave-0.7.3}/src/execweave/evidence_grade.py +0 -0
  253. {execweave-0.7.2 → execweave-0.7.3}/src/execweave/fidelity.py +0 -0
  254. {execweave-0.7.2 → execweave-0.7.3}/src/execweave/filesystem.py +0 -0
  255. {execweave-0.7.2 → execweave-0.7.3}/src/execweave/focus.py +0 -0
  256. {execweave-0.7.2 → execweave-0.7.3}/src/execweave/gemini_adapter.py +0 -0
  257. {execweave-0.7.2 → execweave-0.7.3}/src/execweave/gemini_full_fidelity.py +0 -0
  258. {execweave-0.7.2 → execweave-0.7.3}/src/execweave/gemini_hook_cli.py +0 -0
  259. {execweave-0.7.2 → execweave-0.7.3}/src/execweave/gemini_hook_contract.py +0 -0
  260. {execweave-0.7.2 → execweave-0.7.3}/src/execweave/gemini_record.py +0 -0
  261. {execweave-0.7.2 → execweave-0.7.3}/src/execweave/graph_ops.py +0 -0
  262. {execweave-0.7.2 → execweave-0.7.3}/src/execweave/http_proxy.py +0 -0
  263. {execweave-0.7.2 → execweave-0.7.3}/src/execweave/http_proxy_cli.py +0 -0
  264. {execweave-0.7.2 → execweave-0.7.3}/src/execweave/inference_gateway.py +0 -0
  265. {execweave-0.7.2 → execweave-0.7.3}/src/execweave/inference_gateway_cli.py +0 -0
  266. {execweave-0.7.2 → execweave-0.7.3}/src/execweave/inference_gateway_full_fidelity.py +0 -0
  267. {execweave-0.7.2 → execweave-0.7.3}/src/execweave/inference_identity.py +0 -0
  268. {execweave-0.7.2 → execweave-0.7.3}/src/execweave/inference_identity_cli.py +0 -0
  269. {execweave-0.7.2 → execweave-0.7.3}/src/execweave/integrity.py +0 -0
  270. {execweave-0.7.2 → execweave-0.7.3}/src/execweave/integrity_cli.py +0 -0
  271. {execweave-0.7.2 → execweave-0.7.3}/src/execweave/litellm_callback.py +0 -0
  272. {execweave-0.7.2 → execweave-0.7.3}/src/execweave/litellm_callback_cli.py +0 -0
  273. {execweave-0.7.2 → execweave-0.7.3}/src/execweave/live.py +0 -0
  274. {execweave-0.7.2 → execweave-0.7.3}/src/execweave/live_core.py +0 -0
  275. {execweave-0.7.2 → execweave-0.7.3}/src/execweave/live_view.py +0 -0
  276. {execweave-0.7.2 → execweave-0.7.3}/src/execweave/live_view_extra_style.py +0 -0
  277. {execweave-0.7.2 → execweave-0.7.3}/src/execweave/live_view_markup.py +0 -0
  278. {execweave-0.7.2 → execweave-0.7.3}/src/execweave/live_view_script_a.py +0 -0
  279. {execweave-0.7.2 → execweave-0.7.3}/src/execweave/live_view_script_b.py +0 -0
  280. {execweave-0.7.2 → execweave-0.7.3}/src/execweave/live_view_script_c.py +0 -0
  281. {execweave-0.7.2 → execweave-0.7.3}/src/execweave/live_view_script_d.py +0 -0
  282. {execweave-0.7.2 → execweave-0.7.3}/src/execweave/live_view_style.py +0 -0
  283. {execweave-0.7.2 → execweave-0.7.3}/src/execweave/model_runtime.py +0 -0
  284. {execweave-0.7.2 → execweave-0.7.3}/src/execweave/model_runtime_cli.py +0 -0
  285. {execweave-0.7.2 → execweave-0.7.3}/src/execweave/model_runtime_full_fidelity.py +0 -0
  286. {execweave-0.7.2 → execweave-0.7.3}/src/execweave/openai_compatible.py +0 -0
  287. {execweave-0.7.2 → execweave-0.7.3}/src/execweave/openai_compatible_cli.py +0 -0
  288. {execweave-0.7.2 → execweave-0.7.3}/src/execweave/openai_compatible_full_fidelity.py +0 -0
  289. {execweave-0.7.2 → execweave-0.7.3}/src/execweave/opencode_adapter.py +0 -0
  290. {execweave-0.7.2 → execweave-0.7.3}/src/execweave/opencode_hook_cli.py +0 -0
  291. {execweave-0.7.2 → execweave-0.7.3}/src/execweave/opencode_plugin_cli.py +0 -0
  292. {execweave-0.7.2 → execweave-0.7.3}/src/execweave/opencode_record.py +0 -0
  293. {execweave-0.7.2 → execweave-0.7.3}/src/execweave/overhead_benchmark.py +0 -0
  294. {execweave-0.7.2 → execweave-0.7.3}/src/execweave/provider_lifecycle.py +0 -0
  295. {execweave-0.7.2 → execweave-0.7.3}/src/execweave/provider_record.py +0 -0
  296. {execweave-0.7.2 → execweave-0.7.3}/src/execweave/rule_pack.py +0 -0
  297. {execweave-0.7.2 → execweave-0.7.3}/src/execweave/rule_pack_cli.py +0 -0
  298. {execweave-0.7.2 → execweave-0.7.3}/src/execweave/scalability_benchmark.py +0 -0
  299. {execweave-0.7.2 → execweave-0.7.3}/src/execweave/schema.py +0 -0
  300. {execweave-0.7.2 → execweave-0.7.3}/src/execweave/scope.py +0 -0
  301. {execweave-0.7.2 → execweave-0.7.3}/src/execweave/semantic.py +0 -0
  302. {execweave-0.7.2 → execweave-0.7.3}/src/execweave/sink.py +0 -0
  303. {execweave-0.7.2 → execweave-0.7.3}/src/execweave/strace_backend.py +0 -0
  304. {execweave-0.7.2 → execweave-0.7.3}/src/execweave/theme.py +0 -0
  305. {execweave-0.7.2 → execweave-0.7.3}/src/execweave/top.py +0 -0
  306. {execweave-0.7.2 → execweave-0.7.3}/src/execweave/top_cli.py +0 -0
  307. {execweave-0.7.2 → execweave-0.7.3}/src/execweave/validate.py +0 -0
  308. {execweave-0.7.2 → execweave-0.7.3}/src/execweave/view_cli.py +0 -0
  309. {execweave-0.7.2 → execweave-0.7.3}/src/execweave/viewer.py +0 -0
  310. {execweave-0.7.2 → execweave-0.7.3}/src/execweave/viewer_antigravity_linkage_inspector.py +0 -0
  311. {execweave-0.7.2 → execweave-0.7.3}/src/execweave/viewer_content_inspector.py +0 -0
  312. {execweave-0.7.2 → execweave-0.7.3}/src/execweave/viewer_conversation_panel.py +0 -0
  313. {execweave-0.7.2 → execweave-0.7.3}/src/execweave/viewer_dashboard_clean.py +0 -0
  314. {execweave-0.7.2 → execweave-0.7.3}/src/execweave/viewer_dashboard_focus.py +0 -0
  315. {execweave-0.7.2 → execweave-0.7.3}/src/execweave/viewer_execution_inspector.py +0 -0
  316. {execweave-0.7.2 → execweave-0.7.3}/src/execweave/viewer_live_layout.py +0 -0
  317. {execweave-0.7.2 → execweave-0.7.3}/src/execweave/viewer_projection.py +0 -0
  318. {execweave-0.7.2 → execweave-0.7.3}/src/execweave/viewer_projection_base.py +0 -0
  319. {execweave-0.7.2 → execweave-0.7.3}/src/execweave/workflow.py +0 -0
  320. {execweave-0.7.2 → execweave-0.7.3}/tests/fixtures/hooks/README.md +0 -0
  321. {execweave-0.7.2 → execweave-0.7.3}/tests/fixtures/hooks/claude.json +0 -0
  322. {execweave-0.7.2 → execweave-0.7.3}/tests/fixtures/hooks/codex.json +0 -0
  323. {execweave-0.7.2 → execweave-0.7.3}/tests/fixtures/hooks/cursor.json +0 -0
  324. {execweave-0.7.2 → execweave-0.7.3}/tests/fixtures/hooks/gemini.json +0 -0
  325. {execweave-0.7.2 → execweave-0.7.3}/tests/fixtures/hooks/manifest.json +0 -0
  326. {execweave-0.7.2 → execweave-0.7.3}/tests/fixtures/hooks/opencode.json +0 -0
  327. {execweave-0.7.2 → execweave-0.7.3}/tests/test_agent_bootstrap.py +0 -0
  328. {execweave-0.7.2 → execweave-0.7.3}/tests/test_agent_message_viewer.py +0 -0
  329. {execweave-0.7.2 → execweave-0.7.3}/tests/test_agent_trace_lifecycle.py +0 -0
  330. {execweave-0.7.2 → execweave-0.7.3}/tests/test_agent_trace_viewer_visibility.py +0 -0
  331. {execweave-0.7.2 → execweave-0.7.3}/tests/test_analysis.py +0 -0
  332. {execweave-0.7.2 → execweave-0.7.3}/tests/test_anthropic.py +0 -0
  333. {execweave-0.7.2 → execweave-0.7.3}/tests/test_antigravity_agent_collaboration.py +0 -0
  334. {execweave-0.7.2 → execweave-0.7.3}/tests/test_antigravity_cursor_launch.py +0 -0
  335. {execweave-0.7.2 → execweave-0.7.3}/tests/test_antigravity_lifecycle.py +0 -0
  336. {execweave-0.7.2 → execweave-0.7.3}/tests/test_antigravity_linkage_projection.py +0 -0
  337. {execweave-0.7.2 → execweave-0.7.3}/tests/test_antigravity_official_contract.py +0 -0
  338. {execweave-0.7.2 → execweave-0.7.3}/tests/test_antigravity_subagent_transcript_linkage.py +0 -0
  339. {execweave-0.7.2 → execweave-0.7.3}/tests/test_antigravity_trace_capability_cli.py +0 -0
  340. {execweave-0.7.2 → execweave-0.7.3}/tests/test_auto_specialized.py +0 -0
  341. {execweave-0.7.2 → execweave-0.7.3}/tests/test_backends.py +0 -0
  342. {execweave-0.7.2 → execweave-0.7.3}/tests/test_claude_adapter.py +0 -0
  343. {execweave-0.7.2 → execweave-0.7.3}/tests/test_claude_delegation.py +0 -0
  344. {execweave-0.7.2 → execweave-0.7.3}/tests/test_claude_full_fidelity.py +0 -0
  345. {execweave-0.7.2 → execweave-0.7.3}/tests/test_claude_hook_contract.py +0 -0
  346. {execweave-0.7.2 → execweave-0.7.3}/tests/test_claude_hook_metadata.py +0 -0
  347. {execweave-0.7.2 → execweave-0.7.3}/tests/test_claude_hook_viewer.py +0 -0
  348. {execweave-0.7.2 → execweave-0.7.3}/tests/test_claude_model_observer.py +0 -0
  349. {execweave-0.7.2 → execweave-0.7.3}/tests/test_claude_record.py +0 -0
  350. {execweave-0.7.2 → execweave-0.7.3}/tests/test_codex_adapter.py +0 -0
  351. {execweave-0.7.2 → execweave-0.7.3}/tests/test_codex_archive_full_fidelity.py +0 -0
  352. {execweave-0.7.2 → execweave-0.7.3}/tests/test_codex_conversation_isolation.py +0 -0
  353. {execweave-0.7.2 → execweave-0.7.3}/tests/test_codex_full_fidelity.py +0 -0
  354. {execweave-0.7.2 → execweave-0.7.3}/tests/test_codex_hook_lifecycle.py +0 -0
  355. {execweave-0.7.2 → execweave-0.7.3}/tests/test_codex_message_diagnostics.py +0 -0
  356. {execweave-0.7.2 → execweave-0.7.3}/tests/test_codex_message_transport_diagnostics.py +0 -0
  357. {execweave-0.7.2 → execweave-0.7.3}/tests/test_codex_record.py +0 -0
  358. {execweave-0.7.2 → execweave-0.7.3}/tests/test_codex_reducer_command.py +0 -0
  359. {execweave-0.7.2 → execweave-0.7.3}/tests/test_codex_rollout_structures.py +0 -0
  360. {execweave-0.7.2 → execweave-0.7.3}/tests/test_codex_rollout_trace.py +0 -0
  361. {execweave-0.7.2 → execweave-0.7.3}/tests/test_collector.py +0 -0
  362. {execweave-0.7.2 → execweave-0.7.3}/tests/test_command.py +0 -0
  363. {execweave-0.7.2 → execweave-0.7.3}/tests/test_condense.py +0 -0
  364. {execweave-0.7.2 → execweave-0.7.3}/tests/test_conversation_access.py +0 -0
  365. {execweave-0.7.2 → execweave-0.7.3}/tests/test_conversation_agent_isolation.py +0 -0
  366. {execweave-0.7.2 → execweave-0.7.3}/tests/test_correlation.py +0 -0
  367. {execweave-0.7.2 → execweave-0.7.3}/tests/test_correlation_canonical_path.py +0 -0
  368. {execweave-0.7.2 → execweave-0.7.3}/tests/test_correlation_checker.py +0 -0
  369. {execweave-0.7.2 → execweave-0.7.3}/tests/test_correlation_process_exe.py +0 -0
  370. {execweave-0.7.2 → execweave-0.7.3}/tests/test_cross_provider_agent_trace.py +0 -0
  371. {execweave-0.7.2 → execweave-0.7.3}/tests/test_cursor_adapter.py +0 -0
  372. {execweave-0.7.2 → execweave-0.7.3}/tests/test_cursor_delegation.py +0 -0
  373. {execweave-0.7.2 → execweave-0.7.3}/tests/test_cursor_full_fidelity.py +0 -0
  374. {execweave-0.7.2 → execweave-0.7.3}/tests/test_cursor_hook_contract.py +0 -0
  375. {execweave-0.7.2 → execweave-0.7.3}/tests/test_cursor_hook_fail_open.py +0 -0
  376. {execweave-0.7.2 → execweave-0.7.3}/tests/test_cursor_record.py +0 -0
  377. {execweave-0.7.2 → execweave-0.7.3}/tests/test_cursor_task_linkage.py +0 -0
  378. {execweave-0.7.2 → execweave-0.7.3}/tests/test_dashboard_information_architecture.py +0 -0
  379. {execweave-0.7.2 → execweave-0.7.3}/tests/test_dashboard_simplification.py +0 -0
  380. {execweave-0.7.2 → execweave-0.7.3}/tests/test_dashboard_ux_and_hook_projection.py +0 -0
  381. {execweave-0.7.2 → execweave-0.7.3}/tests/test_delegation_viewer.py +0 -0
  382. {execweave-0.7.2 → execweave-0.7.3}/tests/test_evidence_grade.py +0 -0
  383. {execweave-0.7.2 → execweave-0.7.3}/tests/test_execution_viewer.py +0 -0
  384. {execweave-0.7.2 → execweave-0.7.3}/tests/test_fidelity.py +0 -0
  385. {execweave-0.7.2 → execweave-0.7.3}/tests/test_filesystem_resilience.py +0 -0
  386. {execweave-0.7.2 → execweave-0.7.3}/tests/test_focus.py +0 -0
  387. {execweave-0.7.2 → execweave-0.7.3}/tests/test_full_fidelity.py +0 -0
  388. {execweave-0.7.2 → execweave-0.7.3}/tests/test_gemini_adapter.py +0 -0
  389. {execweave-0.7.2 → execweave-0.7.3}/tests/test_gemini_full_fidelity.py +0 -0
  390. {execweave-0.7.2 → execweave-0.7.3}/tests/test_gemini_hook_contract.py +0 -0
  391. {execweave-0.7.2 → execweave-0.7.3}/tests/test_gemini_lifecycle.py +0 -0
  392. {execweave-0.7.2 → execweave-0.7.3}/tests/test_gemini_record.py +0 -0
  393. {execweave-0.7.2 → execweave-0.7.3}/tests/test_graph.py +0 -0
  394. {execweave-0.7.2 → execweave-0.7.3}/tests/test_graph_ops.py +0 -0
  395. {execweave-0.7.2 → execweave-0.7.3}/tests/test_hook_fixture_corpus.py +0 -0
  396. {execweave-0.7.2 → execweave-0.7.3}/tests/test_http_proxy.py +0 -0
  397. {execweave-0.7.2 → execweave-0.7.3}/tests/test_inference_gateway.py +0 -0
  398. {execweave-0.7.2 → execweave-0.7.3}/tests/test_inference_gateway_full_fidelity.py +0 -0
  399. {execweave-0.7.2 → execweave-0.7.3}/tests/test_inference_identity.py +0 -0
  400. {execweave-0.7.2 → execweave-0.7.3}/tests/test_integrity.py +0 -0
  401. {execweave-0.7.2 → execweave-0.7.3}/tests/test_litellm_callback.py +0 -0
  402. {execweave-0.7.2 → execweave-0.7.3}/tests/test_live.py +0 -0
  403. {execweave-0.7.2 → execweave-0.7.3}/tests/test_live_auth.py +0 -0
  404. {execweave-0.7.2 → execweave-0.7.3}/tests/test_live_dashboard.py +0 -0
  405. {execweave-0.7.2 → execweave-0.7.3}/tests/test_live_dashboard_js.py +0 -0
  406. {execweave-0.7.2 → execweave-0.7.3}/tests/test_live_delta.py +0 -0
  407. {execweave-0.7.2 → execweave-0.7.3}/tests/test_live_logs_export.py +0 -0
  408. {execweave-0.7.2 → execweave-0.7.3}/tests/test_live_theme.py +0 -0
  409. {execweave-0.7.2 → execweave-0.7.3}/tests/test_lmstudio_auto_specialized.py +0 -0
  410. {execweave-0.7.2 → execweave-0.7.3}/tests/test_model_runtime.py +0 -0
  411. {execweave-0.7.2 → execweave-0.7.3}/tests/test_model_runtime_full_fidelity.py +0 -0
  412. {execweave-0.7.2 → execweave-0.7.3}/tests/test_openai_compatible.py +0 -0
  413. {execweave-0.7.2 → execweave-0.7.3}/tests/test_opencode_adapter.py +0 -0
  414. {execweave-0.7.2 → execweave-0.7.3}/tests/test_opencode_event_contract.py +0 -0
  415. {execweave-0.7.2 → execweave-0.7.3}/tests/test_opencode_event_lifecycle.py +0 -0
  416. {execweave-0.7.2 → execweave-0.7.3}/tests/test_opencode_full_fidelity.py +0 -0
  417. {execweave-0.7.2 → execweave-0.7.3}/tests/test_opencode_plugin.py +0 -0
  418. {execweave-0.7.2 → execweave-0.7.3}/tests/test_opencode_record.py +0 -0
  419. {execweave-0.7.2 → execweave-0.7.3}/tests/test_opencode_task_session_linkage.py +0 -0
  420. {execweave-0.7.2 → execweave-0.7.3}/tests/test_overhead_benchmark.py +0 -0
  421. {execweave-0.7.2 → execweave-0.7.3}/tests/test_provider_conversation_evidence.py +0 -0
  422. {execweave-0.7.2 → execweave-0.7.3}/tests/test_provider_lifecycle.py +0 -0
  423. {execweave-0.7.2 → execweave-0.7.3}/tests/test_rule_pack.py +0 -0
  424. {execweave-0.7.2 → execweave-0.7.3}/tests/test_schema.py +0 -0
  425. {execweave-0.7.2 → execweave-0.7.3}/tests/test_scope.py +0 -0
  426. {execweave-0.7.2 → execweave-0.7.3}/tests/test_semantic.py +0 -0
  427. {execweave-0.7.2 → execweave-0.7.3}/tests/test_strace_backend.py +0 -0
  428. {execweave-0.7.2 → execweave-0.7.3}/tests/test_threat_model.py +0 -0
  429. {execweave-0.7.2 → execweave-0.7.3}/tests/test_top_detached.py +0 -0
  430. {execweave-0.7.2 → execweave-0.7.3}/tests/test_v063_features.py +0 -0
  431. {execweave-0.7.2 → execweave-0.7.3}/tests/test_v064_live_auto_integrations.py +0 -0
  432. {execweave-0.7.2 → execweave-0.7.3}/tests/test_v064_live_evidence.py +0 -0
  433. {execweave-0.7.2 → execweave-0.7.3}/tests/test_validate.py +0 -0
  434. {execweave-0.7.2 → execweave-0.7.3}/tests/test_version.py +0 -0
  435. {execweave-0.7.2 → execweave-0.7.3}/tests/test_viewer.py +0 -0
  436. {execweave-0.7.2 → execweave-0.7.3}/tests/test_viewer_content_inspector.py +0 -0
  437. {execweave-0.7.2 → execweave-0.7.3}/tests/test_viewer_projection.py +0 -0
  438. {execweave-0.7.2 → execweave-0.7.3}/tests/test_workflow.py +0 -0
@@ -150,6 +150,12 @@ jobs:
150
150
  run: python scripts/check_correlation_graph.py claude-record-smoke/graph.correlated.json
151
151
  - name: Check correlated standalone viewer JavaScript syntax
152
152
  run: python scripts/check_viewer_js.py claude-record-smoke/viewer.correlated.html --output claude-record-smoke/viewer.correlated.js
153
+ - name: Verify Claude materialized conversations
154
+ run: >
155
+ python scripts/check_conversation_records.py claude-record-smoke
156
+ --expect-agent /root
157
+ --expect-root-text "CI CLAUDE PROMPT"
158
+ --expect-root-text "CI CLAUDE FINAL ANSWER"
153
159
  - name: Gemini run-bound semantic and correlation smoke
154
160
  run: execweave-gemini-record --backend auto --no-files --no-network --output-dir gemini-record-smoke -- python scripts/emit_gemini_hook_smoke.py
155
161
  - name: Validate Gemini runtime stream
@@ -162,6 +168,12 @@ jobs:
162
168
  run: python scripts/check_correlation_graph.py gemini-record-smoke/graph.correlated.json
163
169
  - name: Check Gemini correlated viewer JavaScript syntax
164
170
  run: python scripts/check_viewer_js.py gemini-record-smoke/viewer.correlated.html --output gemini-record-smoke/viewer.correlated.js
171
+ - name: Verify Gemini materialized conversations
172
+ run: >
173
+ python scripts/check_conversation_records.py gemini-record-smoke
174
+ --expect-agent /root
175
+ --expect-root-text "CI GEMINI PROMPT"
176
+ --expect-root-text "CI GEMINI FINAL ANSWER"
165
177
  - name: Cursor run-bound semantic and correlation smoke
166
178
  run: execweave-cursor-record --backend auto --no-files --no-network --output-dir cursor-record-smoke -- python scripts/emit_cursor_hook_smoke.py
167
179
  - name: Validate Cursor runtime stream
@@ -174,6 +186,12 @@ jobs:
174
186
  run: python scripts/check_correlation_graph.py cursor-record-smoke/graph.correlated.json
175
187
  - name: Check Cursor correlated viewer JavaScript syntax
176
188
  run: python scripts/check_viewer_js.py cursor-record-smoke/viewer.correlated.html --output cursor-record-smoke/viewer.correlated.js
189
+ - name: Verify Cursor materialized conversations
190
+ run: >
191
+ python scripts/check_conversation_records.py cursor-record-smoke
192
+ --expect-agent /root
193
+ --expect-root-text "CI CURSOR PROMPT"
194
+ --expect-root-text "CI CURSOR FINAL ANSWER"
177
195
  - name: OpenCode plugin installer smoke
178
196
  run: execweave-opencode-plugin --install --root opencode-plugin-smoke
179
197
  - name: OpenCode run-bound semantic and correlation smoke
@@ -188,6 +206,40 @@ jobs:
188
206
  run: python scripts/check_correlation_graph.py opencode-record-smoke/graph.correlated.json
189
207
  - name: Check OpenCode correlated viewer JavaScript syntax
190
208
  run: python scripts/check_viewer_js.py opencode-record-smoke/viewer.correlated.html --output opencode-record-smoke/viewer.correlated.js
209
+ - name: Verify OpenCode materialized conversations
210
+ run: >
211
+ python scripts/check_conversation_records.py opencode-record-smoke
212
+ --expect-agent /root
213
+ --expect-root-text "CI OPENCODE FINAL ANSWER"
214
+ --forbid-agent /root/ci-opencode-session
215
+ - name: Codex hook command smoke
216
+ run: python scripts/check_codex_hook.py
217
+ - name: Codex run-bound semantic and correlation smoke
218
+ run: execweave-codex-record --backend auto --no-files --no-network --output-dir codex-record-smoke -- python scripts/emit_codex_hook_smoke.py
219
+ - name: Validate Codex runtime stream
220
+ run: execweave validate codex-record-smoke/events.jsonl
221
+ - name: Validate Codex merged stream
222
+ run: execweave validate codex-record-smoke/events.semantic.jsonl
223
+ - name: Validate Codex correlated stream
224
+ run: execweave validate codex-record-smoke/events.correlated.jsonl
225
+ - name: Verify Codex conservative correlation edge
226
+ run: python scripts/check_correlation_graph.py codex-record-smoke/graph.correlated.json
227
+ - name: Check Codex correlated viewer JavaScript syntax
228
+ run: python scripts/check_viewer_js.py codex-record-smoke/viewer.correlated.html --output codex-record-smoke/viewer.correlated.js
229
+ # Codex reports a subagent stop with the child rollout on agent_transcript_path
230
+ # and the parent rollout on transcript_path. Archiving the parent is the
231
+ # v0.7.2 regression, so assert the child conversation survives end to end.
232
+ - name: Verify Codex agent-local subagent conversations
233
+ run: >
234
+ python scripts/check_conversation_records.py codex-record-smoke
235
+ --min-entries 2
236
+ --expect-agent /root
237
+ --expect-agent /root/explorer
238
+ --expect-root-text "CI ROOT PROMPT"
239
+ --expect-root-text "CI ROOT FINAL ANSWER"
240
+ --expect-owned "/root=CI ROOT COMMENTARY"
241
+ --expect-owned "/root/explorer=CI CHILD PRIVATE REASONING"
242
+ --forbid-agent /root/01a04cea-67b2-7683-9f6b-cd644497b862
191
243
  - name: Model runtime CLI smoke
192
244
  run: python scripts/check_model_runtime_cli.py
193
245
  - name: Inference gateway CLI smoke
@@ -3,21 +3,30 @@ name: Publish to PyPI
3
3
  on:
4
4
  release:
5
5
  types: [published]
6
+ workflow_dispatch:
7
+ inputs:
8
+ release_tag:
9
+ description: Release tag to publish
10
+ required: true
11
+ type: string
6
12
 
7
13
  permissions:
8
14
  contents: read
9
15
 
16
+ env:
17
+ RELEASE_TAG: ${{ github.event.release.tag_name || inputs.release_tag }}
18
+
10
19
  jobs:
11
20
  build:
12
21
  runs-on: ubuntu-latest
13
22
  steps:
14
23
  - uses: actions/checkout@v4
24
+ with:
25
+ ref: ${{ env.RELEASE_TAG }}
15
26
  - uses: actions/setup-python@v5
16
27
  with:
17
28
  python-version: "3.12"
18
29
  - name: Verify release tag matches package version
19
- env:
20
- RELEASE_TAG: ${{ github.event.release.tag_name }}
21
30
  run: |
22
31
  python - <<'PY'
23
32
  import os
@@ -75,5 +84,4 @@ jobs:
75
84
  - name: Attach distributions to GitHub Release
76
85
  env:
77
86
  GH_TOKEN: ${{ github.token }}
78
- RELEASE_TAG: ${{ github.event.release.tag_name }}
79
87
  run: gh release upload "$RELEASE_TAG" dist/* --clobber --repo "$GITHUB_REPOSITORY"
@@ -0,0 +1,173 @@
1
+ name: Repair v0.7.3 Release
2
+
3
+ on:
4
+ workflow_run:
5
+ workflows: ["CI"]
6
+ types: [completed]
7
+ branches: [main]
8
+
9
+ permissions:
10
+ actions: write
11
+ contents: write
12
+
13
+ jobs:
14
+ repair:
15
+ if: ${{ github.event.workflow_run.conclusion == 'success' }}
16
+ runs-on: ubuntu-latest
17
+ env:
18
+ GH_TOKEN: ${{ github.token }}
19
+ RELEASE_TAG: v0.7.3
20
+ EXPECTED_VERSION: 0.7.3
21
+ STALE_TAG_SHA: 25321ec325ecf871ec2a56b55b593fcac854ffcf
22
+ HEAD_SHA: ${{ github.event.workflow_run.head_sha }}
23
+ steps:
24
+ - uses: actions/checkout@v4
25
+ with:
26
+ ref: ${{ env.HEAD_SHA }}
27
+
28
+ - name: Verify repaired release candidate
29
+ run: |
30
+ set -euo pipefail
31
+ current_main="$(gh api "repos/$GITHUB_REPOSITORY/git/ref/heads/main" --jq '.object.sha')"
32
+ if [[ "$current_main" != "$HEAD_SHA" ]]; then
33
+ echo "main moved from $HEAD_SHA to $current_main; refusing release repair" >&2
34
+ exit 1
35
+ fi
36
+ python - <<'PY'
37
+ import os
38
+ import tomllib
39
+ from pathlib import Path
40
+
41
+ version = tomllib.loads(Path("pyproject.toml").read_text(encoding="utf-8"))["project"]["version"]
42
+ expected = os.environ["EXPECTED_VERSION"]
43
+ if version != expected:
44
+ raise SystemExit(f"package version {version!r} does not match expected {expected!r}")
45
+ print(f"Release candidate version: {version}")
46
+ PY
47
+
48
+ - name: Wait for all release gates
49
+ run: |
50
+ set -euo pipefail
51
+ required=("CI" "Package Smoke" "Wheel Install Smoke" "Windows Launcher Compatibility")
52
+ for attempt in $(seq 1 60); do
53
+ runs="$(gh api "repos/$GITHUB_REPOSITORY/actions/runs?head_sha=$HEAD_SHA&per_page=100")"
54
+ pending=0
55
+ for gate in "${required[@]}"; do
56
+ state="$(jq -r --arg name "$gate" '
57
+ .workflow_runs
58
+ | map(select(.name == $name and .event == "push"))
59
+ | sort_by(.created_at)
60
+ | reverse
61
+ | .[0]
62
+ | if . == null then "missing"
63
+ else ((.status // "") + ":" + (.conclusion // "")) end
64
+ ' <<<"$runs")"
65
+ echo "$gate => $state"
66
+ case "$state" in
67
+ completed:success) ;;
68
+ completed:*) echo "$gate failed: $state" >&2; exit 1 ;;
69
+ *) pending=1 ;;
70
+ esac
71
+ done
72
+ if [[ "$pending" -eq 0 ]]; then
73
+ exit 0
74
+ fi
75
+ sleep 5
76
+ done
77
+ echo "release gates did not all complete successfully" >&2
78
+ exit 1
79
+
80
+ - name: Replace stale v0.7.3 tag and release
81
+ run: |
82
+ set -euo pipefail
83
+ tag_sha="$(gh api "repos/$GITHUB_REPOSITORY/git/ref/tags/$RELEASE_TAG" --jq '.object.sha' 2>/dev/null || true)"
84
+ release_exists=0
85
+ asset_count=0
86
+ if gh release view "$RELEASE_TAG" --repo "$GITHUB_REPOSITORY" >/dev/null 2>&1; then
87
+ release_exists=1
88
+ asset_count="$(gh release view "$RELEASE_TAG" --repo "$GITHUB_REPOSITORY" --json assets --jq '.assets | length')"
89
+ fi
90
+
91
+ if [[ -n "$tag_sha" && "$tag_sha" != "$STALE_TAG_SHA" && "$tag_sha" != "$HEAD_SHA" ]]; then
92
+ echo "v0.7.3 tag unexpectedly points to $tag_sha; refusing to overwrite" >&2
93
+ exit 1
94
+ fi
95
+ if [[ "$asset_count" -gt 0 && "$tag_sha" != "$HEAD_SHA" ]]; then
96
+ echo "existing v0.7.3 release already has assets; refusing destructive replacement" >&2
97
+ exit 1
98
+ fi
99
+
100
+ if [[ "$tag_sha" != "$HEAD_SHA" ]]; then
101
+ if [[ "$release_exists" -eq 1 ]]; then
102
+ gh release delete "$RELEASE_TAG" --cleanup-tag --yes --repo "$GITHUB_REPOSITORY"
103
+ elif [[ -n "$tag_sha" ]]; then
104
+ gh api --method DELETE "repos/$GITHUB_REPOSITORY/git/refs/tags/$RELEASE_TAG"
105
+ fi
106
+ gh release create "$RELEASE_TAG" \
107
+ --target "$HEAD_SHA" \
108
+ --title "ExecWeave v0.7.3" \
109
+ --generate-notes \
110
+ --repo "$GITHUB_REPOSITORY"
111
+ else
112
+ echo "v0.7.3 tag already points to repaired release candidate"
113
+ fi
114
+
115
+ - name: Dispatch canonical publish workflow
116
+ run: |
117
+ set -euo pipefail
118
+ gh workflow run publish.yml \
119
+ --ref main \
120
+ -f release_tag="$RELEASE_TAG" \
121
+ --repo "$GITHUB_REPOSITORY"
122
+
123
+ run_id=""
124
+ for attempt in $(seq 1 30); do
125
+ run_id="$(gh run list \
126
+ --workflow publish.yml \
127
+ --event workflow_dispatch \
128
+ --branch main \
129
+ --limit 20 \
130
+ --json databaseId,headSha,createdAt \
131
+ --jq ".[] | select(.headSha == \"$HEAD_SHA\") | .databaseId" \
132
+ --repo "$GITHUB_REPOSITORY" | head -n 1)"
133
+ if [[ -n "$run_id" ]]; then
134
+ break
135
+ fi
136
+ sleep 2
137
+ done
138
+ if [[ -z "$run_id" ]]; then
139
+ echo "could not locate dispatched publish workflow" >&2
140
+ exit 1
141
+ fi
142
+ echo "publish_run_id=$run_id" >> "$GITHUB_ENV"
143
+
144
+ - name: Wait for publish workflow
145
+ run: gh run watch "$publish_run_id" --exit-status --repo "$GITHUB_REPOSITORY"
146
+
147
+ - name: Verify release assets and PyPI
148
+ run: |
149
+ set -euo pipefail
150
+ assets="$(gh release view "$RELEASE_TAG" --repo "$GITHUB_REPOSITORY" --json assets --jq '.assets[].name')"
151
+ grep -Fx "execweave-0.7.3-py3-none-any.whl" <<<"$assets"
152
+ grep -Fx "execweave-0.7.3.tar.gz" <<<"$assets"
153
+
154
+ python - <<'PY'
155
+ import json
156
+ import time
157
+ import urllib.error
158
+ import urllib.request
159
+
160
+ url = "https://pypi.org/pypi/execweave/0.7.3/json"
161
+ for _ in range(60):
162
+ try:
163
+ with urllib.request.urlopen(url, timeout=10) as response:
164
+ payload = json.load(response)
165
+ if payload.get("info", {}).get("version") == "0.7.3":
166
+ print("PyPI ExecWeave 0.7.3 verified")
167
+ break
168
+ except (urllib.error.URLError, json.JSONDecodeError):
169
+ pass
170
+ time.sleep(5)
171
+ else:
172
+ raise SystemExit("PyPI did not expose ExecWeave 0.7.3")
173
+ PY
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: execweave
3
- Version: 0.7.2
3
+ Version: 0.7.3
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
@@ -30,7 +30,6 @@ ExecWeave zeichnet Evidenz aus Codex-Lifecycle-Hooks neben unabhängig erfasster
30
30
  - `SubagentStart`
31
31
  - `SubagentStop`
32
32
  - `Stop`
33
- - `Interrupt`
34
33
 
35
34
  Unbekannte oder upstream nicht verfügbare Ereignisse werden nicht erfunden. Hook-Schemata und Dispatch-Abdeckung können sich zwischen Codex-Versionen ändern.
36
35
 
@@ -30,7 +30,6 @@ ExecWeave enregistre les preuves issues des hooks de cycle de vie Codex à côt
30
30
  - `SubagentStart`
31
31
  - `SubagentStop`
32
32
  - `Stop`
33
- - `Interrupt`
34
33
 
35
34
  ExecWeave n'invente pas les événements absents ou indisponibles côté fournisseur. Les schémas et la couverture peuvent changer selon les versions de Codex.
36
35
 
@@ -30,7 +30,6 @@ ExecWeave は Codex lifecycle-hook evidence を独立した OS runtime telemetry
30
30
  - `SubagentStart`
31
31
  - `SubagentStop`
32
32
  - `Stop`
33
- - `Interrupt`
34
33
 
35
34
  未知または利用できない upstream event は作りません。Hook schema と dispatch coverage は Codex version により変わる可能性があります。
36
35
 
@@ -30,7 +30,6 @@ ExecWeave는 Codex 라이프사이클 훅 증거를 독립적인 OS 런타임
30
30
  - `SubagentStart`
31
31
  - `SubagentStop`
32
32
  - `Stop`
33
- - `Interrupt`
34
33
 
35
34
  업스트림에 없거나 사용할 수 없는 이벤트를 ExecWeave가 만들어내지는 않습니다. Codex 버전에 따라 훅 스키마와 디스패치 범위가 달라질 수 있습니다.
36
35
 
@@ -30,7 +30,6 @@ ExecWeave records Codex lifecycle-hook evidence beside independent OS runtime te
30
30
  - `SubagentStart`
31
31
  - `SubagentStop`
32
32
  - `Stop`
33
- - `Interrupt`
34
33
 
35
34
  Unknown or unavailable upstream events are not invented. Hook schemas and dispatch coverage can change between Codex versions.
36
35
 
@@ -30,7 +30,6 @@ ExecWeave записывает evidence из lifecycle hooks Codex рядом с
30
30
  - `SubagentStart`
31
31
  - `SubagentStop`
32
32
  - `Stop`
33
- - `Interrupt`
34
33
 
35
34
  Неизвестные или недоступные upstream events не выдумываются. Hook schemas и dispatch coverage могут меняться между версиями Codex.
36
35
 
@@ -30,7 +30,6 @@ ExecWeave 将 Codex lifecycle-hook evidence 与独立 OS runtime telemetry 并
30
30
  - `SubagentStart`
31
31
  - `SubagentStop`
32
32
  - `Stop`
33
- - `Interrupt`
34
33
 
35
34
  ExecWeave 不会伪造 upstream 未知或不可用的 event。Hook schema 与 dispatch coverage 可能随 Codex 版本改变。
36
35
 
@@ -30,7 +30,6 @@ ExecWeave 會把 Codex lifecycle-hook evidence 與獨立 OS runtime telemetry
30
30
  - `SubagentStart`
31
31
  - `SubagentStop`
32
32
  - `Stop`
33
- - `Interrupt`
34
33
 
35
34
  ExecWeave 不會捏造 upstream 未知或不可用的 event。Hook schema 與 dispatch coverage 可能隨 Codex 版本改變。
36
35
 
@@ -4,8 +4,8 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "execweave"
7
- # ExecWeave v0.7.2 release metadata
8
- version = "0.7.2"
7
+ # ExecWeave v0.7.3 release metadata
8
+ version = "0.7.3"
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"
@@ -65,22 +65,16 @@ def main() -> int:
65
65
  check=True,
66
66
  )
67
67
  parsed = json.loads(config.stdout)
68
- required = {
69
- "PreToolUse",
70
- "PermissionRequest",
71
- "PostToolUse",
72
- "PreCompact",
73
- "PostCompact",
74
- "SessionStart",
75
- "SessionEnd",
76
- "UserPromptSubmit",
77
- "SubagentStart",
78
- "SubagentStop",
79
- "Stop",
80
- "Interrupt",
81
- }
68
+ # Bound to the shipped event set rather than a second hardcoded copy, which had
69
+ # drifted to expect an "Interrupt" hook ExecWeave does not register.
70
+ from execweave.codex_hook_lifecycle import OFFICIAL_CODEX_HOOK_EVENTS
71
+
72
+ required = set(OFFICIAL_CODEX_HOOK_EVENTS)
82
73
  if set(parsed.get("hooks", {})) != required:
83
- raise SystemExit("generated Codex hook config is incomplete")
74
+ raise SystemExit(
75
+ "generated Codex hook config does not match the official event set: "
76
+ f"{sorted(set(parsed.get('hooks', {})) ^ required)}"
77
+ )
84
78
  for event_name in {"PreToolUse", "PermissionRequest", "PostToolUse"}:
85
79
  if parsed["hooks"][event_name][0].get("matcher") != "*":
86
80
  raise SystemExit(f"Codex {event_name} hook is not configured for all tools")
@@ -0,0 +1,215 @@
1
+ """Assert that a recorded run actually materialized the conversations it observed.
2
+
3
+ CI previously ran every provider's record pipeline end to end and never looked at
4
+ ``conversations.json``. All four provider smokes were producing ``entry_count: 0``
5
+ while reporting success, which is how a total conversation collapse reached a tagged
6
+ release with green CI.
7
+
8
+ This checker closes that gap. It reads the final artifact — not an intermediate
9
+ preview object — and fails when a run that observed conversational evidence published
10
+ none, when an expected agent is missing, when one agent execution is published as
11
+ several conversations, or when a message landed in the wrong agent's thread.
12
+
13
+ Every check walks the real entry list. An earlier version keyed previews by agent path
14
+ before running the ownership checks, so a duplicate silently overwrote its twin and the
15
+ isolation assertions only ever saw one of them.
16
+ """
17
+
18
+ from __future__ import annotations
19
+
20
+ import argparse
21
+ import json
22
+ import sys
23
+ from collections import defaultdict
24
+ from pathlib import Path
25
+ from typing import Any
26
+
27
+
28
+ def _fail(message: str) -> None:
29
+ print(f"conversation record check FAILED: {message}", file=sys.stderr)
30
+ raise SystemExit(1)
31
+
32
+
33
+ def _load(run_dir: Path) -> dict[str, Any]:
34
+ path = run_dir / "conversations.json"
35
+ if not path.is_file():
36
+ _fail(f"{path} does not exist")
37
+ try:
38
+ payload = json.loads(path.read_text(encoding="utf-8"))
39
+ except json.JSONDecodeError as exc:
40
+ _fail(f"{path} is not valid JSON: {exc.msg}")
41
+ if not isinstance(payload, dict):
42
+ _fail(f"{path} root must be a JSON object")
43
+ return payload
44
+
45
+
46
+ def _entries_by_agent(document: dict[str, Any]) -> dict[str, list[dict[str, Any]]]:
47
+ """Group every materialized preview under its agent path, keeping duplicates."""
48
+ grouped: dict[str, list[dict[str, Any]]] = defaultdict(list)
49
+ for entry in document.get("entries") or []:
50
+ if not isinstance(entry, dict):
51
+ continue
52
+ preview = entry.get("conversation_preview")
53
+ if isinstance(preview, dict) and preview.get("agent_path"):
54
+ grouped[str(preview["agent_path"])].append(preview)
55
+ return dict(grouped)
56
+
57
+
58
+ def _texts(preview: dict[str, Any]) -> str:
59
+ return "\n".join(
60
+ str(message.get("text") or "") for message in preview.get("messages") or []
61
+ )
62
+
63
+
64
+ def _describe(agent_path: str, previews: list[dict[str, Any]]) -> str:
65
+ threads = [str(preview.get("thread_id")) for preview in previews]
66
+ return f"{agent_path} -> {len(previews)} entries with thread ids {threads}"
67
+
68
+
69
+ def main() -> int:
70
+ parser = argparse.ArgumentParser(
71
+ description="Verify a run's materialized conversations.json"
72
+ )
73
+ parser.add_argument("run_dir", type=Path, help="ExecWeave run artifact directory")
74
+ parser.add_argument(
75
+ "--expect-agent",
76
+ action="append",
77
+ default=[],
78
+ metavar="AGENT_PATH",
79
+ help="agent path that must have a conversation entry (repeatable)",
80
+ )
81
+ parser.add_argument(
82
+ "--expect-root-text",
83
+ action="append",
84
+ default=[],
85
+ metavar="TEXT",
86
+ help="text that must appear in the /root thread (repeatable)",
87
+ )
88
+ parser.add_argument(
89
+ "--expect-owned",
90
+ action="append",
91
+ default=[],
92
+ metavar="AGENT_PATH=TEXT",
93
+ help="text that must appear in one agent's thread and nowhere else (repeatable)",
94
+ )
95
+ parser.add_argument(
96
+ "--forbid-agent",
97
+ action="append",
98
+ default=[],
99
+ metavar="AGENT_PATH",
100
+ help="agent path that must NOT exist, e.g. a fabricated child (repeatable)",
101
+ )
102
+ parser.add_argument(
103
+ "--allow-duplicate-agent",
104
+ action="append",
105
+ default=[],
106
+ metavar="AGENT_PATH",
107
+ help=(
108
+ "permit this agent path to hold several conversation entries. Only for a "
109
+ "fixture where one agent genuinely runs several independent conversations; "
110
+ "one execution published twice is a defect, not a configuration choice."
111
+ ),
112
+ )
113
+ parser.add_argument(
114
+ "--min-entries",
115
+ type=int,
116
+ default=1,
117
+ help="minimum number of materialized conversation entries (default: 1)",
118
+ )
119
+ args = parser.parse_args()
120
+
121
+ document = _load(args.run_dir)
122
+ grouped = _entries_by_agent(document)
123
+ entry_count = document.get("entry_count")
124
+
125
+ if not isinstance(entry_count, int) or entry_count < args.min_entries:
126
+ _fail(
127
+ f"entry_count is {entry_count!r}; expected at least {args.min_entries}. "
128
+ "The run observed conversational evidence but published none."
129
+ )
130
+ if len(grouped) < args.min_entries:
131
+ _fail(f"only {len(grouped)} agents carry a conversation; expected {args.min_entries}")
132
+
133
+ # One agent execution must be published exactly once. Evidence that names its
134
+ # thread differently is provenance, not a second conversation.
135
+ allowed_duplicates = set(args.allow_duplicate_agent)
136
+ for agent_path, previews in sorted(grouped.items()):
137
+ if len(previews) > 1 and agent_path not in allowed_duplicates:
138
+ _fail(
139
+ "one agent execution is published as several conversations: "
140
+ + _describe(agent_path, previews)
141
+ + ". Evidence describing the same execution must merge into one entry."
142
+ )
143
+
144
+ for agent_path in args.expect_agent:
145
+ if agent_path not in grouped:
146
+ _fail(f"no conversation entry for {agent_path}; found {sorted(grouped)}")
147
+ if not any(preview.get("messages") for preview in grouped[agent_path]):
148
+ _fail(f"{agent_path} materialized an entry with no messages")
149
+
150
+ for agent_path in args.forbid_agent:
151
+ if agent_path in grouped:
152
+ _fail(f"{agent_path} was materialized but no evidence establishes it")
153
+
154
+ if args.expect_root_text and "/root" not in grouped:
155
+ _fail(f"no /root conversation; found {sorted(grouped)}")
156
+ for text in args.expect_root_text:
157
+ if not any(text in _texts(preview) for preview in grouped.get("/root", [])):
158
+ _fail(f"/root thread is missing expected text {text!r}")
159
+
160
+ for spec in args.expect_owned:
161
+ agent_path, separator, text = spec.partition("=")
162
+ if not separator:
163
+ _fail(f"--expect-owned needs AGENT_PATH=TEXT, got {spec!r}")
164
+ if agent_path not in grouped:
165
+ _fail(f"no conversation entry for {agent_path}; found {sorted(grouped)}")
166
+ if not any(text in _texts(preview) for preview in grouped[agent_path]):
167
+ _fail(f"{agent_path} is missing its own content {text!r}")
168
+ # Isolation is checked against every published entry, so a duplicate cannot
169
+ # hide a leak by being overwritten before this runs.
170
+ for other_path, others in grouped.items():
171
+ if other_path == agent_path:
172
+ continue
173
+ for preview in others:
174
+ if text in _texts(preview):
175
+ _fail(
176
+ f"content {text!r} owned by {agent_path} leaked into "
177
+ f"{other_path} (thread {preview.get('thread_id')!r})"
178
+ )
179
+
180
+ # Topology provenance: every parent link must name the evidence behind it, and no
181
+ # entry may claim a parent that has no conversation of its own.
182
+ for agent_path, previews in sorted(grouped.items()):
183
+ for preview in previews:
184
+ parent = preview.get("parent_agent_path")
185
+ if preview.get("is_root"):
186
+ if parent is not None:
187
+ _fail(f"{agent_path} is root but names parent {parent!r}")
188
+ continue
189
+ if parent is None:
190
+ _fail(f"{agent_path} is not root but names no parent")
191
+ if not preview.get("parent_relation_source"):
192
+ _fail(f"{agent_path} claims parent {parent!r} with no evidence recorded")
193
+ if parent not in grouped:
194
+ _fail(f"{agent_path} names parent {parent!r}, which has no conversation")
195
+
196
+ print(
197
+ f"conversation record check passed for {args.run_dir}: "
198
+ f"{entry_count} entries, agents {sorted(grouped)}"
199
+ )
200
+ for agent_path, previews in sorted(grouped.items()):
201
+ for preview in previews:
202
+ evidence = preview.get("evidence_thread_ids") or [preview.get("thread_id")]
203
+ print(
204
+ f" {agent_path}: {len(preview.get('messages') or [])} messages, "
205
+ f"completeness={preview.get('conversation_completeness')}, "
206
+ f"path_source={preview.get('agent_path_source')}, "
207
+ f"topology={preview.get('topology_state')}, "
208
+ f"thread={preview.get('thread_id')}, "
209
+ f"evidence_threads={len(evidence)}"
210
+ )
211
+ return 0
212
+
213
+
214
+ if __name__ == "__main__":
215
+ raise SystemExit(main())
@@ -30,12 +30,22 @@ def main() -> int:
30
30
  }
31
31
  if not os.environ.get("EXECWEAVE_SEMANTIC_SIDECAR"):
32
32
  raise SystemExit("run-bound semantic sidecar environment was not inherited")
33
- subprocess.run(
34
- ["execweave-claude-hook"],
35
- input=json.dumps(payload),
36
- text=True,
37
- check=True,
38
- )
33
+
34
+ def send(body: dict) -> None:
35
+ subprocess.run(
36
+ ["execweave-claude-hook"], input=json.dumps(body), text=True, check=True
37
+ )
38
+
39
+ base = {key: payload[key] for key in ("session_id", "cwd", "permission_mode")}
40
+ # Conversation evidence, so the run materializes a conversations.json CI can check.
41
+ send({**base, "hook_event_name": "UserPromptSubmit", "prompt": "CI CLAUDE PROMPT"})
42
+ send(payload)
43
+ send({
44
+ **base,
45
+ "hook_event_name": "Stop",
46
+ "stop_hook_active": False,
47
+ "last_assistant_message": "CI CLAUDE FINAL ANSWER",
48
+ })
39
49
  child = subprocess.Popen(child_argv)
40
50
  # Keep the emitter alive while the child is running so the portable sampler
41
51
  # gets many observation opportunities on slower hosted runners.