redeploy 0.2.54__tar.gz → 0.2.55__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.
- {redeploy-0.2.54 → redeploy-0.2.55}/PKG-INFO +6 -6
- {redeploy-0.2.54 → redeploy-0.2.55}/README.md +5 -5
- {redeploy-0.2.54 → redeploy-0.2.55}/pyproject.toml +1 -1
- {redeploy-0.2.54 → redeploy-0.2.55}/redeploy/__init__.py +1 -1
- {redeploy-0.2.54 → redeploy-0.2.55}/redeploy/heal/runner.py +1 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/redeploy/tests/test_heal.py +5 -5
- {redeploy-0.2.54 → redeploy-0.2.55}/redeploy.egg-info/PKG-INFO +6 -6
- {redeploy-0.2.54 → redeploy-0.2.55}/redeploy.egg-info/SOURCES.txt +2 -0
- redeploy-0.2.55/tests/test_heal_decider.py +63 -0
- redeploy-0.2.55/tests/test_heal_loop_detector.py +47 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/redeploy/apply/__init__.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/redeploy/apply/exceptions.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/redeploy/apply/executor.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/redeploy/apply/handlers.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/redeploy/apply/progress.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/redeploy/apply/rollback.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/redeploy/apply/state.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/redeploy/apply/state_apply.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/redeploy/apply/utils/__init__.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/redeploy/apply/utils/run_container_build.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/redeploy/audit.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/redeploy/blueprint/__init__.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/redeploy/blueprint/extractor.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/redeploy/blueprint/generators/__init__.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/redeploy/blueprint/generators/docker_compose.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/redeploy/blueprint/generators/migration.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/redeploy/blueprint/sources/__init__.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/redeploy/blueprint/sources/compose.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/redeploy/blueprint/sources/hardware.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/redeploy/blueprint/sources/infra.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/redeploy/blueprint/sources/migration.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/redeploy/cli/__init__.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/redeploy/cli/commands/__init__.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/redeploy/cli/commands/audit.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/redeploy/cli/commands/blueprint.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/redeploy/cli/commands/bump_fix.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/redeploy/cli/commands/detect.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/redeploy/cli/commands/device_map.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/redeploy/cli/commands/device_map_renderers.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/redeploy/cli/commands/devices.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/redeploy/cli/commands/diagnose.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/redeploy/cli/commands/diff.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/redeploy/cli/commands/exec_.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/redeploy/cli/commands/export.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/redeploy/cli/commands/hardware.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/redeploy/cli/commands/import_.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/redeploy/cli/commands/init.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/redeploy/cli/commands/inspect.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/redeploy/cli/commands/mcp_cmd.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/redeploy/cli/commands/patterns.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/redeploy/cli/commands/plan_apply.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/redeploy/cli/commands/plugin.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/redeploy/cli/commands/probe.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/redeploy/cli/commands/prompt_cmd.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/redeploy/cli/commands/push.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/redeploy/cli/commands/state.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/redeploy/cli/commands/status.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/redeploy/cli/commands/target.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/redeploy/cli/commands/version/__init__.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/redeploy/cli/commands/version/commands.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/redeploy/cli/commands/version/helpers.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/redeploy/cli/commands/version/monorepo.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/redeploy/cli/commands/version/release.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/redeploy/cli/commands/version/scanner.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/redeploy/cli/commands/workflow.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/redeploy/cli/core.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/redeploy/cli/display.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/redeploy/cli/query.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/redeploy/cli.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/redeploy/config_apply/__init__.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/redeploy/config_apply/applier.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/redeploy/config_apply/loader.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/redeploy/data_sync.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/redeploy/detect/__init__.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/redeploy/detect/builtin/__init__.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/redeploy/detect/detector.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/redeploy/detect/hardware.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/redeploy/detect/hardware_rules.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/redeploy/detect/probes.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/redeploy/detect/remote.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/redeploy/detect/templates.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/redeploy/detect/workflow.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/redeploy/discovery.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/redeploy/dsl/__init__.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/redeploy/dsl/loader.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/redeploy/dsl/parser.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/redeploy/dsl_python/__init__.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/redeploy/dsl_python/context.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/redeploy/dsl_python/decorators.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/redeploy/dsl_python/docker_steps.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/redeploy/dsl_python/exceptions.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/redeploy/dsl_python/runner.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/redeploy/dsl_python/steps.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/redeploy/fleet.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/redeploy/hardware/__init__.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/redeploy/hardware/config_txt.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/redeploy/hardware/data/__init__.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/redeploy/hardware/data/hyperpixel.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/redeploy/hardware/data/official.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/redeploy/hardware/data/waveshare.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/redeploy/hardware/fixes.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/redeploy/hardware/kiosk/__init__.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/redeploy/hardware/kiosk/autostart.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/redeploy/hardware/kiosk/browsers.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/redeploy/hardware/kiosk/compositors.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/redeploy/hardware/kiosk/output_profiles.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/redeploy/hardware/panels.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/redeploy/hardware/raspi_config.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/redeploy/heal/__init__.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/redeploy/heal/decider.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/redeploy/heal/hint_provider.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/redeploy/heal/log_writer.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/redeploy/heal/loop_detector.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/redeploy/heal.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/redeploy/iac/__init__.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/redeploy/iac/base.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/redeploy/iac/config_hints.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/redeploy/iac/docker_compose.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/redeploy/iac/parsers/__init__.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/redeploy/iac/parsers/compose.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/redeploy/iac/registry.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/redeploy/integrations/__init__.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/redeploy/integrations/op3_bridge.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/redeploy/markpact/__init__.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/redeploy/markpact/compiler.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/redeploy/markpact/models.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/redeploy/markpact/parser.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/redeploy/mcp_server.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/redeploy/models.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/redeploy/observe.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/redeploy/parse.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/redeploy/patterns.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/redeploy/plan/__init__.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/redeploy/plan/planner.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/redeploy/plugins/__init__.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/redeploy/plugins/builtin/__init__.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/redeploy/plugins/builtin/browser_reload.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/redeploy/plugins/builtin/hardware_diagnostic.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/redeploy/plugins/builtin/notify.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/redeploy/plugins/builtin/process_control.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/redeploy/plugins/builtin/systemd_reload.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/redeploy/schema.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/redeploy/spec_loader.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/redeploy/ssh.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/redeploy/steps/__init__.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/redeploy/steps/builtins.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/redeploy/steps/kiosk.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/redeploy/tests/__init__.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/redeploy/tests/test_audit.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/redeploy/tests/test_cli.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/redeploy/tests/test_data_sync.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/redeploy/tests/test_discovery.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/redeploy/tests/test_dsl.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/redeploy/tests/test_examples.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/redeploy/tests/test_executor.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/redeploy/tests/test_fleet.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/redeploy/tests/test_git_integration.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/redeploy/tests/test_hooks.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/redeploy/tests/test_iac.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/redeploy/tests/test_manifest.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/redeploy/tests/test_markpact_compiler.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/redeploy/tests/test_markpact_parser.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/redeploy/tests/test_models.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/redeploy/tests/test_observe.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/redeploy/tests/test_parse.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/redeploy/tests/test_patterns.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/redeploy/tests/test_planner_edge.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/redeploy/tests/test_plugins.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/redeploy/tests/test_probes.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/redeploy/tests/test_public_api.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/redeploy/tests/test_resume.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/redeploy/tests/test_spec_loader.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/redeploy/tests/test_ssh.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/redeploy/tests/test_templates.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/redeploy/tests/test_verify.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/redeploy/tests/test_version.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/redeploy/tests/test_version_changelog.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/redeploy/tests/test_version_cli.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/redeploy/tests/test_version_manifest.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/redeploy/tests/test_version_sources.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/redeploy/tests/test_workflow.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/redeploy/verify.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/redeploy/version/__init__.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/redeploy/version/bump.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/redeploy/version/changelog.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/redeploy/version/commits.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/redeploy/version/diff.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/redeploy/version/git_integration.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/redeploy/version/git_transaction.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/redeploy/version/manifest.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/redeploy/version/sources/__init__.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/redeploy/version/sources/base.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/redeploy/version/sources/json_.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/redeploy/version/sources/plain.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/redeploy/version/sources/regex.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/redeploy/version/sources/toml_.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/redeploy/version/sources/yaml_.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/redeploy/version/transaction.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/redeploy/version.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/redeploy.egg-info/dependency_links.txt +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/redeploy.egg-info/entry_points.txt +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/redeploy.egg-info/requires.txt +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/redeploy.egg-info/top_level.txt +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/setup.cfg +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/tests/test_blueprint_sources.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/tests/test_blueprint_sources_compose.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/tests/test_cli_query.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/tests/test_example_argocd_flux_plugin.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/tests/test_example_gitops_ci_plugin.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/tests/test_example_helm_kustomize_plugin.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/tests/test_hardware_config.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/tests/test_hardware_kiosk.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/tests/test_hardware_rules.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/tests/test_iac.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/tests/test_iac_config_hints.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/tests/test_iac_plugin_loading.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/tests/test_import_plugin_template.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/tests/test_parse.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/tests/test_prompt_llm.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/tests/test_redeploy.py +0 -0
- {redeploy-0.2.54 → redeploy-0.2.55}/tests/test_steps_kiosk.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: redeploy
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.55
|
|
4
4
|
Summary: Infrastructure migration toolkit: detect → plan → apply
|
|
5
5
|
Requires-Python: >=3.11
|
|
6
6
|
Description-Content-Type: text/markdown
|
|
@@ -32,17 +32,17 @@ Requires-Dist: mcp>=1.0; extra == "mcp"
|
|
|
32
32
|
|
|
33
33
|
## AI Cost Tracking
|
|
34
34
|
|
|
35
|
-
     
