codesuture 0.7.0__tar.gz → 0.7.1__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 (63) hide show
  1. codesuture-0.7.1/.gitignore +53 -0
  2. {codesuture-0.7.0 → codesuture-0.7.1}/CHANGELOG.md +68 -0
  3. {codesuture-0.7.0 → codesuture-0.7.1}/PKG-INFO +51 -36
  4. {codesuture-0.7.0 → codesuture-0.7.1}/README.md +227 -213
  5. codesuture-0.7.1/codesuture/__init__.py +2 -0
  6. codesuture-0.7.1/codesuture/_eval_fix.py +5 -0
  7. {codesuture-0.7.0 → codesuture-0.7.1}/codesuture/audit.py +7 -10
  8. {codesuture-0.7.0 → codesuture-0.7.1}/codesuture/cli.py +4 -1
  9. {codesuture-0.7.0 → codesuture-0.7.1}/codesuture/explain.py +10 -10
  10. {codesuture-0.7.0 → codesuture-0.7.1}/codesuture/fingerprint.py +26 -21
  11. {codesuture-0.7.0 → codesuture-0.7.1}/codesuture/guard_synthesizer.py +164 -156
  12. {codesuture-0.7.0 → codesuture-0.7.1}/codesuture/middleware.py +10 -5
  13. codesuture-0.7.1/codesuture/opcodes.py +146 -0
  14. {codesuture-0.7.0 → codesuture-0.7.1}/codesuture/pattern_matcher.py +100 -91
  15. {codesuture-0.7.0 → codesuture-0.7.1}/codesuture/persistence.py +52 -21
  16. codesuture-0.7.1/codesuture/rewind.py +78 -0
  17. codesuture-0.7.1/codesuture/rollback.py +167 -0
  18. {codesuture-0.7.0 → codesuture-0.7.1}/codesuture/tracer.py +359 -315
  19. {codesuture-0.7.0 → codesuture-0.7.1}/codesuture.egg-info/PKG-INFO +51 -36
  20. {codesuture-0.7.0 → codesuture-0.7.1}/codesuture.egg-info/SOURCES.txt +6 -6
  21. {codesuture-0.7.0 → codesuture-0.7.1}/pyproject.toml +2 -1
  22. {codesuture-0.7.0 → codesuture-0.7.1}/tests/test_new_guards.py +48 -48
  23. codesuture-0.7.1/tests/test_opcodes.py +222 -0
  24. {codesuture-0.7.0 → codesuture-0.7.1}/tests/test_pattern_matcher.py +15 -2
  25. codesuture-0.7.1/tests/test_persistence.py +201 -0
  26. codesuture-0.7.1/tests/test_rollback.py +210 -0
  27. codesuture-0.7.1/tests/test_thread_safety.py +138 -0
  28. codesuture-0.7.1/tests/test_transparency.py +135 -0
  29. codesuture-0.7.0/.gitignore +0 -14
  30. codesuture-0.7.0/codesuture/__init__.py +0 -2
  31. codesuture-0.7.0/codesuture/_eval_fix.py +0 -5
  32. codesuture-0.7.0/codesuture/rewind.py +0 -49
  33. codesuture-0.7.0/codesuture/rollback.py +0 -85
  34. codesuture-0.7.0/tests/closure_test.py +0 -16
  35. codesuture-0.7.0/tests/debug_gc.py +0 -23
  36. codesuture-0.7.0/tests/harness3.py +0 -46
  37. codesuture-0.7.0/tests/test_codesuture_debuggee.py +0 -17
  38. codesuture-0.7.0/tests/test_tracer_active_shield.py +0 -70
  39. codesuture-0.7.0/tests/test_unknown_bug.py +0 -9
  40. {codesuture-0.7.0 → codesuture-0.7.1}/LICENSE +0 -0
  41. {codesuture-0.7.0 → codesuture-0.7.1}/MANIFEST.in +0 -0
  42. {codesuture-0.7.0 → codesuture-0.7.1}/codesuture/__main__.py +0 -0
  43. {codesuture-0.7.0 → codesuture-0.7.1}/codesuture/code_replacer.py +0 -0
  44. {codesuture-0.7.0 → codesuture-0.7.1}/codesuture/codesuture_fix.py +0 -0
  45. {codesuture-0.7.0 → codesuture-0.7.1}/codesuture/debuggee.py +0 -0
  46. {codesuture-0.7.0 → codesuture-0.7.1}/codesuture/diff_guard.py +0 -0
  47. {codesuture-0.7.0 → codesuture-0.7.1}/codesuture/knowledge.py +0 -0
  48. {codesuture-0.7.0 → codesuture-0.7.1}/codesuture/plugins/__init__.py +0 -0
  49. {codesuture-0.7.0 → codesuture-0.7.1}/codesuture/plugins/autonomous.py +0 -0
  50. {codesuture-0.7.0 → codesuture-0.7.1}/codesuture/sandbox.py +0 -0
  51. {codesuture-0.7.0 → codesuture-0.7.1}/codesuture/shadow.py +0 -0
  52. {codesuture-0.7.0 → codesuture-0.7.1}/codesuture/watcher.py +0 -0
  53. {codesuture-0.7.0 → codesuture-0.7.1}/codesuture.egg-info/dependency_links.txt +0 -0
  54. {codesuture-0.7.0 → codesuture-0.7.1}/codesuture.egg-info/entry_points.txt +0 -0
  55. {codesuture-0.7.0 → codesuture-0.7.1}/codesuture.egg-info/requires.txt +0 -0
  56. {codesuture-0.7.0 → codesuture-0.7.1}/codesuture.egg-info/top_level.txt +0 -0
  57. {codesuture-0.7.0 → codesuture-0.7.1}/setup.cfg +0 -0
  58. {codesuture-0.7.0 → codesuture-0.7.1}/setup.py +0 -0
  59. {codesuture-0.7.0 → codesuture-0.7.1}/tests/__init__.py +0 -0
  60. {codesuture-0.7.0 → codesuture-0.7.1}/tests/test_e2e.py +0 -0
  61. {codesuture-0.7.0 → codesuture-0.7.1}/tests/test_guard_synthesizer.py +0 -0
  62. {codesuture-0.7.0 → codesuture-0.7.1}/tests/test_harness.py +0 -0
  63. {codesuture-0.7.0 → codesuture-0.7.1}/tests/test_harness2.py +0 -0
