patchshuttle 0.1.0a4__tar.gz → 0.1.0a6__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.0a4 → patchshuttle-0.1.0a6}/.github/workflows/ci.yml +37 -5
- {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a6}/.gitignore +1 -0
- {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a6}/CHANGELOG.md +44 -1
- patchshuttle-0.1.0a4/README.md → patchshuttle-0.1.0a6/PKG-INFO +182 -18
- patchshuttle-0.1.0a4/PKG-INFO → patchshuttle-0.1.0a6/README.md +138 -55
- {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a6}/SPEC_V0_1.md +147 -17
- patchshuttle-0.1.0a6/docs/CHATGPT_INTEGRATION.md +54 -0
- patchshuttle-0.1.0a6/docs/DJANGO_MIGRATIONS.md +83 -0
- patchshuttle-0.1.0a6/docs/NEXT_RELEASE.md +170 -0
- {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a6}/docs/RELEASE.md +61 -8
- {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a6}/pyproject.toml +5 -0
- {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a6}/src/patchshuttle/_architecture.py +3 -1
- {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a6}/src/patchshuttle/_python_symbols.py +13 -1
- patchshuttle-0.1.0a6/src/patchshuttle/_refactor.py +147 -0
- {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a6}/src/patchshuttle/_version.py +1 -1
- {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a6}/src/patchshuttle/actions/__init__.py +14 -0
- {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a6}/src/patchshuttle/actions/constructors.py +108 -2
- {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a6}/src/patchshuttle/actions/create.py +6 -0
- {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a6}/src/patchshuttle/actions/modify.py +12 -0
- {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a6}/src/patchshuttle/audit.py +34 -0
- {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a6}/src/patchshuttle/backup.py +28 -2
- {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a6}/src/patchshuttle/cli.py +6 -8
- {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a6}/src/patchshuttle/config.py +1 -0
- patchshuttle-0.1.0a6/src/patchshuttle/django_app/__init__.py +1 -0
- patchshuttle-0.1.0a6/src/patchshuttle/django_app/management/__init__.py +1 -0
- patchshuttle-0.1.0a6/src/patchshuttle/django_app/management/commands/__init__.py +1 -0
- patchshuttle-0.1.0a6/src/patchshuttle/django_app/management/commands/patchshuttle_migrate.py +50 -0
- patchshuttle-0.1.0a6/src/patchshuttle/django_app/workflow.py +306 -0
- {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a6}/src/patchshuttle/errors.py +4 -0
- {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a6}/src/patchshuttle/execution.py +64 -39
- {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a6}/src/patchshuttle/formatters/runner.py +5 -1
- patchshuttle-0.1.0a6/src/patchshuttle/history/__init__.py +35 -0
- patchshuttle-0.1.0a6/src/patchshuttle/history/cli.py +123 -0
- patchshuttle-0.1.0a6/src/patchshuttle/history/models.py +194 -0
- patchshuttle-0.1.0a6/src/patchshuttle/history/records.py +382 -0
- patchshuttle-0.1.0a6/src/patchshuttle/history/storage.py +370 -0
- patchshuttle-0.1.0a6/src/patchshuttle/integrations/__init__.py +1 -0
- patchshuttle-0.1.0a6/src/patchshuttle/integrations/mcp_server.py +182 -0
- {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a6}/src/patchshuttle/linters/runner.py +1 -1
- {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a6}/src/patchshuttle/logging.py +1 -0
- {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a6}/src/patchshuttle/models.py +114 -4
- {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a6}/src/patchshuttle/operations.py +41 -34
- {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a6}/src/patchshuttle/planner.py +248 -187
- patchshuttle-0.1.0a6/src/patchshuttle/planning/__init__.py +1 -0
- patchshuttle-0.1.0a6/src/patchshuttle/planning/imports.py +184 -0
- patchshuttle-0.1.0a6/src/patchshuttle/planning/types.py +194 -0
- {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a6}/src/patchshuttle/preflight.py +2 -0
- {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a6}/src/patchshuttle/resources/AI_GUIDE.md +107 -0
- {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a6}/src/patchshuttle/resources/PATCHSHUTTLE_PROTOCOL.md +112 -2
- {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a6}/src/patchshuttle/rollback.py +6 -0
- {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a6}/src/patchshuttle/runner.py +18 -18
- {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a6}/src/patchshuttle/selfdoc.py +33 -3
- patchshuttle-0.1.0a6/tests/integrations/test_django_migrations.py +356 -0
- patchshuttle-0.1.0a6/tests/integrations/test_imports.py +186 -0
- patchshuttle-0.1.0a6/tests/integrations/test_mcp_server.py +242 -0
- patchshuttle-0.1.0a6/tests/unit/history/test_history.py +373 -0
- patchshuttle-0.1.0a6/tests/unit/history/test_history_integration.py +225 -0
- patchshuttle-0.1.0a6/tests/unit/history/test_history_storage_edges.py +292 -0
- {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a6}/tests/unit/test_cli.py +2 -2
- {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a6}/tests/unit/test_formatters.py +4 -0
- patchshuttle-0.1.0a6/tests/unit/test_move_file.py +217 -0
- {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a6}/tests/unit/test_package.py +1 -1
- {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a6}/tests/unit/test_preflight.py +2 -0
- patchshuttle-0.1.0a6/tests/unit/test_refactor.py +330 -0
- {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a6}/tests/unit/test_release_configuration.py +23 -3
- {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a6}/tests/unit/test_selfdoc.py +1 -1
- patchshuttle-0.1.0a6/tests/unit/test_structural_guards.py +251 -0
- patchshuttle-0.1.0a6/tools/django_postgres_smoke.py +88 -0
- {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a6}/tools/release_checks.py +5 -0
- {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a6}/tools/wheel_smoke.py +6 -0
- {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a6}/.github/workflows/release.yml +0 -0
- {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a6}/.github/workflows/testpypi.yml +0 -0
- {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a6}/LICENSE +0 -0
- {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a6}/SECURITY.md +0 -0
- {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a6}/src/patchshuttle/__init__.py +0 -0
- {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a6}/src/patchshuttle/_ai_log.py +0 -0
- {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a6}/src/patchshuttle/_diff.py +0 -0
- {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a6}/src/patchshuttle/_html_lint.py +0 -0
- {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a6}/src/patchshuttle/_line_ranges.py +0 -0
- {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a6}/src/patchshuttle/_process.py +0 -0
- {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a6}/src/patchshuttle/_python_discovery.py +0 -0
- {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a6}/src/patchshuttle/_python_structure.py +0 -0
- {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a6}/src/patchshuttle/checks/__init__.py +0 -0
- {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a6}/src/patchshuttle/checks/constructors.py +0 -0
- {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a6}/src/patchshuttle/checks/runner.py +0 -0
- {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a6}/src/patchshuttle/context.py +0 -0
- {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a6}/src/patchshuttle/formatter_policy.py +0 -0
- {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a6}/src/patchshuttle/formatters/__init__.py +0 -0
- {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a6}/src/patchshuttle/identifiers.py +0 -0
- {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a6}/src/patchshuttle/inventory.py +0 -0
- {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a6}/src/patchshuttle/linters/__init__.py +0 -0
- {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a6}/src/patchshuttle/parser.py +0 -0
- {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a6}/src/patchshuttle/policy.py +0 -0
- {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a6}/src/patchshuttle/project_python.py +0 -0
- {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a6}/src/patchshuttle/py.typed +0 -0
- {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a6}/src/patchshuttle/registry.py +0 -0
- {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a6}/src/patchshuttle/resources/AUDIT-EXAMPLE.psh.yaml +0 -0
- {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a6}/src/patchshuttle/resources/PATCH-EXAMPLE.psh.yaml +0 -0
- {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a6}/src/patchshuttle/resources/__init__.py +0 -0
- {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a6}/src/patchshuttle/runtime_cache.py +0 -0
- {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a6}/src/patchshuttle/verification.py +0 -0
- {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a6}/src/patchshuttle/warning_baseline.py +0 -0
- {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a6}/src/patchshuttle/workspace.py +0 -0
- {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a6}/tests/e2e/test_cli_project_cycle.py +0 -0
- {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a6}/tests/integration/test_workflows.py +0 -0
- {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a6}/tests/unit/test_a4_coverage_regressions.py +0 -0
- {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a6}/tests/unit/test_actions.py +0 -0
- {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a6}/tests/unit/test_ai_log.py +0 -0
- {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a6}/tests/unit/test_architecture.py +0 -0
- {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a6}/tests/unit/test_attempt_logging.py +0 -0
- {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a6}/tests/unit/test_audit_verify_execution.py +0 -0
- {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a6}/tests/unit/test_backup.py +0 -0
- {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a6}/tests/unit/test_change_transaction.py +0 -0
- {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a6}/tests/unit/test_check_transaction.py +0 -0
- {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a6}/tests/unit/test_checks.py +0 -0
- {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a6}/tests/unit/test_config.py +0 -0
- {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a6}/tests/unit/test_context_and_constructors.py +0 -0
- {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a6}/tests/unit/test_diff.py +0 -0
- {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a6}/tests/unit/test_execution.py +0 -0
- {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a6}/tests/unit/test_formatting_transaction.py +0 -0
- {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a6}/tests/unit/test_guarded_ranges.py +0 -0
- {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a6}/tests/unit/test_html_lint.py +0 -0
- {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a6}/tests/unit/test_identifiers.py +0 -0
- {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a6}/tests/unit/test_inventory.py +0 -0
- {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a6}/tests/unit/test_inventory_transaction.py +0 -0
- {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a6}/tests/unit/test_logging.py +0 -0
- {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a6}/tests/unit/test_manual_rollback.py +0 -0
- {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a6}/tests/unit/test_models.py +0 -0
- {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a6}/tests/unit/test_modify_actions.py +0 -0
- {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a6}/tests/unit/test_operational_execution.py +0 -0
- {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a6}/tests/unit/test_parser.py +0 -0
- {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a6}/tests/unit/test_phase19_cli.py +0 -0
- {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a6}/tests/unit/test_planner.py +0 -0
- {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a6}/tests/unit/test_planner_ux.py +0 -0
- {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a6}/tests/unit/test_policy.py +0 -0
- {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a6}/tests/unit/test_project_python.py +0 -0
- {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a6}/tests/unit/test_python_discovery.py +0 -0
- {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a6}/tests/unit/test_python_structure.py +0 -0
- {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a6}/tests/unit/test_python_structure_action.py +0 -0
- {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a6}/tests/unit/test_python_symbols.py +0 -0
- {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a6}/tests/unit/test_registry.py +0 -0
- {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a6}/tests/unit/test_rollback.py +0 -0
- {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a6}/tests/unit/test_runner.py +0 -0
- {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a6}/tests/unit/test_runtime_cache.py +0 -0
- {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a6}/tests/unit/test_warning_baseline.py +0 -0
- {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a6}/tests/unit/test_workspace.py +0 -0
- {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a6}/tools/check_tag.py +0 -0
- {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a6}/tools/index_smoke.py +0 -0
|
@@ -47,14 +47,46 @@ jobs:
|
|
|
47
47
|
- name: Check formatting
|
|
48
48
|
run: python -m black --check src tests tools
|
|
49
49
|
- name: Run tests with branch coverage
|
|
50
|
-
run:
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
50
|
+
run: python -m coverage run -m pytest -q
|
|
51
|
+
- name: Require full branch coverage
|
|
52
|
+
run: python -m coverage report --fail-under=100
|
|
53
|
+
|
|
54
|
+
postgres:
|
|
55
|
+
name: Django / PostgreSQL 16
|
|
56
|
+
runs-on: ubuntu-24.04
|
|
57
|
+
timeout-minutes: 10
|
|
58
|
+
services:
|
|
59
|
+
postgres:
|
|
60
|
+
image: postgres:16
|
|
61
|
+
env:
|
|
62
|
+
POSTGRES_DB: patchshuttle_test
|
|
63
|
+
POSTGRES_USER: postgres
|
|
64
|
+
POSTGRES_PASSWORD: disposable-ci-password
|
|
65
|
+
ports:
|
|
66
|
+
- 5432:5432
|
|
67
|
+
options: >-
|
|
68
|
+
--health-cmd pg_isready
|
|
69
|
+
--health-interval 10s
|
|
70
|
+
--health-timeout 5s
|
|
71
|
+
--health-retries 5
|
|
72
|
+
steps:
|
|
73
|
+
- uses: actions/checkout@v7.0.1
|
|
74
|
+
- uses: actions/setup-python@v7.0.0
|
|
75
|
+
with:
|
|
76
|
+
python-version: "3.12"
|
|
77
|
+
- name: Install Django adapter and PostgreSQL driver
|
|
78
|
+
run: python -m pip install -e ".[django]" "psycopg[binary]>=3.2,<4"
|
|
79
|
+
- name: Check migration lifecycle and cross-connection lock
|
|
80
|
+
env:
|
|
81
|
+
PSH_PG_DATABASE: patchshuttle_test
|
|
82
|
+
PSH_PG_USER: postgres
|
|
83
|
+
PSH_PG_PASSWORD: disposable-ci-password
|
|
84
|
+
PSH_PG_PORT: "5432"
|
|
85
|
+
run: python tools/django_postgres_smoke.py
|
|
54
86
|
|
|
55
87
|
package:
|
|
56
88
|
name: Build and smoke-test distributions
|
|
57
|
-
needs: test
|
|
89
|
+
needs: [test, postgres]
|
|
58
90
|
runs-on: ubuntu-24.04
|
|
59
91
|
timeout-minutes: 20
|
|
60
92
|
steps:
|
|
@@ -3,7 +3,50 @@
|
|
|
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
|
-
##
|
|
6
|
+
## 0.1.0a6 - 2026-10-21
|
|
7
|
+
|
|
8
|
+
### Added
|
|
9
|
+
|
|
10
|
+
- Guarded `read_imports`, `ensure_import` and `remove_import` with alias-aware AST matching, comment preservation and binding checks.
|
|
11
|
+
|
|
12
|
+
- Optional authenticated MCP history server for ChatGPT, scoped to one workspace and OAuth subject.
|
|
13
|
+
- Optional Django migration command with hashed plans, database locks, pre/post checks, explicit reversals and separate recovery journals.
|
|
14
|
+
- Guarded `move_range` and `move_symbol` source transfers between files,
|
|
15
|
+
including destination fingerprints, structural validation, Python constructors,
|
|
16
|
+
and shared transaction rollback.
|
|
17
|
+
- Guarded `move_file` with destination absence checks, byte/mode preservation,
|
|
18
|
+
explicit deleted-file reporting, and automatic and manual rollback.
|
|
19
|
+
|
|
20
|
+
- Optional AST guards for `replace_symbol`, with hashes and Python version
|
|
21
|
+
reported by `read_symbol`, replacement declaration validation and compile
|
|
22
|
+
validation. Existing text-only job serialization remains compatible.
|
|
23
|
+
|
|
24
|
+
### Changed
|
|
25
|
+
|
|
26
|
+
- Formatter child interpreters and Black preflight explicitly enable Python
|
|
27
|
+
UTF-8 mode, including under isolated execution.
|
|
28
|
+
|
|
29
|
+
See `docs/NEXT_RELEASE.md` for implemented scope and remaining release work.
|
|
30
|
+
|
|
31
|
+
## 0.1.0a5 - 2026-08-28
|
|
32
|
+
|
|
33
|
+
Fourth alpha release, focused on persistent structured execution history
|
|
34
|
+
for bounded external retrieval and long-term orchestration.
|
|
35
|
+
|
|
36
|
+
### Added
|
|
37
|
+
|
|
38
|
+
- Schema-versioned, append-only structured job history records under
|
|
39
|
+
`patches/history/<job-id>/` separate declared intent from observed execution
|
|
40
|
+
facts, reference detailed logs, preserve successful, failed, declined, and
|
|
41
|
+
rollback attempts, and expose bounded read-only Python and CLI access. History
|
|
42
|
+
persistence is a best-effort secondary artifact and cannot change a job result
|
|
43
|
+
or trigger rollback.
|
|
44
|
+
|
|
45
|
+
### Fixed
|
|
46
|
+
|
|
47
|
+
- Structured history models retain the canonical external `schema` JSON key
|
|
48
|
+
without shadowing Pydantic's legacy `BaseModel.schema` attribute or emitting a
|
|
49
|
+
warning during command startup.
|
|
7
50
|
|
|
8
51
|
## 0.1.0a4 - 2026-08-27
|
|
9
52
|
|
|
@@ -1,3 +1,47 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: patchshuttle
|
|
3
|
+
Version: 0.1.0a6
|
|
4
|
+
Summary: Local, auditable patch workflows for AI-assisted software development
|
|
5
|
+
License-Expression: MIT
|
|
6
|
+
License-File: LICENSE
|
|
7
|
+
Keywords: ai,automation,cli,development-tools,patch
|
|
8
|
+
Classifier: Development Status :: 3 - Alpha
|
|
9
|
+
Classifier: Environment :: Console
|
|
10
|
+
Classifier: Intended Audience :: Developers
|
|
11
|
+
Classifier: Operating System :: OS Independent
|
|
12
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
18
|
+
Classifier: Typing :: Typed
|
|
19
|
+
Requires-Python: >=3.10
|
|
20
|
+
Requires-Dist: black<27,>=24
|
|
21
|
+
Requires-Dist: click<9,>=8.1
|
|
22
|
+
Requires-Dist: filelock<4,>=3.30
|
|
23
|
+
Requires-Dist: isort<7,>=5.13
|
|
24
|
+
Requires-Dist: pydantic<3,>=2.6
|
|
25
|
+
Requires-Dist: pyyaml<7,>=6
|
|
26
|
+
Requires-Dist: ruff<1,>=0.16
|
|
27
|
+
Requires-Dist: tomli<3,>=2; python_version < '3.11'
|
|
28
|
+
Provides-Extra: dev
|
|
29
|
+
Requires-Dist: build<2,>=1.2; extra == 'dev'
|
|
30
|
+
Requires-Dist: django<7,>=5.2; extra == 'dev'
|
|
31
|
+
Requires-Dist: mcp<2,>=1.30; extra == 'dev'
|
|
32
|
+
Requires-Dist: pyjwt[crypto]<3,>=2.10; extra == 'dev'
|
|
33
|
+
Requires-Dist: pytest-cov<8,>=5; extra == 'dev'
|
|
34
|
+
Requires-Dist: pytest<10,>=8; extra == 'dev'
|
|
35
|
+
Requires-Dist: twine<7,>=6.1; extra == 'dev'
|
|
36
|
+
Provides-Extra: django
|
|
37
|
+
Requires-Dist: django<7,>=5.2; extra == 'django'
|
|
38
|
+
Provides-Extra: html
|
|
39
|
+
Requires-Dist: djlint<2,>=1.44; extra == 'html'
|
|
40
|
+
Provides-Extra: mcp
|
|
41
|
+
Requires-Dist: mcp<2,>=1.30; extra == 'mcp'
|
|
42
|
+
Requires-Dist: pyjwt[crypto]<3,>=2.10; extra == 'mcp'
|
|
43
|
+
Description-Content-Type: text/markdown
|
|
44
|
+
|
|
1
45
|
# PatchShuttle
|
|
2
46
|
|
|
3
47
|
PatchShuttle is intended to provide local, auditable patch workflows for
|
|
@@ -6,7 +50,7 @@ describes a small job, the user reviews and runs it locally, and PatchShuttle
|
|
|
6
50
|
records the result for the next iteration.
|
|
7
51
|
|
|
8
52
|
> [!IMPORTANT]
|
|
9
|
-
> PatchShuttle is alpha software. Version `0.1.
|
|
53
|
+
> PatchShuttle is alpha software. Version `0.1.0a6` implements the complete
|
|
10
54
|
> local v0.1 workflow. It executes bounded read-only
|
|
11
55
|
> audits, approved patch transactions, and approved one-pass verification jobs
|
|
12
56
|
> under a project lock. Patch jobs retain backups, run controlled checks, apply
|
|
@@ -17,9 +61,9 @@ records the result for the next iteration.
|
|
|
17
61
|
> Trusted Publishing workflows are implemented. Every versioned release must
|
|
18
62
|
> pass its own local qualification, GitHub-hosted Windows/Ubuntu matrix,
|
|
19
63
|
> TestPyPI installation, production publication, and post-release smoke gates.
|
|
20
|
-
> The immutable `0.1.0a2` and `0.1.
|
|
21
|
-
> separately scoped `0.1.0a2` ChatGPT end-to-end
|
|
22
|
-
> [docs/RELEASE.md](docs/RELEASE.md).
|
|
64
|
+
> The immutable `0.1.0a2`, `0.1.0a3`, and `0.1.0a4` qualification
|
|
65
|
+
> evidence, plus the separately scoped `0.1.0a2` ChatGPT end-to-end
|
|
66
|
+
> workflow, are retained in [docs/RELEASE.md](docs/RELEASE.md).
|
|
23
67
|
|
|
24
68
|
> [!NOTE]
|
|
25
69
|
> Compared with `0.1.0a2`, version `0.1.0a3` adds AI-facing planner diagnostics,
|
|
@@ -30,14 +74,20 @@ records the result for the next iteration.
|
|
|
30
74
|
> range hash.
|
|
31
75
|
|
|
32
76
|
> [!NOTE]
|
|
33
|
-
>
|
|
34
|
-
> `
|
|
35
|
-
>
|
|
36
|
-
>
|
|
37
|
-
>
|
|
38
|
-
>
|
|
39
|
-
> `
|
|
40
|
-
|
|
77
|
+
> Version `0.1.0a4` adds `search_context`, `read_symbol`, guarded
|
|
78
|
+
> `replace_symbol`, the fixed Ruff F-only check, compact AI log views, Django
|
|
79
|
+
> warning baselines, owner-controlled project-check Python selection,
|
|
80
|
+
> evidence-only Python discovery telemetry, expanded redaction, bounded
|
|
81
|
+
> declaration-only `python_structure` discovery with compact output, and
|
|
82
|
+
> owner-controlled architecture ratchets. These features are included in the
|
|
83
|
+
> immutable `0.1.0a4` PyPI artifacts.
|
|
84
|
+
|
|
85
|
+
> [!NOTE]
|
|
86
|
+
> Version `0.1.0a5` adds schema-versioned append-only structured job
|
|
87
|
+
> history, facts-first records, best-effort persistence, and bounded
|
|
88
|
+
> read-only Python and CLI retrieval. Detailed execution logs remain the
|
|
89
|
+
> diagnostic source; external orchestrators remain responsible for project
|
|
90
|
+
> memory, semantic retrieval, requirements, and user decisions.
|
|
41
91
|
|
|
42
92
|
## Design goals
|
|
43
93
|
|
|
@@ -57,7 +107,7 @@ After publication, install the exact alpha release from PyPI:
|
|
|
57
107
|
```bash
|
|
58
108
|
python -m venv .venv
|
|
59
109
|
python -m pip install --upgrade pip
|
|
60
|
-
python -m pip install "patchshuttle==0.1.
|
|
110
|
+
python -m pip install "patchshuttle==0.1.0a6"
|
|
61
111
|
```
|
|
62
112
|
|
|
63
113
|
For development from a local checkout:
|
|
@@ -70,7 +120,7 @@ To enable opt-in HTML template linting in an installed release, install the
|
|
|
70
120
|
`html` extra:
|
|
71
121
|
|
|
72
122
|
```bash
|
|
73
|
-
python -m pip install "patchshuttle[html]==0.1.
|
|
123
|
+
python -m pip install "patchshuttle[html]==0.1.0a6"
|
|
74
124
|
```
|
|
75
125
|
|
|
76
126
|
For a local development checkout, install both development and HTML extras:
|
|
@@ -472,6 +522,13 @@ rejects missing, duplicate, syntactically invalid, or stale targets, and does
|
|
|
472
522
|
not use fuzzy relocation or automatic line shifting. Exact desired symbol
|
|
473
523
|
content is an idempotent `NO_CHANGE`.
|
|
474
524
|
|
|
525
|
+
The optional `expected_ast_sha256` guard uses the structural hash from
|
|
526
|
+
`read_symbol` to tolerate formatting changes. It ignores ordinary comments,
|
|
527
|
+
includes docstrings and decorators, and is scoped to the reported Python minor
|
|
528
|
+
version. Supply the text hash too when comments must be guarded. AST-guarded
|
|
529
|
+
replacements retain the name and kind and undergo compile and resolution
|
|
530
|
+
validation. See [next-release work](docs/NEXT_RELEASE.md) for current scope.
|
|
531
|
+
|
|
475
532
|
For a supported plan, the implemented sequence is:
|
|
476
533
|
|
|
477
534
|
1. validate the workspace lock file and acquire a non-blocking cross-platform
|
|
@@ -834,12 +891,13 @@ python -m coverage report --fail-under=100
|
|
|
834
891
|
python -m build
|
|
835
892
|
python -m twine check dist/*
|
|
836
893
|
python tools/release_checks.py dist
|
|
837
|
-
python tools/wheel_smoke.py dist/patchshuttle-0.1.
|
|
894
|
+
python tools/wheel_smoke.py dist/patchshuttle-0.1.0a6-py3-none-any.whl --version 0.1.0a6
|
|
838
895
|
```
|
|
839
896
|
|
|
840
|
-
The `0.1.0a2` and `0.1.
|
|
841
|
-
Windows compatibility matrix, TestPyPI qualification,
|
|
842
|
-
Publishing, and a clean post-release installation.
|
|
897
|
+
The `0.1.0a2`, `0.1.0a3`, and `0.1.0a4` alpha releases each passed the
|
|
898
|
+
required Ubuntu and Windows compatibility matrix, TestPyPI qualification,
|
|
899
|
+
production PyPI Trusted Publishing, and a clean post-release installation.
|
|
900
|
+
Their exact release and
|
|
843
901
|
workflow links and artifact hashes, together with the separately scoped
|
|
844
902
|
`0.1.0a2` ChatGPT end-to-end evidence, are recorded in
|
|
845
903
|
[docs/RELEASE.md](docs/RELEASE.md). Follow that guide in order for every future
|
|
@@ -892,6 +950,54 @@ confirmation, backup, or project checks.
|
|
|
892
950
|
This is deliberately a structural guard. It does not infer feature boundaries,
|
|
893
951
|
build dependency or call graphs, detect cycles, judge semantic responsibility,
|
|
894
952
|
reorganize files, or change the patch scope selected by the AI.
|
|
953
|
+
|
|
954
|
+
## Structured project history
|
|
955
|
+
|
|
956
|
+
PatchShuttle writes one compact JSON record for each recorded execution attempt to
|
|
957
|
+
`patches/history/<job-id>/<record-id>.json`. These records are intended for
|
|
958
|
+
long-term external ingestion and AI retrieval. They describe PatchShuttle's own
|
|
959
|
+
operations only; requirements, conversations, product decisions, stages, browser
|
|
960
|
+
tests, and semantic project memory belong to an external orchestrator.
|
|
961
|
+
|
|
962
|
+
History has a different purpose from the other outputs:
|
|
963
|
+
|
|
964
|
+
- execution logs contain detailed diagnostic evidence and command output;
|
|
965
|
+
- AI logs are bounded deterministic views derived from execution logs;
|
|
966
|
+
- history records contain compact schema-versioned facts plus references to the
|
|
967
|
+
detailed log and its derived AI-log view.
|
|
968
|
+
|
|
969
|
+
`job.title` and bounded, redacted `job.description` are stored below `declared` as
|
|
970
|
+
operator or AI-supplied intent. They are never presented as observed facts.
|
|
971
|
+
`observed` contains only trusted execution state: status, files, checks, failures,
|
|
972
|
+
rollback, warnings, and reliably targeted symbols. PatchShuttle does not infer
|
|
973
|
+
workarounds, semantic meaning, relationships, or affected symbols it cannot prove.
|
|
974
|
+
|
|
975
|
+
Read records without parsing human-readable logs:
|
|
976
|
+
|
|
977
|
+
```powershell
|
|
978
|
+
patchshuttle history list --limit 20
|
|
979
|
+
patchshuttle history latest
|
|
980
|
+
patchshuttle history latest PATCH-EXAMPLE-001
|
|
981
|
+
patchshuttle history show PATCH-EXAMPLE-001/2026_08_27_120000_000001_abcdef01
|
|
982
|
+
```
|
|
983
|
+
|
|
984
|
+
`latest` and `show` return the full canonical JSON record. `list` returns bounded
|
|
985
|
+
JSON summaries, one per line. Python integrations can call
|
|
986
|
+
`list_history_records`, `latest_history_record`, and `read_history_record` from
|
|
987
|
+
`patchshuttle.history`. External systems may also ingest the per-attempt JSON files
|
|
988
|
+
directly.
|
|
989
|
+
|
|
990
|
+
History writing occurs after the required detailed log and registry update. It is
|
|
991
|
+
best-effort: a history storage failure is exposed through the Python result's
|
|
992
|
+
`history_warning`, but does not turn a completed job into a failure or trigger
|
|
993
|
+
rollback. Existing protocol-1 jobs require no changes. Existing workspaces may add
|
|
994
|
+
`patches/history/**` to `project.ignored_paths`; new default configurations already
|
|
995
|
+
exclude it from workspace inventories.
|
|
996
|
+
|
|
997
|
+
The v1 layout is append-only and uses exclusive file creation. It deliberately has
|
|
998
|
+
no database, JSONL index, semantic search, vector store, relationship graph, or
|
|
999
|
+
Farm-specific behavior.
|
|
1000
|
+
|
|
895
1001
|
## Manual workflow
|
|
896
1002
|
|
|
897
1003
|
The implemented local cycle is:
|
|
@@ -916,3 +1022,61 @@ model, or project.
|
|
|
916
1022
|
## License
|
|
917
1023
|
|
|
918
1024
|
PatchShuttle is licensed under the MIT License.
|
|
1025
|
+
|
|
1026
|
+
|
|
1027
|
+
## Guarded source transfers
|
|
1028
|
+
|
|
1029
|
+
- `move_range`: `path`, `start_line`, `end_line`, source `expected_content`
|
|
1030
|
+
and/or `expected_sha256`, `destination`, `destination_line` and
|
|
1031
|
+
`expected_destination_sha256`.
|
|
1032
|
+
- `move_symbol`: `path`, `symbol`, `expected_ast_sha256`, `destination`,
|
|
1033
|
+
`expected_destination_sha256` and optional `destination_class`.
|
|
1034
|
+
|
|
1035
|
+
Destination hashes cover simulated raw bytes; source range hashes cover
|
|
1036
|
+
canonical LF/UTF-8 text. Destinations must exist or be created earlier in the
|
|
1037
|
+
same job. Range insertion is before the 1-based destination line; EOF+1 appends.
|
|
1038
|
+
Symbol insertion appends at module scope or to the named class. Both files are
|
|
1039
|
+
validated and participate in the same backup/check/rollback transaction.
|
|
1040
|
+
|
|
1041
|
+
Same-file transfers, case-only path differences, duplicate destination names,
|
|
1042
|
+
closure extraction, class-bound super/private-name moves and multiline-string
|
|
1043
|
+
reindentation are rejected. Imports and callers are not automatically rewritten;
|
|
1044
|
+
include explicit edits and focused project checks. These actions move source
|
|
1045
|
+
content and leave the source file present. Whole-file moves are separate work.
|
|
1046
|
+
|
|
1047
|
+
|
|
1048
|
+
## Whole-file transfers
|
|
1049
|
+
|
|
1050
|
+
`move_file` moves an existing supported text file to an absent destination.
|
|
1051
|
+
Supply `path`, `destination`, and `expected_sha256` of the original raw bytes.
|
|
1052
|
+
The transaction preserves original bytes and permissions, creates missing
|
|
1053
|
+
parent directories, and reports the source in `deleted_files`. Formatters and
|
|
1054
|
+
checks target the surviving destination. Add explicit import and caller edits
|
|
1055
|
+
when moving Python modules; imports are not automatically rewritten.
|
|
1056
|
+
|
|
1057
|
+
The source and destination must not have been touched earlier in the job.
|
|
1058
|
+
Subsequent edits to the destination are supported. Case-only moves, chains,
|
|
1059
|
+
swaps, binary files and reuse of the vacated path are currently rejected.
|
|
1060
|
+
A failed check restores the source and removes the destination. Manual rollback
|
|
1061
|
+
also verifies the applied state and refuses to overwrite a recreated source.
|
|
1062
|
+
|
|
1063
|
+
|
|
1064
|
+
## Optional integrations
|
|
1065
|
+
|
|
1066
|
+
- `patchshuttle[mcp]`: authenticated, read-only history retrieval for ChatGPT. See [setup and deployment limits](docs/CHATGPT_INTEGRATION.md).
|
|
1067
|
+
- `patchshuttle[django]`: reviewed migration plans, explicit execution/reversal, and a separate recovery journal. See [Django workflow](docs/DJANGO_MIGRATIONS.md).
|
|
1068
|
+
|
|
1069
|
+
|
|
1070
|
+
## Structural editing and optional adapters in 0.1.0a6
|
|
1071
|
+
|
|
1072
|
+
Use `read_symbol` AST hashes for guarded class/method replacements; use
|
|
1073
|
+
`read_imports`, `ensure_import`, and `remove_import` for structural imports.
|
|
1074
|
+
`move_file`, `move_range`, and `move_symbol` support explicit refactoring plans
|
|
1075
|
+
with shared checks and rollback. Imports and callers are not inferred.
|
|
1076
|
+
See [scope and examples](docs/NEXT_RELEASE.md).
|
|
1077
|
+
|
|
1078
|
+
Optional [ChatGPT history retrieval](docs/CHATGPT_INTEGRATION.md) uses an
|
|
1079
|
+
owner-configured authenticated MCP server (`patchshuttle[mcp]`).
|
|
1080
|
+
Optional [Django migrations](docs/DJANGO_MIGRATIONS.md) provide reviewed plans,
|
|
1081
|
+
locks and recovery journals (`patchshuttle[django]`). A live ChatGPT deployment
|
|
1082
|
+
requires the owner's HTTPS endpoint and OAuth configuration.
|
|
@@ -1,40 +1,3 @@
|
|
|
1
|
-
Metadata-Version: 2.4
|
|
2
|
-
Name: patchshuttle
|
|
3
|
-
Version: 0.1.0a4
|
|
4
|
-
Summary: Local, auditable patch workflows for AI-assisted software development
|
|
5
|
-
License-Expression: MIT
|
|
6
|
-
License-File: LICENSE
|
|
7
|
-
Keywords: ai,automation,cli,development-tools,patch
|
|
8
|
-
Classifier: Development Status :: 3 - Alpha
|
|
9
|
-
Classifier: Environment :: Console
|
|
10
|
-
Classifier: Intended Audience :: Developers
|
|
11
|
-
Classifier: Operating System :: OS Independent
|
|
12
|
-
Classifier: Programming Language :: Python :: 3 :: Only
|
|
13
|
-
Classifier: Programming Language :: Python :: 3.10
|
|
14
|
-
Classifier: Programming Language :: Python :: 3.11
|
|
15
|
-
Classifier: Programming Language :: Python :: 3.12
|
|
16
|
-
Classifier: Programming Language :: Python :: 3.13
|
|
17
|
-
Classifier: Programming Language :: Python :: 3.14
|
|
18
|
-
Classifier: Typing :: Typed
|
|
19
|
-
Requires-Python: >=3.10
|
|
20
|
-
Requires-Dist: black<27,>=24
|
|
21
|
-
Requires-Dist: click<9,>=8.1
|
|
22
|
-
Requires-Dist: filelock<4,>=3.30
|
|
23
|
-
Requires-Dist: isort<7,>=5.13
|
|
24
|
-
Requires-Dist: pydantic<3,>=2.6
|
|
25
|
-
Requires-Dist: pyyaml<7,>=6
|
|
26
|
-
Requires-Dist: ruff<1,>=0.16
|
|
27
|
-
Requires-Dist: tomli<3,>=2; python_version < '3.11'
|
|
28
|
-
Provides-Extra: dev
|
|
29
|
-
Requires-Dist: build<2,>=1.2; extra == 'dev'
|
|
30
|
-
Requires-Dist: django<7,>=5.2; extra == 'dev'
|
|
31
|
-
Requires-Dist: pytest-cov<8,>=5; extra == 'dev'
|
|
32
|
-
Requires-Dist: pytest<10,>=8; extra == 'dev'
|
|
33
|
-
Requires-Dist: twine<7,>=6.1; extra == 'dev'
|
|
34
|
-
Provides-Extra: html
|
|
35
|
-
Requires-Dist: djlint<2,>=1.44; extra == 'html'
|
|
36
|
-
Description-Content-Type: text/markdown
|
|
37
|
-
|
|
38
1
|
# PatchShuttle
|
|
39
2
|
|
|
40
3
|
PatchShuttle is intended to provide local, auditable patch workflows for
|
|
@@ -43,7 +6,7 @@ describes a small job, the user reviews and runs it locally, and PatchShuttle
|
|
|
43
6
|
records the result for the next iteration.
|
|
44
7
|
|
|
45
8
|
> [!IMPORTANT]
|
|
46
|
-
> PatchShuttle is alpha software. Version `0.1.
|
|
9
|
+
> PatchShuttle is alpha software. Version `0.1.0a6` implements the complete
|
|
47
10
|
> local v0.1 workflow. It executes bounded read-only
|
|
48
11
|
> audits, approved patch transactions, and approved one-pass verification jobs
|
|
49
12
|
> under a project lock. Patch jobs retain backups, run controlled checks, apply
|
|
@@ -54,9 +17,9 @@ records the result for the next iteration.
|
|
|
54
17
|
> Trusted Publishing workflows are implemented. Every versioned release must
|
|
55
18
|
> pass its own local qualification, GitHub-hosted Windows/Ubuntu matrix,
|
|
56
19
|
> TestPyPI installation, production publication, and post-release smoke gates.
|
|
57
|
-
> The immutable `0.1.0a2` and `0.1.
|
|
58
|
-
> separately scoped `0.1.0a2` ChatGPT end-to-end
|
|
59
|
-
> [docs/RELEASE.md](docs/RELEASE.md).
|
|
20
|
+
> The immutable `0.1.0a2`, `0.1.0a3`, and `0.1.0a4` qualification
|
|
21
|
+
> evidence, plus the separately scoped `0.1.0a2` ChatGPT end-to-end
|
|
22
|
+
> workflow, are retained in [docs/RELEASE.md](docs/RELEASE.md).
|
|
60
23
|
|
|
61
24
|
> [!NOTE]
|
|
62
25
|
> Compared with `0.1.0a2`, version `0.1.0a3` adds AI-facing planner diagnostics,
|
|
@@ -67,14 +30,20 @@ records the result for the next iteration.
|
|
|
67
30
|
> range hash.
|
|
68
31
|
|
|
69
32
|
> [!NOTE]
|
|
70
|
-
>
|
|
71
|
-
> `
|
|
72
|
-
>
|
|
73
|
-
>
|
|
74
|
-
>
|
|
75
|
-
>
|
|
76
|
-
> `
|
|
77
|
-
|
|
33
|
+
> Version `0.1.0a4` adds `search_context`, `read_symbol`, guarded
|
|
34
|
+
> `replace_symbol`, the fixed Ruff F-only check, compact AI log views, Django
|
|
35
|
+
> warning baselines, owner-controlled project-check Python selection,
|
|
36
|
+
> evidence-only Python discovery telemetry, expanded redaction, bounded
|
|
37
|
+
> declaration-only `python_structure` discovery with compact output, and
|
|
38
|
+
> owner-controlled architecture ratchets. These features are included in the
|
|
39
|
+
> immutable `0.1.0a4` PyPI artifacts.
|
|
40
|
+
|
|
41
|
+
> [!NOTE]
|
|
42
|
+
> Version `0.1.0a5` adds schema-versioned append-only structured job
|
|
43
|
+
> history, facts-first records, best-effort persistence, and bounded
|
|
44
|
+
> read-only Python and CLI retrieval. Detailed execution logs remain the
|
|
45
|
+
> diagnostic source; external orchestrators remain responsible for project
|
|
46
|
+
> memory, semantic retrieval, requirements, and user decisions.
|
|
78
47
|
|
|
79
48
|
## Design goals
|
|
80
49
|
|
|
@@ -94,7 +63,7 @@ After publication, install the exact alpha release from PyPI:
|
|
|
94
63
|
```bash
|
|
95
64
|
python -m venv .venv
|
|
96
65
|
python -m pip install --upgrade pip
|
|
97
|
-
python -m pip install "patchshuttle==0.1.
|
|
66
|
+
python -m pip install "patchshuttle==0.1.0a6"
|
|
98
67
|
```
|
|
99
68
|
|
|
100
69
|
For development from a local checkout:
|
|
@@ -107,7 +76,7 @@ To enable opt-in HTML template linting in an installed release, install the
|
|
|
107
76
|
`html` extra:
|
|
108
77
|
|
|
109
78
|
```bash
|
|
110
|
-
python -m pip install "patchshuttle[html]==0.1.
|
|
79
|
+
python -m pip install "patchshuttle[html]==0.1.0a6"
|
|
111
80
|
```
|
|
112
81
|
|
|
113
82
|
For a local development checkout, install both development and HTML extras:
|
|
@@ -509,6 +478,13 @@ rejects missing, duplicate, syntactically invalid, or stale targets, and does
|
|
|
509
478
|
not use fuzzy relocation or automatic line shifting. Exact desired symbol
|
|
510
479
|
content is an idempotent `NO_CHANGE`.
|
|
511
480
|
|
|
481
|
+
The optional `expected_ast_sha256` guard uses the structural hash from
|
|
482
|
+
`read_symbol` to tolerate formatting changes. It ignores ordinary comments,
|
|
483
|
+
includes docstrings and decorators, and is scoped to the reported Python minor
|
|
484
|
+
version. Supply the text hash too when comments must be guarded. AST-guarded
|
|
485
|
+
replacements retain the name and kind and undergo compile and resolution
|
|
486
|
+
validation. See [next-release work](docs/NEXT_RELEASE.md) for current scope.
|
|
487
|
+
|
|
512
488
|
For a supported plan, the implemented sequence is:
|
|
513
489
|
|
|
514
490
|
1. validate the workspace lock file and acquire a non-blocking cross-platform
|
|
@@ -871,12 +847,13 @@ python -m coverage report --fail-under=100
|
|
|
871
847
|
python -m build
|
|
872
848
|
python -m twine check dist/*
|
|
873
849
|
python tools/release_checks.py dist
|
|
874
|
-
python tools/wheel_smoke.py dist/patchshuttle-0.1.
|
|
850
|
+
python tools/wheel_smoke.py dist/patchshuttle-0.1.0a6-py3-none-any.whl --version 0.1.0a6
|
|
875
851
|
```
|
|
876
852
|
|
|
877
|
-
The `0.1.0a2` and `0.1.
|
|
878
|
-
Windows compatibility matrix, TestPyPI qualification,
|
|
879
|
-
Publishing, and a clean post-release installation.
|
|
853
|
+
The `0.1.0a2`, `0.1.0a3`, and `0.1.0a4` alpha releases each passed the
|
|
854
|
+
required Ubuntu and Windows compatibility matrix, TestPyPI qualification,
|
|
855
|
+
production PyPI Trusted Publishing, and a clean post-release installation.
|
|
856
|
+
Their exact release and
|
|
880
857
|
workflow links and artifact hashes, together with the separately scoped
|
|
881
858
|
`0.1.0a2` ChatGPT end-to-end evidence, are recorded in
|
|
882
859
|
[docs/RELEASE.md](docs/RELEASE.md). Follow that guide in order for every future
|
|
@@ -929,6 +906,54 @@ confirmation, backup, or project checks.
|
|
|
929
906
|
This is deliberately a structural guard. It does not infer feature boundaries,
|
|
930
907
|
build dependency or call graphs, detect cycles, judge semantic responsibility,
|
|
931
908
|
reorganize files, or change the patch scope selected by the AI.
|
|
909
|
+
|
|
910
|
+
## Structured project history
|
|
911
|
+
|
|
912
|
+
PatchShuttle writes one compact JSON record for each recorded execution attempt to
|
|
913
|
+
`patches/history/<job-id>/<record-id>.json`. These records are intended for
|
|
914
|
+
long-term external ingestion and AI retrieval. They describe PatchShuttle's own
|
|
915
|
+
operations only; requirements, conversations, product decisions, stages, browser
|
|
916
|
+
tests, and semantic project memory belong to an external orchestrator.
|
|
917
|
+
|
|
918
|
+
History has a different purpose from the other outputs:
|
|
919
|
+
|
|
920
|
+
- execution logs contain detailed diagnostic evidence and command output;
|
|
921
|
+
- AI logs are bounded deterministic views derived from execution logs;
|
|
922
|
+
- history records contain compact schema-versioned facts plus references to the
|
|
923
|
+
detailed log and its derived AI-log view.
|
|
924
|
+
|
|
925
|
+
`job.title` and bounded, redacted `job.description` are stored below `declared` as
|
|
926
|
+
operator or AI-supplied intent. They are never presented as observed facts.
|
|
927
|
+
`observed` contains only trusted execution state: status, files, checks, failures,
|
|
928
|
+
rollback, warnings, and reliably targeted symbols. PatchShuttle does not infer
|
|
929
|
+
workarounds, semantic meaning, relationships, or affected symbols it cannot prove.
|
|
930
|
+
|
|
931
|
+
Read records without parsing human-readable logs:
|
|
932
|
+
|
|
933
|
+
```powershell
|
|
934
|
+
patchshuttle history list --limit 20
|
|
935
|
+
patchshuttle history latest
|
|
936
|
+
patchshuttle history latest PATCH-EXAMPLE-001
|
|
937
|
+
patchshuttle history show PATCH-EXAMPLE-001/2026_08_27_120000_000001_abcdef01
|
|
938
|
+
```
|
|
939
|
+
|
|
940
|
+
`latest` and `show` return the full canonical JSON record. `list` returns bounded
|
|
941
|
+
JSON summaries, one per line. Python integrations can call
|
|
942
|
+
`list_history_records`, `latest_history_record`, and `read_history_record` from
|
|
943
|
+
`patchshuttle.history`. External systems may also ingest the per-attempt JSON files
|
|
944
|
+
directly.
|
|
945
|
+
|
|
946
|
+
History writing occurs after the required detailed log and registry update. It is
|
|
947
|
+
best-effort: a history storage failure is exposed through the Python result's
|
|
948
|
+
`history_warning`, but does not turn a completed job into a failure or trigger
|
|
949
|
+
rollback. Existing protocol-1 jobs require no changes. Existing workspaces may add
|
|
950
|
+
`patches/history/**` to `project.ignored_paths`; new default configurations already
|
|
951
|
+
exclude it from workspace inventories.
|
|
952
|
+
|
|
953
|
+
The v1 layout is append-only and uses exclusive file creation. It deliberately has
|
|
954
|
+
no database, JSONL index, semantic search, vector store, relationship graph, or
|
|
955
|
+
Farm-specific behavior.
|
|
956
|
+
|
|
932
957
|
## Manual workflow
|
|
933
958
|
|
|
934
959
|
The implemented local cycle is:
|
|
@@ -953,3 +978,61 @@ model, or project.
|
|
|
953
978
|
## License
|
|
954
979
|
|
|
955
980
|
PatchShuttle is licensed under the MIT License.
|
|
981
|
+
|
|
982
|
+
|
|
983
|
+
## Guarded source transfers
|
|
984
|
+
|
|
985
|
+
- `move_range`: `path`, `start_line`, `end_line`, source `expected_content`
|
|
986
|
+
and/or `expected_sha256`, `destination`, `destination_line` and
|
|
987
|
+
`expected_destination_sha256`.
|
|
988
|
+
- `move_symbol`: `path`, `symbol`, `expected_ast_sha256`, `destination`,
|
|
989
|
+
`expected_destination_sha256` and optional `destination_class`.
|
|
990
|
+
|
|
991
|
+
Destination hashes cover simulated raw bytes; source range hashes cover
|
|
992
|
+
canonical LF/UTF-8 text. Destinations must exist or be created earlier in the
|
|
993
|
+
same job. Range insertion is before the 1-based destination line; EOF+1 appends.
|
|
994
|
+
Symbol insertion appends at module scope or to the named class. Both files are
|
|
995
|
+
validated and participate in the same backup/check/rollback transaction.
|
|
996
|
+
|
|
997
|
+
Same-file transfers, case-only path differences, duplicate destination names,
|
|
998
|
+
closure extraction, class-bound super/private-name moves and multiline-string
|
|
999
|
+
reindentation are rejected. Imports and callers are not automatically rewritten;
|
|
1000
|
+
include explicit edits and focused project checks. These actions move source
|
|
1001
|
+
content and leave the source file present. Whole-file moves are separate work.
|
|
1002
|
+
|
|
1003
|
+
|
|
1004
|
+
## Whole-file transfers
|
|
1005
|
+
|
|
1006
|
+
`move_file` moves an existing supported text file to an absent destination.
|
|
1007
|
+
Supply `path`, `destination`, and `expected_sha256` of the original raw bytes.
|
|
1008
|
+
The transaction preserves original bytes and permissions, creates missing
|
|
1009
|
+
parent directories, and reports the source in `deleted_files`. Formatters and
|
|
1010
|
+
checks target the surviving destination. Add explicit import and caller edits
|
|
1011
|
+
when moving Python modules; imports are not automatically rewritten.
|
|
1012
|
+
|
|
1013
|
+
The source and destination must not have been touched earlier in the job.
|
|
1014
|
+
Subsequent edits to the destination are supported. Case-only moves, chains,
|
|
1015
|
+
swaps, binary files and reuse of the vacated path are currently rejected.
|
|
1016
|
+
A failed check restores the source and removes the destination. Manual rollback
|
|
1017
|
+
also verifies the applied state and refuses to overwrite a recreated source.
|
|
1018
|
+
|
|
1019
|
+
|
|
1020
|
+
## Optional integrations
|
|
1021
|
+
|
|
1022
|
+
- `patchshuttle[mcp]`: authenticated, read-only history retrieval for ChatGPT. See [setup and deployment limits](docs/CHATGPT_INTEGRATION.md).
|
|
1023
|
+
- `patchshuttle[django]`: reviewed migration plans, explicit execution/reversal, and a separate recovery journal. See [Django workflow](docs/DJANGO_MIGRATIONS.md).
|
|
1024
|
+
|
|
1025
|
+
|
|
1026
|
+
## Structural editing and optional adapters in 0.1.0a6
|
|
1027
|
+
|
|
1028
|
+
Use `read_symbol` AST hashes for guarded class/method replacements; use
|
|
1029
|
+
`read_imports`, `ensure_import`, and `remove_import` for structural imports.
|
|
1030
|
+
`move_file`, `move_range`, and `move_symbol` support explicit refactoring plans
|
|
1031
|
+
with shared checks and rollback. Imports and callers are not inferred.
|
|
1032
|
+
See [scope and examples](docs/NEXT_RELEASE.md).
|
|
1033
|
+
|
|
1034
|
+
Optional [ChatGPT history retrieval](docs/CHATGPT_INTEGRATION.md) uses an
|
|
1035
|
+
owner-configured authenticated MCP server (`patchshuttle[mcp]`).
|
|
1036
|
+
Optional [Django migrations](docs/DJANGO_MIGRATIONS.md) provide reviewed plans,
|
|
1037
|
+
locks and recovery journals (`patchshuttle[django]`). A live ChatGPT deployment
|
|
1038
|
+
requires the owner's HTTPS endpoint and OAuth configuration.
|