codesuture 0.6.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 (67) hide show
  1. codesuture-0.7.1/.gitignore +53 -0
  2. codesuture-0.7.1/CHANGELOG.md +150 -0
  3. codesuture-0.7.1/PKG-INFO +249 -0
  4. codesuture-0.7.1/README.md +227 -0
  5. codesuture-0.7.1/codesuture/__init__.py +2 -0
  6. codesuture-0.7.1/codesuture/_eval_fix.py +5 -0
  7. {codesuture-0.6.0 → codesuture-0.7.1}/codesuture/audit.py +7 -10
  8. {codesuture-0.6.0 → codesuture-0.7.1}/codesuture/cli.py +5 -2
  9. {codesuture-0.6.0 → codesuture-0.7.1}/codesuture/explain.py +10 -10
  10. {codesuture-0.6.0 → codesuture-0.7.1}/codesuture/fingerprint.py +26 -21
  11. {codesuture-0.6.0 → codesuture-0.7.1}/codesuture/guard_synthesizer.py +121 -70
  12. {codesuture-0.6.0 → codesuture-0.7.1}/codesuture/middleware.py +10 -5
  13. codesuture-0.7.1/codesuture/opcodes.py +146 -0
  14. {codesuture-0.6.0 → codesuture-0.7.1}/codesuture/pattern_matcher.py +87 -35
  15. {codesuture-0.6.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.1/codesuture/tracer.py +855 -0
  19. codesuture-0.7.1/codesuture.egg-info/PKG-INFO +249 -0
  20. {codesuture-0.6.0 → codesuture-0.7.1}/codesuture.egg-info/SOURCES.txt +6 -5
  21. {codesuture-0.6.0 → codesuture-0.7.1}/pyproject.toml +5 -6
  22. {codesuture-0.6.0 → codesuture-0.7.1}/tests/test_new_guards.py +43 -3
  23. codesuture-0.7.1/tests/test_opcodes.py +222 -0
  24. {codesuture-0.6.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.6.0/.gitignore +0 -33
  30. codesuture-0.6.0/CHANGELOG.md +0 -71
  31. codesuture-0.6.0/PKG-INFO +0 -167
  32. codesuture-0.6.0/README.md +0 -146
  33. codesuture-0.6.0/codesuture/__init__.py +0 -2
  34. codesuture-0.6.0/codesuture/_eval_fix.py +0 -5
  35. codesuture-0.6.0/codesuture/rewind.py +0 -43
  36. codesuture-0.6.0/codesuture/rollback.py +0 -85
  37. codesuture-0.6.0/codesuture/tracer.py +0 -488
  38. codesuture-0.6.0/codesuture.egg-info/PKG-INFO +0 -167
  39. codesuture-0.6.0/tests/closure_test.py +0 -16
  40. codesuture-0.6.0/tests/debug_gc.py +0 -23
  41. codesuture-0.6.0/tests/harness3.py +0 -46
  42. codesuture-0.6.0/tests/test_codesuture_debuggee.py +0 -17
  43. codesuture-0.6.0/tests/test_unknown_bug.py +0 -9
  44. {codesuture-0.6.0 → codesuture-0.7.1}/LICENSE +0 -0
  45. {codesuture-0.6.0 → codesuture-0.7.1}/MANIFEST.in +0 -0
  46. {codesuture-0.6.0 → codesuture-0.7.1}/codesuture/__main__.py +0 -0
  47. {codesuture-0.6.0 → codesuture-0.7.1}/codesuture/code_replacer.py +0 -0
  48. {codesuture-0.6.0 → codesuture-0.7.1}/codesuture/codesuture_fix.py +0 -0
  49. {codesuture-0.6.0 → codesuture-0.7.1}/codesuture/debuggee.py +0 -0
  50. {codesuture-0.6.0 → codesuture-0.7.1}/codesuture/diff_guard.py +0 -0
  51. {codesuture-0.6.0 → codesuture-0.7.1}/codesuture/knowledge.py +0 -0
  52. {codesuture-0.6.0 → codesuture-0.7.1}/codesuture/plugins/__init__.py +0 -0
  53. {codesuture-0.6.0 → codesuture-0.7.1}/codesuture/plugins/autonomous.py +0 -0
  54. {codesuture-0.6.0 → codesuture-0.7.1}/codesuture/sandbox.py +0 -0
  55. {codesuture-0.6.0 → codesuture-0.7.1}/codesuture/shadow.py +0 -0
  56. {codesuture-0.6.0 → codesuture-0.7.1}/codesuture/watcher.py +0 -0
  57. {codesuture-0.6.0 → codesuture-0.7.1}/codesuture.egg-info/dependency_links.txt +0 -0
  58. {codesuture-0.6.0 → codesuture-0.7.1}/codesuture.egg-info/entry_points.txt +0 -0
  59. {codesuture-0.6.0 → codesuture-0.7.1}/codesuture.egg-info/requires.txt +0 -0
  60. {codesuture-0.6.0 → codesuture-0.7.1}/codesuture.egg-info/top_level.txt +0 -0
  61. {codesuture-0.6.0 → codesuture-0.7.1}/setup.cfg +0 -0
  62. {codesuture-0.6.0 → codesuture-0.7.1}/setup.py +0 -0
  63. {codesuture-0.6.0 → codesuture-0.7.1}/tests/__init__.py +0 -0
  64. {codesuture-0.6.0 → codesuture-0.7.1}/tests/test_e2e.py +0 -0
  65. {codesuture-0.6.0 → codesuture-0.7.1}/tests/test_guard_synthesizer.py +0 -0
  66. {codesuture-0.6.0 → codesuture-0.7.1}/tests/test_harness.py +0 -0
  67. {codesuture-0.6.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/
@@ -0,0 +1,150 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
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
+
76
+ ## [0.7.0] - 2026-05-17
77
+
78
+ ### Added
79
+ - Active Shield: after patching, the engine re-invokes the function with
80
+ original arguments to save the current transaction (eliminates
81
+ ERR_EMPTY_RESPONSE on first request to patched server endpoints)
82
+ - Python 3.12+ sys.monitoring dual engine: zero baseline overhead,
83
+ callback fires only on RAISE events instead of line-by-line tracing
84
+ - Transaction fallback: graceful JSON 500 response for network handlers
85
+ when re-invocation fails, preventing hanging socket connections
86
+
87
+ ## [0.6.0] - 2026-05-12
88
+
89
+ ### Fixed
90
+ - PEP 659: Force de-specialization after `__code__` swap via
91
+ `ctypes.pythonapi.PyFunction_SetCode` — prevents CPython 3.11+
92
+ adaptive bytecode cache from ignoring injected patches
93
+ - Thread blindness: Install trace hook on all threads via
94
+ `threading.settrace` at startup, with `_install_trace_on_all_threads`
95
+ helper covering existing and future threads; added `threading.Lock`
96
+ for thread-safe patch store writes
97
+ - Exception table corruption: Guard injection now detects try/except
98
+ scope via `TryBegin`/`TryEnd` markers and redirects to function
99
+ entry-point injection to avoid corrupting `co_exceptiontable` offsets
100
+ in CPython 3.11+
101
+
102
+ ## [0.5.1] - 2026-05-11
103
+
104
+ ### Fixed
105
+ - propagate_patch: skip list/dict/set/generator comprehensions
106
+ instead of crashing with AttributeError on __code__
107
+ - key_guard, subscript_guard, chain_subscript_guard: infer
108
+ correct default type from downstream bytecode usage
109
+ (string methods -> "" default, numeric ops -> 0 default)
110
+ - KeyError on chained subscripts (e.g. request["headers"]["auth"].strip())
111
+ now produces a chain_subscript_guard instead of a simple key_guard,
112
+ preventing secondary TypeError from None subscript access
113
+
114
+ ## [0.5.0] - 2026-05-08
115
+
116
+ ### Added
117
+ - Async/await support (CO_COROUTINE frame detection) — automatic `RESUME 0` preservation for coroutine bytecode patching.
118
+ - Watch mode: `codesuture watch --max-restarts N` — subprocess loop with automatic crash-patch-restart cycle.
119
+ - Explain command: `codesuture explain [func_name]` — detailed table of active patches with safety assessment (LIKELY/RISKY/UNKNOWN).
120
+ - WSGI middleware: `CodeSutureMiddleware` — intercepts request handler exceptions, patches, and retries with `X-CodeSuture` response header.
121
+
122
+ ## [0.4.0] - 2026-05-07
123
+
124
+ ### Added
125
+ - `codesuture rollback` command to selectively remove persisted patches (`codesuture rollback <func>`, `--all`, and `--dry-run`).
126
+ - Three new guard types:
127
+ - `type_coercion_guard` for `TypeError` and `ValueError` during type conversions.
128
+ - `index_guard` for `IndexError` bounds checking.
129
+ - `key_guard` for safe dictionary `KeyError` fallbacks.
130
+ - Enhanced `--dry-run` mode with confidence levels (HIGH/MEDIUM/LOW) based on fingerprint registry hits.
131
+ - Full PyPI packaging structure (`pyproject.toml`, complete `README.md`, `CHANGELOG.md`).
132
+
133
+ ### Changed
134
+ - Migrated legacy guards `list_bound_guard` to `index_guard` and `dict_get_guard` to `key_guard` for consistency.
135
+ - Standardized CLI output format and improved error reporting.
136
+
137
+ ## [0.3.0] - 2026-05-06
138
+
139
+ ### Added
140
+ - Upgrade D1: Semantic diff safety gate to prevent runaway bytecode corruption.
141
+ - Upgrade D2: Caller-aware patch propagation to automatically fix closures and bound methods in-memory.
142
+ - Upgrade D3: Shadow execution mode (`--shadow`) to monitor and warn when sentinel defaults leak downstream.
143
+ - Upgrade D4: Patch expiry TTL warnings to nudge developers toward source-level fixes.
144
+ - Upgrade D5: Bytecode fingerprint registry for instant cache hits on known crash patterns.
145
+ - Upgrade D6: `codesuture audit` command for viewing all active patches in a formatted table.
146
+
147
+ ### Fixed
148
+ - Addressed Windows `UnicodeDecodeError` and `cp1252` terminal limitations by enforcing `utf-8` encoding.
149
+ - Resolved a race condition where patch persistence was executing after the code object swap, preventing correct caller identification.
150
+ - Fixed namespace pollution during nested patching.
@@ -0,0 +1,249 @@
1
+ Metadata-Version: 2.4
2
+ Name: codesuture
3
+ Version: 0.7.1
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
+ Classifier: Programming Language :: Python :: 3.13
15
+ Requires-Python: >=3.11
16
+ Description-Content-Type: text/markdown
17
+ License-File: LICENSE
18
+ Requires-Dist: bytecode>=0.15.1
19
+ Provides-Extra: autonomous
20
+ Requires-Dist: llama-cpp-python; extra == "autonomous"
21
+ Dynamic: license-file
22
+
23
+ # CodeSuture
24
+
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)]()
33
+
34
+ ```
35
+ pip install codesuture
36
+ ```
37
+
38
+ ---
39
+
40
+ ## What it does
41
+
42
+ 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.
43
+
44
+ The patch persists. Next run, it loads before the first function call.
45
+
46
+ 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.
47
+
48
+ ---
49
+
50
+ ## Quick start — script
51
+
52
+ ```bash
53
+ codesuture run your_script.py
54
+ ```
55
+
56
+ ```
57
+ [CodeSuture] Caught AttributeError: 'NoneType' object has no attribute 'bio'
58
+ [CodeSuture] Applying null_guard on 'profile' ...
59
+ [CodeSuture] Patch applied to get_bio().
60
+ [CodeSuture] Re-executing after 1 patch(es)...
61
+
62
+ Session summary:
63
+ Patches applied: 1
64
+ ```
65
+
66
+ Run it again:
67
+
68
+ ```
69
+ [CodeSuture] Already healed, skipping: loaded persistent patch for get_bio
70
+ Session summary:
71
+ Patches applied: 0
72
+ ```
73
+
74
+ ---
75
+
76
+ ## Quick start — live server
77
+
78
+ ```bash
79
+ codesuture run server.py --verbose --retries 3
80
+ ```
81
+
82
+ ```
83
+ [CodeSuture] Caught AttributeError: 'NoneType' object has no attribute 'get_profile'
84
+ [CodeSuture] Applying null_guard on 'get_profile' ...
85
+ [CodeSuture DEBUG] Diff: +12 -9 instructions (allowed <= 55)
86
+ [CodeSuture] Patch applied to do_GET().
87
+ [CodeSuture] Transaction replay armed for do_GET().
88
+ [CodeSuture] Transaction replay: retrying patched HTTP handler in-place.
89
+ 127.0.0.1 - - "GET /user-data HTTP/1.1" 200 -
90
+ ```
91
+
92
+ The client sees:
93
+
94
+ ```http
95
+ HTTP/1.0 200 OK
96
+ Content-type: application/json
97
+ X-CodeSuture: patched=1; guard=null_guard; target=get_profile
98
+
99
+ {"result": null}
100
+ ```
101
+
102
+ No 500. No traceback. Server process intact.
103
+
104
+ ---
105
+
106
+ ## How it works
107
+
108
+ 1. **Catch** — `sys.settrace` (3.11) or `sys.monitoring` (3.12+) intercepts exceptions at the exact frame and bytecode offset.
109
+ 2. **Analyze** — The pattern matcher walks the instruction chain and identifies the failing variable or operation.
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.
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.
113
+
114
+ No source files are modified.
115
+
116
+ ---
117
+
118
+ ## Supported guard types
119
+
120
+ | Guard type | Triggers on | Example |
121
+ |---|---|---|
122
+ | `null_guard` | `AttributeError` on `None` | `user.profile.bio` when `profile` is `None` |
123
+ | `key_guard` | `KeyError` | `cfg["timeout"]` when key is missing |
124
+ | `subscript_guard` | `TypeError` subscripting `None` | `data["key"]` when `data` is `None` |
125
+ | `chain_subscript_guard` | Nested subscript on `None` | `data["user"]["name"]` |
126
+ | `index_guard` | `IndexError` | `items[10]` when `len(items) == 2` |
127
+ | `type_coercion_guard` | `TypeError` on conversion | `int("not_a_number")` |
128
+ | `division_guard` | `ZeroDivisionError` | `x / count` when `count == 0` |
129
+ | `str_coerce_guard` | `TypeError` on string concat | `"age: " + 25` |
130
+ | `file_guard` | `FileNotFoundError` | `open(path)` when file is missing |
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 |
133
+
134
+ ---
135
+
136
+ ## CLI reference
137
+
138
+ | Command | Flags | What it does |
139
+ |---|---|---|
140
+ | `codesuture run <script>` | | Run with live patching |
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) |
147
+ | `codesuture watch <script>` | `--max-restarts N` | Run continuously, restart after each patch |
148
+ | `codesuture audit` | | Show all active patches in a table |
149
+ | `codesuture explain` | | Plain-language breakdown of every patch |
150
+ | `codesuture explain <name>` | | Explain one function's patch |
151
+ | `codesuture rollback <name>` | | Remove one persisted patch and restore runtime code |
152
+ | `codesuture rollback` | `--all` | Remove all patches and fingerprint registry |
153
+ | `codesuture rollback` | `--dry-run` | Preview what would be removed |
154
+
155
+ ---
156
+
157
+ ## HTTP recovery
158
+
159
+ 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.
160
+
161
+ 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.
162
+
163
+ Every patched response carries:
164
+
165
+ ```
166
+ X-CodeSuture: patched=1; guard=<type>; target=<variable>
167
+ ```
168
+
169
+ ### WSGI middleware
170
+
171
+ ```python
172
+ from codesuture.middleware import CodeSutureMiddleware
173
+
174
+ app = CodeSutureMiddleware(wsgi_app)
175
+ ```
176
+
177
+ See the implementation in [codesuture/middleware.py](codesuture/middleware.py).
178
+
179
+ ---
180
+
181
+ ## Safety features
182
+
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.
190
+
191
+ ---
192
+
193
+ ## What CodeSuture is not
194
+
195
+ **Not a logger.** It does not record exceptions and move on. It patches the function and retries.
196
+
197
+ **Not a static analyzer.** It operates at runtime on live bytecode, not on source.
198
+
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.
200
+
201
+ ---
202
+
203
+ ## Known limitations
204
+
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
+ - **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)
238
+
239
+ ---
240
+
241
+ ## License
242
+
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)
@@ -0,0 +1,227 @@
1
+ # CodeSuture
2
+
3
+ ![CodeSuture Banner](assets/banner.png)
4
+
5
+ **Runtime guard synthesis for CPython 3.11+. Catches structural crashes, patches live bytecode, keeps your server running.**
6
+
7
+ [![Version](https://img.shields.io/badge/version-0.7.1-blue)]()
8
+ [![Python](https://img.shields.io/badge/python-3.11%2B-brightgreen)]()
9
+ [![License: MIT](https://img.shields.io/badge/license-MIT-green)](LICENSE)
10
+ [![Status](https://img.shields.io/badge/status-beta-orange)]()
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
+ See the implementation in [codesuture/middleware.py](codesuture/middleware.py).
156
+
157
+ ---
158
+
159
+ ## Safety features
160
+
161
+ - **Semantic diff gate** — Patches that modify too many instructions are rejected. The engine never corrupts a complex function to fix a simple crash.
162
+ - **SHA-256 integrity** — Persisted patches are checksummed. Tampered `.code` files are refused on load.
163
+ - **Caller-aware propagation** — After patching, `gc.get_referrers` updates every live reference: closures, bound methods, partials. No stale copy survives.
164
+ - **Patch validation** — Synthesized bytecode is checked for `LOAD_FAST` references to variables not in `co_varnames`. Invalid patches are rejected before application.
165
+ - **Patch expiry (TTL)** — Every patch carries a time-to-live. Aged patches trigger a warning to fix the root cause in source.
166
+ - **Thread safety** — All shared state (fingerprint registry, persistence store, healed function sets) is protected by locks.
167
+ - **Rollback** — `codesuture rollback` removes persisted files AND restores original code in the running process.
168
+
169
+ ---
170
+
171
+ ## What CodeSuture is not
172
+
173
+ **Not a logger.** It does not record exceptions and move on. It patches the function and retries.
174
+
175
+ **Not a static analyzer.** It operates at runtime on live bytecode, not on source.
176
+
177
+ **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.
178
+
179
+ ---
180
+
181
+ ## Known limitations
182
+
183
+ <<<<<<< HEAD
184
+ **Python 3.11+ only.** CodeSuture depends on CPython 3.11 bytecode structures.
185
+
186
+ **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.
187
+
188
+ **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.
189
+
190
+ **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.
191
+
192
+ **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.
193
+
194
+ **HTTP recovery covers simple server paths.** Validated against `http.server` and `socketserver`. Full ASGI framework support is in progress.
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)
@@ -0,0 +1,2 @@
1
+ __version__ = "0.7.1"
2
+