
Review Pr
- 1 installs
- 20 repo stars
- Updated August 4, 2026
- elastic/package-spec
review-pr skill documents Review a package-spec pull request or branch for completeness and correctness.
About
review-pr skill documents Review a package-spec pull request or branch for completeness and correctness. Use when the user asks to review a PR, check their branch is ready to merge, verify they have not missed required changes, or wants a pre-submission checklist. Accepts a PR number, a branch name, or no argument (current b. name: review-pr description: Review a package-spec pull request or branch for completeness and correctness. Use when the user asks to review a PR, check their branch is ready to merge, verify they have not missed required changes, or wants a pre-submission checklist. Accepts a PR number, a branch name, or no argument (current branch vs main).
- Review a package-spec pull request or branch for completeness and correctness.
- Platform-specific setup patterns for review-pr.
- Evidence-backed steps from upstream SKILL.md.
- When-to-use criteria for review-pr versus alternatives.
Review Pr by the numbers
- 1 all-time installs (skills.sh)
- Ranked #1,835 of 2,203 Security skills by installs in the Skillselion catalog
- Data as of Aug 5, 2026 (Skillselion catalog sync)
review-pr capabilities & compatibility
- Capabilities
- review pr quick start · review pr when to use guidance · review pr integration patterns
- Works with
- elasticsearch
- Use cases
- security audit
What review-pr says it does
spec: https://agentskills.io/specification.md
This skill conforms to the **[Agent Skills](https://agentskills.io/specification.md)** open format ([agentskills.io](https://agentskills.io/)).
npx skills add https://github.com/elastic/package-spec --skill review-prAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 1 |
|---|---|
| repo stars | ★ 20 |
| Last updated | August 4, 2026 |
| Repository | elastic/package-spec ↗ |
How do I use review-pr correctly?
Review a package-spec pull request or branch for completeness and correctness. Use when the user asks to review a PR, check their branch is ready to merge, verify they have not missed required changes
Who is it for?
Teams implementing review-pr workflows from the catalog.
Skip if: Skip when requirements clearly match a different specialized stack.
When should I use this skill?
User asks about review-pr, review a package-spec pull request or branch for completeness and correctness. use when th.
What you get
Working review-pr setup with validated configuration and next steps.
Files
package-spec PR Review (Agent Skill)
This skill conforms to the [Agent Skills](https://agentskills.io/specification.md) open format (agentskills.io).
This skill does not modify the codebase. It does not edit source files, run any git command that modifies state (no commit, push, checkout, reset, stash, merge, or rebase), or change anything on the branch under review. If an issue is found, describe it and stop — do not attempt to fix it. The only file it writes is the review report at .cursor/review-pr-output.md.
Reviews a branch or pull request against the contribution rules for this repository. See references/checklist.md for full rules and examples.
For narrative onboarding (Makefile targets, scaffolding test packages, testing against the integrations repo), see [CONTRIBUTING.md](../../../CONTRIBUTING.md) at the repository root. This skill and the checklist focus on PR completeness against those practices.
How to Use This Skill
| Situation | What to do |
|---|---|
| Claude Code | /review-pr, /review-pr <branch>, or /review-pr <PR-number> |
| Cursor / Copilot | Attach this file to your chat and say "review my changes" or paste your diff |
| Any LLM | Paste this file as a system message, then provide the output of git diff main...HEAD |
---
Step 1 — Resolve the Target
Determine what to diff based on the input provided:
If a PR number was given (e.g., 1140):
gh pr view 1140 --repo elastic/package-spec --json headRefName,baseRefName,title,url
git fetch origin <headRefName>
# diff: FETCH_HEAD vs <baseRefName>
git diff <baseRefName>...FETCH_HEAD --stat
git diff <baseRefName>...FETCH_HEADIf a branch name was given (e.g., my-feature):
git diff main...<branch> --stat
git diff main...<branch>If no argument was given (review current branch):
git branch --show-current # confirm we are not on main
git diff main...HEAD --stat
git diff main...HEADIf the current branch is main and no argument was given, report that there is nothing to review.
---
Step 2 — Categorize Changed Files
Using the file list from --stat, bucket each changed file into one or more categories:
| Category | File pattern |
|---|---|
| Spec files | spec/**/*.spec.yml |
| Changelog | spec/changelog.yml |
| Semantic validators | code/go/internal/validator/semantic/*.go (excluding *_test.go) |
| Validator registry | code/go/internal/validator/spec.go |
| Validator unit tests | code/go/internal/validator/semantic/*_test.go |
| Validator integration tests | code/go/pkg/validator/validator_test.go |
| Test packages | test/packages/** |
| Compliance packages | compliance/testdata/packages/** |
| Compliance features | compliance/features/*.feature |
Use the categories internally to pick checklist sections; do not paste the full categorized file list into the report unless it clarifies an extra-review item.
---
Step 3 — Run the Checklist
Work through each applicable section from references/checklist.md.
Below is a compact version of the checks. The reference file has full rules, edge cases, and exact examples.
Contribution process (when relevant)
Consult section 0 in the reference file and CONTRIBUTING.md.
- Cross-stack or cross-product spec changes should follow the Change Proposals process before merge.
- New package categories require the Category Proposals process.
- If the change is large and the PR does not reference a proposal or tracking issue, add an extra-review note asking the author to confirm process was followed.
Always: Changelog
- Is
spec/changelog.ymlmodified? - If not: flag as missing (required for all non-trivial changes; dependency-bump PRs
from Dependabot are the only exception).
- If modified, verify:
- Entry is under the correct in-development version (the one with
-nextsuffix). - New entry is at the bottom of that version's
changeslist. descriptionis a complete sentence ending with a period.typeis one of:enhancement,bugfix, orbreaking-change.linkpoints to a valid PR URL or isTBD(not empty, not an issue URL unless the
change originated from an issue with no PR).
- If the feature is blocked on Kibana/elastic-package: a
# Pending on <url>comment
appears directly above the entry.
If spec files changed
Consult the "Version patches" and "Schema reuse" sections of the reference file.
- For new
propertiesordefinitionsthat olderformat_versionvalues must not include, add
versions[].patch remove operations (see the reference file). Not every addition needs a patch: if the change is only meaningful at the introducing spec version (e.g. a new required field or other breaking change with a clear minimum format_version), rely on version scoping instead of remove patches when appropriate.
- The remove order matters: property
$refentries must be removed before the definition
they reference.
- Shared fields used in multiple spec files must be defined once in
spec/integration/manifest.spec.yml and referenced via $ref elsewhere — not duplicated inline.
If semantic validators changed
Consult the "Semantic validators" section of the reference file.
- New validator function: check it is registered in
code/go/internal/validator/spec.go
in the rulesDef slice, with appropriate fn, since, and types fields.
- Tests: at least one of the following must be present:
- A
*_test.gofile alongside the validator usingt.TempDir()(simple/single-file rules). - New test cases in
code/go/pkg/validator/validator_test.goreferencing packages in
test/packages/ (complex multi-file scenarios).
If test packages changed
Consult the "Test packages" section of the reference file.
- Prefer scaffolding with `elastic-package create package` or, for new data streams in an
existing package, `elastic-package create data-stream` (from that package’s directory), over manual copies.
- Each package under
test/packages/orcompliance/testdata/packages/must contain:
manifest.yml, changelog.yml, docs/README.md.
- Any data stream must include a valid ingest pipeline: processors need a
tagfield, and
there must be an on_failure block that sets event.kind: pipeline_error and error.message to a string containing the three Handlebars placeholders.
If compliance feature files changed
Consult the "Compliance features" section of the reference file.
- Every
Scenario:must have a@X.Y.Zversion tag immediately above it. - A
@skiptag must always be paired with a# Pending on <url>comment on the next line. - When
@skipis added, the correspondingspec/changelog.ymlentry must also have a
matching # Pending on <url> comment.
If new Go files added
- Every new
.gofile must start with the Elastic license header:
// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
// or more contributor license agreements. Licensed under the Elastic License;
// you may not use this file except in compliance with the Elastic License.- Variable and function names must be unabbreviated (e.g.,
packageNamenotpkgName,
dataStreamManifests not dsManifests).
- Indentation must use tabs, not spaces.
---
Step 4 — Run Local Validation
If a Go toolchain and make are available in the environment, run at minimum (same order as CONTRIBUTING.md):
# Validate spec YAML syntax (fast, always do this after spec changes)
go test ./code/go/internal
# Lint and license headers
make checkOptional (broader validation): When the diff warrants it, also run make test for the full suite (CONTRIBUTING.md). For changes that should be exercised across many real packages, see Testing with integrations repository in CONTRIBUTING.md (e.g. test integrations PR comment and closing the spawned integrations PR when done).
Record validation outcomes only as described in Step 5 (short summary per command; on failure, include a small excerpt only). If the toolchain is not available, note skipped for those commands.
---
Step 5 — Write the Report
Write a short report to .cursor/review-pr-output.md, overwriting any previous run. Use plain text only (no emoji or decorative symbols). Aim for roughly one screen of content.
Include only what follows. Omit empty sections entirely.
# PR review: <branch or PR title>
<!-- reviewed: <ISO date> -->
## Scope
At most 2–4 bullets: what the diff changes, only if that context helps a reviewer. Omit this section if the PR title and `git diff --stat` are enough and nothing needs extra review.
## Extra review
Bullets **only** for items that need human attention: checklist gaps, blockers, open questions, or parts of the change that are easy to get wrong (for example new `versions` patches, new semantic validators, `spec/changelog.yml` entries, compliance `@skip`, or cross-file `$ref`). For each bullet use `path:approximate-line` (or `path` and a short region description) plus **one sentence**. Prefix with `blocker`, `suggestion`, or `question` when useful.
If there is nothing to flag here and validation passed, use a single line instead of a list:
No items flagged for extra review.
## Validation
One line per command you ran, for example: `go test ./code/go/internal: pass`. Use `fail` or `skipped` as appropriate. If a command failed, add a **short** excerpt (failing test name or error lines only), not the full log. If no commands ran, one line: `Validation: skipped (toolchain not available).`Do not add per-topic sections (changelog, version patches, tests, etc.) when there is nothing to say. Do not paste full go test or make check output on success. Do not list files that look fine.
After writing the file, print this message to the user:
Review written to .cursor/review-pr-output.mdValidating this skill
After substantive edits to this skill, run (if installed):
skills-ref validate ./.cursor/skills/review-prpackage-spec PR Review Checklist — Detailed Reference
This file contains the full rules, rationale, and examples for each review category. It is referenced by SKILL.md and is loaded on demand when deeper detail is needed.
The human-oriented contributor guide (CONTRIBUTING.md) covers the same development workflows (Makefile targets, test packages, integrations testing) in narrative form. Prefer that document for onboarding; use this checklist for systematic PR review.
---
0. Contribution process
When it applies: Large or cross-product spec changes, or new package categories.
| Topic | Rule |
|---|---|
| Change proposals | Changes that impact the Elastic Stack or Elastic Packages beyond this repo should follow the Change Proposals process in CONTRIBUTING.md (GitHub issue, consensus, ordered checklist) before landing as a single drive-by PR. |
| Category proposals | New supported package categories require the Category Proposals flow in CONTRIBUTING.md. |
Review hint: If the diff is a substantial spec or validator change and the PR description does not reference a proposal or tracking issue, add an extra-review note asking the author to confirm process was followed.
---
1. Changelog
File: spec/changelog.yml
Changelog Format
- version: 3.7.0-next # in-development version always has -next suffix
changes:
- description: Brief description of the change ending with a period.
type: enhancement # enhancement | bugfix | breaking-change
link: https://github.com/elastic/package-spec/pull/NUMBERChangelog Rules
| Rule | Detail |
|---|---|
| Always required | Every non-trivial PR must add an entry. Dependabot dependency bumps are the only exception. |
| Position | New entries go at the bottom of the changes list of the in-development version. |
| Version | Must be the version with a -next suffix, not a released version. |
| Description | Complete sentence ending with a period. Describes what was added/changed, not why. |
| Type | Exactly one of: enhancement, bugfix, breaking-change. |
| Link | Full GitHub PR URL. Use TBD only if the PR does not exist yet. Never use an issue URL here unless explicitly intended. |
Pending features
When a spec feature is complete but blocked on upstream (Kibana, elastic-package):
# Pending on https://github.com/elastic/kibana/issues/NNNNNN
- description: Add support for foo.
type: enhancement
link: https://github.com/elastic/package-spec/pull/NNN- The
# Pending on <url>comment must appear on the line directly above the entry. - The corresponding compliance
.featurefile must also have a@skiptag with the same URL. - Remove both when the blocker is resolved.
---
2. Version Patches
Why they exist: The spec supports multiple format versions. When a single .spec.yml still validates older format_version values, remove patches drop newer optional properties and definitions from the schema those older versions use. Not every change needs a remove patch: if the change applies only at the introducing version (e.g. a new required field or breaking change with a clear minimum format_version), version scoping may be enough—see the Patch Rules table below.
Where they live: In the same .spec.yml file that defines the new field, under a versions key at the top level.
Patch Format
Add each new patch block at the top of the versions list so newer spec versions come first (higher before value above lower). When you add a patch for a new release, insert a new list item at the top—do not append at the bottom.
versions:
# Newer `before` first — insert new patch blocks here, above existing entries.
- before: 3.7.0
patch:
- op: remove
path: "/properties/recent_field"
- op: remove
path: "/definitions/recent_field"
- before: 3.6.0
patch:
- op: remove
path: "/properties/my_new_field"
- op: remove
path: "/definitions/my_new_definition"Patch Rules
| Rule | Detail |
|---|---|
When to add before: patches | Add versions.before remove patches for new properties and definitions when the file still validates older format_version values and that schema must not apply to them (typical for optional fields in a spec file shared across versions). Not every change needs a patch: if the change is already scoped to the introducing spec version—e.g. a new required field or other breaking change with a clear minimum format_version—you may rely on that scoping instead of remove patches. |
versions list order | Add new version entries at the top of the versions list (newer spec versions first), per CONTRIBUTING.md. |
| Remove order | References before definitions. Remove /properties/my_field before /definitions/my_field. Otherwise the patch fails because it tries to remove a definition that is still referenced. |
_dev exception | Files under _dev directories do not need version patches. These are developer tooling files, not part of the distributed spec. |
| Patch comments | Comments should be placed on the path: line, not the op: line. Only add comments for non-obvious paths (e.g., array index paths like required/-). Omit comments for simple, self-explanatory paths. |
Comment convention examples
# GOOD — comment on path line, only for complex path
- op: add
path: "/properties/policy_templates/items/required/-" # re-add type as required
value: type
# GOOD — no comment for simple path
- op: remove
path: "/properties/my_field"
# BAD — comment on op line
- op: remove # removes my_field
path: "/properties/my_field"
# BAD — redundant comment for obvious path
- op: remove
path: "/properties/my_field" # removes my_field propertyVersion Patches Checklist
- [ ] Every new
propertiesordefinitionsentry that olderformat_versionvalues must not include has a matchingremovepatch (or the change is correctly scoped to the introducing version only, e.g. required/breaking at a minimumformat_version). - [ ] Properties are removed before their definitions in the patch list.
- [ ]
_devfiles are excluded. - [ ] Comments follow the path-line convention.
---
3. Schema Reuse
Why it matters: Duplicate inline definitions drift out of sync. The spec uses JSON Schema $ref to define a field once and reference it everywhere.
When to use $ref
If the same field definition appears in two or more spec files: define it once in spec/integration/manifest.spec.yml under definitions, then reference it everywhere else.
Cross-file reference syntax
# Same file
$ref: "#/definitions/my_field"
# From spec/input/manifest.spec.yml referencing spec/integration/manifest.spec.yml
$ref: "../integration/manifest.spec.yml#/definitions/my_field"
# From spec/integration/data_stream/manifest.spec.yml
$ref: "../../integration/manifest.spec.yml#/definitions/my_field"Always use relative paths (starting with ../). Absolute or root-relative paths break portability.
additionalProperties: false
Objects should have additionalProperties: false to prevent undeclared fields from silently passing validation. Flag if a new object type is missing this.
Schema Reuse Checklist
- [ ] No field definition appears inline in two different
.spec.ymlfiles. - [ ] Shared definitions live in
spec/integration/manifest.spec.yml. - [ ] All
$refuses relative paths. - [ ] New object schemas include
additionalProperties: falsewhere appropriate.
---
4. Semantic Validators
Location: code/go/internal/validator/semantic/
Registration
New validator functions must be registered in code/go/internal/validator/spec.go inside the rulesDef slice within the rules() function:
// Minimal — applies to all package types and all versions
{fn: semantic.ValidateMyRule},
// With version gate — only applies for spec >= 3.7.0
{fn: semantic.ValidateMyRule, since: semver.MustParse("3.7.0")},
// With package type filter
{fn: semantic.ValidateMyRule, types: []string{"integration", "input"}, since: semver.MustParse("3.7.0")},
// With upper bound — only applies before 3.0.0
{fn: warnOn(semantic.ValidateMyRule), until: semver.MustParse("3.0.0")},Fields:
fn— required, the validator functionsince— optional, minimum spec version (inclusive)until— optional, maximum spec version (exclusive)types— optional, package types this applies to; omit to apply to all types
Semantic Validators Checklist
- [ ] New
ValidateXxxfunction is present in therulesDefslice. - [ ]
sinceis set when the rule corresponds to a new spec feature (should match the spec
version being targeted).
- [ ]
typesis set when the rule is not universally applicable (e.g., only forintegration
packages).
- [ ]
warnOn()is used only for rules that are being phased in (deprecation warnings before
becoming hard errors in a future version).
---
5. Tests for Semantic Validators
Two testing strategies; choose based on complexity:
Simple: unit test with t.TempDir()
Use when the validator reads a single file or a simple directory structure.
func TestValidateMyRule(t *testing.T) {
tests := map[string]struct {
manifest string
expectError bool
errorContains string
}{
"valid": {
manifest: "name: test\nformat_version: 3.7.0\n",
expectError: false,
},
"invalid_missing_field": {
manifest: "name: test\nformat_version: 3.7.0\nbad_field: value\n",
expectError: true,
errorContains: "bad_field",
},
}
for name, tc := range tests {
t.Run(name, func(t *testing.T) {
pkgRoot := t.TempDir()
err := os.WriteFile(filepath.Join(pkgRoot, "manifest.yml"),
[]byte(tc.manifest), 0644)
require.NoError(t, err)
fsys := fspath.DirFS(pkgRoot)
errs := semantic.ValidateMyRule(fsys)
if tc.expectError {
require.NotEmpty(t, errs)
require.Contains(t, errs[0].Error(), tc.errorContains)
} else {
require.Empty(t, errs)
}
})
}
}Complex: test packages + validator_test.go
Use when the rule requires a full package structure (multiple data streams, pipelines, etc.).
1. Scaffold with `elastic-package create package` (cd test/packages first), or add a data stream with `elastic-package create data-stream` from inside the package directory. 2. Modify manifest.yml (and data stream files if applicable) to exercise the rule. 3. Add entries to code/go/pkg/validator/validator_test.go:
tests := map[string]struct {
invalidPkgFilePath string
expectedErrContains []string
}{
"good_my_feature": {}, // valid — no errors expected
"bad_my_feature": {
"manifest.yml",
[]string{`expected error substring here`},
},
}Validator Tests Checklist
- [ ] At least one of the above test strategies is present for every new validator.
- [ ] Tests cover both the valid and invalid cases.
- [ ] Error message substrings in
expectedErrContainsare specific enough to be meaningful.
---
6. Test Packages
Location: test/packages/ (general), compliance/testdata/packages/ (compliance-only)
Required files
The layout below is what `elastic-package` scaffolds when you create artifacts interactively: use `elastic-package create package` for a new package (integration, input, or content), or `elastic-package create data-stream` to add a data stream under an existing package. Prefer those commands over copying folders by hand so required files stay consistent.
Every package directory must contain:
my_package/
├── manifest.yml # package manifest
├── changelog.yml # at minimum: one version entry with at least one change
└── docs/
└── README.md # package documentationValid ingest pipeline
Any data stream that includes an ingest pipeline must follow this structure:
---
description: Pipeline description.
processors:
- set:
tag: set_field_name # tag is required on every processor
field: my.field
value: test
on_failure: # on_failure block is required
- set:
field: event.kind
value: pipeline_error
- set:
field: error.message
value: >-
Processor '{{{ _ingest.on_failure_processor_type }}}'
with tag '{{{ _ingest.on_failure_processor_tag }}}'
in pipeline '{{{ _ingest.pipeline }}}'
failed with message '{{{ _ingest.on_failure_message }}}'Required elements:
- Every processor must have a
tagfield. on_failuremust setevent.kindtopipeline_error.error.messagemust include all three Handlebars placeholders:
_ingest.on_failure_processor_type, _ingest.on_failure_processor_tag, _ingest.pipeline. (A fourth, _ingest.on_failure_message, is also included by convention.)
Transform packages (compliance only)
Transforms in compliance/testdata/packages/ that are installed and uninstalled across test runs must use:
dest:
index: "metrics-mypackage.my_dest_default" # no leading dot — hidden indices cause 403 on uninstall
_meta:
managed: true
run_as_kibana_system: false # use logged-in user credentials, not kibana_systemTest Packages Checklist
- [ ]
manifest.yml,changelog.yml, anddocs/README.mdall present. - [ ] Data stream ingest pipelines have
tagon each processor and a validon_failureblock. - [ ] Compliance-only transform packages use non-hidden dest index and
run_as_kibana_system: false. - [ ] Prefer `elastic-package create package` or `elastic-package create data-stream` over
manual scaffolding when adding a test package or data stream.
---
7. Compliance Feature Files
Location: compliance/features/*.feature
Version tagging
Every Scenario: must be tagged with the minimum spec version that introduced the feature:
@3.6.0
Scenario: Integration package with named input can be installed
Given the "good_v3" package is installed
...The tag controls whether the scenario runs: it is skipped if the TEST_SPEC_VERSION environment variable is lower than the tag.
Skipped scenarios
When a scenario cannot pass because upstream (Kibana or elastic-package) hasn't implemented support yet:
@3.6.0
@skip
# Pending support for qualified input names: https://github.com/elastic/kibana/pull/262138
Scenario: Integration package with OTel input can be installed
Given the "good_v3" package is installed
...Rules:
@skipmust appear directly after the version tag.- A
# Pending <description>: <url>comment must appear on the line after@skip. - The corresponding
spec/changelog.ymlentry must have a matching# Pending on <url>
comment above it.
- Both the
@skipand the# Pending oncomment in the changelog must be removed together
when the blocker is resolved.
Compliance Features Checklist
- [ ] Every
Scenario:has a@X.Y.Ztag. - [ ] Every
@skipis accompanied by a# Pending ...comment with a URL. - [ ] Changelog entry for the same feature has a matching
# Pending on <url>comment. - [ ] No scenario has
@skipwithout a tracking issue URL.
---
8. Go Style
License header
Every new .go file must begin with:
// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
// or more contributor license agreements. Licensed under the Elastic License;
// you may not use this file except in compliance with the Elastic License.Enforced by make check. Running make -C code/go update adds headers automatically.
Naming conventions
| Bad (abbreviation) | Good (full name) |
|---|---|
pkgName | packageName |
dsManifests | dataStreamManifests |
ptIdx | templateIndex |
errs (in loops) | validationErrors or be specific |
Exception: loop variables (i, j) and widely accepted short names (err, ok) are fine.
Indentation
Go files use tabs, not spaces. gofmt enforces this — run make -C code/go format.
Error messages
When creating structured errors with file paths, use fsys.Path("relative/path") rather than file.Path() to get the full package-relative path expected by the test framework:
// Good
specerrors.NewStructuredErrorf("file %q is invalid: %s", fsys.Path("_dev/test/config.yml"), err)
// Bad — path is relative within fsys, not the full package path
specerrors.NewStructuredErrorf("file %q is invalid: %s", config.Path(), err)Go Style Checklist
- [ ] License header present in every new
.gofile. - [ ] No abbreviations in variable/function names (outside
err,ok, loop vars). - [ ] Indentation uses tabs.
- [ ] Error messages use
fsys.Path()for file path references.
Related skills
FAQ
What does review-pr do?
review-pr skill documents Review a package-spec pull request or branch for completeness and correctness.
When should I use review-pr?
User asks about review-pr, review a package-spec pull request or branch for completeness and correctness. use when th.
Is this skill safe to install?
Review the Security Audits panel on this page before installing in production.