Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
7627a63
fix: exclude vendored third-party code from the native lane
saiganakato Jun 21, 2026
3b92066
Merge branch 'main' into claude/dreamy-brattain-c0180a
saiganakato Jun 21, 2026
ce8c295
refactor: derive borrowed-analyzer skip sets from the generated-path …
saiganakato Jun 21, 2026
48d6fd8
Merge branch 'main' into claude/dreamy-brattain-c0180a
saiganakato Jun 21, 2026
e0d57cb
test: lock diff-mode tolerance of deleted files in the changed set
saiganakato Jun 21, 2026
d6633da
Merge branch 'main' into claude/dreamy-brattain-c0180a
saiganakato Jun 21, 2026
f2ef0b1
test: lock the baseline lifecycle across a real edit cycle
saiganakato Jun 21, 2026
e8e4625
Merge branch 'main' into claude/dreamy-brattain-c0180a
saiganakato Jun 21, 2026
ab19716
fix: borrowed-analyzer schema drift degrades to parse-failure, not a …
saiganakato Jun 21, 2026
e0a2971
Merge branch 'main' into claude/dreamy-brattain-c0180a
saiganakato Jun 21, 2026
0c925df
feat: surface the non-exhaustiveness disclosure in the human PR summary
saiganakato Jun 21, 2026
a3f79c1
Merge branch 'main' into claude/dreamy-brattain-c0180a
saiganakato Jun 21, 2026
1275d5c
feat: aci emit-baseline — generate an operations baseline from a scan…
saiganakato Jun 21, 2026
b512302
Merge branch 'main' into claude/dreamy-brattain-c0180a
saiganakato Jun 21, 2026
7863025
fix: stop suppressing native signals ruff doesn't actually emit (dogf…
saiganakato Jun 21, 2026
942c3ac
Merge branch 'main' into claude/dreamy-brattain-c0180a
saiganakato Jun 21, 2026
1a3bfee
refactor: extract the report helpers ACI flagged as duplicated in its…
saiganakato Jun 21, 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
32 changes: 8 additions & 24 deletions shared/python/aci_annotations.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,18 @@
"""GitHub Actions workflow-command annotation emitter for ACI scan reports."""
from __future__ import annotations

from typing import cast

try:
from .aci_findings import SEVERITY_CRITICAL, SEVERITY_HIGH, SEVERITY_MEDIUM, SEVERITY_LOW
from .aci_scan import SCOPE_CLASS_RUNTIME_SOURCE, _classify_relative_path
from .aci_report_helpers import (
gate_scope_classes as _gate_scope_classes,
scope_class as _scope_class,
)
except ImportError: # pragma: no cover - direct script/module import path
from aci_findings import SEVERITY_CRITICAL, SEVERITY_HIGH, SEVERITY_MEDIUM, SEVERITY_LOW
from aci_scan import SCOPE_CLASS_RUNTIME_SOURCE, _classify_relative_path
from aci_report_helpers import ( # type: ignore[no-redef]
gate_scope_classes as _gate_scope_classes,
scope_class as _scope_class,
)


_SEVERITY_TO_LEVEL: dict[str, str] = {
Expand All @@ -21,26 +25,6 @@
}


def _report_map(value: object) -> dict[str, object]:
return cast(dict[str, object], value) if isinstance(value, dict) else {}


def _gate_scope_classes(report: dict[str, object]) -> tuple[str, ...]:
scope_rules = _report_map(report.get("scope_rules"))
raw = scope_rules.get("gate_scope_classes")
if not isinstance(raw, list) or not raw:
return (SCOPE_CLASS_RUNTIME_SOURCE,)
values = tuple(str(item) for item in raw if isinstance(item, str) and item)
return values or (SCOPE_CLASS_RUNTIME_SOURCE,)


def _scope_class(finding: dict[str, object]) -> str:
explicit = finding.get("scope_class")
if isinstance(explicit, str) and explicit:
return explicit
return _classify_relative_path(str(finding.get("target_file") or ""))


