csc-engine / src /gate.py
josephrw's picture
Upload folder using huggingface_hub
fc56cab verified
Raw
History Blame Contribute Delete
12.5 kB
"""
Builder Gate and Evidence Gate for CSC Engine.
Builder Gate: validates code before execution β€” syntax, prose detection, import check.
Evidence Gate: validates that sufficient intent exists before task-specific code generation.
"""
import ast
import sys
import pkgutil
import re
from dataclasses import dataclass, field
# ─── Installed package cache ───
_installed_packages: set[str] | None = None
def _get_installed_packages() -> set[str]:
global _installed_packages
if _installed_packages is None:
_installed_packages = set()
for m in pkgutil.iter_modules():
_installed_packages.add(m.name)
# Add common stdlib modules that might not show up in iter_modules
_installed_packages.update(sys.stdlib_module_names)
# Add common aliases (only packages actually installed)
_installed_packages.update({"PIL", "Pillow"})
return _installed_packages
# ─── Builder Gate ───
@dataclass
class GateResult:
passed: bool
reason: str
code_extracted: str = ""
checks: list[dict] = field(default_factory=list)
def builder_gate(code: str) -> GateResult:
"""Validate code before execution.
Checks:
1. Syntax validation β€” must parse as valid Python (also catches prose)
2. Import validation β€” all imports must be from installed packages
3. Noninteractive check β€” reject input() calls and interactive patterns
"""
checks = []
code = code.strip() if code else ""
# Check 1: Empty
if not code:
return GateResult(passed=False, reason="No code provided", checks=[{"check": "empty", "passed": False}])
# Check 2: Syntax validation (this also catches prose β€” prose won't parse as Python)
try:
ast.parse(code)
except SyntaxError as e:
# If syntax fails, check if it's prose vs actual code error
python_indicators = [
r'\bdef\b', r'\bclass\b', r'\bimport\b', r'\bfrom\b', r'\bif\b', r'\bfor\b',
r'\bwhile\b', r'\breturn\b', r'\bprint\s*\(', r'\bassert\b', r'\bwith\b',
r'\btry\b', r'\bexcept\b', r'\braise\b', r'\byield\b', r'\blambda\b',
]
indicator_count = sum(1 for p in python_indicators if re.search(p, code))
if indicator_count == 0:
checks.append({"check": "prose_detection", "passed": False,
"detail": "No Python indicators found β€” likely prose, not code"})
return GateResult(passed=False, reason="Code looks like prose, not executable Python",
checks=checks)
checks.append({"check": "syntax", "passed": False, "detail": f"SyntaxError: {e.msg} (line {e.lineno})"})
return GateResult(passed=False, reason=f"Syntax error: {e.msg} at line {e.lineno}",
checks=checks)
checks.append({"check": "syntax", "passed": True})
# Check 4: Import validation
tree = ast.parse(code)
imports = []
for node in ast.walk(tree):
if isinstance(node, ast.Import):
for alias in node.names:
imports.append(alias.name.split('.')[0])
elif isinstance(node, ast.ImportFrom):
if node.module:
imports.append(node.module.split('.')[0])
installed = _get_installed_packages()
missing = [imp for imp in imports if imp not in installed and imp != "__future__"]
if missing:
checks.append({"check": "imports", "passed": False,
"detail": f"Missing packages: {', '.join(missing)}"})
return GateResult(passed=False, reason=f"Missing dependencies: {', '.join(missing)}. Install them or use only available packages.",
checks=checks)
checks.append({"check": "imports", "passed": True, "detail": f"{len(imports)} imports validated"})
# Check 5: Noninteractive check
interactive_patterns = [r'\binput\s*\(', r'\braw_input\s*\(', r'\bgetpass\s*\(']
for pattern in interactive_patterns:
if re.search(pattern, code):
checks.append({"check": "noninteractive", "passed": False,
"detail": f"Interactive call detected: {pattern}"})
return GateResult(passed=False, reason="Code contains interactive input β€” not allowed in sandboxed execution",
checks=checks)
checks.append({"check": "noninteractive", "passed": True})
return GateResult(passed=True, reason="All gate checks passed", code_extracted=code, checks=checks)
# ─── Evidence Gate ───
@dataclass
class EvidenceGateResult:
passed: bool
reason: str
evidence_type: str = ""
intent_sources: list[str] = field(default_factory=list)
fallback_level: int = 0
artifact_type: str = ""
sensory_channels: list[str] = field(default_factory=list)
feature_attribution: dict = field(default_factory=dict)
def evidence_gate(observer_output: str, state_dict: dict) -> EvidenceGateResult:
"""Sensory Proprietary Compiler V1 β€” Fallback Ladder.
NEVER returns zero artifact. Every sensory input produces something useful.
Fallback levels:
1. Explicit intent β†’ task code
2. Weak intent + rich sensory β†’ instrumentation code
3. Distinctive sensory features β†’ aesthetic/system motifs
4. Background audio only β†’ topic-to-tool associations
5. Minimal signal β†’ capture protocol improvement
"""
obs = (observer_output or "").lower()
# Gather intent sources
intent_sources = []
sensory_channels = []
feature_attribution = {}
# Check for user speech / transcript
speakers = state_dict.get("speakers", {})
user_transcript = speakers.get("user", {}).get("transcript", "")
if user_transcript and user_transcript.strip():
intent_sources.append("user_speech")
sensory_channels.append("user_voice")
feature_attribution["user_speech"] = user_transcript[:200]
# Check for any audio chunks with content
audio_chunks = state_dict.get("audio", {}).get("chunks", [])
has_audio_content = any(c.get("transcript", "").strip() for c in audio_chunks if isinstance(c, dict))
if has_audio_content:
intent_sources.append("audio_transcript")
sensory_channels.append("audio")
# Check for background speakers (TV, other people)
for spk, info in speakers.items():
if spk != "user" and info.get("transcript", "").strip():
sensory_channels.append(f"background_voice:{spk}")
feature_attribution[f"background_{spk}"] = info["transcript"][:200]
# Check for visible screen text / code in observer output
screen_indicators = ["screen", "code on", "text on", "monitor", "display", "laptop", "ide", "editor", "terminal"]
has_screen_evidence = any(s in obs for s in screen_indicators)
if has_screen_evidence:
intent_sources.append("visible_screen")
sensory_channels.append("screen")
# Check for explicit typed intent / prior goal
if "goal" in obs or "intent" in obs or "task" in obs or "want" in obs:
intent_sources.append("explicit_intent")
# Check for camera sensory features
camera_indicators = ["face", "person", "movement", "object", "light", "wall", "fabric", "hand", "gesture",
"hair", "color", "purple", "brown", "breathing", "motion", "room"]
has_camera_evidence = any(s in obs for s in camera_indicators)
if has_camera_evidence:
sensory_channels.append("camera")
# Extract specific features
for indicator in camera_indicators:
if indicator in obs:
feature_attribution[f"visual_{indicator}"] = True
# Check motion score
motion_score = state_dict.get("motion_score", 0.0)
if motion_score > 0.01:
sensory_channels.append("motion")
feature_attribution["motion_score"] = round(motion_score, 4)
# Check frame count (camera active)
visual = state_dict.get("visual", {})
frame_count = visual.get("frame_count", 0)
if frame_count > 0:
sensory_channels.append("frames")
feature_attribution["frame_count"] = frame_count
feature_attribution["avg_entropy"] = visual.get("avg_entropy", 0)
feature_attribution["avg_motion"] = visual.get("avg_motion", 0)
# Check audio chunk count
audio_chunk_count = state_dict.get("audio", {}).get("chunk_count", 0)
if audio_chunk_count > 0:
feature_attribution["audio_chunks"] = audio_chunk_count
# ─── Fallback Ladder ───
# Level 1: Explicit intent β†’ task code
if intent_sources:
return EvidenceGateResult(
passed=True,
reason=f"Level 1: Explicit intent detected. Sources: {', '.join(intent_sources)}",
evidence_type="sufficient_intent",
intent_sources=intent_sources,
fallback_level=1,
artifact_type="task_code",
sensory_channels=sensory_channels,
feature_attribution=feature_attribution,
)
# Level 2: Weak intent but rich sensory features β†’ instrumentation code
if has_camera_evidence and (len(sensory_channels) >= 2 or motion_score > 0.05):
return EvidenceGateResult(
passed=True,
reason=f"Level 2: Rich sensory evidence ({', '.join(sensory_channels)}). Generating instrumentation code.",
evidence_type="sensory_rich",
intent_sources=[],
fallback_level=2,
artifact_type="instrumentation_code",
sensory_channels=sensory_channels,
feature_attribution=feature_attribution,
)
# Level 3: Distinctive sensory features β†’ aesthetic/system motifs
if has_camera_evidence or frame_count > 0:
return EvidenceGateResult(
passed=True,
reason=f"Level 3: Distinctive sensory features ({', '.join(sensory_channels)}). Generating motif/design artifact.",
evidence_type="sensory_distinctive",
intent_sources=[],
fallback_level=3,
artifact_type="aesthetic_motif",
sensory_channels=sensory_channels,
feature_attribution=feature_attribution,
)
# Level 4: Background audio only β†’ topic-to-tool associations
if audio_chunk_count > 0 or any("background_voice" in ch for ch in sensory_channels):
return EvidenceGateResult(
passed=True,
reason="Level 4: Audio evidence only. Generating topic-to-tool association artifact.",
evidence_type="audio_only",
intent_sources=[],
fallback_level=4,
artifact_type="topic_association",
sensory_channels=sensory_channels,
feature_attribution=feature_attribution,
)
# Level 5: Minimal signal β†’ capture protocol improvement
return EvidenceGateResult(
passed=True,
reason="Level 5: Minimal sensory signal. Generating capture protocol improvement artifact.",
evidence_type="minimal_signal",
intent_sources=[],
fallback_level=5,
artifact_type="capture_protocol",
sensory_channels=sensory_channels,
feature_attribution=feature_attribution,
)
# ─── Gate log for audit ───
_gate_log: list[dict] = []
def log_gate_decision(gate_type: str, result, patch_hash: str = "", code_preview: str = ""):
"""Record gate decision for audit trail."""
entry = {
"gate_type": gate_type,
"passed": result.passed,
"reason": result.reason,
"timestamp": __import__("time").time(),
"patch_hash": patch_hash,
"code_preview": code_preview[:200] if code_preview else "",
}
if hasattr(result, "checks"):
entry["checks"] = result.checks
if hasattr(result, "evidence_type"):
entry["evidence_type"] = result.evidence_type
entry["intent_sources"] = result.intent_sources
if hasattr(result, "fallback_level"):
entry["fallback_level"] = result.fallback_level
entry["artifact_type"] = result.artifact_type
entry["sensory_channels"] = result.sensory_channels
entry["feature_attribution"] = result.feature_attribution
_gate_log.append(entry)
if len(_gate_log) > 100:
_gate_log.pop(0)
def get_gate_log() -> list[dict]:
return list(_gate_log)