codesuture 0.6.0__tar.gz → 0.7.0__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 (58) hide show
  1. codesuture-0.7.0/.gitignore +14 -0
  2. {codesuture-0.6.0 → codesuture-0.7.0}/CHANGELOG.md +17 -6
  3. codesuture-0.7.0/PKG-INFO +234 -0
  4. codesuture-0.7.0/README.md +213 -0
  5. codesuture-0.7.0/codesuture/__init__.py +2 -0
  6. {codesuture-0.6.0 → codesuture-0.7.0}/codesuture/cli.py +1 -1
  7. {codesuture-0.6.0 → codesuture-0.7.0}/codesuture/guard_synthesizer.py +101 -58
  8. {codesuture-0.6.0 → codesuture-0.7.0}/codesuture/pattern_matcher.py +59 -16
  9. codesuture-0.7.0/codesuture/rewind.py +49 -0
  10. {codesuture-0.6.0 → codesuture-0.7.0}/codesuture/tracer.py +352 -29
  11. codesuture-0.7.0/codesuture.egg-info/PKG-INFO +234 -0
  12. {codesuture-0.6.0 → codesuture-0.7.0}/codesuture.egg-info/SOURCES.txt +1 -0
  13. {codesuture-0.6.0 → codesuture-0.7.0}/pyproject.toml +4 -6
  14. {codesuture-0.6.0 → codesuture-0.7.0}/tests/test_new_guards.py +46 -6
  15. codesuture-0.7.0/tests/test_tracer_active_shield.py +70 -0
  16. codesuture-0.6.0/.gitignore +0 -33
  17. codesuture-0.6.0/PKG-INFO +0 -167
  18. codesuture-0.6.0/README.md +0 -146
  19. codesuture-0.6.0/codesuture/__init__.py +0 -2
  20. codesuture-0.6.0/codesuture/rewind.py +0 -43
  21. codesuture-0.6.0/codesuture.egg-info/PKG-INFO +0 -167
  22. {codesuture-0.6.0 → codesuture-0.7.0}/LICENSE +0 -0
  23. {codesuture-0.6.0 → codesuture-0.7.0}/MANIFEST.in +0 -0
  24. {codesuture-0.6.0 → codesuture-0.7.0}/codesuture/__main__.py +0 -0
  25. {codesuture-0.6.0 → codesuture-0.7.0}/codesuture/_eval_fix.py +0 -0
  26. {codesuture-0.6.0 → codesuture-0.7.0}/codesuture/audit.py +0 -0
  27. {codesuture-0.6.0 → codesuture-0.7.0}/codesuture/code_replacer.py +0 -0
  28. {codesuture-0.6.0 → codesuture-0.7.0}/codesuture/codesuture_fix.py +0 -0
  29. {codesuture-0.6.0 → codesuture-0.7.0}/codesuture/debuggee.py +0 -0
  30. {codesuture-0.6.0 → codesuture-0.7.0}/codesuture/diff_guard.py +0 -0
  31. {codesuture-0.6.0 → codesuture-0.7.0}/codesuture/explain.py +0 -0
  32. {codesuture-0.6.0 → codesuture-0.7.0}/codesuture/fingerprint.py +0 -0
  33. {codesuture-0.6.0 → codesuture-0.7.0}/codesuture/knowledge.py +0 -0
  34. {codesuture-0.6.0 → codesuture-0.7.0}/codesuture/middleware.py +0 -0
  35. {codesuture-0.6.0 → codesuture-0.7.0}/codesuture/persistence.py +0 -0
  36. {codesuture-0.6.0 → codesuture-0.7.0}/codesuture/plugins/__init__.py +0 -0
  37. {codesuture-0.6.0 → codesuture-0.7.0}/codesuture/plugins/autonomous.py +0 -0
  38. {codesuture-0.6.0 → codesuture-0.7.0}/codesuture/rollback.py +0 -0
  39. {codesuture-0.6.0 → codesuture-0.7.0}/codesuture/sandbox.py +0 -0
  40. {codesuture-0.6.0 → codesuture-0.7.0}/codesuture/shadow.py +0 -0
  41. {codesuture-0.6.0 → codesuture-0.7.0}/codesuture/watcher.py +0 -0
  42. {codesuture-0.6.0 → codesuture-0.7.0}/codesuture.egg-info/dependency_links.txt +0 -0
  43. {codesuture-0.6.0 → codesuture-0.7.0}/codesuture.egg-info/entry_points.txt +0 -0
  44. {codesuture-0.6.0 → codesuture-0.7.0}/codesuture.egg-info/requires.txt +0 -0
  45. {codesuture-0.6.0 → codesuture-0.7.0}/codesuture.egg-info/top_level.txt +0 -0
  46. {codesuture-0.6.0 → codesuture-0.7.0}/setup.cfg +0 -0
  47. {codesuture-0.6.0 → codesuture-0.7.0}/setup.py +0 -0
  48. {codesuture-0.6.0 → codesuture-0.7.0}/tests/__init__.py +0 -0
  49. {codesuture-0.6.0 → codesuture-0.7.0}/tests/closure_test.py +0 -0
  50. {codesuture-0.6.0 → codesuture-0.7.0}/tests/debug_gc.py +0 -0
  51. {codesuture-0.6.0 → codesuture-0.7.0}/tests/harness3.py +0 -0
  52. {codesuture-0.6.0 → codesuture-0.7.0}/tests/test_codesuture_debuggee.py +0 -0
  53. {codesuture-0.6.0 → codesuture-0.7.0}/tests/test_e2e.py +0 -0
  54. {codesuture-0.6.0 → codesuture-0.7.0}/tests/test_guard_synthesizer.py +0 -0
  55. {codesuture-0.6.0 → codesuture-0.7.0}/tests/test_harness.py +0 -0
  56. {codesuture-0.6.0 → codesuture-0.7.0}/tests/test_harness2.py +0 -0
  57. {codesuture-0.6.0 → codesuture-0.7.0}/tests/test_pattern_matcher.py +0 -0
  58. {codesuture-0.6.0 → codesuture-0.7.0}/tests/test_unknown_bug.py +0 -0
