codesuture 0.7.1__tar.gz → 0.7.2__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.
- {codesuture-0.7.1 → codesuture-0.7.2}/PKG-INFO +2 -34
- {codesuture-0.7.1 → codesuture-0.7.2}/README.md +195 -227
- codesuture-0.7.2/codesuture/__init__.py +1 -0
- {codesuture-0.7.1 → codesuture-0.7.2}/codesuture.egg-info/PKG-INFO +2 -34
- {codesuture-0.7.1 → codesuture-0.7.2}/pyproject.toml +1 -1
- codesuture-0.7.1/codesuture/__init__.py +0 -2
- {codesuture-0.7.1 → codesuture-0.7.2}/.gitignore +0 -0
- {codesuture-0.7.1 → codesuture-0.7.2}/CHANGELOG.md +0 -0
- {codesuture-0.7.1 → codesuture-0.7.2}/LICENSE +0 -0
- {codesuture-0.7.1 → codesuture-0.7.2}/MANIFEST.in +0 -0
- {codesuture-0.7.1 → codesuture-0.7.2}/codesuture/__main__.py +0 -0
- {codesuture-0.7.1 → codesuture-0.7.2}/codesuture/_eval_fix.py +0 -0
- {codesuture-0.7.1 → codesuture-0.7.2}/codesuture/audit.py +0 -0
- {codesuture-0.7.1 → codesuture-0.7.2}/codesuture/cli.py +0 -0
- {codesuture-0.7.1 → codesuture-0.7.2}/codesuture/code_replacer.py +0 -0
- {codesuture-0.7.1 → codesuture-0.7.2}/codesuture/codesuture_fix.py +0 -0
- {codesuture-0.7.1 → codesuture-0.7.2}/codesuture/debuggee.py +0 -0
- {codesuture-0.7.1 → codesuture-0.7.2}/codesuture/diff_guard.py +0 -0
- {codesuture-0.7.1 → codesuture-0.7.2}/codesuture/explain.py +0 -0
- {codesuture-0.7.1 → codesuture-0.7.2}/codesuture/fingerprint.py +0 -0
- {codesuture-0.7.1 → codesuture-0.7.2}/codesuture/guard_synthesizer.py +0 -0
- {codesuture-0.7.1 → codesuture-0.7.2}/codesuture/knowledge.py +0 -0
- {codesuture-0.7.1 → codesuture-0.7.2}/codesuture/middleware.py +0 -0
- {codesuture-0.7.1 → codesuture-0.7.2}/codesuture/opcodes.py +0 -0
- {codesuture-0.7.1 → codesuture-0.7.2}/codesuture/pattern_matcher.py +0 -0
- {codesuture-0.7.1 → codesuture-0.7.2}/codesuture/persistence.py +0 -0
- {codesuture-0.7.1 → codesuture-0.7.2}/codesuture/plugins/__init__.py +0 -0
- {codesuture-0.7.1 → codesuture-0.7.2}/codesuture/plugins/autonomous.py +0 -0
- {codesuture-0.7.1 → codesuture-0.7.2}/codesuture/rewind.py +0 -0
- {codesuture-0.7.1 → codesuture-0.7.2}/codesuture/rollback.py +0 -0
- {codesuture-0.7.1 → codesuture-0.7.2}/codesuture/sandbox.py +0 -0
- {codesuture-0.7.1 → codesuture-0.7.2}/codesuture/shadow.py +0 -0
- {codesuture-0.7.1 → codesuture-0.7.2}/codesuture/tracer.py +0 -0
- {codesuture-0.7.1 → codesuture-0.7.2}/codesuture/watcher.py +0 -0
- {codesuture-0.7.1 → codesuture-0.7.2}/codesuture.egg-info/SOURCES.txt +0 -0
- {codesuture-0.7.1 → codesuture-0.7.2}/codesuture.egg-info/dependency_links.txt +0 -0
- {codesuture-0.7.1 → codesuture-0.7.2}/codesuture.egg-info/entry_points.txt +0 -0
- {codesuture-0.7.1 → codesuture-0.7.2}/codesuture.egg-info/requires.txt +0 -0
- {codesuture-0.7.1 → codesuture-0.7.2}/codesuture.egg-info/top_level.txt +0 -0
- {codesuture-0.7.1 → codesuture-0.7.2}/setup.cfg +0 -0
- {codesuture-0.7.1 → codesuture-0.7.2}/setup.py +0 -0
- {codesuture-0.7.1 → codesuture-0.7.2}/tests/__init__.py +0 -0
- {codesuture-0.7.1 → codesuture-0.7.2}/tests/test_e2e.py +0 -0
- {codesuture-0.7.1 → codesuture-0.7.2}/tests/test_guard_synthesizer.py +0 -0
- {codesuture-0.7.1 → codesuture-0.7.2}/tests/test_harness.py +0 -0
- {codesuture-0.7.1 → codesuture-0.7.2}/tests/test_harness2.py +0 -0
- {codesuture-0.7.1 → codesuture-0.7.2}/tests/test_new_guards.py +0 -0
- {codesuture-0.7.1 → codesuture-0.7.2}/tests/test_opcodes.py +0 -0
- {codesuture-0.7.1 → codesuture-0.7.2}/tests/test_pattern_matcher.py +0 -0
- {codesuture-0.7.1 → codesuture-0.7.2}/tests/test_persistence.py +0 -0
- {codesuture-0.7.1 → codesuture-0.7.2}/tests/test_rollback.py +0 -0
- {codesuture-0.7.1 → codesuture-0.7.2}/tests/test_thread_safety.py +0 -0
- {codesuture-0.7.1 → codesuture-0.7.2}/tests/test_transparency.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: codesuture
|
|
3
|
-
Version: 0.7.
|
|
3
|
+
Version: 0.7.2
|
|
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
|
|
@@ -26,7 +26,7 @@ Dynamic: license-file
|
|
|
26
26
|
|
|
27
27
|
**Runtime guard synthesis for CPython 3.11+. Catches structural crashes, patches live bytecode, keeps your server running.**
|
|
28
28
|
|
|
29
|
-
[]()
|
|
30
30
|
[]()
|
|
31
31
|
[](LICENSE)
|
|
32
32
|
[]()
|
|
@@ -174,8 +174,6 @@ from codesuture.middleware import CodeSutureMiddleware
|
|
|
174
174
|
app = CodeSutureMiddleware(wsgi_app)
|
|
175
175
|
```
|
|
176
176
|
|
|
177
|
-
See the implementation in [codesuture/middleware.py](codesuture/middleware.py).
|
|
178
|
-
|
|
179
177
|
---
|
|
180
178
|
|
|
181
179
|
## Safety features
|
|
@@ -202,31 +200,6 @@ See the implementation in [codesuture/middleware.py](codesuture/middleware.py).
|
|
|
202
200
|
|
|
203
201
|
## Known limitations
|
|
204
202
|
|
|
205
|
-
<<<<<<< HEAD
|
|
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](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
203
|
- **Python 3.11+ only.** Depends on CPython bytecode structures introduced in 3.11.
|
|
231
204
|
- **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
205
|
- **Comprehensions are not patchable.** List/dict/set/generator comprehensions are anonymous nested code objects. CodeSuture logs a warning and skips them.
|
|
@@ -234,16 +207,11 @@ Tracked in [ROADMAP.md](ROADMAP.md). v1.0 themes:
|
|
|
234
207
|
- **Single-process scope.** Patches apply per-process. `.codesuture_store/` is shared on disk, so patches persist across restarts.
|
|
235
208
|
- **Async support is experimental.** Standard `async def` functions are patched. Async generators and deeply nested `await` chains may not be handled correctly.
|
|
236
209
|
- **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)
|
|
238
210
|
|
|
239
211
|
---
|
|
240
212
|
|
|
241
213
|
## License
|
|
242
214
|
|
|
243
|
-
<<<<<<< HEAD
|
|
244
|
-
MIT. See [LICENSE](LICENSE) for details. For a detailed history of changes, see the [Changelog](CHANGELOG.md).
|
|
245
|
-
=======
|
|
246
215
|
MIT. See [LICENSE](LICENSE) for details.
|
|
247
216
|
|
|
248
217
|
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)
|
|
@@ -1,227 +1,195 @@
|
|
|
1
|
-
# CodeSuture
|
|
2
|
-
|
|
3
|
-

|
|
4
|
-
|
|
5
|
-
**Runtime guard synthesis for CPython 3.11+. Catches structural crashes, patches live bytecode, keeps your server running.**
|
|
6
|
-
|
|
7
|
-
[]()
|
|
9
|
-
[](LICENSE)
|
|
10
|
-
[]()
|
|
11
|
-
|
|
12
|
-
```
|
|
13
|
-
pip install codesuture
|
|
14
|
-
```
|
|
15
|
-
|
|
16
|
-
---
|
|
17
|
-
|
|
18
|
-
## What it does
|
|
19
|
-
|
|
20
|
-
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.
|
|
21
|
-
|
|
22
|
-
The patch persists. Next run, it loads before the first function call.
|
|
23
|
-
|
|
24
|
-
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.
|
|
25
|
-
|
|
26
|
-
---
|
|
27
|
-
|
|
28
|
-
## Quick start — script
|
|
29
|
-
|
|
30
|
-
```bash
|
|
31
|
-
codesuture run your_script.py
|
|
32
|
-
```
|
|
33
|
-
|
|
34
|
-
```
|
|
35
|
-
[CodeSuture] Caught AttributeError: 'NoneType' object has no attribute 'bio'
|
|
36
|
-
[CodeSuture] Applying null_guard on 'profile' ...
|
|
37
|
-
[CodeSuture] Patch applied to get_bio().
|
|
38
|
-
[CodeSuture] Re-executing after 1 patch(es)...
|
|
39
|
-
|
|
40
|
-
Session summary:
|
|
41
|
-
Patches applied: 1
|
|
42
|
-
```
|
|
43
|
-
|
|
44
|
-
Run it again:
|
|
45
|
-
|
|
46
|
-
```
|
|
47
|
-
[CodeSuture] Already healed, skipping: loaded persistent patch for get_bio
|
|
48
|
-
Session summary:
|
|
49
|
-
Patches applied: 0
|
|
50
|
-
```
|
|
51
|
-
|
|
52
|
-
---
|
|
53
|
-
|
|
54
|
-
## Quick start — live server
|
|
55
|
-
|
|
56
|
-
```bash
|
|
57
|
-
codesuture run server.py --verbose --retries 3
|
|
58
|
-
```
|
|
59
|
-
|
|
60
|
-
```
|
|
61
|
-
[CodeSuture] Caught AttributeError: 'NoneType' object has no attribute 'get_profile'
|
|
62
|
-
[CodeSuture] Applying null_guard on 'get_profile' ...
|
|
63
|
-
[CodeSuture DEBUG] Diff: +12 -9 instructions (allowed <= 55)
|
|
64
|
-
[CodeSuture] Patch applied to do_GET().
|
|
65
|
-
[CodeSuture] Transaction replay armed for do_GET().
|
|
66
|
-
[CodeSuture] Transaction replay: retrying patched HTTP handler in-place.
|
|
67
|
-
127.0.0.1 - - "GET /user-data HTTP/1.1" 200 -
|
|
68
|
-
```
|
|
69
|
-
|
|
70
|
-
The client sees:
|
|
71
|
-
|
|
72
|
-
```http
|
|
73
|
-
HTTP/1.0 200 OK
|
|
74
|
-
Content-type: application/json
|
|
75
|
-
X-CodeSuture: patched=1; guard=null_guard; target=get_profile
|
|
76
|
-
|
|
77
|
-
{"result": null}
|
|
78
|
-
```
|
|
79
|
-
|
|
80
|
-
No 500. No traceback. Server process intact.
|
|
81
|
-
|
|
82
|
-
---
|
|
83
|
-
|
|
84
|
-
## How it works
|
|
85
|
-
|
|
86
|
-
1. **Catch** — `sys.settrace` (3.11) or `sys.monitoring` (3.12+) intercepts exceptions at the exact frame and bytecode offset.
|
|
87
|
-
2. **Analyze** — The pattern matcher walks the instruction chain and identifies the failing variable or operation.
|
|
88
|
-
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.
|
|
89
|
-
4. **Rewind** — Execution restarts from the patched function via `f_lineno` setter. The guard prevents recurrence.
|
|
90
|
-
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.
|
|
91
|
-
|
|
92
|
-
No source files are modified.
|
|
93
|
-
|
|
94
|
-
---
|
|
95
|
-
|
|
96
|
-
## Supported guard types
|
|
97
|
-
|
|
98
|
-
| Guard type | Triggers on | Example |
|
|
99
|
-
|---|---|---|
|
|
100
|
-
| `null_guard` | `AttributeError` on `None` | `user.profile.bio` when `profile` is `None` |
|
|
101
|
-
| `key_guard` | `KeyError` | `cfg["timeout"]` when key is missing |
|
|
102
|
-
| `subscript_guard` | `TypeError` subscripting `None` | `data["key"]` when `data` is `None` |
|
|
103
|
-
| `chain_subscript_guard` | Nested subscript on `None` | `data["user"]["name"]` |
|
|
104
|
-
| `index_guard` | `IndexError` | `items[10]` when `len(items) == 2` |
|
|
105
|
-
| `type_coercion_guard` | `TypeError` on conversion | `int("not_a_number")` |
|
|
106
|
-
| `division_guard` | `ZeroDivisionError` | `x / count` when `count == 0` |
|
|
107
|
-
| `str_coerce_guard` | `TypeError` on string concat | `"age: " + 25` |
|
|
108
|
-
| `file_guard` | `FileNotFoundError` | `open(path)` when file is missing |
|
|
109
|
-
| `callable_guard` | `TypeError` calling `None` | `func()` when `func` is `None` |
|
|
110
|
-
| `return_guard` | `TypeError` on `None` return | Downstream use of a `None` return value |
|
|
111
|
-
|
|
112
|
-
---
|
|
113
|
-
|
|
114
|
-
## CLI reference
|
|
115
|
-
|
|
116
|
-
| Command | Flags | What it does |
|
|
117
|
-
|---|---|---|
|
|
118
|
-
| `codesuture run <script>` | | Run with live patching |
|
|
119
|
-
| | `--verbose` | Show patch diffs and instruction deltas |
|
|
120
|
-
| | `--shadow` | Warn when patched functions return sentinel values |
|
|
121
|
-
| | `--dry-run` | Preview patches without applying |
|
|
122
|
-
| | `--silent` | Suppress all informational output |
|
|
123
|
-
| | `--ttl DAYS` | Set patch expiry (default: 7 days) |
|
|
124
|
-
| | `--retries N` | Max re-execution attempts (default: 3) |
|
|
125
|
-
| `codesuture watch <script>` | `--max-restarts N` | Run continuously, restart after each patch |
|
|
126
|
-
| `codesuture audit` | | Show all active patches in a table |
|
|
127
|
-
| `codesuture explain` | | Plain-language breakdown of every patch |
|
|
128
|
-
| `codesuture explain <name>` | | Explain one function's patch |
|
|
129
|
-
| `codesuture rollback <name>` | | Remove one persisted patch and restore runtime code |
|
|
130
|
-
| `codesuture rollback` | `--all` | Remove all patches and fingerprint registry |
|
|
131
|
-
| `codesuture rollback` | `--dry-run` | Preview what would be removed |
|
|
132
|
-
|
|
133
|
-
---
|
|
134
|
-
|
|
135
|
-
## HTTP recovery
|
|
136
|
-
|
|
137
|
-
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.
|
|
138
|
-
|
|
139
|
-
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.
|
|
140
|
-
|
|
141
|
-
Every patched response carries:
|
|
142
|
-
|
|
143
|
-
```
|
|
144
|
-
X-CodeSuture: patched=1; guard=<type>; target=<variable>
|
|
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
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
- **
|
|
162
|
-
- **
|
|
163
|
-
- **
|
|
164
|
-
- **
|
|
165
|
-
- **
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
**Not a
|
|
174
|
-
|
|
175
|
-
**Not
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
**
|
|
185
|
-
|
|
186
|
-
**
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
---
|
|
197
|
-
|
|
198
|
-
## Roadmap
|
|
199
|
-
|
|
200
|
-
Tracked in [ROADMAP.md](ROADMAP.md). v1.0 themes:
|
|
201
|
-
|
|
202
|
-
- `sys.monitoring` as the default engine on Python 3.12+ (zero line-tracing overhead on hot paths)
|
|
203
|
-
- Stronger transaction recovery boundaries across web frameworks
|
|
204
|
-
- Verified source-level repair proposals via local LLM
|
|
205
|
-
- Fleet governance, audit lifecycle, and incident export
|
|
206
|
-
- Language-neutral incident protocol for future polyglot adapters
|
|
207
|
-
=======
|
|
208
|
-
- **Python 3.11+ only.** Depends on CPython bytecode structures introduced in 3.11.
|
|
209
|
-
- **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.
|
|
210
|
-
- **Comprehensions are not patchable.** List/dict/set/generator comprehensions are anonymous nested code objects. CodeSuture logs a warning and skips them.
|
|
211
|
-
- **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.
|
|
212
|
-
- **Single-process scope.** Patches apply per-process. `.codesuture_store/` is shared on disk, so patches persist across restarts.
|
|
213
|
-
- **Async support is experimental.** Standard `async def` functions are patched. Async generators and deeply nested `await` chains may not be handled correctly.
|
|
214
|
-
- **HTTP recovery is validated against `http.server`.** Full ASGI framework support is not yet implemented.
|
|
215
|
-
>>>>>>> 0cedff8 (v0.7.1: safety hardening, audit fixes, 3.12+ compat, 120 tests)
|
|
216
|
-
|
|
217
|
-
---
|
|
218
|
-
|
|
219
|
-
## License
|
|
220
|
-
|
|
221
|
-
<<<<<<< HEAD
|
|
222
|
-
MIT. See [LICENSE](LICENSE) for details. For a detailed history of changes, see the [Changelog](CHANGELOG.md).
|
|
223
|
-
=======
|
|
224
|
-
MIT. See [LICENSE](LICENSE) for details.
|
|
225
|
-
|
|
226
|
-
For a detailed history of changes, see the [Changelog](CHANGELOG.md).
|
|
227
|
-
>>>>>>> 0cedff8 (v0.7.1: safety hardening, audit fixes, 3.12+ compat, 120 tests)
|
|
1
|
+
# CodeSuture
|
|
2
|
+
|
|
3
|
+

