fable-engine 1.3.1__py3-none-any.whl

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 (104) hide show
  1. fable_compressor.py +356 -0
  2. fable_engine/__init__.py +1 -0
  3. fable_engine/actions/__init__.py +291 -0
  4. fable_engine/actions/cas.py +182 -0
  5. fable_engine/actions/deliberation.py +523 -0
  6. fable_engine/actions/fleet.py +807 -0
  7. fable_engine/actions/lifecycle.py +298 -0
  8. fable_engine/actions/scrapers.py +116 -0
  9. fable_engine/actions/system3.py +815 -0
  10. fable_engine/browser.py +824 -0
  11. fable_engine/cas.py +974 -0
  12. fable_engine/fable_session.json +510 -0
  13. fable_engine/guards.py +283 -0
  14. fable_engine/schema.py +714 -0
  15. fable_engine/scrapers/__init__.py +32 -0
  16. fable_engine/scrapers/arxiv.py +115 -0
  17. fable_engine/scrapers/base.py +386 -0
  18. fable_engine/scrapers/github.py +129 -0
  19. fable_engine/scrapers/reddit.py +154 -0
  20. fable_engine/scrapers/web.py +120 -0
  21. fable_engine/scrapers/x.py +125 -0
  22. fable_engine/scrapers/youtube.py +132 -0
  23. fable_engine/server.py +414 -0
  24. fable_engine/session.py +1819 -0
  25. fable_engine/test_server.py +1362 -0
  26. fable_engine/updater.py +541 -0
  27. fable_engine-1.3.1.dist-info/LICENSE +22 -0
  28. fable_engine-1.3.1.dist-info/METADATA +173 -0
  29. fable_engine-1.3.1.dist-info/RECORD +104 -0
  30. fable_engine-1.3.1.dist-info/WHEEL +5 -0
  31. fable_engine-1.3.1.dist-info/entry_points.txt +5 -0
  32. fable_engine-1.3.1.dist-info/top_level.txt +6 -0
  33. fable_mode/__init__.py +3 -0
  34. fable_mode/__main__.py +4 -0
  35. fable_mode/adapters.py +1014 -0
  36. fable_mode/installer.py +553 -0
  37. fable_mode/launcher.py +437 -0
  38. fable_mode/manifest.py +142 -0
  39. fable_mode/resources.json +114 -0
  40. fable_mode/safety.py +103 -0
  41. fable_mode_entry.py +10 -0
  42. fable_v2/__init__.py +146 -0
  43. fable_v2/adapters.py +151 -0
  44. fable_v2/coder_fleet/__init__.py +100 -0
  45. fable_v2/coder_fleet/ast_tools.py +158 -0
  46. fable_v2/coder_fleet/compute.py +199 -0
  47. fable_v2/coder_fleet/design_engine.py +1316 -0
  48. fable_v2/coder_fleet/diagnostics.py +293 -0
  49. fable_v2/coder_fleet/fleet_dispatcher.py +214 -0
  50. fable_v2/coder_fleet/mock_auditor.py +306 -0
  51. fable_v2/coder_fleet/mutation.py +216 -0
  52. fable_v2/coder_fleet/property_oracle.py +260 -0
  53. fable_v2/coder_fleet/receipt_attestor.py +122 -0
  54. fable_v2/coder_fleet/red_team_swarm.py +908 -0
  55. fable_v2/coder_fleet/test_harness.py +198 -0
  56. fable_v2/coder_fleet/vector_engine.py +1287 -0
  57. fable_v2/coder_fleet/visual.py +357 -0
  58. fable_v2/coder_fleet/workspace.py +153 -0
  59. fable_v2/cortical/__init__.py +20 -0
  60. fable_v2/cortical/plasticity_engine.py +992 -0
  61. fable_v2/execution_broker.py +811 -0
  62. fable_v2/proof_engine.py +1141 -0
  63. fable_v2/protocol.py +485 -0
  64. fable_v2/runtime.py +1010 -0
  65. fable_v2/system3/__init__.py +204 -0
  66. fable_v2/system3/causal.py +558 -0
  67. fable_v2/system3/dialectical.py +577 -0
  68. fable_v2/system3/evolution.py +503 -0
  69. fable_v2/system3/executive.py +338 -0
  70. fable_v2/system3/free_energy.py +479 -0
  71. fable_v2/system3/hyperbolic.py +555 -0
  72. fable_v2/system3/induction.py +336 -0
  73. fable_v2/system3/kripke.py +548 -0
  74. fable_v2/system3/oracle.py +745 -0
  75. fable_v2/verifiers.py +72 -0
  76. tests/__init__.py +1 -0
  77. tests/test_anti_loop_circuit_breaker.py +64 -0
  78. tests/test_auto_updater.py +407 -0
  79. tests/test_coder_fleet.py +535 -0
  80. tests/test_delegation_compiler.py +54 -0
  81. tests/test_descriptor_boundaries.py +126 -0
  82. tests/test_design_engine.py +603 -0
  83. tests/test_epistemic_evidence_validator.py +66 -0
  84. tests/test_execution_broker.py +233 -0
  85. tests/test_fable_v2.py +406 -0
  86. tests/test_fleet_transitions.py +116 -0
  87. tests/test_fsm_redteam_evolution.py +406 -0
  88. tests/test_goal_rubric_and_pipeline.py +367 -0
  89. tests/test_hebbian_plasticity.py +585 -0
  90. tests/test_packaging_runtime.py +194 -0
  91. tests/test_proof_engine.py +259 -0
  92. tests/test_red_team_swarm.py +645 -0
  93. tests/test_redteam_remediation.py +169 -0
  94. tests/test_registration_transaction.py +375 -0
  95. tests/test_requested_regressions.py +467 -0
  96. tests/test_scrapers.py +370 -0
  97. tests/test_server_actions.py +93 -0
  98. tests/test_server_frontier_actions.py +269 -0
  99. tests/test_server_protocol.py +88 -0
  100. tests/test_stealth_browser.py +970 -0
  101. tests/test_system3.py +381 -0
  102. tests/test_system3_deep_integration.py +385 -0
  103. tests/test_system3_frontier.py +436 -0
  104. tests/test_vector_engine.py +608 -0
