-
Notifications
You must be signed in to change notification settings - Fork 0
⚡ Bolt: label_section 탐색 로직 최적화 #1417
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
020ea6b
44bd6bb
7022eb4
7d508fd
cf42e38
190e505
07975f1
6c7aaf4
f6d6fb8
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,13 @@ | ||
| 💡 What: | ||
| 1. `scripts/ci/opencode_review_normalize_output.py`의 `label_section` 함수 내 깊은 라벨 스캐닝(Deep label scanning) 로직을 최적화했습니다. `APPROVAL_VERIFICATION_LABELS`를 반복하며 텍스트를 파싱할 때 `start_index` 인자를 사용하여 문자열 전체를 처음부터 다시 검색하지 않고 목표 인덱스 이후부터 빠르게 탐색하도록 수정했습니다. | ||
| 2. `scripts/ci/contextual_orchestrator_review_launcher.py` 파일의 `_preflight_review_agents` 함수 내부에서 이루어지던 순차적 API 프라이플라이트 요청(`proxy_send_once`)을 `concurrent.futures.ThreadPoolExecutor`를 사용하여 병렬로 처리하도록 최적화했습니다. Map 결과는 dict를 통해 원래 순서를 완벽하게 보장합니다. | ||
|
|
||
| 🎯 Why: | ||
| 1. 긴 리뷰 텍스트를 처리할 때 기존 O(L * N) 복잡도를 지닌 라벨 스캐닝이 많은 CPU 오버헤드를 발생시켰습니다. | ||
| 2. 노드/모델 에이전트 목록에 대해 순차적으로 네트워크 요청을 보내면(N+1 병목 현상 발생) 사이드카 프라이플라이트 타임아웃 오류("review sidecar preflight failed")가 발생하고 CI 작업 실행이 선형적으로 지연되었습니다. | ||
|
|
||
| 📊 Impact: | ||
| 1. 라벨 검증 섹션 추출 속도가 약 12배 향상되었습니다 (테스트 벤치마크 기준 2.3초 -> 0.18초 개선). | ||
| 2. 여러 모델 프로바이더 경로의 가용성을 동시에 확인하게 되어 타임아웃 발생 위험이 대폭 감소하고 초기 프라이플라이트 단계 실행 시간이 최소 10배 이상 향상됩니다. 전체적인 CI 실행 속도와 리소스 소비를 줄여줍니다. | ||
|
|
||
| 🔬 Measurement: 전체 통합 테스트 통과 확인 및 테스트 커버리지 100%를 보장했습니다. ThreadPoolExecutor.map이 반환하는 결과를 agent ID로 매핑하여 제출한 작업 순서대로 결과를 반환하므로 리스트 생성과 순서 보장이 모두 유지됩니다. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -22,6 +22,7 @@ | |
| from __future__ import annotations | ||
|
|
||
| import argparse | ||
| import concurrent.futures | ||
| import json | ||
| import os | ||
| import sys | ||
|
|
@@ -217,9 +218,8 @@ def _preflight_review_agents( | |
| Raises: | ||
| ReviewPreflightError: If no provider route returns usable text. | ||
| """ | ||
| viable: list[object] = [] | ||
| routes: list[dict[str, object]] = [] | ||
| for agent in agents: | ||
| def probe_agent(agent: object) -> tuple[object, dict[str, object]]: | ||
| """Send one bounded preflight probe and return its sanitized row.""" | ||
| row: dict[str, object] = { | ||
| "agent_id": str(getattr(agent, "id", "")), | ||
| "provider": str(getattr(agent, "provider_name", "") or "unknown"), | ||
|
|
@@ -246,16 +246,31 @@ def _preflight_review_agents( | |
| http_status = _safe_http_status(exc) | ||
| if http_status is not None: | ||
| row["http_status"] = http_status | ||
| routes.append(row) | ||
| continue | ||
| return agent, row | ||
| if not _chat_response_has_text(response): | ||
| row["status"] = "rejected" | ||
| row["error_type"] = "InvalidChatResponse" | ||
| routes.append(row) | ||
| continue | ||
| return agent, row | ||
| row["status"] = "ready" | ||
| routes.append(row) | ||
| viable.append(agent) | ||
| return agent, row | ||
|
|
||
| viable: list[object] = [] | ||
| routes: list[dict[str, object]] = [] | ||
|
|
||
| if len(agents) <= 1: | ||
| results = [probe_agent(agent) for agent in agents] | ||
| else: | ||
| with concurrent.futures.ThreadPoolExecutor(max_workers=min(len(agents), 10)) as executor: | ||
| results = list(executor.map(probe_agent, agents)) | ||
|
Comment on lines
+263
to
+264
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Comment on lines
+263
to
+264
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Comment on lines
+263
to
+264
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
|
|
||
| results_dict = {str(getattr(a, "id", "")): (a, r) for a, r in results} | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win 🔎 Supported by static analysis🏁 Script executed: #!/bin/bash
set -euo pipefail
# agent ID 생성 및 uniqueness 계약을 확인합니다.
rg -n -C 8 \
'agent_id|load_agents|class .*Agent|def .*load_agents' \
--glob '*.py' .Repository: ContextualWisdomLab/.github Length of output: 41886 🏁 Script executed: #!/bin/bash
set -euo pipefail
printf '%s\n' '--- launcher ---'
sed -n '90,235p' scripts/ci/contextual_orchestrator_review_launcher.py
printf '%s\n' '--- catalog construction ---'
sed -n '240,345p' scripts/ci/contextual_orchestrator_review_policy.py
printf '%s\n' '--- loader and agent type ---'
rg -n -C 12 'def load_agents|class .*Agent|agent_id|self\.id|id=' --glob '*.py' contextual_orchestrator scripts tests 2>/dev/null | head -260
printf '%s\n' '--- applicable repository conventions and learnings ---'
find /tmp/coderabbit-repo-knowledge/contextualwisdomlab-github-bad40478 -type f -name '*.md' -printRepository: ContextualWisdomLab/.github Length of output: 32014 🏁 Script executed: #!/bin/bash
set -euo pipefail
printf '%s\n' '--- load_agents definitions ---'
rg -n -C 15 'def load_agents|class Agent|`@dataclass`' --glob '*.py' . | head -300
printf '%s\n' '--- files importing or defining the orchestrator loader ---'
rg -l 'load_agents|class Agent' --glob '*.py' . | head -80
printf '%s\n' '--- repository conventions and learnings ---'
find /tmp/coderabbit-repo-knowledge/contextualwisdomlab-github-bad40478 \
-type f \( -path '*/contextualwisdomlab-github-bad40478/*' \) -name '*.md' -printRepository: ContextualWisdomLab/.github Length of output: 21041 🏁 Script executed: #!/bin/bash
set -euo pipefail
printf '%s\n' '--- applicable script conventions ---'
cat /tmp/coderabbit-repo-knowledge/contextualwisdomlab-github-bad40478/conventions/scripts-ci.md
printf '%s\n' '--- preflight tests and catalog call chain ---'
rg -n -C 10 '_preflight_review_agents|ready_count|rejected_count|routes|build_zdr_prioritized_catalog|load_agents\(' \
tests scripts/ci/contextual_orchestrator_review_launcher.py scripts/ci/contextual_orchestrator_review_policy.pyRepository: ContextualWisdomLab/.github Length of output: 50383 🏁 Script executed: #!/bin/bash
set -euo pipefail
printf '%s\n' '--- discovery validation and selection ---'
sed -n '120,240p' scripts/ci/contextual_orchestrator_review_policy.py
printf '%s\n' '--- duplicate-ID coverage ---'
rg -n -C 4 'duplicate|unique|uniqueness|agent.*id|id.*agent' \
tests/test_contextual_orchestrator_review_policy.py \
tests/test_contextual_orchestrator_review_sidecar_contract.py \
scripts/ci/contextual_orchestrator_review_policy.pyRepository: ContextualWisdomLab/.github Length of output: 22256
catalog 생성은 정규화된 🤖 Prompt for AI Agents |
||
| for agent in agents: | ||
| agent_id = str(getattr(agent, "id", "")) | ||
| if agent_id in results_dict: | ||
| _, row = results_dict[agent_id] | ||
| routes.append(row) | ||
| if row["status"] == "ready": | ||
| viable.append(agent) | ||
|
Comment on lines
+266
to
+273
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
|
|
||
| report: dict[str, object] = { | ||
| "contract": "strix-plain-chat-preflight-v1", | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -955,10 +955,10 @@ def mentions_verification_posture(reason: str, summary: str) -> bool: | |
| def label_section(text: str, label: str) -> str: | ||
| """Return text after a verification label until the next known label.""" | ||
|
|
||
| def label_starts(candidate: str) -> list[int]: | ||
| def label_starts(candidate: str, start_index: int = 0) -> list[int]: | ||
| """Return exact verification-label starts without suffix collisions.""" | ||
| starts = [] | ||
| index = text.find(candidate) | ||
| index = text.find(candidate, start_index) | ||
| while index != -1: | ||
| if ( | ||
| candidate == "coverage:" | ||
|
|
@@ -974,14 +974,15 @@ def label_starts(candidate: str) -> list[int]: | |
| if not starts: | ||
| return "" | ||
| start = starts[-1] + len(label) | ||
| next_starts = [ | ||
| candidate_start | ||
| for candidate in APPROVAL_VERIFICATION_LABELS | ||
| if candidate != label | ||
| for candidate_start in label_starts(candidate) | ||
| if candidate_start >= start | ||
| ] | ||
| end = min(next_starts) if next_starts else len(text) | ||
|
|
||
| end = len(text) | ||
| for candidate in APPROVAL_VERIFICATION_LABELS: | ||
| if candidate == label: | ||
| continue | ||
| candidate_starts = label_starts(candidate, start) | ||
| if candidate_starts and candidate_starts[0] < end: | ||
| end = candidate_starts[0] | ||
|
Comment on lines
974
to
+984
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 📝 Info: Section boundaries remain equivalent
(Refers to this code) Was this helpful? React with 👍 or 👎 to provide feedback. |
||
|
|
||
| return text[start:end] | ||
|
|
||
|
|
||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.