fix: parse skill selection JSON with trailing braces

Greedy \{.*\} matching dropped valid skill-selection objects when the
LLM appended prose that contained braces. Use raw_decode from the first
brace instead.
This commit is contained in:
santhreal 2026-07-18 19:35:29 -07:00
parent 2c5cc409b0
commit f033ecf904
3 changed files with 18 additions and 5 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_registry_skill_selection_json.py
!tests/skill_engine/decision/
tests/skill_engine/decision/*
!tests/skill_engine/decision/test_analysis_adapter.py

View file

@ -1888,13 +1888,13 @@ IMPORTANT: Use the **exact skill_id** from the list above."""
if code_block:
content = code_block.group(1).strip()
else:
# Try to find a raw JSON object
json_match = re.search(r"\{.*\}", content, re.DOTALL)
if json_match:
content = json_match.group()
# Prefer the first object start; raw_decode ignores trailing prose.
brace = content.find("{")
if brace >= 0:
content = content[brace:]
try:
data = json.loads(content)
data, _ = json.JSONDecoder().raw_decode(content)
except json.JSONDecodeError:
logger.warning(f"Failed to parse LLM skill selection JSON: {content[:200]}")
return [], ""

View file

@ -0,0 +1,12 @@
"""Regression: trailing prose with braces must not drop skill-selection JSON."""
from __future__ import annotations
from openspace.skill_engine.registry import SkillRegistry
def test_parse_skill_selection_tolerates_trailing_prose_braces():
text = '{"brief_plan": "ok", "skills": ["a"]}\n\nnote {x}'
ids, plan = SkillRegistry._parse_skill_selection_response(text)
assert ids == ["a"]
assert plan == "ok"