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
5 changes: 5 additions & 0 deletions .agents/rules/cc.md
Original file line number Diff line number Diff line change
@@ -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
Expand Down
5 changes: 5 additions & 0 deletions .agents/rules/docs.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
11 changes: 11 additions & 0 deletions .agents/rules/starlark.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
5 changes: 5 additions & 0 deletions .agents/rules/testing.md
Original file line number Diff line number Diff line change
@@ -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
Expand Down
8 changes: 8 additions & 0 deletions .agents/rules/windows.md
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -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"`).
4 changes: 4 additions & 0 deletions .agents/skills/merge-pr/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -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 <pr_number>` background task is currently
running in the parent conversation, stop it via `manage_task` first so
`Merge PR Shepherd` can acquire `.monitored_pr_<pr_number>.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.
Expand Down
7 changes: 6 additions & 1 deletion .agents/skills/monitor-ci-results/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -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`
Expand Down
54 changes: 50 additions & 4 deletions .agents/skills/monitor-ci-results/scripts/monitor_remote_ci.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import subprocess
import sys
import time
import traceback
import urllib.request


Expand Down Expand Up @@ -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"):
Expand Down Expand Up @@ -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"
Expand All @@ -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)

Expand Down
Loading