# Scorecards

[![Lines of Code](https://dynatrace-apps-sonarqube.ci.dynalabs.io/api/project_badges/measure?project=dynatrace.scorecards&metric=ncloc&token=sqb)](https://dynatrace-apps-sonarqube.ci.dynalabs.io/dashboard?id=dynatrace.scorecards)
[![Quality Gate Status](https://dynatrace-apps-sonarqube.ci.dynalabs.io/api/project_badges/measure?project=dynatrace.scorecards&metric=alert_status&token=sqb)](https://dynatrace-apps-sonarqube.ci.dynalabs.io/dashboard?id=dynatrace.scorecards)
[![Link to Scorecards in Juno](https://juno.internal.dynatrace.com/api/badges/entity/dt-platform/component/dynatrace.scorecards/badge/pingback)](https://juno.internal.dynatrace.com/catalog/dt-platform/component/dynatrace.scorecards)

A Dynatrace App that aggregates quality and security signals — acceptance testing, code coverage, security ratings, and more — into an overall grade for monitored components and services. Grades are displayed per component and version, with filtering and data exploration built in.

---

## Getting Started

**Prerequisites**: Node.js 24.x

```bash
npm install
npm run start   # opens app in Dynatrace Platform UI
```

---

## Project Structure

```
src/
  app/
    components/   # Shared React components (GradeBadge, SignalTile, Header…)
    constants/    # Shared style/CSS constants
    hooks/        # State and side-effect hooks
    models/       # TypeScript interfaces and types
    pages/        # Page-level components (Overview, Components, AppScorePage)
    requests/     # Grail DQL fetch functions and response mapping
    utils/        # Pure utility functions with co-located .spec.ts files
  api/            # Backend Dynatrace App Functions
src/**/*.spec.ts  # Unit tests (co-located with source)
component/tests/  # Playwright component tests
e2e/tests/        # Playwright E2E tests
dql/tests/        # DQL sandbox tests
a11y/tests/       # Accessibility tests
```

### App routes

| Route | Page |
|---|---|
| `/` | Redirects to `/overview` |
| `/overview` | Overview — capability/team/asset tree table |
| `/overview/aggregation` | Aggregation view — filtered, tabbed |
| `/components` | Components — flat asset table |
| `/components/:name` | App Score page — single component detail |

---

## Development Scripts

| Task | Command |
|---|---|
| TypeScript check | `npm run typecheck` |
| Lint | `npm run lint` |
| Lint with autofix | `npx eslint --fix <file>` |
| Unit tests | `npm run test:app` |
| Unit tests (specific file) | `npm run test:app -- --testPathPattern="<pattern>"` |
| Unit tests + coverage | `npm run test:app -- --testPathPattern="<pattern>" --coverage --collectCoverageFrom="<glob>"` |
| Component tests | `npm run test:ct` |
| E2E tests | `npm run test:e2e` |
| DQL sandbox tests | `npm run test:dql` |
| Accessibility tests | `npm run test:a11y` |
| Integration tests | `npm run test:it` |

Coverage gate: all four Jest metrics ≥ 90% per file.

> **E2E / DQL imports**: only import from `e2e/src/`, `dql/`, or `src/app/models/`. Importing from `src/app/utils/` or `src/app/components/` causes `SyntaxError: Unexpected token '.'` at runtime due to Strato CSS-in-JS.

---

## AI-First Development

This repository is developed with [Claude Code](https://claude.ai/code) using a shared skill set from the [QSP ESSOS AI-First tooling repo](https://github.com/Dynatrace-Internal/qsp-essos-ai-first-tooling).

### Setup

Clone the tooling repo and run these install scripts once — they install skills, rules, agents, and global config into `~/.claude/`:

```bash
# 1. Core Claude config — skills, agents, rules, CLAUDE.md
bash shared/claude/install.sh

# 2. MCP server config
bash shared/mcp-config/install.sh
```

Windows: use `shared/claude/install.ps1`. Re-run to update — scripts are safe to run repeatedly.

### Skills

| Skill | When to use |
|---|---|
| `/plan` | Research or refine a ticket into an approved plan |
| `/do` | Implement the plan — code, tests, commit |
| `/check` | Validate before merge — review, simplify, security, architecture |
| `/review` | Summarise branch changes, gap analysis, QA plan |
| `/discuss` | Explore ideas or challenge a design — no code output |
| `/tldr` | Summarize anything into key bullet points |
| `/document` | Generate or update README, feature docs, or Juno onboarding |
| `/init-claude` | Onboard a new repo with CLAUDE.md and knowledge files |

**Typical loop**: `/plan` → human approves → `/do` → verify in browser → `/check` → merge.

---

## Contributing

### Commit messages

Format: `<type>(<optional-scope>): <description>`. Use any conventional type allowed by `@commitlint/config-conventional` (for example `feat`, `fix`, `chore`, `docs`, `refactor`). Include a Jira Work Item ID (for example `QSP-123`) or `NOISSUE` somewhere in the commit message:

```
feat: add grade history chart QSP-123
chore: update ai first dev docs NOISSUE
```

`commitlint` and `husky` enforce this on every commit.
