execweave 0.8.15__tar.gz → 0.8.16__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.15 → execweave-0.8.16}/.github/workflows/provider-capability-stage-integrity.yml +18 -0
- {execweave-0.8.15 → execweave-0.8.16}/PKG-INFO +12 -1
- {execweave-0.8.15 → execweave-0.8.16}/README.md +9 -0
- {execweave-0.8.15 → execweave-0.8.16}/pyproject.toml +4 -2
- {execweave-0.8.15 → execweave-0.8.16}/src/execweave/__init__.py +1 -1
- {execweave-0.8.15 → execweave-0.8.16}/src/execweave/live_view.py +0 -27
- execweave-0.8.16/src/execweave/live_view_script_d.py +40 -0
- {execweave-0.8.15 → execweave-0.8.16}/src/execweave/viewer_dashboard_clean.py +0 -5
- {execweave-0.8.15 → execweave-0.8.16}/src/execweave/viewer_dashboard_hardening_v2.py +1 -22
- execweave-0.8.16/src/execweave/viewer_gif.py +232 -0
- execweave-0.8.16/tests/test_dashboard_gif_export_e2e.py +280 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_live_logs_export.py +3 -2
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_pr25_premerge_hardening_contract.py +3 -8
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_v069_dashboard_release.py +32 -53
- execweave-0.8.15/src/execweave/live_view_script_d.py +0 -47
- execweave-0.8.15/tests/test_dashboard_gif_export_e2e.py +0 -108
- {execweave-0.8.15 → execweave-0.8.16}/.github/workflows/ci.yml +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/.github/workflows/cleanup-workflow-history.yml +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/.github/workflows/i18n.yml +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/.github/workflows/package-benchmark.yml +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/.github/workflows/package-smoke.yml +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/.github/workflows/provider-dashboard-contract.yml +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/.github/workflows/publish.yml +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/.github/workflows/scalability.yml +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/.github/workflows/viewer-agent-isolation.yml +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/.github/workflows/wheel-smoke.yml +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/.github/workflows/windows-launcher.yml +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/.gitignore +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/LICENSE +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/README.de.md +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/README.fr.md +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/README.ja.md +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/README.ko.md +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/README.ru.md +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/README.zh-CN.md +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/README.zh-TW.md +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/benchmarks/phase1_overhead.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/diagnostics/acceptance_hardening_20260906.md +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/diagnostics/audit_eight_children.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/diagnostics/audit_python_journey.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/diagnostics/audit_real_clicks.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/diagnostics/current_state_reaudit.md +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/diagnostics/execweave_full_audit.md +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/diagnostics/gate_status.md +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/diagnostics/gate_status_history_through_g3.md +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/diagnostics/github_pr_inventory.json +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/diagnostics/handoff_checkpoint_20260906.md +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/diagnostics/next_agent_handoff.md +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/diagnostics/pr_regression_map.md +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/docs/antigravity-hooks.md +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/docs/assets/codex.gif +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/docs/benchmarks/README.md +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/docs/benchmarks/v0.6.0-github-actions.json +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/docs/benchmarks/v0.6.0-github-actions.svg +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/docs/claude-code-hooks.de.md +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/docs/claude-code-hooks.fr.md +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/docs/claude-code-hooks.ja.md +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/docs/claude-code-hooks.ko.md +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/docs/claude-code-hooks.md +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/docs/claude-code-hooks.ru.md +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/docs/claude-code-hooks.zh-CN.md +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/docs/claude-code-hooks.zh-TW.md +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/docs/codex-hooks.de.md +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/docs/codex-hooks.fr.md +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/docs/codex-hooks.ja.md +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/docs/codex-hooks.ko.md +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/docs/codex-hooks.md +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/docs/codex-hooks.ru.md +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/docs/codex-hooks.zh-CN.md +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/docs/codex-hooks.zh-TW.md +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/docs/cursor-hooks.de.md +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/docs/cursor-hooks.fr.md +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/docs/cursor-hooks.ja.md +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/docs/cursor-hooks.ko.md +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/docs/cursor-hooks.md +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/docs/cursor-hooks.ru.md +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/docs/cursor-hooks.zh-CN.md +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/docs/cursor-hooks.zh-TW.md +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/docs/evidence-grades.de.md +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/docs/evidence-grades.fr.md +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/docs/evidence-grades.ja.md +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/docs/evidence-grades.ko.md +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/docs/evidence-grades.md +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/docs/evidence-grades.ru.md +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/docs/evidence-grades.zh-CN.md +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/docs/evidence-grades.zh-TW.md +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/docs/inference-gateway.de.md +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/docs/inference-gateway.fr.md +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/docs/inference-gateway.ja.md +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/docs/inference-gateway.ko.md +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/docs/inference-gateway.md +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/docs/inference-gateway.ru.md +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/docs/inference-gateway.zh-CN.md +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/docs/inference-gateway.zh-TW.md +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/docs/internal/provider-capability-matrix.md +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/docs/live-graph.de.md +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/docs/live-graph.fr.md +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/docs/live-graph.ja.md +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/docs/live-graph.ko.md +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/docs/live-graph.md +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/docs/live-graph.ru.md +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/docs/live-graph.zh-CN.md +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/docs/live-graph.zh-TW.md +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/docs/model-runtime.de.md +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/docs/model-runtime.fr.md +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/docs/model-runtime.ja.md +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/docs/model-runtime.ko.md +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/docs/model-runtime.md +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/docs/model-runtime.ru.md +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/docs/model-runtime.zh-CN.md +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/docs/model-runtime.zh-TW.md +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/docs/opencode-plugin.de.md +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/docs/opencode-plugin.fr.md +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/docs/opencode-plugin.ja.md +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/docs/opencode-plugin.ko.md +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/docs/opencode-plugin.md +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/docs/opencode-plugin.ru.md +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/docs/opencode-plugin.zh-CN.md +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/docs/opencode-plugin.zh-TW.md +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/docs/phase-1-runtime-collection.de.md +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/docs/phase-1-runtime-collection.fr.md +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/docs/phase-1-runtime-collection.ja.md +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/docs/phase-1-runtime-collection.ko.md +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/docs/phase-1-runtime-collection.md +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/docs/phase-1-runtime-collection.ru.md +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/docs/phase-1-runtime-collection.zh-CN.md +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/docs/phase-1-runtime-collection.zh-TW.md +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/docs/phase-2-execution-graph.de.md +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/docs/phase-2-execution-graph.fr.md +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/docs/phase-2-execution-graph.ja.md +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/docs/phase-2-execution-graph.ko.md +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/docs/phase-2-execution-graph.md +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/docs/phase-2-execution-graph.ru.md +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/docs/phase-2-execution-graph.zh-CN.md +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/docs/phase-2-execution-graph.zh-TW.md +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/docs/remaining-provider-audit-v0.8.7.md +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/docs/rule-packs.de.md +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/docs/rule-packs.fr.md +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/docs/rule-packs.ja.md +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/docs/rule-packs.ko.md +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/docs/rule-packs.md +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/docs/rule-packs.ru.md +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/docs/rule-packs.zh-CN.md +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/docs/rule-packs.zh-TW.md +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/docs/run-integrity.de.md +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/docs/run-integrity.fr.md +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/docs/run-integrity.ja.md +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/docs/run-integrity.ko.md +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/docs/run-integrity.md +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/docs/run-integrity.ru.md +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/docs/run-integrity.zh-CN.md +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/docs/run-integrity.zh-TW.md +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/docs/runtime-threat-model.de.md +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/docs/runtime-threat-model.fr.md +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/docs/runtime-threat-model.ja.md +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/docs/runtime-threat-model.ko.md +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/docs/runtime-threat-model.md +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/docs/runtime-threat-model.ru.md +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/docs/runtime-threat-model.zh-CN.md +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/docs/runtime-threat-model.zh-TW.md +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/docs/security-analysis.de.md +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/docs/security-analysis.fr.md +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/docs/security-analysis.ja.md +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/docs/security-analysis.ko.md +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/docs/security-analysis.md +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/docs/security-analysis.ru.md +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/docs/security-analysis.zh-CN.md +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/docs/security-analysis.zh-TW.md +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/docs/semantic-telemetry.de.md +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/docs/semantic-telemetry.fr.md +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/docs/semantic-telemetry.ja.md +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/docs/semantic-telemetry.ko.md +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/docs/semantic-telemetry.md +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/docs/semantic-telemetry.ru.md +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/docs/semantic-telemetry.zh-CN.md +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/docs/semantic-telemetry.zh-TW.md +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/docs/v0.6.5-hardening-decisions.md +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/docs/v0.8.3-graph-ergonomics.md +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/scripts/_check_release_stage_integrity_impl.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/scripts/_dashboard_acceptance_impl.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/scripts/_ollama_interactive_acceptance_impl.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/scripts/_ollama_visible_acceptance_impl.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/scripts/_python_native_acceptance_impl.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/scripts/acceptance/__init__.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/scripts/acceptance/browser_diagnostics.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/scripts/acceptance/contracts.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/scripts/acceptance/g5_runner.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/scripts/acceptance/g6_runner.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/scripts/acceptance/interrupt_guard.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/scripts/acceptance/processes.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/scripts/acceptance/reporting.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/scripts/acceptance/terminal_output.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/scripts/annotate_pytest_failures.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/scripts/audit_i18n_parity.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/scripts/check_claude_hook.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/scripts/check_claude_record_graph.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/scripts/check_codex_hook.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/scripts/check_conversation_records.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/scripts/check_correlation_graph.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/scripts/check_inference_gateway_cli.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/scripts/check_model_runtime_cli.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/scripts/check_openai_compatible_cli.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/scripts/check_release_stage_integrity.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/scripts/check_semantic_graph.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/scripts/check_viewer_js.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/scripts/check_wheel_install.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/scripts/check_windows_launchers.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/scripts/dashboard_acceptance.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/scripts/emit_claude_hook_smoke.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/scripts/emit_codex_hook_smoke.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/scripts/emit_cursor_hook_smoke.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/scripts/emit_opencode_plugin_smoke.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/scripts/make_semantic_smoke.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/scripts/measure_graph_metrics.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/scripts/ollama_interactive_acceptance.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/scripts/ollama_visible_acceptance.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/scripts/owned_cleanup_acceptance.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/scripts/probe_provider_capability.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/scripts/python_native_acceptance.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/scripts/sync_i18n_nav.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/src/execweave/__main__.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/src/execweave/_conversation_records_core.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/src/execweave/_dashboard_shell_base.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/src/execweave/_http_proxy_base.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/src/execweave/_http_proxy_bounded.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/src/execweave/_http_proxy_stage.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/src/execweave/agent_bootstrap.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/src/execweave/agent_topology.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/src/execweave/agent_trace.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/src/execweave/agy_preview_sanitize.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/src/execweave/analysis.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/src/execweave/anthropic.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/src/execweave/anthropic_cli.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/src/execweave/anthropic_full_fidelity.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/src/execweave/antigravity_adapter.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/src/execweave/antigravity_adapter_base.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/src/execweave/antigravity_full_fidelity.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/src/execweave/antigravity_full_fidelity_base.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/src/execweave/antigravity_full_fidelity_collaboration_base.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/src/execweave/antigravity_hook_cli.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/src/execweave/antigravity_record.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/src/execweave/antigravity_subagent_linkage.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/src/execweave/antigravity_trace_capability.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/src/execweave/auto_specialized.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/src/execweave/backends.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/src/execweave/benchmark.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/src/execweave/claude_adapter.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/src/execweave/claude_child_transcript.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/src/execweave/claude_delegation.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/src/execweave/claude_full_fidelity.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/src/execweave/claude_hook_cli.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/src/execweave/claude_hook_contract.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/src/execweave/claude_model_observer.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/src/execweave/claude_record.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/src/execweave/cli.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/src/execweave/codex_adapter.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/src/execweave/codex_conversation.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/src/execweave/codex_full_fidelity.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/src/execweave/codex_hook_cli.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/src/execweave/codex_hook_entry.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/src/execweave/codex_hook_lifecycle.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/src/execweave/codex_message_diagnostics.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/src/execweave/codex_message_transport_diagnostics.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/src/execweave/codex_record.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/src/execweave/codex_rollout_structures.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/src/execweave/codex_rollout_trace.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/src/execweave/codex_rollout_trace_base.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/src/execweave/collector.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/src/execweave/command.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/src/execweave/content_evidence.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/src/execweave/content_store.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/src/execweave/conversation_archive.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/src/execweave/conversation_message_identity.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/src/execweave/conversation_preview.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/src/execweave/conversation_preview_antigravity.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/src/execweave/conversation_preview_claude.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/src/execweave/conversation_preview_codex.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/src/execweave/conversation_preview_common.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/src/execweave/conversation_preview_generic.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/src/execweave/conversation_preview_lines.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/src/execweave/conversation_preview_transcript.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/src/execweave/conversation_records.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/src/execweave/conversation_records_antigravity.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/src/execweave/conversation_records_codex.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/src/execweave/conversation_records_common.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/src/execweave/conversation_records_ollama.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/src/execweave/correlation.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/src/execweave/cursor_adapter.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/src/execweave/cursor_delegation.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/src/execweave/cursor_delegation_base.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/src/execweave/cursor_full_fidelity.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/src/execweave/cursor_hook_cli.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/src/execweave/cursor_hook_contract.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/src/execweave/cursor_record.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/src/execweave/dashboard_shell.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/src/execweave/entry.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/src/execweave/evidence_availability.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/src/execweave/evidence_grade.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/src/execweave/fidelity.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/src/execweave/filesystem.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/src/execweave/focus.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/src/execweave/graph.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/src/execweave/graph_ops.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/src/execweave/http_proxy.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/src/execweave/http_proxy_cli.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/src/execweave/inference_gateway.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/src/execweave/inference_gateway_cli.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/src/execweave/inference_gateway_full_fidelity.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/src/execweave/inference_identity.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/src/execweave/inference_identity_cli.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/src/execweave/integrity.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/src/execweave/integrity_cli.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/src/execweave/litellm_callback.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/src/execweave/litellm_callback_cli.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/src/execweave/live.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/src/execweave/live_core.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/src/execweave/live_view_extra_style.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/src/execweave/live_view_markup.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/src/execweave/live_view_process_layout.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/src/execweave/live_view_readability.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/src/execweave/live_view_script_a.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/src/execweave/live_view_script_b.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/src/execweave/live_view_script_c.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/src/execweave/live_view_style.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/src/execweave/model_runtime.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/src/execweave/model_runtime_cli.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/src/execweave/model_runtime_full_fidelity.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/src/execweave/openai_compatible.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/src/execweave/openai_compatible_cli.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/src/execweave/openai_compatible_full_fidelity.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/src/execweave/opencode_adapter.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/src/execweave/opencode_event_contract.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/src/execweave/opencode_full_fidelity.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/src/execweave/opencode_hook_cli.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/src/execweave/opencode_plugin_cli.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/src/execweave/opencode_record.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/src/execweave/opencode_task_linkage.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/src/execweave/overhead_benchmark.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/src/execweave/provider_capability.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/src/execweave/provider_lifecycle.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/src/execweave/provider_record.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/src/execweave/rule_pack.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/src/execweave/rule_pack_cli.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/src/execweave/scalability_benchmark.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/src/execweave/schema.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/src/execweave/scope.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/src/execweave/semantic.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/src/execweave/sink.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/src/execweave/strace_backend.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/src/execweave/stream_assembly.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/src/execweave/theme.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/src/execweave/top.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/src/execweave/top_cli.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/src/execweave/validate.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/src/execweave/vendor/dagre.min.js +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/src/execweave/view_cli.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/src/execweave/viewer.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/src/execweave/viewer_agent_panel.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/src/execweave/viewer_agent_panel_antigravity.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/src/execweave/viewer_agent_panel_claude.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/src/execweave/viewer_agent_panel_codex.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/src/execweave/viewer_agent_panel_cursor.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/src/execweave/viewer_agent_panel_default.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/src/execweave/viewer_agent_panel_ollama.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/src/execweave/viewer_agent_panel_opencode.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/src/execweave/viewer_agent_panel_registry.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/src/execweave/viewer_content_inspector.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/src/execweave/viewer_dashboard_focus.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/src/execweave/viewer_dashboard_hardening.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/src/execweave/viewer_external_endpoints.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/src/execweave/viewer_limits.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/src/execweave/viewer_live_layout.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/src/execweave/viewer_projection.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/src/execweave/viewer_projection_base.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/src/execweave/viewer_semantic_projection.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/src/execweave/workflow.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/dashboard_readability_fixture.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/fixtures/codex_multi_agent/PROVENANCE.md +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/fixtures/codex_multi_agent/hook-payloads.json +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/fixtures/codex_multi_agent/rollout-main.jsonl +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/fixtures/hooks/README.md +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/fixtures/hooks/claude.json +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/fixtures/hooks/codex.json +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/fixtures/hooks/cursor.json +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/fixtures/hooks/manifest.json +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/fixtures/hooks/opencode.json +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/multi_agent_run_fixture.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_acceptance_browser_diagnostics_e2e.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_acceptance_conpty_selection.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_acceptance_interrupt_guard.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_acceptance_owned_processes.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_acceptance_required_capabilities.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_acceptance_terminal_output.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_acceptance_visible_pipe.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_agent_bootstrap.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_agent_message_viewer.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_agent_node_labels.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_agent_said_panel.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_agent_topology_evidence.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_agent_trace_lifecycle.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_agent_trace_viewer_visibility.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_agy_windows_wire_acceptance.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_analysis.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_anthropic.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_antigravity_agent_collaboration.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_antigravity_child_panel_policy.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_antigravity_child_transcript_tools.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_antigravity_cursor_launch.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_antigravity_field_run_regressions.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_antigravity_history_replay.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_antigravity_identity_topology.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_antigravity_invocation_archive.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_antigravity_lifecycle.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_antigravity_linkage_projection.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_antigravity_multi_conversation_isolation.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_antigravity_official_contract.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_antigravity_role_path_fallback.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_antigravity_root_child_history_v2.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_antigravity_subagent_transcript_linkage.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_antigravity_trace_capability_cli.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_auto_specialized.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_auto_specialized_ollama_two_phase.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_backends.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_claude_adapter.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_claude_child_transcript_tools.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_claude_delegation.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_claude_full_fidelity.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_claude_hook_contract.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_claude_hook_metadata.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_claude_hook_viewer.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_claude_model_observer.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_claude_record.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_cleanup_finalizer_identity.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_codex_adapter.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_codex_archive_full_fidelity.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_codex_child_panel_policy.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_codex_conversation_isolation.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_codex_full_fidelity.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_codex_hook_global_fail_open.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_codex_hook_lifecycle.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_codex_hook_partial_capture.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_codex_interrupt_contract.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_codex_message_diagnostics.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_codex_message_transport_diagnostics.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_codex_nickname_path_fallback.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_codex_plain_routed_agent_message.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_codex_real_multi_agent_conversation.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_codex_record.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_codex_reducer_command.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_codex_rollout_structures.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_codex_rollout_trace.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_codex_routing_native_identity.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_collector.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_command.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_condense.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_conversation_access.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_conversation_agent_focus.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_conversation_agent_isolation.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_conversation_identity_merge.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_conversation_message_observation_dedupe.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_conversation_provider_parity.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_conversation_root_authority.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_correlation.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_correlation_canonical_path.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_correlation_checker.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_correlation_process_exe.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_cross_provider_agent_trace.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_cursor_adapter.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_cursor_delegation.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_cursor_full_fidelity.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_cursor_hook_contract.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_cursor_hook_fail_open.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_cursor_ollama_session_lifecycle.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_cursor_record.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_cursor_task_linkage.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_d003_fast_reparent.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_dagre_semantic_pipeline.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_dashboard_acceptance_relative_output_e2e.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_dashboard_acceptance_reporting.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_dashboard_camera_scheduler_e2e.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_dashboard_favicon.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_dashboard_file_activity_filter.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_dashboard_information_architecture.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_dashboard_initial_fit_readability_e2e.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_dashboard_node_drag_camera_e2e.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_dashboard_readability_e2e.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_dashboard_round_fold_state_e2e.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_dashboard_simplification.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_dashboard_ux_and_hook_projection.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_delegation_viewer.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_evidence_grade.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_execution_viewer.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_external_endpoints_all_providers.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_fidelity.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_filesystem_resilience.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_focus.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_fold_budget_setting.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_full_fidelity.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_g5_hardening_contract.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_g6_owned_parity_contract.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_graph.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_graph_arrange_constraints_e2e.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_graph_clear_focus_e2e.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_graph_edge_routing_e2e.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_graph_lane_separation_e2e.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_graph_node_sizing_e2e.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_graph_ops.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_hook_fixture_corpus.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_http_proxy.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_http_proxy_request_phase.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_http_proxy_response_memory.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_http_proxy_streaming.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_i18n_readme_policy.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_inference_endpoint_identity.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_inference_gateway.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_inference_gateway_full_fidelity.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_inference_identity.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_integrity.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_litellm_callback.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_live.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_live_auth.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_live_dashboard.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_live_dashboard_js.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_live_delta.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_live_theme.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_lmstudio_auto_specialized.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_local_runtime_live_capture.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_model_runtime.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_model_runtime_full_fidelity.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_ollama_interactive_acceptance.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_ollama_interactive_terminal_semantics.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_ollama_panel_policy.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_ollama_serve_runtime_integration.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_ollama_visible_acceptance.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_openai_compatible.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_opencode_adapter.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_opencode_event_contract.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_opencode_event_lifecycle.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_opencode_full_fidelity.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_opencode_identity_unification.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_opencode_plugin.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_opencode_record.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_opencode_task_session_linkage.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_overhead_benchmark.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_per_agent_conversation_default.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_pr25_premerge_hardening_e2e.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_pro6_audit_regressions.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_process_tree_layout.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_provider_capability.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_provider_conversation_evidence.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_provider_conversation_history_integrity.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_provider_dashboard_contract.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_provider_lifecycle.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_provider_neutral_viewer_semantics.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_pypi_0812_regressions.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_pypi_0813_cleanup.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_python_native_acceptance.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_relay_prompt_live_e2e.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_release_stage_integrity_version_guard.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_rule_pack.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_schema.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_scope.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_semantic.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_shared_injected_context_scope.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_single_agent_barycenter.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_strace_backend.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_stream_assembly.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_threat_model.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_tool_traffic_e2e.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_top_detached.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_v063_features.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_v064_live_auto_integrations.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_v064_live_evidence.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_v079_review_e2e.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_v079_review_regressions.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_v083_release_gate_p2.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_validate.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_version.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_viewer.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_viewer_agent_isolation_e2e.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_viewer_child_authority.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_viewer_content_inspector.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_viewer_limits.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_viewer_projection.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_visual_ux_readability.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_windows_codex_agy_display_repair.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tests/test_workflow.py +0 -0
- {execweave-0.8.15 → execweave-0.8.16}/tools/verify_metrics_tool.py +0 -0
{execweave-0.8.15 → execweave-0.8.16}/.github/workflows/provider-capability-stage-integrity.yml
RENAMED
|
@@ -87,6 +87,24 @@ jobs:
|
|
|
87
87
|
&& -n "$threat_model_changed" ]]; then
|
|
88
88
|
args+=(--allow-test-change "tests/test_threat_model.py=0.8.15 RC follow-up makes the existing outliving-child assertion hermetic against ambient host PID collisions; the historical test node ID and product expectation are unchanged")
|
|
89
89
|
fi
|
|
90
|
+
if [[ "$HEAD_REF" == "fix/gif-dashboard-parity" ]]; then
|
|
91
|
+
while IFS= read -r path; do
|
|
92
|
+
case "$path" in
|
|
93
|
+
tests/test_dashboard_gif_export_e2e.py)
|
|
94
|
+
args+=(--allow-test-change "$path=GIF export now records the real displayed SVG timeline instead of reconstructing animation from the final graph; the historical repeatable-download test node ID is retained and new screenshot-to-decoded-frame parity regressions are added")
|
|
95
|
+
;;
|
|
96
|
+
tests/test_live_logs_export.py)
|
|
97
|
+
args+=(--allow-test-change "$path=the GIF contract now requires captureGifFrame and forbids the retired sortedGifSteps reconstruction path; historical test node IDs remain unchanged")
|
|
98
|
+
;;
|
|
99
|
+
tests/test_pr25_premerge_hardening_contract.py)
|
|
100
|
+
args+=(--allow-test-change "$path=GIF export now freezes measured SVG geometry directly, so the historical hardening assertion must reject the old separate drawGifFrame renderer while retaining the same test node ID")
|
|
101
|
+
;;
|
|
102
|
+
tests/test_v069_dashboard_release.py)
|
|
103
|
+
args+=(--allow-test-change "$path=the GIF encoder changed from the historical fixed-code replay implementation to the recorded-SVG encoder and is now validated through an independent GIF decoder; release/version assertions and historical test node IDs remain intact")
|
|
104
|
+
;;
|
|
105
|
+
esac
|
|
106
|
+
done < <(git diff --name-only "$BASELINE_REF...HEAD" -- tests)
|
|
107
|
+
fi
|
|
90
108
|
if [[ "$HEAD_REF" == "fix/provider-isolation" ]]; then
|
|
91
109
|
while IFS= read -r path; do
|
|
92
110
|
case "$path" in
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: execweave
|
|
3
|
-
Version: 0.8.
|
|
3
|
+
Version: 0.8.16
|
|
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
|
|
@@ -42,10 +42,12 @@ Requires-Python: >=3.10
|
|
|
42
42
|
Requires-Dist: psutil>=5.9
|
|
43
43
|
Requires-Dist: watchdog>=4.0
|
|
44
44
|
Provides-Extra: dev
|
|
45
|
+
Requires-Dist: pillow>=10.0; extra == 'dev'
|
|
45
46
|
Requires-Dist: pytest>=8.0; extra == 'dev'
|
|
46
47
|
Requires-Dist: pywinpty<4,>=3.0.5; (platform_system == 'Windows') and extra == 'dev'
|
|
47
48
|
Requires-Dist: ruff<0.17,>=0.16; extra == 'dev'
|
|
48
49
|
Provides-Extra: e2e
|
|
50
|
+
Requires-Dist: pillow>=10.0; extra == 'e2e'
|
|
49
51
|
Requires-Dist: playwright>=1.44; extra == 'e2e'
|
|
50
52
|
Requires-Dist: pywinpty<4,>=3.0.5; (platform_system == 'Windows') and extra == 'e2e'
|
|
51
53
|
Provides-Extra: release
|
|
@@ -188,6 +190,15 @@ The dashboard is designed to keep large, multi-agent runs inspectable without ch
|
|
|
188
190
|
- **Large-run folding:** high-cardinality node types can collapse older members while keeping them inspectable.
|
|
189
191
|
- **Selection-focused layout:** selecting an agent or runtime object de-emphasizes unrelated graph traffic.
|
|
190
192
|
|
|
193
|
+
**Download GIF** saves the graph viewport as it appeared while this Dashboard page
|
|
194
|
+
was open and visible, including labels, folding, camera changes, and elapsed time
|
|
195
|
+
(sampled at up to 10 frames per second). It excludes the inspector and logs. A
|
|
196
|
+
reopened finished run has no recorded screen history and exports a still image.
|
|
197
|
+
Keep the viewport size fixed for a consistent frame; resizing adds padding rather
|
|
198
|
+
than rescaling older frames. Recording stops with an explicit message if the page
|
|
199
|
+
is hidden during a live run, rendering is paused, or the 64 MB recording limit is
|
|
200
|
+
reached; it never substitutes an animation reconstructed from the final graph.
|
|
201
|
+
|
|
191
202
|
You can tune large-run rendering with:
|
|
192
203
|
|
|
193
204
|
```text
|
|
@@ -133,6 +133,15 @@ The dashboard is designed to keep large, multi-agent runs inspectable without ch
|
|
|
133
133
|
- **Large-run folding:** high-cardinality node types can collapse older members while keeping them inspectable.
|
|
134
134
|
- **Selection-focused layout:** selecting an agent or runtime object de-emphasizes unrelated graph traffic.
|
|
135
135
|
|
|
136
|
+
**Download GIF** saves the graph viewport as it appeared while this Dashboard page
|
|
137
|
+
was open and visible, including labels, folding, camera changes, and elapsed time
|
|
138
|
+
(sampled at up to 10 frames per second). It excludes the inspector and logs. A
|
|
139
|
+
reopened finished run has no recorded screen history and exports a still image.
|
|
140
|
+
Keep the viewport size fixed for a consistent frame; resizing adds padding rather
|
|
141
|
+
than rescaling older frames. Recording stops with an explicit message if the page
|
|
142
|
+
is hidden during a live run, rendering is paused, or the 64 MB recording limit is
|
|
143
|
+
reached; it never substitutes an animation reconstructed from the final graph.
|
|
144
|
+
|
|
136
145
|
You can tune large-run rendering with:
|
|
137
146
|
|
|
138
147
|
```text
|
|
@@ -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.16 release metadata
|
|
8
|
+
version = "0.8.16"
|
|
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"
|
|
@@ -44,6 +44,7 @@ dependencies = [
|
|
|
44
44
|
[project.optional-dependencies]
|
|
45
45
|
dev = [
|
|
46
46
|
"pytest>=8.0",
|
|
47
|
+
"pillow>=10.0",
|
|
47
48
|
"ruff>=0.16,<0.17",
|
|
48
49
|
"pywinpty>=3.0.5,<4; platform_system == 'Windows'",
|
|
49
50
|
]
|
|
@@ -55,6 +56,7 @@ release = [
|
|
|
55
56
|
# development install stays small; CI installs it and requires the checks to run.
|
|
56
57
|
e2e = [
|
|
57
58
|
"playwright>=1.44",
|
|
59
|
+
"pillow>=10.0",
|
|
58
60
|
"pywinpty>=3.0.5,<4; platform_system == 'Windows'",
|
|
59
61
|
]
|
|
60
62
|
|
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
-
import re
|
|
4
|
-
|
|
5
3
|
from .live_view_extra_style import LIVE_EXTRA_STYLE
|
|
6
4
|
from .live_view_markup import LIVE_MARKUP
|
|
7
5
|
from .live_view_process_layout import LIVE_PROCESS_LAYOUT_SCRIPT
|
|
@@ -15,21 +13,6 @@ from .viewer_agent_panel import inject_agent_panel
|
|
|
15
13
|
from .viewer_dashboard_hardening_v2 import harden_dashboard_html
|
|
16
14
|
|
|
17
15
|
|
|
18
|
-
_SAFE_GIF_LZW = (
|
|
19
|
-
"function lzw(indices,minCodeSize=8){"
|
|
20
|
-
"const clear=1<<minCodeSize,end=clear+1,out=[];"
|
|
21
|
-
"let buffer=0,bits=0;const codeSize=minCodeSize+1;"
|
|
22
|
-
"const chunk=Math.max(1,(1<<codeSize)-clear-8);"
|
|
23
|
-
"const emit=code=>{buffer|=code<<bits;bits+=codeSize;"
|
|
24
|
-
"while(bits>=8){out.push(buffer&255);buffer>>>=8;bits-=8}};"
|
|
25
|
-
"if(!indices.length)emit(clear);"
|
|
26
|
-
"for(let start=0;start<indices.length;start+=chunk){"
|
|
27
|
-
"emit(clear);const stop=Math.min(indices.length,start+chunk);"
|
|
28
|
-
"for(let i=start;i<stop;i++)emit(indices[i])}"
|
|
29
|
-
"emit(end);if(bits>0)out.push(buffer&255);return out}"
|
|
30
|
-
)
|
|
31
|
-
|
|
32
|
-
|
|
33
16
|
def _restore_live_safety_contracts(html: str) -> str:
|
|
34
17
|
"""Preserve live-view safety contracts while retiring legacy final-page swapping."""
|
|
35
18
|
html = html.replace(
|
|
@@ -62,16 +45,6 @@ def _restore_live_safety_contracts(html: str) -> str:
|
|
|
62
45
|
1,
|
|
63
46
|
)
|
|
64
47
|
|
|
65
|
-
html, lzw_count = re.subn(
|
|
66
|
-
r"function lzw\(indices,minCodeSize=8\)\{.*?\}\nfunction gifBlocks",
|
|
67
|
-
_SAFE_GIF_LZW + "\nfunction gifBlocks",
|
|
68
|
-
html,
|
|
69
|
-
count=1,
|
|
70
|
-
flags=re.DOTALL,
|
|
71
|
-
)
|
|
72
|
-
if lzw_count != 1:
|
|
73
|
-
raise RuntimeError("live GIF encoder patch target not found")
|
|
74
|
-
|
|
75
48
|
open_final_button = '<button id="open-final" type="button">Open final graph</button>'
|
|
76
49
|
if open_final_button not in html:
|
|
77
50
|
raise RuntimeError("legacy final action patch target not found")
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from .viewer_gif import GIF_SCRIPT
|
|
4
|
+
|
|
5
|
+
LIVE_SCRIPT_D = r"""
|
|
6
|
+
(()=>{
|
|
7
|
+
const core=window.__execweaveCore;
|
|
8
|
+
if(!core)return;
|
|
9
|
+
const structuredList=document.getElementById('activity-list'),rawLog=document.getElementById('raw-log'),rawRows=document.getElementById('raw-rows'),activityCount=document.getElementById('activity-count'),filterGroup=document.querySelector('.filter-group'),finishedActions=document.getElementById('finished-actions'),replayButton=document.getElementById('replay-run'),gifButton=document.getElementById('download-gif'),openFinalButton=document.getElementById('open-final'),details=document.getElementById('details'),detailsEmpty=document.getElementById('details-empty');
|
|
10
|
+
const MAX_RAW=640;
|
|
11
|
+
let rawEntries=[],logMode='structured',finishedShown=false,finalHtmlCache=null,replaying=false;
|
|
12
|
+
function rawId(entry){return`raw-${entry.stream||'events'}-${entry.line??'x'}-${entry.event?.event_id||entry.event?.sequence||''}`}
|
|
13
|
+
function rawTime(event){const value=event?.timestamp;if(!value)return'—';const d=new Date(value);if(Number.isNaN(d.getTime()))return String(value);return d.toLocaleTimeString([],{hour:'2-digit',minute:'2-digit',second:'2-digit',fractionalSecondDigits:3})}
|
|
14
|
+
function rawEventType(event){return String(event?.event_type||event?.type||'event')}
|
|
15
|
+
function rawRelation(event){return String(event?.relation||'—')}
|
|
16
|
+
function rawSummary(event){try{return JSON.stringify(event)}catch(_){return String(event)}}
|
|
17
|
+
function setRawEntries(items){rawEntries=(items||[]).slice(-MAX_RAW);renderRaw(false)}
|
|
18
|
+
function addRawEntries(items){if(!items?.length)return;rawEntries.push(...items);if(rawEntries.length>MAX_RAW)rawEntries=rawEntries.slice(-MAX_RAW);renderRaw(logMode==='raw')}
|
|
19
|
+
function findGraphEdge(event){const source=event?.source?.id,target=event?.target?.id,relation=event?.relation;if(!source||!target||!relation)return null;const visible=[...document.querySelectorAll('.edge')].find(el=>el.dataset.source===source&&el.dataset.target===target&&el.dataset.relation===String(relation).toLowerCase());return visible?.dataset.edgeId||null}
|
|
20
|
+
function showRaw(entry){const event=entry.event||{};detailsEmpty.hidden=true;details.innerHTML='';const title=document.createElement('div');title.className='current-title';title.textContent=rawEventType(event);const sub=document.createElement('div');sub.className='current-sub';sub.textContent=`${entry.stream||'events.jsonl'} line ${entry.line??'—'} · ${rawRelation(event)}`;const pre=document.createElement('pre');pre.textContent=JSON.stringify(event,null,2);const raw=document.createElement('details');raw.className='raw-toggle';raw.open=true;const summary=document.createElement('summary');summary.textContent='Raw event JSON';raw.append(summary,pre);details.append(title,sub,raw);const nodeMap=new Map();for(const node of(core.getGraph()?.nodes||[])){if(node?.id)nodeMap.set(node.id,node);for(const key of['viewer_member_ids','viewer_agent_member_ids'])for(const member of(node?.attributes?.[key]||[]))nodeMap.set(String(member),node)}const targets=document.createElement('div');targets.className='raw-target-actions';for(const entity of [event.source,event.target]){if(!entity?.id||!nodeMap.has(entity.id))continue;const node=nodeMap.get(entity.id);const button=document.createElement('button');button.type='button';button.textContent=`Inspect ${node.type||'node'}${node.name?` · ${node.name}`:''}`;button.addEventListener('click',()=>core.selectNode(node.id,{syncLog:false}));targets.appendChild(button)}if(targets.childElementCount)details.appendChild(targets)}
|
|
21
|
+
function selectRaw(entry,row){document.querySelectorAll('.raw-row.selected').forEach(el=>el.classList.remove('selected'));row.classList.add('selected');const edge=findGraphEdge(entry.event);if(edge)core.selectEdge(edge,{syncLog:false});showRaw(entry)}
|
|
22
|
+
function renderRaw(scrollLatest=false){rawRows.replaceChildren();activityCount.textContent=logMode==='raw'?`${rawEntries.length} raw event${rawEntries.length===1?'':'s'}`:`${core.getActivities().length} transition${core.getActivities().length===1?'':'s'}`;if(!rawEntries.length){const empty=document.createElement('div');empty.className='empty-activity';empty.textContent='Waiting for runtime or semantic activity…';rawRows.appendChild(empty);return}for(const entry of rawEntries){const row=document.createElement('div');row.className='raw-row';row.dataset.rawId=rawId(entry);const line=document.createElement('span');line.className='raw-line';line.textContent=String(entry.line??'—');const time=document.createElement('span');time.className='raw-time';time.textContent=rawTime(entry.event);const event=document.createElement('span');event.className='raw-event';event.textContent=rawEventType(entry.event);const relation=document.createElement('span');relation.className='raw-relation';relation.textContent=rawRelation(entry.event);const json=document.createElement('span');json.className='raw-json';json.textContent=rawSummary(entry.event);json.title=json.textContent;row.append(line,time,event,relation,json);row.onclick=()=>selectRaw(entry,row);rawRows.appendChild(row)}if(scrollLatest)rawRows.lastElementChild?.scrollIntoView({block:'nearest'})}
|
|
23
|
+
function setLogMode(mode){logMode=mode==='raw'?'raw':'structured';document.querySelectorAll('[data-log-mode]').forEach(button=>button.classList.toggle('active',button.dataset.logMode===logMode));structuredList.hidden=logMode==='raw';rawLog.hidden=logMode!=='raw';filterGroup.hidden=logMode==='raw';if(logMode==='raw')renderRaw(false);else activityCount.textContent=`${core.getActivities().length} transition${core.getActivities().length===1?'':'s'}`}
|
|
24
|
+
document.querySelectorAll('[data-log-mode]').forEach(button=>button.onclick=()=>setLogMode(button.dataset.logMode));
|
|
25
|
+
function onPayload(data){observeGifPayload(data);if(data.kind==='snapshot')setRawEntries(data.raw_events||[]);else if(data.kind==='delta'){const added=[];for(const update of data.updates||[])added.push(...(update.raw_events_added||[]));addRawEntries(added)}}
|
|
26
|
+
function timelineItems(){const activities=core.getActivities().filter(item=>item.edgeId||item.nodeId);return activities.length?activities:[]}
|
|
27
|
+
function revealNode(id){if(!id)return;document.querySelector(`.node[data-id="${CSS.escape(id)}"]`)?.classList.remove('replay-hidden')}
|
|
28
|
+
function revealEdge(id){if(!id)return;const edge=document.querySelector(`.edge[data-edge-id="${CSS.escape(id)}"]`);edge?.classList.remove('replay-hidden');document.querySelector(`.label[data-edge-id="${CSS.escape(id)}"]`)?.classList.remove('replay-hidden');if(edge){revealNode(edge.dataset.source);revealNode(edge.dataset.target)}}
|
|
29
|
+
function restoreReplayDom(){document.querySelectorAll('.replay-hidden,.replay-active').forEach(el=>el.classList.remove('replay-hidden','replay-active'))}
|
|
30
|
+
const sleep=ms=>new Promise(resolve=>setTimeout(resolve,ms));
|
|
31
|
+
async function replayRun(){if(replaying)return;const timeline=timelineItems();if(!timeline.length)return;replaying=true;replayButton.disabled=true;restoreReplayDom();document.querySelectorAll('.node,.edge,.label').forEach(el=>el.classList.add('replay-hidden'));core.setCameraMode('fit');const delay=Math.max(55,Math.min(180,7000/Math.max(1,timeline.length)));for(const item of timeline){document.querySelectorAll('.replay-active').forEach(el=>el.classList.remove('replay-active'));if(item.edgeId){revealEdge(item.edgeId);document.querySelector(`.edge[data-edge-id="${CSS.escape(item.edgeId)}"]`)?.classList.add('replay-active')}if(item.nodeId){revealNode(item.nodeId);document.querySelector(`.node[data-id="${CSS.escape(item.nodeId)}"]`)?.classList.add('replay-active')}core.markLatest(item.nodeId||null,item.edgeId||null);await sleep(delay)}await sleep(380);restoreReplayDom();const last=timeline[timeline.length-1];core.markLatest(last.nodeId||null,last.edgeId||null);replaying=false;replayButton.disabled=false}
|
|
32
|
+
""" + GIF_SCRIPT + r"""
|
|
33
|
+
async function prepareFinalView(){try{const response=await fetch('/final',{cache:'no-store'});if(!response.ok)throw new Error(String(response.status));finalHtmlCache=await response.text()}catch(_){finalHtmlCache=null}}
|
|
34
|
+
function openFinal(){if(!finalHtmlCache)return;document.open();document.write(finalHtmlCache);document.close()}
|
|
35
|
+
function onFinished(){if(finishedShown)return;finishedShown=true;finishedActions.hidden=false;prepareFinalView()}
|
|
36
|
+
replayButton.onclick=replayRun;gifButton.onclick=downloadGif;openFinalButton.onclick=openFinal;
|
|
37
|
+
window.__execweaveDashboard={onPayload,onFinished};
|
|
38
|
+
if(window.__execweaveStaticMode)onFinished();
|
|
39
|
+
})();
|
|
40
|
+
"""
|
|
@@ -397,9 +397,4 @@ def inject_live_dashboard_clean(html: str) -> str:
|
|
|
397
397
|
html = html[:render_index] + html[render_index:].replace(render_marker, render_replacement, 1)
|
|
398
398
|
html = html.replace(_LIVE_CORE_EXPORT, _LIVE_CORE_EXPORT_CLEAN, 1)
|
|
399
399
|
html = html.replace(_LIVE_NOOP_STATS, _LIVE_NOOP_STATS_CLEAN, 1)
|
|
400
|
-
html = html.replace(
|
|
401
|
-
"const graph=core.getGraph(),positions=core.getPositions(),steps=sortedGifSteps(graph);",
|
|
402
|
-
"const graph=core.getDisplayGraph?.()||core.getGraph(),positions=core.getPositions(),steps=sortedGifSteps(graph);",
|
|
403
|
-
1,
|
|
404
|
-
)
|
|
405
400
|
return html
|
|
@@ -58,26 +58,5 @@ def harden_dashboard_html(html: str) -> str:
|
|
|
58
58
|
label="delta geometry rerender",
|
|
59
59
|
)
|
|
60
60
|
|
|
61
|
-
#
|
|
62
|
-
# node rectangle even after the dashboard became adaptive. Export is a projection of
|
|
63
|
-
# the same graph, so its bounds, edge anchors and drawn rectangles must use the same
|
|
64
|
-
# per-node geometry as Live/Finished/viewer rather than silently reverting to v0.8.2.
|
|
65
|
-
html = _replace_once(
|
|
66
|
-
html,
|
|
67
|
-
"minX=Math.min(minX,p.x);maxX=Math.max(maxX,p.x+160);minY=Math.min(minY,p.y);maxY=Math.max(maxY,p.y+50)",
|
|
68
|
-
"minX=Math.min(minX,p.x);maxX=Math.max(maxX,p.x+execweaveCameraWidth(node.id));minY=Math.min(minY,p.y);maxY=Math.max(maxY,p.y+execweaveCameraHeight(node.id))",
|
|
69
|
-
label="gif adaptive bounds",
|
|
70
|
-
)
|
|
71
|
-
html = _replace_once(
|
|
72
|
-
html,
|
|
73
|
-
"const point=(id,right=false)=>{const p=positions.get(id)||{x:0,y:0};return{x:ox+(p.x+(right?160:0))*scale,y:oy+(p.y+25)*scale}};",
|
|
74
|
-
"const point=(id,right=false)=>{const p=positions.get(id)||{x:0,y:0},w=execweaveCameraWidth(id),h=execweaveCameraHeight(id);return{x:ox+(p.x+(right?w:0))*scale,y:oy+(p.y+h/2)*scale}};",
|
|
75
|
-
label="gif adaptive anchors",
|
|
76
|
-
)
|
|
77
|
-
html = _replace_once(
|
|
78
|
-
html,
|
|
79
|
-
"const x=ox+p.x*scale,y=oy+p.y*scale,w=160*scale,h=50*scale;",
|
|
80
|
-
"const x=ox+p.x*scale,y=oy+p.y*scale,w=execweaveCameraWidth(node.id)*scale,h=execweaveCameraHeight(node.id)*scale;",
|
|
81
|
-
label="gif adaptive rectangles",
|
|
82
|
-
)
|
|
61
|
+
# GIF captures measured SVG geometry directly; it has no separate layout.
|
|
83
62
|
return html
|
|
@@ -0,0 +1,232 @@
|
|
|
1
|
+
"""Record the displayed SVG, rather than inventing history from the final graph."""
|
|
2
|
+
|
|
3
|
+
GIF_SCRIPT = r"""
|
|
4
|
+
const gifSvg=document.getElementById('svg');
|
|
5
|
+
const gifNotice=document.createElement('span');
|
|
6
|
+
gifNotice.id='gif-notice';gifNotice.setAttribute('role','status');
|
|
7
|
+
gifNotice.style.cssText='font-size:11px;color:var(--muted);max-width:230px';
|
|
8
|
+
finishedActions.appendChild(gifNotice);
|
|
9
|
+
const gifScope='Graph viewport only, at screen resolution. Records this page while it is visible; reopening a finished run exports a still image.';
|
|
10
|
+
gifButton.title=gifScope;
|
|
11
|
+
gifButton.setAttribute('aria-description',gifScope);
|
|
12
|
+
// Keep actual display states, including folding, labels, edge routing and camera.
|
|
13
|
+
// Never discard old states silently to meet a frame or memory cap.
|
|
14
|
+
const GIF_INTERVAL=100,GIF_MAX_BYTES=64*1024*1024;
|
|
15
|
+
const gifHistory=[];
|
|
16
|
+
let gifSnapshotOnly=!!window.__execweaveStaticMode;
|
|
17
|
+
let gifBytes=0,gifSession=null,gifFailure='',gifExporting=false,gifLastSample=0,gifLastSvg='',gifEpoch=0;
|
|
18
|
+
let gifDirty=true;
|
|
19
|
+
const gifObserver=new MutationObserver(()=>{gifDirty=true;});
|
|
20
|
+
gifObserver.observe(gifSvg,{subtree:true,childList:true,attributes:true,characterData:true});
|
|
21
|
+
gifObserver.observe(document.documentElement,{attributes:true,attributeFilter:['data-theme']});
|
|
22
|
+
const gifResizeObserver=new ResizeObserver(()=>{gifDirty=true;});
|
|
23
|
+
gifResizeObserver.observe(gifSvg);
|
|
24
|
+
const gifProperties=[
|
|
25
|
+
'color','fill','fill-opacity','fill-rule','stroke','stroke-width','stroke-opacity',
|
|
26
|
+
'stroke-dasharray','stroke-dashoffset','stroke-linecap','stroke-linejoin',
|
|
27
|
+
'stroke-miterlimit','paint-order','opacity','display','visibility','filter',
|
|
28
|
+
'font-family','font-size','font-weight','font-style','font-stretch','letter-spacing',
|
|
29
|
+
'word-spacing','text-anchor','dominant-baseline','text-transform','text-rendering',
|
|
30
|
+
'white-space','transform','transform-origin','transform-box','vector-effect',
|
|
31
|
+
'marker-start','marker-mid','marker-end','clip-path','rx','ry'
|
|
32
|
+
];
|
|
33
|
+
function gifError(message){
|
|
34
|
+
gifFailure=message;gifNotice.textContent=message;gifButton.disabled=true;
|
|
35
|
+
}
|
|
36
|
+
function observeGifPayload(data){
|
|
37
|
+
if(!gifHistory.length&&data.live_finished)gifSnapshotOnly=true;
|
|
38
|
+
if(!data.live_finished&&core.getGraph()?.session_id!==gifSession)gifSnapshotOnly=false;
|
|
39
|
+
}
|
|
40
|
+
function gifSnapshot(){
|
|
41
|
+
const box=gifSvg.getBoundingClientRect();
|
|
42
|
+
const width=Math.round(box.width),height=Math.round(box.height);
|
|
43
|
+
if(!width||!height)return null;
|
|
44
|
+
const clone=gifSvg.cloneNode(true);
|
|
45
|
+
const originals=[gifSvg,...gifSvg.querySelectorAll('*')];
|
|
46
|
+
const copies=[clone,...clone.querySelectorAll('*')];
|
|
47
|
+
const styles=new Map();
|
|
48
|
+
for(let i=0;i<originals.length;i++){
|
|
49
|
+
const computed=getComputedStyle(originals[i]),copy=copies[i];
|
|
50
|
+
// Routing metadata contains NUL-delimited bundle keys, legal in HTML DOM
|
|
51
|
+
// attributes but not XML. It has no visual role once styles are frozen.
|
|
52
|
+
for(const attribute of [...copy.attributes]){
|
|
53
|
+
if(attribute.name.startsWith('data-')||attribute.name.startsWith('aria-'))copy.removeAttribute(attribute.name);
|
|
54
|
+
}
|
|
55
|
+
copy.removeAttribute('style');
|
|
56
|
+
for(const property of gifProperties){
|
|
57
|
+
const value=computed.getPropertyValue(property).replace(/url\(["']?[^)"']*#([^)'" ]+)["']?\)/g,'url(#$1)');
|
|
58
|
+
if(value)copy.style.setProperty(property,value);
|
|
59
|
+
}
|
|
60
|
+
// Freeze the sampled appearance; animations must not restart when decoded.
|
|
61
|
+
copy.style.setProperty('animation','none');copy.style.setProperty('transition','none');
|
|
62
|
+
const css=copy.style.cssText;
|
|
63
|
+
if(!styles.has(css))styles.set(css,`execweave-gif-style-${styles.size}`);
|
|
64
|
+
copy.removeAttribute('style');copy.classList.add(styles.get(css));
|
|
65
|
+
}
|
|
66
|
+
clone.setAttribute('xmlns','http://www.w3.org/2000/svg');
|
|
67
|
+
clone.setAttribute('width',width);clone.setAttribute('height',height);
|
|
68
|
+
clone.setAttribute('viewBox',`0 0 ${width} ${height}`);
|
|
69
|
+
const ns='http://www.w3.org/2000/svg';
|
|
70
|
+
const stylesheet=document.createElementNS(ns,'style');
|
|
71
|
+
stylesheet.textContent=[...styles].map(([css,name])=>`.${name}{${css}}`).join('\n');
|
|
72
|
+
clone.insertBefore(stylesheet,clone.firstChild);
|
|
73
|
+
const background=document.createElementNS(ns,'rect');
|
|
74
|
+
background.setAttribute('width',width);background.setAttribute('height',height);
|
|
75
|
+
background.setAttribute('fill',getComputedStyle(document.getElementById('graph-panel')).backgroundColor);
|
|
76
|
+
clone.insertBefore(background,clone.firstChild);
|
|
77
|
+
// The graph's dotted paper is CSS on #wrap, outside the SVG itself.
|
|
78
|
+
const defs=document.createElementNS(ns,'defs'),pattern=document.createElementNS(ns,'pattern');
|
|
79
|
+
pattern.id='execweave-gif-paper';pattern.setAttribute('width','22');pattern.setAttribute('height','22');pattern.setAttribute('patternUnits','userSpaceOnUse');
|
|
80
|
+
const dot=document.createElementNS(ns,'circle');dot.setAttribute('cx','1');dot.setAttribute('cy','1');dot.setAttribute('r','1');
|
|
81
|
+
dot.setAttribute('fill',`color-mix(in srgb,${getComputedStyle(gifSvg).getPropertyValue('--border')} 52%,transparent)`);
|
|
82
|
+
pattern.appendChild(dot);defs.appendChild(pattern);clone.insertBefore(defs,background);
|
|
83
|
+
const paper=background.cloneNode();paper.setAttribute('fill','url(#execweave-gif-paper)');background.after(paper);
|
|
84
|
+
return{svg:new XMLSerializer().serializeToString(clone),width,height,time:performance.now()};
|
|
85
|
+
}
|
|
86
|
+
function captureGifFrame(force=false){
|
|
87
|
+
if(gifExporting||replaying)return;
|
|
88
|
+
const graph=core.getGraph(),session=graph?.session_id;
|
|
89
|
+
if(!session)return;
|
|
90
|
+
if(session!==gifSession){gifHistory.length=0;gifBytes=0;gifSession=session;gifFailure='';gifLastSvg='';gifEpoch++;gifNotice.textContent='';gifButton.disabled=false;}
|
|
91
|
+
if(gifFailure||!gifSvg.querySelector('.node'))return;
|
|
92
|
+
if(document.hidden){gifError('GIF unavailable: this page was hidden during recording.');return;}
|
|
93
|
+
const protective=document.getElementById('protective');
|
|
94
|
+
if(protective&&!protective.hidden){gifError('GIF unavailable: graph rendering was paused.');return;}
|
|
95
|
+
const now=performance.now();
|
|
96
|
+
if(!force&&now-gifLastSample<GIF_INTERVAL)return;
|
|
97
|
+
if(!force&&!gifDirty&&!gifSvg.getAnimations({subtree:true}).some(a=>a.playState==='running'))return;
|
|
98
|
+
gifLastSample=now;
|
|
99
|
+
try{
|
|
100
|
+
const frame=gifSnapshot();if(!frame)return;
|
|
101
|
+
gifDirty=false;
|
|
102
|
+
if(gifHistory.length&&frame.svg===gifLastSvg)return;
|
|
103
|
+
gifLastSvg=frame.svg;
|
|
104
|
+
const raw=new Blob([frame.svg],{type:'image/svg+xml;charset=utf-8'}),bytes=raw.size;
|
|
105
|
+
if(gifBytes+bytes>GIF_MAX_BYTES){gifError('GIF unavailable: recording exceeded 64 MB.');return;}
|
|
106
|
+
delete frame.svg;
|
|
107
|
+
const epoch=gifEpoch;
|
|
108
|
+
// Compress immutable snapshots, never drop historical frames. Account for
|
|
109
|
+
// in-flight uncompressed bytes too, so a slow compressor cannot grow a queue.
|
|
110
|
+
frame.data=(async()=>{
|
|
111
|
+
if(typeof CompressionStream==='undefined')return raw;
|
|
112
|
+
try{
|
|
113
|
+
const compressed=await new Response(raw.stream().pipeThrough(new CompressionStream('gzip'))).blob();
|
|
114
|
+
frame.compressed=true;if(epoch===gifEpoch)gifBytes+=compressed.size-bytes;
|
|
115
|
+
return compressed;
|
|
116
|
+
}catch(_){return raw;}
|
|
117
|
+
})();
|
|
118
|
+
gifHistory.push(frame);gifBytes+=bytes;
|
|
119
|
+
}catch(error){gifError(`GIF unavailable: ${error.message}`);}
|
|
120
|
+
}
|
|
121
|
+
// Sample painted frames, not network events: camera motion and user layout changes
|
|
122
|
+
// also matter. Stop sampling when the page closes; background gaps are explicit.
|
|
123
|
+
let gifAnimationFrame=0;
|
|
124
|
+
function sampleGif(){if(!gifSnapshotOnly)captureGifFrame();gifAnimationFrame=requestAnimationFrame(sampleGif);}
|
|
125
|
+
gifAnimationFrame=requestAnimationFrame(sampleGif);
|
|
126
|
+
window.addEventListener('pagehide',()=>{cancelAnimationFrame(gifAnimationFrame);gifObserver.disconnect();gifResizeObserver.disconnect();});
|
|
127
|
+
document.addEventListener('visibilitychange',()=>{
|
|
128
|
+
if(document.hidden&&gifHistory.length&&!finishedShown)gifError('GIF unavailable: this page was hidden during recording.');
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
function pushWord(out,value){out.push(value&255,(value>>8)&255);}
|
|
132
|
+
function pushText(out,text){for(let i=0;i<text.length;i++)out.push(text.charCodeAt(i)&255);}
|
|
133
|
+
function gifBlocks(data){
|
|
134
|
+
const out=new Uint8Array(data.length+Math.ceil(data.length/255)+1);
|
|
135
|
+
let source=0,target=0;
|
|
136
|
+
while(source<data.length){const size=Math.min(255,data.length-source);out[target++]=size;out.set(data.subarray(source,source+size),target);source+=size;target+=size;}
|
|
137
|
+
return out;
|
|
138
|
+
}
|
|
139
|
+
function lzw(indices){
|
|
140
|
+
const clear=256,end=257,out=[],dictionary=new Map();
|
|
141
|
+
let next=258,size=9,buffer=0,bits=0;
|
|
142
|
+
const emit=code=>{buffer|=code<<bits;bits+=size;while(bits>=8){out.push(buffer&255);buffer>>>=8;bits-=8;}};
|
|
143
|
+
emit(clear);
|
|
144
|
+
if(indices.length){
|
|
145
|
+
let prefix=indices[0];
|
|
146
|
+
for(let i=1;i<indices.length;i++){
|
|
147
|
+
const symbol=indices[i],key=prefix*256+symbol,hit=dictionary.get(key);
|
|
148
|
+
if(hit!==undefined){prefix=hit;continue;}
|
|
149
|
+
emit(prefix);
|
|
150
|
+
if(next<4096){
|
|
151
|
+
dictionary.set(key,next++);
|
|
152
|
+
// The decoder adds each entry one emitted code later than the encoder.
|
|
153
|
+
if(next>(1<<size)&&size<12)size++;
|
|
154
|
+
}else{emit(clear);dictionary.clear();next=258;size=9;}
|
|
155
|
+
prefix=symbol;
|
|
156
|
+
}
|
|
157
|
+
emit(prefix);
|
|
158
|
+
if(next===(1<<size)&&size<12)size++;
|
|
159
|
+
}
|
|
160
|
+
emit(end);if(bits)out.push(buffer&255);return Uint8Array.from(out);
|
|
161
|
+
}
|
|
162
|
+
function gifPixels(imageData){
|
|
163
|
+
// A local palette preserves dark backgrounds and small colored/text details;
|
|
164
|
+
// the old six-level cube quantized most of the dashboard to black.
|
|
165
|
+
const data=imageData.data,counts=new Uint32Array(32768),rs=new Float64Array(32768),gs=new Float64Array(32768),bs=new Float64Array(32768);
|
|
166
|
+
for(let i=0;i<data.length;i+=4){const key=(data[i]>>3)*1024+(data[i+1]>>3)*32+(data[i+2]>>3);counts[key]++;rs[key]+=data[i];gs[key]+=data[i+1];bs[key]+=data[i+2];}
|
|
167
|
+
const colors=[];for(let key=0;key<counts.length;key++)if(counts[key])colors.push(key);
|
|
168
|
+
colors.sort((a,b)=>counts[b]-counts[a]||a-b);
|
|
169
|
+
const palette=new Uint8Array(768),lookup=new Int16Array(32768);lookup.fill(-1);
|
|
170
|
+
const chosen=colors.slice(0,256);
|
|
171
|
+
for(let i=0;i<chosen.length;i++){const k=chosen[i];palette[i*3]=Math.round(rs[k]/counts[k]);palette[i*3+1]=Math.round(gs[k]/counts[k]);palette[i*3+2]=Math.round(bs[k]/counts[k]);lookup[k]=i;}
|
|
172
|
+
for(const k of colors){
|
|
173
|
+
if(lookup[k]>=0)continue;
|
|
174
|
+
const r=rs[k]/counts[k],g=gs[k]/counts[k],b=bs[k]/counts[k];let best=Infinity,index=0;
|
|
175
|
+
for(let j=0;j<chosen.length;j++){const distance=(r-palette[j*3])**2+(g-palette[j*3+1])**2+(b-palette[j*3+2])**2;if(distance<best){best=distance;index=j;}}
|
|
176
|
+
lookup[k]=index;
|
|
177
|
+
}
|
|
178
|
+
const pixels=new Uint8Array(imageData.width*imageData.height);
|
|
179
|
+
for(let i=0,j=0;i<data.length;i+=4,j++)pixels[j]=lookup[(data[i]>>3)*1024+(data[i+1]>>3)*32+(data[i+2]>>3)];
|
|
180
|
+
return{palette,pixels};
|
|
181
|
+
}
|
|
182
|
+
async function rasterGifFrame(frame,width,height){
|
|
183
|
+
let data=await frame.data;
|
|
184
|
+
if(frame.compressed)data=await new Response(data.stream().pipeThrough(new DecompressionStream('gzip'))).blob();
|
|
185
|
+
const url=URL.createObjectURL(new Blob([data],{type:'image/svg+xml;charset=utf-8'}));
|
|
186
|
+
try{
|
|
187
|
+
const image=new Image();image.src=url;await image.decode();
|
|
188
|
+
const canvas=document.createElement('canvas');canvas.width=width;canvas.height=height;
|
|
189
|
+
const ctx=canvas.getContext('2d',{willReadFrequently:true});
|
|
190
|
+
ctx.fillStyle='#0a0f16';ctx.fillRect(0,0,width,height);
|
|
191
|
+
// Resizes are letterboxed at original pixel size, never re-laid out or scaled.
|
|
192
|
+
ctx.drawImage(image,0,0,frame.width,frame.height);
|
|
193
|
+
return gifPixels(ctx.getImageData(0,0,width,height));
|
|
194
|
+
}finally{URL.revokeObjectURL(url);}
|
|
195
|
+
}
|
|
196
|
+
async function downloadGif(){
|
|
197
|
+
if(gifButton.disabled||gifExporting)return;
|
|
198
|
+
if(replaying){gifNotice.textContent='Wait for replay to finish before exporting.';return;}
|
|
199
|
+
if(gifSnapshotOnly){gifHistory.length=0;gifBytes=0;gifLastSvg='';gifEpoch++;}
|
|
200
|
+
captureGifFrame(true);if(gifFailure)return;
|
|
201
|
+
if(!gifHistory.length){gifNotice.textContent='No visible graph recorded yet.';return;}
|
|
202
|
+
const frames=gifHistory.slice(),session=gifSession;
|
|
203
|
+
const stop=performance.now();
|
|
204
|
+
const width=Math.max(...frames.map(f=>f.width)),height=Math.max(...frames.map(f=>f.height));
|
|
205
|
+
if(width>65535||height>65535){gifError('GIF unavailable: viewport is too large.');return;}
|
|
206
|
+
gifExporting=true;gifButton.disabled=true;replayButton.disabled=true;
|
|
207
|
+
const original=gifButton.textContent;
|
|
208
|
+
try{
|
|
209
|
+
const header=[];pushText(header,'GIF89a');pushWord(header,width);pushWord(header,height);header.push(0x70,0,0);
|
|
210
|
+
header.push(0x21,0xFF,0x0B);pushText(header,'NETSCAPE2.0');header.push(3,1,0,0,0);
|
|
211
|
+
const parts=[Uint8Array.from(header)];let previousEnd=0;
|
|
212
|
+
for(let i=0;i<frames.length;i++){
|
|
213
|
+
gifButton.textContent=`Encoding ${i+1}/${frames.length}`;await sleep(0);
|
|
214
|
+
const raster=await rasterGifFrame(frames[i],width,height);
|
|
215
|
+
const end=Math.round(((frames[i+1]?.time??stop)-frames[0].time)/10);
|
|
216
|
+
let delay=Math.max(2,end-previousEnd);previousEnd+=delay;
|
|
217
|
+
// GIF's delay field is 16-bit centiseconds; preserve long idle intervals.
|
|
218
|
+
do{
|
|
219
|
+
const chunk=Math.min(65535,delay),block=[0x21,0xF9,4,4];pushWord(block,chunk);block.push(0,0,0x2C);
|
|
220
|
+
pushWord(block,0);pushWord(block,0);pushWord(block,width);pushWord(block,height);block.push(0x87);
|
|
221
|
+
parts.push(Uint8Array.from(block),raster.palette,Uint8Array.of(8),gifBlocks(lzw(raster.pixels)));delay-=chunk;
|
|
222
|
+
}while(delay>0);
|
|
223
|
+
}
|
|
224
|
+
parts.push(Uint8Array.of(0x3B));
|
|
225
|
+
const blob=new Blob(parts,{type:'image/gif'}),url=URL.createObjectURL(blob),a=document.createElement('a');
|
|
226
|
+
a.href=url;a.download=`execweave-${session}.gif`;document.body.appendChild(a);a.click();a.remove();
|
|
227
|
+
setTimeout(()=>URL.revokeObjectURL(url),1000);
|
|
228
|
+
gifNotice.textContent=frames.length===1?'Saved current graph (still image).':'Saved recorded graph viewport.';
|
|
229
|
+
}catch(error){gifNotice.textContent=`GIF export failed: ${error.message}`;}
|
|
230
|
+
finally{gifExporting=false;gifButton.disabled=!!gifFailure;replayButton.disabled=false;gifButton.textContent=original;}
|
|
231
|
+
}
|
|
232
|
+
"""
|