Skip to content

Commit 9f828fd

Browse files
committed
chore(claude): add project skills and generalize dev-conventions rules
Add five Claude Code skills distilled from recurring che-dashboard development workflows: - fix-cve-dep: upgrade a vulnerable npm dep, check ClearlyDefined, pin in resolutions, regenerate .deps files, commit and push - rebase-to-main: rebase a branch onto main, resolve .deps conflicts (take-theirs + regenerate), run license check, force-push - fix-pr-feedback: fetch and triage GitHub PR review comments, fix open items, commit and push - check-coverage: run coverage for changed packages, find uncovered code, write missing tests; enforces thresholds (common 99/100, frontend 92/88/85, backend 86/80/86) before PR is opened - pr-description: generate a PR description from branch context and save to openspec/docs/ following project template (check-coverage must pass first) Update CLAUDE.md to reference the new rules file and list all skills. Update AGENTS.md to reference .claude/rules/ and document all skills. Simplify .claude/rules/che-dashboard-dev.mdc (292 → 173 lines): - Remove §2 pre-push trailer cleanup (Cursor IDE defense) - Remove §7 building local images (human how-to, not an AI rule) - Remove §8 PR descriptions (superseded by pr-description skill) - Fix §3: split pre-commit (fast) vs pre-push (full suite) - Fix §4 dep format example to match actual .deps/prod.md format - Remove duplicate --updateSnapshot and tooltip CSS sub-section Remove personal identity data from all rules and skill files: - Signed-off-by uses {AUTHOR_NAME} <{AUTHOR_EMAIL}> placeholder - quay.io/oorel/ replaced with quay.io/{YOUR_QUAY_USERNAME}/ Assisted-by: Claude Sonnet 4.6 Signed-off-by: Oleksii Orel <oorel@redhat.com>
1 parent 6767dad commit 9f828fd

11 files changed

Lines changed: 1297 additions & 1 deletion

File tree

.claude/CLAUDE.md

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,23 @@ See @../AGENTS.md for project guidelines.
44

55
See @../redhat-compliance-and-responsible-ai.md for Red Hat compliance and responsible AI rules.
66

7+
See @rules/che-dashboard-dev.md for development conventions — commits, CSS, deps, git patterns, accessibility.
8+
9+
## Available Skills
10+
11+
Project-specific skills live in `.claude/skills/`. Invoke with `/skill-name`:
12+
13+
| Skill | When to use |
14+
|---|---|
15+
| `commit-message` | Write a human-style commit message following project conventions |
16+
| `manage-resolutions` | Audit and clean up the `resolutions` field in `package.json` |
17+
| `fix-cve-dep` | Upgrade a vulnerable npm dependency (CVE/Jira ticket) |
18+
| `rebase-to-main` | Rebase a branch onto latest main, resolve `.deps/` conflicts, force-push |
19+
| `fix-pr-feedback` | Fetch PR review comments, triage fixed vs open, apply outstanding fixes |
20+
| `check-coverage` | Verify test coverage meets thresholds before opening a PR |
21+
| `pr-test-section` | Write the "Is it tested? How?" section of a PR description |
22+
| `pr-description` | Generate a PR description and save to `openspec/docs/` (run `check-coverage` first) |
23+
724
## Hard Rules
825

926
- **No `any` type**: NEVER use `any` or cast to `any` in TypeScript code. Use proper types, type guards, `unknown`, or specific interfaces instead.

.claude/rules/che-dashboard-dev.md

