patchshuttle 0.1.0a4__tar.gz → 0.1.0a5__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.
Files changed (127) hide show
  1. {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a5}/.gitignore +1 -0
  2. {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a5}/CHANGELOG.md +20 -0
  3. {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a5}/PKG-INFO +74 -19
  4. {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a5}/README.md +73 -18
  5. {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a5}/SPEC_V0_1.md +62 -16
  6. {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a5}/docs/RELEASE.md +47 -8
  7. {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a5}/src/patchshuttle/_version.py +1 -1
  8. {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a5}/src/patchshuttle/cli.py +6 -8
  9. {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a5}/src/patchshuttle/config.py +1 -0
  10. {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a5}/src/patchshuttle/errors.py +4 -0
  11. {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a5}/src/patchshuttle/execution.py +62 -39
  12. patchshuttle-0.1.0a5/src/patchshuttle/history/__init__.py +35 -0
  13. patchshuttle-0.1.0a5/src/patchshuttle/history/cli.py +123 -0
  14. patchshuttle-0.1.0a5/src/patchshuttle/history/models.py +194 -0
  15. patchshuttle-0.1.0a5/src/patchshuttle/history/records.py +382 -0
  16. patchshuttle-0.1.0a5/src/patchshuttle/history/storage.py +370 -0
  17. {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a5}/src/patchshuttle/operations.py +41 -34
  18. {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a5}/src/patchshuttle/resources/AI_GUIDE.md +24 -0
  19. {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a5}/src/patchshuttle/resources/PATCHSHUTTLE_PROTOCOL.md +33 -0
  20. patchshuttle-0.1.0a5/tests/unit/history/test_history.py +373 -0
  21. patchshuttle-0.1.0a5/tests/unit/history/test_history_integration.py +225 -0
  22. patchshuttle-0.1.0a5/tests/unit/history/test_history_storage_edges.py +292 -0
  23. {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a5}/tests/unit/test_cli.py +2 -2
  24. {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a5}/tests/unit/test_package.py +1 -1
  25. {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a5}/tests/unit/test_release_configuration.py +1 -1
  26. {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a5}/tests/unit/test_selfdoc.py +1 -1
  27. {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a5}/tools/release_checks.py +5 -0
  28. {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a5}/tools/wheel_smoke.py +6 -0
  29. {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a5}/.github/workflows/ci.yml +0 -0
  30. {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a5}/.github/workflows/release.yml +0 -0
  31. {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a5}/.github/workflows/testpypi.yml +0 -0
  32. {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a5}/LICENSE +0 -0
  33. {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a5}/SECURITY.md +0 -0
  34. {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a5}/pyproject.toml +0 -0
  35. {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a5}/src/patchshuttle/__init__.py +0 -0
  36. {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a5}/src/patchshuttle/_ai_log.py +0 -0
  37. {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a5}/src/patchshuttle/_architecture.py +0 -0
  38. {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a5}/src/patchshuttle/_diff.py +0 -0
  39. {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a5}/src/patchshuttle/_html_lint.py +0 -0
  40. {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a5}/src/patchshuttle/_line_ranges.py +0 -0
  41. {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a5}/src/patchshuttle/_process.py +0 -0
  42. {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a5}/src/patchshuttle/_python_discovery.py +0 -0
  43. {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a5}/src/patchshuttle/_python_structure.py +0 -0
  44. {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a5}/src/patchshuttle/_python_symbols.py +0 -0
  45. {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a5}/src/patchshuttle/actions/__init__.py +0 -0
  46. {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a5}/src/patchshuttle/actions/constructors.py +0 -0
  47. {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a5}/src/patchshuttle/actions/create.py +0 -0
  48. {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a5}/src/patchshuttle/actions/modify.py +0 -0
  49. {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a5}/src/patchshuttle/audit.py +0 -0
  50. {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a5}/src/patchshuttle/backup.py +0 -0
  51. {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a5}/src/patchshuttle/checks/__init__.py +0 -0
  52. {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a5}/src/patchshuttle/checks/constructors.py +0 -0
  53. {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a5}/src/patchshuttle/checks/runner.py +0 -0
  54. {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a5}/src/patchshuttle/context.py +0 -0
  55. {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a5}/src/patchshuttle/formatter_policy.py +0 -0
  56. {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a5}/src/patchshuttle/formatters/__init__.py +0 -0
  57. {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a5}/src/patchshuttle/formatters/runner.py +0 -0
  58. {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a5}/src/patchshuttle/identifiers.py +0 -0
  59. {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a5}/src/patchshuttle/inventory.py +0 -0
  60. {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a5}/src/patchshuttle/linters/__init__.py +0 -0
  61. {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a5}/src/patchshuttle/linters/runner.py +0 -0
  62. {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a5}/src/patchshuttle/logging.py +0 -0
  63. {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a5}/src/patchshuttle/models.py +0 -0
  64. {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a5}/src/patchshuttle/parser.py +0 -0
  65. {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a5}/src/patchshuttle/planner.py +0 -0
  66. {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a5}/src/patchshuttle/policy.py +0 -0
  67. {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a5}/src/patchshuttle/preflight.py +0 -0
  68. {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a5}/src/patchshuttle/project_python.py +0 -0
  69. {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a5}/src/patchshuttle/py.typed +0 -0
  70. {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a5}/src/patchshuttle/registry.py +0 -0
  71. {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a5}/src/patchshuttle/resources/AUDIT-EXAMPLE.psh.yaml +0 -0
  72. {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a5}/src/patchshuttle/resources/PATCH-EXAMPLE.psh.yaml +0 -0
  73. {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a5}/src/patchshuttle/resources/__init__.py +0 -0
  74. {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a5}/src/patchshuttle/rollback.py +0 -0
  75. {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a5}/src/patchshuttle/runner.py +0 -0
  76. {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a5}/src/patchshuttle/runtime_cache.py +0 -0
  77. {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a5}/src/patchshuttle/selfdoc.py +0 -0
  78. {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a5}/src/patchshuttle/verification.py +0 -0
  79. {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a5}/src/patchshuttle/warning_baseline.py +0 -0
  80. {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a5}/src/patchshuttle/workspace.py +0 -0
  81. {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a5}/tests/e2e/test_cli_project_cycle.py +0 -0
  82. {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a5}/tests/integration/test_workflows.py +0 -0
  83. {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a5}/tests/unit/test_a4_coverage_regressions.py +0 -0
  84. {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a5}/tests/unit/test_actions.py +0 -0
  85. {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a5}/tests/unit/test_ai_log.py +0 -0
  86. {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a5}/tests/unit/test_architecture.py +0 -0
  87. {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a5}/tests/unit/test_attempt_logging.py +0 -0
  88. {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a5}/tests/unit/test_audit_verify_execution.py +0 -0
  89. {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a5}/tests/unit/test_backup.py +0 -0
  90. {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a5}/tests/unit/test_change_transaction.py +0 -0
  91. {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a5}/tests/unit/test_check_transaction.py +0 -0
  92. {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a5}/tests/unit/test_checks.py +0 -0
  93. {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a5}/tests/unit/test_config.py +0 -0
  94. {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a5}/tests/unit/test_context_and_constructors.py +0 -0
  95. {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a5}/tests/unit/test_diff.py +0 -0
  96. {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a5}/tests/unit/test_execution.py +0 -0
  97. {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a5}/tests/unit/test_formatters.py +0 -0
  98. {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a5}/tests/unit/test_formatting_transaction.py +0 -0
  99. {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a5}/tests/unit/test_guarded_ranges.py +0 -0
  100. {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a5}/tests/unit/test_html_lint.py +0 -0
  101. {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a5}/tests/unit/test_identifiers.py +0 -0
  102. {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a5}/tests/unit/test_inventory.py +0 -0
  103. {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a5}/tests/unit/test_inventory_transaction.py +0 -0
  104. {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a5}/tests/unit/test_logging.py +0 -0
  105. {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a5}/tests/unit/test_manual_rollback.py +0 -0
  106. {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a5}/tests/unit/test_models.py +0 -0
  107. {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a5}/tests/unit/test_modify_actions.py +0 -0
  108. {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a5}/tests/unit/test_operational_execution.py +0 -0
  109. {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a5}/tests/unit/test_parser.py +0 -0
  110. {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a5}/tests/unit/test_phase19_cli.py +0 -0
  111. {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a5}/tests/unit/test_planner.py +0 -0
  112. {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a5}/tests/unit/test_planner_ux.py +0 -0
  113. {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a5}/tests/unit/test_policy.py +0 -0
  114. {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a5}/tests/unit/test_preflight.py +0 -0
  115. {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a5}/tests/unit/test_project_python.py +0 -0
  116. {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a5}/tests/unit/test_python_discovery.py +0 -0
  117. {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a5}/tests/unit/test_python_structure.py +0 -0
  118. {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a5}/tests/unit/test_python_structure_action.py +0 -0
  119. {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a5}/tests/unit/test_python_symbols.py +0 -0
  120. {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a5}/tests/unit/test_registry.py +0 -0
  121. {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a5}/tests/unit/test_rollback.py +0 -0
  122. {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a5}/tests/unit/test_runner.py +0 -0
  123. {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a5}/tests/unit/test_runtime_cache.py +0 -0
  124. {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a5}/tests/unit/test_warning_baseline.py +0 -0
  125. {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a5}/tests/unit/test_workspace.py +0 -0
  126. {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a5}/tools/check_tag.py +0 -0
  127. {patchshuttle-0.1.0a4 → patchshuttle-0.1.0a5}/tools/index_smoke.py +0 -0