@@ -0,0 +1,260 @@
1
+ """Property Oracle Engine for Boundary Matrix Generation and Algebraic Invariant Verification.
2
+
3
+ Generates extreme edge-case fuzzing matrices and verifies roundtrip invariants
4
+ (e.g., decode(encode(x)) == x) using isolated execution harnesses.
5
+ """
6
+ from __future__ import annotations
7
+
8
+ import base64
9
+ import json
10
+ import math
11
+ import pickle
12
+ import sys
13
+ from typing import Any
14
+
15
+ from .test_harness import TestHarnessEngine
16
+
17
+
18
+ class PropertyOracleEngine:
19
+ """Engine for generating boundary property testing matrices and verifying algebraic invariants."""
20
+
21
+ def __init__(self, test_harness: TestHarnessEngine | None = None) -> None:
22
+ self._harness = test_harness or TestHarnessEngine()
23
+
24
+ def generate_property_matrix(self, types: list[str], count: int = 50) -> list[Any]:
25
+ """Generate extreme boundary values (empty strings, MAX_INT, unicode, negative values,
26
+
27
+ None, large lists, floats) for the specified types.
28
+ """
29
+ pools: list[list[Any]] = []
30
+ normalized_types = {t.lower().strip() for t in types}
31
+
32
+ if any(t in normalized_types for t in ("str", "string", "text")):
33
+ pools.append([
34
+ "",
35
+ " ",
36
+ "\t",
37
+ "\n",
38
+ "\r\n",
39
+ "\x00",
40
+ "null",
41
+ "None",
42
+ "undefined",
43
+ "0",
44
+ "-1",
45
+ "🔥🚀✨🎉",
46
+ "A" * 1024,
47
+ "a\x00b\x00c",
48
+ "<script>alert('xss')</script>",
49
+ "' OR '1'='1' --",
50
+ '{"key": "value", "nested": [1, 2]}',
51
+ "https://example.com/api?q=test&page=1",
52
+ "c:\\Windows\\System32\\cmd.exe",
53
+ "/dev/null",
54
+ ])
55
+
56
+ if any(t in normalized_types for t in ("int", "integer", "number")):
57
+ pools.append([
58
+ 0,
59
+ 1,
60
+ -1,
61
+ 2,
62
+ -2,
63
+ 42,
64
+ -42,
65
+ 100,
66
+ -100,
67
+ 255,
68
+ 256,
69
+ 65535,
70
+ 65536,
71
+ 2**31 - 1,
72
+ -2**31,
73
+ 2**63 - 1,
74
+ -2**63,
75
+ 10**18,
76
+ -10**18,
77
+ sys.maxsize,
78
+ -sys.maxsize - 1,
79
+ ])
80
+
81
+ if any(t in normalized_types for t in ("float", "decimal", "real")):
82
+ pools.append([
83
+ 0.0,
84
+ -0.0,
85
+ 1.0,
86
+ -1.0,
87
+ 0.5,
88
+ -0.5,
89
+ math.pi,
90
+ math.e,
91
+ 1e-15,
92
+ 1e15,
93
+ 1e-300,
94
+ 1e300,
95
+ float("inf"),
96
+ float("-inf"),
97
+ ])
98
+
99
+ if any(t in normalized_types for t in ("bool", "boolean")):
100
+ pools.append([True, False])
101
+
102
+ if any(t in normalized_types for t in ("list", "array", "sequence")):
103
+ pools.append([
104
+ [],
105
+ [None],
106
+ [0],
107
+ [""],
108
+ [True, False],
109
+ [1, 2, 3, 4, 5],
110
+ ["alpha", "beta", "gamma"],
111
+ [[], [[]]],
112
+ list(range(50)),
113
+ [0] * 100,
114
+ ])
115
+
116
+ if any(t in normalized_types for t in ("dict", "map", "object")):
117
+ pools.append([
118
+ {},
119
+ {"": ""},
120
+ {"key": "value"},
121
+ {"a": 1, "b": 2, "c": 3},
122
+ {"nested": {"level1": {"level2": True}}},
123
+ {"list": [1, 2, 3]},
124
+ ])
125
+
126
+ if any(t in normalized_types for t in ("none", "null", "nonetype")):
127
+ pools.append([None])
128
+
129
+ if any(t in normalized_types for t in ("bytes", "binary")):
130
+ pools.append([
131
+ b"",
132
+ b"\x00",
133
+ b"hello world",
134
+ b"\xff\xfe\xfd\xfc",
135
+ bytes([i % 256 for i in range(128)]),
136
+ ])
137
+
138
+ if not pools:
139
+ pools.append(["", 0, 0.0, False, None, [], {}])
140
+
141
+ # Interleave round-robin across all requested pools to ensure balanced coverage
142
+ result: list[Any] = []
143
+ max_pool_len = max(len(p) for p in pools)
144
+ for idx in range(max_pool_len):
145
+ for pool in pools:
146
+ if idx < len(pool):
147
+ result.append(pool[idx])
148
+ if len(result) >= count:
149
+ return result
150
+
151
+ # If count still exceeds unique items, cycle through
152
+ cycle_idx = 0
153
+ while len(result) < count and pools:
154
+ pool = pools[cycle_idx % len(pools)]
155
+ result.append(pool[(cycle_idx // len(pools)) % len(pool)])
156
+ cycle_idx += 1
157
+
158
+ return result[:count]
159
+
160
+ def verify_algebraic_invariants(
161
+ self,
162
+ module_code: str,
163
+ encode_fn: str,
164
+ decode_fn: str,
165
+ sample_inputs: list[Any],
166
+ ) -> dict[str, Any]:
167
+ """Test decode(encode(x)) == x roundtrip consistency."""
168
+ if not sample_inputs:
169
+ return {
170
+ "total_tested": 0,
171
+ "passed": 0,
172
+ "failed": 0,
173
+ "success_rate": 1.0,
174
+ "roundtrip_invariant_holds": True,
175
+ "failure_examples": [],
176
+ }
177
+
178
+ encoded_payload = base64.b64encode(pickle.dumps(sample_inputs)).decode("ascii")
179
+
180
+ driver = f"""
181
+ import base64
182
+ import json
183
+ import pickle
184
+ import sys
185
+
186
+ {module_code}
187
+
188
+ raw_inputs = pickle.loads(base64.b64decode("{encoded_payload}".encode("ascii")))
189
+ encoder = globals().get("{encode_fn}")
190
+ decoder = globals().get("{decode_fn}")
191
+
192
+ if encoder is None or decoder is None:
193
+ print("__INVARIANT_OUTPUT__" + json.dumps({{"error": "Target functions not found in module"}}))
194
+ sys.exit(0)
195
+
196
+ total = len(raw_inputs)
197
+ passed = 0
198
+ failed = 0
199
+ failure_examples = []
200
+
201
+ for item in raw_inputs:
202
+ try:
203
+ enc = encoder(item)
204
+ dec = decoder(enc)
205
+ # Handle float nan comparison
206
+ if isinstance(item, float) and item != item:
207
+ is_equal = isinstance(dec, float) and dec != dec
208
+ else:
209
+ is_equal = (dec == item)
210
+
211
+ if is_equal:
212
+ passed += 1
213
+ else:
214
+ failed += 1
215
+ if len(failure_examples) < 10:
216
+ failure_examples.append({{
217
+ "input": repr(item),
218
+ "encoded": repr(enc),
219
+ "decoded": repr(dec),
220
+ "reason": "dec(enc(x)) != x",
221
+ }})
222
+ except Exception as exc:
223
+ failed += 1
224
+ if len(failure_examples) < 10:
225
+ failure_examples.append({{
226
+ "input": repr(item),
227
+ "error": f"{{type(exc).__name__}}: {{exc}}",
228
+ "reason": "Exception during roundtrip",
229
+ }})
230
+
231
+ output = {{
232
+ "total_tested": total,
233
+ "passed": passed,
234
+ "failed": failed,
235
+ "success_rate": round(passed / max(1, total), 4),
236
+ "roundtrip_invariant_holds": failed == 0,
237
+ "failure_examples": failure_examples,
238
+ }}
239
+ print("__INVARIANT_OUTPUT__" + json.dumps(output))
240
+ """
241
+ res = self._harness.run_scratch_test(driver, timeout_sec=6.0)
242
+ marker = "__INVARIANT_OUTPUT__"
243
+
244
+ if marker in res.get("stdout", ""):
245
+ payload_str = res["stdout"].split(marker, 1)[1].strip()
246
+ try:
247
+ data = json.loads(payload_str)
248
+ return data
249
+ except json.JSONDecodeError:
250
+ pass
251
+
252
+ return {
253
+ "total_tested": len(sample_inputs),
254
+ "passed": 0,
255
+ "failed": len(sample_inputs),
256
+ "success_rate": 0.0,
257
+ "roundtrip_invariant_holds": False,
258
+ "error": res.get("stderr") or "Failed to execute roundtrip verification",
259
+ "failure_examples": [],
260
+ }
@@ -0,0 +1,122 @@
1
+ """Receipt Attestor Engine for Cryptographic Tool Execution Attestation.
2
+
3
+ Records process execution telemetry (PID, exit code, stdout/stderr hashes, timestamps)
4
+ and signs them using HMAC-SHA256 into a tamper-evident ToolReceipt.
5
+ """
6
+ from __future__ import annotations
7
+
8
+ import hashlib
9
+ import hmac
10
+ import subprocess
11
+ import time
12
+ import uuid
13
+ from datetime import datetime, timezone
14
+ from typing import Any
15
+
16
+
17
+ class ReceiptAttestorEngine:
18
+ """Engine for attesting subprocess execution and cryptographically verifying execution receipts."""
19
+
20
+ def __init__(self, secret_key: bytes | None = None) -> None:
21
+ self._secret_key = secret_key or hashlib.sha256(b"fable_receipt_attestor_default_secret").digest()
22
+
23
+ def _compute_signature(
24
+ self,
25
+ cmd: list[str],
26
+ cwd: str,
27
+ pid: int,
28
+ started_at: str,
29
+ finished_at: str,
30
+ exit_code: int,
31
+ stdout_hash: str,
32
+ stderr_hash: str,
33
+ ) -> str:
34
+ payload = f"{' '.join(cmd)}|{cwd}|{pid}|{started_at}|{finished_at}|{exit_code}|{stdout_hash}|{stderr_hash}"
35
+ return hmac.new(self._secret_key, payload.encode("utf-8"), hashlib.sha256).hexdigest()
36
+
37
+ def attest_execution(self, cmd: list[str], cwd: str = ".") -> dict[str, Any]:
38
+ """Execute subprocess, record OS PID, start/end time, exit code, stdout hash,
39
+
40
+ and HMAC-SHA256 signature, creating a tamper-evident ToolReceipt.
41
+ """
42
+ started_at = datetime.now(timezone.utc).isoformat()
43
+ t0 = time.perf_counter()
44
+
45
+ proc = subprocess.Popen(
46
+ cmd,
47
+ cwd=cwd,
48
+ stdout=subprocess.PIPE,
49
+ stderr=subprocess.PIPE,
50
+ text=True,
51
+ )
52
+ pid = proc.pid
53
+ stdout, stderr = proc.communicate()
54
+ duration_ms = (time.perf_counter() - t0) * 1000.0
55
+ finished_at = datetime.now(timezone.utc).isoformat()
56
+ exit_code = proc.returncode
57
+
58
+ stdout_hash = hashlib.sha256(stdout.encode("utf-8")).hexdigest()
59
+ stderr_hash = hashlib.sha256(stderr.encode("utf-8")).hexdigest()
60
+
61
+ signature = self._compute_signature(
62
+ cmd=cmd,
63
+ cwd=cwd,
64
+ pid=pid,
65
+ started_at=started_at,
66
+ finished_at=finished_at,
67
+ exit_code=exit_code,
68
+ stdout_hash=stdout_hash,
69
+ stderr_hash=stderr_hash,
70
+ )
71
+
72
+ receipt_id = f"rcpt_{uuid.uuid4().hex[:12]}"
73
+
74
+ return {
75
+ "receipt_id": receipt_id,
76
+ "cmd": list(cmd),
77
+ "cwd": cwd,
78
+ "pid": pid,
79
+ "started_at": started_at,
80
+ "finished_at": finished_at,
81
+ "duration_ms": round(duration_ms, 2),
82
+ "exit_code": exit_code,
83
+ "stdout": stdout,
84
+ "stderr": stderr,
85
+ "stdout_hash": stdout_hash,
86
+ "stderr_hash": stderr_hash,
87
+ "signature": signature,
88
+ "tamper_evident": True,
89
+ }
90
+
91
+ def verify_receipt(self, receipt: dict[str, Any]) -> bool:
92
+ """Validate hash and HMAC-SHA256 signature integrity of a ToolReceipt."""
93
+ if not isinstance(receipt, dict):
94
+ return False
95
+
96
+ required = ("cmd", "cwd", "pid", "started_at", "finished_at", "exit_code", "stdout_hash", "stderr_hash", "signature")
97
+ if not all(k in receipt for k in required):
98
+ return False
99
+
100
+ # If full stdout / stderr text is provided, verify against hashes
101
+ if "stdout" in receipt:
102
+ actual_stdout_hash = hashlib.sha256(str(receipt["stdout"]).encode("utf-8")).hexdigest()
103
+ if actual_stdout_hash != receipt["stdout_hash"]:
104
+ return False
105
+
106
+ if "stderr" in receipt:
107
+ actual_stderr_hash = hashlib.sha256(str(receipt["stderr"]).encode("utf-8")).hexdigest()
108
+ if actual_stderr_hash != receipt["stderr_hash"]:
109
+ return False
110
+
111
+ expected_sig = self._compute_signature(
112
+ cmd=receipt["cmd"],
113
+ cwd=receipt["cwd"],
114
+ pid=int(receipt["pid"]),
115
+ started_at=str(receipt["started_at"]),
116
+ finished_at=str(receipt["finished_at"]),
117
+ exit_code=int(receipt["exit_code"]),
118
+ stdout_hash=str(receipt["stdout_hash"]),
119
+ stderr_hash=str(receipt["stderr_hash"]),
120
+ )
121
+
122
+ return hmac.compare_digest(expected_sig, str(receipt["signature"]))