Skip to content

Commit 7458570

Browse files
ida613claude
andcommitted
chore(skills): add code-review skill with improved structure
Improved from PR #7888: description is explicit about trigger phrases, SKILL.md body is lean (no checklist duplication), checklist is in references/ per skill anatomy conventions, and gh pr diff is the preferred method for fetching PR content. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent d14c6dd commit 7458570

File tree

2 files changed

+179
-104
lines changed

2 files changed

+179
-104
lines changed
Lines changed: 46 additions & 104 deletions
Original file line numberDiff line numberDiff line change
@@ -1,46 +1,65 @@
11
---
22
name: code-review
3-
description: >
4-
Review a PR or code change against the dd-trace-js codebase standards. Use when asked to review
5-
code, check a PR before submitting, or identify issues across architecture, correctness, style,
6-
tests, and observability. Outputs categorised comments with severity labels and fix suggestions.
7-
disable-model-invocation: true
3+
description: |
4+
Review a PR or code change against dd-trace-js codebase standards. Use this skill whenever
5+
someone asks to "review" code or a PR, types "/review", asks "can you check this before I
6+
submit", wants to identify issues in a change, asks for a code review, says "PTAL", or
7+
mentions a PR number and wants quality feedback. Also use proactively when someone is about
8+
to open a PR and wants a pre-submission check. The input can be a PR number, a file path,
9+
a diff pasted inline, or a description of the change.
810
allowed-tools: Read, Grep, Glob, Bash, WebFetch
911
---
1012

11-
You are performing a thorough code review of a dd-trace-js change. Use the checklist in
12-
[review-checklist.md](review-checklist.md) to guide your analysis. Group your output by category,
13-
label each comment by severity, and include a concrete fix suggestion for every issue raised.
13+
# Code Review
1414

15-
## Input
15+
You are performing a thorough code review of a dd-trace-js change. Work through
16+
[references/review-checklist.md](references/review-checklist.md) category by category, flag
17+
every issue you find, and always pair a finding with a concrete fix suggestion.
18+
19+
## Getting the change
1620

1721
`$ARGUMENTS` — a PR number, file path, diff, or description of the change to review.
1822

19-
If a PR number is given, use the GitHub API or WebFetch to read the diff and description:
23+
**If a PR number is given**, prefer the GitHub CLI — it handles auth and gives the full diff:
24+
25+
```bash
26+
gh pr view <PR_NUMBER> --repo DataDog/dd-trace-js # title, description, labels
27+
gh pr diff <PR_NUMBER> --repo DataDog/dd-trace-js # full unified diff
28+
```
29+
30+
If `gh` is unavailable, fall back to WebFetch:
2031
- `https://github.com/DataDog/dd-trace-js/pull/<PR_NUMBER>/files`
21-
- `https://api.github.com/repos/DataDog/dd-trace-js/pulls/<PR_NUMBER>/files`
2232

23-
If a file path is given, read the file and review it in context.
33+
**If a file path is given**, read the file and read the surrounding context (callers, tests,
34+
similar patterns in the codebase) before commenting.
2435

25-
## Output Format
36+
## How to review
37+
38+
1. Read [references/review-checklist.md](references/review-checklist.md) before starting.
39+
2. Work through each applicable category. For each finding, ask: what is the actual risk, and
40+
is there an existing pattern in the codebase the author should follow?
41+
3. For reviewer-specific preferences (what rochdev, BridgeAR, simon-id, etc. tend to flag),
42+
see `.cursor/skills/reviewer-profiles.md`.
43+
44+
## Output format
45+
46+
Group findings by category. Omit any category with no findings.
2647

2748
```
2849
## Architecture & Design
2950
3051
### [BLOCKER | CONCERN | NIT] Short title
52+
3153
**File:** path/to/file.js:line
32-
**Comment:** Specific feedback.
33-
**Suggested fix:** Concrete code or approach to address it.
3454
35-
---
55+
**Comment:** Specific feedback explaining why this matters.
3656
37-
## Performance & Memory
57+
**Suggested fix:** Concrete code or approach.
3858
39-
### [BLOCKER | CONCERN | NIT] Short title
40-
...
59+
---
4160
```
4261