@@ -26,5 +26,6 @@ Thumbs.db
26
26
  patches/applied/
27
27
  patches/backups/
28
28
  patches/failed/
29
+ patches/history/
29
30
  patches/logs/
30
31
  patches/state/
@@ -5,6 +5,26 @@ uses semantic versioning, including Python-compatible pre-release versions.
5
5
 
6
6
  ## Unreleased
7
7
 
8
+ ## 0.1.0a5 - 2026-08-28
9
+
10
+ Fourth alpha release, focused on persistent structured execution history
11
+ for bounded external retrieval and long-term orchestration.
12
+
13
+ ### Added
14
+
15
+ - Schema-versioned, append-only structured job history records under
16
+ `patches/history/<job-id>/` separate declared intent from observed execution
17
+ facts, reference detailed logs, preserve successful, failed, declined, and
18
+ rollback attempts, and expose bounded read-only Python and CLI access. History
19
+ persistence is a best-effort secondary artifact and cannot change a job result
20
+ or trigger rollback.
21
+
22
+ ### Fixed
23
+
24
+ - Structured history models retain the canonical external `schema` JSON key
25
+ without shadowing Pydantic's legacy `BaseModel.schema` attribute or emitting a
26
+ warning during command startup.
27
+
8
28
  ## 0.1.0a4 - 2026-08-27
