Add the Craft release pipeline so packages/installer can be published to
npm as @sentry/ai.
- .craft.yml configures a single npm target (public scoped access) with a
tarball-name guard. There is deliberately no github target, so a release
creates no git tags and no GitHub releases -- nothing repo-wide implying
the skills/plugins are versioned by it.
- The release branch is scoped to `release-installer/<version>` via
releaseBranchPrefix, so it reads as a package release. craft creates it
during prepare and deletes it after publish, so it is transient.
- changelogPolicy is `simple` (matching sentry-javascript) and the
changelog lives with the package at packages/installer/CHANGELOG.md. The
entry is written by hand before releasing; `auto` would sweep this repo's
skill-drift and plugin churn into the installer changelog.
- release.yml runs `craft prepare` via the Sentry release bot App token.
It must be an App token rather than GITHUB_TOKEN so the pushed release
branch triggers release-build.yml, which packs the tarball and uploads
it as the SHA-named artifact Craft's GitHub provider expects.
- The package gains `files: ["dist", "CHANGELOG.md"]`, publishConfig.access
public, and an explicit LICENSE so the published tarball is complete
without relying on pnpm copying the root LICENSE.
Publishing runs from getsentry/publish after a team lead approves the
release issue; this repo only prepares the release and builds the artifact.
Add a pnpm workspace with a `packages/installer` package (`@sentry/ai`)
that provides a single CLI for installing the Sentry plugin into any
supported AI coding assistant: Claude Code, Codex, Cursor, and Grok.
The CLI (built on citty) exposes an `install` subcommand. By default it
shows an interactive selector pre-selecting the detected agents;
`--no-interactive`/`--yes` skips the prompt and installs every detected
agent — used for CI and unattended runs.
Each agent is a self-contained harness implementing a common strategy
interface — detect, isInstalled, canInstall, install — so adding a new
agent is just another module. System access (shell, fs, platform,
homedir) is injected through a SystemDeps seam, keeping every harness
unit-testable without side effects.
Behavior:
- Already-installed agents update in place rather than erroring or
no-opping: Cursor pulls, Grok/Claude use their update commands, Codex
re-adds (idempotent; it has no update command).
- Claude refreshes its marketplace index before installing, since a fresh
CLI ships a stale index that cannot resolve the plugin.
- canInstall gates prerequisites (Cursor needs git) and reports a clear
skip instead of a cryptic failure.
- One agent failing does not abort the rest, and the CLI exits non-zero
if any selected agent failed or was blocked.
- Cross-platform: binary detection uses where/which per OS, Cursor is
located via its per-OS install path, and git paths are quoted for
Windows spaces.
Distribution:
- rolldown bundles the npm package (deps external).
- fossilize builds standalone Node SEA binaries; --hole-punch drops
non-English ICU data to cut the download ~30%.
CI:
- A smoke-test matrix (Linux, macOS, Windows) installs the real agent
CLIs and runs the installer non-interactively, asserting the plugin
lands for every detected agent.
Instrumented with the Sentry Node SDK.
The hardcoded skill-to-team mapping in this workflow is now handled by
CODEOWNERS, which gives GitHub native reviewer assignment without a
separate Actions job.
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
This repository is the single source of truth for skills and routing metadata,
but it is not itself an installable plugin, and each assistant (Claude Code,
Cursor, Codex, Grok) expects the plugin in a different on-disk shape. No plugin
ecosystem can consume a zip or release asset; all install from a git ref. So a
GitHub Actions workflow builds each agent's distribution from this repository
and deploys it to a dedicated repository whose root is exactly that agent's
plugin, which a marketplace points at as getsentry/plugin-<agent>.
Each agent has a `plugin-src/<agent>/` dir with its manifests, README, and a
`build.sh` that assembles the dist tree from shared repo content. Claude, Cursor,
and Grok consume the plugin at the repo root; Codex requires it under
`plugins/sentry/` and rejects the `disable-model-invocation` field the skill
tree relies on, so its build strips that field and emits a per-skill
`agents/openai.yaml` (see `hide-skills.py`). MCP config is built from the repo's
`mcp.json` source of truth: inline in Claude's manifest, and a file for the
others.
Cross-repo writes use a short-lived token from a dedicated GitHub App scoped to
contents:write on the plugin repos; the default GITHUB_TOKEN cannot push to
other repositories.
The root `.claude-plugin/`, `.cursor-plugin/`, and `.mcp.json` are retained so
existing installs that consumed the plugin from this repo's root keep working;
their READMEs announce removal on or after 2026-07-11.
Map each SDK skill directory to the GitHub team that owns the
corresponding SDK repository. This ensures the right team gets
requested for review when skill content changes.
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
The plan job's UNKNOWN-skill check used `jq --argjson ... --argjson ...
'$wanted | map(...)'` without `-n` and without stdin. jq waited for
stdin, got EOF, applied the filter zero times, and produced no output —
silently yielding UNKNOWN="" rather than UNKNOWN="[]".
Then `jq 'length' <<<""` also produced no output, so the comparison
`[[ "" != "0" ]]` evaluated true and the workflow died with a
false-positive "Unknown skill(s) in workflow_dispatch input: " error
on every dispatch (run 26625830364).
Add `-nc` so jq treats null as the input, applies the filter once,
and produces the expected empty array. Also guard the length check
with `${UNKNOWN:-[]}` so a future empty value can't trip the same
false positive.
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* feat(skill-drift): replace gh-aw workflow with matrix-fanout Claude runs
Replaces .github/workflows/skill-drift-check.{md,lock.yml} (single
sequential gh-aw run) with a plain GitHub Actions workflow that fans out
one Claude Sonnet session per SDK skill via matrix strategy.
Each per-skill job reads the last 7 days of merged PRs in the
corresponding SDK repo, opens the actually changed source files at the
merge SHA (not just the diff summary), compares against the local skill
bundle, and emits either a file diff under skills/<skill>/ or a
structured summary for the apply job to act on.
Security
- All actions pinned to a full commit SHA.
- permissions: {} at workflow root; each job grants only what it needs.
- The agent job (detect) runs with contents: read ONLY — no write tokens
reachable from the LLM session.
- Agent tool allowlist restricts Bash to a handful of gh/jq/date
subcommands; no git, curl, or arbitrary shell.
- The apply job is pure deterministic shell with a path allowlist
(skills/<this-skill>/ only) enforced before any commit, push, or PR.
- Inline reviewer assignment in the apply job since PRs opened by
GITHUB_TOKEN do not trigger downstream workflow_run events.
- Trigger surface is schedule + workflow_dispatch only.
Matrix lives in .github/skill-drift-matrix.json so adding a new SDK skill
is a one-line change.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* fix(skill-drift): address review feedback in apply job
Four issues flagged on PR #135:
1. (Cursor Bugbot, HIGH) The `artifacts/` directory placed by
download-artifact was being picked up by `git ls-files --others
--exclude-standard` in the apply job's path-allowlist check, which
would have downgraded EVERY create_pr to an issue because no
`artifacts/...` path matches the `^skills/<skill>/` regex. Scope
both `git diff` and `git ls-files` to `-- skills/` so anything
outside that subtree (artifacts/, dotfiles, etc.) is invisible to
the allowlist scan.
2. (Sentry Bot, HIGH) On the path-allowlist and empty-diff bail-out
paths the script switched branches but did not remove the untracked
files left behind by `rsync`. The next iteration would then see
those files via `git ls-files --others` and trigger a false-positive
allowlist violation, cascading the failure across all remaining
skills. Add `git clean -fd -- skills/` at the start of each
create_pr iteration and on both bail-out paths.
3. (Cursor Bugbot, MEDIUM) `git diff --quiet HEAD` does not detect
brand-new untracked files. If the agent's only change was adding a
new `references/*.md`, the empty-diff guard would have silently
skipped the PR. Replace with an `[[ -z "$TOUCHED" ]]` check, since
TOUCHED already includes untracked files.
4. (Sentry Bot, MEDIUM) Parsing the PR number from `gh pr create`
stdout via `basename` is fragile — extra text would corrupt it and
the downstream JS reviewer-assignment step would silently skip.
Look up the number via `gh pr view "$BRANCH" --json number --jq
.number` instead, and log a `::warning::` (plus increment FAILED)
if it still cannot be determined. Also add a warning log in the JS
step when an invalid PR number is encountered.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* fix(skill-drift): second review pass — length caps, retries, pagination, edge cases
Addresses the round of review comments left on commit fea5d4a:
1. (sentry-warden, security) Untrusted SDK PR content reaches issue/PR
bodies via `gh issue create --body "$BODY"` and `gh pr create --body`.
Add a 256-char cap on `title` and a 10000-char cap on `body`, enforced
in both detect's validate step and apply's re-validation. Prepend a
GitHub `> [!WARNING]` alert header to every issue/PR body the agent
produces so human reviewers see "Auto-generated from external SDK
content. Review all links and code suggestions before acting on
them." before reading agent-authored text. Limits the blast radius
of a successful prompt-injection from an SDK PR.
2. (sentry-bot, MEDIUM) Race condition between `gh pr create` and
`gh pr view`. GitHub's API is eventually consistent — the immediate
view can 404 and silently skip reviewer assignment. Retry up to 5
times with a 1s sleep; warn (not silently skip) if all attempts fail.
3. (cursor-bot, MEDIUM) `actions/download-artifact@v4` fails the step
when its pattern matches zero artifacts, before the apply script's
graceful empty-artifact branch can run. Mark the download step
`continue-on-error: true`. The apply script already handles a
missing `artifacts/` directory and now also emits a complete set of
step-outputs (prs/issues/no_drift/failed/opened_pr_nums) on the
no-artifacts early-exit so downstream conditions see consistent
values.
4. (cursor-bot, LOW) `github.rest.pulls.listFiles` in the inline
reviewer-assignment step only returns the first page. Use
`github.paginate(..., per_page: 100)` so PRs with many files don't
miss teams. Matches the convention used by
skill-drift-assign-reviewers.yml.
5. (cursor-bot, LOW) Trailing/leading/double commas in the
`workflow_dispatch` `skills` input parsed as empty tokens, which
then failed the unknown-skill check. Drop empty entries in the jq
pipeline.
6. (cursor-bot, MEDIUM) `title` and `body` were validated as strings
but empty strings passed, which would have broken `git commit -m ""`
and yielded useless empty issues. Require non-empty values for
`create_pr`/`create_issue` (still allowed for `no_drift`, which the
apply job ignores entirely).
WONTFIX: the "hardcoded `main`" comment. This workflow is pinned to
`getsentry/sentry-for-ai` via `if: github.repository ==` guards on
every job; the default branch IS `main`. Parameterizing
`github.event.repository.default_branch` adds complexity for a
portability story we don't have.
Also: update the agent prompt with the new length caps and non-empty
requirement so the agent's output isn't silently rejected by
validation.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The Weekly SDK Skill Drift Detector workflow runs on a `schedule:`
trigger, so there is no `pull_request` context. The agent's `add_reviewer`
safe output therefore failed every run with:
add_reviewer: No pull_request_number provided and not in pull request context
turning the job red even when the PR and issues were created successfully
(see run https://github.com/getsentry/sentry-for-ai/actions/runs/25321035855).
The step was also redundant: `.github/workflows/skill-drift-assign-reviewers.yml`
already maps changed `skills/sentry-*-sdk/**` paths to the correct team and
requests review per skill (more granular than the agent's union-of-teams call).
Changes:
- Drop `add-reviewer:` from the `safe-outputs:` block.
- Remove Step 4a item 5 telling the agent to call `add_reviewer`.
- Add a short note pointing the agent at the dedicated reviewer-assignment
workflow so it knows not to try to assign reviewers itself.
- Recompile `skill-drift-check.lock.yml` with gh-aw v0.71.1 (was v0.67.1) so
CI uses the latest compiler and pinned actions.
Note: the assign-reviewers workflow does not currently fire for these PRs
because gh-aw opens them with `GITHUB_TOKEN`, which by design does not
trigger downstream `pull_request` events. That is a separate issue and is
not addressed here.
Co-authored-by: Claude <noreply@anthropic.com>
Recompile the skill-drift-check workflow with the latest gh-aw CLI.
Key upgrades:
- gh-aw: v0.64.2 → v0.67.1
- AWF (firewall): v0.25.1 → v0.25.13
- MCP Gateway: v0.2.6 → v0.2.14
The previous run (#24033021813) failed because the apiKeyHelper script
was not accessible inside the AWF chroot jail, causing Claude Code to
immediately fail with 'authentication_failed'. The newer AWF version
includes 12 patch releases that address container/chroot reliability.
Closes#91
* feat: skill drift workflow opens PRs with fixes and assigns SDK teams
Extend the weekly skill-drift-check workflow to directly fix straightforward
drift by opening PRs instead of only creating issues. The agent now:
- Prefers opening PRs for mechanical changes (new config options, version
bumps, new integration entries) with the fix applied inline
- Falls back to issues for complex/risky drift (breaking API removals,
ambiguous behavior, coordinated rewrites)
- Uses add_reviewer to assign the appropriate SDK team (from the mapping
table) as reviewer on each PR
- PRs are opened as ready-for-review (not draft) with auto-labels and
14-day expiry
Frontmatter changes:
- Added create-pull-request safe output (max 10, non-draft, protected
supply-chain files fall back to issues)
- Added add-reviewer safe output restricted to the 5 SDK team slugs
- Recompiled lock.yml with gh-aw v0.64.2 (was v0.55.0)
Co-Authored-By: Claude Sonnet 4 <noreply@anthropic.com>
* feat: auto-assign SDK team reviewers on skill-drift PRs
Add a lightweight workflow that triggers on PR open for skill-drift labeled
PRs. It checks which skills/sentry-*-sdk/ directories were modified and
requests review from the corresponding SDK team via a hardcoded mapping.
This removes the dependency on the agentic workflow remembering to call
add_reviewer — team assignment happens deterministically based on file
paths regardless of how the PR was created.
Co-Authored-By: Claude Sonnet 4 <noreply@anthropic.com>
* fix: use org-prefixed team slugs for reviewer assignment
The requestReviewers API needs the full org/team-slug format
(e.g., getsentry/team-javascript-sdks) to resolve teams correctly.
Co-Authored-By: Claude Sonnet 4 <noreply@anthropic.com>
---------
Co-authored-by: Claude Sonnet 4 <noreply@anthropic.com>
Extend the weekly skill-drift-check workflow to directly fix straightforward
drift by opening PRs instead of only creating issues. The agent now:
- Prefers opening PRs for mechanical changes (new config options, version
bumps, new integration entries) with the fix applied inline
- Falls back to issues for complex/risky drift (breaking API removals,
ambiguous behavior, coordinated rewrites)
- Uses add_reviewer to assign the appropriate SDK team (from the mapping
table) as reviewer on each PR
- PRs are opened as ready-for-review (not draft) with auto-labels and
14-day expiry
Frontmatter changes:
- Added create-pull-request safe output (max 10, non-draft, protected
supply-chain files fall back to issues)
- Added add-reviewer safe output restricted to the 5 SDK team slugs
- Recompiled lock.yml with gh-aw v0.64.2 (was v0.55.0)
Co-authored-by: Claude Sonnet 4 <noreply@anthropic.com>
- Assign copilot to drift issues so the skill-updater agent picks them up
- Add team owner column to SDK-to-repo mapping table
- Include cc @team mention in issue body to notify the SDK team
- Teams: team-javascript-sdks, owners-python-sdk, team-web-sdk-backend,
team-mobile, team-mobile-cross-platform
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
* feat: add skill-creator custom agent for GitHub Copilot
Adds a specialized agent that creates complete SDK skill bundles from
scratch. Key differentiator: it clones the SDK repo locally to verify
every API name, config option, and import path against actual source
code before writing anything.
Workflow: study existing skills -> research docs -> clone SDK repo ->
verify APIs against source -> write skill bundle -> run quality
checklist -> register in skill tree -> open PR.
References skill-creator files (philosophy.md, quality-checklist.md,
research-playbook.md) as source of truth rather than duplicating them.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: run skill tree registration before validation
Swaps Steps 6 and 7 so the new skill is registered in the parent
router table before build-skill-tree.sh runs. The validator checks
that every skill with a parent field appears in its router — running
it before registration always fails.
Also switches to --check flag for the final validation to prevent
unintended SKILL_TREE.md modifications during verification.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Adds a GitHub Copilot custom agent profile that specializes in creating
and updating Sentry SDK skill bundles. Instead of duplicating knowledge,
it references the skill-creator files (philosophy.md, quality-checklist.md,
research-playbook.md) as its source of truth — so it stays current as
those files evolve.
Designed to work with skill-drift issues from the weekly drift detector.
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
* Initial plan
* fix: add mcp.sentry.dev to allowed domains in SDK Skill Drift Detector workflow
The workflow was failing because the project's .mcp.json configures a `sentry`
MCP server at https://mcp.sentry.dev/mcp. When Claude Code runs in the agentic
workflow, it reads the project-level .mcp.json and tries to connect to this
server. Since mcp.sentry.dev was not in the firewall's allowed domains list,
the connection was blocked and Claude Code reported:
ERR_API: MCP server(s) failed to launch: sentry
The "Parse agent logs for step summary" step detected this error and marked the
job as failed — even though the actual work (creating skill drift issues) was
completed successfully.
Fix: Add mcp.sentry.dev to the allowed domains in both the workflow source file
(skill-drift-check.md) and the compiled lock file (skill-drift-check.lock.yml).
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Co-authored-by: HazAT <363802+HazAT@users.noreply.github.com>
---------
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: HazAT <363802+HazAT@users.noreply.github.com>
* feat: add weekly SDK skill drift detector agentic workflow
Adds a GitHub Agentic Workflow that runs weekly (Monday) using Claude
to detect when SDK skill files have fallen behind changes in Sentry
SDK repos. Monitors all 15 SDK skills across 10 GitHub repos, with
smart monorepo path filtering for sentry-javascript.
When drift is detected (new config options, deprecated APIs, new
framework integrations, feature changes, version bumps, or breaking
changes), it creates labeled issues in this repo with specific
gaps and links to the relevant PRs and skill files.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* chore: remove design doc from PR
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Extract validate-skill-tree from the warden workflow into a dedicated
.github/workflows/validate-skill-tree.yml. Keeps concerns separate —
warden handles AI code review, skill tree validation handles structural
integrity. Both trigger on the same PR events but run independently.
Adds a parallel CI job that runs `./scripts/build-skill-tree.sh --check`
on every PR. The job checks out the repo with minimal permissions
(contents: read) and fails if SKILL_TREE.md is stale or any skill
frontmatter/breadcrumb/router-table validation errors are found.
Running it as a separate job (rather than a step in the warden review
job) keeps concerns isolated and lets both jobs run in parallel.
Co-Authored-By: Claude Sonnet 4.5 (Anthropic)