|
| 1 | +--- |
| 2 | +name: check-code-attribution |
| 3 | +description: Per-file check of vendored code attribution — headers, THIRD_PARTY_NOTICES.md entries, and license compatibility |
| 4 | +allowed-tools: Bash Read Grep Glob |
| 5 | +--- |
| 6 | + |
| 7 | +# Check Code Attribution |
| 8 | + |
| 9 | +You are reviewing changed files for third-party code attribution compliance in **sentry-java**, an MIT-licensed repository. |
| 10 | + |
| 11 | +## Local runs — discover changed files first |
| 12 | + |
| 13 | +When running locally (not via Warden), determine which files changed on this branch: |
| 14 | + |
| 15 | +```bash |
| 16 | +MB=$(git merge-base HEAD origin/main 2>/dev/null || git merge-base HEAD main) |
| 17 | +git diff --name-only "${MB}"..HEAD |
| 18 | +``` |
| 19 | + |
| 20 | +Then run the Quick triage and subsequent checks on **every** file in that list. Warden's `ignorePaths` in `warden.toml` lists the paths to skip — apply the same exclusions locally. |
| 21 | + |
| 22 | +### Warden CLI (optional local parity check) |
| 23 | + |
| 24 | +Warden does **not** use Cursor auth. Before running Warden locally, configure a provider (same model family as `warden.toml`, or override with `-m`): |
| 25 | + |
| 26 | +```bash |
| 27 | +# Option A: Anthropic API key (matches CI model in warden.toml) |
| 28 | +export WARDEN_ANTHROPIC_API_KEY=sk-ant-... # or: export ANTHROPIC_API_KEY=sk-ant-... |
| 29 | + |
| 30 | +# Option B: Pi OAuth / API key store (~/.pi/agent/auth.json) |
| 31 | +npx pi # then run /login and pick Anthropic (or another provider) |
| 32 | + |
| 33 | +# Option C: Different provider for a one-off run |
| 34 | +export WARDEN_OPENAI_API_KEY=sk-... |
| 35 | +npx @sentry/warden origin/main..HEAD --skill check-code-attribution -m openai/gpt-5.5 -vv |
| 36 | +``` |
| 37 | + |
| 38 | +```bash |
| 39 | +npx @sentry/warden origin/main..HEAD --skill check-code-attribution -vv |
| 40 | +``` |
| 41 | + |
| 42 | +If you only need attribution review in the IDE, `/check-code-attribution` in Cursor does not require Warden credentials. |
| 43 | + |
| 44 | +When running via Warden, the changed file is already provided — skip branch-wide discovery, but follow **Warden execution** below. |
| 45 | + |
| 46 | +## Warden execution |
| 47 | + |
| 48 | +Warden analyzes one changed file per run (whole-file mode). Complete every Quick triage step — the diff alone is not sufficient. |
| 49 | + |
| 50 | +**Mandatory on every run (do not skip):** |
| 51 | + |
| 52 | +1. `Read` the first 20 lines of the changed file. |
| 53 | +2. `Grep` `THIRD_PARTY_NOTICES.md` for the class name (filename without extension, e.g. `ANRWatchDog` for `ANRWatchDog.java`). |
| 54 | +3. When Bash is available, compare the merge-base header: |
| 55 | + ```bash |
| 56 | + MB=$(git merge-base HEAD origin/main 2>/dev/null || git merge-base HEAD main) |
| 57 | + git show "${MB}:<file-path>" | head -50 |
| 58 | + ``` |
| 59 | + |
| 60 | +**Do not dismiss findings because:** |
| 61 | + |
| 62 | +- A `THIRD_PARTY_NOTICES.md` entry exists — file headers are still required; NOTICES does not replace them. |
| 63 | +- The diff only removes a header comment block — removed `-` lines with `Copyright`, `Licensed under`, license disclaimers, or vendoring language ("adapted from", etc.) mean attribution was stripped. |
| 64 | +- The header says "Adapted from …" but omits copyright holder or license name — flag missing header fields. |
| 65 | + |
| 66 | +For `THIRD_PARTY_NOTICES.md` runs: for every **removed** entry in the diff, use `Read` or `Glob` to confirm whether Scope files still exist with attribution headers. If they do, the entry must not be removed. |
| 67 | + |
| 68 | +## Quick triage |
| 69 | + |
| 70 | +Sentry's own files carry **no** copyright headers — any copyright/license line indicates third-party code. Every file that reaches this skill is in scope — do not skip files based on extension. |
| 71 | + |
| 72 | +If this file is `THIRD_PARTY_NOTICES.md`, go to the THIRD_PARTY_NOTICES section below. |
| 73 | + |
| 74 | +For all other files, perform these checks **before** deciding whether to proceed: |
| 75 | + |
| 76 | +1. **Read the file header** — use the Read tool to read the first 20 lines of the file. Look for vendored-code signals: `Copyright`, `Licensed under`, `SPDX-License-Identifier`, or vendoring language ("adapted from", "backported from", "based on", "copied from", "derived from", "inspired by", "ported from", "translated from", "vendored"). |
| 77 | +2. **Check THIRD_PARTY_NOTICES.md** — use Grep to search `THIRD_PARTY_NOTICES.md` for the file name without extension (e.g., search for `ANRWatchDog` when reviewing `ANRWatchDog.java`). A match means this is a known vendored file. |
| 78 | +3. **Scan the diff** — check for vendored-code signals on both added (`+`) and **removed (`-`)** lines. Removed copyright/license lines ARE signals — they mean attribution is being stripped. |
| 79 | + |
| 80 | +**A signal in ANY of these three sources means this is vendored code — proceed to the vendored source file section.** |
| 81 | + |
| 82 | +A file referenced in THIRD_PARTY_NOTICES.md is ALWAYS vendored, even if its current header has no attribution. |
| 83 | + |
| 84 | +**If none of the three sources have signals, report no findings and stop.** |
| 85 | + |
| 86 | +--- |
| 87 | + |
| 88 | +## If this file is `THIRD_PARTY_NOTICES.md` |
| 89 | + |
| 90 | +Validate the changed entries using the diff context: |
| 91 | + |
| 92 | +1. For each added or modified entry, verify it has all required fields: **Source URL**, **License name**, **Copyright**, **Scope** (file paths), and **full license text** in a fenced code block. |
| 93 | +2. For each Scope path, verify the file(s) exist (use Glob or Read). |
| 94 | +3. Flag new license types — especially copyleft or AGPL. |
| 95 | +4. Flag orphaned entries whose Scope files no longer exist. |
| 96 | +5. For **removed** entries (lines prefixed with `-` in the diff), use Read to check whether the Scope files still exist and still have attribution headers. If they do, the entry must not be removed. |
| 97 | +6. Check **copyright consistency** — the Copyright field must match the copyright line inside the embedded license text. Flag mismatches. |
| 98 | + |
| 99 | +--- |
| 100 | + |
| 101 | +## If this is a vendored file |
| 102 | + |
| 103 | +### 1. Check attribution header |
| 104 | + |
| 105 | +The file must have a license header near the top (before the `package` statement in Java/Kotlin files) with: |
| 106 | +- Library name or origin |
| 107 | +- Copyright year and holder |
| 108 | +- License name |
| 109 | +- Source URL |
| 110 | + |
| 111 | +Exact wording and comment style may vary. Only flag **missing fields**, not formatting. |
| 112 | + |
| 113 | +Compare the current header (from the Read in Quick triage) against the THIRD_PARTY_NOTICES.md entry. For example, if the NOTICES entry says this file is MIT-licensed by "Salomon BRYS" but the current header has no copyright or license mention, the header was stripped. |
| 114 | + |
| 115 | +When Bash is available (local runs), also compare against the merge-base version for additional context: |
| 116 | +```bash |
| 117 | +MB=$(git merge-base HEAD origin/main 2>/dev/null || git merge-base HEAD main) |
| 118 | +git show "${MB}:<file-path>" | head -50 |
| 119 | +``` |
| 120 | + |
| 121 | +Flag these issues: |
| 122 | +- **Header stripped** — file is in NOTICES but current header has no attribution |
| 123 | +- **Header truncated** — header is present but missing required fields (e.g., copyright line removed, license disclaimer removed) |
| 124 | +- **Header inconsistent** — header contradicts what the NOTICES entry says |
| 125 | +- **Diff removes attribution lines** — `Copyright`, `Licensed under`, etc. appear on removed lines in the diff |
| 126 | + |
| 127 | +### 2. Check THIRD_PARTY_NOTICES.md entry |
| 128 | + |
| 129 | +From the Grep in Quick triage: if no matching entry exists, flag it as missing. A valid entry needs: Source URL, License name, Copyright, Scope, full license text. |
| 130 | + |
| 131 | +### 3. Check license compatibility |
| 132 | + |
| 133 | +Classify the license per Sentry's Open Source Legal Policy (https://open.sentry.io/licensing/): |
| 134 | + |
| 135 | +| Tier | Examples | Severity | |
| 136 | +|-----------------|-------------------------------------------------|----------------------------------------------| |
| 137 | +| Permissive | MIT, BSD, Apache 2.0, ISC, CC0, Unlicense, Zlib | Allowed | |
| 138 | +| Weak copyleft | LGPL, MPL, EPL, CDDL | **high** — requires review | |
| 139 | +| Strong copyleft | GPL, QPL, Sleepycat, OSL | **high** — requires legal review | |
| 140 | +| AGPL | — | **high** — absolute ban, must be removed | |
| 141 | +| No license | — | **high** — assume no permission | |
| 142 | + |
| 143 | +--- |
| 144 | + |
| 145 | +## If this is a deleted vendored file |
| 146 | + |
| 147 | +If the diff deletes a file and the removed lines contained attribution headers, check whether `THIRD_PARTY_NOTICES.md` still references it — the entry should be updated or removed. |
| 148 | + |
| 149 | +--- |
| 150 | + |
| 151 | +## Severity guide |
| 152 | + |
| 153 | +| Level | Use for | |
| 154 | +|------------|-----------------------------------------------------------------------------------------------------------------------------------------------------| |
| 155 | +| **high** | 🚨 License violations: AGPL, copyleft, unlicensed, no-license code | |
| 156 | +| **medium** | ⚠️ Missing attribution header fields, stripped headers, missing/inconsistent NOTICES entries, deleted/renamed vendored files needing NOTICES update | |
| 157 | +| **low** | 👀 Attribution present but could be improved | |
| 158 | + |
| 159 | +Note: Warden relies on these severity levels when deciding whether to make comments on PRs or require changes. |
| 160 | + |
| 161 | +## Output |
| 162 | + |
| 163 | +**No issues → empty response (say nothing).** |
| 164 | + |
| 165 | +Otherwise, number each finding and order by severity (most severe first). Use this exact format — note the escaped period (`\.`) to prevent markdown list collapsing, and the blank line between entries: |
| 166 | + |
| 167 | +``` |
| 168 | +1\. <severity emoji> **<fully qualified class name>** |
| 169 | + <what's wrong and how to fix it — one or two lines> |
| 170 | +
|
| 171 | +2\. <severity emoji> **<fully qualified class name>** |
| 172 | + <what's wrong and how to fix it — one or two lines> |
| 173 | +``` |
| 174 | + |
| 175 | +Rules: |
| 176 | +- **Escape the period** after the number (`1\.` not `1.`) so markdown does not collapse entries into a tight list. |
| 177 | +- Use the emoji from the severity guide (🚨, ⚠️, or 👀) — not the word. |
| 178 | +- Use fully qualified Java class names (e.g. `io.sentry.CircularFifoQueue`), not file paths. |
| 179 | +- Start the description on a new indented line below the class name. |
| 180 | +- Leave an empty line between each numbered finding. |
| 181 | +- For license issues, include the policy link. |
0 commit comments