patchshuttle 0.1.0a6__tar.gz → 0.1.0a7__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.
- {patchshuttle-0.1.0a6 → patchshuttle-0.1.0a7}/CHANGELOG.md +30 -0
- {patchshuttle-0.1.0a6 → patchshuttle-0.1.0a7}/PKG-INFO +33 -12
- {patchshuttle-0.1.0a6 → patchshuttle-0.1.0a7}/README.md +32 -11
- {patchshuttle-0.1.0a6 → patchshuttle-0.1.0a7}/docs/NEXT_RELEASE.md +28 -5
- {patchshuttle-0.1.0a6 → patchshuttle-0.1.0a7}/docs/RELEASE.md +36 -10
- patchshuttle-0.1.0a7/docs/ROADMAP.md +56 -0
- {patchshuttle-0.1.0a6 → patchshuttle-0.1.0a7}/src/patchshuttle/_python_discovery.py +16 -2
- {patchshuttle-0.1.0a6 → patchshuttle-0.1.0a7}/src/patchshuttle/_version.py +1 -1
- {patchshuttle-0.1.0a6 → patchshuttle-0.1.0a7}/src/patchshuttle/actions/__init__.py +6 -0
- {patchshuttle-0.1.0a6 → patchshuttle-0.1.0a7}/src/patchshuttle/actions/constructors.py +64 -3
- patchshuttle-0.1.0a7/src/patchshuttle/analysis/__init__.py +1 -0
- patchshuttle-0.1.0a7/src/patchshuttle/analysis/dependencies.py +160 -0
- patchshuttle-0.1.0a7/src/patchshuttle/analysis/references.py +136 -0
- {patchshuttle-0.1.0a6 → patchshuttle-0.1.0a7}/src/patchshuttle/audit.py +51 -4
- {patchshuttle-0.1.0a6 → patchshuttle-0.1.0a7}/src/patchshuttle/cli.py +4 -141
- {patchshuttle-0.1.0a6 → patchshuttle-0.1.0a7}/src/patchshuttle/context.py +10 -1
- patchshuttle-0.1.0a7/src/patchshuttle/documentation/__init__.py +1 -0
- patchshuttle-0.1.0a7/src/patchshuttle/documentation/cli.py +93 -0
- patchshuttle-0.1.0a7/src/patchshuttle/documentation/refresh.py +132 -0
- {patchshuttle-0.1.0a6 → patchshuttle-0.1.0a7}/src/patchshuttle/logging.py +9 -57
- {patchshuttle-0.1.0a6 → patchshuttle-0.1.0a7}/src/patchshuttle/models.py +60 -2
- {patchshuttle-0.1.0a6 → patchshuttle-0.1.0a7}/src/patchshuttle/planner.py +12 -28
- patchshuttle-0.1.0a7/src/patchshuttle/planning/discovery_log.py +70 -0
- patchshuttle-0.1.0a7/src/patchshuttle/planning/display.py +114 -0
- patchshuttle-0.1.0a7/src/patchshuttle/planning/guidance.py +38 -0
- {patchshuttle-0.1.0a6 → patchshuttle-0.1.0a7}/src/patchshuttle/planning/imports.py +31 -6
- patchshuttle-0.1.0a7/src/patchshuttle/planning/symbols.py +53 -0
- patchshuttle-0.1.0a7/src/patchshuttle/planning/templates.py +39 -0
- {patchshuttle-0.1.0a6 → patchshuttle-0.1.0a7}/src/patchshuttle/planning/types.py +5 -0
- patchshuttle-0.1.0a7/src/patchshuttle/resources/AI_GUIDE.md +734 -0
- {patchshuttle-0.1.0a6 → patchshuttle-0.1.0a7}/src/patchshuttle/resources/PATCHSHUTTLE_PROTOCOL.md +153 -5
- {patchshuttle-0.1.0a6 → patchshuttle-0.1.0a7}/src/patchshuttle/selfdoc.py +34 -3
- {patchshuttle-0.1.0a6 → patchshuttle-0.1.0a7}/tests/unit/test_cli.py +2 -2
- {patchshuttle-0.1.0a6 → patchshuttle-0.1.0a7}/tests/unit/test_package.py +1 -1
- {patchshuttle-0.1.0a6 → patchshuttle-0.1.0a7}/tests/unit/test_release_configuration.py +1 -1
- {patchshuttle-0.1.0a6 → patchshuttle-0.1.0a7}/tests/unit/test_selfdoc.py +1 -1
- patchshuttle-0.1.0a7/tests/unit/workflow/test_ai_doc_contract.py +108 -0
- patchshuttle-0.1.0a7/tests/unit/workflow/test_ai_guidance.py +122 -0
- patchshuttle-0.1.0a7/tests/unit/workflow/test_audit_templates.py +131 -0
- patchshuttle-0.1.0a7/tests/unit/workflow/test_dependencies.py +142 -0
- patchshuttle-0.1.0a7/tests/unit/workflow/test_guide_refresh.py +180 -0
- patchshuttle-0.1.0a7/tests/unit/workflow/test_import_batch.py +167 -0
- patchshuttle-0.1.0a7/tests/unit/workflow/test_references.py +118 -0
- patchshuttle-0.1.0a7/tests/unit/workflow/test_symbol_diagnostics.py +81 -0
- {patchshuttle-0.1.0a6 → patchshuttle-0.1.0a7}/tools/wheel_smoke.py +12 -0
- {patchshuttle-0.1.0a6 → patchshuttle-0.1.0a7}/.github/workflows/ci.yml +0 -0
- {patchshuttle-0.1.0a6 → patchshuttle-0.1.0a7}/.github/workflows/release.yml +0 -0
- {patchshuttle-0.1.0a6 → patchshuttle-0.1.0a7}/.github/workflows/testpypi.yml +0 -0
- {patchshuttle-0.1.0a6 → patchshuttle-0.1.0a7}/.gitignore +0 -0
- {patchshuttle-0.1.0a6 → patchshuttle-0.1.0a7}/LICENSE +0 -0
- {patchshuttle-0.1.0a6 → patchshuttle-0.1.0a7}/SECURITY.md +0 -0
- {patchshuttle-0.1.0a6 → patchshuttle-0.1.0a7}/SPEC_V0_1.md +0 -0
- {patchshuttle-0.1.0a6 → patchshuttle-0.1.0a7}/docs/CHATGPT_INTEGRATION.md +0 -0
- {patchshuttle-0.1.0a6 → patchshuttle-0.1.0a7}/docs/DJANGO_MIGRATIONS.md +0 -0
- {patchshuttle-0.1.0a6 → patchshuttle-0.1.0a7}/pyproject.toml +0 -0
- {patchshuttle-0.1.0a6 → patchshuttle-0.1.0a7}/src/patchshuttle/__init__.py +0 -0
- {patchshuttle-0.1.0a6 → patchshuttle-0.1.0a7}/src/patchshuttle/_ai_log.py +0 -0
- {patchshuttle-0.1.0a6 → patchshuttle-0.1.0a7}/src/patchshuttle/_architecture.py +0 -0
- {patchshuttle-0.1.0a6 → patchshuttle-0.1.0a7}/src/patchshuttle/_diff.py +0 -0
- {patchshuttle-0.1.0a6 → patchshuttle-0.1.0a7}/src/patchshuttle/_html_lint.py +0 -0
- {patchshuttle-0.1.0a6 → patchshuttle-0.1.0a7}/src/patchshuttle/_line_ranges.py +0 -0
- {patchshuttle-0.1.0a6 → patchshuttle-0.1.0a7}/src/patchshuttle/_process.py +0 -0
- {patchshuttle-0.1.0a6 → patchshuttle-0.1.0a7}/src/patchshuttle/_python_structure.py +0 -0
- {patchshuttle-0.1.0a6 → patchshuttle-0.1.0a7}/src/patchshuttle/_python_symbols.py +0 -0
- {patchshuttle-0.1.0a6 → patchshuttle-0.1.0a7}/src/patchshuttle/_refactor.py +0 -0
- {patchshuttle-0.1.0a6 → patchshuttle-0.1.0a7}/src/patchshuttle/actions/create.py +0 -0
- {patchshuttle-0.1.0a6 → patchshuttle-0.1.0a7}/src/patchshuttle/actions/modify.py +0 -0
- {patchshuttle-0.1.0a6 → patchshuttle-0.1.0a7}/src/patchshuttle/backup.py +0 -0
- {patchshuttle-0.1.0a6 → patchshuttle-0.1.0a7}/src/patchshuttle/checks/__init__.py +0 -0
- {patchshuttle-0.1.0a6 → patchshuttle-0.1.0a7}/src/patchshuttle/checks/constructors.py +0 -0
- {patchshuttle-0.1.0a6 → patchshuttle-0.1.0a7}/src/patchshuttle/checks/runner.py +0 -0
- {patchshuttle-0.1.0a6 → patchshuttle-0.1.0a7}/src/patchshuttle/config.py +0 -0
- {patchshuttle-0.1.0a6 → patchshuttle-0.1.0a7}/src/patchshuttle/django_app/__init__.py +0 -0
- {patchshuttle-0.1.0a6 → patchshuttle-0.1.0a7}/src/patchshuttle/django_app/management/__init__.py +0 -0
- {patchshuttle-0.1.0a6 → patchshuttle-0.1.0a7}/src/patchshuttle/django_app/management/commands/__init__.py +0 -0
- {patchshuttle-0.1.0a6 → patchshuttle-0.1.0a7}/src/patchshuttle/django_app/management/commands/patchshuttle_migrate.py +0 -0
- {patchshuttle-0.1.0a6 → patchshuttle-0.1.0a7}/src/patchshuttle/django_app/workflow.py +0 -0
- {patchshuttle-0.1.0a6 → patchshuttle-0.1.0a7}/src/patchshuttle/errors.py +0 -0
- {patchshuttle-0.1.0a6 → patchshuttle-0.1.0a7}/src/patchshuttle/execution.py +0 -0
- {patchshuttle-0.1.0a6 → patchshuttle-0.1.0a7}/src/patchshuttle/formatter_policy.py +0 -0
- {patchshuttle-0.1.0a6 → patchshuttle-0.1.0a7}/src/patchshuttle/formatters/__init__.py +0 -0
- {patchshuttle-0.1.0a6 → patchshuttle-0.1.0a7}/src/patchshuttle/formatters/runner.py +0 -0
- {patchshuttle-0.1.0a6 → patchshuttle-0.1.0a7}/src/patchshuttle/history/__init__.py +0 -0
- {patchshuttle-0.1.0a6 → patchshuttle-0.1.0a7}/src/patchshuttle/history/cli.py +0 -0
- {patchshuttle-0.1.0a6 → patchshuttle-0.1.0a7}/src/patchshuttle/history/models.py +0 -0
- {patchshuttle-0.1.0a6 → patchshuttle-0.1.0a7}/src/patchshuttle/history/records.py +0 -0
- {patchshuttle-0.1.0a6 → patchshuttle-0.1.0a7}/src/patchshuttle/history/storage.py +0 -0
- {patchshuttle-0.1.0a6 → patchshuttle-0.1.0a7}/src/patchshuttle/identifiers.py +0 -0
- {patchshuttle-0.1.0a6 → patchshuttle-0.1.0a7}/src/patchshuttle/integrations/__init__.py +0 -0
- {patchshuttle-0.1.0a6 → patchshuttle-0.1.0a7}/src/patchshuttle/integrations/mcp_server.py +0 -0
- {patchshuttle-0.1.0a6 → patchshuttle-0.1.0a7}/src/patchshuttle/inventory.py +0 -0
- {patchshuttle-0.1.0a6 → patchshuttle-0.1.0a7}/src/patchshuttle/linters/__init__.py +0 -0
- {patchshuttle-0.1.0a6 → patchshuttle-0.1.0a7}/src/patchshuttle/linters/runner.py +0 -0
- {patchshuttle-0.1.0a6 → patchshuttle-0.1.0a7}/src/patchshuttle/operations.py +0 -0
- {patchshuttle-0.1.0a6 → patchshuttle-0.1.0a7}/src/patchshuttle/parser.py +0 -0
- {patchshuttle-0.1.0a6 → patchshuttle-0.1.0a7}/src/patchshuttle/planning/__init__.py +0 -0
- {patchshuttle-0.1.0a6 → patchshuttle-0.1.0a7}/src/patchshuttle/policy.py +0 -0
- {patchshuttle-0.1.0a6 → patchshuttle-0.1.0a7}/src/patchshuttle/preflight.py +0 -0
- {patchshuttle-0.1.0a6 → patchshuttle-0.1.0a7}/src/patchshuttle/project_python.py +0 -0
- {patchshuttle-0.1.0a6 → patchshuttle-0.1.0a7}/src/patchshuttle/py.typed +0 -0
- {patchshuttle-0.1.0a6 → patchshuttle-0.1.0a7}/src/patchshuttle/registry.py +0 -0
- {patchshuttle-0.1.0a6 → patchshuttle-0.1.0a7}/src/patchshuttle/resources/AUDIT-EXAMPLE.psh.yaml +0 -0
- {patchshuttle-0.1.0a6 → patchshuttle-0.1.0a7}/src/patchshuttle/resources/PATCH-EXAMPLE.psh.yaml +0 -0
- {patchshuttle-0.1.0a6 → patchshuttle-0.1.0a7}/src/patchshuttle/resources/__init__.py +0 -0
- {patchshuttle-0.1.0a6 → patchshuttle-0.1.0a7}/src/patchshuttle/rollback.py +0 -0
- {patchshuttle-0.1.0a6 → patchshuttle-0.1.0a7}/src/patchshuttle/runner.py +0 -0
- {patchshuttle-0.1.0a6 → patchshuttle-0.1.0a7}/src/patchshuttle/runtime_cache.py +0 -0
- {patchshuttle-0.1.0a6 → patchshuttle-0.1.0a7}/src/patchshuttle/verification.py +0 -0
- {patchshuttle-0.1.0a6 → patchshuttle-0.1.0a7}/src/patchshuttle/warning_baseline.py +0 -0
- {patchshuttle-0.1.0a6 → patchshuttle-0.1.0a7}/src/patchshuttle/workspace.py +0 -0
- {patchshuttle-0.1.0a6 → patchshuttle-0.1.0a7}/tests/e2e/test_cli_project_cycle.py +0 -0
- {patchshuttle-0.1.0a6 → patchshuttle-0.1.0a7}/tests/integration/test_workflows.py +0 -0
- {patchshuttle-0.1.0a6 → patchshuttle-0.1.0a7}/tests/integrations/test_django_migrations.py +0 -0
- {patchshuttle-0.1.0a6 → patchshuttle-0.1.0a7}/tests/integrations/test_imports.py +0 -0
- {patchshuttle-0.1.0a6 → patchshuttle-0.1.0a7}/tests/integrations/test_mcp_server.py +0 -0
- {patchshuttle-0.1.0a6 → patchshuttle-0.1.0a7}/tests/unit/history/test_history.py +0 -0
- {patchshuttle-0.1.0a6 → patchshuttle-0.1.0a7}/tests/unit/history/test_history_integration.py +0 -0
- {patchshuttle-0.1.0a6 → patchshuttle-0.1.0a7}/tests/unit/history/test_history_storage_edges.py +0 -0
- {patchshuttle-0.1.0a6 → patchshuttle-0.1.0a7}/tests/unit/test_a4_coverage_regressions.py +0 -0
- {patchshuttle-0.1.0a6 → patchshuttle-0.1.0a7}/tests/unit/test_actions.py +0 -0
- {patchshuttle-0.1.0a6 → patchshuttle-0.1.0a7}/tests/unit/test_ai_log.py +0 -0
- {patchshuttle-0.1.0a6 → patchshuttle-0.1.0a7}/tests/unit/test_architecture.py +0 -0
- {patchshuttle-0.1.0a6 → patchshuttle-0.1.0a7}/tests/unit/test_attempt_logging.py +0 -0
- {patchshuttle-0.1.0a6 → patchshuttle-0.1.0a7}/tests/unit/test_audit_verify_execution.py +0 -0
- {patchshuttle-0.1.0a6 → patchshuttle-0.1.0a7}/tests/unit/test_backup.py +0 -0
- {patchshuttle-0.1.0a6 → patchshuttle-0.1.0a7}/tests/unit/test_change_transaction.py +0 -0
- {patchshuttle-0.1.0a6 → patchshuttle-0.1.0a7}/tests/unit/test_check_transaction.py +0 -0
- {patchshuttle-0.1.0a6 → patchshuttle-0.1.0a7}/tests/unit/test_checks.py +0 -0
- {patchshuttle-0.1.0a6 → patchshuttle-0.1.0a7}/tests/unit/test_config.py +0 -0
- {patchshuttle-0.1.0a6 → patchshuttle-0.1.0a7}/tests/unit/test_context_and_constructors.py +0 -0
- {patchshuttle-0.1.0a6 → patchshuttle-0.1.0a7}/tests/unit/test_diff.py +0 -0
- {patchshuttle-0.1.0a6 → patchshuttle-0.1.0a7}/tests/unit/test_execution.py +0 -0
- {patchshuttle-0.1.0a6 → patchshuttle-0.1.0a7}/tests/unit/test_formatters.py +0 -0
- {patchshuttle-0.1.0a6 → patchshuttle-0.1.0a7}/tests/unit/test_formatting_transaction.py +0 -0
- {patchshuttle-0.1.0a6 → patchshuttle-0.1.0a7}/tests/unit/test_guarded_ranges.py +0 -0
- {patchshuttle-0.1.0a6 → patchshuttle-0.1.0a7}/tests/unit/test_html_lint.py +0 -0
- {patchshuttle-0.1.0a6 → patchshuttle-0.1.0a7}/tests/unit/test_identifiers.py +0 -0
- {patchshuttle-0.1.0a6 → patchshuttle-0.1.0a7}/tests/unit/test_inventory.py +0 -0
- {patchshuttle-0.1.0a6 → patchshuttle-0.1.0a7}/tests/unit/test_inventory_transaction.py +0 -0
- {patchshuttle-0.1.0a6 → patchshuttle-0.1.0a7}/tests/unit/test_logging.py +0 -0
- {patchshuttle-0.1.0a6 → patchshuttle-0.1.0a7}/tests/unit/test_manual_rollback.py +0 -0
- {patchshuttle-0.1.0a6 → patchshuttle-0.1.0a7}/tests/unit/test_models.py +0 -0
- {patchshuttle-0.1.0a6 → patchshuttle-0.1.0a7}/tests/unit/test_modify_actions.py +0 -0
- {patchshuttle-0.1.0a6 → patchshuttle-0.1.0a7}/tests/unit/test_move_file.py +0 -0
- {patchshuttle-0.1.0a6 → patchshuttle-0.1.0a7}/tests/unit/test_operational_execution.py +0 -0
- {patchshuttle-0.1.0a6 → patchshuttle-0.1.0a7}/tests/unit/test_parser.py +0 -0
- {patchshuttle-0.1.0a6 → patchshuttle-0.1.0a7}/tests/unit/test_phase19_cli.py +0 -0
- {patchshuttle-0.1.0a6 → patchshuttle-0.1.0a7}/tests/unit/test_planner.py +0 -0
- {patchshuttle-0.1.0a6 → patchshuttle-0.1.0a7}/tests/unit/test_planner_ux.py +0 -0
- {patchshuttle-0.1.0a6 → patchshuttle-0.1.0a7}/tests/unit/test_policy.py +0 -0
- {patchshuttle-0.1.0a6 → patchshuttle-0.1.0a7}/tests/unit/test_preflight.py +0 -0
- {patchshuttle-0.1.0a6 → patchshuttle-0.1.0a7}/tests/unit/test_project_python.py +0 -0
- {patchshuttle-0.1.0a6 → patchshuttle-0.1.0a7}/tests/unit/test_python_discovery.py +0 -0
- {patchshuttle-0.1.0a6 → patchshuttle-0.1.0a7}/tests/unit/test_python_structure.py +0 -0
- {patchshuttle-0.1.0a6 → patchshuttle-0.1.0a7}/tests/unit/test_python_structure_action.py +0 -0
- {patchshuttle-0.1.0a6 → patchshuttle-0.1.0a7}/tests/unit/test_python_symbols.py +0 -0
- {patchshuttle-0.1.0a6 → patchshuttle-0.1.0a7}/tests/unit/test_refactor.py +0 -0
- {patchshuttle-0.1.0a6 → patchshuttle-0.1.0a7}/tests/unit/test_registry.py +0 -0
- {patchshuttle-0.1.0a6 → patchshuttle-0.1.0a7}/tests/unit/test_rollback.py +0 -0
- {patchshuttle-0.1.0a6 → patchshuttle-0.1.0a7}/tests/unit/test_runner.py +0 -0
- {patchshuttle-0.1.0a6 → patchshuttle-0.1.0a7}/tests/unit/test_runtime_cache.py +0 -0
- {patchshuttle-0.1.0a6 → patchshuttle-0.1.0a7}/tests/unit/test_structural_guards.py +0 -0
- {patchshuttle-0.1.0a6 → patchshuttle-0.1.0a7}/tests/unit/test_warning_baseline.py +0 -0
- {patchshuttle-0.1.0a6 → patchshuttle-0.1.0a7}/tests/unit/test_workspace.py +0 -0
- /patchshuttle-0.1.0a6/src/patchshuttle/resources/AI_GUIDE.md → /patchshuttle-0.1.0a7/tests/unit/workflow/fixtures/a6-guide.md +0 -0
- {patchshuttle-0.1.0a6 → patchshuttle-0.1.0a7}/tools/check_tag.py +0 -0
- {patchshuttle-0.1.0a6 → patchshuttle-0.1.0a7}/tools/django_postgres_smoke.py +0 -0
- {patchshuttle-0.1.0a6 → patchshuttle-0.1.0a7}/tools/index_smoke.py +0 -0
- {patchshuttle-0.1.0a6 → patchshuttle-0.1.0a7}/tools/release_checks.py +0 -0
|
@@ -3,6 +3,36 @@
|
|
|
3
3
|
All notable changes to PatchShuttle are recorded in this file. The project
|
|
4
4
|
uses semantic versioning, including Python-compatible pre-release versions.
|
|
5
5
|
|
|
6
|
+
## 0.1.0a7 - release candidate (not yet published)
|
|
7
|
+
|
|
8
|
+
- Audit AI instructions: complete action catalogs, correct method YAML indentation
|
|
9
|
+
and job-ID rules, clarify guard sources, MCP limits and database boundaries.
|
|
10
|
+
|
|
11
|
+
- Add `python_references` for bounded, explicitly unverified symbol-reference
|
|
12
|
+
candidates with import aliases and unresolved attributes.
|
|
13
|
+
|
|
14
|
+
- Add read-only `python_dependencies` for static local import candidates, cycle
|
|
15
|
+
groups and explicitly unresolved/dynamic cases before module refactoring.
|
|
16
|
+
|
|
17
|
+
- Add opt-in, bounded action drafts to symbol/import audits with observed guards;
|
|
18
|
+
fragments require review and never execute during audit.
|
|
19
|
+
|
|
20
|
+
- Add `edit_imports`: 1-100 ordered import edits guarded by one initial import
|
|
21
|
+
hash, with step diagnostics and the existing import safety checks.
|
|
22
|
+
|
|
23
|
+
- Explain structural replacement failures with bounded indentation context and
|
|
24
|
+
YAML guidance, without rewriting input or changing guard semantics.
|
|
25
|
+
|
|
26
|
+
- Add reviewed `docs refresh` for recognized AI guide templates, retaining
|
|
27
|
+
appended owner notes and exact backups; unknown inline edits require review.
|
|
28
|
+
- Add conditional Python symbol-edit guidance to CLI plans, full and compact
|
|
29
|
+
logs, including targeting failures; advisory does not alter guards or policy.
|
|
30
|
+
- Add operation-selection rules and an audit-to-patch example to AI guidance.
|
|
31
|
+
- Prefer configured MCP history retrieval, retaining manual logs as fallback.
|
|
32
|
+
- Count symbol/range transfers and report structural imports and file moves.
|
|
33
|
+
- Extract plan and discovery-log presentation into smaller modules without
|
|
34
|
+
relaxing the existing architecture ratchet.
|
|
35
|
+
|
|
6
36
|
## 0.1.0a6 - 2026-10-21
|
|
7
37
|
|
|
8
38
|
### Added
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: patchshuttle
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.0a7
|
|
4
4
|
Summary: Local, auditable patch workflows for AI-assisted software development
|
|
5
5
|
License-Expression: MIT
|
|
6
6
|
License-File: LICENSE
|
|
@@ -50,7 +50,8 @@ describes a small job, the user reviews and runs it locally, and PatchShuttle
|
|
|
50
50
|
records the result for the next iteration.
|
|
51
51
|
|
|
52
52
|
> [!IMPORTANT]
|
|
53
|
-
> PatchShuttle is alpha software.
|
|
53
|
+
> PatchShuttle is alpha software. This branch prepares `0.1.0a7`; the latest
|
|
54
|
+
> recorded published version is `0.1.0a6`. It implements the complete
|
|
54
55
|
> local v0.1 workflow. It executes bounded read-only
|
|
55
56
|
> audits, approved patch transactions, and approved one-pass verification jobs
|
|
56
57
|
> under a project lock. Patch jobs retain backups, run controlled checks, apply
|
|
@@ -483,7 +484,8 @@ retained formatted-file states, final check results, audit observations, and a
|
|
|
483
484
|
workspace comparison where applicable.
|
|
484
485
|
|
|
485
486
|
An audit executes `tree`, `read`, literal `search`, bounded `search_context`,
|
|
486
|
-
Python `read_symbol`, `
|
|
487
|
+
Python `read_symbol`, `read_imports`, `python_structure`, `python_dependencies`,
|
|
488
|
+
`python_references`, `find_files`, `file_info`, SHA-256 `hash`, canonical
|
|
487
489
|
`hash_range`, `git_status`, and `environment`. Traversal, file reads, match
|
|
488
490
|
counts, and recorded output are bounded by local policy. Protected and ignored
|
|
489
491
|
paths are skipped, source content appears only when explicitly requested by a
|
|
@@ -503,7 +505,8 @@ automatically undo those changes.
|
|
|
503
505
|
|
|
504
506
|
A patch plan may contain `create_directory`, `create_file`, `replace_exact`,
|
|
505
507
|
`replace_symbol`, `insert_before`, `insert_after`, `delete_exact`,
|
|
506
|
-
`replace_range`, `delete_range`, `insert_at_line`,
|
|
508
|
+
`replace_range`, `delete_range`, `insert_at_line`, `apply_diff`, `ensure_import`,
|
|
509
|
+
`remove_import`, `edit_imports`, `move_file`, `move_range`, or `move_symbol` actions and
|
|
507
510
|
applies the final bytes already computed by the planner.
|
|
508
511
|
|
|
509
512
|
The optional line-range actions are strict guarded operations for cases where
|
|
@@ -764,18 +767,19 @@ actions:
|
|
|
764
767
|
symbol: Service.run
|
|
765
768
|
```
|
|
766
769
|
|
|
767
|
-
If a change is needed,
|
|
768
|
-
|
|
770
|
+
If a change is needed, use the audit-derived draft or copy `ast_sha256` from
|
|
771
|
+
`read_symbol` on the same Python minor version. Add its text `sha256` too when
|
|
772
|
+
comments must be guarded. The action below is illustrative:
|
|
769
773
|
|
|
770
774
|
```yaml
|
|
771
775
|
actions:
|
|
772
776
|
- replace_symbol:
|
|
773
777
|
path: src/example/service.py
|
|
774
778
|
symbol: Service.run
|
|
775
|
-
|
|
776
|
-
new_content: |
|
|
777
|
-
|
|
778
|
-
|
|
779
|
+
expected_ast_sha256: 0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef
|
|
780
|
+
new_content: |2
|
|
781
|
+
def run(self, value):
|
|
782
|
+
return value
|
|
779
783
|
```
|
|
780
784
|
|
|
781
785
|
The same audit can be constructed through the public Python adapter:
|
|
@@ -891,7 +895,7 @@ python -m coverage report --fail-under=100
|
|
|
891
895
|
python -m build
|
|
892
896
|
python -m twine check dist/*
|
|
893
897
|
python tools/release_checks.py dist
|
|
894
|
-
python tools/wheel_smoke.py dist/patchshuttle-0.1.
|
|
898
|
+
python tools/wheel_smoke.py dist/patchshuttle-0.1.0a7-py3-none-any.whl --version 0.1.0a7
|
|
895
899
|
```
|
|
896
900
|
|
|
897
901
|
The `0.1.0a2`, `0.1.0a3`, and `0.1.0a4` alpha releases each passed the
|
|
@@ -1009,7 +1013,9 @@ The implemented local cycle is:
|
|
|
1009
1013
|
5. For a patch, run optional changed-HTML linting, controlled checks, the
|
|
1010
1014
|
locally resolved isort/Black scopes, and final checks.
|
|
1011
1015
|
6. Receive a timestamped log or generate a fresh handoff.
|
|
1012
|
-
7.
|
|
1016
|
+
7. Retrieve configured MCP history or provide the log through an authorized
|
|
1017
|
+
channel. Current MCP history returns summaries/references, not full logs.
|
|
1018
|
+
Review the observed result before continuing with the next job.
|
|
1013
1019
|
|
|
1014
1020
|
See [SPEC_V0_1.md](SPEC_V0_1.md) for the approved product contract and
|
|
1015
1021
|
[CHANGELOG.md](CHANGELOG.md) for release notes. PatchShuttle is designed for
|
|
@@ -1080,3 +1086,18 @@ owner-configured authenticated MCP server (`patchshuttle[mcp]`).
|
|
|
1080
1086
|
Optional [Django migrations](docs/DJANGO_MIGRATIONS.md) provide reviewed plans,
|
|
1081
1087
|
locks and recovery journals (`patchshuttle[django]`). A live ChatGPT deployment
|
|
1082
1088
|
requires the owner's HTTPS endpoint and OAuth configuration.
|
|
1089
|
+
|
|
1090
|
+
|
|
1091
|
+
## AI workflow in a7 development
|
|
1092
|
+
|
|
1093
|
+
Start with the installed capabilities/schema and the workspace handoff. The
|
|
1094
|
+
[AI guide](src/patchshuttle/resources/AI_GUIDE.md) contains the operation decision
|
|
1095
|
+
table, guard sources, refactoring checklist and recovery boundaries. Existing
|
|
1096
|
+
Python declaration edits should normally use `read_symbol` then `replace_symbol`;
|
|
1097
|
+
request `include_template: true` for a guarded draft. Use `edit_imports` for a
|
|
1098
|
+
sequence of import edits. Keep audits separate from patches and review actual
|
|
1099
|
+
execution outcomes. The explicit `|2` in the method example preserves Python
|
|
1100
|
+
indentation after YAML parsing. Documentation examples use illustrative bodies
|
|
1101
|
+
and hashes; replace these with observed source and guards before submitting.
|
|
1102
|
+
|
|
1103
|
+
This section describes the development branch, not a published a7 release.
|
|
@@ -6,7 +6,8 @@ describes a small job, the user reviews and runs it locally, and PatchShuttle
|
|
|
6
6
|
records the result for the next iteration.
|
|
7
7
|
|
|
8
8
|
> [!IMPORTANT]
|
|
9
|
-
> PatchShuttle is alpha software.
|
|
9
|
+
> PatchShuttle is alpha software. This branch prepares `0.1.0a7`; the latest
|
|
10
|
+
> recorded published version is `0.1.0a6`. It implements the complete
|
|
10
11
|
> local v0.1 workflow. It executes bounded read-only
|
|
11
12
|
> audits, approved patch transactions, and approved one-pass verification jobs
|
|
12
13
|
> under a project lock. Patch jobs retain backups, run controlled checks, apply
|
|
@@ -439,7 +440,8 @@ retained formatted-file states, final check results, audit observations, and a
|
|
|
439
440
|
workspace comparison where applicable.
|
|
440
441
|
|
|
441
442
|
An audit executes `tree`, `read`, literal `search`, bounded `search_context`,
|
|
442
|
-
Python `read_symbol`, `
|
|
443
|
+
Python `read_symbol`, `read_imports`, `python_structure`, `python_dependencies`,
|
|
444
|
+
`python_references`, `find_files`, `file_info`, SHA-256 `hash`, canonical
|
|
443
445
|
`hash_range`, `git_status`, and `environment`. Traversal, file reads, match
|
|
444
446
|
counts, and recorded output are bounded by local policy. Protected and ignored
|
|
445
447
|
paths are skipped, source content appears only when explicitly requested by a
|
|
@@ -459,7 +461,8 @@ automatically undo those changes.
|
|
|
459
461
|
|
|
460
462
|
A patch plan may contain `create_directory`, `create_file`, `replace_exact`,
|
|
461
463
|
`replace_symbol`, `insert_before`, `insert_after`, `delete_exact`,
|
|
462
|
-
`replace_range`, `delete_range`, `insert_at_line`,
|
|
464
|
+
`replace_range`, `delete_range`, `insert_at_line`, `apply_diff`, `ensure_import`,
|
|
465
|
+
`remove_import`, `edit_imports`, `move_file`, `move_range`, or `move_symbol` actions and
|
|
463
466
|
applies the final bytes already computed by the planner.
|
|
464
467
|
|
|
465
468
|
The optional line-range actions are strict guarded operations for cases where
|
|
@@ -720,18 +723,19 @@ actions:
|
|
|
720
723
|
symbol: Service.run
|
|
721
724
|
```
|
|
722
725
|
|
|
723
|
-
If a change is needed,
|
|
724
|
-
|
|
726
|
+
If a change is needed, use the audit-derived draft or copy `ast_sha256` from
|
|
727
|
+
`read_symbol` on the same Python minor version. Add its text `sha256` too when
|
|
728
|
+
comments must be guarded. The action below is illustrative:
|
|
725
729
|
|
|
726
730
|
```yaml
|
|
727
731
|
actions:
|
|
728
732
|
- replace_symbol:
|
|
729
733
|
path: src/example/service.py
|
|
730
734
|
symbol: Service.run
|
|
731
|
-
|
|
732
|
-
new_content: |
|
|
733
|
-
|
|
734
|
-
|
|
735
|
+
expected_ast_sha256: 0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef
|
|
736
|
+
new_content: |2
|
|
737
|
+
def run(self, value):
|
|
738
|
+
return value
|
|
735
739
|
```
|
|
736
740
|
|
|
737
741
|
The same audit can be constructed through the public Python adapter:
|
|
@@ -847,7 +851,7 @@ python -m coverage report --fail-under=100
|
|
|
847
851
|
python -m build
|
|
848
852
|
python -m twine check dist/*
|
|
849
853
|
python tools/release_checks.py dist
|
|
850
|
-
python tools/wheel_smoke.py dist/patchshuttle-0.1.
|
|
854
|
+
python tools/wheel_smoke.py dist/patchshuttle-0.1.0a7-py3-none-any.whl --version 0.1.0a7
|
|
851
855
|
```
|
|
852
856
|
|
|
853
857
|
The `0.1.0a2`, `0.1.0a3`, and `0.1.0a4` alpha releases each passed the
|
|
@@ -965,7 +969,9 @@ The implemented local cycle is:
|
|
|
965
969
|
5. For a patch, run optional changed-HTML linting, controlled checks, the
|
|
966
970
|
locally resolved isort/Black scopes, and final checks.
|
|
967
971
|
6. Receive a timestamped log or generate a fresh handoff.
|
|
968
|
-
7.
|
|
972
|
+
7. Retrieve configured MCP history or provide the log through an authorized
|
|
973
|
+
channel. Current MCP history returns summaries/references, not full logs.
|
|
974
|
+
Review the observed result before continuing with the next job.
|
|
969
975
|
|
|
970
976
|
See [SPEC_V0_1.md](SPEC_V0_1.md) for the approved product contract and
|
|
971
977
|
[CHANGELOG.md](CHANGELOG.md) for release notes. PatchShuttle is designed for
|
|
@@ -1036,3 +1042,18 @@ owner-configured authenticated MCP server (`patchshuttle[mcp]`).
|
|
|
1036
1042
|
Optional [Django migrations](docs/DJANGO_MIGRATIONS.md) provide reviewed plans,
|
|
1037
1043
|
locks and recovery journals (`patchshuttle[django]`). A live ChatGPT deployment
|
|
1038
1044
|
requires the owner's HTTPS endpoint and OAuth configuration.
|
|
1045
|
+
|
|
1046
|
+
|
|
1047
|
+
## AI workflow in a7 development
|
|
1048
|
+
|
|
1049
|
+
Start with the installed capabilities/schema and the workspace handoff. The
|
|
1050
|
+
[AI guide](src/patchshuttle/resources/AI_GUIDE.md) contains the operation decision
|
|
1051
|
+
table, guard sources, refactoring checklist and recovery boundaries. Existing
|
|
1052
|
+
Python declaration edits should normally use `read_symbol` then `replace_symbol`;
|
|
1053
|
+
request `include_template: true` for a guarded draft. Use `edit_imports` for a
|
|
1054
|
+
sequence of import edits. Keep audits separate from patches and review actual
|
|
1055
|
+
execution outcomes. The explicit `|2` in the method example preserves Python
|
|
1056
|
+
indentation after YAML parsing. Documentation examples use illustrative bodies
|
|
1057
|
+
and hashes; replace these with observed source and guards before submitting.
|
|
1058
|
+
|
|
1059
|
+
This section describes the development branch, not a published a7 release.
|
|
@@ -1,7 +1,29 @@
|
|
|
1
1
|
# Next release: structural editing and controlled refactoring
|
|
2
2
|
|
|
3
|
-
Status: 0.1.0a6
|
|
4
|
-
|
|
3
|
+
Status: 0.1.0a6 published; see RELEASE.md for immutable publication evidence.
|
|
4
|
+
The sections below describe a6 scope and remaining work.
|
|
5
|
+
|
|
6
|
+
## 0.1.0a7 release candidate
|
|
7
|
+
|
|
8
|
+
Implemented a7 scope:
|
|
9
|
+
|
|
10
|
+
- Python operation-selection rules and conditional advisory feedback in plans,
|
|
11
|
+
full/compact logs and handoff; transfer/import telemetry.
|
|
12
|
+
- Reviewed `docs refresh` for recognized AI guide templates, preserving appended
|
|
13
|
+
owner notes and backups; inline customizations still require manual review.
|
|
14
|
+
- Bounded indentation diagnostics for structural replacements.
|
|
15
|
+
- `edit_imports`: ordered import changes with one initial import-set guard.
|
|
16
|
+
- Optional `include_template` drafts from `read_symbol` and `read_imports`.
|
|
17
|
+
- Read-only `python_dependencies` and `python_references` for bounded static
|
|
18
|
+
dependency/cycle and unverified reference candidates. No automatic rewrites.
|
|
19
|
+
- Audited AI guide, handoff, protocol and CLI explanations, with executable
|
|
20
|
+
YAML example tests and action-catalog checks.
|
|
21
|
+
|
|
22
|
+
No a7 publication is recorded yet. Source version is now `0.1.0a7` for candidate
|
|
23
|
+
qualification. Final commit CI, TestPyPI and production publication gates remain
|
|
24
|
+
required before recording this version as released.
|
|
25
|
+
See ROADMAP.md for the broader backlog. The following sections record the a6
|
|
26
|
+
foundation and its remaining limitations, not additional a7 completion claims.
|
|
5
27
|
|
|
6
28
|
## Implemented in this branch
|
|
7
29
|
|
|
@@ -28,7 +50,7 @@ This is AST-selected source replacement, not AST unparse of the whole file.
|
|
|
28
50
|
path: services/offers.py
|
|
29
51
|
symbol: OfferService.calculate
|
|
30
52
|
expected_ast_sha256: "<64 hex digits from read_symbol>"
|
|
31
|
-
new_content: |
|
|
53
|
+
new_content: |2
|
|
32
54
|
def calculate(self, amount):
|
|
33
55
|
return amount * 2
|
|
34
56
|
```
|
|
@@ -166,5 +188,6 @@ module is compiled without importing or executing it.
|
|
|
166
188
|
|
|
167
189
|
Unrelated source remains intact before the normal scoped formatter phase.
|
|
168
190
|
Neither action rewrites callers, proves runtime compatibility, nor infers
|
|
169
|
-
imports when moving files or symbols.
|
|
170
|
-
|
|
191
|
+
imports when moving files or symbols. Separate import actions need the hash of each simulated intermediate import
|
|
192
|
+
set, or separate audited jobs. In a7, prefer `edit_imports` for multiple ordered
|
|
193
|
+
changes: its guard targets the import set at entry to that action.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# PatchShuttle release guide
|
|
2
2
|
|
|
3
|
-
This guide records
|
|
3
|
+
This guide records immutable published release evidence through `0.1.0a6` and
|
|
4
4
|
the staged qualification procedure for later releases. Do not publish a
|
|
5
5
|
stable `0.1.0` release until every acceptance criterion in `SPEC_V0_1.md` has
|
|
6
6
|
passed and the stable release is approved.
|
|
@@ -158,7 +158,7 @@ python tools/wheel_smoke.py dist/patchshuttle-<VERSION>-py3-none-any.whl --versi
|
|
|
158
158
|
`release_checks.py` requires exactly one wheel and one source archive for the
|
|
159
159
|
source version and writes `dist/SHA256SUMS`. Replace `<VERSION>` with the exact
|
|
160
160
|
source version under qualification. For the most recent recorded qualification it
|
|
161
|
-
was `0.1.
|
|
161
|
+
was `0.1.0a6`. Do not reuse an immutable published version for a future upload.
|
|
162
162
|
|
|
163
163
|
During a source-version transition, metadata in an already-installed editable
|
|
164
164
|
environment may still report the previous version until the package is
|
|
@@ -181,7 +181,8 @@ logs must keep exposing resolved formatter and architecture decisions.
|
|
|
181
181
|
3. Do not upload `.venv/`, caches, previous phase archives, or local runtime
|
|
182
182
|
`patches/` directories.
|
|
183
183
|
4. Push the default branch and wait for the `CI` workflow.
|
|
184
|
-
5. Require all five matrix jobs
|
|
184
|
+
5. Require all five matrix jobs, the PostgreSQL integration job and the package
|
|
185
|
+
job to pass before publishing.
|
|
185
186
|
|
|
186
187
|
The required matrix is Ubuntu/Python 3.10, 3.12, and 3.14 plus
|
|
187
188
|
Windows/Python 3.12 and 3.14. A local Linux result does not replace these jobs.
|
|
@@ -252,15 +253,40 @@ statement also requires a separate recorded ChatGPT end-to-end workflow using
|
|
|
252
253
|
that released protocol and must state the tested scope.
|
|
253
254
|
|
|
254
255
|
|
|
255
|
-
## 0.1.0a6
|
|
256
|
+
## Recorded `0.1.0a6` qualification
|
|
257
|
+
|
|
258
|
+
Published on 2026-10-22 from immutable tag `v0.1.0a6`, resolving to
|
|
259
|
+
`831dc2a8b4342150785a227a4834e5c1efdfc5be`.
|
|
256
260
|
|
|
257
|
-
Source candidate prepared on 2026-10-21. This is not a publication record.
|
|
258
261
|
Scope: AST-guarded symbol/import edits, guarded file/range/symbol transfers,
|
|
259
262
|
UTF-8 formatter subprocesses, optional authenticated MCP history retrieval,
|
|
260
263
|
and an optional Django migration command with reviewed plans and journals.
|
|
261
264
|
The owner must configure the live HTTPS/OAuth deployment separately.
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
265
|
+
Refactoring does not automatically rewrite callers or infer dependencies;
|
|
266
|
+
database recovery requires explicit owner review rather than automatic rollback.
|
|
267
|
+
|
|
268
|
+
External gates completed successfully:
|
|
269
|
+
|
|
270
|
+
- [main CI: all seven jobs](https://github.com/ratundo/patchshuttle/actions/runs/39643741606),
|
|
271
|
+
including Ubuntu, Windows, PostgreSQL 16 and clean-wheel checks;
|
|
272
|
+
- [tag CI](https://github.com/ratundo/patchshuttle/actions/runs/39741537873);
|
|
273
|
+
- [TestPyPI build, publish and clean-index verification](https://github.com/ratundo/patchshuttle/actions/runs/39740928641);
|
|
274
|
+
- [GitHub pre-release](https://github.com/ratundo/patchshuttle/releases/tag/v0.1.0a6);
|
|
275
|
+
- [PyPI build, publish and clean-index verification](https://github.com/ratundo/patchshuttle/actions/runs/39741537464),
|
|
276
|
+
with `INDEX_SMOKE_OK pypi 0.1.0a6`;
|
|
277
|
+
- [PyPI version](https://pypi.org/project/patchshuttle/0.1.0a6/).
|
|
278
|
+
|
|
279
|
+
The qualified suite passed 1,112 tests with 100% statement and branch coverage.
|
|
280
|
+
Windows pytest and coverage-report steps are separate so a later successful
|
|
281
|
+
native command cannot mask a failed test command.
|
|
282
|
+
|
|
283
|
+
The TestPyPI and production PyPI JSON APIs independently reported byte-identical
|
|
284
|
+
artifacts (matching sizes and SHA-256 digests):
|
|
285
|
+
|
|
286
|
+
- `patchshuttle-0.1.0a6-py3-none-any.whl`, 202331 bytes:
|
|
287
|
+
`fd83e54be01115af1217d56ae73bd7cf2c8880ce79b84a7fd7d5b06678efb92f`;
|
|
288
|
+
- `patchshuttle-0.1.0a6.tar.gz`, 355211 bytes:
|
|
289
|
+
`15654537705304ab843ba6cfa5d615900420efd2f6ebefc83b28ca7d64da8c91`.
|
|
290
|
+
|
|
291
|
+
This publication record does not extend the separately scoped a2
|
|
292
|
+
**Tested with ChatGPT** claim or claim deployment of a live MCP endpoint.
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# Development roadmap after 0.1.0a6
|
|
2
|
+
|
|
3
|
+
This is a backlog, not a statement that every item ships in a7.
|
|
4
|
+
Published a6 evidence remains in RELEASE.md. Source version stays a6 until
|
|
5
|
+
an a7 candidate is qualified; no a7 package has been published.
|
|
6
|
+
|
|
7
|
+
## First a7 milestone
|
|
8
|
+
|
|
9
|
+
Implemented locally: conditional symbol-edit advisory in plans/full/compact logs,
|
|
10
|
+
operation selection rules, handoff example, MCP-aware retrieval guidance,
|
|
11
|
+
transfer/import telemetry, and smaller presentation modules.
|
|
12
|
+
The first guidance milestone passed hosted Linux/Windows/PostgreSQL CI.
|
|
13
|
+
Guide refresh now supports reviewed updates of recognized current/a4/a5/a6
|
|
14
|
+
templates with appended notes, hashes and backups; inline customizations require
|
|
15
|
+
manual review.
|
|
16
|
+
Guide refresh passed hosted CI. Structural replacement failures now include
|
|
17
|
+
bounded indentation context and YAML guidance; input is never reindented.
|
|
18
|
+
Indentation diagnostics passed both hosted CI runs. Batch import editing with
|
|
19
|
+
one initial guard is implemented; qualification is in progress.
|
|
20
|
+
Batch imports passed hosted CI. Opt-in audit-derived action drafts are
|
|
21
|
+
implemented. Static module-import dependency auditing is implemented;
|
|
22
|
+
dependency auditing passed hosted CI. Syntactic symbol-reference candidates
|
|
23
|
+
are implemented; binding-aware resolution, rewrites and release qualification
|
|
24
|
+
remain pending.
|
|
25
|
+
|
|
26
|
+
## Subsequent work, in priority order
|
|
27
|
+
|
|
28
|
+
1. Synchronize AI guide, protocol and explain output; detect stale generated
|
|
29
|
+
guides and support reviewed refresh preserving owner additions.
|
|
30
|
+
2. Batch import edits with one initial guard; audit-derived action templates;
|
|
31
|
+
explain conflicts with initial versus simulated intermediate state.
|
|
32
|
+
3. Static dependency/reference analysis before moves, unresolved dynamic cases,
|
|
33
|
+
import-cycle reporting, reviewed updates and optional compatibility reexports.
|
|
34
|
+
4. End-to-end refactors: rename symbols/modules, extract selected declarations,
|
|
35
|
+
move groups into packages, report architecture before/after.
|
|
36
|
+
5. Extend transfers: same-file moves, multiple destinations/anchors, move chains,
|
|
37
|
+
case-only renames, binary files, multi-alias and selected conditional imports.
|
|
38
|
+
6. Improve indentation diagnostics; evaluate explicit dedented input and CST
|
|
39
|
+
for targeted edits while preserving multiline-string semantics.
|
|
40
|
+
7. Deploy and test read-only MCP with real owner HTTPS/OAuth configuration;
|
|
41
|
+
retrieve bounded diagnostics and the separate migration journal.
|
|
42
|
+
8. Migration data checks, partial-success reports, recovery integration and
|
|
43
|
+
imported-helper identity. Do not claim file/database atomic rollback.
|
|
44
|
+
9. Reproduce the owner's original Windows isort error and add a regression test;
|
|
45
|
+
cover Cyrillic paths, CRLF/BOM and subprocess output encodings.
|
|
46
|
+
10. Benchmark discovery/planning/checks/output size/retries before optimizing
|
|
47
|
+
AST reuse, traversal or owner-configured focused check profiles.
|
|
48
|
+
11. Maintain reproducible dogfooding tasks with model/instruction versions,
|
|
49
|
+
input state, timings, attempt counts, outputs and recovery outcomes.
|
|
50
|
+
|
|
51
|
+
## Release gates
|
|
52
|
+
|
|
53
|
+
Formatting, meaningful regression tests, full statement/branch coverage,
|
|
54
|
+
Ubuntu/Windows/PostgreSQL CI, build and clean-wheel checks, TestPyPI verification,
|
|
55
|
+
then a tagged GitHub prerelease and PyPI verification. Record evidence only after
|
|
56
|
+
completion. Do not weaken guards or architecture policy to pass these gates.
|
|
@@ -11,8 +11,10 @@ from patchshuttle.models import Job
|
|
|
11
11
|
_TEXT_ACTIONS = frozenset(
|
|
12
12
|
{"delete_exact", "insert_after", "insert_before", "replace_exact"}
|
|
13
13
|
)
|
|
14
|
-
_SYMBOL_ACTIONS = frozenset({"replace_symbol"})
|
|
15
|
-
_LINE_ACTIONS = frozenset(
|
|
14
|
+
_SYMBOL_ACTIONS = frozenset({"replace_symbol", "move_symbol"})
|
|
15
|
+
_LINE_ACTIONS = frozenset(
|
|
16
|
+
{"delete_range", "insert_at_line", "replace_range", "move_range"}
|
|
17
|
+
)
|
|
16
18
|
_FAILURE_SIGNALS = {
|
|
17
19
|
"LINE_RANGE_GUARD_MISMATCH": "LINE_TARGETING_FAILURE",
|
|
18
20
|
"LINE_RANGE_OUT_OF_BOUNDS": "LINE_TARGETING_FAILURE",
|
|
@@ -47,6 +49,8 @@ class PythonDiscoveryEvaluation:
|
|
|
47
49
|
declared_python_line_actions: int
|
|
48
50
|
failure_signal: str | None
|
|
49
51
|
reason_codes: tuple[str, ...]
|
|
52
|
+
declared_python_import_actions: int = 0
|
|
53
|
+
declared_python_file_move_actions: int = 0
|
|
50
54
|
|
|
51
55
|
|
|
52
56
|
def evaluate_python_discovery(
|
|
@@ -77,6 +81,8 @@ def evaluate_python_discovery(
|
|
|
77
81
|
declared_python_symbol_actions = 0
|
|
78
82
|
declared_python_line_actions = 0
|
|
79
83
|
|
|
84
|
+
import_actions = 0
|
|
85
|
+
file_moves = 0
|
|
80
86
|
for index, action in enumerate(job.actions, start=1):
|
|
81
87
|
name = action.name
|
|
82
88
|
parameters = action.parameters
|
|
@@ -118,6 +124,10 @@ def evaluate_python_discovery(
|
|
|
118
124
|
|
|
119
125
|
if not python_targeted:
|
|
120
126
|
continue
|
|
127
|
+
if name in {"ensure_import", "remove_import", "edit_imports"}:
|
|
128
|
+
import_actions += 1
|
|
129
|
+
if name == "move_file":
|
|
130
|
+
file_moves += 1
|
|
121
131
|
if name in _TEXT_ACTIONS:
|
|
122
132
|
declared_python_text_actions += 1
|
|
123
133
|
elif name in _SYMBOL_ACTIONS:
|
|
@@ -142,6 +152,8 @@ def evaluate_python_discovery(
|
|
|
142
152
|
declared_python_line_actions=declared_python_line_actions,
|
|
143
153
|
failure_signal=failure_signal,
|
|
144
154
|
)
|
|
155
|
+
reason_codes += ("PYTHON_IMPORT_TARGETING_USED",) if import_actions else ()
|
|
156
|
+
reason_codes += ("PYTHON_FILE_MOVE_USED",) if file_moves else ()
|
|
145
157
|
applicable = bool(python_paths or reason_codes)
|
|
146
158
|
return PythonDiscoveryEvaluation(
|
|
147
159
|
applicable=applicable,
|
|
@@ -164,6 +176,8 @@ def evaluate_python_discovery(
|
|
|
164
176
|
declared_python_line_actions=declared_python_line_actions,
|
|
165
177
|
failure_signal=failure_signal,
|
|
166
178
|
reason_codes=reason_codes,
|
|
179
|
+
declared_python_import_actions=import_actions,
|
|
180
|
+
declared_python_file_move_actions=file_moves,
|
|
167
181
|
)
|
|
168
182
|
|
|
169
183
|
|
|
@@ -10,6 +10,7 @@ from patchshuttle.actions.constructors import (
|
|
|
10
10
|
create_file,
|
|
11
11
|
delete_exact,
|
|
12
12
|
delete_range,
|
|
13
|
+
edit_imports,
|
|
13
14
|
ensure_import,
|
|
14
15
|
environment,
|
|
15
16
|
file_info,
|
|
@@ -23,6 +24,8 @@ from patchshuttle.actions.constructors import (
|
|
|
23
24
|
move_file,
|
|
24
25
|
move_range,
|
|
25
26
|
move_symbol,
|
|
27
|
+
python_dependencies,
|
|
28
|
+
python_references,
|
|
26
29
|
python_structure,
|
|
27
30
|
read,
|
|
28
31
|
read_imports,
|
|
@@ -91,8 +94,11 @@ __all__ = [
|
|
|
91
94
|
"read",
|
|
92
95
|
"read_symbol",
|
|
93
96
|
"read_imports",
|
|
97
|
+
"edit_imports",
|
|
94
98
|
"ensure_import",
|
|
95
99
|
"remove_import",
|
|
100
|
+
"python_references",
|
|
101
|
+
"python_dependencies",
|
|
96
102
|
"python_structure",
|
|
97
103
|
"move_file",
|
|
98
104
|
"move_range",
|
|
@@ -86,8 +86,9 @@ def read_symbol(
|
|
|
86
86
|
symbol: str,
|
|
87
87
|
*,
|
|
88
88
|
max_bytes: int | None = None,
|
|
89
|
+
include_template: bool = False,
|
|
89
90
|
) -> Action:
|
|
90
|
-
parameters = {"path": path, "symbol": symbol}
|
|
91
|
+
parameters = {"path": path, "symbol": symbol, "include_template": include_template}
|
|
91
92
|
if max_bytes is not None:
|
|
92
93
|
parameters["max_bytes"] = max_bytes
|
|
93
94
|
return Action({"read_symbol": parameters})
|
|
@@ -445,8 +446,10 @@ def _add_guards(
|
|
|
445
446
|
parameters["expected_sha256"] = expected_sha256
|
|
446
447
|
|
|
447
448
|
|
|
448
|
-
def read_imports(
|
|
449
|
-
|
|
449
|
+
def read_imports(
|
|
450
|
+
path: str, *, max_bytes: int | None = None, include_template: bool = False
|
|
451
|
+
) -> Action:
|
|
452
|
+
parameters = {"path": path, "include_template": include_template}
|
|
450
453
|
if max_bytes is not None:
|
|
451
454
|
parameters["max_bytes"] = max_bytes
|
|
452
455
|
return Action({"read_imports": parameters})
|
|
@@ -480,8 +483,66 @@ def remove_import(
|
|
|
480
483
|
)
|
|
481
484
|
|
|
482
485
|
|
|
486
|
+
def edit_imports(path: str, edits, *, expected_imports_ast_sha256: str) -> Action:
|
|
487
|
+
"""Apply ordered import edits guarded by the initial simulated import set."""
|
|
488
|
+
return Action(
|
|
489
|
+
{
|
|
490
|
+
"edit_imports": {
|
|
491
|
+
"path": path,
|
|
492
|
+
"edits": edits,
|
|
493
|
+
"expected_imports_ast_sha256": expected_imports_ast_sha256,
|
|
494
|
+
}
|
|
495
|
+
}
|
|
496
|
+
)
|
|
497
|
+
|
|
498
|
+
|
|
499
|
+
def python_dependencies(
|
|
500
|
+
path: str = ".",
|
|
501
|
+
*,
|
|
502
|
+
max_files: int = 300,
|
|
503
|
+
max_findings: int = 2000,
|
|
504
|
+
max_bytes: int = 50000,
|
|
505
|
+
) -> Action:
|
|
506
|
+
return Action(
|
|
507
|
+
{
|
|
508
|
+
"python_dependencies": dict(
|
|
509
|
+
path=path,
|
|
510
|
+
max_files=max_files,
|
|
511
|
+
max_findings=max_findings,
|
|
512
|
+
max_bytes=max_bytes,
|
|
513
|
+
)
|
|
514
|
+
}
|
|
515
|
+
)
|
|
516
|
+
|
|
517
|
+
|
|
518
|
+
def python_references(
|
|
519
|
+
module: str,
|
|
520
|
+
symbol: str,
|
|
521
|
+
*,
|
|
522
|
+
path: str = ".",
|
|
523
|
+
max_files: int = 300,
|
|
524
|
+
max_findings: int = 2000,
|
|
525
|
+
max_bytes: int = 50000,
|
|
526
|
+
) -> Action:
|
|
527
|
+
return Action(
|
|
528
|
+
{
|
|
529
|
+
"python_references": dict(
|
|
530
|
+
module=module,
|
|
531
|
+
symbol=symbol,
|
|
532
|
+
path=path,
|
|
533
|
+
max_files=max_files,
|
|
534
|
+
max_findings=max_findings,
|
|
535
|
+
max_bytes=max_bytes,
|
|
536
|
+
)
|
|
537
|
+
}
|
|
538
|
+
)
|
|
539
|
+
|
|
540
|
+
|
|
483
541
|
__all__ = [
|
|
542
|
+
"python_references",
|
|
543
|
+
"python_dependencies",
|
|
484
544
|
"read_imports",
|
|
545
|
+
"edit_imports",
|
|
485
546
|
"ensure_import",
|
|
486
547
|
"remove_import",
|
|
487
548
|
"apply_diff",
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""Read-only static analysis helpers."""
|