Lines changed: 168 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,168 @@
1+
# che-dashboard Development Conventions
2+
3+
---
4+
5+
## 1. Commit Trailers
6+
7+
Only these trailers are permitted:
8+
9+
```
10+
Assisted-by: {AGENT_NAME}
11+
Signed-off-by: {AUTHOR_NAME} <{AUTHOR_EMAIL}>
12+
```
13+
14+
`{AGENT_NAME}` — specific agent name, e.g. `Claude Sonnet 4.6`.
15+
`{AUTHOR_NAME}` / `{AUTHOR_EMAIL}` — from `git config user.name` / `git config user.email`.
16+
17+
**Do NOT add:** `Made-with`, `Co-authored-by`, or duplicate trailers.
18+
**Do NOT add** AI explanation comments inside source code.
19+
**On amend:** always pass the full message with `-m "..."` so trailers are not stacked.
20+
21+
### Commit message format
22+
23+
- Subject line ≤ 50 chars, conventional commits: `type(scope): short description`
24+
- Common types: `fix`, `feat`, `chore`, `refactor`, `test`, `docs`
25+
26+
### Example
27+
28+
```
29+
fix(ui): prevent error message from overflowing the ErrorReporter widget
30+
31+
Assisted-by: Claude Sonnet 4.6
32+
Signed-off-by: Jane Developer <jane@example.com>
33+
```
34+
35+
---
36+
37+
## 2. Pre-commit Checks
38+
39+
**Before each commit** (fast — run every time):
40+
41+
```bash
42+
yarn lint:fix
43+
yarn format:fix
44+
yarn workspace @eclipse-che/dashboard-frontend test --testPathPatterns="ComponentName" --no-cache
45+
```
46+
47+
**Before pushing / opening a PR** (full suite):
48+
49+
```bash
50+
yarn build
51+
yarn test
52+
```
53+
54+
Follow the Surgical Change Workflow in `AGENTS.md` — targeted test runs before commit, full suite before push.
55+
56+
### Updating snapshots
57+
58+
When rendering changes break existing snapshots:
59+
60+
```bash
61+
yarn workspace @eclipse-che/dashboard-frontend test --testPathPatterns="ComponentName" --updateSnapshot
62+
```
63+
64+
Always verify the snapshot diff makes sense before committing.
65+
66+
---
67+
68+
## 3. Dependency Changes — License Regeneration
69+
70+
When `package.json` or `yarn.lock` changes:
71+
72+
```bash
73+
yarn license:generate
74+
```
75+
76+
If it exits with **"UNRESOLVED dependencies"**, add the missing package to `.deps/EXCLUDED/dev.md` (dev dep) or `.deps/EXCLUDED/prod.md` (runtime dep):
77+
78+
```markdown
79+
| `package-name@X.Y.Z` | [clearlydefined](https://clearlydefined.io/definitions/npm/npmjs/-/package-name/X.Y.Z) |
80+
```
81+
82+
Then re-run `yarn license:generate`. Remove entries for packages no longer in `yarn.lock`.
83+
84+
---
85+
86+
## 4. CSS Property Ordering
87+
88+
This project uses `stylelint-config-clean-order`. Follow these group conventions:
89+
90+
| Group | Properties |
91+
|-------|-----------|
92+
| Layout | `position`, `z-index`, `overflow`, `overflow-x`, `overflow-y`, `display`, `flex-*`, `grid-*` |
93+
| Box/Size | `box-sizing`, `width`, `min-width`, `max-width`, `height`, `margin`, `padding` |
94+
| Typography | `font-*`, `color`, `text-*`, `word-break`, `white-space`, `line-height` |
95+
| Visual | `background`, `background-color`, `border*`, `border-radius`, `box-shadow` |
96+
| Animation | `transition`, `animation` |
97+
98+
- Empty lines **between groups** when rule has ≥ 5 properties
99+
- **No empty lines within a group**
100+
101+
---
102+
103+
## 5. Error Handling
104+
105+
Use typed error classes with status codes instead of string matching:
106+
107+
```typescript
108+
export class GitClientError extends Error {
109+
constructor(public readonly statusCode: number, message: string) {
110+
super(message);
111+
this.name = 'GitClientError';
112+
}
113+
}
114+
115+
// In route handler:
116+
const statusCode = e instanceof GitClientError ? e.statusCode : 500;
117+
reply.status(statusCode).send(helpers.errors.getMessage(e));
118+
```
119+
120+
---
121+
122+
## 6. Git Workflow Patterns
123+
124+
### Squash all branch commits into one
125+
126+
```bash
127+
git reset $(git merge-base origin/main HEAD)
128+
git add -A
129+
git commit -m "feat: ..."
130+
```
131+
132+
### Strip forbidden trailers from a range
133+
134+
```bash
135+
# upstream exists:
136+
FILTER_BRANCH_SQUELCH_WARNING=1 git filter-branch -f --msg-filter \
137+
'sed "/^Made-with:/d; /^Co-authored-by:/d"' \
138+
-- origin/BRANCH..HEAD
139+
140+
# no upstream yet:
141+
FILTER_BRANCH_SQUELCH_WARNING=1 git filter-branch -f --msg-filter \
142+
'sed "/^Made-with:/d; /^Co-authored-by:/d"' \
143+
-- HEAD~1..HEAD
144+
145+
git update-ref -d refs/original/refs/heads/$(git branch --show-current)
146+
```
147+
148+
Note: `--msg-filter` only rewrites commit messages — no stash needed.
149+
150+
### Resolve .deps merge conflicts
151+
152+
```bash
153+
git checkout --theirs .deps/EXCLUDED/dev.md .deps/EXCLUDED/prod.md
154+
git add .deps/EXCLUDED/dev.md .deps/EXCLUDED/prod.md
155+
```
156+
157+
Then re-run `yarn license:generate` after the rebase continues.
158+
159+
---
160+
161+
## 7. Accessibility and UI Conventions
162+
163+
- Icon hover color: `var(--pf-t--global--icon--color--subtle)` default, `var(--pf-t--global--text--color--link--default)` on hover
164+
- Tooltip `<a>` link colors: inverse background — use dark tokens in light theme, light tokens in dark theme (see the tooltip CSS module)
165+
- Keyboard toggle for `Switch`: wrap in `<div onKeyDown>` and handle `Enter`
166+
- Keyboard selection in `Select`/`SelectOption` with `hasCheckbox`: add explicit `onKeyDown` on each `SelectOption`
167+
- `ErrorReporter` overlay: `position: fixed; inset: 0; z-index: 9999`
168+
- Error `<pre>` blocks: `max-width: 100%; overflow-x: auto`
Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
---
2+
name: check-coverage
3+
description: Run test coverage for all packages changed on this branch and identify uncovered code. Always invoke before writing a PR description, after adding new code, or when a PR receives coverage-related review feedback. Prevents CI coverage failures and catches untested code before reviewers do.
4+
---
5+
6+
# Check Test Coverage
7+
8+
## Coverage thresholds (enforced by CI)
9+
10+
| Package | Statements | Branches | Functions | Lines |
11+
|---|---|---|---|---|
12+
| `common` | 99% | 99% | **100%** | 99% |
13+
| `dashboard-frontend` | 92% | 88% | 85% | 92% |
14+
| `dashboard-backend` | 86% | 80% | 86% | 86% |
15+
16+
## Workflow
17+
18+
### 1. Identify changed packages
19+
20+
```bash
21+
git diff origin/main..HEAD --name-only | grep "^packages/" | cut -d/ -f2 | sort -u
22+
```
23+
24+
Only run coverage for packages with changed files.
25+
26+
### 2. Run coverage
27+
28+
```bash
29+
yarn workspace @eclipse-che/common test --coverage --no-cache
30+
yarn workspace @eclipse-che/dashboard-frontend test --coverage --no-cache
31+
yarn workspace @eclipse-che/dashboard-backend test --coverage --no-cache
32+
```
33+
34+
Look for the `Coverage summary` block at the end:
35+
36+
```
37+
Statements : 91.5% ( 1001/1094 ) ← must be ≥ threshold
38+
Branches : 87.2% ( 106/122 )
39+
Functions : 84.6% ( 22/26 )
40+
Lines : 91.5% ( 1001/1094 )
41+
Jest: "global" coverage threshold for statements (92%) not met: 91.5%
42+
```
43+
44+
All thresholds met → go to step 5.
45+
46+
### 3. Find uncovered code
47+
48+
```bash
49+
yarn workspace @eclipse-che/<package> test --coverage --no-cache \
50+
--coverageReporters=text 2>&1 | grep "| " | \
51+
awk -F'|' '{if ($3+0 < 90 || $4+0 < 85 || $5+0 < 85) print}' | head -20
52+
```
53+
54+
Also check whether changed source files have corresponding test files:
55+
56+
```bash
57+
# Changed source files (not tests)
58+
git diff origin/main..HEAD --name-only | grep "^packages/<pkg>/src" | grep -v "__tests__\|spec\|mock"
59+
# Expected test location: src/<path>/__tests__/<name>.spec.ts
60+
```
61+
62+
### 4. Write missing tests
63+
64+
For each uncovered file or function:
65+
66+
1. Read the source file
67+
2. Create or update `__tests__/<name>.spec.ts`
68+
3. Cover happy path, error path, edge cases, and both sides of every branch
69+
70+
Iterate quickly with `--testPathPatterns`:
71+
72+
```bash
73+
yarn workspace @eclipse-che/<package> test \
74+
--testPathPatterns "<FileName>" --coverage --no-cache
75+
```
76+
77+
### 5. Verify thresholds
78+
79+
```bash
80+
yarn workspace @eclipse-che/<package> test --coverage --no-cache 2>&1 | tail -10
81+
```
82+
83+
Must show no `"coverage threshold … not met"` lines. Do not proceed to PR description until every changed package passes.
84+
85+
## Common patterns for untested code
86+
87+
### New utility function
88+
```typescript
89+
it('returns X for valid input', () => { ... });
90+
it('throws for invalid input', () => { ... });
91+
it('handles empty array', () => { ... });
92+
```
93+
94+
### New React component
95+
```typescript
96+
it('renders without crashing', () => { renderComponent(); });
97+
it('shows error state when prop is true', () => { ... });
98+
it('calls callback on button click', () => { ... });
99+
```
100+
101+
### New async action / Redux thunk
102+
```typescript
103+
it('dispatches success on 200', async () => { ... });
104+
it('dispatches error on network failure', async () => { ... });
105+
```
106+
107+
### New API route (backend)
108+
```typescript
109+
it('returns 200 with correct body', async () => { ... });
110+
it('returns 403 when not authorized', async () => { ... });
111+
```
112+
113+
## What NOT to test (excluded from coverage)
114+
115+
- `src/**/__tests__/**` — test files themselves
116+
- `src/**/*.d.ts` — type declarations
117+
- `src/**/*.config.ts` — config files
118+
- `src/index.tsx`, `src/App.tsx`, `src/Routes.tsx` — frontend entry points
119+
- `src/localRun/**`, `src/utils/**`, `src/server.ts` — backend exclusions
120+
121+
## Note on snapshots
122+
123+
Updating snapshots (`--updateSnapshot`) does not improve branch/function coverage. Add behavioral tests alongside snapshot updates when coverage is at risk.

0 commit comments

Comments
 (0)