Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions .claude/CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,23 @@ See @../AGENTS.md for project guidelines.

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

See @rules/che-dashboard-dev.md for development conventions — commits, CSS, deps, git patterns, accessibility.

## Available Skills

Project-specific skills live in `.claude/skills/`. Invoke with `/skill-name`:

| Skill | When to use |
|---|---|
| `commit-message` | Write a human-style commit message following project conventions |
| `manage-resolutions` | Audit and clean up the `resolutions` field in `package.json` |
| `fix-cve-dep` | Upgrade a vulnerable npm dependency (CVE/Jira ticket) |
| `rebase-to-main` | Rebase a branch onto latest main, resolve `.deps/` conflicts, force-push |
| `fix-pr-feedback` | Fetch PR review comments, triage fixed vs open, apply outstanding fixes |
| `check-coverage` | Verify test coverage meets thresholds before opening a PR |
| `pr-test-section` | Write the "Is it tested? How?" section of a PR description |
| `pr-description` | Generate a PR description and save to `openspec/docs/` (run `check-coverage` first) |

## Hard Rules

- **No `any` type**: NEVER use `any` or cast to `any` in TypeScript code. Use proper types, type guards, `unknown`, or specific interfaces instead.
164 changes: 164 additions & 0 deletions .claude/rules/che-dashboard-dev.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
# che-dashboard Development Conventions

---

## 1. Commit Trailers

Only these trailers are permitted:

```
Assisted-by: {AGENT_NAME}
Signed-off-by: {AUTHOR_NAME} <{AUTHOR_EMAIL}>
```

`{AGENT_NAME}` — specific agent name, e.g. `Claude Sonnet 4.6`.
`{AUTHOR_NAME}` / `{AUTHOR_EMAIL}` — from `git config user.name` / `git config user.email`.

**Do NOT add:** `Made-with`, `Co-authored-by`, or duplicate trailers.
**Do NOT add** AI explanation comments inside source code.
**On amend:** always pass the full message with `-m "..."` so trailers are not stacked.

### Commit message format

- Subject line ≤ 50 chars, conventional commits: `type(scope): short description`
- Common types: `fix`, `feat`, `chore`, `refactor`, `test`, `docs`

### Example

```
fix(ui): prevent error message from overflowing the ErrorReporter widget

Assisted-by: Claude Sonnet 4.6
Signed-off-by: Jane Developer <jane@example.com>
```

---

## 2. Pre-commit Checks

**Before each commit** (fast — run every time):

```bash
yarn lint:fix
yarn format:fix
yarn workspace @eclipse-che/dashboard-frontend test --testPathPatterns="ComponentName" --no-cache
```

**Before pushing / opening a PR** (full suite):

```bash
yarn build
yarn test
```

Follow the Surgical Change Workflow in `AGENTS.md` — targeted test runs before commit, full suite before push.

### Updating snapshots

When rendering changes break existing snapshots:

```bash
yarn workspace @eclipse-che/dashboard-frontend test --testPathPatterns="ComponentName" --updateSnapshot
```

Always verify the snapshot diff makes sense before committing.

---

## 3. Dependency Changes — License Regeneration

When `package.json` or `yarn.lock` changes:

```bash
yarn license:generate
```

If it exits with **"UNRESOLVED dependencies"**, add the missing package to `.deps/EXCLUDED/dev.md` (dev dep) or `.deps/EXCLUDED/prod.md` (runtime dep):

```markdown
| `package-name@X.Y.Z` | [clearlydefined](https://clearlydefined.io/definitions/npm/npmjs/-/package-name/X.Y.Z) |
```

Then re-run `yarn license:generate`. Remove entries for packages no longer in `yarn.lock`.

---

## 4. CSS Property Ordering

This project uses `stylelint-config-clean-order`. Follow these group conventions:

| Group | Properties |
|-------|-----------|
| Layout | `position`, `z-index`, `overflow`, `overflow-x`, `overflow-y`, `display`, `flex-*`, `grid-*` |
| Box/Size | `box-sizing`, `width`, `min-width`, `max-width`, `height`, `margin`, `padding` |
| Typography | `font-*`, `color`, `text-*`, `word-break`, `white-space`, `line-height` |
| Visual | `background`, `background-color`, `border*`, `border-radius`, `box-shadow` |
| Animation | `transition`, `animation` |

- Empty lines **between groups** when rule has ≥ 5 properties
- **No empty lines within a group**

---

## 5. Error Handling

Use typed error classes with status codes instead of string matching:

```typescript
export class GitClientError extends Error {
constructor(public readonly statusCode: number, message: string) {
super(message);
this.name = 'GitClientError';
}
}

// In route handler:
const statusCode = e instanceof GitClientError ? e.statusCode : 500;
reply.status(statusCode).send(helpers.errors.getMessage(e));
```

---

## 6. Git Workflow Patterns

### Squash all branch commits into one

```bash
git reset $(git merge-base origin/main HEAD)
git add -A
git commit -m "feat: ..."
```

### Strip forbidden trailers from new local commits (not yet pushed)

Use only on commits that have never been pushed. Once a branch has a remote tracking branch, use `git rebase -i` to reword commit messages instead.