|
|
36
|
+
  
|
|
37
37
|
|
|
38
|
-
- 🤖 **LLM usage:** $7.5000 (
|
|
39
|
-
- 👤 **Human dev:** ~$
|
|
38
|
+
- 🤖 **LLM usage:** $7.5000 (75 commits)
|
|
39
|
+
- 👤 **Human dev:** ~$2853 (28.5h @ $100/h, 30min dedup)
|
|
40
40
|
|
|
41
41
|
Generated on 2026-04-21 using [openrouter/qwen/qwen3-coder-next](https://openrouter.ai/qwen/qwen3-coder-next)
|
|
42
42
|
|
|
43
43
|
---
|
|
44
44
|
|
|
45
|
-
    
|
|
46
46
|
|
|
47
47
|
Infrastructure migration and device deploy toolkit — VPS, Raspberry Pi kiosk, Podman Quadlet, k3s.
|
|
48
48
|
|
|
@@ -3,17 +3,17 @@
|
|
|
3
3
|
|
|
4
4
|
## AI Cost Tracking
|
|
5
5
|
|
|
6
|
-
     
|
|
7
|
+
  
|
|
8
8
|
|
|
9
|
-
- 🤖 **LLM usage:** $7.5000 (
|
|
10
|
-
- 👤 **Human dev:** ~$
|
|
9
|
+
- 🤖 **LLM usage:** $7.5000 (75 commits)
|
|
10
|
+
- 👤 **Human dev:** ~$2853 (28.5h @ $100/h, 30min dedup)
|
|
11
11
|
|
|
12
12
|
Generated on 2026-04-21 using [openrouter/qwen/qwen3-coder-next](https://openrouter.ai/qwen/qwen3-coder-next)
|
|
13
13
|
|
|
14
14
|
---
|
|
15
15
|
|
|
16
|
-
    
|
|
17
17
|
|
|
18
18
|
Infrastructure migration and device deploy toolkit — VPS, Raspberry Pi kiosk, Podman Quadlet, k3s.
|
|
19
19
|
|
|
@@ -7,7 +7,7 @@ Public API (stable from 0.2.0, semver guaranteed)::
|
|
|
7
7
|
|
|
8
8
|
Everything not listed in ``__all__`` is internal and may change without notice.
|
|
9
9
|
"""
|
|
10
|
-
__version__ = "0.2.
|
|
10
|
+
__version__ = "0.2.55"
|
|
11
11
|
|
|
12
12
|
# ── Core models ───────────────────────────────────────────────────────────────
|
|
13
13
|
from .models import ( # noqa: F401
|
|
@@ -60,11 +60,11 @@ def test_heal_runner_stops_on_repeating_hint_pattern(monkeypatch, tmp_path):
|
|
|
60
60
|
ask_calls.append(True)
|
|
61
61
|
return "```yaml\n- id: sync_env\n action: ssh_cmd\n description: \"manual\"\n```"
|
|
62
62
|
|
|
63
|
-
monkeypatch.setattr("redeploy.heal.parse_failed_step", lambda *_a, **_k: ("sync_env", "boom"))
|
|
64
|
-
monkeypatch.setattr("redeploy.heal.collect_diagnostics", lambda *_a, **_k: "ERROR: same")
|
|
65
|
-
monkeypatch.setattr("redeploy.heal.ask_llm", _fake_ask)
|
|
66
|
-
monkeypatch.setattr("redeploy.heal.apply_fix_to_spec", lambda *_a, **_k:
|
|
67
|
-
monkeypatch.setattr("redeploy.heal.write_repair_log", lambda *_a, **_k: None)
|
|
63
|
+
monkeypatch.setattr("redeploy.heal.runner.parse_failed_step", lambda *_a, **_k: ("sync_env", "boom"))
|
|
64
|
+
monkeypatch.setattr("redeploy.heal.runner.collect_diagnostics", lambda *_a, **_k: "ERROR: same")
|
|
65
|
+
monkeypatch.setattr("redeploy.heal.runner.ask_llm", _fake_ask)
|
|
66
|
+
monkeypatch.setattr("redeploy.heal.runner.apply_fix_to_spec", lambda *_a, **_k: True)
|
|
67
|
+
monkeypatch.setattr("redeploy.heal.runner.write_repair_log", lambda *_a, **_k: None)
|
|
68
68
|
monkeypatch.setattr(HealRunner, "_make_executor", _fake_make_executor)
|
|
69
69
|
monkeypatch.setattr(HealRunner, "_reload_migration", lambda *_a, **_k: None)
|
|
70
70
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: redeploy
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.55
|
|
4
4
|
Summary: Infrastructure migration toolkit: detect → plan → apply
|
|
5
5
|
Requires-Python: >=3.11
|
|
6
6
|
Description-Content-Type: text/markdown
|
|
@@ -32,17 +32,17 @@ Requires-Dist: mcp>=1.0; extra == "mcp"
|
|
|
32
32
|
|
|
33
33
|
## AI Cost Tracking
|
|
34
34
|
|
|
35
|
-
     
|
|
36
|
+
  
|
|
37
37
|
|
|
38
|
-
- 🤖 **LLM usage:** $7.5000 (
|
|
39
|
-
- 👤 **Human dev:** ~$
|
|
38
|
+
- 🤖 **LLM usage:** $7.5000 (75 commits)
|
|
39
|
+
- 👤 **Human dev:** ~$2853 (28.5h @ $100/h, 30min dedup)
|
|
40
40
|
|
|
41
41
|
Generated on 2026-04-21 using [openrouter/qwen/qwen3-coder-next](https://openrouter.ai/qwen/qwen3-coder-next)
|
|
42
42
|
|
|
43
43
|
---
|
|
44
44
|
|
|
45
|
-
    
|
|
46
46
|
|
|
47
47
|
Infrastructure migration and device deploy toolkit — VPS, Raspberry Pi kiosk, Podman Quadlet, k3s.
|
|
48
48
|
|
|
@@ -207,6 +207,8 @@ tests/test_example_helm_kustomize_plugin.py
|
|
|
207
207
|
tests/test_hardware_config.py
|
|
208
208
|
tests/test_hardware_kiosk.py
|
|
209
209
|
tests/test_hardware_rules.py
|
|
210
|
+
tests/test_heal_decider.py
|
|
211
|
+
tests/test_heal_loop_detector.py
|
|
210
212
|
tests/test_iac.py
|
|
211
213
|
tests/test_iac_config_hints.py
|
|
212
214
|
tests/test_iac_plugin_loading.py
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
"""Unit tests for redeploy.heal.decider (R1)."""
|
|
2
|
+
import pytest
|
|
3
|
+
|
|
4
|
+
from redeploy.heal.decider import Action, Decision, decide_after_failure, format_decision_message
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class TestDecideAfterFailure:
|
|
8
|
+
def test_loop_aborts(self):
|
|
9
|
+
d = decide_after_failure(
|
|
10
|
+
attempt=1, max_retries=5, failed_step="s",
|
|
11
|
+
loop_detected=True, llm_error=False, spec_patched=False,
|
|
12
|
+
)
|
|
13
|
+
assert d.action is Action.ABORT
|
|
14
|
+
assert "Loop detected" in d.reason
|
|
15
|
+
|
|
16
|
+
def test_missing_step_aborts(self):
|
|
17
|
+
d = decide_after_failure(
|
|
18
|
+
attempt=1, max_retries=5, failed_step=None,
|
|
19
|
+
loop_detected=False, llm_error=False, spec_patched=False,
|
|
20
|
+
)
|
|
21
|
+
assert d.action is Action.ABORT
|
|
22
|
+
|
|
23
|
+
def test_max_retries_aborts(self):
|
|
24
|
+
d = decide_after_failure(
|
|
25
|
+
attempt=3, max_retries=3, failed_step="s",
|
|
26
|
+
loop_detected=False, llm_error=False, spec_patched=False,
|
|
27
|
+
)
|
|
28
|
+
assert d.action is Action.ABORT
|
|
29
|
+
assert "exhausted" in d.reason
|
|
30
|
+
|
|
31
|
+
def test_patch_retries(self):
|
|
32
|
+
d = decide_after_failure(
|
|
33
|
+
attempt=2, max_retries=3, failed_step="s",
|
|
34
|
+
loop_detected=False, llm_error=False, spec_patched=True,
|
|
35
|
+
)
|
|
36
|
+
assert d.action is Action.RETRY
|
|
37
|
+
|
|
38
|
+
def test_llm_error_retries_then_aborts(self):
|
|
39
|
+
d = decide_after_failure(
|
|
40
|
+
attempt=1, max_retries=3, failed_step="s",
|
|
41
|
+
loop_detected=False, llm_error=True, spec_patched=False,
|
|
42
|
+
)
|
|
43
|
+
assert d.action is Action.RETRY
|
|
44
|
+
d2 = decide_after_failure(
|
|
45
|
+
attempt=3, max_retries=3, failed_step="s",
|
|
46
|
+
loop_detected=False, llm_error=True, spec_patched=False,
|
|
47
|
+
)
|
|
48
|
+
assert d2.action is Action.ABORT
|
|
49
|
+
|
|
50
|
+
def test_no_patch_skips(self):
|
|
51
|
+
d = decide_after_failure(
|
|
52
|
+
attempt=1, max_retries=3, failed_step="s",
|
|
53
|
+
loop_detected=False, llm_error=False, spec_patched=False,
|
|
54
|
+
)
|
|
55
|
+
assert d.action is Action.SKIP
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
class TestFormatDecisionMessage:
|
|
59
|
+
def test_contains_action(self):
|
|
60
|
+
d = Decision(Action.RETRY, "because patched")
|
|
61
|
+
msg = format_decision_message(d, "step-1")
|
|
62
|
+
assert "RETRY" in msg
|
|
63
|
+
assert "patched" in msg
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
"""Unit tests for redeploy.heal.loop_detector (R1)."""
|
|
2
|
+
import pytest
|
|
3
|
+
|
|
4
|
+
from redeploy.heal.loop_detector import HealAbort, HealLoopDetector
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class TestHealLoopDetector:
|
|
8
|
+
def test_empty_hint_ignored(self):
|
|
9
|
+
d = HealLoopDetector(max_identical_hints=2)
|
|
10
|
+
assert d.observe("step1", "") is False
|
|
11
|
+
assert d.observe("step1", " ") is False
|
|
12
|
+
|
|
13
|
+
def test_loop_detected_after_n_identical(self):
|
|
14
|
+
d = HealLoopDetector(max_identical_hints=3)
|
|
15
|
+
assert d.observe("s", "hint-a") is False
|
|
16
|
+
assert d.observe("s", "hint-a") is False
|
|
17
|
+
assert d.observe("s", "hint-a") is True
|
|
18
|
+
|
|
19
|
+
def test_different_hints_reset(self):
|
|
20
|
+
d = HealLoopDetector(max_identical_hints=3)
|
|
21
|
+
d.observe("s", "hint-a")
|
|
22
|
+
d.observe("s", "hint-a")
|
|
23
|
+
assert d.observe("s", "hint-b") is False
|
|
24
|
+
assert d.observe("s", "hint-b") is False
|
|
25
|
+
assert d.observe("s", "hint-b") is True
|
|
26
|
+
|
|
27
|
+
def test_reset_clears_history(self):
|
|
28
|
+
d = HealLoopDetector(max_identical_hints=2)
|
|
29
|
+
d.observe("s", "h")
|
|
30
|
+
d.reset("s")
|
|
31
|
+
assert d.observe("s", "h") is False
|
|
32
|
+
|
|
33
|
+
def test_different_step_ids_isolated(self):
|
|
34
|
+
d = HealLoopDetector(max_identical_hints=2)
|
|
35
|
+
assert d.observe("s1", "h") is False
|
|
36
|
+
assert d.observe("s2", "h") is False
|
|
37
|
+
assert d.observe("s1", "h") is True
|
|
38
|
+
assert d.observe("s2", "h") is True
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
class TestHealAbort:
|
|
42
|
+
def test_message(self):
|
|
43
|
+
exc = HealAbort("sync_env", "bad hint", 3)
|
|
44
|
+
assert "sync_env" in str(exc)
|
|
45
|
+
assert "3x" in str(exc)
|
|
46
|
+
assert exc.step_id == "sync_env"
|
|
47
|
+
assert exc.repeats == 3
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|