43-
Repeat for each applicable category:
62+
Categories:
4463
- Architecture & Design
4564
- Performance & Memory
4665
- Configuration System
@@ -50,89 +69,12 @@ Repeat for each applicable category:
5069
- Observability & Logging
5170
- Documentation & PR Hygiene
5271

53-
Omit any category that has no findings.
54-
55-
Label each comment:
72+
Severity:
5673
- **BLOCKER** — must be fixed before merge
57-
- **CONCERN** — notable issue worth discussing; likely approved conditional on author's response
58-
- **NIT** — style/readability preference; non-blocking
59-
60-
At the end, add a `## Summary` section with an overall verdict:
61-
- "LGTM" — no significant issues
62-
- "LGTM with caveats" — concerns worth tracking but not blocking
63-
- "CHANGES_REQUESTED" — one or more BLOCKERs present
64-
65-
---
74+
- **CONCERN** — worth discussing; approval may be conditional on author's response
75+
- **NIT** — non-blocking style preference
6676

67-
## Review Checklist (read before reviewing)
68-
69-
See [review-checklist.md](review-checklist.md) for the full reference.
70-
71-
### Architecture & Design (most likely BLOCKER)
72-
- Does the code bypass an existing designed mechanism (Diagnostics Channel, store bindings,
73-
`runStores`/`bindStore`, propagator interfaces)?
74-
- Does it call internal APIs directly when a public/designed interface exists?
75-
- Does it mix cross-cutting concerns (e.g., tying baggage to span context when the systems are
76-
intentionally separate)?
77-
- Are WeakRefs used for cleanup that should go through proper store lifecycle?
78-
- Is a helper function that only wraps another function with no transformation?
79-
- Are symbols re-exported without modification?
80-
- Is a function called in only one place that could be inlined?
81-
82-
### Performance & Memory (BLOCKER or CONCERN)
83-
- Is there a risk of unbounded growth (streams, maps, listeners)?
84-
- Are there unnecessary allocations in a hot path?
85-
- If the PR claims a performance improvement, is there a benchmark?
86-
- Is a Map keyed by objects (e.g., request objects, contexts) without guaranteed cleanup? Prefer WeakMap.
87-
- Is timer-based cleanup used where it could cause sawtooth memory growth?
88-
- Is an expensive computation created eagerly when it is only needed conditionally?
89-
90-
### Configuration System (BLOCKER)
91-
- Is a new environment variable defined outside of `packages/dd-trace/src/config/index.js`?
92-
- Is it missing from `supported-configurations.json`?
93-
- Does it lack telemetry registration?
94-
- Is the config file modified in a way that looks corrupted (e.g., rebase artifact)?
95-
- Is a new boolean toggle being added that tightly mirrors an existing option?
96-
97-
### Async & Correctness (BLOCKER or CONCERN)
98-
- Are two `await` calls in sequence where rejection of the first would leave the second unhandled?
99-
Use `Promise.all([...])` instead.
100-
- Does code rely on NaN being falsy? Be explicit.
101-
- Is there an unnecessary fallback that silently changes existing behaviour (e.g., `undefined``null`)?
102-
- Does a Node.js built-in API exist that avoids a custom workaround?
103-
104-
### Test Quality (BLOCKER or CONCERN)
105-
- Are plugin tests mocking tracer internals instead of reconfiguring via public API?
106-
- Is `afterEach` cleanup missing? (Reset after an assertion = unstable test)
107-
- Does the test spy on implementation details that don't need to be tested?
108-
- Does a bug fix lack a test to verify it?
109-
- Does one `it` block depend on side effects from a previous `it` block?
110-
- Is shared mutable state missing `beforeEach`/`afterEach` setup/teardown?
111-
- Is there a redundant existence check immediately before a value assertion? Assert the value directly.
112-
- Are there copy-paste mistakes (duplicate assertions on the same property)?
113-
- Could multiple `assert.strictEqual` calls be combined into one `assert.deepStrictEqual` or
114-
`assertObjectContains`?
115-
116-
### Code Style & Readability (NIT)
117-
- Are `_underscore` prefixed properties used on a class where `#private` fields would work?
118-
- Are properties conditionally added to an object after construction, causing V8 shape changes?
119-
- Are static getters used instead of static class members? Use static properties.
120-
- Do non-class symbols have a leading capital letter? They shouldn't.
121-
- Are `require()` calls inside functions or try/catch blocks when they could be at the top of the file?
122-
- Is a try/catch wrapping more code than what can actually throw? Prefer narrow try/catch.
123-
- Are bitwise or type-coercion tricks used that are hard to follow at a glance?
124-
- Is there commented-out code that should be removed?
125-
126-
### Observability & Logging (CONCERN or NIT)
127-
- Is any existing log/debug output being removed without a replacement?
128-
- Is there a code path where a feature could silently fail without any log?
129-
- Should a `catch` block log the error?
130-
131-
### Documentation & PR Hygiene (NIT or CONCERN)
132-
- Are there unrelated changes that should be in a separate PR?
133-
- Is a new CI workflow justified, or could it go in an existing one?
134-
- Is retry logic too broad (retrying non-flaky commands)?
135-
- Does the PR add new public API surface area that needs a semver label update?
136-
- Does AGENTS.md use fenced code blocks where inline code would save tokens?
137-
- Does AGENTS.md contain inaccurate, vague, or contradictory claims?
138-
- Does moving a file to a new directory change a user-facing `require()` path?
77+
End with a `## Summary` section giving an overall verdict:
78+
- `LGTM` — no significant issues
79+
- `LGTM with caveats` — concerns worth tracking, not blocking
80+
- `CHANGES_REQUESTED` — one or more BLOCKERs present
Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
# dd-trace-js Code Review Checklist
2+
3+
Aggregated from analysis of review patterns across the primary maintainers of this repository.
4+
5+
---
6+
7+
## Architecture & Design
8+
9+
**BLOCKER when a shortcut bypasses the intended system design.**
10+
11+
- Route through designed interfaces — don't call internal APIs directly when a public interface
12+
exists (Diagnostics Channel, `runStores`/`bindStore`, propagator interfaces).
13+
- Don't mix cross-cutting concerns. Systems that are intentionally separate (e.g., baggage and
14+
span context) must stay separate.
15+
- Avoid `WeakRef` for cleanup — it has caused memory leaks in this codebase. Use proper store
16+
lifecycle (`runStores`/`bindStore`) instead.
17+
- Don't add helpers that only call another function with no transformation. Inline them.
18+
- Don't re-export symbols without modification — it adds confusion.
19+
- Functions called in only one place should be inlined for clarity.
20+
- Plugin hook setup that is repetitive should be made implicit via `addHooks`.
21+
22+
---
23+
24+
## Performance & Memory
25+
26+
**BLOCKER or CONCERN in hot paths; CONCERN elsewhere.**
27+
28+
- dd-trace runs in application hot paths — every allocation and lookup counts.
29+
- Flag unbounded collections: streams, maps, or listeners that can grow without limit.
30+
- Flag unnecessary allocations or object creation in hot paths.
31+
- A Map keyed by user-operation objects (requests, contexts) must have a guaranteed cleanup
32+
path, or use `WeakMap` instead. Timer-based cleanup is risky — it can cause sawtooth memory
33+
growth.
34+
- Prefer lazy initialisation: don't create expensive objects or run expensive computations
35+
until they are needed.
36+
- If a PR claims a performance improvement, a benchmark is required to demonstrate it.
37+
38+
---
39+
40+
## Configuration System
41+
42+
**BLOCKER when registration is missing.**
43+
44+
- New environment variables must be defined in `packages/dd-trace/src/config/index.js` inside
45+
`#applyEnvironment()`.
46+
- Every new env var must have an entry in `supported-configurations.json` with a
47+
`configurationNames` field.
48+
- Every new env var must be registered for telemetry.
49+
- `supported-configurations.json` must not be corrupted (watch for rebase artifacts).
50+
- Don't add a new boolean toggle that mirrors an existing option. If a feature is enabled by a
51+
parent config, it should not need its own sub-toggle.
52+
53+
---
54+
55+
## Async & Correctness
56+
57+
**BLOCKER for unhandled rejections; CONCERN for logic issues.**
58+
59+
- Sequential `await` calls where rejection of the first would leave the second as an unhandled
60+
rejection must be rewritten as `Promise.all([...])`.
61+
- Don't rely on NaN being falsy — be explicit. TypeScript rejects it and it obscures intent.
62+
- Don't introduce a fallback that silently changes existing behaviour (e.g., `undefined``null`).
63+
- Check whether a Node.js built-in API already solves the problem before writing a custom
64+
workaround.
65+
66+
---
67+
68+
## Test Quality
69+
70+
**BLOCKER for missing bug-fix tests or broken test isolation; CONCERN for flakiness risks.**
71+
72+
- Every bug fix must have a test that would have caught the bug.
73+
- Plugin tests are integration tests — don't mock tracer internals. Reconfigure via the public
74+
API instead.
75+
- Cleanup/reset logic must be in `afterEach`, not after an assertion. If the assertion throws,
76+
the reset never runs.
77+
- Don't spy on implementation details — test behaviour only.
78+
- Each `it` block must be independently runnable with `it.only`. If it depends on side effects
79+
from a previous `it`, move the shared setup into `beforeEach` and teardown into `afterEach`.
80+
- Don't add an existence check (`assert(x.foo)`) immediately before asserting the value
81+
(`assert.strictEqual(x.foo, 'bar')`). Assert the value directly.
82+
- Combine multiple `assert.strictEqual` calls on the same object into a single
83+
`assert.deepStrictEqual` or `assertObjectContains` call.
84+
- Check for copy-paste mistakes: duplicate assertions on the same property.
85+
86+
---
87+
88+
## Code Style & Readability
89+
90+
**NIT unless it affects correctness.**
91+
92+
- Use `#private` class fields instead of `_underscore` prefixes for class-internal state.
93+
- Pre-construct objects with all possible fields (some `undefined`) to keep V8 object shapes
94+
stable. Don't conditionally add properties after construction.
95+
- Use static class properties, not static getters (static getters are a holdover from before
96+
static properties were supported).
97+
- Non-class symbols must not have a leading capital letter.
98+
- `require()` calls must be at the top of the file. Only the instantiation (not the require)
99+
should be inside try/catch if the require itself cannot fail.
100+
- Keep try/catch blocks narrow — wrap only the code that can actually throw.
101+
- Avoid bitwise or type-coercion tricks that require knowing operator precedence or implicit
102+
coercion rules. Write explicit, readable code.
103+
- Remove commented-out code before merging.
104+
105+
---
106+
107+
## Observability & Logging
108+
109+
**CONCERN when silent failures are possible; NIT for improvements.**
110+
111+
- Don't remove existing log or debug output without a replacement. Diagnostic information helps
112+
production debugging.
113+
- Any code path where a feature could silently fail should have a log statement.
114+
- `catch` blocks that swallow errors should log them.
115+
- Log at the point of failure, not only at the call site.
116+
117+
---
118+
119+
## Documentation & PR Hygiene
120+
121+
**CONCERN or NIT.**
122+
123+
- Unrelated changes belong in a separate PR.
124+
- A new CI workflow must be justified — prefer adding to an existing workflow.
125+
- Retry logic must be scoped: only commands that can be flaky (e.g., registry installs) should
126+
be retried.
127+
- New public API surface area requires a semver-minor label and may require a corresponding PR
128+
in dd-trace-api-js.
129+
- AGENTS.md: prefer inline code over fenced code blocks (token efficiency). Avoid vague
130+
language; use concrete examples.
131+
- AGENTS.md must not contain inaccurate or contradictory claims, and should not include
132+
contributing-guide content that belongs in CONTRIBUTING.md.
133+
- Moving a file to a new directory must not change a user-facing `require()` path.

0 commit comments

Comments
 (0)