This commit is contained in:
Santh 2026-08-12 22:22:03 +07:00 committed by GitHub
commit 08757c784f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 28 additions and 9 deletions

1
.gitignore vendored
View file

@ -51,6 +51,7 @@ tests/skill_engine/*
!tests/skill_engine/test_evolver_length_recovery.py
!tests/skill_engine/test_evolution_retry_idempotency.py
!tests/skill_engine/test_analyzer_length_recovery.py
!tests/skill_engine/test_extract_json_trailing_prose.py
!tests/skill_engine/decision/
tests/skill_engine/decision/*
!tests/skill_engine/decision/test_analysis_adapter.py

View file

@ -1508,13 +1508,13 @@ class ExecutionAnalyzer:
if code_match:
text = code_match.group(1).strip()
else:
# Try bare JSON object
json_match = re.search(r"\{.*\}", text, re.DOTALL)
if json_match:
text = json_match.group()
# Prefer the first object start; raw_decode ignores trailing prose.
brace = text.find("{")
if brace >= 0:
text = text[brace:]
try:
data = json.loads(text)
data, _ = json.JSONDecoder().raw_decode(text)
if isinstance(data, dict):
return data
logger.warning(f"LLM returned non-dict JSON: {type(data)}")

View file

@ -399,11 +399,13 @@ def _extract_json(text: str) -> dict[str, Any] | None:
if match:
text = match.group(1)
else:
match = re.search(r"\{.*\}", text, re.DOTALL)
if match:
text = match.group(0)
brace = text.find("{")
if brace >= 0:
text = text[brace:]
else:
return None
try:
value = json.loads(text)
value, _ = json.JSONDecoder().raw_decode(text)
except Exception:
return None
return dict(value) if isinstance(value, Mapping) else None

View file

@ -0,0 +1,16 @@
"""Regression: trailing prose with braces must not drop valid analysis JSON."""
from __future__ import annotations
from openspace.skill_engine.analyzer import ExecutionAnalyzer
from openspace.skill_engine.evolution.capture_semantic import _extract_json as capture_extract_json
def test_analyzer_extract_json_tolerates_trailing_prose_braces():
text = '{"task_completed": true}\n\nReplace {foo} with {bar}.'
assert ExecutionAnalyzer._extract_json(text) == {"task_completed": True}
def test_capture_semantic_extract_json_tolerates_trailing_prose_braces():
text = '{"ok": true}\n\nnote {x}'
assert capture_extract_json(text) == {"ok": True}