9
29
 
10
30
  Third alpha release, focused on bounded Python source discovery, compact
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: patchshuttle
3
- Version: 0.1.0a4
3
+ Version: 0.1.0a5
4
4
  Summary: Local, auditable patch workflows for AI-assisted software development
5
5
  License-Expression: MIT
6
6
  License-File: LICENSE
@@ -43,7 +43,7 @@ describes a small job, the user reviews and runs it locally, and PatchShuttle
43
43
  records the result for the next iteration.
44
44
 
45
45
  > [!IMPORTANT]
46
- > PatchShuttle is alpha software. Version `0.1.0a4` implements the complete
46
+ > PatchShuttle is alpha software. Version `0.1.0a5` implements the complete
47
47
  > local v0.1 workflow. It executes bounded read-only
48
48
  > audits, approved patch transactions, and approved one-pass verification jobs
49
49
  > under a project lock. Patch jobs retain backups, run controlled checks, apply
@@ -54,9 +54,9 @@ records the result for the next iteration.
54
54
  > Trusted Publishing workflows are implemented. Every versioned release must
55
55
  > pass its own local qualification, GitHub-hosted Windows/Ubuntu matrix,
56
56
  > TestPyPI installation, production publication, and post-release smoke gates.
57
- > The immutable `0.1.0a2` and `0.1.0a3` qualification evidence, plus the
58
- > separately scoped `0.1.0a2` ChatGPT end-to-end workflow, are retained in
59
- > [docs/RELEASE.md](docs/RELEASE.md).
57
+ > The immutable `0.1.0a2`, `0.1.0a3`, and `0.1.0a4` qualification
58
+ > evidence, plus the separately scoped `0.1.0a2` ChatGPT end-to-end
59
+ > workflow, are retained in [docs/RELEASE.md](docs/RELEASE.md).
60
60
 
61
61
  > [!NOTE]
62
62
  > Compared with `0.1.0a2`, version `0.1.0a3` adds AI-facing planner diagnostics,
@@ -67,14 +67,20 @@ records the result for the next iteration.
67
67
  > range hash.
68
68
 
69
69
  > [!NOTE]
70
- > The current development branch also contains unreleased work completed after
71
- > `0.1.0a3`: `search_context`, `read_symbol`, guarded `replace_symbol`, a fixed
72
- > Ruff F-only check, compact text and JSON AI log views, explicit Django warning
73
- > baselines, owner-controlled project-check Python selection, evidence-only
74
- > Python discovery telemetry, expanded Python secret redaction, nested
75
- > dependency-environment exclusions, and bounded declaration-only
76
- > `python_structure` discovery. These features are available from the source
77
- > branch and are not part of the immutable `0.1.0a3` PyPI artifacts.
70
+ > Version `0.1.0a4` adds `search_context`, `read_symbol`, guarded
71
+ > `replace_symbol`, the fixed Ruff F-only check, compact AI log views, Django
72
+ > warning baselines, owner-controlled project-check Python selection,
73
+ > evidence-only Python discovery telemetry, expanded redaction, bounded
74
+ > declaration-only `python_structure` discovery with compact output, and
75
+ > owner-controlled architecture ratchets. These features are included in the
76
+ > immutable `0.1.0a4` PyPI artifacts.
77
+
78
+ > [!NOTE]
79
+ > Version `0.1.0a5` adds schema-versioned append-only structured job
80
+ > history, facts-first records, best-effort persistence, and bounded
81
+ > read-only Python and CLI retrieval. Detailed execution logs remain the
82
+ > diagnostic source; external orchestrators remain responsible for project
83
+ > memory, semantic retrieval, requirements, and user decisions.
78
84
 
79
85
  ## Design goals
80
86
 
@@ -94,7 +100,7 @@ After publication, install the exact alpha release from PyPI:
94
100
  ```bash
95
101
  python -m venv .venv
96
102
  python -m pip install --upgrade pip
97
- python -m pip install "patchshuttle==0.1.0a4"
103
+ python -m pip install "patchshuttle==0.1.0a5"
98
104
  ```
99
105
 
100
106
  For development from a local checkout:
@@ -107,7 +113,7 @@ To enable opt-in HTML template linting in an installed release, install the
107
113
  `html` extra:
108
114
 
109
115
  ```bash
110
- python -m pip install "patchshuttle[html]==0.1.0a4"
116
+ python -m pip install "patchshuttle[html]==0.1.0a5"
111
117
  ```
112
118
 
113
119
  For a local development checkout, install both development and HTML extras:
@@ -871,12 +877,13 @@ python -m coverage report --fail-under=100
871
877
  python -m build
