From 961966465431ea19ebce75ad9d918e2790f8e161 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Enrique=20Lo=CC=81pez=20Man=CC=83as?= Date: Thu, 29 Oct 2026 13:41:04 +0100 Subject: [PATCH 1/2] ci: fail pull requests that add agent leftovers Adds an Agent leftovers check that scans only what a pull request adds (diff lines, new file names, commit messages, title and body) for local paths, internal links and bug IDs, Google API keys, AI co-author trailers and agent session links. A line can opt out with "agent-leftovers: ignore". --- .github/scripts/check_agent_leftovers.py | 172 +++++++++++++++++++++++ .github/workflows/agent-leftovers.yml | 46 ++++++ 2 files changed, 218 insertions(+) create mode 100755 .github/scripts/check_agent_leftovers.py create mode 100644 .github/workflows/agent-leftovers.yml diff --git a/.github/scripts/check_agent_leftovers.py b/.github/scripts/check_agent_leftovers.py new file mode 100755 index 000000000..dba28286f --- /dev/null +++ b/.github/scripts/check_agent_leftovers.py @@ -0,0 +1,172 @@ +#!/usr/bin/env python3 +# +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Fail a pull request that carries leftovers from local or agent-assisted work. + +Only what the pull request adds is checked: added lines of the diff, the +names of added files, the messages of its commits, and its title and body. +Existing content on the base branch is never flagged. + +Things that are fine on the author's machine but wrong in a public repo: + + local paths file:// URLs into home or temp directories, and home + directories themselves (/Users/x/, /home/x/, + /usr/local/google/, C:\\Users\\x\\) + internal links go/ short links, b/ bug IDs, corp and googleplex hosts + secrets Google API keys + agent traces AI co-author trailers, links to agent chat sessions + local files agent settings meant to stay local, merge leftovers + +A line that legitimately needs one of these can opt out by containing +"agent-leftovers: ignore". + +Usage, from the repository root: + + BASE_SHA= [HEAD_SHA=] [PR_TITLE=...] [PR_BODY=...] \\ + check_agent_leftovers.py + +Findings are printed as GitHub Actions error annotations. +""" + +import os +import re +import subprocess +import sys + +IGNORE_MARKER = "agent-leftovers: ignore" + +# This script and its workflow describe the patterns, so they would match them. +SKIPPED_FILES = { + ".github/scripts/check_agent_leftovers.py", + ".github/workflows/agent-leftovers.yml", +} + +CONTENT_PATTERNS = [ + ("local file URL", re.compile(r"file:///(Users|home|usr/local/google|private/var|var/folders|[A-Za-z]:)")), + ("local path", re.compile(r"/usr/local/google/")), + ("local path", re.compile(r"(? Date: Thu, 29 Oct 2026 13:41:04 +0100 Subject: [PATCH 2/2] docs: share agent instructions and skills across coding agents Moves the skill to .agents/skills, with .claude/skills and .gemini/skills as symlinks, adds GEMINI.md importing AGENTS.md, and documents the setup in AGENTS.md together with pull request rules for scope, review threads and machine-specific content. --- .../skills/android-maps-compose/SKILL.md | 0 .claude/skills | 1 + .gemini/skills | 1 + .github/scripts/answer_issue.py | 2 +- .github/scripts/update_skill.py | 2 +- .github/workflows/release-rc.yml | 4 +-- AGENTS.md | 27 +++++++++++++++++++ GEMINI.md | 1 + release-please-config.json | 2 +- 9 files changed, 35 insertions(+), 5 deletions(-) rename {.gemini => .agents}/skills/android-maps-compose/SKILL.md (100%) create mode 120000 .claude/skills create mode 120000 .gemini/skills create mode 100644 GEMINI.md diff --git a/.gemini/skills/android-maps-compose/SKILL.md b/.agents/skills/android-maps-compose/SKILL.md similarity index 100% rename from .gemini/skills/android-maps-compose/SKILL.md rename to .agents/skills/android-maps-compose/SKILL.md diff --git a/.claude/skills b/.claude/skills new file mode 120000 index 000000000..2b7a412b8 --- /dev/null +++ b/.claude/skills @@ -0,0 +1 @@ +../.agents/skills \ No newline at end of file diff --git a/.gemini/skills b/.gemini/skills new file mode 120000 index 000000000..2b7a412b8 --- /dev/null +++ b/.gemini/skills @@ -0,0 +1 @@ +../.agents/skills \ No newline at end of file diff --git a/.github/scripts/answer_issue.py b/.github/scripts/answer_issue.py index a0afe17c5..9ea032d8a 100644 --- a/.github/scripts/answer_issue.py +++ b/.github/scripts/answer_issue.py @@ -80,7 +80,7 @@ def main(): api_key = os.getenv("GEMINI_API_KEY") issue_title = os.getenv("ISSUE_TITLE") issue_body = os.getenv("ISSUE_BODY") - skill_file = os.getenv("SKILL_FILE", ".gemini/skills/android-maps-compose/SKILL.md") + skill_file = os.getenv("SKILL_FILE", ".agents/skills/android-maps-compose/SKILL.md") response_file = os.getenv("RESPONSE_FILE", "issue_response.md") if not api_key: diff --git a/.github/scripts/update_skill.py b/.github/scripts/update_skill.py index 151ee914c..861821b97 100644 --- a/.github/scripts/update_skill.py +++ b/.github/scripts/update_skill.py @@ -46,7 +46,7 @@ def get_gemini_response(api_key, prompt): def main(): api_key = os.getenv("GEMINI_API_KEY") diff_file = os.getenv("DIFF_FILE", "release_diff.patch") - skill_file = os.getenv("SKILL_FILE", ".gemini/skills/android-maps-compose/SKILL.md") + skill_file = os.getenv("SKILL_FILE", ".agents/skills/android-maps-compose/SKILL.md") if not api_key: print("GEMINI_API_KEY not found", file=sys.stderr) diff --git a/.github/workflows/release-rc.yml b/.github/workflows/release-rc.yml index d862a578b..942a1c174 100644 --- a/.github/workflows/release-rc.yml +++ b/.github/workflows/release-rc.yml @@ -54,7 +54,7 @@ jobs: sed -i 's/version = "[^"]*"/version = "'"$VERSION"'"/' build.gradle.kts # Files with x-release-please-version inline marker - for file in README.md llm-integration-prompt.md .gemini/skills/android-maps-compose/SKILL.md; do + for file in README.md llm-integration-prompt.md .agents/skills/android-maps-compose/SKILL.md; do if [ -f "$file" ]; then sed -i "/x-release-please-version/s/[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*[a-zA-Z0-9.-]*/$VERSION/" "$file" fi @@ -70,7 +70,7 @@ jobs: build.gradle.kts \ README.md \ llm-integration-prompt.md \ - .gemini/skills/android-maps-compose/SKILL.md + .agents/skills/android-maps-compose/SKILL.md git commit -m "chore: release v${VERSION}" git push origin "$BRANCH" diff --git a/AGENTS.md b/AGENTS.md index 80c542b2d..a9346413a 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -80,6 +80,21 @@ Running `maps-app` requires a Maps API key: put `MAPS_API_KEY=...` in `secrets.properties` at the repo root (see `local.defaults.properties` for the template). Never hardcode or commit API keys. +## Agent setup + +This file is the shared instruction set for every coding agent. `CLAUDE.md` +and `GEMINI.md` only import it, and Codex and Copilot read it directly, so put +new guidance here rather than in a tool-specific file. + +Skills live in `.agents/skills/`. `.claude/skills` and `.gemini/skills` are +symlinks to that folder, so edit the files under `.agents/skills/` only. +`.agents/skills/android-maps-compose/SKILL.md` teaches agents how apps use this +library: release-please bumps its version lines, and the `Update Skill` +workflow refreshes its content after each release. + +`.gemini/config.yaml` and `.gemini/styleguide.md` configure Gemini Code Assist +reviews on pull requests, so they stay specific to that tool. + ## Code style - Adhere to formatting rules defined in `.editorconfig`. @@ -117,6 +132,18 @@ template). Never hardcode or commit API keys. The PR title still has to be a valid Conventional Commit. Each line counts for the version bump, so a `feat:` or `!` line bumps accordingly. +- Keep a pull request to what its title says. Once review has started, put + new features or unrelated fixes in a separate pull request. If the scope + does change, update the type in the title (a `refactor:` that now adds + behavior is a `feat:`), since release-please reads it. +- Answer every review thread before asking for another review: push the + change, or reply in the thread with why not. A new commit alone does not + tell the reviewer which comments it addresses. +- Never commit anything that only makes sense on your machine or inside + Google: local paths (`file:///`, `/Users/...`, workstation home + directories), `go/` links, `b/` bug IDs or API keys. The `Agent leftovers` check fails + the pull request on these, and on AI co-author trailers and links to agent + chat sessions. - Every behavior change needs a unit test in the affected module. - All pull requests are to be created as drafts (`gh pr create --draft`) until authorization is explicitly given to mark them ready for review. Always inform the user that the PR was created as a draft. - Run the module's tests and `lint` before declaring work done, and report diff --git a/GEMINI.md b/GEMINI.md new file mode 100644 index 000000000..43c994c2d --- /dev/null +++ b/GEMINI.md @@ -0,0 +1 @@ +@AGENTS.md diff --git a/release-please-config.json b/release-please-config.json index 8d338c8c3..74ebfc49a 100644 --- a/release-please-config.json +++ b/release-please-config.json @@ -6,7 +6,7 @@ "build.gradle.kts", "README.md", "llm-integration-prompt.md", - ".gemini/skills/android-maps-compose/SKILL.md" + ".agents/skills/android-maps-compose/SKILL.md" ] } }