@@ -0,0 +1,53 @@
1
+ # ---------------------------
2
+ # Python
3
+ # ---------------------------
4
+ __pycache__/
5
+ *.pyc
6
+ *.pyo
7
+ *.egg-info/
8
+ dist/
9
+ build/
10
+
11
+ # ---------------------------
12
+ # Virtual environments
13
+ # ---------------------------
14
+ .venv/
15
+ env/
16
+ venv/
17
+
18
+ # ---------------------------
19
+ # IDE / editor
20
+ # ---------------------------
21
+ .vscode/
22
+ .idea/
23
+ *.code-workspace
24
+
25
+ # ---------------------------
26
+ # CodeSuture runtime artifacts
27
+ # ---------------------------
28
+ .codesuture_store/
29
+ .codesuture_cache/
30
+ .livepatch_cache/
31
+ .codesuture_fingerprints
32
+ .models/
33
+
34
+ # ---------------------------
35
+ # Test / CI artifacts
36
+ # ---------------------------
37
+ .pytest_cache/
38
+ htmlcov/
39
+ .coverage
40
+ *.log
41
+
42
+ # ---------------------------
43
+ # Planning & roadmap (local only)
44
+ # ---------------------------
45
+ ROADMAP.md
46
+ implementation_plan.md
47
+ task.md
48
+ walkthrough.md
49
+
50
+ # ---------------------------
51
+ # Old verification suites (deleted)
52
+ # ---------------------------
53
+ v4test/
@@ -5,6 +5,74 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [0.7.1] - 2026-05-25
9
+
10
+ ### Fixed — Safety Hardening
11
+ - **Index guard no longer returns wrong item:** `index_guard` now returns a
12
+ type-appropriate default value instead of clamping the index to 0 (which
13
+ silently returned `list[0]` — a data corruption bug)
14
+ - **Callable guard no longer replaces unknown functions with `lambda: 0`:**
15
+ Unknown callables are skipped with a warning instead of being silently
16
+ replaced with a stub that could bypass validation logic
17
+ - **Exception tracebacks shown by default:** `_codesuture_excepthook` now
18
+ prints a structured summary of self-healed exceptions instead of
19
+ suppressing all output; use `--silent` to restore old behavior
20
+ - **Rollback restores runtime code:** `codesuture rollback` now restores
21
+ original bytecode in memory (not just deletes files); original code
22
+ objects are backed up before patching and saved as `.orig.code` files
23
+ - **Marshal integrity checks:** Persisted `.code` files now include SHA-256
24
+ checksums in metadata; tampered files are refused on load
25
+ - **Thread safety:** Added locking on `HEALED_FUNCTIONS`,
26
+ `ANNOUNCED_HEALED_FUNCTIONS`, `_retried_exc_types`, fingerprint registry,
27
+ and `CodeSutureMetaFinder` recursion guard (now uses `threading.local()`)
28
+ - **`_INLINE_STRATEGIES` set populated:** Try-block detection for inline
29
+ strategies (`subscript_guard`, `key_guard`, `division_guard`,
30
+ `chain_subscript_guard`) is now active — previously disabled by empty set
31
+ - **Safe tuple propagation:** Replaced dangerous `ctypes` memory write into
32
+ tuple `ob_item` array with safe `code.replace(co_consts=...)` approach
33
+
34
+ ### Added — CPython 3.12+ Compatibility
35
+ - **`codesuture/opcodes.py`:** Version-aware opcode abstraction layer
36
+ providing correct opcode names, instruction builders, and opcode name
37
+ sets for Python 3.11, 3.12, and 3.13+
38
+ - All guard builders now use `opcodes.py` instead of hardcoded 3.11-only
39
+ opcode names (`PRECALL`, `POP_JUMP_FORWARD_IF_FALSE`, `LOAD_METHOD`)
40
+ - Pattern matcher uses opcode sets for resilient bytecode analysis across
41
+ Python versions
42
+ - Frame rewind offset detection is now runtime-detected instead of
43
+ hardcoded to CPython 3.11 struct layout (`id(frame) + 40`)
44
+ - CLI: added `--silent` flag to `codesuture run`
45
+
46
+ ### Changed
47
+ - Removed old test files, v4test/ verification suite, and heavily-mocked
48
+ tracer test; replaced with comprehensive new test suite
49
+
50
+ ### Fixed — Audit Round (Post-Release)
51
+ - **`_eval_fix.py`:** Fixed `ImportError` — was importing `apply_fix_with_info`
52
+ which doesn't exist; changed to `apply_fix`
53
+ - **`_build_subscript_guarded_code`:** No longer calls `.get()` on lists/tuples;
54
+ now checks `isinstance(container, dict)` before using `.get()`, falls back to
55
+ direct subscript for non-dict containers
56
+ - **`rollback_runtime`:** Removed dead `gc.get_referrers` loop that had only `pass`
57
+ in its body
58
+ - **`middleware.py`:** Retry tracking now uses `(exc_type, filename, func_name)`
59
+ tuple instead of bare exception type — prevents second crash of same type in
60
+ different function from being silently ignored
61
+ - **`persistence.py`:** Thread name now uses `threading.current_thread().name`
62
+ instead of hardcoded `"MainThread"`; `datetime.utcnow()` replaced with
63
+ `datetime.now(timezone.utc)` (Python 3.12 deprecation fix);
64
+ `_iter_cached_function_names` now excludes `.orig.code` files
65
+ - **`audit.py`:** Unicode box-drawing characters now actually used when terminal
66
+ supports them (was identical ASCII `|` on both branches);
67
+ `datetime.utcnow()` deprecation fixed
68
+ - **`rollback.py`:** `datetime.utcnow()` replaced with timezone-aware datetime
69
+ (was causing `TypeError` when comparing with timezone-aware `patched_at` values)
70
+ - **`tracer.py`:** `--silent` flag now gates ALL 20+ informational print statements
71
+ (fingerprint hits, patch applied, already healed, etc.); errors/warnings still
72
+ always print
73
+ - **`opcodes.py`:** Added Python 3.13 compatibility documentation; expanded
74
+ `SUBSCRIPT_OPCODES` to include `BINARY_SLICE` for 3.13 slice operations
75
+
8
76
  ## [0.7.0] - 2026-05-17
