From d6bbe71a5c9e69692cedd6b00e214b89cace6c99 Mon Sep 17 00:00:00 2001 From: seonghobae <8172694+seonghobae@users.noreply.github.com> Date: Wed, 30 Sep 2026 04:48:20 +0000 Subject: [PATCH 1/6] =?UTF-8?q?=E2=9A=A1=20Bolt:=20=EB=8B=A8=EC=9D=BC=20?= =?UTF-8?q?=EB=A3=A8=ED=94=84=EB=A1=9C=20=EC=A1=B0=EC=A7=81=20=EC=9D=B8?= =?UTF-8?q?=EB=B2=A4=ED=86=A0=EB=A6=AC=20=EC=A7=91=EA=B3=84=20=EC=B5=9C?= =?UTF-8?q?=EC=A0=81=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit appguardrail_core/org_intelligence.py 내부 `build_org_inventory` 함수가 동일한 github 리포지토리 컬렉션을 다중 순회(O(N) * K)하며 파생 리스트들을 생성하던 것을 단일 루프로 통합하여 성능을 최적화함. 상수 인자(constant-factor) 개선사항이며, 변경사항은 .jules/bolt.md 에 기록됨. --- .jules/bolt.md | 4 ++ appguardrail_core/org_intelligence.py | 59 ++++++++++++++++----------- 2 files changed, 39 insertions(+), 24 deletions(-) diff --git a/.jules/bolt.md b/.jules/bolt.md index 8ce7ce8f7..d3247080c 100644 --- a/.jules/bolt.md +++ b/.jules/bolt.md @@ -77,3 +77,7 @@ ## 2024-11-20 - Optimize multiple tuple generation from a single collection **Learning:** `build_rule_metadata` derives exactly two collections, `owasp` and `cwe`, from the same references. Replacing its two generator traversals with one explicit loop reduces element visits from about 2N to N. Both versions remain O(N), so this is a constant-factor optimization rather than an asymptotic complexity improvement. **Action:** Combine repeated traversal when fixed derived collections share one source, while preserving ordering and classification semantics. Benchmark the production hot path before claiming a material wall-clock improvement. + +## 2024-11-20 - Optimize multiple list comprehensions into single O(N) loop +**Learning:** In `appguardrail_core/org_intelligence.py`, `build_org_inventory` derived several values using multiple O(N) list and generator comprehensions. Consolidating them into a single loop reduced the number of iterations from 2N to N. This is a constant-factor optimization rather than an asymptotic complexity improvement. +**Action:** Combine repeated O(N) traversals of the same source iterable into a single loop when building multiple derived collections or counters, avoiding redundant evaluations while preserving functionality. diff --git a/appguardrail_core/org_intelligence.py b/appguardrail_core/org_intelligence.py index 632179f1d..9a0015000 100644 --- a/appguardrail_core/org_intelligence.py +++ b/appguardrail_core/org_intelligence.py @@ -122,35 +122,46 @@ def build_org_inventory( active_repository_target: int = 20, ) -> OrgInventory: """Build a stable organization inventory from GitHub repo JSON.""" - repo_list = list(repos) - nonforks = [repo for repo in repo_list if not _truthy(repo.get("isFork"))] - forks = [repo for repo in repo_list if _truthy(repo.get("isFork"))] - primary_languages = Counter(_primary_language(repo) for repo in repo_list) - default_branches = Counter(_default_branch(repo) for repo in repo_list) - unsupported = sorted( - { - _primary_language(repo) - for repo in nonforks - if _primary_language(repo) not in SUPPORTED_PRIMARY_LANGUAGES - and _primary_language(repo) != "Unknown" - } - ) - supported_nonforks = sum( - 1 for repo in nonforks if _primary_language(repo) in SUPPORTED_PRIMARY_LANGUAGES - ) + nonfork_count = 0 + fork_count = 0 + private_count = 0 + supported_nonforks = 0 + unsupported_set = set() + primary_languages = Counter() + default_branches = Counter() + + for repo in repos: + is_fork = _truthy(repo.get("isFork")) + is_private = _truthy(repo.get("isPrivate")) + lang = _primary_language(repo) + branch = _default_branch(repo) + + primary_languages[lang] += 1 + default_branches[branch] += 1 + + if is_private: + private_count += 1 + + if is_fork: + fork_count += 1 + else: + nonfork_count += 1 + if lang in SUPPORTED_PRIMARY_LANGUAGES: + supported_nonforks += 1 + elif lang != "Unknown": + unsupported_set.add(lang) + return OrgInventory( - total_repositories=len(repo_list), - nonfork_repositories=len(nonforks), - fork_repositories=len(forks), - private_repositories=sum( - 1 for repo in repo_list if _truthy(repo.get("isPrivate")) - ), + total_repositories=nonfork_count + fork_count, + nonfork_repositories=nonfork_count, + fork_repositories=fork_count, + private_repositories=private_count, supported_nonfork_repositories=supported_nonforks, - unsupported_nonfork_languages=tuple(unsupported), + unsupported_nonfork_languages=tuple(sorted(unsupported_set)), primary_language_counts=_sorted_counts(primary_languages), default_branch_counts=_sorted_counts(default_branches), active_repository_target=active_repository_target, - active_repository_target_met=len(nonforks) >= active_repository_target, + active_repository_target_met=nonfork_count >= active_repository_target, ) From f9d6a3dc5ab13aa18276431bb5074c99f0cf8eb6 Mon Sep 17 00:00:00 2001 From: seonghobae <8172694+seonghobae@users.noreply.github.com> Date: Wed, 30 Sep 2026 08:20:37 +0000 Subject: [PATCH 2/6] =?UTF-8?q?=E2=9A=A1=20Bolt:=20=EB=8B=A8=EC=9D=BC=20?= =?UTF-8?q?=EB=A3=A8=ED=94=84=EB=A1=9C=20=EC=A1=B0=EC=A7=81=20=EC=9D=B8?= =?UTF-8?q?=EB=B2=A4=ED=86=A0=EB=A6=AC=20=EC=A7=91=EA=B3=84=20=EC=B5=9C?= =?UTF-8?q?=EC=A0=81=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit appguardrail_core/org_intelligence.py 내부 `build_org_inventory` 함수가 동일한 github 리포지토리 컬렉션을 다중 순회(O(N) * K)하며 파생 리스트들을 생성하던 것을 단일 루프로 통합하여 성능을 최적화함. 상수 인자(constant-factor) 개선사항이며, 변경사항은 .jules/bolt.md 에 기록됨. From c5ca0d8c1bf6713ab21cdfbf372638ce774753af Mon Sep 17 00:00:00 2001 From: seonghobae <8172694+seonghobae@users.noreply.github.com> Date: Wed, 30 Sep 2026 10:50:35 +0000 Subject: [PATCH 3/6] =?UTF-8?q?=E2=9A=A1=20Bolt:=20=EB=8B=A8=EC=9D=BC=20?= =?UTF-8?q?=EB=A3=A8=ED=94=84=EB=A1=9C=20=EC=A1=B0=EC=A7=81=20=EC=9D=B8?= =?UTF-8?q?=EB=B2=A4=ED=86=A0=EB=A6=AC=20=EC=A7=91=EA=B3=84=20=EC=B5=9C?= =?UTF-8?q?=EC=A0=81=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit appguardrail_core/org_intelligence.py 내부 `build_org_inventory` 함수가 동일한 github 리포지토리 컬렉션을 다중 순회(O(N) * K)하며 파생 리스트들을 생성하던 것을 단일 루프로 통합하여 성능을 최적화함. 상수 인자(constant-factor) 개선사항이며, 변경사항은 .jules/bolt.md 에 기록됨. --- appguardrail_core/org_intelligence.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/appguardrail_core/org_intelligence.py b/appguardrail_core/org_intelligence.py index 9a0015000..a7b3fd2d9 100644 --- a/appguardrail_core/org_intelligence.py +++ b/appguardrail_core/org_intelligence.py @@ -126,9 +126,9 @@ def build_org_inventory( fork_count = 0 private_count = 0 supported_nonforks = 0 - unsupported_set = set() - primary_languages = Counter() - default_branches = Counter() + unsupported_set: set[str] = set() + primary_languages: Counter[str] = Counter() + default_branches: Counter[str] = Counter() for repo in repos: is_fork = _truthy(repo.get("isFork")) From 7764372202ab1736987b0ea1f2951765e61b89b3 Mon Sep 17 00:00:00 2001 From: seonghobae <8172694+seonghobae@users.noreply.github.com> Date: Wed, 30 Sep 2026 14:22:21 +0000 Subject: [PATCH 4/6] =?UTF-8?q?=E2=9A=A1=20Bolt:=20=EB=8B=A8=EC=9D=BC=20?= =?UTF-8?q?=EB=A3=A8=ED=94=84=EB=A1=9C=20=EC=A1=B0=EC=A7=81=20=EC=9D=B8?= =?UTF-8?q?=EB=B2=A4=ED=86=A0=EB=A6=AC=20=EC=A7=91=EA=B3=84=20=EC=B5=9C?= =?UTF-8?q?=EC=A0=81=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit appguardrail_core/org_intelligence.py 내부 `build_org_inventory` 함수가 동일한 github 리포지토리 컬렉션을 다중 순회(O(N) * K)하며 파생 리스트들을 생성하던 것을 단일 루프로 통합하여 성능을 최적화함. 상수 인자(constant-factor) 개선사항이며, 변경사항은 .jules/bolt.md 에 기록됨. From 72584935b924d5ad252b19fc1a4fe40cf5d7d8b0 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 3 Oct 2026 19:58:50 +0900 Subject: [PATCH 5/6] chore: retire duplicate .jules/bolt.md delta into #1292 --- .jules/bolt.md | 4 ---- 1 file changed, 4 deletions(-) diff --git a/.jules/bolt.md b/.jules/bolt.md index d3247080c..8ce7ce8f7 100644 --- a/.jules/bolt.md +++ b/.jules/bolt.md @@ -77,7 +77,3 @@ ## 2024-11-20 - Optimize multiple tuple generation from a single collection **Learning:** `build_rule_metadata` derives exactly two collections, `owasp` and `cwe`, from the same references. Replacing its two generator traversals with one explicit loop reduces element visits from about 2N to N. Both versions remain O(N), so this is a constant-factor optimization rather than an asymptotic complexity improvement. **Action:** Combine repeated traversal when fixed derived collections share one source, while preserving ordering and classification semantics. Benchmark the production hot path before claiming a material wall-clock improvement. - -## 2024-11-20 - Optimize multiple list comprehensions into single O(N) loop -**Learning:** In `appguardrail_core/org_intelligence.py`, `build_org_inventory` derived several values using multiple O(N) list and generator comprehensions. Consolidating them into a single loop reduced the number of iterations from 2N to N. This is a constant-factor optimization rather than an asymptotic complexity improvement. -**Action:** Combine repeated O(N) traversals of the same source iterable into a single loop when building multiple derived collections or counters, avoiding redundant evaluations while preserving functionality. From fdb57af4cc5066784748d82ce3153f18e9bde642 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sat, 3 Oct 2026 19:58:51 +0900 Subject: [PATCH 6/6] chore: retire duplicate appguardrail_core/org_intelligence.py delta into #1292 --- appguardrail_core/org_intelligence.py | 59 +++++++++++---------------- 1 file changed, 24 insertions(+), 35 deletions(-) diff --git a/appguardrail_core/org_intelligence.py b/appguardrail_core/org_intelligence.py index a7b3fd2d9..632179f1d 100644 --- a/appguardrail_core/org_intelligence.py +++ b/appguardrail_core/org_intelligence.py @@ -122,46 +122,35 @@ def build_org_inventory( active_repository_target: int = 20, ) -> OrgInventory: """Build a stable organization inventory from GitHub repo JSON.""" - nonfork_count = 0 - fork_count = 0 - private_count = 0 - supported_nonforks = 0 - unsupported_set: set[str] = set() - primary_languages: Counter[str] = Counter() - default_branches: Counter[str] = Counter() - - for repo in repos: - is_fork = _truthy(repo.get("isFork")) - is_private = _truthy(repo.get("isPrivate")) - lang = _primary_language(repo) - branch = _default_branch(repo) - - primary_languages[lang] += 1 - default_branches[branch] += 1 - - if is_private: - private_count += 1 - - if is_fork: - fork_count += 1 - else: - nonfork_count += 1 - if lang in SUPPORTED_PRIMARY_LANGUAGES: - supported_nonforks += 1 - elif lang != "Unknown": - unsupported_set.add(lang) - + repo_list = list(repos) + nonforks = [repo for repo in repo_list if not _truthy(repo.get("isFork"))] + forks = [repo for repo in repo_list if _truthy(repo.get("isFork"))] + primary_languages = Counter(_primary_language(repo) for repo in repo_list) + default_branches = Counter(_default_branch(repo) for repo in repo_list) + unsupported = sorted( + { + _primary_language(repo) + for repo in nonforks + if _primary_language(repo) not in SUPPORTED_PRIMARY_LANGUAGES + and _primary_language(repo) != "Unknown" + } + ) + supported_nonforks = sum( + 1 for repo in nonforks if _primary_language(repo) in SUPPORTED_PRIMARY_LANGUAGES + ) return OrgInventory( - total_repositories=nonfork_count + fork_count, - nonfork_repositories=nonfork_count, - fork_repositories=fork_count, - private_repositories=private_count, + total_repositories=len(repo_list), + nonfork_repositories=len(nonforks), + fork_repositories=len(forks), + private_repositories=sum( + 1 for repo in repo_list if _truthy(repo.get("isPrivate")) + ), supported_nonfork_repositories=supported_nonforks, - unsupported_nonfork_languages=tuple(sorted(unsupported_set)), + unsupported_nonfork_languages=tuple(unsupported), primary_language_counts=_sorted_counts(primary_languages), default_branch_counts=_sorted_counts(default_branches), active_repository_target=active_repository_target, - active_repository_target_met=nonfork_count >= active_repository_target, + active_repository_target_met=len(nonforks) >= active_repository_target, )