```bash
FILTER_BRANCH_SQUELCH_WARNING=1 git filter-branch -f --msg-filter \
'sed "/^Made-with:/d; /^Co-authored-by:/d"' \
-- HEAD~1..HEAD

git update-ref -d refs/original/refs/heads/$(git branch --show-current)
```

Note: `--msg-filter` only rewrites commit messages — no stash needed.

### Resolve .deps merge conflicts

```bash
git checkout --theirs .deps/EXCLUDED/dev.md .deps/EXCLUDED/prod.md
git add .deps/EXCLUDED/dev.md .deps/EXCLUDED/prod.md
```

Then re-run `yarn license:generate` after the rebase continues.

---

## 7. Accessibility and UI Conventions

- Icon hover color: `var(--pf-t--global--icon--color--subtle)` default, `var(--pf-t--global--text--color--link--default)` on hover
- Tooltip `<a>` link colors: inverse background — use dark tokens in light theme, light tokens in dark theme (see the tooltip CSS module)
- Keyboard toggle for `Switch`: wrap in `<div onKeyDown>` and handle `Enter`
- Keyboard selection in `Select`/`SelectOption` with `hasCheckbox`: add explicit `onKeyDown` on each `SelectOption`
- `ErrorReporter` overlay: `position: fixed; inset: 0; z-index: 9999`
- Error `<pre>` blocks: `max-width: 100%; overflow-x: auto`
123 changes: 123 additions & 0 deletions .claude/skills/check-coverage/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
---
name: check-coverage
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.
---

# Check Test Coverage

## Coverage thresholds (enforced by CI)

| Package | Statements | Branches | Functions | Lines |
|---|---|---|---|---|
| `common` | 99% | 99% | **100%** | 99% |
| `dashboard-frontend` | 92% | 88% | 85% | 92% |
| `dashboard-backend` | 86% | 80% | 86% | 86% |

## Workflow

### 1. Identify changed packages

```bash
git diff origin/main..HEAD --name-only | grep "^packages/" | cut -d/ -f2 | sort -u
```

Only run coverage for packages with changed files.

### 2. Run coverage

```bash
yarn workspace @eclipse-che/common test --coverage --no-cache
yarn workspace @eclipse-che/dashboard-frontend test --coverage --no-cache
yarn workspace @eclipse-che/dashboard-backend test --coverage --no-cache
```

Look for the `Coverage summary` block at the end:

```
Statements : 91.5% ( 1001/1094 ) ← must be ≥ threshold
Branches : 87.2% ( 106/122 )
Functions : 84.6% ( 22/26 )
Lines : 91.5% ( 1001/1094 )
Jest: "global" coverage threshold for statements (92%) not met: 91.5%
```

All thresholds met → go to step 5.

### 3. Find uncovered code

```bash
yarn workspace @eclipse-che/<package> test --coverage --no-cache \
--coverageReporters=text 2>&1 | grep "| " | \
awk -F'|' '{if ($3+0 < 90 || $4+0 < 85 || $5+0 < 85) print}' | head -20
```

Also check whether changed source files have corresponding test files:

```bash
# Changed source files (not tests)
git diff origin/main..HEAD --name-only | grep "^packages/<pkg>/src" | grep -v "__tests__\|spec\|mock"
# Expected test location: src/<path>/__tests__/<name>.spec.ts
```

### 4. Write missing tests

For each uncovered file or function:

1. Read the source file
2. Create or update `__tests__/<name>.spec.ts`
3. Cover happy path, error path, edge cases, and both sides of every branch

Iterate quickly with `--testPathPatterns`:

```bash
yarn workspace @eclipse-che/<package> test \
--testPathPatterns "<FileName>" --coverage --no-cache
```

### 5. Verify thresholds

```bash
yarn workspace @eclipse-che/<package> test --coverage --no-cache 2>&1 | tail -10
```

Must show no `"coverage threshold … not met"` lines. Do not proceed to PR description until every changed package passes.

## Common patterns for untested code

### New utility function
```typescript
it('returns X for valid input', () => { ... });
it('throws for invalid input', () => { ... });
it('handles empty array', () => { ... });
```

### New React component
```typescript
it('renders without crashing', () => { renderComponent(); });
it('shows error state when prop is true', () => { ... });
it('calls callback on button click', () => { ... });
```

### New async action / Redux thunk
```typescript
it('dispatches success on 200', async () => { ... });
it('dispatches error on network failure', async () => { ... });
```

### New API route (backend)
```typescript
it('returns 200 with correct body', async () => { ... });
it('returns 403 when not authorized', async () => { ... });
```

## What NOT to test (excluded from coverage)

- `src/**/__tests__/**` — test files themselves
- `src/**/*.d.ts` — type declarations
- `src/**/*.config.ts` — config files
- `src/index.tsx`, `src/App.tsx`, `src/Routes.tsx` — frontend entry points
- `src/localRun/**`, `src/utils/**`, `src/server.ts` — backend exclusions

## Note on snapshots

Updating snapshots (`--updateSnapshot`) does not improve branch/function coverage. Add behavioral tests alongside snapshot updates when coverage is at risk.
Loading
Loading