@@ -0,0 +1,14 @@
1
+ __pycache__/
2
+ *.pyc
3
+ *.pyo
4
+ .venv/
5
+ env/
6
+ venv/
7
+ *.egg-info/
8
+ dist/
9
+ build/
10
+ .livepatch_cache/
11
+ .codesuture_cache/
12
+ .models/
13
+ .vscode/
14
+ *.code-workspace
@@ -5,6 +5,17 @@ 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.0] - 2026-05-17
9
+
10
+ ### Added
11
+ - Active Shield: after patching, the engine re-invokes the function with
12
+ original arguments to save the current transaction (eliminates
13
+ ERR_EMPTY_RESPONSE on first request to patched server endpoints)
14
+ - Python 3.12+ sys.monitoring dual engine: zero baseline overhead,
15
+ callback fires only on RAISE events instead of line-by-line tracing
16
+ - Transaction fallback: graceful JSON 500 response for network handlers
17
+ when re-invocation fails, preventing hanging socket connections
18
+
8
19
  ## [0.6.0] - 2026-05-12
9
20
 
10
21
  ### Fixed
@@ -58,12 +69,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
58
69
  ## [0.3.0] - 2026-05-06
59
70
 
60
71
  ### Added
61
- - Dark Upgrade D1: Semantic diff safety gate to prevent runaway bytecode corruption.
62
- - Dark Upgrade D2: Caller-aware patch propagation to automatically fix closures and bound methods in-memory.
63
- - Dark Upgrade D3: Shadow execution mode (`--shadow`) to monitor and warn when sentinel defaults leak downstream.
64
- - Dark Upgrade D4: Patch expiry TTL warnings to nudge developers toward source-level fixes.
65
- - Dark Upgrade D5: Bytecode fingerprint registry for instant cache hits on known crash patterns.
66
- - Dark Upgrade D6: `codesuture audit` command for viewing all active patches in a formatted table.
72
+ - Upgrade D1: Semantic diff safety gate to prevent runaway bytecode corruption.
73
+ - Upgrade D2: Caller-aware patch propagation to automatically fix closures and bound methods in-memory.
74
+ - Upgrade D3: Shadow execution mode (`--shadow`) to monitor and warn when sentinel defaults leak downstream.
75
+ - Upgrade D4: Patch expiry TTL warnings to nudge developers toward source-level fixes.
76
+ - Upgrade D5: Bytecode fingerprint registry for instant cache hits on known crash patterns.
77
+ - Upgrade D6: `codesuture audit` command for viewing all active patches in a formatted table.
67
78
 
