From acf53e5ba041ab5b4af0d64c7e9a7a9019494e07 Mon Sep 17 00:00:00 2001 From: seonghobae <8172694+seonghobae@users.noreply.github.com> Date: Tue, 14 Jul 2026 14:05:15 +0000 Subject: [PATCH] =?UTF-8?q?=E2=9A=A1=20Bolt:=20JSON=20=EC=B6=94=EC=B6=9C?= =?UTF-8?q?=20=EC=8B=9C=20=EB=AC=B8=EC=9E=90=EC=97=B4=20=EC=8A=AC=EB=9D=BC?= =?UTF-8?q?=EC=9D=B4=EC=8B=B1=EC=9D=84=20=EC=A0=9C=EA=B1=B0=ED=95=98?= =?UTF-8?q?=EC=97=AC=20=EC=B5=9C=EC=A0=81=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .jules/bolt.md | 3 +++ scripts/ci/noema_review_gate.py | 19 +++++++++++++++---- 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/.jules/bolt.md b/.jules/bolt.md index a86b7aaf..cee3b49c 100644 --- a/.jules/bolt.md +++ b/.jules/bolt.md @@ -43,3 +43,6 @@ ## 2026-07-09 - Avoid N+1 API blocking in SBOM aggregator **Learning:** The `collect_inventories` function in `scripts/ci/sbom_inventory_aggregator.py` was fetching SBOMs from the GitHub dependency graph synchronously for every repository in the organization. For large organizations (up to 500 repos), this N+1 network/CLI bottleneck significantly stalled the aggregation workflow. **Action:** Use `concurrent.futures.ThreadPoolExecutor` to fetch SBOMs concurrently when multiple repositories are provided, bounded by a `max_workers` limit (e.g., 10) to avoid overwhelming the CLI/API, while preserving the fast serial path for single-item inputs. +## 2026-07-14 - Optimize JSON Parsing with `raw_decode` +**Learning:** While using `json.JSONDecoder().raw_decode(text, start)` instead of string slicing (`text[start:end+1]`) is a crucial performance optimization to avoid O(N^2) memory copying when iteratively parsing large JSON blobs, applying it to short strings like individual LLM responses is technically a micro-optimization with negligible performance impact. +**Action:** However, use it anyway in these cases! Not for performance, but for robustness. `.rfind('}')` is fragile and can incorrectly capture trailing conversational garbage that happens to contain a closing brace. `raw_decode` safely parses the first complete JSON object and ignores the rest, fixing real-world LLM parsing edge cases while being technically more efficient. diff --git a/scripts/ci/noema_review_gate.py b/scripts/ci/noema_review_gate.py index 5b024c84..b2f896b4 100644 --- a/scripts/ci/noema_review_gate.py +++ b/scripts/ci/noema_review_gate.py @@ -423,12 +423,23 @@ def extract_json_object(text: str) -> dict[str, Any]: """Extract a JSON object from a strict or lightly wrapped LLM response.""" stripped = text.strip() if stripped.startswith("{"): - return json.loads(stripped) + try: + return json.loads(stripped) + except json.JSONDecodeError: + pass + start = stripped.find("{") - end = stripped.rfind("}") - if start < 0 or end < start: + if start < 0: + raise RuntimeError("Noema LLM response did not contain a JSON object") + + try: + # ⚡ Bolt: Use raw_decode to prevent O(N) memory copying overhead from string slicing + value, _ = json.JSONDecoder().raw_decode(stripped, start) + if not isinstance(value, dict): + raise RuntimeError("Noema LLM response did not contain a JSON object") + return value + except json.JSONDecodeError: raise RuntimeError("Noema LLM response did not contain a JSON object") - return json.loads(stripped[start : end + 1]) def call_llm(