aether-lang-runtime 0.1.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.
- aether_lang_runtime-0.1.0/.gitignore +26 -0
- aether_lang_runtime-0.1.0/PKG-INFO +457 -0
- aether_lang_runtime-0.1.0/README.md +427 -0
- aether_lang_runtime-0.1.0/ai_runtime/__init__.py +31 -0
- aether_lang_runtime-0.1.0/ai_runtime/_types.py +66 -0
- aether_lang_runtime-0.1.0/ai_runtime/ast/engine.py +301 -0
- aether_lang_runtime-0.1.0/ai_runtime/cli.py +208 -0
- aether_lang_runtime-0.1.0/ai_runtime/observability/__init__.py +14 -0
- aether_lang_runtime-0.1.0/ai_runtime/observability/audit_log.py +209 -0
- aether_lang_runtime-0.1.0/ai_runtime/observability/diff.py +276 -0
- aether_lang_runtime-0.1.0/ai_runtime/observability/events.py +69 -0
- aether_lang_runtime-0.1.0/ai_runtime/orchestrator.py +363 -0
- aether_lang_runtime-0.1.0/ai_runtime/patch_engine.py +272 -0
- aether_lang_runtime-0.1.0/ai_runtime/sandbox.py +326 -0
- aether_lang_runtime-0.1.0/ai_runtime/sandbox_runner.py +136 -0
- aether_lang_runtime-0.1.0/ai_runtime/sandbox_t1.py +317 -0
- aether_lang_runtime-0.1.0/ai_runtime/sandbox_t2.py +227 -0
- aether_lang_runtime-0.1.0/ai_runtime/sandbox_t3.py +392 -0
- aether_lang_runtime-0.1.0/ai_runtime/snapshot/__init__.py +12 -0
- aether_lang_runtime-0.1.0/ai_runtime/snapshot/gitignore.py +200 -0
- aether_lang_runtime-0.1.0/ai_runtime/snapshot/lock.py +138 -0
- aether_lang_runtime-0.1.0/ai_runtime/snapshot/store.py +441 -0
- aether_lang_runtime-0.1.0/ai_runtime/validation/__init__.py +25 -0
- aether_lang_runtime-0.1.0/ai_runtime/validation/ae_bridge.py +363 -0
- aether_lang_runtime-0.1.0/ai_runtime/validation/patch_schema.json +231 -0
- aether_lang_runtime-0.1.0/ai_runtime/validation/rules.py +209 -0
- aether_lang_runtime-0.1.0/ai_runtime/validation/schema.py +111 -0
- aether_lang_runtime-0.1.0/pyproject.toml +61 -0
- aether_lang_runtime-0.1.0/tests/test_agent_skill_examples.py +20 -0
- aether_lang_runtime-0.1.0/tests/test_ast_engine.py +234 -0
- aether_lang_runtime-0.1.0/tests/test_cli_agent_commands.py +77 -0
- aether_lang_runtime-0.1.0/tests/test_ffi_fuzz.py +312 -0
- aether_lang_runtime-0.1.0/tests/test_observability.py +108 -0
- aether_lang_runtime-0.1.0/tests/test_orchestrator.py +222 -0
- aether_lang_runtime-0.1.0/tests/test_rollback_fault.py +289 -0
- aether_lang_runtime-0.1.0/tests/test_sandbox.py +257 -0
- aether_lang_runtime-0.1.0/tests/test_sandbox_t2.py +65 -0
- aether_lang_runtime-0.1.0/tests/test_sandbox_t3_windows.py +50 -0
- aether_lang_runtime-0.1.0/tests/test_semantic_gate.py +330 -0
- aether_lang_runtime-0.1.0/tests/test_snapshot.py +329 -0
- aether_lang_runtime-0.1.0/tests/test_validation.py +323 -0
- aether_lang_runtime-0.1.0/uv.lock +1195 -0
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# Python
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.pyc
|
|
4
|
+
*.pyo
|
|
5
|
+
*.pyd
|
|
6
|
+
.mypy_cache/
|
|
7
|
+
.ruff_cache/
|
|
8
|
+
.pytest_cache/
|
|
9
|
+
*.egg-info/
|
|
10
|
+
dist/
|
|
11
|
+
build/
|
|
12
|
+
.venv/
|
|
13
|
+
venv/
|
|
14
|
+
env/
|
|
15
|
+
|
|
16
|
+
# AI-Safe runtime store (generated at runtime, not source)
|
|
17
|
+
.ai_runtime/
|
|
18
|
+
.benchmarks/
|
|
19
|
+
|
|
20
|
+
# Coverage
|
|
21
|
+
.coverage
|
|
22
|
+
htmlcov/
|
|
23
|
+
|
|
24
|
+
# OS
|
|
25
|
+
.DS_Store
|
|
26
|
+
Thumbs.db
|
|
@@ -0,0 +1,457 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: aether-lang-runtime
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: AI-Safe Execution Infrastructure: structured, sandboxed, reversible AI code modification
|
|
5
|
+
License: MIT
|
|
6
|
+
Keywords: agents,ai,execution,patch,safe,sandbox
|
|
7
|
+
Classifier: Development Status :: 3 - Alpha
|
|
8
|
+
Classifier: Intended Audience :: Developers
|
|
9
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
10
|
+
Classifier: Programming Language :: Python :: 3
|
|
11
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
14
|
+
Classifier: Topic :: Security
|
|
15
|
+
Classifier: Topic :: Software Development :: Libraries
|
|
16
|
+
Requires-Python: >=3.10
|
|
17
|
+
Requires-Dist: jsonschema>=4.22
|
|
18
|
+
Requires-Dist: libcst>=1.1.0
|
|
19
|
+
Requires-Dist: pathspec>=0.12
|
|
20
|
+
Requires-Dist: zstandard>=0.23; sys_platform != 'win32'
|
|
21
|
+
Provides-Extra: dev
|
|
22
|
+
Requires-Dist: mypy>=1.10; extra == 'dev'
|
|
23
|
+
Requires-Dist: pytest-benchmark>=4.0; extra == 'dev'
|
|
24
|
+
Requires-Dist: pytest-cov>=5.0; extra == 'dev'
|
|
25
|
+
Requires-Dist: pytest>=8.0; extra == 'dev'
|
|
26
|
+
Requires-Dist: ruff>=0.5; extra == 'dev'
|
|
27
|
+
Provides-Extra: wasm
|
|
28
|
+
Requires-Dist: wasmtime>=23.0; extra == 'wasm'
|
|
29
|
+
Description-Content-Type: text/markdown
|
|
30
|
+
|
|
31
|
+
# AI-Safe Execution Infrastructure
|
|
32
|
+
|
|
33
|
+
> **A structured, sandboxed, and reversible execution layer for AI-driven code modification.**
|
|
34
|
+
|
|
35
|
+
[](https://www.python.org/downloads/)
|
|
36
|
+
[](LICENSE)
|
|
37
|
+
[](#testing)
|
|
38
|
+
[](#requirements)
|
|
39
|
+
|
|
40
|
+
---
|
|
41
|
+
|
|
42
|
+
## The Problem
|
|
43
|
+
|
|
44
|
+
When AI agents generate code and apply it directly to a codebase, several fundamental failure modes emerge:
|
|
45
|
+
|
|
46
|
+
| Failure | Impact |
|
|
47
|
+
|:--------|:-------|
|
|
48
|
+
| **Syntax errors** | File is broken, app crashes |
|
|
49
|
+
| **Semantic errors** | Logic is wrong, tests fail silently |
|
|
50
|
+
| **Uncontrolled execution** | Changes applied directly against live state |
|
|
51
|
+
| **No rollback path** | Recovery requires manual `git reset` or worse |
|
|
52
|
+
| **Ambiguous intent** | Agent emits free-form diffs, no structured contract |
|
|
53
|
+
|
|
54
|
+
`aether-lang-runtime` reframes the problem: instead of agents generating raw source code, they emit **structured patch instructions** — a typed JSON contract — that the runtime validates, sandboxes, and commits or rolls back automatically.
|
|
55
|
+
|
|
56
|
+
---
|
|
57
|
+
|
|
58
|
+
## Architecture
|
|
59
|
+
|
|
60
|
+
```
|
|
61
|
+
┌─────────────────────────────────────────────────────────────────┐
|
|
62
|
+
│ AI Agent │
|
|
63
|
+
│ (LLM, Copilot, AutoGPT, etc.) │
|
|
64
|
+
└────────────────────────┬────────────────────────────────────────┘
|
|
65
|
+
│ Structured Patch (JSON)
|
|
66
|
+
▼
|
|
67
|
+
┌─────────────────────────────────────────────────────────────────┐
|
|
68
|
+
│ Validation Layer │
|
|
69
|
+
│ │
|
|
70
|
+
│ Gate 1 ──── JSON Schema (Draft 2020-12) │
|
|
71
|
+
│ • Action type enforcement │
|
|
72
|
+
│ • UUID patch_id required │
|
|
73
|
+
│ • Payload size ceiling (64 KB) │
|
|
74
|
+
│ • Timeout bounds [100ms – 30s] │
|
|
75
|
+
│ │
|
|
76
|
+
│ Gate 2 ──── Allow-list & Security Rules │
|
|
77
|
+
│ • (action, operation) allow-list │
|
|
78
|
+
│ • No absolute paths / path traversal │
|
|
79
|
+
│ • No os.system / subprocess / eval in payload │
|
|
80
|
+
│ • run_script requires explicit trust elevation │
|
|
81
|
+
└────────────────────────┬────────────────────────────────────────┘
|
|
82
|
+
│ Valid patch only
|
|
83
|
+
▼
|
|
84
|
+
┌─────────────────────────────────────────────────────────────────┐
|
|
85
|
+
│ Snapshot System │
|
|
86
|
+
│ │
|
|
87
|
+
│ • Captures project state → .tar.gz archive │
|
|
88
|
+
│ • .gitignore + .ai_runtimeignore aware │
|
|
89
|
+
│ • Always skips: node_modules / venv / __pycache__ / .git │
|
|
90
|
+
│ • SQLite WAL index (concurrent-reader safe) │
|
|
91
|
+
│ • Cross-platform write lock (fcntl / msvcrt) │
|
|
92
|
+
│ • Atomic rename: no partial archives ever on disk │
|
|
93
|
+
└────────────────────────┬────────────────────────────────────────┘
|
|
94
|
+
│
|
|
95
|
+
▼
|
|
96
|
+
┌─────────────────────────────────────────────────────────────────┐
|
|
97
|
+
│ Sandbox Execution │
|
|
98
|
+
│ │
|
|
99
|
+
│ Tier 1 ── Cranelift JIT (zero-syscall, v1.2+) │
|
|
100
|
+
│ Tier 2 ── Wasmtime/WASM (hardware boundary, v1.1+) │
|
|
101
|
+
│ Tier 3 ── Subprocess (OS process isolation, v1.0 ✅) │
|
|
102
|
+
│ • Windows: Win32 Job Objects (memory limit) │
|
|
103
|
+
│ • Linux: resource.setrlimit (RLIMIT_AS + CPU) │
|
|
104
|
+
│ • Timeout enforced via communicate(timeout=) │
|
|
105
|
+
│ • CREATE_NEW_PROCESS_GROUP (Windows signal safety) │
|
|
106
|
+
│ • setsid() + preexec_fn (Unix process group) │
|
|
107
|
+
└────────────────────────┬────────────────────────────────────────┘
|
|
108
|
+
│
|
|
109
|
+
┌──────────┴──────────┐
|
|
110
|
+
│ │
|
|
111
|
+
Success Failure
|
|
112
|
+
│ │
|
|
113
|
+
▼ ▼
|
|
114
|
+
┌──────────┐ ┌──────────────┐
|
|
115
|
+
│ Commit │ │ Rollback │
|
|
116
|
+
│ snapshot │ │ from archive │
|
|
117
|
+
└──────────┘ └──────────────┘
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
---
|
|
121
|
+
|
|
122
|
+
## Project Layout
|
|
123
|
+
|
|
124
|
+
```
|
|
125
|
+
aether-lang/
|
|
126
|
+
├── sdk/
|
|
127
|
+
│ └── python/
|
|
128
|
+
│ ├── ai_runtime/
|
|
129
|
+
│ │ ├── __init__.py # Public API: PatchEngine, Sandbox, etc.
|
|
130
|
+
│ │ ├── _types.py # Shared dataclasses (ExecutionResult, SnapshotHandle)
|
|
131
|
+
│ │ ├── patch_engine.py # PatchEngine — validate() + apply() orchestrator
|
|
132
|
+
│ │ ├── sandbox.py # Sandbox — tier-dispatching execution environment
|
|
133
|
+
│ │ ├── sandbox_t3.py # T3 subprocess backend (Windows + Unix)
|
|
134
|
+
│ │ ├── sandbox_runner.py # Worker script run inside child process
|
|
135
|
+
│ │ ├── validation/
|
|
136
|
+
│ │ │ ├── patch_schema.json # JSON Schema Draft 2020-12 contract
|
|
137
|
+
│ │ │ ├── schema.py # Gate 1: schema validator
|
|
138
|
+
│ │ │ └── rules.py # Gate 2: allow-list + security rules
|
|
139
|
+
│ │ └── snapshot/
|
|
140
|
+
│ │ ├── __init__.py
|
|
141
|
+
│ │ ├── store.py # SnapshotStore — capture/restore/commit/prune
|
|
142
|
+
│ │ ├── gitignore.py # .gitignore-aware file collector
|
|
143
|
+
│ │ └── lock.py # Cross-platform advisory file lock
|
|
144
|
+
│ └── tests/
|
|
145
|
+
│ ├── test_validation.py # Phase 1: 34 tests
|
|
146
|
+
│ ├── test_sandbox.py # Phase 2: 26 tests (cross-platform)
|
|
147
|
+
│ ├── test_sandbox_t3_windows.py # Phase 2: 3 tests (Windows-only)
|
|
148
|
+
│ └── test_snapshot.py # Phase 3: 31 tests
|
|
149
|
+
├── architecture doc/
|
|
150
|
+
│ └── AI-Safe-Execution-Infrastructure-Documentation.md
|
|
151
|
+
└── crates/ # Legacy Aether language compiler (Cranelift/Rust)
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
---
|
|
155
|
+
|
|
156
|
+
## Quick Start
|
|
157
|
+
|
|
158
|
+
### Install
|
|
159
|
+
|
|
160
|
+
```bash
|
|
161
|
+
pip install aether-lang-runtime
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
### Basic usage
|
|
165
|
+
|
|
166
|
+
```python
|
|
167
|
+
import uuid
|
|
168
|
+
from ai_runtime import PatchEngine
|
|
169
|
+
|
|
170
|
+
engine = PatchEngine()
|
|
171
|
+
|
|
172
|
+
patch = {
|
|
173
|
+
"schema_version": "1.0",
|
|
174
|
+
"patch_id": str(uuid.uuid4()), # must be valid UUID v4
|
|
175
|
+
"action": "modify_function",
|
|
176
|
+
"target": {
|
|
177
|
+
"file": "src/app.py", # relative path only
|
|
178
|
+
"symbol": "calculate_total",
|
|
179
|
+
"symbol_type": "function",
|
|
180
|
+
},
|
|
181
|
+
"changes": {
|
|
182
|
+
"operation": "replace_body",
|
|
183
|
+
"payload": " return sum(items)",
|
|
184
|
+
},
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
report = engine.validate(patch)
|
|
188
|
+
if report.ok:
|
|
189
|
+
engine.apply(patch)
|
|
190
|
+
print(f"✅ Applied in {report.elapsed_ms:.1f}ms")
|
|
191
|
+
else:
|
|
192
|
+
print(f"❌ Rejected: {report.first_error}")
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
### Agent CLI
|
|
196
|
+
|
|
197
|
+
After installation, agents can use Aether without writing Python glue:
|
|
198
|
+
|
|
199
|
+
```bash
|
|
200
|
+
aether validate patch.json
|
|
201
|
+
aether apply patch.json
|
|
202
|
+
aether rollback <snapshot-id>
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
`aether apply` runs validation through `PatchOrchestrator`, captures a snapshot,
|
|
206
|
+
applies the patch, and rolls back if application fails. `ae-safe` is kept as a
|
|
207
|
+
backwards-compatible alias for the same CLI.
|
|
208
|
+
|
|
209
|
+
### With snapshot + auto-rollback
|
|
210
|
+
|
|
211
|
+
```python
|
|
212
|
+
from ai_runtime import PatchEngine, Sandbox
|
|
213
|
+
|
|
214
|
+
sandbox = Sandbox(project_root=".")
|
|
215
|
+
engine = PatchEngine(sandbox=sandbox)
|
|
216
|
+
|
|
217
|
+
# Capture state before any change
|
|
218
|
+
handle = sandbox.snapshot(patch_id=patch["patch_id"])
|
|
219
|
+
|
|
220
|
+
report = engine.validate(patch)
|
|
221
|
+
if report.ok:
|
|
222
|
+
result = engine.apply(patch)
|
|
223
|
+
if result and result.failed:
|
|
224
|
+
# Execution failed — restore immediately
|
|
225
|
+
sandbox.restore(handle)
|
|
226
|
+
print(f"⚠️ Rolled back: {result.error}")
|
|
227
|
+
else:
|
|
228
|
+
sandbox.commit_snapshot(handle)
|
|
229
|
+
print("✅ Committed")
|
|
230
|
+
else:
|
|
231
|
+
print(f"❌ Rejected at gate {report.first_error}")
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
### Execute a sandboxed script
|
|
235
|
+
|
|
236
|
+
```python
|
|
237
|
+
from ai_runtime import Sandbox
|
|
238
|
+
|
|
239
|
+
with Sandbox(project_root=".") as sb:
|
|
240
|
+
result = sb.execute(
|
|
241
|
+
payload="print('hello from sandbox')",
|
|
242
|
+
timeout_ms=5000,
|
|
243
|
+
memory_limit_mb=128,
|
|
244
|
+
)
|
|
245
|
+
|
|
246
|
+
print(result.stdout) # "hello from sandbox"
|
|
247
|
+
print(result.tier) # "t3_subprocess"
|
|
248
|
+
print(result.succeeded) # True
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
---
|
|
252
|
+
|
|
253
|
+
## Patch Schema
|
|
254
|
+
|
|
255
|
+
Every patch must be a JSON object conforming to [patch_schema.json](ai_runtime/validation/patch_schema.json) (JSON Schema Draft 2020-12).
|
|
256
|
+
|
|
257
|
+
### Required fields
|
|
258
|
+
|
|
259
|
+
| Field | Type | Description |
|
|
260
|
+
|:------|:-----|:------------|
|
|
261
|
+
| `schema_version` | `"1.0"` | Schema version — must be exactly `"1.0"` |
|
|
262
|
+
| `patch_id` | UUID v4 string | Unique identifier for idempotency tracking |
|
|
263
|
+
| `action` | enum | One of the 7 supported actions below |
|
|
264
|
+
| `target.file` | string | **Relative** path to the target file |
|
|
265
|
+
| `changes.operation` | string | Operation type (must be in allow-list for action) |
|
|
266
|
+
| `changes.payload` | string | Code content, max 64 KB |
|
|
267
|
+
|
|
268
|
+
### Supported actions
|
|
269
|
+
|
|
270
|
+
| Action | Operations | Description |
|
|
271
|
+
|:-------|:-----------|:------------|
|
|
272
|
+
| `modify_function` | `replace_body`, `insert_before`, `insert_after`, `update_logic` | Modify an existing function |
|
|
273
|
+
| `add_function` | `replace_body` | Insert a new function |
|
|
274
|
+
| `remove_function` | `replace_body` | Delete a function |
|
|
275
|
+
| `modify_class` | `replace_body`, `insert_before`, `insert_after` | Modify a class |
|
|
276
|
+
| `update_import` | `add_import`, `remove_import` | Add or remove imports |
|
|
277
|
+
| `replace_block` | `context_replace` | Context-based block replacement |
|
|
278
|
+
| `run_script` | `run` | Execute a script (requires `trust_level='elevated'`) |
|
|
279
|
+
|
|
280
|
+
### Optional fields
|
|
281
|
+
|
|
282
|
+
```json
|
|
283
|
+
{
|
|
284
|
+
"constraints": {
|
|
285
|
+
"timeout_ms": 5000,
|
|
286
|
+
"memory_limit_mb": 128,
|
|
287
|
+
"allow_network": false,
|
|
288
|
+
"allow_filesystem": false
|
|
289
|
+
},
|
|
290
|
+
"metadata": {
|
|
291
|
+
"generated_by": "my-agent-v1",
|
|
292
|
+
"model": "gemini-2.0-flash",
|
|
293
|
+
"confidence": 0.95
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
```
|
|
297
|
+
|
|
298
|
+
---
|
|
299
|
+
|
|
300
|
+
## Security Model
|
|
301
|
+
|
|
302
|
+
### Two-gate validation
|
|
303
|
+
|
|
304
|
+
```
|
|
305
|
+
Patch JSON
|
|
306
|
+
│
|
|
307
|
+
▼
|
|
308
|
+
Gate 1: JSON Schema ─── rejects malformed structure
|
|
309
|
+
│
|
|
310
|
+
▼ (valid)
|
|
311
|
+
Gate 2: Security Rules
|
|
312
|
+
├── Operation allow-list ────── unknown (action, operation) pairs rejected
|
|
313
|
+
├── Path safety ─────────────── absolute paths, ../ traversal blocked
|
|
314
|
+
├── Payload patterns ────────── os.system / subprocess / eval blocked
|
|
315
|
+
└── Trust elevation ─────────── run_script requires explicit elevated trust
|
|
316
|
+
│
|
|
317
|
+
▼ (valid)
|
|
318
|
+
Execution
|
|
319
|
+
```
|
|
320
|
+
|
|
321
|
+
### What is NOT protected by this layer
|
|
322
|
+
|
|
323
|
+
- **AI model hallucination**: The runtime validates structure and security, not semantic correctness. A syntactically valid patch can still produce wrong program behaviour.
|
|
324
|
+
- **Supply chain attacks**: Malicious packages in the project's dependencies are not audited.
|
|
325
|
+
- **Persistent rootkits**: A sufficiently clever payload could attempt to escape the T3 subprocess sandbox. T1 (Cranelift) and T2 (WASM) are the hardened tiers for untrusted code.
|
|
326
|
+
|
|
327
|
+
---
|
|
328
|
+
|
|
329
|
+
## Sandbox Tiers
|
|
330
|
+
|
|
331
|
+
| Tier | Technology | Memory Limit | Syscall Restriction | Status |
|
|
332
|
+
|:-----|:-----------|:-------------|:--------------------|:-------|
|
|
333
|
+
| **T3** | OS subprocess | Win32 Job Objects / `RLIMIT_AS` | None (process boundary only) | ✅ v1.0 |
|
|
334
|
+
| **T2** | Wasmtime/WASI | WASM linear memory | WASI capabilities | 🔜 v1.1 |
|
|
335
|
+
| **T1** | Cranelift JIT | Custom memory allocator | Zero syscall surface | 🔜 v1.2 |
|
|
336
|
+
|
|
337
|
+
Tier selection is automatic (`preferred_tier="auto"`). T3 is always available; T1/T2 are used when their respective runtimes are detected.
|
|
338
|
+
|
|
339
|
+
---
|
|
340
|
+
|
|
341
|
+
## Snapshot System
|
|
342
|
+
|
|
343
|
+
### Storage layout
|
|
344
|
+
|
|
345
|
+
```
|
|
346
|
+
<project_root>/
|
|
347
|
+
└── .ai_runtime/
|
|
348
|
+
├── snapshot.lock ← Advisory write lock (fcntl / msvcrt)
|
|
349
|
+
├── snapshots.db ← SQLite index (WAL mode)
|
|
350
|
+
└── snapshots/
|
|
351
|
+
├── <uuid>.tar.gz ← Compressed project archive
|
|
352
|
+
└── ...
|
|
353
|
+
```
|
|
354
|
+
|
|
355
|
+
### What gets snapshotted
|
|
356
|
+
|
|
357
|
+
The file collector applies a layered exclusion strategy:
|
|
358
|
+
|
|
359
|
+
```
|
|
360
|
+
All files in project_root
|
|
361
|
+
│
|
|
362
|
+
▼ Tier 1: O(1) frozenset fast-skip
|
|
363
|
+
│ (node_modules, .git, venv, __pycache__, dist, target, ...)
|
|
364
|
+
│
|
|
365
|
+
▼ Tier 2: pathspec regex
|
|
366
|
+
│ (*.pyc, *.egg-info/, *.so, ...)
|
|
367
|
+
│
|
|
368
|
+
▼ Tier 3: .gitignore patterns
|
|
369
|
+
│
|
|
370
|
+
▼ Tier 4: .ai_runtimeignore patterns
|
|
371
|
+
│
|
|
372
|
+
▼ Tier 5: Size ceiling (> 5 MB per file → skip)
|
|
373
|
+
│
|
|
374
|
+
▼
|
|
375
|
+
Source files to archive
|
|
376
|
+
```
|
|
377
|
+
|
|
378
|
+
### Snapshot lifecycle
|
|
379
|
+
|
|
380
|
+
```
|
|
381
|
+
capture("patch-123") status = 'pending'
|
|
382
|
+
│
|
|
383
|
+
├── patch applied OK ──▶ commit(handle) status = 'committed'
|
|
384
|
+
│
|
|
385
|
+
└── execution failed ──▶ restore(handle) status = 'rolled_back'
|
|
386
|
+
|
|
387
|
+
prune(keep=10) ──▶ deletes oldest committed/rolled_back archives
|
|
388
|
+
```
|
|
389
|
+
|
|
390
|
+
### Concurrency
|
|
391
|
+
|
|
392
|
+
Multiple agents can operate on the same project simultaneously:
|
|
393
|
+
- `validate()` — fully parallel (read-only, no locking)
|
|
394
|
+
- `capture()` / `restore()` — serialized via advisory write lock per project root
|
|
395
|
+
- SQLite WAL mode — concurrent readers never block during write
|
|
396
|
+
|
|
397
|
+
---
|
|
398
|
+
|
|
399
|
+
## Performance SLOs
|
|
400
|
+
|
|
401
|
+
| Operation | Target | Measured (this machine) |
|
|
402
|
+
|:----------|:-------|:------------------------|
|
|
403
|
+
| `validate()` | < 20 ms | **0.12 ms** |
|
|
404
|
+
| `capture()` (< 50 MB project) | < 100 ms | passes ✅ |
|
|
405
|
+
| `restore()` | < 500 ms | passes ✅ |
|
|
406
|
+
| T3 sandbox overhead | < 500 ms | < 200 ms |
|
|
407
|
+
| T3 timeout enforcement | within 2× budget | ✅ |
|
|
408
|
+
|
|
409
|
+
---
|
|
410
|
+
|
|
411
|
+
## Testing
|
|
412
|
+
|
|
413
|
+
```bash
|
|
414
|
+
# Install with dev dependencies
|
|
415
|
+
pip install -e ".[dev]"
|
|
416
|
+
|
|
417
|
+
# Run full suite
|
|
418
|
+
pytest tests/ -v
|
|
419
|
+
|
|
420
|
+
# Phase-by-phase
|
|
421
|
+
pytest tests/test_validation.py # Phase 1 — 34 tests
|
|
422
|
+
pytest tests/test_sandbox.py # Phase 2 — 26 tests
|
|
423
|
+
pytest tests/test_snapshot.py # Phase 3 — 31 tests
|
|
424
|
+
pytest tests/test_sandbox_t3_windows.py # Windows-only — 3 tests
|
|
425
|
+
```
|
|
426
|
+
|
|
427
|
+
Current suite: **94 tests, 94 passed** (Python 3.14 / Windows 11)
|
|
428
|
+
|
|
429
|
+
---
|
|
430
|
+
|
|
431
|
+
## Roadmap
|
|
432
|
+
|
|
433
|
+
| Phase | Status | Description |
|
|
434
|
+
|:------|:-------|:------------|
|
|
435
|
+
| 1 — Validation Layer | ✅ Done | JSON Schema Gate + security rule allow-list |
|
|
436
|
+
| 2 — Sandbox (T3) | ✅ Done | Subprocess isolation, Windows Job Objects, Unix rlimit |
|
|
437
|
+
| 3 — Snapshot System | ✅ Done | `.tar.gz` archives, SQLite WAL, gitignore-aware, cross-platform locks |
|
|
438
|
+
| 4 — Observability | ✅ Done | Structured diffs, audit log, `aether status` CLI |
|
|
439
|
+
| 5 — AST Apply Engine | 🔄 Next | Real `modify_function` / `add_function` via `ast` + `libcst` |
|
|
440
|
+
| 6 — Node.js SDK | 🔜 Planned | `sdk/node/` TypeScript port |
|
|
441
|
+
| 7 — T2 Sandbox (WASM) | 🔜 Planned | Wasmtime WASI integration |
|
|
442
|
+
| 8 — T1 Sandbox (JIT) | 🔜 Planned | Cranelift FFI from existing `crates/ae-codegen` |
|
|
443
|
+
|
|
444
|
+
---
|
|
445
|
+
|
|
446
|
+
## Requirements
|
|
447
|
+
|
|
448
|
+
- Python ≥ 3.11
|
|
449
|
+
- `jsonschema >= 4.22`
|
|
450
|
+
- `pathspec >= 0.12`
|
|
451
|
+
- No Docker, no external daemons, no root required
|
|
452
|
+
|
|
453
|
+
---
|
|
454
|
+
|
|
455
|
+
## License
|
|
456
|
+
|
|
457
|
+
MIT — see [LICENSE](LICENSE).
|