Spaces:
Paused
Paused
Upload folder using huggingface_hub
Browse files- app.py +21 -30
- src/builder_llm.py +58 -12
- src/gate.py +113 -21
app.py
CHANGED
|
@@ -217,18 +217,12 @@ async def generate_patch(request: Request):
|
|
| 217 |
state = sessions[session_id]
|
| 218 |
compact = compress_state(state)
|
| 219 |
|
| 220 |
-
# βββ Evidence Gate:
|
|
|
|
| 221 |
ev_result = evidence_gate("", compact)
|
| 222 |
log_gate_decision("evidence_gate", ev_result, patch_hash="")
|
| 223 |
-
if not ev_result.passed:
|
| 224 |
-
return JSONResponse({
|
| 225 |
-
"error": "Code generation blocked by Evidence Gate",
|
| 226 |
-
"gate_reason": ev_result.reason,
|
| 227 |
-
"evidence_type": ev_result.evidence_type,
|
| 228 |
-
"intent_sources": ev_result.intent_sources,
|
| 229 |
-
"observer_output": "",
|
| 230 |
-
}, 403)
|
| 231 |
|
|
|
|
| 232 |
observation = observe(state, compact)
|
| 233 |
state.observer_state = observation
|
| 234 |
state.last_observer_ts = time.time()
|
|
@@ -236,16 +230,9 @@ async def generate_patch(request: Request):
|
|
| 236 |
# Re-check Evidence Gate with observer output now available
|
| 237 |
ev_result2 = evidence_gate(observation.get("observer_output", ""), compact)
|
| 238 |
log_gate_decision("evidence_gate", ev_result2, patch_hash="")
|
| 239 |
-
|
| 240 |
-
|
| 241 |
-
|
| 242 |
-
"gate_reason": ev_result2.reason,
|
| 243 |
-
"evidence_type": ev_result2.evidence_type,
|
| 244 |
-
"intent_sources": ev_result2.intent_sources,
|
| 245 |
-
"observer_output": observation.get("observer_output", ""),
|
| 246 |
-
}, 403)
|
| 247 |
-
|
| 248 |
-
result = build(state, observation)
|
| 249 |
state.current_artifact = result["patch_output"]
|
| 250 |
state.last_patch_hash = result["patch_hash"]
|
| 251 |
state.last_builder_ts = time.time()
|
|
@@ -253,17 +240,8 @@ async def generate_patch(request: Request):
|
|
| 253 |
|
| 254 |
save_receipt(result["receipt"])
|
| 255 |
|
| 256 |
-
# Check if builder returned INSUFFICIENT_EVIDENCE
|
| 257 |
-
patch_output = result["patch_output"]
|
| 258 |
-
if "INSUFFICIENT_EVIDENCE" in patch_output:
|
| 259 |
-
return {
|
| 260 |
-
"patch_output": patch_output,
|
| 261 |
-
"patch_hash": result["patch_hash"],
|
| 262 |
-
"receipt": result["receipt"],
|
| 263 |
-
"insufficient_evidence": True,
|
| 264 |
-
}
|
| 265 |
-
|
| 266 |
# Auto-store artifact so patch_hash can be resolved and executed
|
|
|
|
| 267 |
extracted_code = extract_code_from_output(patch_output)
|
| 268 |
if not extracted_code:
|
| 269 |
extracted_code = patch_output # fallback: store raw output as code
|
|
@@ -273,11 +251,24 @@ async def generate_patch(request: Request):
|
|
| 273 |
"observer_output": patch_output,
|
| 274 |
"timestamp": time.time(),
|
| 275 |
"session_id": session_id,
|
|
|
|
|
|
|
|
|
|
|
|
|
| 276 |
}
|
| 277 |
artifact_store[result["patch_hash"]] = artifact_data
|
| 278 |
save_artifact_disk(result["patch_hash"], artifact_data)
|
| 279 |
|
| 280 |
-
return
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 281 |
|
| 282 |
|
| 283 |
# In-memory artifact store: patch_hash -> {code, output, timestamp}
|
|
|
|
| 217 |
state = sessions[session_id]
|
| 218 |
compact = compress_state(state)
|
| 219 |
|
| 220 |
+
# βββ Evidence Gate: Sensory Proprietary Compiler V1 β Fallback Ladder βββ
|
| 221 |
+
# Gate NEVER blocks. It assigns a fallback level (1-5) and artifact_type.
|
| 222 |
ev_result = evidence_gate("", compact)
|
| 223 |
log_gate_decision("evidence_gate", ev_result, patch_hash="")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 224 |
|
| 225 |
+
# Observe with the gate result β observer gets context about what level we're at
|
| 226 |
observation = observe(state, compact)
|
| 227 |
state.observer_state = observation
|
| 228 |
state.last_observer_ts = time.time()
|
|
|
|
| 230 |
# Re-check Evidence Gate with observer output now available
|
| 231 |
ev_result2 = evidence_gate(observation.get("observer_output", ""), compact)
|
| 232 |
log_gate_decision("evidence_gate", ev_result2, patch_hash="")
|
| 233 |
+
|
| 234 |
+
# Build with fallback level β always produces an artifact
|
| 235 |
+
result = build(state, observation, gate_result=ev_result2)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 236 |
state.current_artifact = result["patch_output"]
|
| 237 |
state.last_patch_hash = result["patch_hash"]
|
| 238 |
state.last_builder_ts = time.time()
|
|
|
|
| 240 |
|
| 241 |
save_receipt(result["receipt"])
|
| 242 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 243 |
# Auto-store artifact so patch_hash can be resolved and executed
|
| 244 |
+
patch_output = result["patch_output"]
|
| 245 |
extracted_code = extract_code_from_output(patch_output)
|
| 246 |
if not extracted_code:
|
| 247 |
extracted_code = patch_output # fallback: store raw output as code
|
|
|
|
| 251 |
"observer_output": patch_output,
|
| 252 |
"timestamp": time.time(),
|
| 253 |
"session_id": session_id,
|
| 254 |
+
"fallback_level": result.get("fallback_level", 0),
|
| 255 |
+
"artifact_type": result.get("artifact_type", ""),
|
| 256 |
+
"sensory_channels": ev_result2.sensory_channels,
|
| 257 |
+
"feature_attribution": ev_result2.feature_attribution,
|
| 258 |
}
|
| 259 |
artifact_store[result["patch_hash"]] = artifact_data
|
| 260 |
save_artifact_disk(result["patch_hash"], artifact_data)
|
| 261 |
|
| 262 |
+
return {
|
| 263 |
+
**result,
|
| 264 |
+
"gate": {
|
| 265 |
+
"fallback_level": ev_result2.fallback_level,
|
| 266 |
+
"artifact_type": ev_result2.artifact_type,
|
| 267 |
+
"sensory_channels": ev_result2.sensory_channels,
|
| 268 |
+
"feature_attribution": ev_result2.feature_attribution,
|
| 269 |
+
"reason": ev_result2.reason,
|
| 270 |
+
},
|
| 271 |
+
}
|
| 272 |
|
| 273 |
|
| 274 |
# In-memory artifact store: patch_hash -> {code, output, timestamp}
|
src/builder_llm.py
CHANGED
|
@@ -12,26 +12,53 @@ import requests
|
|
| 12 |
from .stream_state import SessionState, sha256_text
|
| 13 |
|
| 14 |
|
| 15 |
-
BUILDER_PROMPT = """You are the Builder in a Continuity Sensory Code Engine.
|
| 16 |
|
| 17 |
-
You receive an observation from the Observer LLM and
|
| 18 |
|
| 19 |
CRITICAL RULES β VIOLATION = REJECTION:
|
| 20 |
1. The CODE section MUST contain ONLY valid, executable Python code.
|
| 21 |
2. Do NOT put prose, explanations, or English text in the CODE section.
|
| 22 |
3. Do NOT put code in the EVIDENCE or REASONING sections.
|
| 23 |
-
4. All imports MUST be from packages available in the environment: fastapi, uvicorn, pillow, numpy, requests, openai, huggingface_hub, python-multipart, and Python stdlib (os, sys, json, math, re, collections, datetime, etc.).
|
| 24 |
5. Do NOT import cv2, torch, tensorflow, pandas, matplotlib, scipy, sklearn, or any package not listed above.
|
| 25 |
6. Do NOT use input() or any interactive call β code must run non-interactively.
|
| 26 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 27 |
|
| 28 |
Output format (use exactly these headers):
|
| 29 |
|
| 30 |
EVIDENCE:
|
| 31 |
-
- List specific sensory evidence from the observation.
|
| 32 |
|
| 33 |
REASONING:
|
| 34 |
-
- Step by step: why this
|
| 35 |
|
| 36 |
CODE:
|
| 37 |
```python
|
|
@@ -46,10 +73,7 @@ TEST:
|
|
| 46 |
- Minimal verification step.
|
| 47 |
|
| 48 |
ATTRIBUTION:
|
| 49 |
-
- Which sensory evidence (frame hashes, audio segments, motion scores) triggered this code.
|
| 50 |
-
|
| 51 |
-
If evidence is insufficient, output:
|
| 52 |
-
INSUFFICIENT_EVIDENCE: [explanation of what's missing]
|
| 53 |
"""
|
| 54 |
|
| 55 |
|
|
@@ -106,11 +130,22 @@ def call_hf_inference(prompt: str) -> str:
|
|
| 106 |
return response.choices[0].message.content
|
| 107 |
|
| 108 |
|
| 109 |
-
def build(state: SessionState, observation: dict) -> dict:
|
| 110 |
"""Run builder LLM on observer output.
|
| 111 |
|
| 112 |
Returns code patch with attribution receipt.
|
|
|
|
| 113 |
"""
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 114 |
prompt = f"""{BUILDER_PROMPT}
|
| 115 |
|
| 116 |
OBSERVER OUTPUT:
|
|
@@ -118,7 +153,12 @@ OBSERVER OUTPUT:
|
|
| 118 |
|
| 119 |
MODE: {state.mode}
|
| 120 |
|
| 121 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 122 |
|
| 123 |
provider = os.getenv("PROVIDER", "groq").lower().strip()
|
| 124 |
if provider == "ollama":
|
|
@@ -151,12 +191,18 @@ The observer has inferred the intent from camera + audio. Generate code based on
|
|
| 151 |
"uncertainty": _extract_uncertainty(observation),
|
| 152 |
"mode": state.mode,
|
| 153 |
"provider": provider,
|
|
|
|
|
|
|
|
|
|
|
|
|
| 154 |
}
|
| 155 |
|
| 156 |
return {
|
| 157 |
"patch_output": output,
|
| 158 |
"patch_hash": patch_hash,
|
| 159 |
"receipt": receipt,
|
|
|
|
|
|
|
| 160 |
}
|
| 161 |
|
| 162 |
|
|
|
|
| 12 |
from .stream_state import SessionState, sha256_text
|
| 13 |
|
| 14 |
|
| 15 |
+
BUILDER_PROMPT = """You are the Builder in a Continuity Sensory Code Engine β Sensory Proprietary Compiler V1.
|
| 16 |
|
| 17 |
+
You receive an observation from the Observer LLM and a FALLBACK LEVEL. You MUST produce a structured artifact. NEVER return empty. NEVER return INSUFFICIENT_EVIDENCE.
|
| 18 |
|
| 19 |
CRITICAL RULES β VIOLATION = REJECTION:
|
| 20 |
1. The CODE section MUST contain ONLY valid, executable Python code.
|
| 21 |
2. Do NOT put prose, explanations, or English text in the CODE section.
|
| 22 |
3. Do NOT put code in the EVIDENCE or REASONING sections.
|
| 23 |
+
4. All imports MUST be from packages available in the environment: fastapi, uvicorn, pillow, numpy, requests, openai, huggingface_hub, python-multipart, and Python stdlib (os, sys, json, math, re, collections, datetime, hashlib, time, uuid, etc.).
|
| 24 |
5. Do NOT import cv2, torch, tensorflow, pandas, matplotlib, scipy, sklearn, or any package not listed above.
|
| 25 |
6. Do NOT use input() or any interactive call β code must run non-interactively.
|
| 26 |
+
|
| 27 |
+
FALLBACK LADDER β you are at the level indicated. Generate code appropriate to that level:
|
| 28 |
+
|
| 29 |
+
LEVEL 1 (task_code): Explicit user intent detected. Generate task-specific code that does what the user asked.
|
| 30 |
+
|
| 31 |
+
LEVEL 2 (instrumentation_code): No explicit intent, but rich sensory features (camera, motion, audio). Generate instrumentation code that:
|
| 32 |
+
- Captures and quantifies the sensory channels present (motion metrics, audio energy, frame entropy)
|
| 33 |
+
- Creates reusable measurement utilities
|
| 34 |
+
- Produces a feature vector or data structure from the sensory input
|
| 35 |
+
- Example: motion rhythm analyzer, audio energy spectrum, frame entropy tracker
|
| 36 |
+
|
| 37 |
+
LEVEL 3 (aesthetic_motif): Distinctive visual features but no clear intent. Generate code that:
|
| 38 |
+
- Extracts aesthetic features from described visual input (color palette, light patterns, composition)
|
| 39 |
+
- Creates a UI theme, color scheme, or visual motif from the sensory description
|
| 40 |
+
- Produces a design grammar or style specification
|
| 41 |
+
- Example: color palette generator from room description, UI theme from lighting conditions
|
| 42 |
+
|
| 43 |
+
LEVEL 4 (topic_association): Only background audio/speech detected. Generate code that:
|
| 44 |
+
- Maps detected topics to relevant tools or code patterns
|
| 45 |
+
- Creates a topic-to-tool association dictionary
|
| 46 |
+
- Generates a transcript summarizer or topic classifier
|
| 47 |
+
- Example: TV topic to code domain mapper, background speech topic extractor
|
| 48 |
+
|
| 49 |
+
LEVEL 5 (capture_protocol): Minimal sensory signal. Generate code that:
|
| 50 |
+
- Improves the capture protocol itself
|
| 51 |
+
- Creates a better sampling strategy or capture diagnostic
|
| 52 |
+
- Produces a session health check or capture quality report
|
| 53 |
+
- Example: adaptive frame rate calculator, audio sensitivity tuner, capture health monitor
|
| 54 |
|
| 55 |
Output format (use exactly these headers):
|
| 56 |
|
| 57 |
EVIDENCE:
|
| 58 |
+
- List specific sensory evidence from the observation. Include channel names and feature values.
|
| 59 |
|
| 60 |
REASONING:
|
| 61 |
+
- Step by step: why this artifact should exist. Connect sensory evidence to code decisions. Explain which fallback level triggered this.
|
| 62 |
|
| 63 |
CODE:
|
| 64 |
```python
|
|
|
|
| 73 |
- Minimal verification step.
|
| 74 |
|
| 75 |
ATTRIBUTION:
|
| 76 |
+
- Which sensory evidence (frame hashes, audio segments, motion scores, visual features) triggered this code. Be specific.
|
|
|
|
|
|
|
|
|
|
| 77 |
"""
|
| 78 |
|
| 79 |
|
|
|
|
| 130 |
return response.choices[0].message.content
|
| 131 |
|
| 132 |
|
| 133 |
+
def build(state: SessionState, observation: dict, gate_result=None) -> dict:
|
| 134 |
"""Run builder LLM on observer output.
|
| 135 |
|
| 136 |
Returns code patch with attribution receipt.
|
| 137 |
+
Now accepts gate_result with fallback_level and feature_attribution.
|
| 138 |
"""
|
| 139 |
+
fallback_level = 1
|
| 140 |
+
artifact_type = "task_code"
|
| 141 |
+
sensory_channels = []
|
| 142 |
+
feature_attribution = {}
|
| 143 |
+
if gate_result:
|
| 144 |
+
fallback_level = gate_result.fallback_level
|
| 145 |
+
artifact_type = gate_result.artifact_type
|
| 146 |
+
sensory_channels = gate_result.sensory_channels
|
| 147 |
+
feature_attribution = gate_result.feature_attribution
|
| 148 |
+
|
| 149 |
prompt = f"""{BUILDER_PROMPT}
|
| 150 |
|
| 151 |
OBSERVER OUTPUT:
|
|
|
|
| 153 |
|
| 154 |
MODE: {state.mode}
|
| 155 |
|
| 156 |
+
FALLBACK LEVEL: {fallback_level}
|
| 157 |
+
ARTIFACT TYPE: {artifact_type}
|
| 158 |
+
SENSORY CHANNELS: {', '.join(sensory_channels) if sensory_channels else 'none'}
|
| 159 |
+
FEATURE ATTRIBUTION: {json.dumps(feature_attribution, default=str)}
|
| 160 |
+
|
| 161 |
+
You are at FALLBACK LEVEL {fallback_level}. Generate {artifact_type} based on the available sensory evidence. NEVER return INSUFFICIENT_EVIDENCE. Always produce a CODE section with runnable Python."""
|
| 162 |
|
| 163 |
provider = os.getenv("PROVIDER", "groq").lower().strip()
|
| 164 |
if provider == "ollama":
|
|
|
|
| 191 |
"uncertainty": _extract_uncertainty(observation),
|
| 192 |
"mode": state.mode,
|
| 193 |
"provider": provider,
|
| 194 |
+
"fallback_level": fallback_level,
|
| 195 |
+
"artifact_type": artifact_type,
|
| 196 |
+
"sensory_channels": sensory_channels,
|
| 197 |
+
"feature_attribution": feature_attribution,
|
| 198 |
}
|
| 199 |
|
| 200 |
return {
|
| 201 |
"patch_output": output,
|
| 202 |
"patch_hash": patch_hash,
|
| 203 |
"receipt": receipt,
|
| 204 |
+
"fallback_level": fallback_level,
|
| 205 |
+
"artifact_type": artifact_type,
|
| 206 |
}
|
| 207 |
|
| 208 |
|
src/gate.py
CHANGED
|
@@ -120,72 +120,159 @@ class EvidenceGateResult:
|
|
| 120 |
reason: str
|
| 121 |
evidence_type: str = ""
|
| 122 |
intent_sources: list[str] = field(default_factory=list)
|
|
|
|
|
|
|
|
|
|
|
|
|
| 123 |
|
| 124 |
|
| 125 |
def evidence_gate(observer_output: str, state_dict: dict) -> EvidenceGateResult:
|
| 126 |
-
"""
|
| 127 |
|
| 128 |
-
|
| 129 |
-
|
| 130 |
-
|
| 131 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 132 |
"""
|
| 133 |
obs = (observer_output or "").lower()
|
| 134 |
|
| 135 |
# Gather intent sources
|
| 136 |
intent_sources = []
|
|
|
|
|
|
|
| 137 |
|
| 138 |
# Check for user speech / transcript
|
| 139 |
speakers = state_dict.get("speakers", {})
|
| 140 |
user_transcript = speakers.get("user", {}).get("transcript", "")
|
| 141 |
if user_transcript and user_transcript.strip():
|
| 142 |
intent_sources.append("user_speech")
|
|
|
|
|
|
|
| 143 |
|
| 144 |
# Check for any audio chunks with content
|
| 145 |
audio_chunks = state_dict.get("audio", {}).get("chunks", [])
|
| 146 |
has_audio_content = any(c.get("transcript", "").strip() for c in audio_chunks if isinstance(c, dict))
|
| 147 |
if has_audio_content:
|
| 148 |
intent_sources.append("audio_transcript")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 149 |
|
| 150 |
# Check for visible screen text / code in observer output
|
| 151 |
screen_indicators = ["screen", "code on", "text on", "monitor", "display", "laptop", "ide", "editor", "terminal"]
|
| 152 |
has_screen_evidence = any(s in obs for s in screen_indicators)
|
| 153 |
if has_screen_evidence:
|
| 154 |
intent_sources.append("visible_screen")
|
|
|
|
| 155 |
|
| 156 |
# Check for explicit typed intent / prior goal
|
| 157 |
if "goal" in obs or "intent" in obs or "task" in obs or "want" in obs:
|
| 158 |
intent_sources.append("explicit_intent")
|
| 159 |
|
| 160 |
-
# Check for
|
| 161 |
-
camera_indicators = ["face", "person", "movement", "object", "light", "wall", "fabric", "hand", "gesture"
|
|
|
|
| 162 |
has_camera_evidence = any(s in obs for s in camera_indicators)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 163 |
|
| 164 |
-
#
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 165 |
if intent_sources:
|
| 166 |
-
evidence_type = "sufficient_intent"
|
| 167 |
return EvidenceGateResult(
|
| 168 |
passed=True,
|
| 169 |
-
reason=f"
|
| 170 |
-
evidence_type=
|
| 171 |
intent_sources=intent_sources,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 172 |
)
|
| 173 |
-
|
| 174 |
-
|
|
|
|
| 175 |
return EvidenceGateResult(
|
| 176 |
-
passed=
|
| 177 |
-
reason="
|
| 178 |
-
evidence_type=
|
| 179 |
intent_sources=[],
|
|
|
|
|
|
|
|
|
|
|
|
|
| 180 |
)
|
| 181 |
-
|
| 182 |
-
|
|
|
|
| 183 |
return EvidenceGateResult(
|
| 184 |
-
passed=
|
| 185 |
-
reason="
|
| 186 |
-
evidence_type=
|
| 187 |
intent_sources=[],
|
|
|
|
|
|
|
|
|
|
|
|
|
| 188 |
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 189 |
|
| 190 |
|
| 191 |
# βββ Gate log for audit βββ
|
|
@@ -208,6 +295,11 @@ def log_gate_decision(gate_type: str, result, patch_hash: str = "", code_preview
|
|
| 208 |
if hasattr(result, "evidence_type"):
|
| 209 |
entry["evidence_type"] = result.evidence_type
|
| 210 |
entry["intent_sources"] = result.intent_sources
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 211 |
_gate_log.append(entry)
|
| 212 |
if len(_gate_log) > 100:
|
| 213 |
_gate_log.pop(0)
|
|
|
|
| 120 |
reason: str
|
| 121 |
evidence_type: str = ""
|
| 122 |
intent_sources: list[str] = field(default_factory=list)
|
| 123 |
+
fallback_level: int = 0
|
| 124 |
+
artifact_type: str = ""
|
| 125 |
+
sensory_channels: list[str] = field(default_factory=list)
|
| 126 |
+
feature_attribution: dict = field(default_factory=dict)
|
| 127 |
|
| 128 |
|
| 129 |
def evidence_gate(observer_output: str, state_dict: dict) -> EvidenceGateResult:
|
| 130 |
+
"""Sensory Proprietary Compiler V1 β Fallback Ladder.
|
| 131 |
|
| 132 |
+
NEVER returns zero artifact. Every sensory input produces something useful.
|
| 133 |
+
|
| 134 |
+
Fallback levels:
|
| 135 |
+
1. Explicit intent β task code
|
| 136 |
+
2. Weak intent + rich sensory β instrumentation code
|
| 137 |
+
3. Distinctive sensory features β aesthetic/system motifs
|
| 138 |
+
4. Background audio only β topic-to-tool associations
|
| 139 |
+
5. Minimal signal β capture protocol improvement
|
| 140 |
"""
|
| 141 |
obs = (observer_output or "").lower()
|
| 142 |
|
| 143 |
# Gather intent sources
|
| 144 |
intent_sources = []
|
| 145 |
+
sensory_channels = []
|
| 146 |
+
feature_attribution = {}
|
| 147 |
|
| 148 |
# Check for user speech / transcript
|
| 149 |
speakers = state_dict.get("speakers", {})
|
| 150 |
user_transcript = speakers.get("user", {}).get("transcript", "")
|
| 151 |
if user_transcript and user_transcript.strip():
|
| 152 |
intent_sources.append("user_speech")
|
| 153 |
+
sensory_channels.append("user_voice")
|
| 154 |
+
feature_attribution["user_speech"] = user_transcript[:200]
|
| 155 |
|
| 156 |
# Check for any audio chunks with content
|
| 157 |
audio_chunks = state_dict.get("audio", {}).get("chunks", [])
|
| 158 |
has_audio_content = any(c.get("transcript", "").strip() for c in audio_chunks if isinstance(c, dict))
|
| 159 |
if has_audio_content:
|
| 160 |
intent_sources.append("audio_transcript")
|
| 161 |
+
sensory_channels.append("audio")
|
| 162 |
+
|
| 163 |
+
# Check for background speakers (TV, other people)
|
| 164 |
+
for spk, info in speakers.items():
|
| 165 |
+
if spk != "user" and info.get("transcript", "").strip():
|
| 166 |
+
sensory_channels.append(f"background_voice:{spk}")
|
| 167 |
+
feature_attribution[f"background_{spk}"] = info["transcript"][:200]
|
| 168 |
|
| 169 |
# Check for visible screen text / code in observer output
|
| 170 |
screen_indicators = ["screen", "code on", "text on", "monitor", "display", "laptop", "ide", "editor", "terminal"]
|
| 171 |
has_screen_evidence = any(s in obs for s in screen_indicators)
|
| 172 |
if has_screen_evidence:
|
| 173 |
intent_sources.append("visible_screen")
|
| 174 |
+
sensory_channels.append("screen")
|
| 175 |
|
| 176 |
# Check for explicit typed intent / prior goal
|
| 177 |
if "goal" in obs or "intent" in obs or "task" in obs or "want" in obs:
|
| 178 |
intent_sources.append("explicit_intent")
|
| 179 |
|
| 180 |
+
# Check for camera sensory features
|
| 181 |
+
camera_indicators = ["face", "person", "movement", "object", "light", "wall", "fabric", "hand", "gesture",
|
| 182 |
+
"hair", "color", "purple", "brown", "breathing", "motion", "room"]
|
| 183 |
has_camera_evidence = any(s in obs for s in camera_indicators)
|
| 184 |
+
if has_camera_evidence:
|
| 185 |
+
sensory_channels.append("camera")
|
| 186 |
+
# Extract specific features
|
| 187 |
+
for indicator in camera_indicators:
|
| 188 |
+
if indicator in obs:
|
| 189 |
+
feature_attribution[f"visual_{indicator}"] = True
|
| 190 |
+
|
| 191 |
+
# Check motion score
|
| 192 |
+
motion_score = state_dict.get("motion_score", 0.0)
|
| 193 |
+
if motion_score > 0.01:
|
| 194 |
+
sensory_channels.append("motion")
|
| 195 |
+
feature_attribution["motion_score"] = round(motion_score, 4)
|
| 196 |
+
|
| 197 |
+
# Check frame count (camera active)
|
| 198 |
+
visual = state_dict.get("visual", {})
|
| 199 |
+
frame_count = visual.get("frame_count", 0)
|
| 200 |
+
if frame_count > 0:
|
| 201 |
+
sensory_channels.append("frames")
|
| 202 |
+
feature_attribution["frame_count"] = frame_count
|
| 203 |
+
feature_attribution["avg_entropy"] = visual.get("avg_entropy", 0)
|
| 204 |
+
feature_attribution["avg_motion"] = visual.get("avg_motion", 0)
|
| 205 |
|
| 206 |
+
# Check audio chunk count
|
| 207 |
+
audio_chunk_count = state_dict.get("audio", {}).get("chunk_count", 0)
|
| 208 |
+
if audio_chunk_count > 0:
|
| 209 |
+
feature_attribution["audio_chunks"] = audio_chunk_count
|
| 210 |
+
|
| 211 |
+
# βββ Fallback Ladder βββ
|
| 212 |
+
|
| 213 |
+
# Level 1: Explicit intent β task code
|
| 214 |
if intent_sources:
|
|
|
|
| 215 |
return EvidenceGateResult(
|
| 216 |
passed=True,
|
| 217 |
+
reason=f"Level 1: Explicit intent detected. Sources: {', '.join(intent_sources)}",
|
| 218 |
+
evidence_type="sufficient_intent",
|
| 219 |
intent_sources=intent_sources,
|
| 220 |
+
fallback_level=1,
|
| 221 |
+
artifact_type="task_code",
|
| 222 |
+
sensory_channels=sensory_channels,
|
| 223 |
+
feature_attribution=feature_attribution,
|
| 224 |
+
)
|
| 225 |
+
|
| 226 |
+
# Level 2: Weak intent but rich sensory features β instrumentation code
|
| 227 |
+
if has_camera_evidence and (len(sensory_channels) >= 2 or motion_score > 0.05):
|
| 228 |
+
return EvidenceGateResult(
|
| 229 |
+
passed=True,
|
| 230 |
+
reason=f"Level 2: Rich sensory evidence ({', '.join(sensory_channels)}). Generating instrumentation code.",
|
| 231 |
+
evidence_type="sensory_rich",
|
| 232 |
+
intent_sources=[],
|
| 233 |
+
fallback_level=2,
|
| 234 |
+
artifact_type="instrumentation_code",
|
| 235 |
+
sensory_channels=sensory_channels,
|
| 236 |
+
feature_attribution=feature_attribution,
|
| 237 |
)
|
| 238 |
+
|
| 239 |
+
# Level 3: Distinctive sensory features β aesthetic/system motifs
|
| 240 |
+
if has_camera_evidence or frame_count > 0:
|
| 241 |
return EvidenceGateResult(
|
| 242 |
+
passed=True,
|
| 243 |
+
reason=f"Level 3: Distinctive sensory features ({', '.join(sensory_channels)}). Generating motif/design artifact.",
|
| 244 |
+
evidence_type="sensory_distinctive",
|
| 245 |
intent_sources=[],
|
| 246 |
+
fallback_level=3,
|
| 247 |
+
artifact_type="aesthetic_motif",
|
| 248 |
+
sensory_channels=sensory_channels,
|
| 249 |
+
feature_attribution=feature_attribution,
|
| 250 |
)
|
| 251 |
+
|
| 252 |
+
# Level 4: Background audio only β topic-to-tool associations
|
| 253 |
+
if audio_chunk_count > 0 or any("background_voice" in ch for ch in sensory_channels):
|
| 254 |
return EvidenceGateResult(
|
| 255 |
+
passed=True,
|
| 256 |
+
reason="Level 4: Audio evidence only. Generating topic-to-tool association artifact.",
|
| 257 |
+
evidence_type="audio_only",
|
| 258 |
intent_sources=[],
|
| 259 |
+
fallback_level=4,
|
| 260 |
+
artifact_type="topic_association",
|
| 261 |
+
sensory_channels=sensory_channels,
|
| 262 |
+
feature_attribution=feature_attribution,
|
| 263 |
)
|
| 264 |
+
|
| 265 |
+
# Level 5: Minimal signal β capture protocol improvement
|
| 266 |
+
return EvidenceGateResult(
|
| 267 |
+
passed=True,
|
| 268 |
+
reason="Level 5: Minimal sensory signal. Generating capture protocol improvement artifact.",
|
| 269 |
+
evidence_type="minimal_signal",
|
| 270 |
+
intent_sources=[],
|
| 271 |
+
fallback_level=5,
|
| 272 |
+
artifact_type="capture_protocol",
|
| 273 |
+
sensory_channels=sensory_channels,
|
| 274 |
+
feature_attribution=feature_attribution,
|
| 275 |
+
)
|
| 276 |
|
| 277 |
|
| 278 |
# βββ Gate log for audit βββ
|
|
|
|
| 295 |
if hasattr(result, "evidence_type"):
|
| 296 |
entry["evidence_type"] = result.evidence_type
|
| 297 |
entry["intent_sources"] = result.intent_sources
|
| 298 |
+
if hasattr(result, "fallback_level"):
|
| 299 |
+
entry["fallback_level"] = result.fallback_level
|
| 300 |
+
entry["artifact_type"] = result.artifact_type
|
| 301 |
+
entry["sensory_channels"] = result.sensory_channels
|
| 302 |
+
entry["feature_attribution"] = result.feature_attribution
|
| 303 |
_gate_log.append(entry)
|
| 304 |
if len(_gate_log) > 100:
|
| 305 |
_gate_log.pop(0)
|