def _encode_param(value: str) -> str:
"""Percent-encode characters that break GitHub Actions workflow command parsing."""
return (
Expand Down
9 changes: 4 additions & 5 deletions shared/python/aci_github_summary.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,10 @@
"""GitHub-friendly markdown summary emitter for ACI reports."""
from __future__ import annotations

from typing import cast


def _report_map(value: object) -> dict[str, object]:
return cast(dict[str, object], value) if isinstance(value, dict) else {}
try:
from .aci_report_helpers import report_map as _report_map
except ImportError: # pragma: no cover - direct script/module import path
from aci_report_helpers import report_map as _report_map # type: ignore[no-redef]


def build_github_summary_markdown(report: dict[str, object]) -> str:
Expand Down
41 changes: 41 additions & 0 deletions shared/python/aci_report_helpers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""Shared report-reading helpers for the emit/view surfaces.

These three helpers were copy-pasted, byte-identical, across the SARIF,
annotations, GitHub-summary, and report-view emitters. ACI's own CI-05
(copy-paste) detector flagged the duplication on a self-scan; this module is the
shared abstraction it asked for. Each emitter imports these (aliased to its
former private names) instead of redefining them.
"""
from __future__ import annotations

from typing import cast

try:
from .aci_scan import SCOPE_CLASS_RUNTIME_SOURCE, _classify_relative_path
except ImportError: # pragma: no cover - direct script/module import path
from aci_scan import SCOPE_CLASS_RUNTIME_SOURCE, _classify_relative_path # type: ignore[no-redef]


def report_map(value: object) -> dict[str, object]:
"""Coerce an arbitrary report value to a dict, or {} if it is not one."""
return cast(dict[str, object], value) if isinstance(value, dict) else {}


def gate_scope_classes(report: dict[str, object]) -> tuple[str, ...]:
"""The report's gate scope classes, defaulting to runtime-source."""
scope_rules = report_map(report.get("scope_rules"))
raw = scope_rules.get("gate_scope_classes")
if not isinstance(raw, list) or not raw:
return (SCOPE_CLASS_RUNTIME_SOURCE,)
values = tuple(str(item) for item in raw if isinstance(item, str) and item)
return values or (SCOPE_CLASS_RUNTIME_SOURCE,)


def scope_class(finding: dict[str, object]) -> str:
"""A finding's explicit scope_class, else one derived from its target file."""
explicit = finding.get("scope_class")
if isinstance(explicit, str) and explicit:
return explicit
return _classify_relative_path(str(finding.get("target_file") or ""))
18 changes: 2 additions & 16 deletions shared/python/aci_report_view.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
SCOPE_CLASS_TESTS,
_classify_relative_path,
)
from .aci_report_helpers import report_map as _report_map, gate_scope_classes as _gate_scope_classes
except ImportError: # pragma: no cover - direct script/module import path
from aci_findings import ( # type: ignore[no-redef]
LANE_EXTERNAL_ANALYZER,
Expand All @@ -48,6 +49,7 @@
SCOPE_CLASS_TESTS,
_classify_relative_path,
)
from aci_report_helpers import report_map as _report_map, gate_scope_classes as _gate_scope_classes # type: ignore[no-redef]


SUPPORTED_REPORT_SCOPE_CLASSES: tuple[str, ...] = (
Expand Down Expand Up @@ -82,10 +84,6 @@
}


def _report_map(value: object) -> dict[str, object]:
return cast(dict[str, object], value) if isinstance(value, dict) else {}


def _report_rows(value: object) -> list[dict[str, object]]:
if not isinstance(value, list):
return []
Expand Down Expand Up @@ -155,18 +153,6 @@ def _top_counts(values: list[str], *, limit: int = 5) -> list[dict[str, object]]
return [{"name": name, "count": count} for name, count in counter.most_common(limit)]


def _gate_scope_classes(report: dict[str, object]) -> tuple[str, ...]:
scope_rules = _report_map(report.get("scope_rules"))
gate_scope_classes = scope_rules.get("gate_scope_classes")
if not isinstance(gate_scope_classes, list) or not gate_scope_classes:
return (SCOPE_CLASS_RUNTIME_SOURCE,)
return tuple(
str(item)
for item in gate_scope_classes
if isinstance(item, str) and item
) or (SCOPE_CLASS_RUNTIME_SOURCE,)


def _filter_findings(
findings: list[dict[str, object]],
scope_classes: tuple[str, ...],
Expand Down
24 changes: 2 additions & 22 deletions shared/python/aci_sarif.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@

try:
from .aci_findings import SEVERITY_CRITICAL, SEVERITY_HIGH, SEVERITY_MEDIUM, SEVERITY_LOW
from .aci_scan import SCOPE_CLASS_RUNTIME_SOURCE, _classify_relative_path
from .aci_report_helpers import gate_scope_classes as _gate_scope_classes, scope_class as _scope_class
except ImportError: # pragma: no cover - direct script/module import path
from aci_findings import SEVERITY_CRITICAL, SEVERITY_HIGH, SEVERITY_MEDIUM, SEVERITY_LOW
from aci_scan import SCOPE_CLASS_RUNTIME_SOURCE, _classify_relative_path
from aci_report_helpers import gate_scope_classes as _gate_scope_classes, scope_class as _scope_class # type: ignore[no-redef]


SEVERITY_TO_LEVEL = {
Expand All @@ -21,26 +21,6 @@
}


def _report_map(value: object) -> dict[str, object]:
return cast(dict[str, object], value) if isinstance(value, dict) else {}


def _gate_scope_classes(report: dict[str, object]) -> tuple[str, ...]:
scope_rules = _report_map(report.get("scope_rules"))
raw = scope_rules.get("gate_scope_classes")
if not isinstance(raw, list) or not raw:
return (SCOPE_CLASS_RUNTIME_SOURCE,)
values = tuple(str(item) for item in raw if isinstance(item, str) and item)
return values or (SCOPE_CLASS_RUNTIME_SOURCE,)


def _scope_class(finding: dict[str, object]) -> str:
explicit = finding.get("scope_class")
if isinstance(explicit, str) and explicit:
return explicit
return _classify_relative_path(str(finding.get("target_file") or ""))


def build_sarif_report(report: dict[str, object]) -> dict[str, object]:
raw_findings = report.get("findings") or []
findings: list[dict[str, object]] = raw_findings if isinstance(raw_findings, list) else []
Expand Down
Loading