|
|
4
|
+
|
|
5
|
+
**Runtime guard synthesis for CPython 3.11+. Catches structural crashes, patches live bytecode, keeps your server running.**
|
|
6
|
+
|
|
7
|
+
[]()
|
|
8
|
+
[]()
|
|
9
|
+
[](LICENSE)
|
|
10
|
+
[]()
|
|
11
|
+
|
|
12
|
+
```
|
|
13
|
+
pip install codesuture
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
## What it does
|
|
19
|
+
|
|
20
|
+
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.
|
|
21
|
+
|
|
22
|
+
The patch persists. Next run, it loads before the first function call.
|
|
23
|
+
|
|
24
|
+
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.
|
|
25
|
+
|
|
26
|
+
---
|
|
27
|
+
|
|
28
|
+
## Quick start — script
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
codesuture run your_script.py
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
```
|
|
35
|
+
[CodeSuture] Caught AttributeError: 'NoneType' object has no attribute 'bio'
|
|
36
|
+
[CodeSuture] Applying null_guard on 'profile' ...
|
|
37
|
+
[CodeSuture] Patch applied to get_bio().
|
|
38
|
+
[CodeSuture] Re-executing after 1 patch(es)...
|
|
39
|
+
|
|
40
|
+
Session summary:
|
|
41
|
+
Patches applied: 1
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
Run it again:
|
|
45
|
+
|
|
46
|
+
```
|
|
47
|
+
[CodeSuture] Already healed, skipping: loaded persistent patch for get_bio
|
|
48
|
+
Session summary:
|
|
49
|
+
Patches applied: 0
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
---
|
|
53
|
+
|
|
54
|
+
## Quick start — live server
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
codesuture run server.py --verbose --retries 3
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
```
|
|
61
|
+
[CodeSuture] Caught AttributeError: 'NoneType' object has no attribute 'get_profile'
|
|
62
|
+
[CodeSuture] Applying null_guard on 'get_profile' ...
|
|
63
|
+
[CodeSuture DEBUG] Diff: +12 -9 instructions (allowed <= 55)
|
|
64
|
+
[CodeSuture] Patch applied to do_GET().
|
|
65
|
+
[CodeSuture] Transaction replay armed for do_GET().
|
|
66
|
+
[CodeSuture] Transaction replay: retrying patched HTTP handler in-place.
|
|
67
|
+
127.0.0.1 - - "GET /user-data HTTP/1.1" 200 -
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
The client sees:
|
|
71
|
+
|
|
72
|
+
```http
|
|
73
|
+
HTTP/1.0 200 OK
|
|
74
|
+
Content-type: application/json
|
|
75
|
+
X-CodeSuture: patched=1; guard=null_guard; target=get_profile
|
|
76
|
+
|
|
77
|
+
{"result": null}
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
No 500. No traceback. Server process intact.
|
|
81
|
+
|
|
82
|
+
---
|
|
83
|
+
|
|
84
|
+
## How it works
|
|
85
|
+
|
|
86
|
+
1. **Catch** — `sys.settrace` (3.11) or `sys.monitoring` (3.12+) intercepts exceptions at the exact frame and bytecode offset.
|
|
87
|
+
2. **Analyze** — The pattern matcher walks the instruction chain and identifies the failing variable or operation.
|
|
88
|
+
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.
|
|
89
|
+
4. **Rewind** — Execution restarts from the patched function via `f_lineno` setter. The guard prevents recurrence.
|
|
90
|
+
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.
|
|
91
|
+
|
|
92
|
+
No source files are modified.
|
|
93
|
+
|
|
94
|
+
---
|
|
95
|
+
|
|
96
|
+
## Supported guard types
|
|
97
|
+
|
|
98
|
+
| Guard type | Triggers on | Example |
|
|
99
|
+
|---|---|---|
|
|
100
|
+
| `null_guard` | `AttributeError` on `None` | `user.profile.bio` when `profile` is `None` |
|
|
101
|
+
| `key_guard` | `KeyError` | `cfg["timeout"]` when key is missing |
|
|
102
|
+
| `subscript_guard` | `TypeError` subscripting `None` | `data["key"]` when `data` is `None` |
|
|
103
|
+
| `chain_subscript_guard` | Nested subscript on `None` | `data["user"]["name"]` |
|
|
104
|
+
| `index_guard` | `IndexError` | `items[10]` when `len(items) == 2` |
|
|
105
|
+
| `type_coercion_guard` | `TypeError` on conversion | `int("not_a_number")` |
|
|
106
|
+
| `division_guard` | `ZeroDivisionError` | `x / count` when `count == 0` |
|
|
107
|
+
| `str_coerce_guard` | `TypeError` on string concat | `"age: " + 25` |
|
|
108
|
+
| `file_guard` | `FileNotFoundError` | `open(path)` when file is missing |
|
|
109
|
+
| `callable_guard` | `TypeError` calling `None` | `func()` when `func` is `None` |
|
|
110
|
+
| `return_guard` | `TypeError` on `None` return | Downstream use of a `None` return value |
|
|
111
|
+
|
|
112
|
+
---
|
|
113
|
+
|
|
114
|
+
## CLI reference
|
|
115
|
+
|
|
116
|
+
| Command | Flags | What it does |
|
|
117
|
+
|---|---|---|
|
|
118
|
+
| `codesuture run <script>` | | Run with live patching |
|
|
119
|
+
| | `--verbose` | Show patch diffs and instruction deltas |
|
|
120
|
+
| | `--shadow` | Warn when patched functions return sentinel values |
|
|
121
|
+
| | `--dry-run` | Preview patches without applying |
|
|
122
|
+
| | `--silent` | Suppress all informational output |
|
|
123
|
+
| | `--ttl DAYS` | Set patch expiry (default: 7 days) |
|
|
124
|
+
| | `--retries N` | Max re-execution attempts (default: 3) |
|
|
125
|
+
| `codesuture watch <script>` | `--max-restarts N` | Run continuously, restart after each patch |
|
|
126
|
+
| `codesuture audit` | | Show all active patches in a table |
|
|
127
|
+
| `codesuture explain` | | Plain-language breakdown of every patch |
|
|
128
|
+
| `codesuture explain <name>` | | Explain one function's patch |
|
|
129
|
+
| `codesuture rollback <name>` | | Remove one persisted patch and restore runtime code |
|
|
130
|
+
| `codesuture rollback` | `--all` | Remove all patches and fingerprint registry |
|
|
131
|
+
| `codesuture rollback` | `--dry-run` | Preview what would be removed |
|
|
132
|
+
|
|
133
|
+
---
|
|
134
|
+
|
|
135
|
+
## HTTP recovery
|
|
136
|
+
|
|
137
|
+
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.
|
|
138
|
+
|
|
139
|
+
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.
|
|
140
|
+
|
|
141
|
+
Every patched response carries:
|
|
142
|
+
|
|
143
|
+
```
|
|
144
|
+
X-CodeSuture: patched=1; guard=<type>; target=<variable>
|
|
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
|
+
## Safety features
|
|
158
|
+
|
|
159
|
+
- **Semantic diff gate** — Patches that modify too many instructions are rejected. The engine never corrupts a complex function to fix a simple crash.
|
|
160
|
+
- **SHA-256 integrity** — Persisted patches are checksummed. Tampered `.code` files are refused on load.
|
|
161
|
+
- **Caller-aware propagation** — After patching, `gc.get_referrers` updates every live reference: closures, bound methods, partials. No stale copy survives.
|
|
162
|
+
- **Patch validation** — Synthesized bytecode is checked for `LOAD_FAST` references to variables not in `co_varnames`. Invalid patches are rejected before application.
|
|
163
|
+
- **Patch expiry (TTL)** — Every patch carries a time-to-live. Aged patches trigger a warning to fix the root cause in source.
|
|
164
|
+
- **Thread safety** — All shared state (fingerprint registry, persistence store, healed function sets) is protected by locks.
|
|
165
|
+
- **Rollback** — `codesuture rollback` removes persisted files AND restores original code in the running process.
|
|
166
|
+
|
|
167
|
+
---
|
|
168
|
+
|
|
169
|
+
## What CodeSuture is not
|
|
170
|
+
|
|
171
|
+
**Not a logger.** It does not record exceptions and move on. It patches the function and retries.
|
|
172
|
+
|
|
173
|
+
**Not a static analyzer.** It operates at runtime on live bytecode, not on source.
|
|
174
|
+
|
|
175
|
+
**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.
|
|
176
|
+
|
|
177
|
+
---
|
|
178
|
+
|
|
179
|
+
## Known limitations
|
|
180
|
+
|
|
181
|
+
- **Python 3.11+ only.** Depends on CPython bytecode structures introduced in 3.11.
|
|
182
|
+
- **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.
|
|
183
|
+
- **Comprehensions are not patchable.** List/dict/set/generator comprehensions are anonymous nested code objects. CodeSuture logs a warning and skips them.
|
|
184
|
+
- **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.
|
|
185
|
+
- **Single-process scope.** Patches apply per-process. `.codesuture_store/` is shared on disk, so patches persist across restarts.
|
|
186
|
+
- **Async support is experimental.** Standard `async def` functions are patched. Async generators and deeply nested `await` chains may not be handled correctly.
|
|
187
|
+
- **HTTP recovery is validated against `http.server`.** Full ASGI framework support is not yet implemented.
|
|
188
|
+
|
|
189
|
+
---
|
|
190
|
+
|
|
191
|
+
## License
|
|
192
|
+
|
|
193
|
+
MIT. See [LICENSE](LICENSE) for details.
|
|
194
|
+
|
|
195
|
+
For a detailed history of changes, see the [Changelog](CHANGELOG.md).
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "0.7.2"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: codesuture
|
|
3
|
-
Version: 0.7.
|
|
3
|
+
Version: 0.7.2
|
|
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
|
|
@@ -26,7 +26,7 @@ Dynamic: license-file
|
|
|
26
26
|
|
|
27
27
|
**Runtime guard synthesis for CPython 3.11+. Catches structural crashes, patches live bytecode, keeps your server running.**
|
|
28
28
|
|
|
29
|
-
[]()
|
|
30
30
|
[]()
|
|
31
31
|
[](LICENSE)
|
|
32
32
|
[]()
|
|
@@ -174,8 +174,6 @@ from codesuture.middleware import CodeSutureMiddleware
|
|
|
174
174
|
app = CodeSutureMiddleware(wsgi_app)
|
|
175
175
|
```
|
|
176
176
|
|
|
177
|
-
See the implementation in [codesuture/middleware.py](codesuture/middleware.py).
|
|
178
|
-
|
|
179
177
|
---
|
|
180
178
|
|
|
181
179
|
## Safety features
|
|
@@ -202,31 +200,6 @@ See the implementation in [codesuture/middleware.py](codesuture/middleware.py).
|
|
|
202
200
|
|
|
203
201
|
## Known limitations
|
|
204
202
|
|
|
205
|
-
<<<<<<< HEAD
|
|
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](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
203
|
- **Python 3.11+ only.** Depends on CPython bytecode structures introduced in 3.11.
|
|
231
204
|
- **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
205
|
- **Comprehensions are not patchable.** List/dict/set/generator comprehensions are anonymous nested code objects. CodeSuture logs a warning and skips them.
|
|
@@ -234,16 +207,11 @@ Tracked in [ROADMAP.md](ROADMAP.md). v1.0 themes:
|
|
|
234
207
|
- **Single-process scope.** Patches apply per-process. `.codesuture_store/` is shared on disk, so patches persist across restarts.
|
|
235
208
|
- **Async support is experimental.** Standard `async def` functions are patched. Async generators and deeply nested `await` chains may not be handled correctly.
|
|
236
209
|
- **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)
|
|
238
210
|
|
|
239
211
|
---
|
|
240
212
|
|
|
241
213
|
## License
|
|
242
214
|
|
|
243
|
-
<<<<<<< HEAD
|
|
244
|
-
MIT. See [LICENSE](LICENSE) for details. For a detailed history of changes, see the [Changelog](CHANGELOG.md).
|
|
245
|
-
=======
|
|
246
215
|
MIT. See [LICENSE](LICENSE) for details.
|
|
247
216
|
|
|
248
217
|
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)
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "codesuture"
|
|
7
|
-
version = "0.7.
|
|
7
|
+
version = "0.7.2"
|
|
8
8
|
description = "Runtime Python bytecode patcher with guard knowledge base, persistence, and self-healing re-execution"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = "MIT"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|