Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
040dd52
⚡ Bolt: 단일 O(N) 루프 적용을 통한 저장소 분류 성능 개선
seonghobae Sep 22, 2026
df5f111
⚡ Bolt: 단일 O(N) 루프 적용을 통한 저장소 분류 성능 개선 및 버그 수정
seonghobae Sep 22, 2026
1e3a5a2
test: pin single-pass org inventory traversal
seonghobae Sep 22, 2026
1ad9d4e
fix: keep org inventory aggregation single-pass
seonghobae Sep 22, 2026
a2f97d3
docs: drop unproven blanket performance rule
seonghobae Sep 22, 2026
d3953aa
⚡ Bolt: 단일 O(N) 루프 적용 최적화에 대한 AST 검사 호환성 수정
seonghobae Sep 22, 2026
7cc4f67
⚡ Bolt: 단일 O(N) 루프 적용 최적화에 대한 AST 검사 호환성 수정
seonghobae Sep 22, 2026
49240ea
⚡ Bolt: 단일 O(N) 루프 적용 최적화에 대한 외부 CI 응답 대기 및 최종 제출 검증
seonghobae Sep 22, 2026
5f8cc2c
⚡ Bolt: 단일 O(N) 루프 적용 최적화 검증
seonghobae Sep 26, 2026
d439c12
⚡ Bolt: 단일 O(N) 루프 적용 최적화 최종 제출
seonghobae Sep 26, 2026
8bdf4cc
⚡ Bolt: 단일 O(N) 루프 적용 최적화 최종 제출
seonghobae Sep 28, 2026
df5657b
⚡ Bolt: 단일 O(N) 루프 적용 최적화 최종 제출
seonghobae Sep 28, 2026
f0d8fd8
test(inventory): require incremental repository release
seonghobae Oct 3, 2026
1cb5668
refactor(inventory): stream aggregation without retained records
seonghobae Oct 3, 2026
c12402e
merge(develop): reconcile streaming inventory writer
seonghobae Oct 3, 2026
86951bb
⚡ Bolt: 단일 O(N) 루프 적용 최적화 최종 검증
seonghobae Oct 3, 2026
bcfbfb3
repair(boundary): restore CHANGELOG.d/929-workflow-lifecycle-detectio…
seonghobae Oct 3, 2026
e19de7c
repair(boundary): restore appguardrail_core/workflow_lifecycle.py
seonghobae Oct 3, 2026
5b5095e
repair(boundary): restore docs/workflow-lifecycle-detection.md
seonghobae Oct 3, 2026
9729e60
repair(boundary): restore tests/test_github_actions_writer_rules.py
seonghobae Oct 3, 2026
6668af6
repair(boundary): restore tests/test_workflow_lifecycle.py
seonghobae Oct 3, 2026
88a7c07
repair(boundary): restore tests/test_workflow_lifecycle_central_contr…
seonghobae Oct 3, 2026
83ff423
repair(boundary): restore protected-base DOCUMENTATION.md
seonghobae Oct 3, 2026
6b76a65
repair(boundary): restore protected-base scanner/rules/github_actions…
seonghobae Oct 3, 2026
c12630d
repair(inventory): restore behavioral streaming contract in appguardr…
seonghobae Oct 3, 2026
be032f1
repair(inventory): restore behavioral streaming contract in tests/tes…
seonghobae Oct 3, 2026
e685567
⚡ Bolt: O(1) 메모리 스트리밍을 통한 단일 O(N) 루프 최적화 및 동작 기반 테스트 개선
seonghobae Oct 3, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 0 additions & 14 deletions CHANGELOG.d/929-workflow-lifecycle-detection.md

This file was deleted.

3 changes: 1 addition & 2 deletions DOCUMENTATION.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ AppGuardrail has extensive rule, scanner, report, release, issue, and scheduler
| Architecture decisions | [`docs/adr/README.md`](docs/adr/README.md) |
| Security reporting | [`SECURITY.md`](SECURITY.md) |
| Release automation | [`docs/release-automation.md`](docs/release-automation.md) |
| GitHub workflow lifecycle detection | [`docs/workflow-lifecycle-detection.md`](docs/workflow-lifecycle-detection.md) |
| Productization roadmap | [`docs/product/2026-07-02-2b-krw-sale-readiness-plan.md`](docs/product/2026-07-02-2b-krw-sale-readiness-plan.md) |
| Agent development rules | [`AGENTS.md`](AGENTS.md) |
| Agent context | [`CLAUDE.md`](CLAUDE.md) |
Expand All @@ -31,4 +30,4 @@ AppGuardrail has extensive rule, scanner, report, release, issue, and scheduler
- **external-engine** — capability delegated to an optional scanner such as Semgrep/Trivy/Bandit/ZAP rather than AppGuardrail's lightweight built-in matcher.
- **evidence-only** — information visible in reports/history but not yet executable as an AppGuardrail detector.

Critical current distinction: PR #911's no-exclusions issue-to-detector registry and executable obligation coverage remain **active-PR**, not protected-branch behavior. Stored-webhook SSRF prevention from PR #924 and bounded built-in detection from PR #910 are **implemented-main** as separate controls; the packaged rule covers its tested Python `set_webhook` persistence patterns and is not a universal SSRF taint-analysis claim.
Critical current distinction: PR #911's no-exclusions issue-to-detector registry and executable obligation coverage remain **active-PR**, not protected-branch behavior. Stored-webhook SSRF prevention from PR #924 and bounded built-in detection from PR #910 are **implemented-main** as separate controls; the packaged rule covers its tested Python `set_webhook` persistence patterns and is not a universal SSRF taint-analysis claim.
56 changes: 33 additions & 23 deletions appguardrail_core/org_intelligence.py
Original file line number Diff line number Diff line change
Expand Up @@ -122,35 +122,45 @@ 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
)
total_repositories = 0
nonfork_repositories = 0
fork_repositories = 0
primary_languages = Counter()
default_branches = Counter()
unsupported_set = set()
supported_nonforks = 0
private_repositories = 0

for repo in repos:
total_repositories += 1
lang = _primary_language(repo)
is_fork = _truthy(repo.get("isFork"))
if is_fork:
fork_repositories += 1
else:
nonfork_repositories += 1
if lang in SUPPORTED_PRIMARY_LANGUAGES:
supported_nonforks += 1
elif lang != "Unknown":
unsupported_set.add(lang)

if _truthy(repo.get("isPrivate")):
private_repositories += 1
primary_languages[lang] += 1
default_branches[_default_branch(repo)] += 1

unsupported = sorted(unsupported_set)
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=total_repositories,
nonfork_repositories=nonfork_repositories,
fork_repositories=fork_repositories,
private_repositories=private_repositories,
supported_nonfork_repositories=supported_nonforks,
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=len(nonforks) >= active_repository_target,
active_repository_target_met=nonfork_repositories >= active_repository_target,
)


Expand Down
Loading
Loading