9
77
 
10
78
  ### Added
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: codesuture
3
- Version: 0.7.0
3
+ Version: 0.7.1
4
4
  Summary: Runtime Python bytecode patcher with guard knowledge base, persistence, and self-healing re-execution
5
5
  License-Expression: MIT
6
6
  Project-URL: Source, https://github.com/codesuture/codesuture
@@ -11,6 +11,7 @@ Classifier: Topic :: Software Development :: Debuggers
11
11
  Classifier: Topic :: Software Development :: Libraries :: Python Modules
12
12
  Classifier: Programming Language :: Python :: 3.11
13
13
  Classifier: Programming Language :: Python :: 3.12
14
+ Classifier: Programming Language :: Python :: 3.13
14
15
  Requires-Python: >=3.11
15
16
  Description-Content-Type: text/markdown
16
17
  License-File: LICENSE
@@ -21,7 +22,14 @@ Dynamic: license-file
21
22
 
22
23
  # CodeSuture
23
24
 
24
- **Runtime guard synthesis for CPython. Catches structural crashes, patches live bytecode, keeps your server running.**
25
+ ![CodeSuture Banner](assets/banner.png)
26
+
27
+ **Runtime guard synthesis for CPython 3.11+. Catches structural crashes, patches live bytecode, keeps your server running.**
28
+
29
+ [![Version](https://img.shields.io/badge/version-0.7.1-blue)]()
30
+ [![Python](https://img.shields.io/badge/python-3.11%2B-brightgreen)]()
31
+ [![License: MIT](https://img.shields.io/badge/license-MIT-green)](LICENSE)
32
+ [![Status](https://img.shields.io/badge/status-beta-orange)]()
25
33
 
26
34
  ```
27
35
  pip install codesuture
@@ -97,11 +105,11 @@ No 500. No traceback. Server process intact.
97
105
 
98
106
  ## How it works
99
107
 
100
- 1. **Catch** — `sys.settrace` intercepts exceptions at the exact frame and bytecode offset.
108
+ 1. **Catch** — `sys.settrace` (3.11) or `sys.monitoring` (3.12+) intercepts exceptions at the exact frame and bytecode offset.
101
109
  2. **Analyze** — The pattern matcher walks the instruction chain and identifies the failing variable or operation.
102
110
  3. **Patch** — The guard synthesizer injects new bytecode into the function's code object. A semantic diff gate rejects patches that change too much logic.
103
- 4. **Rewind** — Execution restarts from the patched function. The guard prevents recurrence.
104
- 5. **Persist** — The patched code object is serialized to `.codesuture_store/` with JSON metadata. Subsequent runs load it before the first call.
111
+ 4. **Rewind** — Execution restarts from the patched function via `f_lineno` setter. The guard prevents recurrence.
112
+ 5. **Persist** — The patched code object is serialized to `.codesuture_store/` with SHA-256 integrity checks and JSON metadata. Subsequent runs load it before the first call.
105
113
 
106
114
  No source files are modified.
107
115
 
@@ -121,6 +129,7 @@ No source files are modified.
121
129
  | `str_coerce_guard` | `TypeError` on string concat | `"age: " + 25` |
122
130
  | `file_guard` | `FileNotFoundError` | `open(path)` when file is missing |
123
131
  | `callable_guard` | `TypeError` calling `None` | `func()` when `func` is `None` |
132
+ | `return_guard` | `TypeError` on `None` return | Downstream use of a `None` return value |
124
133
 
125
134
  ---
126
135
 
@@ -129,16 +138,17 @@ No source files are modified.
129
138
  | Command | Flags | What it does |
130
139
  |---|---|---|
131
140
  | `codesuture run <script>` | | Run with live patching |
132
- | `codesuture run <script>` | `--verbose` | Show patch diffs and instruction deltas |
133
- | `codesuture run <script>` | `--shadow` | Warn when patched functions return sentinel values |
134
- | `codesuture run <script>` | `--dry-run` | Preview patches without applying |
135
- | `codesuture run <script>` | `--ttl DAYS` | Set patch expiry (default: 7 days) |
136
- | `codesuture run <script>` | `--retries N` | Max re-execution attempts (default: 3) |
141
+ | | `--verbose` | Show patch diffs and instruction deltas |
142
+ | | `--shadow` | Warn when patched functions return sentinel values |
143
+ | | `--dry-run` | Preview patches without applying |
144
+ | | `--silent` | Suppress all informational output |
145
+ | | `--ttl DAYS` | Set patch expiry (default: 7 days) |
146
+ | | `--retries N` | Max re-execution attempts (default: 3) |
137
147
  | `codesuture watch <script>` | `--max-restarts N` | Run continuously, restart after each patch |
138
148
  | `codesuture audit` | | Show all active patches in a table |
139
149
  | `codesuture explain` | | Plain-language breakdown of every patch |
140
150
  | `codesuture explain <name>` | | Explain one function's patch |
141
- | `codesuture rollback <name>` | | Remove one persisted patch |
151
+ | `codesuture rollback <name>` | | Remove one persisted patch and restore runtime code |
142
152
  | `codesuture rollback` | `--all` | Remove all patches and fingerprint registry |
143
153
  | `codesuture rollback` | `--dry-run` | Preview what would be removed |
144
154
 
@@ -156,15 +166,6 @@ Every patched response carries:
156
166
  X-CodeSuture: patched=1; guard=<type>; target=<variable>
157
167
  ```
158
168
 
159
- Four crash types, one server, all returning 200:
160
-
161
- ```
162
- "GET /user-data HTTP/1.1" 200 ← null_guard on None object
163
- "GET /config HTTP/1.1" 200 ← key_guard on missing key
164
- "GET /process-payment HTTP/1.1" 200 ← type_coercion_guard on bad input
165
- "GET /latest-user HTTP/1.1" 200 ← chain_subscript_guard on out-of-bounds
166
- ```
167
-
168
169
  ### WSGI middleware
169
170
 
170
171
  ```python
@@ -173,21 +174,19 @@ from codesuture.middleware import CodeSutureMiddleware
173
174
  app = CodeSutureMiddleware(wsgi_app)
174
175
  ```
175
176
 
176
- ---
177
+ See the implementation in [codesuture/middleware.py](codesuture/middleware.py).
177
178
 
178
- ## Runtime Intelligence
179
-
180
- **Semantic diff gate** — Patches that modify too many instructions for the guard type are automatically rejected. The engine never corrupts a complex function to patch a simple crash.
181
-
182
- **Caller-aware propagation** — After patching, CodeSuture uses `gc.get_referrers` to update every live reference to the original code object: closures, bound methods, partials. No stale copy survives.
183
-
184
- **Shadow execution mode** — `--shadow` monitors return values of patched functions. If a sentinel default leaks into downstream logic, a warning fires before it causes a second failure.
185
-
186
- **Patch expiry** — Every persisted patch carries a TTL. When it ages past the limit, CodeSuture logs a reminder to fix the root cause in source. Patches are scaffolding, not permanent fixes.
179
+ ---
187
180
 
188
- **Bytecode fingerprint registry** — Crash sites are hashed by their surrounding instruction window. Repeat patterns get instant cached guard application without re-analysis.
181
+ ## Safety features
189
182
 
190
- **Audit trail** — `codesuture audit` shows every active patch: function, guard type, target, default value, age. `codesuture explain` gives a plain-language breakdown of what changed and whether the default is safe downstream.
183
+ - **Semantic diff gate** — Patches that modify too many instructions are rejected. The engine never corrupts a complex function to fix a simple crash.
184
+ - **SHA-256 integrity** — Persisted patches are checksummed. Tampered `.code` files are refused on load.
185
+ - **Caller-aware propagation** — After patching, `gc.get_referrers` updates every live reference: closures, bound methods, partials. No stale copy survives.
186
+ - **Patch validation** — Synthesized bytecode is checked for `LOAD_FAST` references to variables not in `co_varnames`. Invalid patches are rejected before application.
187
+ - **Patch expiry (TTL)** — Every patch carries a time-to-live. Aged patches trigger a warning to fix the root cause in source.
188
+ - **Thread safety** — All shared state (fingerprint registry, persistence store, healed function sets) is protected by locks.
189
+ - **Rollback** — `codesuture rollback` removes persisted files AND restores original code in the running process.
191
190
 
192
191
  ---
193
192
 
@@ -197,12 +196,13 @@ app = CodeSutureMiddleware(wsgi_app)
197
196
 
198
197
  **Not a static analyzer.** It operates at runtime on live bytecode, not on source.
199
198
 
200
- **Not autonomous.** Patches should be reviewed via `codesuture audit` and `codesuture explain`. The goal is to keep your program running while you fix the root cause not to replace the fix.
199
+ **Not autonomous by default.** All patches are deterministic rule-based guards. An opt-in `--autonomous` flag exists for experimental LLM-powered suggestions via local models, but it is off by default and never auto-applies fixes.
201
200
 
202
201
  ---
203
202
 
204
- ## Limitations
203
+ ## Known limitations
205
204
 
205
+ <<<<<<< HEAD
206
206
  **Python 3.11+ only.** CodeSuture depends on CPython 3.11 bytecode structures.
207
207
 
208
208
  **Comprehensions are not patchable.** List, dict, set, and generator comprehensions are anonymous nested code objects. CodeSuture logs a warning and skips them. Refactor into a named function to enable patching.
@@ -219,16 +219,31 @@ app = CodeSutureMiddleware(wsgi_app)
219
219
 
220
220
  ## Roadmap
221
221
 
222
- Tracked in `ROADMAP.md`. v1.0 themes:
222
+ Tracked in [ROADMAP.md](ROADMAP.md). v1.0 themes:
223
223
 
224
224
  - `sys.monitoring` as the default engine on Python 3.12+ (zero line-tracing overhead on hot paths)
225
225
  - Stronger transaction recovery boundaries across web frameworks
226
226
  - Verified source-level repair proposals via local LLM
227
227
  - Fleet governance, audit lifecycle, and incident export
228
228
  - Language-neutral incident protocol for future polyglot adapters
229
+ =======
230
+ - **Python 3.11+ only.** Depends on CPython bytecode structures introduced in 3.11.
231
+ - **3.12+ frame rewind.** The Python-level `f_lineno` setter is used on 3.12+. The ctypes fallback is disabled on 3.12+ to prevent memory corruption from struct layout changes.
232
+ - **Comprehensions are not patchable.** List/dict/set/generator comprehensions are anonymous nested code objects. CodeSuture logs a warning and skips them.
233
+ - **Semantic bugs are out of scope.** CodeSuture fixes structural crashes — null access, missing keys, type mismatches, bounds errors. Logic errors that produce wrong results without crashing cannot be detected.
234
+ - **Single-process scope.** Patches apply per-process. `.codesuture_store/` is shared on disk, so patches persist across restarts.
235
+ - **Async support is experimental.** Standard `async def` functions are patched. Async generators and deeply nested `await` chains may not be handled correctly.
236
+ - **HTTP recovery is validated against `http.server`.** Full ASGI framework support is not yet implemented.
237
+ >>>>>>> 0cedff8 (v0.7.1: safety hardening, audit fixes, 3.12+ compat, 120 tests)
229
238
 
230
239
  ---
231
240
 
232
241
  ## License
233
242
 
234
- MIT. See `LICENSE` for details.
243
+ <<<<<<< HEAD
244
+ MIT. See [LICENSE](LICENSE) for details. For a detailed history of changes, see the [Changelog](CHANGELOG.md).
245
+ =======
246
+ MIT. See [LICENSE](LICENSE) for details.
247
+
248
+ For a detailed history of changes, see the [Changelog](CHANGELOG.md).
249
+ >>>>>>> 0cedff8 (v0.7.1: safety hardening, audit fixes, 3.12+ compat, 120 tests)