Skip to content
Open
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ run_pr_ready_path_validations() {
files="$tmp_root/range-files.z"
write_range_files "$files"

local control_plane_paths_pattern='^(Scripts/conductor\.py|Scripts/guardrails\.sh|Scripts/test_conductor_(lifecycle|output)\.py|Scripts/test_contribution_preflight\.py|\.agents/skills/rpce-contribution-check/scripts/preflight\.sh|Makefile)$'
local control_plane_paths_pattern='^(Scripts/conductor\.py|Scripts/conductor_diagnostics\.py|Scripts/guardrails\.sh|Scripts/test_conductor_(lifecycle|output|diagnostics|high_output)\.py|Scripts/test_contribution_preflight\.py|\.agents/skills/rpce-contribution-check/scripts/preflight\.sh|Makefile)$'
local ci_app_test_runner_paths_pattern='^(Scripts/ci_app_test_runner\.py|Scripts/test_ci_app_test_runner\.py|\.github/workflows/ci\.yml)$'
local swift_paths_pattern='\.swift$'
local root_test_paths_pattern='^(Sources/RepoPrompt/|Tests/RepoPrompt[^/]*Tests/)'
Expand Down
2 changes: 2 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,8 @@ conductor-selftest:
python3 Scripts/test_contribution_preflight.py
python3 Scripts/test_ci_app_test_runner.py
python3 Scripts/test_conductor_output.py
python3 Scripts/test_conductor_diagnostics.py
python3 Scripts/test_conductor_high_output.py
python3 Scripts/test_agent_mode_file_tools_benchmark.py
python3 Scripts/test_conductor_lifecycle.py
python3 Scripts/test_local_production_installer.py
Expand Down
53 changes: 50 additions & 3 deletions Scripts/conductor.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@
LANE_NAMES = {"build", "debugArtifact", "liveApp", "release", "style"}
LOG_TAIL_LINES = 30
BUILD_CACHE_DIAGNOSTIC_MAX_ROWS = 12
SUMMARY_VERSION = 1
SUMMARY_VERSION = 2
SUMMARY_SUCCESS_MAX_LINES = 25
SUMMARY_FAILURE_MAX_LINES = 100
SUMMARY_MAX_CHARS = 16000
Expand Down Expand Up @@ -148,6 +148,8 @@
(without --launch/--packaged-app, requires the CE debug app to already be running and CLI installed)
./conductor diagnostics agent-mode-on [--log-file <path>]
./conductor diagnostics build-cache [--limit <n>]
./conductor diagnostics focused-build [--product <name>] [--test] [--filter <filter>]
./conductor diagnostics high-output [--lines <n>] [--warnings <n>] [--exit-code <n>] [--linger <s>]
./conductor release preflight|artifact|package|local-install

Foundation validation operation:
Expand Down Expand Up @@ -794,7 +796,7 @@ class OutputSummarizer:
re.IGNORECASE,
)
SWIFT_ERROR_RE = re.compile(r"(: error:|error: emit-module command failed|Command SwiftCompile failed|Command CompileSwift failed|fatal error:)")
WARNING_RE = re.compile(r"(: warning:|^WARNING:)")
WARNING_RE = re.compile(r"(: warning:|^WARNING:)", re.IGNORECASE)
TEST_FAILURE_RE = re.compile(
r"(Test Case '.*' failed|XCTAssert|: error: .*Test|Executed .* tests?, with .* failures?|Failing tests:|error: Exited with unexpected signal|error: terminated)"
)
Expand Down Expand Up @@ -838,6 +840,7 @@ def summarize_lines(
lines_iterable: Any,
) -> Dict[str, Any]:
del args
summary_start = now()
failure = state in {"failed", "canceled"} or bool(timed_out) or (exit_code not in (None, 0))
launch_lifecycle = {
"transitionStarted": False,
Expand Down Expand Up @@ -885,7 +888,7 @@ def summarize_lines(

if cls.WARNING_RE.search(line):
warning_count += 1
if failure or line.startswith("WARNING:"):
if failure or cls.WARNING_RE.match(line):
sections["Warnings"].add(line)
if cls.SWIFT_ERROR_RE.search(line) or cls.FAILURE_RE.search(line):
error_count += 1
Expand Down Expand Up @@ -993,6 +996,7 @@ def summarize_lines(
"omittedLineCount": omitted_line_count,
"errorCount": error_count,
"warningCount": warning_count,
"summaryDurationSeconds": round(now() - summary_start, 6),
"launchLifecycle": launch_lifecycle,
"sections": payload_sections,
"truncated": truncated,
Expand Down Expand Up @@ -1022,6 +1026,7 @@ def _minimal_summary(cls, operation: str, state: str, exit_code: Optional[int],
"omittedLineCount": 0,
"errorCount": 0,
"warningCount": 0,
"summaryDurationSeconds": 0.0,
"sections": [
{
"title": "Summary notes",
Expand Down Expand Up @@ -1061,6 +1066,8 @@ def operation_requires_global_heavy_slot(operation: str, args: Dict[str, Any]) -
return True
if operation == "release" and args.get("subcommand") in {"artifact", "package", "local-install"}:
return True
if operation == "diagnostics" and args.get("subcommand") == "focused-build":
return True
return False


Expand Down Expand Up @@ -1410,6 +1417,10 @@ def prepare(self, request: Dict[str, Any]) -> Tuple[List[str], List[str], Path,
return self._internal_argv("diagnostics_agent_mode_on", dict(args)), ["debugArtifact", "liveApp"], cwd, env, effective_timeout
if subcommand == "build-cache":
return self._internal_argv("diagnostics_build_cache", dict(args)), lanes, cwd, env, effective_timeout
if subcommand == "focused-build":
return self._internal_argv("diagnostics_focused_build", dict(args)), ["build"], cwd, env, effective_timeout
if subcommand == "high-output":
return self._internal_argv("diagnostics_high_output", dict(args)), lanes, cwd, env, effective_timeout
if operation == "release":
subcommand = args.get("subcommand")
if subcommand == "package":
Expand Down Expand Up @@ -4512,6 +4523,10 @@ def run_operation_runner(payload_json: str) -> int:
return operation_diagnostics_agent_mode_on(repo_root, args)
if kind == "diagnostics_build_cache":
return operation_diagnostics_build_cache(repo_root, args)
if kind == "diagnostics_focused_build" or kind == "diagnostics_high_output":
import conductor_diagnostics

return conductor_diagnostics.run_diagnostic(kind, repo_root, args)
if kind == "release_preflight_missing":
return operation_release_preflight_missing(repo_root)
print(f"unknown internal operation runner kind: {kind}", file=sys.stderr)
Expand Down Expand Up @@ -4682,6 +4697,17 @@ def handle_real_operation(paths: Paths, operation: str, argv: List[str]) -> int:
build_cache = subparsers.add_parser("build-cache")
build_cache.add_argument("--limit", type=int, default=BUILD_CACHE_DIAGNOSTIC_MAX_ROWS)

focused_build = subparsers.add_parser("focused-build")
focused_build.add_argument("--product", default="RepoPrompt")
focused_build.add_argument("--test", action="store_true")
focused_build.add_argument("--filter")

high_output = subparsers.add_parser("high-output")
high_output.add_argument("--lines", type=int, default=1000)
high_output.add_argument("--warnings", type=int, default=0)
high_output.add_argument("--exit-code", type=int, default=0)
high_output.add_argument("--linger", type=float, default=0.0)

ns = parser.parse_args(rest)
args["subcommand"] = ns.subcommand
if ns.subcommand == "agent-mode-on":
Expand All @@ -4690,6 +4716,27 @@ def handle_real_operation(paths: Paths, operation: str, argv: List[str]) -> int:
if ns.limit <= 0:
raise ConductorError("diagnostics build-cache --limit must be greater than zero")
args["limit"] = ns.limit
elif ns.subcommand == "focused-build":
args.update({
"product": ns.product,
"runTests": ns.test or bool(ns.filter),
"testFilter": ns.filter,
})
elif ns.subcommand == "high-output":
if ns.lines < 0:
raise ConductorError("diagnostics high-output --lines must be non-negative")
if ns.warnings < 0:
raise ConductorError("diagnostics high-output --warnings must be non-negative")
if ns.exit_code < 0 or ns.exit_code > 255:
raise ConductorError("diagnostics high-output --exit-code must be 0-255")
if ns.linger < 0:
raise ConductorError("diagnostics high-output --linger must be non-negative")
args.update({
"lines": ns.lines,
"warnings": ns.warnings,
"exitCode": ns.exit_code,
"linger": ns.linger,
})
elif operation == "release":
parser = argparse.ArgumentParser(prog="conductor release")
parser.add_argument("subcommand", choices=["preflight", "artifact", "package", "local-install"])
Expand Down
Loading
Loading