execweave 0.8.12__tar.gz → 0.8.14__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.
- {execweave-0.8.12 → execweave-0.8.14}/PKG-INFO +1 -1
- {execweave-0.8.12 → execweave-0.8.14}/pyproject.toml +2 -2
- {execweave-0.8.12 → execweave-0.8.14}/src/execweave/__init__.py +1 -1
- {execweave-0.8.12 → execweave-0.8.14}/src/execweave/collector.py +120 -24
- {execweave-0.8.12 → execweave-0.8.14}/src/execweave/command.py +6 -1
- execweave-0.8.14/tests/test_pypi_0812_regressions.py +171 -0
- execweave-0.8.14/tests/test_pypi_0813_cleanup.py +382 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/test_v069_dashboard_release.py +3 -3
- {execweave-0.8.12 → execweave-0.8.14}/.github/workflows/ci.yml +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/.github/workflows/cleanup-workflow-history.yml +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/.github/workflows/i18n.yml +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/.github/workflows/package-benchmark.yml +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/.github/workflows/package-smoke.yml +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/.github/workflows/provider-capability-stage-integrity.yml +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/.github/workflows/provider-dashboard-contract.yml +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/.github/workflows/publish.yml +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/.github/workflows/scalability.yml +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/.github/workflows/viewer-agent-isolation.yml +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/.github/workflows/wheel-smoke.yml +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/.github/workflows/windows-launcher.yml +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/.gitignore +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/LICENSE +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/README.de.md +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/README.fr.md +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/README.ja.md +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/README.ko.md +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/README.md +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/README.ru.md +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/README.zh-CN.md +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/README.zh-TW.md +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/benchmarks/phase1_overhead.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/diagnostics/acceptance_hardening_20260906.md +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/diagnostics/audit_eight_children.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/diagnostics/audit_python_journey.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/diagnostics/audit_real_clicks.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/diagnostics/current_state_reaudit.md +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/diagnostics/execweave_full_audit.md +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/diagnostics/gate_status.md +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/diagnostics/gate_status_history_through_g3.md +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/diagnostics/github_pr_inventory.json +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/diagnostics/handoff_checkpoint_20260906.md +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/diagnostics/next_agent_handoff.md +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/diagnostics/pr_regression_map.md +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/docs/antigravity-hooks.md +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/docs/assets/codex.gif +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/docs/benchmarks/README.md +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/docs/benchmarks/v0.6.0-github-actions.json +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/docs/benchmarks/v0.6.0-github-actions.svg +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/docs/claude-code-hooks.de.md +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/docs/claude-code-hooks.fr.md +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/docs/claude-code-hooks.ja.md +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/docs/claude-code-hooks.ko.md +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/docs/claude-code-hooks.md +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/docs/claude-code-hooks.ru.md +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/docs/claude-code-hooks.zh-CN.md +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/docs/claude-code-hooks.zh-TW.md +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/docs/codex-hooks.de.md +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/docs/codex-hooks.fr.md +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/docs/codex-hooks.ja.md +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/docs/codex-hooks.ko.md +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/docs/codex-hooks.md +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/docs/codex-hooks.ru.md +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/docs/codex-hooks.zh-CN.md +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/docs/codex-hooks.zh-TW.md +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/docs/cursor-hooks.de.md +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/docs/cursor-hooks.fr.md +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/docs/cursor-hooks.ja.md +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/docs/cursor-hooks.ko.md +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/docs/cursor-hooks.md +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/docs/cursor-hooks.ru.md +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/docs/cursor-hooks.zh-CN.md +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/docs/cursor-hooks.zh-TW.md +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/docs/evidence-grades.de.md +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/docs/evidence-grades.fr.md +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/docs/evidence-grades.ja.md +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/docs/evidence-grades.ko.md +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/docs/evidence-grades.md +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/docs/evidence-grades.ru.md +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/docs/evidence-grades.zh-CN.md +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/docs/evidence-grades.zh-TW.md +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/docs/inference-gateway.de.md +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/docs/inference-gateway.fr.md +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/docs/inference-gateway.ja.md +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/docs/inference-gateway.ko.md +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/docs/inference-gateway.md +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/docs/inference-gateway.ru.md +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/docs/inference-gateway.zh-CN.md +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/docs/inference-gateway.zh-TW.md +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/docs/internal/provider-capability-matrix.md +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/docs/live-graph.de.md +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/docs/live-graph.fr.md +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/docs/live-graph.ja.md +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/docs/live-graph.ko.md +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/docs/live-graph.md +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/docs/live-graph.ru.md +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/docs/live-graph.zh-CN.md +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/docs/live-graph.zh-TW.md +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/docs/model-runtime.de.md +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/docs/model-runtime.fr.md +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/docs/model-runtime.ja.md +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/docs/model-runtime.ko.md +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/docs/model-runtime.md +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/docs/model-runtime.ru.md +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/docs/model-runtime.zh-CN.md +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/docs/model-runtime.zh-TW.md +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/docs/opencode-plugin.de.md +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/docs/opencode-plugin.fr.md +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/docs/opencode-plugin.ja.md +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/docs/opencode-plugin.ko.md +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/docs/opencode-plugin.md +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/docs/opencode-plugin.ru.md +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/docs/opencode-plugin.zh-CN.md +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/docs/opencode-plugin.zh-TW.md +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/docs/phase-1-runtime-collection.de.md +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/docs/phase-1-runtime-collection.fr.md +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/docs/phase-1-runtime-collection.ja.md +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/docs/phase-1-runtime-collection.ko.md +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/docs/phase-1-runtime-collection.md +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/docs/phase-1-runtime-collection.ru.md +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/docs/phase-1-runtime-collection.zh-CN.md +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/docs/phase-1-runtime-collection.zh-TW.md +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/docs/phase-2-execution-graph.de.md +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/docs/phase-2-execution-graph.fr.md +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/docs/phase-2-execution-graph.ja.md +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/docs/phase-2-execution-graph.ko.md +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/docs/phase-2-execution-graph.md +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/docs/phase-2-execution-graph.ru.md +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/docs/phase-2-execution-graph.zh-CN.md +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/docs/phase-2-execution-graph.zh-TW.md +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/docs/remaining-provider-audit-v0.8.7.md +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/docs/rule-packs.de.md +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/docs/rule-packs.fr.md +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/docs/rule-packs.ja.md +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/docs/rule-packs.ko.md +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/docs/rule-packs.md +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/docs/rule-packs.ru.md +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/docs/rule-packs.zh-CN.md +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/docs/rule-packs.zh-TW.md +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/docs/run-integrity.de.md +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/docs/run-integrity.fr.md +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/docs/run-integrity.ja.md +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/docs/run-integrity.ko.md +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/docs/run-integrity.md +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/docs/run-integrity.ru.md +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/docs/run-integrity.zh-CN.md +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/docs/run-integrity.zh-TW.md +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/docs/runtime-threat-model.de.md +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/docs/runtime-threat-model.fr.md +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/docs/runtime-threat-model.ja.md +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/docs/runtime-threat-model.ko.md +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/docs/runtime-threat-model.md +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/docs/runtime-threat-model.ru.md +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/docs/runtime-threat-model.zh-CN.md +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/docs/runtime-threat-model.zh-TW.md +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/docs/security-analysis.de.md +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/docs/security-analysis.fr.md +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/docs/security-analysis.ja.md +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/docs/security-analysis.ko.md +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/docs/security-analysis.md +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/docs/security-analysis.ru.md +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/docs/security-analysis.zh-CN.md +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/docs/security-analysis.zh-TW.md +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/docs/semantic-telemetry.de.md +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/docs/semantic-telemetry.fr.md +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/docs/semantic-telemetry.ja.md +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/docs/semantic-telemetry.ko.md +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/docs/semantic-telemetry.md +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/docs/semantic-telemetry.ru.md +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/docs/semantic-telemetry.zh-CN.md +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/docs/semantic-telemetry.zh-TW.md +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/docs/v0.6.5-hardening-decisions.md +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/docs/v0.8.3-graph-ergonomics.md +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/scripts/_check_release_stage_integrity_impl.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/scripts/_dashboard_acceptance_impl.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/scripts/_ollama_interactive_acceptance_impl.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/scripts/_ollama_visible_acceptance_impl.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/scripts/_python_native_acceptance_impl.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/scripts/acceptance/__init__.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/scripts/acceptance/browser_diagnostics.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/scripts/acceptance/contracts.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/scripts/acceptance/g5_runner.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/scripts/acceptance/g6_runner.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/scripts/acceptance/interrupt_guard.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/scripts/acceptance/processes.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/scripts/acceptance/reporting.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/scripts/acceptance/terminal_output.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/scripts/annotate_pytest_failures.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/scripts/audit_i18n_parity.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/scripts/check_claude_hook.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/scripts/check_claude_record_graph.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/scripts/check_codex_hook.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/scripts/check_conversation_records.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/scripts/check_correlation_graph.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/scripts/check_inference_gateway_cli.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/scripts/check_model_runtime_cli.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/scripts/check_openai_compatible_cli.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/scripts/check_release_stage_integrity.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/scripts/check_semantic_graph.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/scripts/check_viewer_js.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/scripts/check_wheel_install.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/scripts/check_windows_launchers.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/scripts/dashboard_acceptance.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/scripts/emit_claude_hook_smoke.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/scripts/emit_codex_hook_smoke.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/scripts/emit_cursor_hook_smoke.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/scripts/emit_opencode_plugin_smoke.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/scripts/make_semantic_smoke.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/scripts/measure_graph_metrics.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/scripts/ollama_interactive_acceptance.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/scripts/ollama_visible_acceptance.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/scripts/owned_cleanup_acceptance.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/scripts/probe_provider_capability.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/scripts/python_native_acceptance.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/scripts/sync_i18n_nav.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/src/execweave/__main__.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/src/execweave/_conversation_records_core.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/src/execweave/_dashboard_shell_base.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/src/execweave/_http_proxy_base.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/src/execweave/_http_proxy_bounded.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/src/execweave/_http_proxy_stage.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/src/execweave/agent_bootstrap.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/src/execweave/agent_topology.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/src/execweave/agent_trace.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/src/execweave/agy_preview_sanitize.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/src/execweave/analysis.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/src/execweave/anthropic.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/src/execweave/anthropic_cli.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/src/execweave/anthropic_full_fidelity.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/src/execweave/antigravity_adapter.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/src/execweave/antigravity_adapter_base.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/src/execweave/antigravity_full_fidelity.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/src/execweave/antigravity_full_fidelity_base.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/src/execweave/antigravity_full_fidelity_collaboration_base.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/src/execweave/antigravity_hook_cli.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/src/execweave/antigravity_record.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/src/execweave/antigravity_subagent_linkage.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/src/execweave/antigravity_trace_capability.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/src/execweave/auto_specialized.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/src/execweave/backends.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/src/execweave/benchmark.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/src/execweave/claude_adapter.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/src/execweave/claude_child_transcript.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/src/execweave/claude_delegation.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/src/execweave/claude_full_fidelity.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/src/execweave/claude_hook_cli.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/src/execweave/claude_hook_contract.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/src/execweave/claude_model_observer.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/src/execweave/claude_record.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/src/execweave/cli.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/src/execweave/codex_adapter.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/src/execweave/codex_conversation.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/src/execweave/codex_full_fidelity.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/src/execweave/codex_hook_cli.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/src/execweave/codex_hook_entry.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/src/execweave/codex_hook_lifecycle.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/src/execweave/codex_message_diagnostics.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/src/execweave/codex_message_transport_diagnostics.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/src/execweave/codex_record.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/src/execweave/codex_rollout_structures.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/src/execweave/codex_rollout_trace.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/src/execweave/codex_rollout_trace_base.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/src/execweave/content_evidence.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/src/execweave/content_store.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/src/execweave/conversation_archive.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/src/execweave/conversation_message_identity.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/src/execweave/conversation_preview.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/src/execweave/conversation_preview_antigravity.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/src/execweave/conversation_preview_claude.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/src/execweave/conversation_preview_codex.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/src/execweave/conversation_preview_common.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/src/execweave/conversation_preview_generic.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/src/execweave/conversation_preview_lines.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/src/execweave/conversation_preview_transcript.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/src/execweave/conversation_records.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/src/execweave/conversation_records_antigravity.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/src/execweave/conversation_records_codex.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/src/execweave/conversation_records_common.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/src/execweave/conversation_records_ollama.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/src/execweave/correlation.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/src/execweave/cursor_adapter.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/src/execweave/cursor_delegation.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/src/execweave/cursor_delegation_base.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/src/execweave/cursor_full_fidelity.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/src/execweave/cursor_hook_cli.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/src/execweave/cursor_hook_contract.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/src/execweave/cursor_record.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/src/execweave/dashboard_shell.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/src/execweave/entry.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/src/execweave/evidence_availability.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/src/execweave/evidence_grade.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/src/execweave/fidelity.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/src/execweave/filesystem.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/src/execweave/focus.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/src/execweave/graph.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/src/execweave/graph_ops.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/src/execweave/http_proxy.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/src/execweave/http_proxy_cli.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/src/execweave/inference_gateway.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/src/execweave/inference_gateway_cli.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/src/execweave/inference_gateway_full_fidelity.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/src/execweave/inference_identity.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/src/execweave/inference_identity_cli.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/src/execweave/integrity.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/src/execweave/integrity_cli.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/src/execweave/litellm_callback.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/src/execweave/litellm_callback_cli.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/src/execweave/live.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/src/execweave/live_core.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/src/execweave/live_view.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/src/execweave/live_view_extra_style.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/src/execweave/live_view_markup.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/src/execweave/live_view_process_layout.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/src/execweave/live_view_readability.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/src/execweave/live_view_script_a.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/src/execweave/live_view_script_b.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/src/execweave/live_view_script_c.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/src/execweave/live_view_script_d.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/src/execweave/live_view_style.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/src/execweave/model_runtime.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/src/execweave/model_runtime_cli.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/src/execweave/model_runtime_full_fidelity.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/src/execweave/openai_compatible.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/src/execweave/openai_compatible_cli.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/src/execweave/openai_compatible_full_fidelity.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/src/execweave/opencode_adapter.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/src/execweave/opencode_event_contract.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/src/execweave/opencode_full_fidelity.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/src/execweave/opencode_hook_cli.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/src/execweave/opencode_plugin_cli.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/src/execweave/opencode_record.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/src/execweave/opencode_task_linkage.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/src/execweave/overhead_benchmark.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/src/execweave/provider_capability.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/src/execweave/provider_lifecycle.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/src/execweave/provider_record.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/src/execweave/rule_pack.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/src/execweave/rule_pack_cli.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/src/execweave/scalability_benchmark.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/src/execweave/schema.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/src/execweave/scope.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/src/execweave/semantic.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/src/execweave/sink.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/src/execweave/strace_backend.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/src/execweave/stream_assembly.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/src/execweave/theme.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/src/execweave/top.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/src/execweave/top_cli.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/src/execweave/validate.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/src/execweave/vendor/dagre.min.js +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/src/execweave/view_cli.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/src/execweave/viewer.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/src/execweave/viewer_agent_panel.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/src/execweave/viewer_agent_panel_antigravity.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/src/execweave/viewer_agent_panel_claude.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/src/execweave/viewer_agent_panel_codex.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/src/execweave/viewer_agent_panel_cursor.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/src/execweave/viewer_agent_panel_default.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/src/execweave/viewer_agent_panel_ollama.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/src/execweave/viewer_agent_panel_opencode.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/src/execweave/viewer_agent_panel_registry.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/src/execweave/viewer_content_inspector.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/src/execweave/viewer_dashboard_clean.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/src/execweave/viewer_dashboard_focus.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/src/execweave/viewer_dashboard_hardening.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/src/execweave/viewer_dashboard_hardening_v2.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/src/execweave/viewer_external_endpoints.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/src/execweave/viewer_limits.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/src/execweave/viewer_live_layout.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/src/execweave/viewer_projection.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/src/execweave/viewer_projection_base.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/src/execweave/viewer_semantic_projection.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/src/execweave/workflow.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/dashboard_readability_fixture.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/fixtures/codex_multi_agent/PROVENANCE.md +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/fixtures/codex_multi_agent/hook-payloads.json +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/fixtures/codex_multi_agent/rollout-main.jsonl +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/fixtures/hooks/README.md +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/fixtures/hooks/claude.json +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/fixtures/hooks/codex.json +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/fixtures/hooks/cursor.json +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/fixtures/hooks/manifest.json +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/fixtures/hooks/opencode.json +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/multi_agent_run_fixture.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/test_acceptance_browser_diagnostics_e2e.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/test_acceptance_conpty_selection.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/test_acceptance_interrupt_guard.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/test_acceptance_owned_processes.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/test_acceptance_required_capabilities.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/test_acceptance_terminal_output.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/test_acceptance_visible_pipe.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/test_agent_bootstrap.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/test_agent_message_viewer.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/test_agent_node_labels.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/test_agent_said_panel.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/test_agent_topology_evidence.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/test_agent_trace_lifecycle.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/test_agent_trace_viewer_visibility.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/test_agy_windows_wire_acceptance.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/test_analysis.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/test_anthropic.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/test_antigravity_agent_collaboration.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/test_antigravity_child_panel_policy.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/test_antigravity_child_transcript_tools.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/test_antigravity_cursor_launch.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/test_antigravity_field_run_regressions.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/test_antigravity_history_replay.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/test_antigravity_identity_topology.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/test_antigravity_invocation_archive.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/test_antigravity_lifecycle.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/test_antigravity_linkage_projection.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/test_antigravity_multi_conversation_isolation.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/test_antigravity_official_contract.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/test_antigravity_role_path_fallback.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/test_antigravity_root_child_history_v2.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/test_antigravity_subagent_transcript_linkage.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/test_antigravity_trace_capability_cli.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/test_auto_specialized.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/test_auto_specialized_ollama_two_phase.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/test_backends.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/test_claude_adapter.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/test_claude_child_transcript_tools.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/test_claude_delegation.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/test_claude_full_fidelity.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/test_claude_hook_contract.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/test_claude_hook_metadata.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/test_claude_hook_viewer.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/test_claude_model_observer.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/test_claude_record.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/test_cleanup_finalizer_identity.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/test_codex_adapter.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/test_codex_archive_full_fidelity.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/test_codex_child_panel_policy.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/test_codex_conversation_isolation.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/test_codex_full_fidelity.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/test_codex_hook_global_fail_open.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/test_codex_hook_lifecycle.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/test_codex_hook_partial_capture.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/test_codex_interrupt_contract.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/test_codex_message_diagnostics.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/test_codex_message_transport_diagnostics.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/test_codex_nickname_path_fallback.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/test_codex_plain_routed_agent_message.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/test_codex_real_multi_agent_conversation.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/test_codex_record.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/test_codex_reducer_command.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/test_codex_rollout_structures.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/test_codex_rollout_trace.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/test_codex_routing_native_identity.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/test_collector.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/test_command.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/test_condense.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/test_conversation_access.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/test_conversation_agent_focus.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/test_conversation_agent_isolation.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/test_conversation_identity_merge.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/test_conversation_message_observation_dedupe.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/test_conversation_provider_parity.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/test_conversation_root_authority.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/test_correlation.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/test_correlation_canonical_path.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/test_correlation_checker.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/test_correlation_process_exe.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/test_cross_provider_agent_trace.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/test_cursor_adapter.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/test_cursor_delegation.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/test_cursor_full_fidelity.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/test_cursor_hook_contract.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/test_cursor_hook_fail_open.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/test_cursor_ollama_session_lifecycle.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/test_cursor_record.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/test_cursor_task_linkage.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/test_dagre_semantic_pipeline.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/test_dashboard_acceptance_relative_output_e2e.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/test_dashboard_acceptance_reporting.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/test_dashboard_camera_scheduler_e2e.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/test_dashboard_favicon.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/test_dashboard_gif_export_e2e.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/test_dashboard_information_architecture.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/test_dashboard_initial_fit_readability_e2e.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/test_dashboard_node_drag_camera_e2e.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/test_dashboard_readability_e2e.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/test_dashboard_round_fold_state_e2e.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/test_dashboard_simplification.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/test_dashboard_ux_and_hook_projection.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/test_delegation_viewer.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/test_evidence_grade.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/test_execution_viewer.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/test_external_endpoints_all_providers.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/test_fidelity.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/test_filesystem_resilience.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/test_focus.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/test_fold_budget_setting.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/test_full_fidelity.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/test_g5_hardening_contract.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/test_g6_owned_parity_contract.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/test_graph.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/test_graph_arrange_constraints_e2e.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/test_graph_clear_focus_e2e.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/test_graph_edge_routing_e2e.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/test_graph_lane_separation_e2e.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/test_graph_node_sizing_e2e.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/test_graph_ops.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/test_hook_fixture_corpus.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/test_http_proxy.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/test_http_proxy_request_phase.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/test_http_proxy_response_memory.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/test_http_proxy_streaming.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/test_i18n_readme_policy.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/test_inference_endpoint_identity.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/test_inference_gateway.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/test_inference_gateway_full_fidelity.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/test_inference_identity.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/test_integrity.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/test_litellm_callback.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/test_live.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/test_live_auth.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/test_live_dashboard.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/test_live_dashboard_js.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/test_live_delta.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/test_live_logs_export.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/test_live_theme.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/test_lmstudio_auto_specialized.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/test_local_runtime_live_capture.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/test_model_runtime.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/test_model_runtime_full_fidelity.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/test_ollama_interactive_acceptance.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/test_ollama_interactive_terminal_semantics.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/test_ollama_panel_policy.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/test_ollama_serve_runtime_integration.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/test_ollama_visible_acceptance.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/test_openai_compatible.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/test_opencode_adapter.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/test_opencode_event_contract.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/test_opencode_event_lifecycle.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/test_opencode_full_fidelity.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/test_opencode_identity_unification.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/test_opencode_plugin.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/test_opencode_record.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/test_opencode_task_session_linkage.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/test_overhead_benchmark.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/test_per_agent_conversation_default.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/test_pr25_premerge_hardening_contract.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/test_pr25_premerge_hardening_e2e.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/test_pro6_audit_regressions.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/test_process_tree_layout.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/test_provider_capability.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/test_provider_conversation_evidence.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/test_provider_conversation_history_integrity.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/test_provider_dashboard_contract.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/test_provider_lifecycle.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/test_provider_neutral_viewer_semantics.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/test_python_native_acceptance.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/test_relay_prompt_live_e2e.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/test_release_stage_integrity_version_guard.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/test_rule_pack.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/test_schema.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/test_scope.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/test_semantic.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/test_shared_injected_context_scope.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/test_single_agent_barycenter.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/test_strace_backend.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/test_stream_assembly.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/test_threat_model.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/test_tool_traffic_e2e.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/test_top_detached.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/test_v063_features.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/test_v064_live_auto_integrations.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/test_v064_live_evidence.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/test_v079_review_e2e.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/test_v079_review_regressions.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/test_v083_release_gate_p2.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/test_validate.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/test_version.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/test_viewer.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/test_viewer_agent_isolation_e2e.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/test_viewer_child_authority.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/test_viewer_content_inspector.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/test_viewer_limits.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/test_viewer_projection.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/test_visual_ux_readability.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/test_windows_codex_agy_display_repair.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tests/test_workflow.py +0 -0
- {execweave-0.8.12 → execweave-0.8.14}/tools/verify_metrics_tool.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: execweave
|
|
3
|
-
Version: 0.8.
|
|
3
|
+
Version: 0.8.14
|
|
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
|
|
@@ -4,8 +4,8 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "execweave"
|
|
7
|
-
# ExecWeave v0.8.
|
|
8
|
-
version = "0.8.
|
|
7
|
+
# ExecWeave v0.8.14 release metadata
|
|
8
|
+
version = "0.8.14"
|
|
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"
|
|
@@ -123,12 +123,35 @@ class RuntimeCollector:
|
|
|
123
123
|
self.collect_filesystem = collect_filesystem
|
|
124
124
|
self.collect_network = collect_network
|
|
125
125
|
self._seen_processes: dict[int, ProcessSnapshot] = {}
|
|
126
|
+
self._discovered_processes: dict[int, ProcessSnapshot] = {}
|
|
126
127
|
self._seen_connections: set[tuple[str, str | None, str | None, str]] = set()
|
|
127
128
|
self._network_sample_attempts = 0
|
|
128
129
|
self._network_sample_successes = 0
|
|
129
130
|
self._network_sample_errors = 0
|
|
130
131
|
self._network_access_denied = 0
|
|
131
132
|
|
|
133
|
+
def _filesystem_excluded_roots(self) -> list[Path]:
|
|
134
|
+
"""Return ExecWeave-owned paths that must never become workload evidence.
|
|
135
|
+
|
|
136
|
+
The default ``.execweave`` tree and the runtime event stream were already
|
|
137
|
+
internal. Live mode can also place ``events.jsonl`` and ``semantic.jsonl``
|
|
138
|
+
together in a caller-selected output directory inside the watch root. When
|
|
139
|
+
those files are siblings, exclude their whole run directory so ExecWeave's
|
|
140
|
+
own evidence writes cannot recursively manufacture filesystem evidence.
|
|
141
|
+
A separately configured semantic sidecar remains an exact-file exclusion.
|
|
142
|
+
"""
|
|
143
|
+
sink_path = self.sink.path.expanduser().resolve()
|
|
144
|
+
excluded = [(self.watch_root / ".execweave").resolve(), sink_path]
|
|
145
|
+
configured = os.environ.get("EXECWEAVE_SEMANTIC_SIDECAR")
|
|
146
|
+
if not configured:
|
|
147
|
+
return excluded
|
|
148
|
+
|
|
149
|
+
semantic_path = Path(configured).expanduser().resolve()
|
|
150
|
+
excluded.append(
|
|
151
|
+
semantic_path.parent if semantic_path.parent == sink_path.parent else semantic_path
|
|
152
|
+
)
|
|
153
|
+
return excluded
|
|
154
|
+
|
|
132
155
|
def run(self, command: list[str]) -> int:
|
|
133
156
|
if not command:
|
|
134
157
|
raise ValueError("command must not be empty")
|
|
@@ -163,17 +186,17 @@ class RuntimeCollector:
|
|
|
163
186
|
)
|
|
164
187
|
|
|
165
188
|
watcher: FileWatcher | None = None
|
|
166
|
-
internal_root = self.watch_root / ".execweave"
|
|
167
189
|
if self.collect_filesystem:
|
|
168
190
|
watcher = FileWatcher(
|
|
169
191
|
root=self.watch_root,
|
|
170
192
|
session_id=self.session_id,
|
|
171
193
|
session_entity=session,
|
|
172
194
|
sink=self.sink,
|
|
173
|
-
excluded_roots=
|
|
195
|
+
excluded_roots=self._filesystem_excluded_roots(),
|
|
174
196
|
)
|
|
175
197
|
|
|
176
198
|
process: subprocess.Popen[bytes] | None = None
|
|
199
|
+
owned: list[psutil.Process] = []
|
|
177
200
|
return_code = 1
|
|
178
201
|
interrupted = False
|
|
179
202
|
collector_error_type: str | None = None
|
|
@@ -209,8 +232,6 @@ class RuntimeCollector:
|
|
|
209
232
|
except KeyboardInterrupt:
|
|
210
233
|
interrupted = True
|
|
211
234
|
return_code = 130
|
|
212
|
-
if process is not None:
|
|
213
|
-
self._terminate_process_tree(process)
|
|
214
235
|
|
|
215
236
|
if not interrupted:
|
|
216
237
|
run_post_command_specialized_probe(
|
|
@@ -220,16 +241,24 @@ class RuntimeCollector:
|
|
|
220
241
|
return return_code
|
|
221
242
|
except BaseException as exc:
|
|
222
243
|
collector_error_type = type(exc).__name__
|
|
223
|
-
if process is not None and process.poll() is None:
|
|
224
|
-
self._terminate_process_tree(process)
|
|
225
|
-
workload_terminated_due_to_collector_error = True
|
|
226
244
|
raise
|
|
227
245
|
finally:
|
|
246
|
+
# A workload exception is a nonzero child exit, not an exception in
|
|
247
|
+
# this collector. Finalize observed descendants on every exit path,
|
|
248
|
+
# including successful launchers that leave reparented children.
|
|
249
|
+
if process is not None:
|
|
250
|
+
owned = self._owned_live_processes(process)
|
|
251
|
+
workload_terminated_due_to_collector_error = (
|
|
252
|
+
collector_error_type is not None and bool(owned)
|
|
253
|
+
)
|
|
254
|
+
self._terminate_process_tree(process, owned=owned)
|
|
228
255
|
if watcher is not None:
|
|
229
256
|
watcher.stop()
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
257
|
+
# A failed termination must not become a false clean result merely
|
|
258
|
+
# because the selected child has since reparented out of the tree.
|
|
259
|
+
workload_alive_after_cleanup = any(
|
|
260
|
+
self._process_is_live(candidate) for candidate in owned
|
|
261
|
+
) or bool(process is not None and self._owned_live_processes(process))
|
|
233
262
|
self.sink.emit(
|
|
234
263
|
RuntimeEvent.create(
|
|
235
264
|
session_id=self.session_id,
|
|
@@ -258,33 +287,95 @@ class RuntimeCollector:
|
|
|
258
287
|
)
|
|
259
288
|
|
|
260
289
|
@staticmethod
|
|
261
|
-
def
|
|
262
|
-
|
|
290
|
+
def _process_is_live(proc: psutil.Process) -> bool:
|
|
291
|
+
try:
|
|
292
|
+
if not proc.is_running():
|
|
293
|
+
return False
|
|
294
|
+
try:
|
|
295
|
+
return proc.status() != psutil.STATUS_ZOMBIE
|
|
296
|
+
except psutil.AccessDenied:
|
|
297
|
+
return True
|
|
298
|
+
except (psutil.NoSuchProcess, psutil.ZombieProcess):
|
|
299
|
+
return False
|
|
300
|
+
|
|
301
|
+
def _process_for_snapshot(self, snapshot: ProcessSnapshot) -> psutil.Process | None:
|
|
263
302
|
try:
|
|
264
|
-
|
|
265
|
-
|
|
303
|
+
process = psutil.Process(snapshot.pid)
|
|
304
|
+
# Cleanup needs identity, not readable exe/name/cmdline metadata.
|
|
305
|
+
# Never treat a reused PID as the process we originally observed.
|
|
306
|
+
if process.create_time() != snapshot.create_time:
|
|
307
|
+
return None
|
|
308
|
+
return process
|
|
266
309
|
except (psutil.NoSuchProcess, psutil.AccessDenied, psutil.ZombieProcess):
|
|
267
|
-
|
|
310
|
+
return None
|
|
268
311
|
|
|
269
|
-
|
|
312
|
+
def _owned_live_processes(
|
|
313
|
+
self,
|
|
314
|
+
process: subprocess.Popen[bytes],
|
|
315
|
+
) -> list[psutil.Process]:
|
|
316
|
+
"""Return live processes still owned by this collector's launched workload.
|
|
317
|
+
|
|
318
|
+
A shell or launcher can exit before its children. Relying only on the current
|
|
319
|
+
root process tree then loses those reparented descendants. The collector's
|
|
320
|
+
lifetime-qualified process snapshots preserve enough ownership evidence to
|
|
321
|
+
find and clean them without risking a reused PID.
|
|
322
|
+
"""
|
|
323
|
+
owned: dict[int, psutil.Process] = {}
|
|
324
|
+
|
|
325
|
+
def add_with_descendants(candidate: psutil.Process) -> None:
|
|
326
|
+
if not self._process_is_live(candidate):
|
|
327
|
+
return
|
|
328
|
+
owned[candidate.pid] = candidate
|
|
270
329
|
try:
|
|
271
|
-
|
|
330
|
+
descendants = candidate.children(recursive=True)
|
|
272
331
|
except (psutil.NoSuchProcess, psutil.AccessDenied, psutil.ZombieProcess):
|
|
273
|
-
|
|
332
|
+
descendants = []
|
|
333
|
+
for child in descendants:
|
|
334
|
+
if self._process_is_live(child):
|
|
335
|
+
owned[child.pid] = child
|
|
274
336
|
|
|
275
337
|
if process.poll() is None:
|
|
276
338
|
try:
|
|
277
|
-
process.
|
|
278
|
-
except
|
|
339
|
+
add_with_descendants(psutil.Process(process.pid))
|
|
340
|
+
except (psutil.NoSuchProcess, psutil.AccessDenied, psutil.ZombieProcess):
|
|
341
|
+
pass
|
|
342
|
+
|
|
343
|
+
snapshots = {**self._seen_processes, **self._discovered_processes}
|
|
344
|
+
for snapshot in snapshots.values():
|
|
345
|
+
tracked = self._process_for_snapshot(snapshot)
|
|
346
|
+
if tracked is not None:
|
|
347
|
+
add_with_descendants(tracked)
|
|
348
|
+
|
|
349
|
+
return list(owned.values())
|
|
350
|
+
|
|
351
|
+
def _terminate_process_tree(
|
|
352
|
+
self,
|
|
353
|
+
process: subprocess.Popen[bytes],
|
|
354
|
+
*,
|
|
355
|
+
owned: list[psutil.Process] | None = None,
|
|
356
|
+
) -> None:
|
|
357
|
+
# A caller's selection must survive reparenting between discovery and
|
|
358
|
+
# termination. Re-querying here can lose children we just proved owned.
|
|
359
|
+
if owned is None:
|
|
360
|
+
owned = self._owned_live_processes(process)
|
|
361
|
+
# Terminate descendants/tracked orphans before the launcher/root when it is
|
|
362
|
+
# still alive. Holding psutil handles also keeps cleanup robust if a parent
|
|
363
|
+
# exits while the loop is running.
|
|
364
|
+
for candidate in sorted(owned, key=lambda item: item.pid == process.pid):
|
|
365
|
+
try:
|
|
366
|
+
candidate.terminate()
|
|
367
|
+
except (psutil.NoSuchProcess, psutil.AccessDenied, psutil.ZombieProcess):
|
|
279
368
|
pass
|
|
280
369
|
|
|
281
|
-
if
|
|
282
|
-
_, alive = psutil.wait_procs(
|
|
283
|
-
for
|
|
370
|
+
if owned:
|
|
371
|
+
_, alive = psutil.wait_procs(owned, timeout=2.0)
|
|
372
|
+
for candidate in alive:
|
|
284
373
|
try:
|
|
285
|
-
|
|
374
|
+
candidate.kill()
|
|
286
375
|
except (psutil.NoSuchProcess, psutil.AccessDenied, psutil.ZombieProcess):
|
|
287
376
|
pass
|
|
377
|
+
if alive:
|
|
378
|
+
psutil.wait_procs(alive, timeout=2.0)
|
|
288
379
|
|
|
289
380
|
try:
|
|
290
381
|
process.wait(timeout=2.0)
|
|
@@ -319,6 +410,11 @@ class RuntimeCollector:
|
|
|
319
410
|
current[snapshot.pid] = snapshot
|
|
320
411
|
process_objects[snapshot.pid] = proc
|
|
321
412
|
|
|
413
|
+
# Preserve the complete discovered tree before any event/network callback
|
|
414
|
+
# can raise. _seen_processes only contains successfully registered starts;
|
|
415
|
+
# a root callback can fail after its children have already reparented.
|
|
416
|
+
# Retain only the latest sample here, not an unbounded lifetime history.
|
|
417
|
+
self._discovered_processes = current
|
|
322
418
|
for snapshot in current.values():
|
|
323
419
|
previous = self._seen_processes.get(snapshot.pid)
|
|
324
420
|
if previous is None or not self._same_process_lifetime(previous, snapshot):
|
|
@@ -80,7 +80,12 @@ def _resolve_executable(executable: str, *, path: str | None = None) -> str:
|
|
|
80
80
|
candidate = Path(executable).expanduser()
|
|
81
81
|
if not candidate.is_file():
|
|
82
82
|
raise FileNotFoundError(f"command executable not found: {executable!r}")
|
|
83
|
-
|
|
83
|
+
# Keep the user-selected launcher path itself. In particular, a virtualenv
|
|
84
|
+
# Python executable is commonly a symlink to the base interpreter on POSIX;
|
|
85
|
+
# dereferencing it changes Python's prefix discovery and silently drops the
|
|
86
|
+
# virtualenv site-packages. ``abspath`` normalizes the argv path without
|
|
87
|
+
# resolving symlinks.
|
|
88
|
+
resolved = os.path.abspath(os.fspath(candidate))
|
|
84
89
|
else:
|
|
85
90
|
path_launcher = shutil.which(executable, path=path)
|
|
86
91
|
if executable.lower() == "cursor" and _prefer_cursor_desktop_launcher():
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import os
|
|
4
|
+
import subprocess
|
|
5
|
+
import sys
|
|
6
|
+
import time
|
|
7
|
+
import venv
|
|
8
|
+
from pathlib import Path
|
|
9
|
+
|
|
10
|
+
import psutil
|
|
11
|
+
import pytest
|
|
12
|
+
|
|
13
|
+
from execweave.collector import RuntimeCollector, _safe_process_snapshot
|
|
14
|
+
from execweave.command import resolve_launch_command
|
|
15
|
+
from execweave.sink import JsonlSink
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def _process_is_live(pid: int) -> bool:
|
|
19
|
+
try:
|
|
20
|
+
process = psutil.Process(pid)
|
|
21
|
+
return process.is_running() and process.status() != psutil.STATUS_ZOMBIE
|
|
22
|
+
except (psutil.NoSuchProcess, psutil.AccessDenied, psutil.ZombieProcess):
|
|
23
|
+
return False
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def _wait_for(predicate, *, timeout: float = 5.0) -> None:
|
|
27
|
+
deadline = time.monotonic() + timeout
|
|
28
|
+
while time.monotonic() < deadline:
|
|
29
|
+
if predicate():
|
|
30
|
+
return
|
|
31
|
+
time.sleep(0.02)
|
|
32
|
+
raise AssertionError("condition did not become true before timeout")
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def test_explicit_virtualenv_python_keeps_launcher_and_site_prefix(tmp_path: Path) -> None:
|
|
36
|
+
venv_root = tmp_path / ".venv"
|
|
37
|
+
venv.EnvBuilder(with_pip=False, symlinks=os.name != "nt").create(venv_root)
|
|
38
|
+
venv_python = (
|
|
39
|
+
venv_root / "Scripts" / "python.exe"
|
|
40
|
+
if os.name == "nt"
|
|
41
|
+
else venv_root / "bin" / "python"
|
|
42
|
+
)
|
|
43
|
+
if os.name != "nt":
|
|
44
|
+
assert venv_python.is_symlink()
|
|
45
|
+
|
|
46
|
+
launch = resolve_launch_command(
|
|
47
|
+
[str(venv_python), "-c", "import sys; print(sys.prefix)"]
|
|
48
|
+
)
|
|
49
|
+
|
|
50
|
+
assert launch[0] == os.path.abspath(os.fspath(venv_python))
|
|
51
|
+
if os.name != "nt":
|
|
52
|
+
assert Path(launch[0]).is_symlink()
|
|
53
|
+
completed = subprocess.run(
|
|
54
|
+
launch,
|
|
55
|
+
check=True,
|
|
56
|
+
capture_output=True,
|
|
57
|
+
text=True,
|
|
58
|
+
)
|
|
59
|
+
assert Path(completed.stdout.strip()).resolve() == venv_root.resolve()
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
def test_live_sibling_sidecar_excludes_entire_internal_output_dir(
|
|
63
|
+
monkeypatch: pytest.MonkeyPatch,
|
|
64
|
+
tmp_path: Path,
|
|
65
|
+
) -> None:
|
|
66
|
+
run_dir = tmp_path / "custom-live-output"
|
|
67
|
+
run_dir.mkdir()
|
|
68
|
+
event_path = run_dir / "events.jsonl"
|
|
69
|
+
semantic_path = run_dir / "semantic.jsonl"
|
|
70
|
+
monkeypatch.setenv("EXECWEAVE_SEMANTIC_SIDECAR", str(semantic_path))
|
|
71
|
+
|
|
72
|
+
collector = RuntimeCollector(
|
|
73
|
+
session_id="d001",
|
|
74
|
+
sink=JsonlSink(event_path),
|
|
75
|
+
watch_root=tmp_path,
|
|
76
|
+
poll_interval=0.02,
|
|
77
|
+
collect_filesystem=True,
|
|
78
|
+
collect_network=False,
|
|
79
|
+
)
|
|
80
|
+
|
|
81
|
+
excluded = collector._filesystem_excluded_roots()
|
|
82
|
+
assert run_dir.resolve() in excluded
|
|
83
|
+
assert event_path.resolve() in excluded
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
def test_separate_semantic_sidecar_does_not_hide_unrelated_parent_directory(
|
|
87
|
+
monkeypatch: pytest.MonkeyPatch,
|
|
88
|
+
tmp_path: Path,
|
|
89
|
+
) -> None:
|
|
90
|
+
run_dir = tmp_path / "runtime-output"
|
|
91
|
+
sidecar_dir = tmp_path / "user-selected-sidecar-dir"
|
|
92
|
+
run_dir.mkdir()
|
|
93
|
+
sidecar_dir.mkdir()
|
|
94
|
+
semantic_path = sidecar_dir / "semantic.jsonl"
|
|
95
|
+
monkeypatch.setenv("EXECWEAVE_SEMANTIC_SIDECAR", str(semantic_path))
|
|
96
|
+
|
|
97
|
+
collector = RuntimeCollector(
|
|
98
|
+
session_id="d001-separate",
|
|
99
|
+
sink=JsonlSink(run_dir / "events.jsonl"),
|
|
100
|
+
watch_root=tmp_path,
|
|
101
|
+
poll_interval=0.02,
|
|
102
|
+
collect_filesystem=True,
|
|
103
|
+
collect_network=False,
|
|
104
|
+
)
|
|
105
|
+
|
|
106
|
+
excluded = collector._filesystem_excluded_roots()
|
|
107
|
+
assert semantic_path.resolve() in excluded
|
|
108
|
+
assert sidecar_dir.resolve() not in excluded
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
def test_cleanup_terminates_tracked_child_after_launcher_has_exited(tmp_path: Path) -> None:
|
|
112
|
+
child_pid_path = tmp_path / "child.pid"
|
|
113
|
+
release_parent_path = tmp_path / "release-parent"
|
|
114
|
+
parent_code = r'''
|
|
115
|
+
import subprocess
|
|
116
|
+
import sys
|
|
117
|
+
import time
|
|
118
|
+
from pathlib import Path
|
|
119
|
+
|
|
120
|
+
pid_path = Path(sys.argv[1])
|
|
121
|
+
release_path = Path(sys.argv[2])
|
|
122
|
+
child = subprocess.Popen([sys.executable, "-c", "import time; time.sleep(30)"])
|
|
123
|
+
pid_path.write_text(str(child.pid), encoding="utf-8")
|
|
124
|
+
while not release_path.exists():
|
|
125
|
+
time.sleep(0.02)
|
|
126
|
+
'''
|
|
127
|
+
parent = subprocess.Popen(
|
|
128
|
+
[
|
|
129
|
+
sys.executable,
|
|
130
|
+
"-c",
|
|
131
|
+
parent_code,
|
|
132
|
+
str(child_pid_path),
|
|
133
|
+
str(release_parent_path),
|
|
134
|
+
]
|
|
135
|
+
)
|
|
136
|
+
child_pid: int | None = None
|
|
137
|
+
try:
|
|
138
|
+
_wait_for(child_pid_path.exists)
|
|
139
|
+
child_pid = int(child_pid_path.read_text(encoding="utf-8"))
|
|
140
|
+
child = psutil.Process(child_pid)
|
|
141
|
+
snapshot = _safe_process_snapshot(child)
|
|
142
|
+
assert snapshot is not None
|
|
143
|
+
|
|
144
|
+
collector = RuntimeCollector(
|
|
145
|
+
session_id="d003",
|
|
146
|
+
sink=JsonlSink(tmp_path / "events.jsonl"),
|
|
147
|
+
watch_root=tmp_path,
|
|
148
|
+
poll_interval=0.02,
|
|
149
|
+
collect_filesystem=False,
|
|
150
|
+
collect_network=False,
|
|
151
|
+
)
|
|
152
|
+
collector._seen_processes[child_pid] = snapshot
|
|
153
|
+
|
|
154
|
+
release_parent_path.touch()
|
|
155
|
+
parent.wait(timeout=5)
|
|
156
|
+
assert parent.poll() is not None
|
|
157
|
+
assert _process_is_live(child_pid)
|
|
158
|
+
|
|
159
|
+
collector._terminate_process_tree(parent)
|
|
160
|
+
|
|
161
|
+
_wait_for(lambda: not _process_is_live(child_pid))
|
|
162
|
+
assert not _process_is_live(child_pid)
|
|
163
|
+
finally:
|
|
164
|
+
if parent.poll() is None:
|
|
165
|
+
parent.kill()
|
|
166
|
+
parent.wait(timeout=5)
|
|
167
|
+
if child_pid is not None and _process_is_live(child_pid):
|
|
168
|
+
try:
|
|
169
|
+
psutil.Process(child_pid).kill()
|
|
170
|
+
except (psutil.NoSuchProcess, psutil.AccessDenied, psutil.ZombieProcess):
|
|
171
|
+
pass
|