diff --git a/.agents/rules/cc.md b/.agents/rules/cc.md index 5f2c2b43c2..c903a05e3c 100644 --- a/.agents/rules/cc.md +++ b/.agents/rules/cc.md @@ -1,3 +1,8 @@ +--- +trigger: model_decision +description: C/C++ rules design and Bazel rules_cc integration invariants +--- + # C/C++ Rules Design & Bazel rules_cc Integration ## Concise `cc_shared_library` Interface & Export Rules diff --git a/.agents/rules/docs.md b/.agents/rules/docs.md index e463527a8d..ab9318c7f9 100644 --- a/.agents/rules/docs.md +++ b/.agents/rules/docs.md @@ -14,6 +14,11 @@ globs: "docs/**,RELEASING.md" * **API Docstrings vs. Narrative Docs**: Keep `.bzl` docstrings brief (purpose and arguments). Put setup guides and multi-scenario examples in `docs/`, and link to them with `{ref}` or `{obj}` instead of repeating rules. +* **Bidirectional Alias Cross-References**: When documenting public `alias` + targets alongside a canonical target, cross-link in both directions: + reference the canonical target from each alias entry and list the aliases on + the canonical `{bzl:target}` entry (use `{obj}` for documented in-repo + targets and inline code for generated external-repo labels). * **How-to Guides (`docs/howto/`)**: * Prefer adding sections to an existing topical guide (e.g. `docs/howto/build-a-wheel.md`) over creating a separate granular file. diff --git a/.agents/rules/starlark.md b/.agents/rules/starlark.md index e4becec282..167a9081bc 100644 --- a/.agents/rules/starlark.md +++ b/.agents/rules/starlark.md @@ -42,6 +42,17 @@ globs: "*.bzl,BUILD,BUILD.bazel,*.bazel" `allow_single_file = True`, when the attribute may accept `py_binary` (whose `DefaultInfo.files` has multiple files). +## Forwarding Executables in `executable = True` Rules +* When an `executable = True` rule forwards an underlying executable target + (from an attribute or resolved toolchain): + * Declare the output preserving `target_executable.extension` (e.g., `.exe` + on Windows) and materialize it with `ctx.actions.symlink(output = out, + target_file = target_executable, is_executable = True)`. + * Set `files = depset([out])`, and merge + `ctx.runfiles(files = [target_executable])` with the underlying target's + `default_runfiles` in `DefaultInfo(files = depset([out]), executable = out, + runfiles = ...)`. + ## native.test_suite API * Don't forward target `tags` to `native.test_suite`; tags on test suites filter tests instead of setting target execution behavior. diff --git a/.agents/rules/testing.md b/.agents/rules/testing.md index 21a0191aa6..59d3e227c6 100644 --- a/.agents/rules/testing.md +++ b/.agents/rules/testing.md @@ -1,3 +1,8 @@ +--- +trigger: model_decision +description: Bazel test execution, integration test flags, and lockfiles +--- + # Testing & Validation Guardrails ## `--config=fast-tests` for Test Targets diff --git a/.agents/rules/windows.md b/.agents/rules/windows.md index 271b5c6c63..ce8d0e68c0 100644 --- a/.agents/rules/windows.md +++ b/.agents/rules/windows.md @@ -1,3 +1,8 @@ +--- +trigger: model_decision +description: Windows MSVC linking, ABI tags, MAX_PATH, and .exe portability +--- + # Windows MSVC Toolchains & Linking ## MSVC `#pragma comment(lib, ...)` Embedded References @@ -47,3 +52,6 @@ * **RECORD File Paths**: In `RECORD` files, append `.bat` only to the shebang-rewritten scripts. Leave all other script paths unchanged. +## CLI Help & Binary Name Output in Tests +* Allow optional `.exe` suffixes when matching binary names in CLI output + assertions (e.g., `r"Usage: tool(\.exe)?\b"`). diff --git a/.agents/skills/merge-pr/SKILL.md b/.agents/skills/merge-pr/SKILL.md index 96304d1244..1939d711ee 100644 --- a/.agents/skills/merge-pr/SKILL.md +++ b/.agents/skills/merge-pr/SKILL.md @@ -19,6 +19,10 @@ this PR", or monitor its merge): `gh pr merge`; it fails when a merge queue is enabled on the repository. 2. **Invoke a Background Shepherd**: Launch a background subagent with the role `Merge PR Shepherd` to continuously watch the PR until it merges. + - If a `monitor_remote_ci.py ` background task is currently + running in the parent conversation, stop it via `manage_task` first so + `Merge PR Shepherd` can acquire `.monitored_pr_.lock` and + receive CI failure notifications directly. 3. **Leverage Existing CI Skills**: - Have the subagent use the **`monitor-ci-results`** skill to watch for CI check failures and generate analysis reports. diff --git a/.agents/skills/monitor-ci-results/SKILL.md b/.agents/skills/monitor-ci-results/SKILL.md index c92bdda027..c73295ed70 100644 --- a/.agents/skills/monitor-ci-results/SKILL.md +++ b/.agents/skills/monitor-ci-results/SKILL.md @@ -44,10 +44,15 @@ or when monitoring CI after PR updates: with errors, `monitor_remote_ci.py` dispatches a high-priority notification message reporting the failed check back to your conversation. - Soft failures (e.g. `*rolling*` Bazel) are non-blocking warnings; ignore. + - If `blocks-do-not-merge` fails while the PR intentionally carries the + `"do not merge"` label, treat it as an expected merge gate rather than a + code failure. 4. **Subagent Analysis**: Upon receiving a failure notification message from the monitoring script, immediately launch a separate subagent using the `invoke_subagent` tool with the role "CI Failure Analyzer" to run the - `analyze-ci-failure` skill on the reported failure. + `analyze-ci-failure` skill on the reported failure (instructing the + subagent to pass its own subagent conversation ID to + `analyze_ci_failure.py` so only its completion message wakes the parent). 5. **Autonomous Flake Retry**: If the CI Failure Analyzer subagent confirms that the failure is a transient infrastructure or network flake (e.g. disk I/O error, 504 gateway, sandbox initialization failure, or `setup-bazel` diff --git a/.agents/skills/monitor-ci-results/scripts/monitor_remote_ci.py b/.agents/skills/monitor-ci-results/scripts/monitor_remote_ci.py index e8d3a02809..15bc5c3d37 100755 --- a/.agents/skills/monitor-ci-results/scripts/monitor_remote_ci.py +++ b/.agents/skills/monitor-ci-results/scripts/monitor_remote_ci.py @@ -8,6 +8,7 @@ import subprocess import sys import time +import traceback import urllib.request @@ -39,6 +40,29 @@ def get_pr_checks(pr_number): return [] +def _has_do_not_merge_label(pr_number): + cmd = ["gh", "pr", "view", str(pr_number), "--json", "labels"] + try: + res = subprocess.run(cmd, capture_output=True, text=True, check=True) + except subprocess.CalledProcessError as e: + e.add_note( + "==================== STDOUT BEGIN ====================\n" + f"{e.stdout or ''}" + "==================== STDOUT END ====================\n" + "==================== STDERR BEGIN ====================\n" + f"{e.stderr or ''}" + "==================== STDERR END ====================" + ) + raise + out = res.stdout + json_str = out[out.find("{") :] if "{" in out else out + data = json.loads(json_str) + return any( + label.get("name", "").lower() == "do not merge" + for label in data.get("labels", []) + ) + + def get_buildkite_jobs(build_url): base_url = build_url.split("#")[0] if base_url.endswith(".json"): @@ -329,7 +353,29 @@ def main(): ): job_id = link.split("/")[-1].split("?")[0] if "/" in link else link gh_key = f"gh_{job_id}" if job_id else name - if gh_key not in monitored: + if gh_key in monitored: + continue + skip_expected_dnm = False + if name == "blocks-do-not-merge": + try: + skip_expected_dnm = _has_do_not_merge_label(args.pr) + except ( + OSError, + subprocess.CalledProcessError, + json.JSONDecodeError, + ) as e: + details = "".join(traceback.format_exception_only(e)).strip() + print( + f"⚠️ Error fetching PR labels: {details}", + file=sys.stderr, + ) + continue + if skip_expected_dnm: + print( + "ℹ️ Skipping expected 'blocks-do-not-merge' failure " + "while 'do not merge' label is present." + ) + else: print(f"🚨 Notifying failure for GitHub check '{name}'...") msg = ( f"⚠️ Remote CI GitHub Check '{name}' completed with errors!\n\n" @@ -347,9 +393,9 @@ def main(): msg, ] ) - monitored[gh_key] = time.time() - with open(state_file, "w") as f: - json.dump(monitored, f) + monitored[gh_key] = time.time() + with open(state_file, "w") as f: + json.dump(monitored, f) time.sleep(args.interval)