872
878
  python -m twine check dist/*
873
879
  python tools/release_checks.py dist
874
- python tools/wheel_smoke.py dist/patchshuttle-0.1.0a4-py3-none-any.whl --version 0.1.0a4
880
+ python tools/wheel_smoke.py dist/patchshuttle-0.1.0a5-py3-none-any.whl --version 0.1.0a5
875
881
  ```
876
882
 
877
- The `0.1.0a2` and `0.1.0a3` alpha releases each passed the required Ubuntu and
878
- Windows compatibility matrix, TestPyPI qualification, production PyPI Trusted
879
- Publishing, and a clean post-release installation. Their exact release and
883
+ The `0.1.0a2`, `0.1.0a3`, and `0.1.0a4` alpha releases each passed the
884
+ required Ubuntu and Windows compatibility matrix, TestPyPI qualification,
885
+ production PyPI Trusted Publishing, and a clean post-release installation.
886
+ Their exact release and
880
887
  workflow links and artifact hashes, together with the separately scoped
881
888
  `0.1.0a2` ChatGPT end-to-end evidence, are recorded in
882
889
  [docs/RELEASE.md](docs/RELEASE.md). Follow that guide in order for every future
@@ -929,6 +936,54 @@ confirmation, backup, or project checks.
929
936
  This is deliberately a structural guard. It does not infer feature boundaries,
930
937
  build dependency or call graphs, detect cycles, judge semantic responsibility,
931
938
  reorganize files, or change the patch scope selected by the AI.
939
+
940
+ ## Structured project history
941
+
942
+ PatchShuttle writes one compact JSON record for each recorded execution attempt to
943
+ `patches/history/<job-id>/<record-id>.json`. These records are intended for
944
+ long-term external ingestion and AI retrieval. They describe PatchShuttle's own
945
+ operations only; requirements, conversations, product decisions, stages, browser
946
+ tests, and semantic project memory belong to an external orchestrator.
947
+
948
+ History has a different purpose from the other outputs:
949
+
950
+ - execution logs contain detailed diagnostic evidence and command output;
951
+ - AI logs are bounded deterministic views derived from execution logs;
952
+ - history records contain compact schema-versioned facts plus references to the
953
+ detailed log and its derived AI-log view.
954
+
955
+ `job.title` and bounded, redacted `job.description` are stored below `declared` as
956
+ operator or AI-supplied intent. They are never presented as observed facts.
957
+ `observed` contains only trusted execution state: status, files, checks, failures,
958
+ rollback, warnings, and reliably targeted symbols. PatchShuttle does not infer
959
+ workarounds, semantic meaning, relationships, or affected symbols it cannot prove.
960
+
961
+ Read records without parsing human-readable logs:
962
+
963
+ ```powershell
964
+ patchshuttle history list --limit 20
965
+ patchshuttle history latest
966
+ patchshuttle history latest PATCH-EXAMPLE-001
967
+ patchshuttle history show PATCH-EXAMPLE-001/2026_08_27_120000_000001_abcdef01
968
+ ```
969
+
970
+ `latest` and `show` return the full canonical JSON record. `list` returns bounded
971
+ JSON summaries, one per line. Python integrations can call
972
+ `list_history_records`, `latest_history_record`, and `read_history_record` from
973
+ `patchshuttle.history`. External systems may also ingest the per-attempt JSON files
974
+ directly.
975
+
976
+ History writing occurs after the required detailed log and registry update. It is
977
+ best-effort: a history storage failure is exposed through the Python result's
978
+ `history_warning`, but does not turn a completed job into a failure or trigger
979
+ rollback. Existing protocol-1 jobs require no changes. Existing workspaces may add
980
+ `patches/history/**` to `project.ignored_paths`; new default configurations already
981
+ exclude it from workspace inventories.
982
+
983
+ The v1 layout is append-only and uses exclusive file creation. It deliberately has
984
+ no database, JSONL index, semantic search, vector store, relationship graph, or
985
+ Farm-specific behavior.
986
+
932
987
  ## Manual workflow
933
988
 
934
989
  The implemented local cycle is:
@@ -6,7 +6,7 @@ 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. Version `0.1.0a4` implements the complete
9
+ > PatchShuttle is alpha software. Version `0.1.0a5` implements the complete
10
10
  > local v0.1 workflow. It executes bounded read-only
11
11
  > audits, approved patch transactions, and approved one-pass verification jobs
12
12
  > under a project lock. Patch jobs retain backups, run controlled checks, apply
@@ -17,9 +17,9 @@ records the result for the next iteration.
17
17
  > Trusted Publishing workflows are implemented. Every versioned release must
18
18
  > pass its own local qualification, GitHub-hosted Windows/Ubuntu matrix,
19
19
  > TestPyPI installation, production publication, and post-release smoke gates.
20
- > The immutable `0.1.0a2` and `0.1.0a3` qualification evidence, plus the
21
- > separately scoped `0.1.0a2` ChatGPT end-to-end workflow, are retained in
22
- > [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).
23
23
 
24
24
  > [!NOTE]
25
25
  > Compared with `0.1.0a2`, version `0.1.0a3` adds AI-facing planner diagnostics,
@@ -30,14 +30,20 @@ records the result for the next iteration.
30
30
  > range hash.
31
31
 
32
32
  > [!NOTE]
33
- > The current development branch also contains unreleased work completed after
34
- > `0.1.0a3`: `search_context`, `read_symbol`, guarded `replace_symbol`, a fixed
35
- > Ruff F-only check, compact text and JSON AI log views, explicit Django warning
36
- > baselines, owner-controlled project-check Python selection, evidence-only
37
- > Python discovery telemetry, expanded Python secret redaction, nested
38
- > dependency-environment exclusions, and bounded declaration-only
39
- > `python_structure` discovery. These features are available from the source
40
- > branch and are not part of the immutable `0.1.0a3` PyPI artifacts.
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.
41
47
 
42
48
  ## Design goals
43
49
 
@@ -57,7 +63,7 @@ After publication, install the exact alpha release from PyPI:
57
63
  ```bash
58
64
  python -m venv .venv
59
65
  python -m pip install --upgrade pip
60
- python -m pip install "patchshuttle==0.1.0a4"
66
+ python -m pip install "patchshuttle==0.1.0a5"
61
67
  ```
62
68
 
63
69
  For development from a local checkout:
@@ -70,7 +76,7 @@ To enable opt-in HTML template linting in an installed release, install the
70
76
  `html` extra:
71
77
 
72
78
  ```bash
73
- python -m pip install "patchshuttle[html]==0.1.0a4"
79
+ python -m pip install "patchshuttle[html]==0.1.0a5"
74
80
  ```
75
81
 
76
82
  For a local development checkout, install both development and HTML extras:
@@ -834,12 +840,13 @@ python -m coverage report --fail-under=100
834
840
  python -m build
835
841
  python -m twine check dist/*
836
842
  python tools/release_checks.py dist
837
- python tools/wheel_smoke.py dist/patchshuttle-0.1.0a4-py3-none-any.whl --version 0.1.0a4
843
+ python tools/wheel_smoke.py dist/patchshuttle-0.1.0a5-py3-none-any.whl --version 0.1.0a5
838
844
  ```
839
845
 
840
- The `0.1.0a2` and `0.1.0a3` alpha releases each passed the required Ubuntu and
841
- Windows compatibility matrix, TestPyPI qualification, production PyPI Trusted
842
- Publishing, and a clean post-release installation. Their exact release and
846
+ The `0.1.0a2`, `0.1.0a3`, and `0.1.0a4` alpha releases each passed the
847
+ required Ubuntu and Windows compatibility matrix, TestPyPI qualification,
848
+ production PyPI Trusted Publishing, and a clean post-release installation.
849
+ Their exact release and
843
850
  workflow links and artifact hashes, together with the separately scoped
844
851
  `0.1.0a2` ChatGPT end-to-end evidence, are recorded in
845
852
  [docs/RELEASE.md](docs/RELEASE.md). Follow that guide in order for every future
@@ -892,6 +899,54 @@ confirmation, backup, or project checks.
892
899
  This is deliberately a structural guard. It does not infer feature boundaries,
893
900
  build dependency or call graphs, detect cycles, judge semantic responsibility,
894
901
  reorganize files, or change the patch scope selected by the AI.
902
+
903
+ ## Structured project history
904
+
905
+ PatchShuttle writes one compact JSON record for each recorded execution attempt to
906
+ `patches/history/<job-id>/<record-id>.json`. These records are intended for
907
+ long-term external ingestion and AI retrieval. They describe PatchShuttle's own
908
+ operations only; requirements, conversations, product decisions, stages, browser
909
+ tests, and semantic project memory belong to an external orchestrator.
910
+
911
+ History has a different purpose from the other outputs:
912
+
913
+ - execution logs contain detailed diagnostic evidence and command output;
914
+ - AI logs are bounded deterministic views derived from execution logs;
915
+ - history records contain compact schema-versioned facts plus references to the
916
+ detailed log and its derived AI-log view.
917
+
918
+ `job.title` and bounded, redacted `job.description` are stored below `declared` as
919
+ operator or AI-supplied intent. They are never presented as observed facts.
920
+ `observed` contains only trusted execution state: status, files, checks, failures,
921
+ rollback, warnings, and reliably targeted symbols. PatchShuttle does not infer
922
+ workarounds, semantic meaning, relationships, or affected symbols it cannot prove.
923
+
924
+ Read records without parsing human-readable logs:
925
+
926
+ ```powershell
927
+ patchshuttle history list --limit 20
928
+ patchshuttle history latest
929
+ patchshuttle history latest PATCH-EXAMPLE-001
930
+ patchshuttle history show PATCH-EXAMPLE-001/2026_08_27_120000_000001_abcdef01
931
+ ```
932
+
933
+ `latest` and `show` return the full canonical JSON record. `list` returns bounded
934
+ JSON summaries, one per line. Python integrations can call
935
+ `list_history_records`, `latest_history_record`, and `read_history_record` from
936
+ `patchshuttle.history`. External systems may also ingest the per-attempt JSON files
937
+ directly.
938
+
939
+ History writing occurs after the required detailed log and registry update. It is
940
+ best-effort: a history storage failure is exposed through the Python result's
941
+ `history_warning`, but does not turn a completed job into a failure or trigger
942
+ rollback. Existing protocol-1 jobs require no changes. Existing workspaces may add
943
+ `patches/history/**` to `project.ignored_paths`; new default configurations already
944
+ exclude it from workspace inventories.
945
+
946
+ The v1 layout is append-only and uses exclusive file creation. It deliberately has
947
+ no database, JSONL index, semantic search, vector store, relationship graph, or
948
+ Farm-specific behavior.
949
+
895
950
  ## Manual workflow
896
951
 
897
952
  The implemented local cycle is:
@@ -13,20 +13,17 @@
13
13
  > on 2026-08-16, followed by successful TestPyPI qualification, production
14
14
  > PyPI publication, and a clean installation smoke test. A recorded ChatGPT
15
15
  > end-to-end workflow passed on Windows 11 with Python 3.14.2 on 2026-08-17.
16
- > Version `0.1.0a3` is a published alpha release, not stable `0.1.0`.
17
- > Compared with published `0.1.0a2`, it adds AI-facing mismatch diagnostics,
18
- > resolved diff previews, Python formatter preflight, opt-in changed-HTML
19
- > linting, early failure logs, explicit workspace routing, installed-contract
20
- > self-documentation, per-file formatter policy, Django-aware import checks,
21
- > defensive runtime-cache cleanup, and guarded physical-line range actions.
22
- > The feature-complete source passed 834 local tests on Linux/Python 3.12 with
23
- > one environment-only skip, 100% statement and branch coverage, release
24
- > artifact validation, `twine check`, and a clean wheel smoke test. The final
25
- > versioned commit `06f3125aacd92ae32a832d34d86246a97fdc74f7` passed the
26
- > required hosted Windows/Ubuntu matrix, TestPyPI qualification, production
27
- > PyPI publication, and a clean Windows CPython 3.14 installation on
28
- > 2026-08-23. TestPyPI and production PyPI contain byte-identical `0.1.0a3`
29
- > distributions.
16
+ > Version `0.1.0a4` is a published alpha release, not stable `0.1.0`.
17
+ > It retains the published `0.1.0a3` workflow and adds bounded Python source
18
+ > discovery, compact structure output, owner-controlled project-check Python
19
+ > selection, evidence-only discovery telemetry, and owner-controlled Python
20
+ > architecture ratchets. The immutable artifacts were built from commit
21
+ > `f0f6188b6e81727401152023d701f0e065fcc481` and passed the required hosted
22
+ > Windows/Ubuntu matrix, TestPyPI qualification, production PyPI Trusted
23
+ > Publishing, and a clean Windows CPython 3.14 installation on 2026-08-27.
24
+ > TestPyPI and production PyPI contain byte-identical `0.1.0a4`
25
+ > distributions; exact workflow links, sizes, and SHA-256 hashes are recorded
26
+ > in `docs/RELEASE.md`.
30
27
  >
31
28
  > This document defines the target behavior of PatchShuttle v0.1. The README
32
29
  > identifies the currently implemented subset; all other features remain
@@ -413,6 +410,36 @@ The policy is structural only: it does not inspect source semantics, infer
413
410
  features or dependencies, build graphs, reorganize files, or choose patch scope.
414
411
  Disabling or changing thresholds requires an owner edit to
415
412
  `patches/patchshuttle.toml`.
413
+ ### 9.2 Persistent structured job history
414
+
415
+ PatchShuttle records compact facts about its own execution attempts separately from
416
+ full diagnostic logs. A history record is a schema-versioned JSON projection of the
417
+ same trusted run state used by logging. It separates submitted intent from observed
418
+ execution facts and references, rather than duplicates, detailed evidence.
419
+
420
+ Version 1 uses one exclusive file per attempt under
421
+ `patches/history/<job-id>/<record-id>.json`. Multiple attempts for the same job ID
422
+ never overwrite one another. Readers validate schema, project identity, record/path
423
+ identity, real-file boundaries, and size and scan limits. External orchestrators may
424
+ ingest these files into their own databases and indexes.
425
+
426
+ Required content includes PatchShuttle and schema versions, job identity and hash,
427
+ timestamp, result and exit code, bounded declared title and description intent,
428
+ planned counts and targets, observed file changes, executed checks, failure and
429
+ rollback facts, check warnings, and references to detailed log, derived AI-log view,
430
+ archived job, and backup. Affected symbols are included only when an explicit
431
+ `replace_symbol` target corresponds to an observed affected file. Relationships are
432
+ `null` in v1 because protocol 1 supplies no authoritative relationship metadata.
433
+
434
+ History creation is a best-effort secondary operation after log and registry
435
+ persistence. Failure to create it does not fail or roll back an otherwise completed
436
+ job. The Python result exposes the bounded warning. Existing job schemas, normalized
437
+ hashes, registry semantics, logs, and AI-log formats remain unchanged.
438
+
439
+ PatchShuttle does not store conversations, requirements, product decisions, stages,
440
+ artifacts, runtime history, semantic memory, or vector indexes. Those remain the
441
+ responsibility of external orchestration systems.
442
+
416
443
  ## 10. YAML job protocol
417
444
 
418
445
  ### 10.1 Canonical extension
@@ -1930,7 +1957,7 @@ has been tested through a documented end-to-end scenario.
1930
1957
  TestPyPI and production Trusted Publishing, and a clean production-index
1931
1958
  installation on 2026-08-23.
1932
1959
 
1933
- ### Unreleased after `0.1.0a3`
1960
+ ### `0.1.0a4`
1934
1961
 
1935
1962
  - bounded `search_context` and decorator-aware Python `read_symbol` audits;
1936
1963
  - guarded `replace_symbol` planning and transactional execution;
@@ -1952,6 +1979,25 @@ has been tested through a documented end-to-end scenario.
1952
1979
  the standard-library AST, with no project-code execution, semantic resolution,
1953
1980
  cache, persistence, inferred patch scope, or symbol-index implementation verdict.
1954
1981
 
1982
+ - opt-in compact `python_structure` output that retains bounded navigational
1983
+ identities, source ranges, parse errors, and limit signals;
1984
+ - owner-controlled `modular-monolith` / `package-by-feature` architecture
1985
+ ratchets with bounded stable `ARCH` findings;
1986
+ - immutable artifacts from commit
1987
+ `f0f6188b6e81727401152023d701f0e065fcc481` passed final `main` and tag CI,
1988
+ TestPyPI and production Trusted Publishing, and a clean production-index
1989
+ Windows CPython 3.14 installation on 2026-08-27.
1990
+ ### `0.1.0a5`
1991
+
1992
+ - schema-versioned append-only structured records for PatchShuttle job
1993
+ attempts, with declared intent kept separate from observed execution facts;
1994
+ - compact file, check, failure, rollback, warning, and diagnostic-reference
1995
+ metadata without full command output, patch contents, or project memory;
1996
+ - best-effort secondary persistence that cannot change an authoritative job
1997
+ result or trigger rollback;
1998
+ - bounded read-only Python and CLI retrieval for external ingestion, without a
1999
+ database, semantic search, relationship graph, or orchestrator-specific state.
2000
+
1955
2001
  ### `0.1.0b1`
1956
2002
 
1957
2003
  - AI guide and handoff;
@@ -2008,7 +2054,7 @@ PatchShuttle v0.1.0 is ready when all of the following are demonstrated:
2008
2054
 
2009
2055
  ### Current qualification record
2010
2056
 
2011
- As of the completed `0.1.0a3` qualification on 2026-08-23, criteria 1 through
2057
+ As of the completed `0.1.0a4` qualification on 2026-08-27, criteria 1 through
2012
2058
  18 above have explicit evidence for that published alpha release: local
2013
2059
  implementation and test evidence for criteria 2 through 16, plus independent
2014
2060
  hosted CI, TestPyPI, production PyPI, and clean post-release installation
@@ -1,6 +1,6 @@
1
1
  # PatchShuttle release guide
2
2
 
3
- This guide records the immutable published `0.1.0a2` and `0.1.0a3` evidence and
3
+ This guide records the immutable published `0.1.0a2`, `0.1.0a3`, and `0.1.0a4` evidence 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.
@@ -98,6 +98,44 @@ The **Tested with ChatGPT** statement remains scoped to the separately recorded
98
98
  `0.1.0a2` end-to-end workflow above; this release record does not silently
99
99
  extend that product claim to `0.1.0a3`.
100
100
 
101
+ ## 0.2. Recorded `0.1.0a4` qualification
102
+
103
+ The immutable `0.1.0a4` artifacts were built from commit
104
+ `f0f6188b6e81727401152023d701f0e065fcc481`. The annotated
105
+ `v0.1.0a4` tag resolves to the same commit. The release adds bounded
106
+ Python source discovery, compact structure output, owner-controlled
107
+ project-check Python selection, evidence-only discovery telemetry, and
108
+ owner-controlled Python architecture ratchets.
109
+
110
+ The release passed these external gates on 2026-08-27:
111
+
112
+ - [final release-candidate CI on `main`](https://github.com/ratundo/patchshuttle/actions/runs/33089001064);
113
+ - [TestPyPI publication](https://github.com/ratundo/patchshuttle/actions/runs/33094686124);
114
+ - [CI for tag `v0.1.0a4`](https://github.com/ratundo/patchshuttle/actions/runs/33095708487);
115
+ - [GitHub `v0.1.0a4` pre-release](https://github.com/ratundo/patchshuttle/releases/tag/v0.1.0a4);
116
+ - [production PyPI Trusted Publishing](https://github.com/ratundo/patchshuttle/actions/runs/33096689962);
117
+ - [production PyPI release](https://pypi.org/project/patchshuttle/0.1.0a4/)
118
+ and a clean post-release installation smoke test.
119
+
120
+ TestPyPI and production PyPI received byte-identical distributions:
121
+
122
+ - wheel `patchshuttle-0.1.0a4-py3-none-any.whl`, 167610 bytes,
123
+ SHA-256:
124
+ `b5a372b3879ea7382903556cb041ff9233d5e44624da28a5d1a2d8a2bdd2c832`;
125
+ - source archive `patchshuttle-0.1.0a4.tar.gz`, 296869 bytes,
126
+ SHA-256:
127
+ `14585ad971f374da2466807e876c4742acd140a069ae2ab159afccec297ad05c`.
128
+
129
+ A separate clean Windows CPython 3.14 temporary environment installed
130
+ `patchshuttle[html]==0.1.0a4` from production PyPI with
131
+ `--no-cache-dir`. `patchshuttle version` reported
132
+ `PatchShuttle 0.1.0a4`; `patchshuttle capabilities` reported
133
+ `patchshuttle_version: 0.1.0a4` and `protocol: 1`.
134
+
135
+ The **Tested with ChatGPT** statement remains scoped to the separately
136
+ recorded `0.1.0a2` end-to-end workflow above. This release record does
137
+ not extend that claim to every action, AI model, project, or intentional
138
+ failure and rollback path.
101
139
  ## 1. Local release gate
102
140
 
103
141
  From a clean repository root, use Python 3.12 and start with an empty `dist/`
@@ -119,8 +157,8 @@ python tools/wheel_smoke.py dist/patchshuttle-<VERSION>-py3-none-any.whl --versi
119
157
 
120
158
  `release_checks.py` requires exactly one wheel and one source archive for the
121
159
  source version and writes `dist/SHA256SUMS`. Replace `<VERSION>` with the exact
122
- source version under qualification. For the recorded qualification above it
123
- was `0.1.0a3`. Do not reuse an immutable published version for a future upload.
160
+ source version under qualification. For the most recent recorded qualification it
161
+ was `0.1.0a4`. Do not reuse an immutable published version for a future upload.
124
162
 
125
163
  During a source-version transition, metadata in an already-installed editable
126
164
  environment may still report the previous version until the package is
@@ -128,11 +166,12 @@ reinstalled. Source-tree tests validate the imported source version. The build,
128
166
  `release_checks.py`, and clean-wheel smoke test are the authoritative metadata
129
167
  alignment gates for the new distributions.
130
168
 
131
- For the next alpha, the local and hosted suites must also retain explicit
132
- coverage for formatter baseline-versus-planned classification, per-tool local
133
- exclusions, `django_import_check`, and rollback after runtime `.pyc` creation.
134
- The plan and run logs must show the resolved formatter decision for each
135
- changed Python path.
169
+ Future release candidates must retain explicit coverage for formatter
170
+ baseline-versus-planned classification, per-tool local exclusions,
171
+ `django_import_check`, rollback after runtime `.pyc` creation, bounded Python
172
+ structure discovery, architecture-ratchet evaluation, structured-history wheel
173
+ contents, and clean-installed history persistence and retrieval. Plan and run
174
+ logs must keep exposing resolved formatter and architecture decisions.
136
175
 
137
176
  ## 2. Publish the repository and run CI
138
177
 
@@ -1,3 +1,3 @@
1
1
  """Single source of truth for the PatchShuttle package version."""
2
2
 
3
- __version__ = "0.1.0a4"
3
+ __version__ = "0.1.0a5"
@@ -26,6 +26,7 @@ from patchshuttle.execution import (
26
26
  record_declined_plan,
27
27
  resolve_registered_job,
28
28
  )
29
+ from patchshuttle.history.cli import history_command
29
30
  from patchshuttle.logging import (
30
31
  AttemptLogData,
31
32
  current_run_clock,
@@ -74,6 +75,9 @@ def main(workspace_path: Path | None) -> None:
74
75
  """Run local, auditable workflows for AI-assisted project changes."""
75
76
 
76
77
 
78
+ main.add_command(history_command)
79
+
80
+
77
81
  @main.command()
78
82
  def version() -> None:
79
83
  """Print the installed PatchShuttle version."""
@@ -328,10 +332,7 @@ def snapshot_command() -> None:
328
332
  except WorkspaceError as error:
329
333
  _fail_workspace(error, failure_prefix="SNAPSHOT_FAILED")
330
334
  except ExecutionError as error:
331
- click.echo(
332
- _render_execution_error(error, prefix="SNAPSHOT_FAILED"),
333
- err=True,
334
- )
335
+ click.echo(_render_execution_error(error, prefix="SNAPSHOT_FAILED"), err=True)
335
336
  raise click.exceptions.Exit(execution_exit_code(error.code)) from error
336
337
  click.echo(
337
338
  "\n".join(
@@ -355,10 +356,7 @@ def handoff_command() -> None:
355
356
  except WorkspaceError as error:
356
357
  _fail_workspace(error, failure_prefix="HANDOFF_FAILED")
357
358
  except ExecutionError as error:
358
- click.echo(
359
- _render_execution_error(error, prefix="HANDOFF_FAILED"),
360
- err=True,
361
- )
359
+ click.echo(_render_execution_error(error, prefix="HANDOFF_FAILED"), err=True)
362
360
  raise click.exceptions.Exit(execution_exit_code(error.code)) from error
363
361
  click.echo(
364
362
  "\n".join(
@@ -46,6 +46,7 @@ DEFAULT_PROTECTED_PATH_EXCEPTIONS = (
46
46
  DEFAULT_IGNORED_PATHS = (
47
47
  ".git/**",
48
48
  "patches/backups/**",
49
+ "patches/history/**",
49
50
  "patches/logs/**",
50
51
  "patches/state/**",
51
52
  "**/.venv/**",
@@ -268,6 +268,8 @@ class ExecutionError(RuntimeError):
268
268
  workspace_comparison: WorkspaceComparison | None = None,
269
269
  log_path: Path | None = None,
270
270
  archived_job_path: Path | None = None,
271
+ history_path: Path | None = None,
272
+ history_warning: str | None = None,
271
273
  ) -> None:
272
274
  self.code = code
273
275
  self.message = message
@@ -285,6 +287,8 @@ class ExecutionError(RuntimeError):
285
287
  self.workspace_comparison = workspace_comparison
286
288
  self.log_path = log_path
287
289
  self.archived_job_path = archived_job_path
290
+ self.history_path = history_path
291
+ self.history_warning = history_warning
288
292
  super().__init__(message)
289
293
 
290
294
  def __str__(self) -> str: