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.
- fable_compressor.py +356 -0
- fable_engine/__init__.py +1 -0
- fable_engine/actions/__init__.py +291 -0
- fable_engine/actions/cas.py +182 -0
- fable_engine/actions/deliberation.py +523 -0
- fable_engine/actions/fleet.py +807 -0
- fable_engine/actions/lifecycle.py +298 -0
- fable_engine/actions/scrapers.py +116 -0
- fable_engine/actions/system3.py +815 -0
- fable_engine/browser.py +824 -0
- fable_engine/cas.py +974 -0
- fable_engine/fable_session.json +510 -0
- fable_engine/guards.py +283 -0
- fable_engine/schema.py +714 -0
- fable_engine/scrapers/__init__.py +32 -0
- fable_engine/scrapers/arxiv.py +115 -0
- fable_engine/scrapers/base.py +386 -0
- fable_engine/scrapers/github.py +129 -0
- fable_engine/scrapers/reddit.py +154 -0
- fable_engine/scrapers/web.py +120 -0
- fable_engine/scrapers/x.py +125 -0
- fable_engine/scrapers/youtube.py +132 -0
- fable_engine/server.py +414 -0
- fable_engine/session.py +1819 -0
- fable_engine/test_server.py +1362 -0
- fable_engine/updater.py +541 -0
- fable_engine-1.3.1.dist-info/LICENSE +22 -0
- fable_engine-1.3.1.dist-info/METADATA +173 -0
- fable_engine-1.3.1.dist-info/RECORD +104 -0
- fable_engine-1.3.1.dist-info/WHEEL +5 -0
- fable_engine-1.3.1.dist-info/entry_points.txt +5 -0
- fable_engine-1.3.1.dist-info/top_level.txt +6 -0
- fable_mode/__init__.py +3 -0
- fable_mode/__main__.py +4 -0
- fable_mode/adapters.py +1014 -0
- fable_mode/installer.py +553 -0
- fable_mode/launcher.py +437 -0
- fable_mode/manifest.py +142 -0
- fable_mode/resources.json +114 -0
- fable_mode/safety.py +103 -0
- fable_mode_entry.py +10 -0
- fable_v2/__init__.py +146 -0
- fable_v2/adapters.py +151 -0
- fable_v2/coder_fleet/__init__.py +100 -0
- fable_v2/coder_fleet/ast_tools.py +158 -0
- fable_v2/coder_fleet/compute.py +199 -0
- fable_v2/coder_fleet/design_engine.py +1316 -0
- fable_v2/coder_fleet/diagnostics.py +293 -0
- fable_v2/coder_fleet/fleet_dispatcher.py +214 -0
- fable_v2/coder_fleet/mock_auditor.py +306 -0
- fable_v2/coder_fleet/mutation.py +216 -0
- fable_v2/coder_fleet/property_oracle.py +260 -0
- fable_v2/coder_fleet/receipt_attestor.py +122 -0
- fable_v2/coder_fleet/red_team_swarm.py +908 -0
- fable_v2/coder_fleet/test_harness.py +198 -0
- fable_v2/coder_fleet/vector_engine.py +1287 -0
- fable_v2/coder_fleet/visual.py +357 -0
- fable_v2/coder_fleet/workspace.py +153 -0
- fable_v2/cortical/__init__.py +20 -0
- fable_v2/cortical/plasticity_engine.py +992 -0
- fable_v2/execution_broker.py +811 -0
- fable_v2/proof_engine.py +1141 -0
- fable_v2/protocol.py +485 -0
- fable_v2/runtime.py +1010 -0
- fable_v2/system3/__init__.py +204 -0
- fable_v2/system3/causal.py +558 -0
- fable_v2/system3/dialectical.py +577 -0
- fable_v2/system3/evolution.py +503 -0
- fable_v2/system3/executive.py +338 -0
- fable_v2/system3/free_energy.py +479 -0
- fable_v2/system3/hyperbolic.py +555 -0
- fable_v2/system3/induction.py +336 -0
- fable_v2/system3/kripke.py +548 -0
- fable_v2/system3/oracle.py +745 -0
- fable_v2/verifiers.py +72 -0
- tests/__init__.py +1 -0
- tests/test_anti_loop_circuit_breaker.py +64 -0
- tests/test_auto_updater.py +407 -0
- tests/test_coder_fleet.py +535 -0
- tests/test_delegation_compiler.py +54 -0
- tests/test_descriptor_boundaries.py +126 -0
- tests/test_design_engine.py +603 -0
- tests/test_epistemic_evidence_validator.py +66 -0
- tests/test_execution_broker.py +233 -0
- tests/test_fable_v2.py +406 -0
- tests/test_fleet_transitions.py +116 -0
- tests/test_fsm_redteam_evolution.py +406 -0
- tests/test_goal_rubric_and_pipeline.py +367 -0
- tests/test_hebbian_plasticity.py +585 -0
- tests/test_packaging_runtime.py +194 -0
- tests/test_proof_engine.py +259 -0
- tests/test_red_team_swarm.py +645 -0
- tests/test_redteam_remediation.py +169 -0
- tests/test_registration_transaction.py +375 -0
- tests/test_requested_regressions.py +467 -0
- tests/test_scrapers.py +370 -0
- tests/test_server_actions.py +93 -0
- tests/test_server_frontier_actions.py +269 -0
- tests/test_server_protocol.py +88 -0
- tests/test_stealth_browser.py +970 -0
- tests/test_system3.py +381 -0
- tests/test_system3_deep_integration.py +385 -0
- tests/test_system3_frontier.py +436 -0
- tests/test_vector_engine.py +608 -0
|
@@ -0,0 +1,293 @@
|
|
|
1
|
+
"""Diagnostics Engine for AST-based Static Analysis and Automated Quick-Fixes.
|
|
2
|
+
|
|
3
|
+
Pure-Python implementation with zero external C-dependencies.
|
|
4
|
+
"""
|
|
5
|
+
from __future__ import annotations
|
|
6
|
+
|
|
7
|
+
import ast
|
|
8
|
+
import builtins
|
|
9
|
+
import re
|
|
10
|
+
from typing import Any
|
|
11
|
+
|
|
12
|
+
# Standard known library symbols for automated quick-fixes
|
|
13
|
+
KNOWN_IMPORTS: dict[str, str] = {
|
|
14
|
+
"os": "import os",
|
|
15
|
+
"sys": "import sys",
|
|
16
|
+
"re": "import re",
|
|
17
|
+
"json": "import json",
|
|
18
|
+
"math": "import math",
|
|
19
|
+
"time": "import time",
|
|
20
|
+
"datetime": "import datetime",
|
|
21
|
+
"Path": "from pathlib import Path",
|
|
22
|
+
"List": "from typing import List",
|
|
23
|
+
"Dict": "from typing import Dict",
|
|
24
|
+
"Set": "from typing import Set",
|
|
25
|
+
"Tuple": "from typing import Tuple",
|
|
26
|
+
"Optional": "from typing import Optional",
|
|
27
|
+
"Union": "from typing import Union",
|
|
28
|
+
"Any": "from typing import Any",
|
|
29
|
+
"Callable": "from typing import Callable",
|
|
30
|
+
"Iterable": "from typing import Iterable",
|
|
31
|
+
"Mapping": "from typing import Mapping",
|
|
32
|
+
"Sequence": "from typing import Sequence",
|
|
33
|
+
"defaultdict": "from collections import defaultdict",
|
|
34
|
+
"Counter": "from collections import Counter",
|
|
35
|
+
"deque": "from collections import deque",
|
|
36
|
+
"uuid": "import uuid",
|
|
37
|
+
"hashlib": "import hashlib",
|
|
38
|
+
"subprocess": "import subprocess",
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
class DiagnosticsEngine:
|
|
43
|
+
"""Engine for syntax validation, AST semantic diagnostics, and automated quick fixes."""
|
|
44
|
+
|
|
45
|
+
def __init__(self) -> None:
|
|
46
|
+
self._builtins: set[str] = set(dir(builtins)) | {
|
|
47
|
+
"__name__",
|
|
48
|
+
"__doc__",
|
|
49
|
+
"__file__",
|
|
50
|
+
"__package__",
|
|
51
|
+
"__annotations__",
|
|
52
|
+
"__builtins__",
|
|
53
|
+
"__spec__",
|
|
54
|
+
"__loader__",
|
|
55
|
+
"self",
|
|
56
|
+
"cls",
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
def run_diagnostics(self, source_code: str, language: str = "python") -> list[dict[str, Any]]:
|
|
60
|
+
"""Run AST-based syntax and semantic checks.
|
|
61
|
+
|
|
62
|
+
Returns list of {line, col, code, message, severity, symbol}.
|
|
63
|
+
"""
|
|
64
|
+
if language.lower() != "python":
|
|
65
|
+
return [
|
|
66
|
+
{
|
|
67
|
+
"line": 1,
|
|
68
|
+
"col": 0,
|
|
69
|
+
"code": "UNSUPPORTED_LANGUAGE",
|
|
70
|
+
"message": f"Language '{language}' diagnostics not supported (Python only)",
|
|
71
|
+
"severity": "warning",
|
|
72
|
+
}
|
|
73
|
+
]
|
|
74
|
+
|
|
75
|
+
diagnostics: list[dict[str, Any]] = []
|
|
76
|
+
|
|
77
|
+
try:
|
|
78
|
+
tree = ast.parse(source_code)
|
|
79
|
+
except SyntaxError as exc:
|
|
80
|
+
return [
|
|
81
|
+
{
|
|
82
|
+
"line": exc.lineno or 1,
|
|
83
|
+
"col": exc.offset or 0,
|
|
84
|
+
"code": "E999",
|
|
85
|
+
"message": f"SyntaxError: {exc.msg}",
|
|
86
|
+
"severity": "error",
|
|
87
|
+
"symbol": None,
|
|
88
|
+
}
|
|
89
|
+
]
|
|
90
|
+
|
|
91
|
+
# 1. Collect imports, defined symbols, loaded symbols, and special nodes
|
|
92
|
+
imported_symbols: dict[str, tuple[int, int, ast.AST, str]] = {} # name -> (line, col, node, import_stmt)
|
|
93
|
+
defined_symbols: set[str] = set(self._builtins)
|
|
94
|
+
loaded_symbols: list[tuple[str, int, int]] = []
|
|
95
|
+
|
|
96
|
+
class ScopeCollector(ast.NodeVisitor):
|
|
97
|
+
def __init__(self) -> None:
|
|
98
|
+
self.bare_excepts: list[tuple[int, int]] = []
|
|
99
|
+
self.duplicate_keys: list[tuple[int, int, str]] = []
|
|
100
|
+
|
|
101
|
+
def visit_Import(self, node: ast.Import) -> None:
|
|
102
|
+
for alias in node.names:
|
|
103
|
+
name = alias.asname or alias.name.split(".")[0]
|
|
104
|
+
imported_symbols[name] = (node.lineno, node.col_offset, node, "import")
|
|
105
|
+
defined_symbols.add(name)
|
|
106
|
+
self.generic_visit(node)
|
|
107
|
+
|
|
108
|
+
def visit_ImportFrom(self, node: ast.ImportFrom) -> None:
|
|
109
|
+
for alias in node.names:
|
|
110
|
+
name = alias.asname or alias.name
|
|
111
|
+
imported_symbols[name] = (node.lineno, node.col_offset, node, "from")
|
|
112
|
+
defined_symbols.add(name)
|
|
113
|
+
self.generic_visit(node)
|
|
114
|
+
|
|
115
|
+
def visit_FunctionDef(self, node: ast.FunctionDef) -> None:
|
|
116
|
+
defined_symbols.add(node.name)
|
|
117
|
+
for arg in node.args.args + node.args.kwonlyargs:
|
|
118
|
+
defined_symbols.add(arg.arg)
|
|
119
|
+
if node.args.vararg:
|
|
120
|
+
defined_symbols.add(node.args.vararg.arg)
|
|
121
|
+
if node.args.kwarg:
|
|
122
|
+
defined_symbols.add(node.args.kwarg.arg)
|
|
123
|
+
self.generic_visit(node)
|
|
124
|
+
|
|
125
|
+
def visit_AsyncFunctionDef(self, node: ast.AsyncFunctionDef) -> None:
|
|
126
|
+
defined_symbols.add(node.name)
|
|
127
|
+
for arg in node.args.args + node.args.kwonlyargs:
|
|
128
|
+
defined_symbols.add(arg.arg)
|
|
129
|
+
if node.args.vararg:
|
|
130
|
+
defined_symbols.add(node.args.vararg.arg)
|
|
131
|
+
if node.args.kwarg:
|
|
132
|
+
defined_symbols.add(node.args.kwarg.arg)
|
|
133
|
+
self.generic_visit(node)
|
|
134
|
+
|
|
135
|
+
def visit_ClassDef(self, node: ast.ClassDef) -> None:
|
|
136
|
+
defined_symbols.add(node.name)
|
|
137
|
+
self.generic_visit(node)
|
|
138
|
+
|
|
139
|
+
def visit_Name(self, node: ast.Name) -> None:
|
|
140
|
+
if isinstance(node.ctx, (ast.Store, ast.Del)):
|
|
141
|
+
defined_symbols.add(node.id)
|
|
142
|
+
elif isinstance(node.ctx, ast.Load):
|
|
143
|
+
loaded_symbols.append((node.id, node.lineno, node.col_offset))
|
|
144
|
+
self.generic_visit(node)
|
|
145
|
+
|
|
146
|
+
def visit_ExceptHandler(self, node: ast.ExceptHandler) -> None:
|
|
147
|
+
if node.type is None:
|
|
148
|
+
self.bare_excepts.append((node.lineno, node.col_offset))
|
|
149
|
+
if node.name:
|
|
150
|
+
defined_symbols.add(node.name)
|
|
151
|
+
self.generic_visit(node)
|
|
152
|
+
|
|
153
|
+
def visit_comprehension(self, node: ast.comprehension) -> None:
|
|
154
|
+
if isinstance(node.target, ast.Name):
|
|
155
|
+
defined_symbols.add(node.target.id)
|
|
156
|
+
elif isinstance(node.target, (ast.Tuple, ast.List)):
|
|
157
|
+
for elt in node.target.elts:
|
|
158
|
+
if isinstance(elt, ast.Name):
|
|
159
|
+
defined_symbols.add(elt.id)
|
|
160
|
+
self.generic_visit(node)
|
|
161
|
+
|
|
162
|
+
def visit_Dict(self, node: ast.Dict) -> None:
|
|
163
|
+
seen_keys: set[Any] = set()
|
|
164
|
+
for k in node.keys:
|
|
165
|
+
if isinstance(k, ast.Constant):
|
|
166
|
+
if k.value in seen_keys:
|
|
167
|
+
self.duplicate_keys.append((k.lineno, k.col_offset, repr(k.value)))
|
|
168
|
+
else:
|
|
169
|
+
seen_keys.add(k.value)
|
|
170
|
+
self.generic_visit(node)
|
|
171
|
+
|
|
172
|
+
collector = ScopeCollector()
|
|
173
|
+
collector.visit(tree)
|
|
174
|
+
|
|
175
|
+
# 2. Check for unused imports (W0611)
|
|
176
|
+
loaded_names = {name for name, _, _ in loaded_symbols}
|
|
177
|
+
for name, (line, col, _node, _stmt_type) in imported_symbols.items():
|
|
178
|
+
if name not in loaded_names:
|
|
179
|
+
diagnostics.append({
|
|
180
|
+
"line": line,
|
|
181
|
+
"col": col,
|
|
182
|
+
"code": "W0611",
|
|
183
|
+
"message": f"Unused import '{name}'",
|
|
184
|
+
"severity": "warning",
|
|
185
|
+
"symbol": name,
|
|
186
|
+
})
|
|
187
|
+
|
|
188
|
+
# 3. Check for undefined names (E0602)
|
|
189
|
+
reported_undefined: set[str] = set()
|
|
190
|
+
for name, line, col in loaded_symbols:
|
|
191
|
+
if name not in defined_symbols and name not in reported_undefined:
|
|
192
|
+
reported_undefined.add(name)
|
|
193
|
+
diagnostics.append({
|
|
194
|
+
"line": line,
|
|
195
|
+
"col": col,
|
|
196
|
+
"code": "E0602",
|
|
197
|
+
"message": f"Undefined name '{name}'",
|
|
198
|
+
"severity": "error",
|
|
199
|
+
"symbol": name,
|
|
200
|
+
})
|
|
201
|
+
|
|
202
|
+
# 4. Check bare excepts (W0702)
|
|
203
|
+
for line, col in collector.bare_excepts:
|
|
204
|
+
diagnostics.append({
|
|
205
|
+
"line": line,
|
|
206
|
+
"col": col,
|
|
207
|
+
"code": "W0702",
|
|
208
|
+
"message": "Bare 'except:' used without specifying exception type",
|
|
209
|
+
"severity": "warning",
|
|
210
|
+
"symbol": None,
|
|
211
|
+
})
|
|
212
|
+
|
|
213
|
+
# 5. Check duplicate dictionary keys (W0109)
|
|
214
|
+
for line, col, key_repr in collector.duplicate_keys:
|
|
215
|
+
diagnostics.append({
|
|
216
|
+
"line": line,
|
|
217
|
+
"col": col,
|
|
218
|
+
"code": "W0109",
|
|
219
|
+
"message": f"Duplicate key {key_repr} in dictionary literal",
|
|
220
|
+
"severity": "warning",
|
|
221
|
+
"symbol": key_repr,
|
|
222
|
+
})
|
|
223
|
+
|
|
224
|
+
# Sort diagnostics by line number
|
|
225
|
+
diagnostics.sort(key=lambda d: (d.get("line", 0), d.get("col", 0)))
|
|
226
|
+
return diagnostics
|
|
227
|
+
|
|
228
|
+
def apply_quick_fix(self, diagnostic: dict[str, Any], source_code: str) -> str:
|
|
229
|
+
"""Apply an automated fix for a diagnostic issue."""
|
|
230
|
+
code = diagnostic.get("code")
|
|
231
|
+
symbol = diagnostic.get("symbol")
|
|
232
|
+
line_num = diagnostic.get("line", 1)
|
|
233
|
+
lines = source_code.splitlines(keepends=True)
|
|
234
|
+
|
|
235
|
+
if code == "W0611" and symbol:
|
|
236
|
+
# Unused import removal
|
|
237
|
+
if 1 <= line_num <= len(lines):
|
|
238
|
+
target_line = lines[line_num - 1]
|
|
239
|
+
# If the line only imports this symbol, remove the line
|
|
240
|
+
# Example: "import os\n" or "from math import sqrt\n"
|
|
241
|
+
clean = target_line.strip()
|
|
242
|
+
if clean in (f"import {symbol}", f"import {symbol} as {symbol}"):
|
|
243
|
+
lines.pop(line_num - 1)
|
|
244
|
+
return "".join(lines)
|
|
245
|
+
from_match = re.match(r"^from\s+[\w\.]+\s+import\s+(.+)$", clean)
|
|
246
|
+
if from_match:
|
|
247
|
+
imported_items = [i.strip() for i in from_match.group(1).split(",") if i.strip()]
|
|
248
|
+
remaining = [i for i in imported_items if i != symbol and not i.endswith(f" as {symbol}")]
|
|
249
|
+
if not remaining:
|
|
250
|
+
lines.pop(line_num - 1)
|
|
251
|
+
else:
|
|
252
|
+
module_part = clean.split("import")[0]
|
|
253
|
+
indent = len(target_line) - len(target_line.lstrip())
|
|
254
|
+
new_line = " " * indent + module_part + "import " + ", ".join(remaining) + "\n"
|
|
255
|
+
lines[line_num - 1] = new_line
|
|
256
|
+
return "".join(lines)
|
|
257
|
+
# Fallback: remove full line if symbol is found in it
|
|
258
|
+
if symbol in clean:
|
|
259
|
+
lines.pop(line_num - 1)
|
|
260
|
+
return "".join(lines)
|
|
261
|
+
|
|
262
|
+
elif code == "E0602" and symbol:
|
|
263
|
+
# Undefined name: auto-insert import if recognized
|
|
264
|
+
fix_stmt = KNOWN_IMPORTS.get(symbol)
|
|
265
|
+
if fix_stmt:
|
|
266
|
+
# Find best insertion point (after module docstring and future imports)
|
|
267
|
+
insert_idx = 0
|
|
268
|
+
for idx, line in enumerate(lines):
|
|
269
|
+
s = line.strip()
|
|
270
|
+
if s.startswith('"""') or s.startswith("'''"):
|
|
271
|
+
# docstring handling
|
|
272
|
+
continue
|
|
273
|
+
if s.startswith("from __future__"):
|
|
274
|
+
insert_idx = idx + 1
|
|
275
|
+
elif s.startswith("import ") or s.startswith("from "):
|
|
276
|
+
insert_idx = idx
|
|
277
|
+
break
|
|
278
|
+
elif s and not s.startswith("#"):
|
|
279
|
+
insert_idx = idx
|
|
280
|
+
break
|
|
281
|
+
|
|
282
|
+
lines.insert(insert_idx, fix_stmt + "\n")
|
|
283
|
+
return "".join(lines)
|
|
284
|
+
|
|
285
|
+
elif code == "W0702":
|
|
286
|
+
# Bare except fix
|
|
287
|
+
if 1 <= line_num <= len(lines):
|
|
288
|
+
target_line = lines[line_num - 1]
|
|
289
|
+
if "except:" in target_line:
|
|
290
|
+
lines[line_num - 1] = target_line.replace("except:", "except Exception:", 1)
|
|
291
|
+
return "".join(lines)
|
|
292
|
+
|
|
293
|
+
return source_code
|
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
"""Coder Fleet Dispatcher for Unified Routing to All 10 Coder Subagent Engines.
|
|
2
|
+
|
|
3
|
+
Provides centralized dispatch(action, params) mapping with error containment,
|
|
4
|
+
telemetry, and action discovery.
|
|
5
|
+
"""
|
|
6
|
+
from __future__ import annotations
|
|
7
|
+
|
|
8
|
+
import inspect
|
|
9
|
+
from typing import Any, Callable
|
|
10
|
+
|
|
11
|
+
from ..cortical import HebbianPlasticityEngine
|
|
12
|
+
from .ast_tools import TreeSitterCodemodEngine
|
|
13
|
+
from .compute import ComputeOrchestratorEngine
|
|
14
|
+
from .design_engine import DesignEngine
|
|
15
|
+
from .diagnostics import DiagnosticsEngine
|
|
16
|
+
from .mock_auditor import MockAuditorEngine
|
|
17
|
+
from .mutation import MutationVerifierEngine
|
|
18
|
+
from .property_oracle import PropertyOracleEngine
|
|
19
|
+
from .receipt_attestor import ReceiptAttestorEngine
|
|
20
|
+
from .red_team_swarm import RedTeamSwarm
|
|
21
|
+
from .test_harness import TestHarnessEngine
|
|
22
|
+
from .vector_engine import FableVectorCompiler, VLayoutSolver, VNode
|
|
23
|
+
from .visual import VisualGroundingEngine
|
|
24
|
+
from .workspace import AtomicWorkspaceEngine
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
class CoderFleetDispatcher:
|
|
28
|
+
"""Unified dispatcher for the 10-Tool Coder Subagent MCP Fleet, Cortical Engine, and Design Engine."""
|
|
29
|
+
|
|
30
|
+
def __init__(
|
|
31
|
+
self,
|
|
32
|
+
visual: VisualGroundingEngine | None = None,
|
|
33
|
+
diagnostics: DiagnosticsEngine | None = None,
|
|
34
|
+
ast_tools: TreeSitterCodemodEngine | None = None,
|
|
35
|
+
workspace: AtomicWorkspaceEngine | None = None,
|
|
36
|
+
test_harness: TestHarnessEngine | None = None,
|
|
37
|
+
mutation: MutationVerifierEngine | None = None,
|
|
38
|
+
mock_auditor: MockAuditorEngine | None = None,
|
|
39
|
+
property_oracle: PropertyOracleEngine | None = None,
|
|
40
|
+
receipt_attestor: ReceiptAttestorEngine | None = None,
|
|
41
|
+
compute: ComputeOrchestratorEngine | None = None,
|
|
42
|
+
red_team_swarm: RedTeamSwarm | None = None,
|
|
43
|
+
plasticity_engine: HebbianPlasticityEngine | None = None,
|
|
44
|
+
vector_compiler: FableVectorCompiler | None = None,
|
|
45
|
+
layout_solver: VLayoutSolver | None = None,
|
|
46
|
+
design_engine: DesignEngine | None = None,
|
|
47
|
+
) -> None:
|
|
48
|
+
self.visual = visual or VisualGroundingEngine()
|
|
49
|
+
self.diagnostics = diagnostics or DiagnosticsEngine()
|
|
50
|
+
self.ast_tools = ast_tools or TreeSitterCodemodEngine()
|
|
51
|
+
self.workspace = workspace or AtomicWorkspaceEngine()
|
|
52
|
+
self.test_harness = test_harness or TestHarnessEngine()
|
|
53
|
+
self.mutation = mutation or MutationVerifierEngine(test_harness=self.test_harness)
|
|
54
|
+
self.mock_auditor = mock_auditor or MockAuditorEngine()
|
|
55
|
+
self.property_oracle = property_oracle or PropertyOracleEngine(test_harness=self.test_harness)
|
|
56
|
+
self.receipt_attestor = receipt_attestor or ReceiptAttestorEngine()
|
|
57
|
+
self.compute = compute or ComputeOrchestratorEngine()
|
|
58
|
+
self.plasticity_engine = plasticity_engine or HebbianPlasticityEngine()
|
|
59
|
+
self.vector_compiler = vector_compiler or FableVectorCompiler()
|
|
60
|
+
self.layout_solver = layout_solver or VLayoutSolver()
|
|
61
|
+
self.design_engine = design_engine or DesignEngine()
|
|
62
|
+
self.red_team_swarm = red_team_swarm or RedTeamSwarm(
|
|
63
|
+
test_harness=self.test_harness,
|
|
64
|
+
mock_auditor=self.mock_auditor,
|
|
65
|
+
property_oracle=self.property_oracle,
|
|
66
|
+
plasticity_engine=self.plasticity_engine,
|
|
67
|
+
)
|
|
68
|
+
|
|
69
|
+
self._actions: dict[str, Callable[..., Any]] = {
|
|
70
|
+
# 1. Visual Grounding Engine
|
|
71
|
+
"render_vector": self.visual.render_vector,
|
|
72
|
+
"perceptual_diff": self.visual.perceptual_diff,
|
|
73
|
+
"extract_palette_and_boxes": self.visual.extract_palette_and_boxes,
|
|
74
|
+
# 2. Diagnostics Engine
|
|
75
|
+
"run_diagnostics": self.diagnostics.run_diagnostics,
|
|
76
|
+
"apply_quick_fix": self.diagnostics.apply_quick_fix,
|
|
77
|
+
# 3. TreeSitter / AST Codemod Engine
|
|
78
|
+
"query_ast": self.ast_tools.query_ast,
|
|
79
|
+
"rename_symbol": self.ast_tools.rename_symbol,
|
|
80
|
+
"verify_syntax": self.ast_tools.verify_syntax,
|
|
81
|
+
# 4. Atomic Workspace Engine
|
|
82
|
+
"create_checkpoint": self.workspace.create_checkpoint,
|
|
83
|
+
"inspect_patch": self.workspace.inspect_patch,
|
|
84
|
+
"rollback": self.workspace.rollback,
|
|
85
|
+
"commit_milestone": self.workspace.commit_milestone,
|
|
86
|
+
# 5. Test Harness Engine
|
|
87
|
+
"run_scratch_test": self.test_harness.run_scratch_test,
|
|
88
|
+
"concurrency_fuzz": self.test_harness.concurrency_fuzz,
|
|
89
|
+
"profile_memory_and_cpu": self.test_harness.profile_memory_and_cpu,
|
|
90
|
+
# 6. Mutation Verifier Engine
|
|
91
|
+
"inject_mutants": self.mutation.inject_mutants,
|
|
92
|
+
"audit_test_strength": self.mutation.audit_test_strength,
|
|
93
|
+
# 7. Mock Auditor Engine
|
|
94
|
+
"audit_assertions": self.mock_auditor.audit_assertions,
|
|
95
|
+
"detect_mock_leakage": self.mock_auditor.detect_mock_leakage,
|
|
96
|
+
"enforce_negative_paths": self.mock_auditor.enforce_negative_paths,
|
|
97
|
+
# 8. Property Oracle Engine
|
|
98
|
+
"generate_property_matrix": self.property_oracle.generate_property_matrix,
|
|
99
|
+
"verify_algebraic_invariants": self.property_oracle.verify_algebraic_invariants,
|
|
100
|
+
# 9. Receipt Attestor Engine
|
|
101
|
+
"attest_execution": self.receipt_attestor.attest_execution,
|
|
102
|
+
"verify_receipt": self.receipt_attestor.verify_receipt,
|
|
103
|
+
# 10. Compute Orchestrator Engine
|
|
104
|
+
"calculate_thinking_budget": self.compute.calculate_thinking_budget,
|
|
105
|
+
"mcts_explore": self.compute.mcts_explore,
|
|
106
|
+
"best_of_n_consensus": self.compute.best_of_n_consensus,
|
|
107
|
+
# 11. Red Team Swarm Engine (Modular Fable Part 1: Adversarial Code Review)
|
|
108
|
+
"red_team_generate_scenarios": self.red_team_swarm.generate_break_scenarios,
|
|
109
|
+
"red_team_execute_attack": self.red_team_swarm.execute_swarm_attack,
|
|
110
|
+
"red_team_document_breakage": self.red_team_swarm.document_breakage,
|
|
111
|
+
"red_team_verify_remediation": self.red_team_swarm.verify_remediation,
|
|
112
|
+
"red_team_full_review_cycle": self.red_team_swarm.run_full_review_cycle,
|
|
113
|
+
"red_team_code_review": self.red_team_swarm.run_full_review_cycle,
|
|
114
|
+
"record_breakage_report": self.red_team_swarm.document_breakage,
|
|
115
|
+
"verify_red_team_remediation": self.red_team_swarm.verify_remediation,
|
|
116
|
+
# 12. Cortical Plasticity Engine (Modular Fable Part 2: Hebbian Learning & Domain Lobes)
|
|
117
|
+
"cortical_define_lobe": self.plasticity_engine.define_cortical_lobe,
|
|
118
|
+
"cortical_list_lobes": self.plasticity_engine.list_cortical_lobes,
|
|
119
|
+
"cortical_activate_lobe": self.plasticity_engine.activate_lobe,
|
|
120
|
+
"cortical_consolidate_task": self.plasticity_engine.consolidate_task,
|
|
121
|
+
"cortical_recall_context": self.plasticity_engine.recall_cortical_context,
|
|
122
|
+
"cortical_inspect_matrix": self.plasticity_engine.get_synaptic_matrix,
|
|
123
|
+
"evolve_cortex": self.plasticity_engine.consolidate_task,
|
|
124
|
+
# 13. Fable-Vector Neuro-Symbolic Vector Engine
|
|
125
|
+
"compile_vector": self.compile_vector,
|
|
126
|
+
"solve_layout": self.solve_layout,
|
|
127
|
+
# 14. Anti-Slop Frontend & Design Taste Engine
|
|
128
|
+
"audit_anti_slop": self.design_engine.audit_anti_slop,
|
|
129
|
+
"infer_design_brief": self.design_engine.infer_design_brief,
|
|
130
|
+
"generate_design_tokens": self.design_engine.generate_design_tokens,
|
|
131
|
+
"generate_awwwards_scaffold": self.design_engine.generate_awwwards_scaffold,
|
|
132
|
+
"validate_preflight_design": self.design_engine.validate_preflight_design,
|
|
133
|
+
"list_design_archetypes": self.design_engine.list_design_archetypes,
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
def list_actions(self) -> list[str]:
|
|
137
|
+
"""Return list of all registered action names."""
|
|
138
|
+
return sorted(self._actions.keys())
|
|
139
|
+
|
|
140
|
+
def dispatch(self, action: str, params: dict[str, Any] | None = None) -> dict[str, Any]:
|
|
141
|
+
"""Dispatch an action with parameter dictionary to the corresponding fleet engine."""
|
|
142
|
+
if action not in self._actions:
|
|
143
|
+
return {
|
|
144
|
+
"success": False,
|
|
145
|
+
"action": action,
|
|
146
|
+
"error": f"Unknown fleet action '{action}'. Available actions: {', '.join(self.list_actions())}",
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
target_fn = self._actions[action]
|
|
150
|
+
kwargs = dict(params or {})
|
|
151
|
+
|
|
152
|
+
try:
|
|
153
|
+
sig = inspect.signature(target_fn)
|
|
154
|
+
# Filter kwargs to only accepted parameters if not accepting **kwargs
|
|
155
|
+
has_var_keyword = any(p.kind == inspect.Parameter.VAR_KEYWORD for p in sig.parameters.values())
|
|
156
|
+
if not has_var_keyword:
|
|
157
|
+
valid_params = set(sig.parameters.keys())
|
|
158
|
+
filtered_kwargs = {k: v for k, v in kwargs.items() if k in valid_params}
|
|
159
|
+
else:
|
|
160
|
+
filtered_kwargs = kwargs
|
|
161
|
+
|
|
162
|
+
result = target_fn(**filtered_kwargs)
|
|
163
|
+
return {
|
|
164
|
+
"success": True,
|
|
165
|
+
"action": action,
|
|
166
|
+
"result": result,
|
|
167
|
+
}
|
|
168
|
+
except TypeError as type_err:
|
|
169
|
+
return {
|
|
170
|
+
"success": False,
|
|
171
|
+
"action": action,
|
|
172
|
+
"error": f"Invalid arguments for action '{action}': {type_err}",
|
|
173
|
+
}
|
|
174
|
+
except Exception as exc:
|
|
175
|
+
return {
|
|
176
|
+
"success": False,
|
|
177
|
+
"action": action,
|
|
178
|
+
"error": f"Execution error in action '{action}': {exc}",
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
def compile_vector(
|
|
182
|
+
self,
|
|
183
|
+
node: VNode | dict[str, Any] | None = None,
|
|
184
|
+
tree: VNode | dict[str, Any] | None = None,
|
|
185
|
+
root: VNode | dict[str, Any] | None = None,
|
|
186
|
+
options: dict[str, Any] | None = None,
|
|
187
|
+
) -> dict[str, Any]:
|
|
188
|
+
"""Compile a VNode tree or dictionary definition into production SVG."""
|
|
189
|
+
target = node if node is not None else (tree if tree is not None else root)
|
|
190
|
+
if target is None:
|
|
191
|
+
raise ValueError("No node, tree, or root provided to compile_vector")
|
|
192
|
+
svg_code = self.vector_compiler.compile(target, options=options)
|
|
193
|
+
return {
|
|
194
|
+
"svg": svg_code,
|
|
195
|
+
"valid": True,
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
def solve_layout(
|
|
199
|
+
self,
|
|
200
|
+
root: VNode | dict[str, Any] | None = None,
|
|
201
|
+
node: VNode | dict[str, Any] | None = None,
|
|
202
|
+
tree: VNode | dict[str, Any] | None = None,
|
|
203
|
+
viewport_width: float = 1920.0,
|
|
204
|
+
viewport_height: float = 1080.0,
|
|
205
|
+
) -> dict[str, Any]:
|
|
206
|
+
"""Solve layout constraints and return computed coordinates and bounding boxes."""
|
|
207
|
+
target = root if root is not None else (node if node is not None else tree)
|
|
208
|
+
if target is None:
|
|
209
|
+
raise ValueError("No root, node, or tree provided to solve_layout")
|
|
210
|
+
return self.layout_solver.solve_layout(
|
|
211
|
+
target,
|
|
212
|
+
viewport_width=viewport_width,
|
|
213
|
+
viewport_height=viewport_height,
|
|
214
|
+
)
|