Skip to content
Merged
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
33 changes: 28 additions & 5 deletions .github/scripts/check_spec_failures.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
COMPLETENESS_VERDICT - Verdict from completeness check
TRACE_INFRA_FAILURE - Whether trace failure was infrastructure-related
COMPLETENESS_INFRA_FAILURE - Whether completeness failure was infrastructure-related
TRACE_FINDINGS - Findings text from traceability check
COMPLETENESS_FINDINGS - Findings text from completeness check
GITHUB_WORKSPACE - Workspace root (for package imports)
"""

Expand All @@ -24,9 +26,18 @@
from scripts.ai_review_common import spec_validation_failed # noqa: E402


def _is_infra_failure(flag: str) -> bool:
"""Return True if the infrastructure failure flag is set."""
return flag.lower() in ("true", "1", "yes")
def _is_infra_failure(flag: str, findings: str = "") -> bool:
"""Return True if the failure is infrastructure-related.

Checks the explicit flag first. Falls back to detecting infrastructure
failure keywords in the findings text, which handles cases where the
composite action output does not propagate correctly.
"""
if flag.lower() in ("true", "1", "yes"):
return True
if findings and "infrastructure failure" in findings.lower():
return True
return False


def build_parser() -> argparse.ArgumentParser:
Expand Down Expand Up @@ -54,6 +65,16 @@ def build_parser() -> argparse.ArgumentParser:
default=os.environ.get("COMPLETENESS_INFRA_FAILURE", ""),
help="Whether completeness failure was infrastructure-related",
)
parser.add_argument(
"--trace-findings",
default=os.environ.get("TRACE_FINDINGS", ""),
help="Findings text from traceability check",
)
parser.add_argument(
"--completeness-findings",
default=os.environ.get("COMPLETENESS_FINDINGS", ""),
help="Findings text from completeness check",
)
return parser


Expand All @@ -62,8 +83,10 @@ def main(argv: list[str] | None = None) -> int:
trace: str = args.trace_verdict
completeness: str = args.completeness_verdict

trace_infra = _is_infra_failure(args.trace_infra_failure)
completeness_infra = _is_infra_failure(args.completeness_infra_failure)
trace_infra = _is_infra_failure(args.trace_infra_failure, args.trace_findings)
completeness_infra = _is_infra_failure(
args.completeness_infra_failure, args.completeness_findings
)

if trace_infra and completeness_infra:
print(
Expand Down
12 changes: 12 additions & 0 deletions .github/workflows/ai-session-protocol.yml
Original file line number Diff line number Diff line change
Expand Up @@ -296,6 +296,18 @@ jobs:
id: validate-claims
run: python3 .github/scripts/validate_investigation_claims.py

# Pass-through job: satisfies required "Aggregate Results" check when path
# filter skips the real aggregate job. GitHub branch protection requires
# SUCCESS (not SKIPPED) for required checks. See issue #1168.

aggregate-skip:
name: Aggregate Results
Copy link

Copilot AI Feb 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Two jobs in the workflow have the same name "Aggregate Results" (aggregate-skip at line 304 and aggregate at line 314). GitHub Actions uses job names in the UI and for branch protection rules. Having duplicate job names can cause confusion and may lead to issues with branch protection rule matching. The aggregate-skip job should have a distinct name like "Aggregate Results (Skip)" to differentiate it from the actual aggregate job.

Suggested change
name: Aggregate Results
name: Aggregate Results (Skip)

Copilot uses AI. Check for mistakes.
runs-on: ubuntu-24.04-arm
needs: [detect-changes]
if: always() && needs.detect-changes.result == 'success' && needs.detect-changes.outputs.has_sessions != 'true'
steps:
- run: echo "Skipped - no session file changes detected"

# Aggregate results and post comment

aggregate:
Expand Down
2 changes: 2 additions & 0 deletions .github/workflows/ai-spec-validation.yml
Original file line number Diff line number Diff line change
Expand Up @@ -320,4 +320,6 @@ jobs:
COMPLETENESS_VERDICT: ${{ steps.completeness.outputs.verdict }}
TRACE_INFRA_FAILURE: ${{ steps.trace.outputs['infrastructure-failure'] }}
COMPLETENESS_INFRA_FAILURE: ${{ steps.completeness.outputs['infrastructure-failure'] }}
TRACE_FINDINGS: ${{ steps.trace.outputs.findings }}
COMPLETENESS_FINDINGS: ${{ steps.completeness.outputs.findings }}
run: python3 .github/scripts/check_spec_failures.py
13 changes: 13 additions & 0 deletions .serena/project.yml
Original file line number Diff line number Diff line change
Expand Up @@ -107,3 +107,16 @@ default_modes:
# fixed set of tools to use as the base tool set (if non-empty), replacing Serena's default set of tools.
# This cannot be combined with non-empty excluded_tools or included_optional_tools.
fixed_tools: []

# time budget (seconds) per tool call for the retrieval of additional symbol information
# such as docstrings or parameter information.
# This overrides the corresponding setting in the global configuration; see the documentation there.
# If null or missing, use the setting from the global configuration.
symbol_info_budget:

# The language backend to use for this project.
# If not set, the global setting from serena_config.yml is used.
# Valid values: LSP, JetBrains
# Note: the backend is fixed at startup. If a project with a different backend
# is activated post-init, an error will be returned.
language_backend:
Comment on lines +110 to +122
Copy link

Copilot AI Feb 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This PR includes several changes that are not mentioned in the PR description or related to parallel workflow execution:

  1. Changes to scripts/detect_hook_bypass.py (merge commit filtering)
  2. Changes to .github/scripts/check_spec_failures.py (infrastructure failure detection via findings text)
  3. Changes to .github/workflows/ai-spec-validation.yml (passing findings to script)
  4. Changes to .github/workflows/ai-session-protocol.yml (adding aggregate-skip job)
  5. Changes to .serena/project.yml (adding symbol_info_budget and language_backend config)
  6. Changes to tests/test_check_spec_failures.py (new tests for infrastructure failure detection)

These appear to be unrelated bug fixes and configuration updates that should be in separate PRs for better traceability and easier review. Including unrelated changes makes it harder to understand the scope and risk of this PR, and makes it more difficult to bisect issues or revert specific changes if needed.

Copilot uses AI. Check for mistakes.
17 changes: 16 additions & 1 deletion scripts/detect_hook_bypass.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,18 @@

import argparse
import json
import re
import subprocess
import sys
from dataclasses import asdict, dataclass, field
from datetime import datetime, timezone
from pathlib import Path

# Matches squashed merge-resolution commits (single parent, merge-like subject)
_MERGE_SUBJECT_RE = re.compile(
r"^Merge (branch|remote-tracking branch) '.+' into .+"
)


@dataclass
class BypassIndicator:
Expand Down Expand Up @@ -68,14 +74,21 @@ def get_current_branch() -> str:


def get_pr_commits(base_ref: str) -> list[tuple[str, str]]:
"""Get commits in the PR (since diverging from base).
"""Get non-merge commits in the PR (since diverging from base).

Skips merge commits because they integrate changes already validated
on their source branches. Also skips squashed merge-resolution commits
(single-parent commits with merge-like subjects) since they only
bring in base-branch changes. Only authored commits are checked for
hook bypass indicators.

Returns list of (sha, subject) tuples.
"""
result = subprocess.run(
[
"git",
"log",
"--no-merges",
f"{base_ref}..HEAD",
"--format=%H %s",
],
Expand All @@ -91,6 +104,8 @@ def get_pr_commits(base_ref: str) -> list[tuple[str, str]]:
if not line.strip():
continue
sha, _, subject = line.partition(" ")
if _MERGE_SUBJECT_RE.match(subject):
continue
commits.append((sha, subject))
return commits

Expand Down
23 changes: 21 additions & 2 deletions scripts/workflow/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
"""Workflow execution and chaining for agent pipelines."""
"""Workflow execution and chaining for agent pipelines.

Supports sequential chaining, parallel execution, and refinement loops.
"""

from scripts.workflow.coordinator import (
CentralizedStrategy,
Expand All @@ -10,6 +13,15 @@
find_ready_steps,
get_strategy,
)
from scripts.workflow.executor import WorkflowExecutor
from scripts.workflow.parallel import (
AggregationStrategy,
ParallelGroup,
ParallelStepExecutor,
can_parallelize,
identify_parallel_groups,
mark_parallel_steps,
)
from scripts.workflow.schema import (
CoordinationMode,
StepKind,
Expand All @@ -22,20 +34,27 @@
)

__all__ = [
"AggregationStrategy",
"CentralizedStrategy",
"CoordinationMode",
"CoordinationStrategy",
"CentralizedStrategy",
"HierarchicalStrategy",
Comment on lines +37 to 41
Copy link

Copilot AI Feb 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The __all__ list is not sorted alphabetically. In the added lines, "CentralizedStrategy" is placed after "AggregationStrategy" at line 38, but the comment in the diff shows it was originally before "CoordinationStrategy". The current order places "CentralizedStrategy" at line 38, "CoordinationMode" at line 39, then "CoordinationStrategy" at line 40. This breaks alphabetical ordering which appears to be the convention (based on the mostly-sorted nature of the rest of the list).

Copilot uses AI. Check for mistakes.
"MeshStrategy",
"ParallelGroup",
"ParallelStepExecutor",
"StepKind",
"StepRef",
"StepResult",
"WorkflowDefinition",
"WorkflowExecutor",
"WorkflowResult",
"WorkflowStatus",
"WorkflowStep",
"aggregate_subordinate_outputs",
"build_execution_plan",
"can_parallelize",
"find_ready_steps",
"get_strategy",
"identify_parallel_groups",
"mark_parallel_steps",
]
Loading
Loading