68
79
  ### Fixed
69
80
  - Addressed Windows `UnicodeDecodeError` and `cp1252` terminal limitations by enforcing `utf-8` encoding.
@@ -0,0 +1,234 @@
1
+ Metadata-Version: 2.4
2
+ Name: codesuture
3
+ Version: 0.7.0
4
+ Summary: Runtime Python bytecode patcher with guard knowledge base, persistence, and self-healing re-execution
5
+ License-Expression: MIT
6
+ Project-URL: Source, https://github.com/codesuture/codesuture
7
+ Keywords: bytecode,runtime,patching,self-healing,debugging,null-safety,resilience
8
+ Classifier: Development Status :: 4 - Beta
9
+ Classifier: Intended Audience :: Developers
10
+ Classifier: Topic :: Software Development :: Debuggers
11
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
12
+ Classifier: Programming Language :: Python :: 3.11
13
+ Classifier: Programming Language :: Python :: 3.12
14
+ Requires-Python: >=3.11
15
+ Description-Content-Type: text/markdown
16
+ License-File: LICENSE
17
+ Requires-Dist: bytecode>=0.15.1
18
+ Provides-Extra: autonomous
19
+ Requires-Dist: llama-cpp-python; extra == "autonomous"
20
+ Dynamic: license-file
21
+
22
+ # CodeSuture
23
+
24
+ **Runtime guard synthesis for CPython. Catches structural crashes, patches live bytecode, keeps your server running.**
25
+
26
+ ```
27
+ pip install codesuture
28
+ ```
29
+
30
+ ---
31
+
32
+ ## What it does
33
+
34
+ When a Python program crashes, CodeSuture intercepts the exception at the exact bytecode instruction, disassembles the failing function, injects a deterministic guard into its code object in memory, and retries — without touching a single source file.
35
+
36
+ The patch persists. Next run, it loads before the first function call.
37
+
38
+ On a live HTTP server, CodeSuture patches the handler mid-request and replays the transaction. The client receives a 200. No restart. No traceback leak.
39
+
40
+ ---
41
+
42
+ ## Quick start — script
43
+
44
+ ```bash
45
+ codesuture run your_script.py
46
+ ```
47
+
48
+ ```
49
+ [CodeSuture] Caught AttributeError: 'NoneType' object has no attribute 'bio'
50
+ [CodeSuture] Applying null_guard on 'profile' ...
51
+ [CodeSuture] Patch applied to get_bio().
52
+ [CodeSuture] Re-executing after 1 patch(es)...
53
+
54
+ Session summary:
55
+ Patches applied: 1
56
+ ```
57
+
58
+ Run it again:
59
+
60
+ ```
61
+ [CodeSuture] Already healed, skipping: loaded persistent patch for get_bio
62
+ Session summary:
63
+ Patches applied: 0
64
+ ```
65
+
66
+ ---
67
+
68
+ ## Quick start — live server
69
+
70
+ ```bash
71
+ codesuture run server.py --verbose --retries 3
72
+ ```
73
+
74
+ ```
75
+ [CodeSuture] Caught AttributeError: 'NoneType' object has no attribute 'get_profile'
76
+ [CodeSuture] Applying null_guard on 'get_profile' ...
77
+ [CodeSuture DEBUG] Diff: +12 -9 instructions (allowed <= 55)
78
+ [CodeSuture] Patch applied to do_GET().
79
+ [CodeSuture] Transaction replay armed for do_GET().
80
+ [CodeSuture] Transaction replay: retrying patched HTTP handler in-place.
81
+ 127.0.0.1 - - "GET /user-data HTTP/1.1" 200 -
82
+ ```
83
+
84
+ The client sees:
85
+
86
+ ```http
87
+ HTTP/1.0 200 OK
88
+ Content-type: application/json
89
+ X-CodeSuture: patched=1; guard=null_guard; target=get_profile
90
+
91
+ {"result": null}
92
+ ```
93
+
94
+ No 500. No traceback. Server process intact.
95
+
96
+ ---
97
+
98
+ ## How it works
99
+
100
+ 1. **Catch** — `sys.settrace` intercepts exceptions at the exact frame and bytecode offset.
101
+ 2. **Analyze** — The pattern matcher walks the instruction chain and identifies the failing variable or operation.
102
+ 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.
105
+
106
+ No source files are modified.
107
+
108
+ ---
109
+
110
+ ## Supported guard types
111
+
112
+ | Guard type | Triggers on | Example |
113
+ |---|---|---|
114
+ | `null_guard` | `AttributeError` on `None` | `user.profile.bio` when `profile` is `None` |
115
+ | `key_guard` | `KeyError` | `cfg["timeout"]` when key is missing |
116
+ | `subscript_guard` | `TypeError` subscripting `None` | `data["key"]` when `data` is `None` |
117
+ | `chain_subscript_guard` | Nested subscript on `None` | `data["user"]["name"]` |
118
+ | `index_guard` | `IndexError` | `items[10]` when `len(items) == 2` |
119
+ | `type_coercion_guard` | `TypeError` on conversion | `int("not_a_number")` |
120
+ | `division_guard` | `ZeroDivisionError` | `x / count` when `count == 0` |
121
+ | `str_coerce_guard` | `TypeError` on string concat | `"age: " + 25` |
122
+ | `file_guard` | `FileNotFoundError` | `open(path)` when file is missing |
123
+ | `callable_guard` | `TypeError` calling `None` | `func()` when `func` is `None` |
124
+
125
+ ---
126
+
127
+ ## CLI reference
128
+
129
+ | Command | Flags | What it does |
130
+ |---|---|---|
131
+ | `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) |
137
+ | `codesuture watch <script>` | `--max-restarts N` | Run continuously, restart after each patch |
138
+ | `codesuture audit` | | Show all active patches in a table |
139
+ | `codesuture explain` | | Plain-language breakdown of every patch |
140
+ | `codesuture explain <name>` | | Explain one function's patch |
141
+ | `codesuture rollback <name>` | | Remove one persisted patch |
142
+ | `codesuture rollback` | `--all` | Remove all patches and fingerprint registry |
143
+ | `codesuture rollback` | `--dry-run` | Preview what would be removed |
144
+
145
+ ---
146
+
147
+ ## HTTP recovery
148
+
149
+ CodeSuture patches exceptions inside `http.server` and `socketserver` request handlers. The handler runs in its own thread — CodeSuture installs `threading.settrace` to intercept crashes there.
150
+
151
+ When a handler crashes and a guard is available, CodeSuture patches the function mid-request and replays the transaction in-place. The client receives a response instead of a socket close.
152
+
153
+ Every patched response carries:
154
+
155
+ ```
156
+ X-CodeSuture: patched=1; guard=<type>; target=<variable>
157
+ ```
158
+
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
+ ### WSGI middleware
169
+
170
+ ```python
171
+ from codesuture.middleware import CodeSutureMiddleware
172
+
173
+ app = CodeSutureMiddleware(wsgi_app)
174
+ ```
175
+
176
+ ---
177
+
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.
187
+
188
+ **Bytecode fingerprint registry** — Crash sites are hashed by their surrounding instruction window. Repeat patterns get instant cached guard application without re-analysis.
189
+
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.
191
+
192
+ ---
193
+
194
+ ## What CodeSuture is not
195
+
196
+ **Not a logger.** It does not record exceptions and move on. It patches the function and retries.
197
+
198
+ **Not a static analyzer.** It operates at runtime on live bytecode, not on source.
199
+
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.
201
+
202
+ ---
203
+
204
+ ## Limitations
205
+
206
+ **Python 3.11+ only.** CodeSuture depends on CPython 3.11 bytecode structures.
207
+
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.
209
+
210
+ **Semantic bugs are not patchable.** CodeSuture fixes structural crashes — null access, missing keys, type mismatches, bounds errors. Logic errors that produce wrong results without crashing are out of scope.
211
+
212
+ **Single-process scope.** Patches apply per-process. Multi-process applications need one instance per worker. `.codesuture_store/` is shared on disk, so patches load correctly on restart.
213
+
214
+ **Async support is experimental.** Standard `async def` functions are patched. Async generators and deeply nested `await` chains may not be handled correctly in all cases.
215
+
216
+ **HTTP recovery covers simple server paths.** Validated against `http.server` and `socketserver`. Full ASGI framework support is in progress.
217
+
218
+ ---
219
+
220
+ ## Roadmap
221
+
222
+ Tracked in `ROADMAP.md`. v1.0 themes:
223
+
224
+ - `sys.monitoring` as the default engine on Python 3.12+ (zero line-tracing overhead on hot paths)
225
+ - Stronger transaction recovery boundaries across web frameworks
226
+ - Verified source-level repair proposals via local LLM
227
+ - Fleet governance, audit lifecycle, and incident export
228
+ - Language-neutral incident protocol for future polyglot adapters
229
+
230
+ ---
231
+
232
+ ## License
233
+
234
+ MIT. See `LICENSE` for details.
@@ -0,0 +1,213 @@
1
+ # CodeSuture
2
+
3
+ **Runtime guard synthesis for CPython. Catches structural crashes, patches live bytecode, keeps your server running.**
4
+
5
+ ```
6
+ pip install codesuture
7
+ ```
8
+
9
+ ---
10
+
11
+ ## What it does
12
+
13
+ When a Python program crashes, CodeSuture intercepts the exception at the exact bytecode instruction, disassembles the failing function, injects a deterministic guard into its code object in memory, and retries — without touching a single source file.
14
+
15
+ The patch persists. Next run, it loads before the first function call.
16
+
17
+ On a live HTTP server, CodeSuture patches the handler mid-request and replays the transaction. The client receives a 200. No restart. No traceback leak.
18
+
19
+ ---
20
+
21
+ ## Quick start — script
22
+
23
+ ```bash
24
+ codesuture run your_script.py
25
+ ```
26
+
27
+ ```
28
+ [CodeSuture] Caught AttributeError: 'NoneType' object has no attribute 'bio'
29
+ [CodeSuture] Applying null_guard on 'profile' ...
30
+ [CodeSuture] Patch applied to get_bio().
31
+ [CodeSuture] Re-executing after 1 patch(es)...
32
+
33
+ Session summary:
34
+ Patches applied: 1
35
+ ```
36
+
37
+ Run it again:
38
+
39
+ ```
40
+ [CodeSuture] Already healed, skipping: loaded persistent patch for get_bio
41
+ Session summary:
42
+ Patches applied: 0
43
+ ```
44
+
45
+ ---
46
+
47
+ ## Quick start — live server
48
+
49
+ ```bash
50
+ codesuture run server.py --verbose --retries 3
51
+ ```
52
+
53
+ ```
54
+ [CodeSuture] Caught AttributeError: 'NoneType' object has no attribute 'get_profile'
55
+ [CodeSuture] Applying null_guard on 'get_profile' ...
56
+ [CodeSuture DEBUG] Diff: +12 -9 instructions (allowed <= 55)
57
+ [CodeSuture] Patch applied to do_GET().
58
+ [CodeSuture] Transaction replay armed for do_GET().
59
+ [CodeSuture] Transaction replay: retrying patched HTTP handler in-place.
60
+ 127.0.0.1 - - "GET /user-data HTTP/1.1" 200 -
61
+ ```
62
+
63
+ The client sees:
64
+
65
+ ```http
66
+ HTTP/1.0 200 OK
67
+ Content-type: application/json
68
+ X-CodeSuture: patched=1; guard=null_guard; target=get_profile
69
+
70
+ {"result": null}
71
+ ```
72
+
73
+ No 500. No traceback. Server process intact.
74
+
75
+ ---
76
+
77
+ ## How it works
78
+
79
+ 1. **Catch** — `sys.settrace` intercepts exceptions at the exact frame and bytecode offset.
80
+ 2. **Analyze** — The pattern matcher walks the instruction chain and identifies the failing variable or operation.
81
+ 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.
82
+ 4. **Rewind** — Execution restarts from the patched function. The guard prevents recurrence.
83
+ 5. **Persist** — The patched code object is serialized to `.codesuture_store/` with JSON metadata. Subsequent runs load it before the first call.
84
+
85
+ No source files are modified.
86
+
87
+ ---
88
+
89
+ ## Supported guard types
90
+
91
+ | Guard type | Triggers on | Example |
92
+ |---|---|---|
93
+ | `null_guard` | `AttributeError` on `None` | `user.profile.bio` when `profile` is `None` |
94
+ | `key_guard` | `KeyError` | `cfg["timeout"]` when key is missing |
95
+ | `subscript_guard` | `TypeError` subscripting `None` | `data["key"]` when `data` is `None` |
96
+ | `chain_subscript_guard` | Nested subscript on `None` | `data["user"]["name"]` |
97
+ | `index_guard` | `IndexError` | `items[10]` when `len(items) == 2` |
98
+ | `type_coercion_guard` | `TypeError` on conversion | `int("not_a_number")` |
99
+ | `division_guard` | `ZeroDivisionError` | `x / count` when `count == 0` |
100
+ | `str_coerce_guard` | `TypeError` on string concat | `"age: " + 25` |
101
+ | `file_guard` | `FileNotFoundError` | `open(path)` when file is missing |
102
+ | `callable_guard` | `TypeError` calling `None` | `func()` when `func` is `None` |
103
+
104
+ ---
105
+
106
+ ## CLI reference
107
+
108
+ | Command | Flags | What it does |
109
+ |---|---|---|
110
+ | `codesuture run <script>` | | Run with live patching |
111
+ | `codesuture run <script>` | `--verbose` | Show patch diffs and instruction deltas |
112
+ | `codesuture run <script>` | `--shadow` | Warn when patched functions return sentinel values |
113
+ | `codesuture run <script>` | `--dry-run` | Preview patches without applying |
114
+ | `codesuture run <script>` | `--ttl DAYS` | Set patch expiry (default: 7 days) |
115
+ | `codesuture run <script>` | `--retries N` | Max re-execution attempts (default: 3) |
116
+ | `codesuture watch <script>` | `--max-restarts N` | Run continuously, restart after each patch |
117
+ | `codesuture audit` | | Show all active patches in a table |
118
+ | `codesuture explain` | | Plain-language breakdown of every patch |
119
+ | `codesuture explain <name>` | | Explain one function's patch |
120
+ | `codesuture rollback <name>` | | Remove one persisted patch |
121
+ | `codesuture rollback` | `--all` | Remove all patches and fingerprint registry |
122
+ | `codesuture rollback` | `--dry-run` | Preview what would be removed |
123
+
124
+ ---
125
+
126
+ ## HTTP recovery
127
+
128
+ CodeSuture patches exceptions inside `http.server` and `socketserver` request handlers. The handler runs in its own thread — CodeSuture installs `threading.settrace` to intercept crashes there.
129
+
130
+ When a handler crashes and a guard is available, CodeSuture patches the function mid-request and replays the transaction in-place. The client receives a response instead of a socket close.
131
+
132
+ Every patched response carries:
133
+
134
+ ```
135
+ X-CodeSuture: patched=1; guard=<type>; target=<variable>
136
+ ```
137
+
138
+ Four crash types, one server, all returning 200:
139
+
140
+ ```
141
+ "GET /user-data HTTP/1.1" 200 ← null_guard on None object
142
+ "GET /config HTTP/1.1" 200 ← key_guard on missing key
143
+ "GET /process-payment HTTP/1.1" 200 ← type_coercion_guard on bad input
144
+ "GET /latest-user HTTP/1.1" 200 ← chain_subscript_guard on out-of-bounds
145
+ ```
146
+
147
+ ### WSGI middleware
148
+
149
+ ```python
150
+ from codesuture.middleware import CodeSutureMiddleware
151
+
152
+ app = CodeSutureMiddleware(wsgi_app)
153
+ ```
154
+
155
+ ---
156
+
157
+ ## Runtime Intelligence
158
+
159
+ **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.
160
+
161
+ **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.
162
+
163
+ **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.
164
+
165
+ **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.
166
+
167
+ **Bytecode fingerprint registry** — Crash sites are hashed by their surrounding instruction window. Repeat patterns get instant cached guard application without re-analysis.
168
+
169
+ **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.
170
+
171
+ ---
172
+
173
+ ## What CodeSuture is not
174
+
175
+ **Not a logger.** It does not record exceptions and move on. It patches the function and retries.
176
+
177
+ **Not a static analyzer.** It operates at runtime on live bytecode, not on source.
178
+
179
+ **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.
180
+
181
+ ---
182
+
183
+ ## Limitations
184
+
185
+ **Python 3.11+ only.** CodeSuture depends on CPython 3.11 bytecode structures.
186
+
187
+ **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.
188
+
189
+ **Semantic bugs are not patchable.** CodeSuture fixes structural crashes — null access, missing keys, type mismatches, bounds errors. Logic errors that produce wrong results without crashing are out of scope.
190
+
191
+ **Single-process scope.** Patches apply per-process. Multi-process applications need one instance per worker. `.codesuture_store/` is shared on disk, so patches load correctly on restart.
192
+
193
+ **Async support is experimental.** Standard `async def` functions are patched. Async generators and deeply nested `await` chains may not be handled correctly in all cases.
194
+
195
+ **HTTP recovery covers simple server paths.** Validated against `http.server` and `socketserver`. Full ASGI framework support is in progress.
196
+
197
+ ---
198
+
199
+ ## Roadmap
200
+
201
+ Tracked in `ROADMAP.md`. v1.0 themes:
202
+
203
+ - `sys.monitoring` as the default engine on Python 3.12+ (zero line-tracing overhead on hot paths)
204
+ - Stronger transaction recovery boundaries across web frameworks
205
+ - Verified source-level repair proposals via local LLM
206
+ - Fleet governance, audit lifecycle, and incident export
207
+ - Language-neutral incident protocol for future polyglot adapters
208
+
209
+ ---
210
+
211
+ ## License
212
+
213
+ MIT. See `LICENSE` for details.
@@ -0,0 +1,2 @@
1
+ __version__ = "0.7.0"
2
+
@@ -5,7 +5,7 @@ from codesuture.tracer import install, uninstall, _install_trace_on_all_threads
5
5
  def main():
6
6
  parser = argparse.ArgumentParser(prog='codesuture',
7
7
  description='Runtime Python bytecode patcher with self-healing re-execution')
8
- parser.add_argument('--version', action='version', version='codesuture 0.6.0')
8
+ parser.add_argument('--version', action='version', version='codesuture 0.7.0')
9
9
  sub = parser.add_subparsers(dest='command', required=True)
10
10
 
11
11
  run_parser = sub.add_parser('run', help='Run a script with live patching')