Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ this file. The format follows Keep a Changelog, and versioned releases follow
Semantic Versioning where the repository publishes a release.

## [Unreleased]
- Review summaries now report test and documentation coverage separately and
consistently. Open the summary to confirm both values before merging.
- Route Strix cross-provider fallbacks to explicit direct-OpenAI models
(`openai-direct/...`) through the OpenAI inference endpoint instead of
inheriting a provider-specific primary base: the workflow now provisions
Expand Down
45 changes: 20 additions & 25 deletions scripts/ci/opencode_review_normalize_output.py
Original file line number Diff line number Diff line change
Expand Up @@ -133,9 +133,14 @@
"security/privacy:",
)

APPROVAL_VERIFICATION_PATTERNS = {
label: re.compile(re.escape(label)) for label in APPROVAL_VERIFICATION_LABELS
}
# Match the longest label first so a future label cannot shadow a more specific
# label that starts at the same position (for example, docstring coverage:).
ANY_LABEL_PATTERN = re.compile(
"|".join(
re.escape(label)
for label in sorted(APPROVAL_VERIFICATION_LABELS, key=len, reverse=True)
)
)

SOURCE_LIKE_CHANGED_FILE_EXTENSIONS = frozenset(
{
Expand Down Expand Up @@ -959,32 +964,22 @@ 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]:
"""Return exact verification-label starts without suffix collisions."""
starts = []
pattern = APPROVAL_VERIFICATION_PATTERNS.get(candidate)
if pattern is None:
pattern = re.compile(re.escape(candidate))
for match in pattern.finditer(text):
index = match.start()
if (
candidate == "coverage:"
and text[max(0, index - 10) : index] == "docstring "
):
continue
starts.append(index)
return starts

starts = label_starts(label)
actual_matches = [
(match.start(), match.group(0)) for match in ANY_LABEL_PATTERN.finditer(text)
]
if label in APPROVAL_VERIFICATION_LABELS:
starts = [index for index, candidate in actual_matches if candidate == label]
else:
# Preserve repository-specific labels without rescanning catalogue labels.
starts = [match.start() for match in re.finditer(re.escape(label), text)]
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
index
for index, candidate in actual_matches
if candidate != label and index >= start
]
end = min(next_starts) if next_starts else len(text)
return text[start:end]
Comment thread
seonghobae marked this conversation as resolved.
Comment thread
seonghobae marked this conversation as resolved.
Expand Down
21 changes: 21 additions & 0 deletions tests/test_opencode_review_normalize_output.py
Original file line number Diff line number Diff line change
Expand Up @@ -1386,6 +1386,7 @@ def test_label_and_full_coverage_detection(tmp_path, monkeypatch):
assert not norm.mentions_full_coverage("", no_source_summary)
assert norm.contradicts_changed_file_kinds("", no_source_summary)


changed_files = tmp_path / "opencode-changed-files.txt"
changed_files.write_text("README.md\n", encoding="utf-8")
monkeypatch.setenv("OPENCODE_CHANGED_FILES_FILE", str(changed_files))
Expand Down Expand Up @@ -1434,6 +1435,26 @@ def test_label_and_full_coverage_detection(tmp_path, monkeypatch):
)


def test_label_section_scans_labels_once_and_prefers_longest_label():
"""Parse adjacent labels without rescanning the input for every label."""
text = "docstring coverage: 100% coverage: 98% performance: measured"

assert norm.label_section(text, "docstring coverage:") == " 100% "
assert norm.label_section(text, "coverage:") == " 98% "
assert norm.label_section(text, "performance:") == " measured"
alternatives = norm.ANY_LABEL_PATTERN.pattern.split("|")
assert alternatives.index(re.escape("docstring coverage:")) < alternatives.index(
re.escape("coverage:")
)


def test_label_section_preserves_custom_label_lookup():
"""Repository-specific labels retain the helper's backwards-compatible path."""
text = "custom evidence: measured coverage: 98%"

assert norm.label_section(text, "custom evidence:") == " measured "


def test_check_structural_approval_rejects_invalid_or_unsafe_approvals(
tmp_path, monkeypatch
):
Expand Down
Loading