{"owner":"open-metadata","repo":"OpenMetadata","hasSkills":true,"totalSkillsCount":6,"totalTokensCount":8760,"categories":["root-instruction","claude-rule","copilot-instructions","mcp-config","marketplace","plugin-manifest"],"hasMcp":true,"mcpConfig":{"mcpServers":{"OpenMetadata":{"command":"npx","args":["-y","@modelcontextprotocol/server-OpenMetadata"]}}},"found":["AGENTS.md","CLAUDE.md",".github/copilot-instructions.md",".cursor/mcp.json",".claude-plugin/marketplace.json",".claude-plugin/plugin.json"],"skills":{"AGENTS.md":"# AGENTS.md\n\nAlways-loaded guidance for every session, whatever the harness — **the only instruction file:** every `CLAUDE.md` and\n`.github/copilot-instructions.md` is a symlink to the `AGENTS.md` beside it\n(ADR:2026-10-09-agents-md-is-the-one-instruction-file), so edit this file, never a copy. **Language- and path-specific\nrules live in `.claude/rules/*.md` (Claude Code auto-loads them on matching files; other harnesses read the matching\none before editing); procedures live in skills (loaded on invoke).** This file is the map — see the pointer index at\nthe bottom. Read [ARCHITECTURE.md](ARCHITECTURE.md) for the **system map** (modules, the request/ingestion/search\npaths, the invariants that hold); read [DEVELOPER.md](DEVELOPER.md) for **how to build, test, and add an entity or\nconnector** (deep dives + end-to-end checklists). Consult [docs/index.md](docs/index.md) — the **knowledge index** —\nto **find existing design, plan, and reference docs** for whatever area you're working on.\n\n## About OpenMetadata\n\nOpenMetadata is a unified metadata platform for data discovery, observability, and governance — a\nmulti-module project with a Java backend, a React/TypeScript frontend, a Python ingestion framework,\nand Docker infrastructure.\n\n## Stack at a glance\n\n- **Backend**: Java 21 + Dropwizard, multi-module Maven.\n- **Frontend**: React + TypeScript, built with **Vite** (dev server on :3000); component library\n  `openmetadata-ui-core-components` — the **UntitledUI + Tailwind v4** (`tw:` prefix, react-aria-components)\n  go-forward design system; legacy stack is Ant Design + Less (deprecated). Machine-readable design-system\n  specs: `openmetadata-ui/src/main/resources/ui/specs/` (read `specs/README.md` before UI work).\n- **Ingestion**: Python (`>=3.10`, no pinned ceiling; **CI runs 3.10**) + Pydantic 2.x, 75+ connectors.\n- **Database**: MySQL (default) or PostgreSQL. **Search**: Elasticsearch 7.17+ or OpenSearch 2.6+.\n- **Infrastructure**: Apache Airflow for ingestion orchestration.\n\n## Environment setup (every session)\n\n- **Python venv is REQUIRED before any Python work, `make generate`, or `make install_dev*`:**\n  ```bash\n  source env/bin/activate          # first time: python3.11 -m venv env\n  python --version                 # expect 3.10.x/3.11.x\n  ```\n  In a Claude Code **worktree** the venv is NOT copied — create one\n  (`python3.11 -m venv env && source env/bin/activate && cd ingestion && make install_dev`) or\n  symlink the main repo's (`ln -s /path/to/main-repo/env env`).\n- **One-call setup (macOS + Linux)**: `make dev_setup` (or `./scripts/dev_setup.sh`) does everything\n  below — toolchain, venv, generation, UI deps, pre-commit — and is idempotent. `make dev_check`\n  diagnoses an existing checkout without changing it. See the `dev-setup` skill.\n- **First-time bootstrap** (from the **repo root** — `make generate` is a root-only target; it does\n  not exist under `ingestion/`):\n  ```bash\n  make prerequisites\n  source env/bin/activate && cd ingestion && make install_dev_env && cd ..\n  make generate                    # regenerate models after any schema change\n  make yarn_install_cache\n  make install_test precommit_install   # activate the commit-time format/license gate (pre-commit)\n  ```\n  The last line installs the `pre-commit` hooks (`.pre-commit-config.yaml`): on `git commit` they run\n  Java format (spotless), Python format (ruff), UI format (prettier), design-token, and Apache-2.0\n  license checks on your changed files, matching CI. Do not skip them with `--no-verify`.\n- **Java**: Java 21; use `mvn`. **Frontend**: use `yarn` (never `npm`); frontend root is `openmetadata-ui/src/main/resources/ui/`.\n- **Docker dev services**: `docker compose -f docker/development/docker-compose.yml up -d`.\n\n## Repository layout\n\nMaven modules (reactor order is computed from the graph, not this list):\n\n- `openmetadata-spec/` — JSON Schemas + generated POJOs; the schema-first source of truth\n- `openmetadata-sdk/` — Java client SDK\n- `common/` — shared utilities (`CommonUtil`, etc.)\n- `openmetadata-shaded-deps/` — ES/OS clients relocated behind `es.*`/`os.*` (do not edit — see rules)\n- `openmetadata-service/` — core Java backend, REST APIs, repositories, migrations runner\n- `openmetadata-k8s-operator/` — Kubernetes operator\n- `openmetadata-integration-tests/` — backend API integration tests (`*IT.java`)\n- `openmetadata-mcp/` — MCP server\n- `openmetadata-ui-core-components/` — canonical React component library\n- `openmetadata-ui/src/main/resources/ui/` — React frontend application\n- `openmetadata-dist/` — packaging/distribution\n- `openmetadata-clients/` — client artifacts\n\nOther key trees: `ingestion/` (Python framework + connectors), `bootstrap/sql/` (DB migrations), `conf/` (configuration), `docker/` (local + prod deployment).\n\n## Hard cross-cutting constraints (apply to every session, all languages)\n\n**Secrets & security.** Never commit secrets — use environment variables or a secrets manager.\nAuth is JWT with OAuth2/SAML; RBAC lives in Java entities; config in `conf/openmetadata.yaml`.\n**Do not modify `.github/workflows/**` on your own** — CI workflows are a supply-chain surface; a\n`PreToolUse` hook blocks edits there unless the user explicitly authorizes them (by setting\n`CLAUDE_ALLOW_WORKFLOW_EDITS=1`). Ask first.\n\n**All caches MUST be bounded.** Never use a bare `dict` / `HashMap` / `Map` as a cache without an\nexplicit size cap — they grow with input and OOM on large catalogs/ingestions (only exception: the\nuser explicitly asks for unbounded). Pick a sane default (100–1000 entries); if unsure, ask.\nPython: `collections.OrderedDict` + `popitem(last=False)`, `@functools.lru_cache(maxsize=N)`, or\n`cachetools.LRUCache` (cache hits **and** misses). Java: Caffeine/Guava `maximumSize(N)`.\nTypeScript: `lru-cache`. Before adding a cache, check it isn't already cached a layer down (e.g.\n`OpenMetadata._search_es_entity` is already `@lru_cache(maxsize=512)`).\n\n**Comments explain *why*, never restate code.** Do NOT add comments that describe what obvious code\ndoes (`// Create user` before `createUser()`). Only comment complex business logic, non-obvious\nalgorithms/workarounds, public-API JavaDoc, or `TODO/FIXME` with a ticket reference. If code needs a\ncomment to be understood, refactor it to be clearer instead.\n\n**Testing philosophy.** Test real behavior, not mock wiring — if a test mocks 3+ of your own classes\nto verify a method call, it tests the wrong thing. Prefer integration tests over heavily-mocked unit\ntests (this project has real ITs: `OpenMetadataApplicationTest`, Docker, real OpenSearch). Mocks are\nfor boundaries (HTTP clients, third-party APIs), not internals. Ask \"what breaks if this test passes\nbut the code is wrong?\" — if the answer is \"nothing\", rewrite it. Assert on observable outcomes\n(API responses, DB state), not internal `verify()` calls.\n\n**License headers are per-module — copy one from a sibling file, never assume Apache.** UI TS/TSX:\nApache-2.0 (`yarn license-header-fix`). Python: `ingestion/` is **Collate Community License 1.0** (`ingestion/LICENSE`); `openmetadata-airflow-apis/` Python files use the same Collate header template.\nJava: Apache-2.0, most files carry none.\nOnly the UI is enforced — the `ui-license-header` pre-commit hook and CI `ui-checkstyle`; spotless\nand `py_format_check` never look at headers, so a wrong Python or Java header ships silently.\n\n**Schema-first.** JSON Schemas in `openmetadata-spec/` are the single source of truth; all generated\ncode (Java POJOs, Pydantic models, TS types) is derived. **Edit the schema, then regenerate — never\nhand-edit generated output.** Details in `.claude/rules/schema-first.md`.\n\n**Output style.** Clean code blocks, no unnecessary explanation; assume an experienced reader; focus\non functionality over education. Do not add unnecessary blank lines between prose and code blocks.\n\n**No wrappers around core-ui components.** If a wrapper component exists that wraps a core-ui component, skip it — use the `openmetadata-ui-core-components` component directly at the call site. Only create a wrapper if it adds genuine, non-trivial behaviour (custom hook logic, composed sub-components, domain-specific state). A wrapper that only passes props through is a maintenance liability: it hides which core component is in use and drifts from upstream updates.\n\n**Icons and assets: always go through the design-system layer.** Import icons from `@openmetadata/ui-core-components/icons`, never directly from `@untitledui/icons` — the barrel ships only the design team's own curated SVG set, so add a missing glyph there via `yarn icons:generate` (see the core-components `ICONS.md`) rather than reaching for `@untitledui/icons`. For the same reason, do not import SVG icons directly from `assets/` paths; use the designated abstraction instead.\n\n## Pointer index — when to reach for what\n\n### Path-scoped rules (`.claude/rules/*.md`, auto-load on matching files)\n\n| Rule file | Reach for it when you are editing… |\n|---|---|\n| `java.md` / `java-impact-map.md` | any `**/*.java` — style, spotless, no-wildcard, Kafka-grade method/class rules, ITs; own new code and ITs in `.github/java-tests/impact-map.json` before the PR |\n| `frontend-react.md` | UI `*.{ts,tsx}` — components, hooks, state, types, and the CI lint code-rules |\n| `frontend-styling.md` | UI `*.{ts,tsx,less,css}` — `tw:` prefix, design tokens, ring→border, token-audit |\n| `component-library.md` | UI `*.{ts,tsx}` — prefer `ui-core-components`, do not add Ant Design for new work |\n| `frontend-performance.md` | UI `*.{ts,tsx}` — waterfalls, barrel imports, re-renders, bundle discipline |\n| `frontend-permissions.md` | UI `*.{ts,tsx}` — `useEntityPermissions` and derived flags; never read a permission key directly |\n| `frontend-a11y.md` | UI `*.{ts,tsx}` — semantics over `div`+`role`, keyboard, focus, contrast, targets |\n| `i18n.md` | UI `*.{ts,tsx}` + `src/locale/**` — no string literals, `yarn i18n`, translate placeholders |\n| `frontend-playwright.md` | UI `playwright/**` — E2E test constraints |\n| `python-ingestion.md` | `ingestion/src/**/*.py` — pytest style, connector-specific-file rule, `model_str()` |\n| `schema-first.md` | `openmetadata-spec/.../schema/**` and any `generated/**` — regen, never hand-edit generated |\n| `migrations.md` | `bootstrap/sql/**` — append-only, native path, MySQL+Postgres, idempotent |\n\n### Repo coding conventions (read before writing non-trivial code)\n\n- `docs/design-patterns.md` — the design patterns this codebase uses idiomatically (Template Method\n  for repositories, Factory/Registry for dispatch, Strategy/Adapter/Observer, the ingestion\n  Source→Sink pipeline, …) with the canonical class to copy each from. Extend the established pattern\n  rather than inventing a parallel one.\n- `openmetadata-ui/src/main/resources/ui/DEVELOPER_HANDBOOK.md` — **the UI folder structure and file\n  naming spec.** Read before creating any new file under `openmetadata-ui/.../ui/src/`. Layers stay\n  top-level (`components/`, `pages/`, `rest/`, `utils/`, `hooks/`) and are grouped inside by\n  `domain/feature/`; new files use one stem with a role suffix (`GlossaryList.tsx`, `.types.ts`,\n  `.utils.ts`, `.test.tsx`). Legacy `.component.tsx`/`.interface.ts` files stay as they are.\n- `REVIEW.md` — **the review bar every PR is held to**: the logic defects, test gaps and flaky-test\n  shapes reviewers keep finding here. Read it before writing code; `pr-checklist` self-reviews against it.\n- `docs/decisions/` — dated records of the choices that shape the code. **When a choice looks\n  arbitrary, find its record before re-deciding it; a PR that makes a durable decision adds the\n  record in the same PR.** Cite as `ADR:<date>-<slug>`; format and triggers in its `README.md`.\n\n### Skills (`skills/<name>/`, linked into `.claude/skills/` and `.agents/skills/`; invoke by name)\n\n| Skill | Reach for it when… |\n|---|---|\n| `dev-setup` | setting up / repairing a dev environment, a fresh clone, or a new worktree |\n| `planning` | starting any non-trivial, multi-file feature or refactor |\n| `tdd` | implementing a feature or bug fix (RED→GREEN→REFACTOR) |\n| `systematic-debugging` | a failing test/build/runtime issue whose cause isn't obvious |\n| `test-enforcement` | before a PR — 90% changed-class coverage, ITs for new endpoints, Playwright for UI |\n| `java-affected-tests` | before a PR touching Java/schemas/migrations — runs the impacted unit tests + ITs (PR CI runs no ITs) |\n| `verification` | before claiming \"done\" — run real commands, show evidence |\n| `code-review` | reviewing a local diff before it is a PR — `REVIEW.md` as the bar, spec compliance then code quality |\n| `java-checkstyle` | after touching `.java` — runs `mvn spotless:apply` and verifies |\n| `ui-checkstyle` | after touching UI `*.{ts,tsx,js,jsx,json}` — the exact CI ESLint+Prettier+organize-imports pass |\n| `ui-core-components` | building UI layout/color before reaching for raw `<div>` + Tailwind |\n| `test-locally` | spinning up the full local Docker stack to test a change/connector |\n| `connector-standards` / `connector-building` / `connector-review` | building or reviewing an ingestion connector |\n| `playwright` / `writing-playwright-tests` / `playwright-validation` | authoring or validating Playwright E2E tests |\n| `pr-checklist` / `ui-pr-recording` | opening any PR — self-review against `REVIEW.md`, test evidence, the body; a UI feature PR also runs the build in Docker with sample data and uploads its screen recording |\n| `openmetadata-pr-review` | reviewing a real GitHub PR (number/URL/batch) — maintainer merge verdict: live diff, CI, meaningful-test rubric |\n\n> `openmetadata-workflow` is a meta-skill that routes tasks to the skills above; it is auto-loaded at\n> session start when the `openmetadata-skills` plugin is installed.\n\n### Harness integrity (CI, warnings-only)\n\nA CI workflow (harness-integrity.yml) runs `scripts/harness/check_harness.py` on PRs — also `make harness-check` locally.\nIt **warns, never blocks** (promote to a gate only with maintainer sign-off) when the agent-facing config decays:\n\n- **dead references** — a path, `make`/`yarn` target, or `mvn` goal named in this file,\n  ARCHITECTURE.md, `docs/index.md`, `.claude/rules/**`, or a SKILL.md that no longer resolves;\n- **one instruction file** — a `CLAUDE.md` or `copilot-instructions.md` that is not a link to its `AGENTS.md`, another\n  harness's own file (`GEMINI.md`, `.cursorrules`, …), a rule missing from the index, a chain over Codex's 32,768 bytes;\n- **skill symlinks** — a real file where a symlink into `skills/` is expected (`.claude/skills`,\n  `.agents/skills`), a skill missing from either of them, or two same-named SKILL.md that differ;\n- **doc-size budgets** — this file > 200 lines, ARCHITECTURE.md > 300, any single rule > 100;\n- **rule globs** — a `.claude/rules/**` `paths:` glob matching zero files;\n- **generated-doc freshness** — `docs/generated/**` out of date with its source;\n- **decision records** — a malformed record or a dangling `ADR:` citation (also a pre-commit hook).\n\n## Git commit conventions\n- Never add \"Co-Authored-By\" lines or any AI-attribution trailers to commit messages. \n- The commit is authored by me; you are a tool, not a co-author.\n","CLAUDE.md":"# AGENTS.md\n\nAlways-loaded guidance for every session, whatever the harness — **the only instruction file:** every `CLAUDE.md` and\n`.github/copilot-instructions.md` is a symlink to the `AGENTS.md` beside it\n(ADR:2026-10-09-agents-md-is-the-one-instruction-file), so edit this file, never a copy. **Language- and path-specific\nrules live in `.claude/rules/*.md` (Claude Code auto-loads them on matching files; other harnesses read the matching\none before editing); procedures live in skills (loaded on invoke).** This file is the map — see the pointer index at\nthe bottom. Read [ARCHITECTURE.md](ARCHITECTURE.md) for the **system map** (modules, the request/ingestion/search\npaths, the invariants that hold); read [DEVELOPER.md](DEVELOPER.md) for **how to build, test, and add an entity or\nconnector** (deep dives + end-to-end checklists). Consult [docs/index.md](docs/index.md) — the **knowledge index** —\nto **find existing design, plan, and reference docs** for whatever area you're working on.\n\n## About OpenMetadata\n\nOpenMetadata is a unified metadata platform for data discovery, observability, and governance — a\nmulti-module project with a Java backend, a React/TypeScript frontend, a Python ingestion framework,\nand Docker infrastructure.\n\n## Stack at a glance\n\n- **Backend**: Java 21 + Dropwizard, multi-module Maven.\n- **Frontend**: React + TypeScript, built with **Vite** (dev server on :3000); component library\n  `openmetadata-ui-core-components` — the **UntitledUI + Tailwind v4** (`tw:` prefix, react-aria-components)\n  go-forward design system; legacy stack is Ant Design + Less (deprecated). Machine-readable design-system\n  specs: `openmetadata-ui/src/main/resources/ui/specs/` (read `specs/README.md` before UI work).\n- **Ingestion**: Python (`>=3.10`, no pinned ceiling; **CI runs 3.10**) + Pydantic 2.x, 75+ connectors.\n- **Database**: MySQL (default) or PostgreSQL. **Search**: Elasticsearch 7.17+ or OpenSearch 2.6+.\n- **Infrastructure**: Apache Airflow for ingestion orchestration.\n\n## Environment setup (every session)\n\n- **Python venv is REQUIRED before any Python work, `make generate`, or `make install_dev*`:**\n  ```bash\n  source env/bin/activate          # first time: python3.11 -m venv env\n  python --version                 # expect 3.10.x/3.11.x\n  ```\n  In a Claude Code **worktree** the venv is NOT copied — create one\n  (`python3.11 -m venv env && source env/bin/activate && cd ingestion && make install_dev`) or\n  symlink the main repo's (`ln -s /path/to/main-repo/env env`).\n- **One-call setup (macOS + Linux)**: `make dev_setup` (or `./scripts/dev_setup.sh`) does everything\n  below — toolchain, venv, generation, UI deps, pre-commit — and is idempotent. `make dev_check`\n  diagnoses an existing checkout without changing it. See the `dev-setup` skill.\n- **First-time bootstrap** (from the **repo root** — `make generate` is a root-only target; it does\n  not exist under `ingestion/`):\n  ```bash\n  make prerequisites\n  source env/bin/activate && cd ingestion && make install_dev_env && cd ..\n  make generate                    # regenerate models after any schema change\n  make yarn_install_cache\n  make install_test precommit_install   # activate the commit-time format/license gate (pre-commit)\n  ```\n  The last line installs the `pre-commit` hooks (`.pre-commit-config.yaml`): on `git commit` they run\n  Java format (spotless), Python format (ruff), UI format (prettier), design-token, and Apache-2.0\n  license checks on your changed files, matching CI. Do not skip them with `--no-verify`.\n- **Java**: Java 21; use `mvn`. **Frontend**: use `yarn` (never `npm`); frontend root is `openmetadata-ui/src/main/resources/ui/`.\n- **Docker dev services**: `docker compose -f docker/development/docker-compose.yml up -d`.\n\n## Repository layout\n\nMaven modules (reactor order is computed from the graph, not this list):\n\n- `openmetadata-spec/` — JSON Schemas + generated POJOs; the schema-first source of truth\n- `openmetadata-sdk/` — Java client SDK\n- `common/` — shared utilities (`CommonUtil`, etc.)\n- `openmetadata-shaded-deps/` — ES/OS clients relocated behind `es.*`/`os.*` (do not edit — see rules)\n- `openmetadata-service/` — core Java backend, REST APIs, repositories, migrations runner\n- `openmetadata-k8s-operator/` — Kubernetes operator\n- `openmetadata-integration-tests/` — backend API integration tests (`*IT.java`)\n- `openmetadata-mcp/` — MCP server\n- `openmetadata-ui-core-components/` — canonical React component library\n- `openmetadata-ui/src/main/resources/ui/` — React frontend application\n- `openmetadata-dist/` — packaging/distribution\n- `openmetadata-clients/` — client artifacts\n\nOther key trees: `ingestion/` (Python framework + connectors), `bootstrap/sql/` (DB migrations), `conf/` (configuration), `docker/` (local + prod deployment).\n\n## Hard cross-cutting constraints (apply to every session, all languages)\n\n**Secrets & security.** Never commit secrets — use environment variables or a secrets manager.\nAuth is JWT with OAuth2/SAML; RBAC lives in Java entities; config in `conf/openmetadata.yaml`.\n**Do not modify `.github/workflows/**` on your own** — CI workflows are a supply-chain surface; a\n`PreToolUse` hook blocks edits there unless the user explicitly authorizes them (by setting\n`CLAUDE_ALLOW_WORKFLOW_EDITS=1`). Ask first.\n\n**All caches MUST be bounded.** Never use a bare `dict` / `HashMap` / `Map` as a cache without an\nexplicit size cap — they grow with input and OOM on large catalogs/ingestions (only exception: the\nuser explicitly asks for unbounded). Pick a sane default (100–1000 entries); if unsure, ask.\nPython: `collections.OrderedDict` + `popitem(last=False)`, `@functools.lru_cache(maxsize=N)`, or\n`cachetools.LRUCache` (cache hits **and** misses). Java: Caffeine/Guava `maximumSize(N)`.\nTypeScript: `lru-cache`. Before adding a cache, check it isn't already cached a layer down (e.g.\n`OpenMetadata._search_es_entity` is already `@lru_cache(maxsize=512)`).\n\n**Comments explain *why*, never restate code.** Do NOT add comments that describe what obvious code\ndoes (`// Create user` before `createUser()`). Only comment complex business logic, non-obvious\nalgorithms/workarounds, public-API JavaDoc, or `TODO/FIXME` with a ticket reference. If code needs a\ncomment to be understood, refactor it to be clearer instead.\n\n**Testing philosophy.** Test real behavior, not mock wiring — if a test mocks 3+ of your own classes\nto verify a method call, it tests the wrong thing. Prefer integration tests over heavily-mocked unit\ntests (this project has real ITs: `OpenMetadataApplicationTest`, Docker, real OpenSearch). Mocks are\nfor boundaries (HTTP clients, third-party APIs), not internals. Ask \"what breaks if this test passes\nbut the code is wrong?\" — if the answer is \"nothing\", rewrite it. Assert on observable outcomes\n(API responses, DB state), not internal `verify()` calls.\n\n**License headers are per-module — copy one from a sibling file, never assume Apache.** UI TS/TSX:\nApache-2.0 (`yarn license-header-fix`). Python: `ingestion/` is **Collate Community License 1.0** (`ingestion/LICENSE`); `openmetadata-airflow-apis/` Python files use the same Collate header template.\nJava: Apache-2.0, most files carry none.\nOnly the UI is enforced — the `ui-license-header` pre-commit hook and CI `ui-checkstyle`; spotless\nand `py_format_check` never look at headers, so a wrong Python or Java header ships silently.\n\n**Schema-first.** JSON Schemas in `openmetadata-spec/` are the single source of truth; all generated\ncode (Java POJOs, Pydantic models, TS types) is derived. **Edit the schema, then regenerate — never\nhand-edit generated output.** Details in `.claude/rules/schema-first.md`.\n\n**Output style.** Clean code blocks, no unnecessary explanation; assume an experienced reader; focus\non functionality over education. Do not add unnecessary blank lines between prose and code blocks.\n\n**No wrappers around core-ui components.** If a wrapper component exists that wraps a core-ui component, skip it — use the `openmetadata-ui-core-components` component directly at the call site. Only create a wrapper if it adds genuine, non-trivial behaviour (custom hook logic, composed sub-components, domain-specific state). A wrapper that only passes props through is a maintenance liability: it hides which core component is in use and drifts from upstream updates.\n\n**Icons and assets: always go through the design-system layer.** Import icons from `@openmetadata/ui-core-components/icons`, never directly from `@untitledui/icons` — the barrel ships only the design team's own curated SVG set, so add a missing glyph there via `yarn icons:generate` (see the core-components `ICONS.md`) rather than reaching for `@untitledui/icons`. For the same reason, do not import SVG icons directly from `assets/` paths; use the designated abstraction instead.\n\n## Pointer index — when to reach for what\n\n### Path-scoped rules (`.claude/rules/*.md`, auto-load on matching files)\n\n| Rule file | Reach for it when you are editing… |\n|---|---|\n| `java.md` / `java-impact-map.md` | any `**/*.java` — style, spotless, no-wildcard, Kafka-grade method/class rules, ITs; own new code and ITs in `.github/java-tests/impact-map.json` before the PR |\n| `frontend-react.md` | UI `*.{ts,tsx}` — components, hooks, state, types, and the CI lint code-rules |\n| `frontend-styling.md` | UI `*.{ts,tsx,less,css}` — `tw:` prefix, design tokens, ring→border, token-audit |\n| `component-library.md` | UI `*.{ts,tsx}` — prefer `ui-core-components`, do not add Ant Design for new work |\n| `frontend-performance.md` | UI `*.{ts,tsx}` — waterfalls, barrel imports, re-renders, bundle discipline |\n| `frontend-permissions.md` | UI `*.{ts,tsx}` — `useEntityPermissions` and derived flags; never read a permission key directly |\n| `frontend-a11y.md` | UI `*.{ts,tsx}` — semantics over `div`+`role`, keyboard, focus, contrast, targets |\n| `i18n.md` | UI `*.{ts,tsx}` + `src/locale/**` — no string literals, `yarn i18n`, translate placeholders |\n| `frontend-playwright.md` | UI `playwright/**` — E2E test constraints |\n| `python-ingestion.md` | `ingestion/src/**/*.py` — pytest style, connector-specific-file rule, `model_str()` |\n| `schema-first.md` | `openmetadata-spec/.../schema/**` and any `generated/**` — regen, never hand-edit generated |\n| `migrations.md` | `bootstrap/sql/**` — append-only, native path, MySQL+Postgres, idempotent |\n\n### Repo coding conventions (read before writing non-trivial code)\n\n- `docs/design-patterns.md` — the design patterns this codebase uses idiomatically (Template Method\n  for repositories, Factory/Registry for dispatch, Strategy/Adapter/Observer, the ingestion\n  Source→Sink pipeline, …) with the canonical class to copy each from. Extend the established pattern\n  rather than inventing a parallel one.\n- `openmetadata-ui/src/main/resources/ui/DEVELOPER_HANDBOOK.md` — **the UI folder structure and file\n  naming spec.** Read before creating any new file under `openmetadata-ui/.../ui/src/`. Layers stay\n  top-level (`components/`, `pages/`, `rest/`, `utils/`, `hooks/`) and are grouped inside by\n  `domain/feature/`; new files use one stem with a role suffix (`GlossaryList.tsx`, `.types.ts`,\n  `.utils.ts`, `.test.tsx`). Legacy `.component.tsx`/`.interface.ts` files stay as they are.\n- `REVIEW.md` — **the review bar every PR is held to**: the logic defects, test gaps and flaky-test\n  shapes reviewers keep finding here. Read it before writing code; `pr-checklist` self-reviews against it.\n- `docs/decisions/` — dated records of the choices that shape the code. **When a choice looks\n  arbitrary, find its record before re-deciding it; a PR that makes a durable decision adds the\n  record in the same PR.** Cite as `ADR:<date>-<slug>`; format and triggers in its `README.md`.\n\n### Skills (`skills/<name>/`, linked into `.claude/skills/` and `.agents/skills/`; invoke by name)\n\n| Skill | Reach for it when… |\n|---|---|\n| `dev-setup` | setting up / repairing a dev environment, a fresh clone, or a new worktree |\n| `planning` | starting any non-trivial, multi-file feature or refactor |\n| `tdd` | implementing a feature or bug fix (RED→GREEN→REFACTOR) |\n| `systematic-debugging` | a failing test/build/runtime issue whose cause isn't obvious |\n| `test-enforcement` | before a PR — 90% changed-class coverage, ITs for new endpoints, Playwright for UI |\n| `java-affected-tests` | before a PR touching Java/schemas/migrations — runs the impacted unit tests + ITs (PR CI runs no ITs) |\n| `verification` | before claiming \"done\" — run real commands, show evidence |\n| `code-review` | reviewing a local diff before it is a PR — `REVIEW.md` as the bar, spec compliance then code quality |\n| `java-checkstyle` | after touching `.java` — runs `mvn spotless:apply` and verifies |\n| `ui-checkstyle` | after touching UI `*.{ts,tsx,js,jsx,json}` — the exact CI ESLint+Prettier+organize-imports pass |\n| `ui-core-components` | building UI layout/color before reaching for raw `<div>` + Tailwind |\n| `test-locally` | spinning up the full local Docker stack to test a change/connector |\n| `connector-standards` / `connector-building` / `connector-review` | building or reviewing an ingestion connector |\n| `playwright` / `writing-playwright-tests` / `playwright-validation` | authoring or validating Playwright E2E tests |\n| `pr-checklist` / `ui-pr-recording` | opening any PR — self-review against `REVIEW.md`, test evidence, the body; a UI feature PR also runs the build in Docker with sample data and uploads its screen recording |\n| `openmetadata-pr-review` | reviewing a real GitHub PR (number/URL/batch) — maintainer merge verdict: live diff, CI, meaningful-test rubric |\n\n> `openmetadata-workflow` is a meta-skill that routes tasks to the skills above; it is auto-loaded at\n> session start when the `openmetadata-skills` plugin is installed.\n\n### Harness integrity (CI, warnings-only)\n\nA CI workflow (harness-integrity.yml) runs `scripts/harness/check_harness.py` on PRs — also `make harness-check` locally.\nIt **warns, never blocks** (promote to a gate only with maintainer sign-off) when the agent-facing config decays:\n\n- **dead references** — a path, `make`/`yarn` target, or `mvn` goal named in this file,\n  ARCHITECTURE.md, `docs/index.md`, `.claude/rules/**`, or a SKILL.md that no longer resolves;\n- **one instruction file** — a `CLAUDE.md` or `copilot-instructions.md` that is not a link to its `AGENTS.md`, another\n  harness's own file (`GEMINI.md`, `.cursorrules`, …), a rule missing from the index, a chain over Codex's 32,768 bytes;\n- **skill symlinks** — a real file where a symlink into `skills/` is expected (`.claude/skills`,\n  `.agents/skills`), a skill missing from either of them, or two same-named SKILL.md that differ;\n- **doc-size budgets** — this file > 200 lines, ARCHITECTURE.md > 300, any single rule > 100;\n- **rule globs** — a `.claude/rules/**` `paths:` glob matching zero files;\n- **generated-doc freshness** — `docs/generated/**` out of date with its source;\n- **decision records** — a malformed record or a dangling `ADR:` citation (also a pre-commit hook).\n\n## Git commit conventions\n- Never add \"Co-Authored-By\" lines or any AI-attribution trailers to commit messages. \n- The commit is authored by me; you are a tool, not a co-author.\n",".github/copilot-instructions.md":"../AGENTS.md",".cursor/mcp.json":"# Model Context Protocol (MCP) Configuration\n\nPath: `.cursor/mcp.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/open-metadata/OpenMetadata/HEAD/.cursor/mcp.json)",".claude-plugin/marketplace.json":"# Claude Plugin Marketplace Catalog\n\nPath: `.claude-plugin/marketplace.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/open-metadata/OpenMetadata/HEAD/.claude-plugin/marketplace.json)",".claude-plugin/plugin.json":"# claude-plugin Plugin Manifest\n\nPath: `.claude-plugin/plugin.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/open-metadata/OpenMetadata/HEAD/.claude-plugin/plugin.json)"},"files":{"AGENTS.md":"# AGENTS.md\n\nAlways-loaded guidance for every session, whatever the harness — **the only instruction file:** every `CLAUDE.md` and\n`.github/copilot-instructions.md` is a symlink to the `AGENTS.md` beside it\n(ADR:2026-10-09-agents-md-is-the-one-instruction-file), so edit this file, never a copy. **Language- and path-specific\nrules live in `.claude/rules/*.md` (Claude Code auto-loads them on matching files; other harnesses read the matching\none before editing); procedures live in skills (loaded on invoke).** This file is the map — see the pointer index at\nthe bottom. Read [ARCHITECTURE.md](ARCHITECTURE.md) for the **system map** (modules, the request/ingestion/search\npaths, the invariants that hold); read [DEVELOPER.md](DEVELOPER.md) for **how to build, test, and add an entity or\nconnector** (deep dives + end-to-end checklists). Consult [docs/index.md](docs/index.md) — the **knowledge index** —\nto **find existing design, plan, and reference docs** for whatever area you're working on.\n\n## About OpenMetadata\n\nOpenMetadata is a unified metadata platform for data discovery, observability, and governance — a\nmulti-module project with a Java backend, a React/TypeScript frontend, a Python ingestion framework,\nand Docker infrastructure.\n\n## Stack at a glance\n\n- **Backend**: Java 21 + Dropwizard, multi-module Maven.\n- **Frontend**: React + TypeScript, built with **Vite** (dev server on :3000); component library\n  `openmetadata-ui-core-components` — the **UntitledUI + Tailwind v4** (`tw:` prefix, react-aria-components)\n  go-forward design system; legacy stack is Ant Design + Less (deprecated). Machine-readable design-system\n  specs: `openmetadata-ui/src/main/resources/ui/specs/` (read `specs/README.md` before UI work).\n- **Ingestion**: Python (`>=3.10`, no pinned ceiling; **CI runs 3.10**) + Pydantic 2.x, 75+ connectors.\n- **Database**: MySQL (default) or PostgreSQL. **Search**: Elasticsearch 7.17+ or OpenSearch 2.6+.\n- **Infrastructure**: Apache Airflow for ingestion orchestration.\n\n## Environment setup (every session)\n\n- **Python venv is REQUIRED before any Python work, `make generate`, or `make install_dev*`:**\n  ```bash\n  source env/bin/activate          # first time: python3.11 -m venv env\n  python --version                 # expect 3.10.x/3.11.x\n  ```\n  In a Claude Code **worktree** the venv is NOT copied — create one\n  (`python3.11 -m venv env && source env/bin/activate && cd ingestion && make install_dev`) or\n  symlink the main repo's (`ln -s /path/to/main-repo/env env`).\n- **One-call setup (macOS + Linux)**: `make dev_setup` (or `./scripts/dev_setup.sh`) does everything\n  below — toolchain, venv, generation, UI deps, pre-commit — and is idempotent. `make dev_check`\n  diagnoses an existing checkout without changing it. See the `dev-setup` skill.\n- **First-time bootstrap** (from the **repo root** — `make generate` is a root-only target; it does\n  not exist under `ingestion/`):\n  ```bash\n  make prerequisites\n  source env/bin/activate && cd ingestion && make install_dev_env && cd ..\n  make generate                    # regenerate models after any schema change\n  make yarn_install_cache\n  make install_test precommit_install   # activate the commit-time format/license gate (pre-commit)\n  ```\n  The last line installs the `pre-commit` hooks (`.pre-commit-config.yaml`): on `git commit` they run\n  Java format (spotless), Python format (ruff), UI format (prettier), design-token, and Apache-2.0\n  license checks on your changed files, matching CI. Do not skip them with `--no-verify`.\n- **Java**: Java 21; use `mvn`. **Frontend**: use `yarn` (never `npm`); frontend root is `openmetadata-ui/src/main/resources/ui/`.\n- **Docker dev services**: `docker compose -f docker/development/docker-compose.yml up -d`.\n\n## Repository layout\n\nMaven modules (reactor order is computed from the graph, not this list):\n\n- `openmetadata-spec/` — JSON Schemas + generated POJOs; the schema-first source of truth\n- `openmetadata-sdk/` — Java client SDK\n- `common/` — shared utilities (`CommonUtil`, etc.)\n- `openmetadata-shaded-deps/` — ES/OS clients relocated behind `es.*`/`os.*` (do not edit — see rules)\n- `openmetadata-service/` — core Java backend, REST APIs, repositories, migrations runner\n- `openmetadata-k8s-operator/` — Kubernetes operator\n- `openmetadata-integration-tests/` — backend API integration tests (`*IT.java`)\n- `openmetadata-mcp/` — MCP server\n- `openmetadata-ui-core-components/` — canonical React component library\n- `openmetadata-ui/src/main/resources/ui/` — React frontend application\n- `openmetadata-dist/` — packaging/distribution\n- `openmetadata-clients/` — client artifacts\n\nOther key trees: `ingestion/` (Python framework + connectors), `bootstrap/sql/` (DB migrations), `conf/` (configuration), `docker/` (local + prod deployment).\n\n## Hard cross-cutting constraints (apply to every session, all languages)\n\n**Secrets & security.** Never commit secrets — use environment variables or a secrets manager.\nAuth is JWT with OAuth2/SAML; RBAC lives in Java entities; config in `conf/openmetadata.yaml`.\n**Do not modify `.github/workflows/**` on your own** — CI workflows are a supply-chain surface; a\n`PreToolUse` hook blocks edits there unless the user explicitly authorizes them (by setting\n`CLAUDE_ALLOW_WORKFLOW_EDITS=1`). Ask first.\n\n**All caches MUST be bounded.** Never use a bare `dict` / `HashMap` / `Map` as a cache without an\nexplicit size cap — they grow with input and OOM on large catalogs/ingestions (only exception: the\nuser explicitly asks for unbounded). Pick a sane default (100–1000 entries); if unsure, ask.\nPython: `collections.OrderedDict` + `popitem(last=False)`, `@functools.lru_cache(maxsize=N)`, or\n`cachetools.LRUCache` (cache hits **and** misses). Java: Caffeine/Guava `maximumSize(N)`.\nTypeScript: `lru-cache`. Before adding a cache, check it isn't already cached a layer down (e.g.\n`OpenMetadata._search_es_entity` is already `@lru_cache(maxsize=512)`).\n\n**Comments explain *why*, never restate code.** Do NOT add comments that describe what obvious code\ndoes (`// Create user` before `createUser()`). Only comment complex business logic, non-obvious\nalgorithms/workarounds, public-API JavaDoc, or `TODO/FIXME` with a ticket reference. If code needs a\ncomment to be understood, refactor it to be clearer instead.\n\n**Testing philosophy.** Test real behavior, not mock wiring — if a test mocks 3+ of your own classes\nto verify a method call, it tests the wrong thing. Prefer integration tests over heavily-mocked unit\ntests (this project has real ITs: `OpenMetadataApplicationTest`, Docker, real OpenSearch). Mocks are\nfor boundaries (HTTP clients, third-party APIs), not internals. Ask \"what breaks if this test passes\nbut the code is wrong?\" — if the answer is \"nothing\", rewrite it. Assert on observable outcomes\n(API responses, DB state), not internal `verify()` calls.\n\n**License headers are per-module — copy one from a sibling file, never assume Apache.** UI TS/TSX:\nApache-2.0 (`yarn license-header-fix`). Python: `ingestion/` is **Collate Community License 1.0** (`ingestion/LICENSE`); `openmetadata-airflow-apis/` Python files use the same Collate header template.\nJava: Apache-2.0, most files carry none.\nOnly the UI is enforced — the `ui-license-header` pre-commit hook and CI `ui-checkstyle`; spotless\nand `py_format_check` never look at headers, so a wrong Python or Java header ships silently.\n\n**Schema-first.** JSON Schemas in `openmetadata-spec/` are the single source of truth; all generated\ncode (Java POJOs, Pydantic models, TS types) is derived. **Edit the schema, then regenerate — never\nhand-edit generated output.** Details in `.claude/rules/schema-first.md`.\n\n**Output style.** Clean code blocks, no unnecessary explanation; assume an experienced reader; focus\non functionality over education. Do not add unnecessary blank lines between prose and code blocks.\n\n**No wrappers around core-ui components.** If a wrapper component exists that wraps a core-ui component, skip it — use the `openmetadata-ui-core-components` component directly at the call site. Only create a wrapper if it adds genuine, non-trivial behaviour (custom hook logic, composed sub-components, domain-specific state). A wrapper that only passes props through is a maintenance liability: it hides which core component is in use and drifts from upstream updates.\n\n**Icons and assets: always go through the design-system layer.** Import icons from `@openmetadata/ui-core-components/icons`, never directly from `@untitledui/icons` — the barrel ships only the design team's own curated SVG set, so add a missing glyph there via `yarn icons:generate` (see the core-components `ICONS.md`) rather than reaching for `@untitledui/icons`. For the same reason, do not import SVG icons directly from `assets/` paths; use the designated abstraction instead.\n\n## Pointer index — when to reach for what\n\n### Path-scoped rules (`.claude/rules/*.md`, auto-load on matching files)\n\n| Rule file | Reach for it when you are editing… |\n|---|---|\n| `java.md` / `java-impact-map.md` | any `**/*.java` — style, spotless, no-wildcard, Kafka-grade method/class rules, ITs; own new code and ITs in `.github/java-tests/impact-map.json` before the PR |\n| `frontend-react.md` | UI `*.{ts,tsx}` — components, hooks, state, types, and the CI lint code-rules |\n| `frontend-styling.md` | UI `*.{ts,tsx,less,css}` — `tw:` prefix, design tokens, ring→border, token-audit |\n| `component-library.md` | UI `*.{ts,tsx}` — prefer `ui-core-components`, do not add Ant Design for new work |\n| `frontend-performance.md` | UI `*.{ts,tsx}` — waterfalls, barrel imports, re-renders, bundle discipline |\n| `frontend-permissions.md` | UI `*.{ts,tsx}` — `useEntityPermissions` and derived flags; never read a permission key directly |\n| `frontend-a11y.md` | UI `*.{ts,tsx}` — semantics over `div`+`role`, keyboard, focus, contrast, targets |\n| `i18n.md` | UI `*.{ts,tsx}` + `src/locale/**` — no string literals, `yarn i18n`, translate placeholders |\n| `frontend-playwright.md` | UI `playwright/**` — E2E test constraints |\n| `python-ingestion.md` | `ingestion/src/**/*.py` — pytest style, connector-specific-file rule, `model_str()` |\n| `schema-first.md` | `openmetadata-spec/.../schema/**` and any `generated/**` — regen, never hand-edit generated |\n| `migrations.md` | `bootstrap/sql/**` — append-only, native path, MySQL+Postgres, idempotent |\n\n### Repo coding conventions (read before writing non-trivial code)\n\n- `docs/design-patterns.md` — the design patterns this codebase uses idiomatically (Template Method\n  for repositories, Factory/Registry for dispatch, Strategy/Adapter/Observer, the ingestion\n  Source→Sink pipeline, …) with the canonical class to copy each from. Extend the established pattern\n  rather than inventing a parallel one.\n- `openmetadata-ui/src/main/resources/ui/DEVELOPER_HANDBOOK.md` — **the UI folder structure and file\n  naming spec.** Read before creating any new file under `openmetadata-ui/.../ui/src/`. Layers stay\n  top-level (`components/`, `pages/`, `rest/`, `utils/`, `hooks/`) and are grouped inside by\n  `domain/feature/`; new files use one stem with a role suffix (`GlossaryList.tsx`, `.types.ts`,\n  `.utils.ts`, `.test.tsx`). Legacy `.component.tsx`/`.interface.ts` files stay as they are.\n- `REVIEW.md` — **the review bar every PR is held to**: the logic defects, test gaps and flaky-test\n  shapes reviewers keep finding here. Read it before writing code; `pr-checklist` self-reviews against it.\n- `docs/decisions/` — dated records of the choices that shape the code. **When a choice looks\n  arbitrary, find its record before re-deciding it; a PR that makes a durable decision adds the\n  record in the same PR.** Cite as `ADR:<date>-<slug>`; format and triggers in its `README.md`.\n\n### Skills (`skills/<name>/`, linked into `.claude/skills/` and `.agents/skills/`; invoke by name)\n\n| Skill | Reach for it when… |\n|---|---|\n| `dev-setup` | setting up / repairing a dev environment, a fresh clone, or a new worktree |\n| `planning` | starting any non-trivial, multi-file feature or refactor |\n| `tdd` | implementing a feature or bug fix (RED→GREEN→REFACTOR) |\n| `systematic-debugging` | a failing test/build/runtime issue whose cause isn't obvious |\n| `test-enforcement` | before a PR — 90% changed-class coverage, ITs for new endpoints, Playwright for UI |\n| `java-affected-tests` | before a PR touching Java/schemas/migrations — runs the impacted unit tests + ITs (PR CI runs no ITs) |\n| `verification` | before claiming \"done\" — run real commands, show evidence |\n| `code-review` | reviewing a local diff before it is a PR — `REVIEW.md` as the bar, spec compliance then code quality |\n| `java-checkstyle` | after touching `.java` — runs `mvn spotless:apply` and verifies |\n| `ui-checkstyle` | after touching UI `*.{ts,tsx,js,jsx,json}` — the exact CI ESLint+Prettier+organize-imports pass |\n| `ui-core-components` | building UI layout/color before reaching for raw `<div>` + Tailwind |\n| `test-locally` | spinning up the full local Docker stack to test a change/connector |\n| `connector-standards` / `connector-building` / `connector-review` | building or reviewing an ingestion connector |\n| `playwright` / `writing-playwright-tests` / `playwright-validation` | authoring or validating Playwright E2E tests |\n| `pr-checklist` / `ui-pr-recording` | opening any PR — self-review against `REVIEW.md`, test evidence, the body; a UI feature PR also runs the build in Docker with sample data and uploads its screen recording |\n| `openmetadata-pr-review` | reviewing a real GitHub PR (number/URL/batch) — maintainer merge verdict: live diff, CI, meaningful-test rubric |\n\n> `openmetadata-workflow` is a meta-skill that routes tasks to the skills above; it is auto-loaded at\n> session start when the `openmetadata-skills` plugin is installed.\n\n### Harness integrity (CI, warnings-only)\n\nA CI workflow (harness-integrity.yml) runs `scripts/harness/check_harness.py` on PRs — also `make harness-check` locally.\nIt **warns, never blocks** (promote to a gate only with maintainer sign-off) when the agent-facing config decays:\n\n- **dead references** — a path, `make`/`yarn` target, or `mvn` goal named in this file,\n  ARCHITECTURE.md, `docs/index.md`, `.claude/rules/**`, or a SKILL.md that no longer resolves;\n- **one instruction file** — a `CLAUDE.md` or `copilot-instructions.md` that is not a link to its `AGENTS.md`, another\n  harness's own file (`GEMINI.md`, `.cursorrules`, …), a rule missing from the index, a chain over Codex's 32,768 bytes;\n- **skill symlinks** — a real file where a symlink into `skills/` is expected (`.claude/skills`,\n  `.agents/skills`), a skill missing from either of them, or two same-named SKILL.md that differ;\n- **doc-size budgets** — this file > 200 lines, ARCHITECTURE.md > 300, any single rule > 100;\n- **rule globs** — a `.claude/rules/**` `paths:` glob matching zero files;\n- **generated-doc freshness** — `docs/generated/**` out of date with its source;\n- **decision records** — a malformed record or a dangling `ADR:` citation (also a pre-commit hook).\n\n## Git commit conventions\n- Never add \"Co-Authored-By\" lines or any AI-attribution trailers to commit messages. \n- The commit is authored by me; you are a tool, not a co-author.\n","CLAUDE.md":"# AGENTS.md\n\nAlways-loaded guidance for every session, whatever the harness — **the only instruction file:** every `CLAUDE.md` and\n`.github/copilot-instructions.md` is a symlink to the `AGENTS.md` beside it\n(ADR:2026-10-09-agents-md-is-the-one-instruction-file), so edit this file, never a copy. **Language- and path-specific\nrules live in `.claude/rules/*.md` (Claude Code auto-loads them on matching files; other harnesses read the matching\none before editing); procedures live in skills (loaded on invoke).** This file is the map — see the pointer index at\nthe bottom. Read [ARCHITECTURE.md](ARCHITECTURE.md) for the **system map** (modules, the request/ingestion/search\npaths, the invariants that hold); read [DEVELOPER.md](DEVELOPER.md) for **how to build, test, and add an entity or\nconnector** (deep dives + end-to-end checklists). Consult [docs/index.md](docs/index.md) — the **knowledge index** —\nto **find existing design, plan, and reference docs** for whatever area you're working on.\n\n## About OpenMetadata\n\nOpenMetadata is a unified metadata platform for data discovery, observability, and governance — a\nmulti-module project with a Java backend, a React/TypeScript frontend, a Python ingestion framework,\nand Docker infrastructure.\n\n## Stack at a glance\n\n- **Backend**: Java 21 + Dropwizard, multi-module Maven.\n- **Frontend**: React + TypeScript, built with **Vite** (dev server on :3000); component library\n  `openmetadata-ui-core-components` — the **UntitledUI + Tailwind v4** (`tw:` prefix, react-aria-components)\n  go-forward design system; legacy stack is Ant Design + Less (deprecated). Machine-readable design-system\n  specs: `openmetadata-ui/src/main/resources/ui/specs/` (read `specs/README.md` before UI work).\n- **Ingestion**: Python (`>=3.10`, no pinned ceiling; **CI runs 3.10**) + Pydantic 2.x, 75+ connectors.\n- **Database**: MySQL (default) or PostgreSQL. **Search**: Elasticsearch 7.17+ or OpenSearch 2.6+.\n- **Infrastructure**: Apache Airflow for ingestion orchestration.\n\n## Environment setup (every session)\n\n- **Python venv is REQUIRED before any Python work, `make generate`, or `make install_dev*`:**\n  ```bash\n  source env/bin/activate          # first time: python3.11 -m venv env\n  python --version                 # expect 3.10.x/3.11.x\n  ```\n  In a Claude Code **worktree** the venv is NOT copied — create one\n  (`python3.11 -m venv env && source env/bin/activate && cd ingestion && make install_dev`) or\n  symlink the main repo's (`ln -s /path/to/main-repo/env env`).\n- **One-call setup (macOS + Linux)**: `make dev_setup` (or `./scripts/dev_setup.sh`) does everything\n  below — toolchain, venv, generation, UI deps, pre-commit — and is idempotent. `make dev_check`\n  diagnoses an existing checkout without changing it. See the `dev-setup` skill.\n- **First-time bootstrap** (from the **repo root** — `make generate` is a root-only target; it does\n  not exist under `ingestion/`):\n  ```bash\n  make prerequisites\n  source env/bin/activate && cd ingestion && make install_dev_env && cd ..\n  make generate                    # regenerate models after any schema change\n  make yarn_install_cache\n  make install_test precommit_install   # activate the commit-time format/license gate (pre-commit)\n  ```\n  The last line installs the `pre-commit` hooks (`.pre-commit-config.yaml`): on `git commit` they run\n  Java format (spotless), Python format (ruff), UI format (prettier), design-token, and Apache-2.0\n  license checks on your changed files, matching CI. Do not skip them with `--no-verify`.\n- **Java**: Java 21; use `mvn`. **Frontend**: use `yarn` (never `npm`); frontend root is `openmetadata-ui/src/main/resources/ui/`.\n- **Docker dev services**: `docker compose -f docker/development/docker-compose.yml up -d`.\n\n## Repository layout\n\nMaven modules (reactor order is computed from the graph, not this list):\n\n- `openmetadata-spec/` — JSON Schemas + generated POJOs; the schema-first source of truth\n- `openmetadata-sdk/` — Java client SDK\n- `common/` — shared utilities (`CommonUtil`, etc.)\n- `openmetadata-shaded-deps/` — ES/OS clients relocated behind `es.*`/`os.*` (do not edit — see rules)\n- `openmetadata-service/` — core Java backend, REST APIs, repositories, migrations runner\n- `openmetadata-k8s-operator/` — Kubernetes operator\n- `openmetadata-integration-tests/` — backend API integration tests (`*IT.java`)\n- `openmetadata-mcp/` — MCP server\n- `openmetadata-ui-core-components/` — canonical React component library\n- `openmetadata-ui/src/main/resources/ui/` — React frontend application\n- `openmetadata-dist/` — packaging/distribution\n- `openmetadata-clients/` — client artifacts\n\nOther key trees: `ingestion/` (Python framework + connectors), `bootstrap/sql/` (DB migrations), `conf/` (configuration), `docker/` (local + prod deployment).\n\n## Hard cross-cutting constraints (apply to every session, all languages)\n\n**Secrets & security.** Never commit secrets — use environment variables or a secrets manager.\nAuth is JWT with OAuth2/SAML; RBAC lives in Java entities; config in `conf/openmetadata.yaml`.\n**Do not modify `.github/workflows/**` on your own** — CI workflows are a supply-chain surface; a\n`PreToolUse` hook blocks edits there unless the user explicitly authorizes them (by setting\n`CLAUDE_ALLOW_WORKFLOW_EDITS=1`). Ask first.\n\n**All caches MUST be bounded.** Never use a bare `dict` / `HashMap` / `Map` as a cache without an\nexplicit size cap — they grow with input and OOM on large catalogs/ingestions (only exception: the\nuser explicitly asks for unbounded). Pick a sane default (100–1000 entries); if unsure, ask.\nPython: `collections.OrderedDict` + `popitem(last=False)`, `@functools.lru_cache(maxsize=N)`, or\n`cachetools.LRUCache` (cache hits **and** misses). Java: Caffeine/Guava `maximumSize(N)`.\nTypeScript: `lru-cache`. Before adding a cache, check it isn't already cached a layer down (e.g.\n`OpenMetadata._search_es_entity` is already `@lru_cache(maxsize=512)`).\n\n**Comments explain *why*, never restate code.** Do NOT add comments that describe what obvious code\ndoes (`// Create user` before `createUser()`). Only comment complex business logic, non-obvious\nalgorithms/workarounds, public-API JavaDoc, or `TODO/FIXME` with a ticket reference. If code needs a\ncomment to be understood, refactor it to be clearer instead.\n\n**Testing philosophy.** Test real behavior, not mock wiring — if a test mocks 3+ of your own classes\nto verify a method call, it tests the wrong thing. Prefer integration tests over heavily-mocked unit\ntests (this project has real ITs: `OpenMetadataApplicationTest`, Docker, real OpenSearch). Mocks are\nfor boundaries (HTTP clients, third-party APIs), not internals. Ask \"what breaks if this test passes\nbut the code is wrong?\" — if the answer is \"nothing\", rewrite it. Assert on observable outcomes\n(API responses, DB state), not internal `verify()` calls.\n\n**License headers are per-module — copy one from a sibling file, never assume Apache.** UI TS/TSX:\nApache-2.0 (`yarn license-header-fix`). Python: `ingestion/` is **Collate Community License 1.0** (`ingestion/LICENSE`); `openmetadata-airflow-apis/` Python files use the same Collate header template.\nJava: Apache-2.0, most files carry none.\nOnly the UI is enforced — the `ui-license-header` pre-commit hook and CI `ui-checkstyle`; spotless\nand `py_format_check` never look at headers, so a wrong Python or Java header ships silently.\n\n**Schema-first.** JSON Schemas in `openmetadata-spec/` are the single source of truth; all generated\ncode (Java POJOs, Pydantic models, TS types) is derived. **Edit the schema, then regenerate — never\nhand-edit generated output.** Details in `.claude/rules/schema-first.md`.\n\n**Output style.** Clean code blocks, no unnecessary explanation; assume an experienced reader; focus\non functionality over education. Do not add unnecessary blank lines between prose and code blocks.\n\n**No wrappers around core-ui components.** If a wrapper component exists that wraps a core-ui component, skip it — use the `openmetadata-ui-core-components` component directly at the call site. Only create a wrapper if it adds genuine, non-trivial behaviour (custom hook logic, composed sub-components, domain-specific state). A wrapper that only passes props through is a maintenance liability: it hides which core component is in use and drifts from upstream updates.\n\n**Icons and assets: always go through the design-system layer.** Import icons from `@openmetadata/ui-core-components/icons`, never directly from `@untitledui/icons` — the barrel ships only the design team's own curated SVG set, so add a missing glyph there via `yarn icons:generate` (see the core-components `ICONS.md`) rather than reaching for `@untitledui/icons`. For the same reason, do not import SVG icons directly from `assets/` paths; use the designated abstraction instead.\n\n## Pointer index — when to reach for what\n\n### Path-scoped rules (`.claude/rules/*.md`, auto-load on matching files)\n\n| Rule file | Reach for it when you are editing… |\n|---|---|\n| `java.md` / `java-impact-map.md` | any `**/*.java` — style, spotless, no-wildcard, Kafka-grade method/class rules, ITs; own new code and ITs in `.github/java-tests/impact-map.json` before the PR |\n| `frontend-react.md` | UI `*.{ts,tsx}` — components, hooks, state, types, and the CI lint code-rules |\n| `frontend-styling.md` | UI `*.{ts,tsx,less,css}` — `tw:` prefix, design tokens, ring→border, token-audit |\n| `component-library.md` | UI `*.{ts,tsx}` — prefer `ui-core-components`, do not add Ant Design for new work |\n| `frontend-performance.md` | UI `*.{ts,tsx}` — waterfalls, barrel imports, re-renders, bundle discipline |\n| `frontend-permissions.md` | UI `*.{ts,tsx}` — `useEntityPermissions` and derived flags; never read a permission key directly |\n| `frontend-a11y.md` | UI `*.{ts,tsx}` — semantics over `div`+`role`, keyboard, focus, contrast, targets |\n| `i18n.md` | UI `*.{ts,tsx}` + `src/locale/**` — no string literals, `yarn i18n`, translate placeholders |\n| `frontend-playwright.md` | UI `playwright/**` — E2E test constraints |\n| `python-ingestion.md` | `ingestion/src/**/*.py` — pytest style, connector-specific-file rule, `model_str()` |\n| `schema-first.md` | `openmetadata-spec/.../schema/**` and any `generated/**` — regen, never hand-edit generated |\n| `migrations.md` | `bootstrap/sql/**` — append-only, native path, MySQL+Postgres, idempotent |\n\n### Repo coding conventions (read before writing non-trivial code)\n\n- `docs/design-patterns.md` — the design patterns this codebase uses idiomatically (Template Method\n  for repositories, Factory/Registry for dispatch, Strategy/Adapter/Observer, the ingestion\n  Source→Sink pipeline, …) with the canonical class to copy each from. Extend the established pattern\n  rather than inventing a parallel one.\n- `openmetadata-ui/src/main/resources/ui/DEVELOPER_HANDBOOK.md` — **the UI folder structure and file\n  naming spec.** Read before creating any new file under `openmetadata-ui/.../ui/src/`. Layers stay\n  top-level (`components/`, `pages/`, `rest/`, `utils/`, `hooks/`) and are grouped inside by\n  `domain/feature/`; new files use one stem with a role suffix (`GlossaryList.tsx`, `.types.ts`,\n  `.utils.ts`, `.test.tsx`). Legacy `.component.tsx`/`.interface.ts` files stay as they are.\n- `REVIEW.md` — **the review bar every PR is held to**: the logic defects, test gaps and flaky-test\n  shapes reviewers keep finding here. Read it before writing code; `pr-checklist` self-reviews against it.\n- `docs/decisions/` — dated records of the choices that shape the code. **When a choice looks\n  arbitrary, find its record before re-deciding it; a PR that makes a durable decision adds the\n  record in the same PR.** Cite as `ADR:<date>-<slug>`; format and triggers in its `README.md`.\n\n### Skills (`skills/<name>/`, linked into `.claude/skills/` and `.agents/skills/`; invoke by name)\n\n| Skill | Reach for it when… |\n|---|---|\n| `dev-setup` | setting up / repairing a dev environment, a fresh clone, or a new worktree |\n| `planning` | starting any non-trivial, multi-file feature or refactor |\n| `tdd` | implementing a feature or bug fix (RED→GREEN→REFACTOR) |\n| `systematic-debugging` | a failing test/build/runtime issue whose cause isn't obvious |\n| `test-enforcement` | before a PR — 90% changed-class coverage, ITs for new endpoints, Playwright for UI |\n| `java-affected-tests` | before a PR touching Java/schemas/migrations — runs the impacted unit tests + ITs (PR CI runs no ITs) |\n| `verification` | before claiming \"done\" — run real commands, show evidence |\n| `code-review` | reviewing a local diff before it is a PR — `REVIEW.md` as the bar, spec compliance then code quality |\n| `java-checkstyle` | after touching `.java` — runs `mvn spotless:apply` and verifies |\n| `ui-checkstyle` | after touching UI `*.{ts,tsx,js,jsx,json}` — the exact CI ESLint+Prettier+organize-imports pass |\n| `ui-core-components` | building UI layout/color before reaching for raw `<div>` + Tailwind |\n| `test-locally` | spinning up the full local Docker stack to test a change/connector |\n| `connector-standards` / `connector-building` / `connector-review` | building or reviewing an ingestion connector |\n| `playwright` / `writing-playwright-tests` / `playwright-validation` | authoring or validating Playwright E2E tests |\n| `pr-checklist` / `ui-pr-recording` | opening any PR — self-review against `REVIEW.md`, test evidence, the body; a UI feature PR also runs the build in Docker with sample data and uploads its screen recording |\n| `openmetadata-pr-review` | reviewing a real GitHub PR (number/URL/batch) — maintainer merge verdict: live diff, CI, meaningful-test rubric |\n\n> `openmetadata-workflow` is a meta-skill that routes tasks to the skills above; it is auto-loaded at\n> session start when the `openmetadata-skills` plugin is installed.\n\n### Harness integrity (CI, warnings-only)\n\nA CI workflow (harness-integrity.yml) runs `scripts/harness/check_harness.py` on PRs — also `make harness-check` locally.\nIt **warns, never blocks** (promote to a gate only with maintainer sign-off) when the agent-facing config decays:\n\n- **dead references** — a path, `make`/`yarn` target, or `mvn` goal named in this file,\n  ARCHITECTURE.md, `docs/index.md`, `.claude/rules/**`, or a SKILL.md that no longer resolves;\n- **one instruction file** — a `CLAUDE.md` or `copilot-instructions.md` that is not a link to its `AGENTS.md`, another\n  harness's own file (`GEMINI.md`, `.cursorrules`, …), a rule missing from the index, a chain over Codex's 32,768 bytes;\n- **skill symlinks** — a real file where a symlink into `skills/` is expected (`.claude/skills`,\n  `.agents/skills`), a skill missing from either of them, or two same-named SKILL.md that differ;\n- **doc-size budgets** — this file > 200 lines, ARCHITECTURE.md > 300, any single rule > 100;\n- **rule globs** — a `.claude/rules/**` `paths:` glob matching zero files;\n- **generated-doc freshness** — `docs/generated/**` out of date with its source;\n- **decision records** — a malformed record or a dangling `ADR:` citation (also a pre-commit hook).\n\n## Git commit conventions\n- Never add \"Co-Authored-By\" lines or any AI-attribution trailers to commit messages. \n- The commit is authored by me; you are a tool, not a co-author.\n",".github/copilot-instructions.md":"../AGENTS.md",".cursor/mcp.json":"# Model Context Protocol (MCP) Configuration\n\nPath: `.cursor/mcp.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/open-metadata/OpenMetadata/HEAD/.cursor/mcp.json)",".claude-plugin/marketplace.json":"# Claude Plugin Marketplace Catalog\n\nPath: `.claude-plugin/marketplace.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/open-metadata/OpenMetadata/HEAD/.claude-plugin/marketplace.json)",".claude-plugin/plugin.json":"# claude-plugin Plugin Manifest\n\nPath: `.claude-plugin/plugin.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/open-metadata/OpenMetadata/HEAD/.claude-plugin/plugin.json)"},"items":[{"name":"AGENTS.md","path":"AGENTS.md","rawUrl":"https://raw.githubusercontent.com/open-metadata/OpenMetadata/HEAD/AGENTS.md","title":"AI Agent Protocol & Instructions","category":"root-instruction","format":"markdown","content":"# AGENTS.md\n\nAlways-loaded guidance for every session, whatever the harness — **the only instruction file:** every `CLAUDE.md` and\n`.github/copilot-instructions.md` is a symlink to the `AGENTS.md` beside it\n(ADR:2026-10-09-agents-md-is-the-one-instruction-file), so edit this file, never a copy. **Language- and path-specific\nrules live in `.claude/rules/*.md` (Claude Code auto-loads them on matching files; other harnesses read the matching\none before editing); procedures live in skills (loaded on invoke).** This file is the map — see the pointer index at\nthe bottom. Read [ARCHITECTURE.md](ARCHITECTURE.md) for the **system map** (modules, the request/ingestion/search\npaths, the invariants that hold); read [DEVELOPER.md](DEVELOPER.md) for **how to build, test, and add an entity or\nconnector** (deep dives + end-to-end checklists). Consult [docs/index.md](docs/index.md) — the **knowledge index** —\nto **find existing design, plan, and reference docs** for whatever area you're working on.\n\n## About OpenMetadata\n\nOpenMetadata is a unified metadata platform for data discovery, observability, and governance — a\nmulti-module project with a Java backend, a React/TypeScript frontend, a Python ingestion framework,\nand Docker infrastructure.\n\n## Stack at a glance\n\n- **Backend**: Java 21 + Dropwizard, multi-module Maven.\n- **Frontend**: React + TypeScript, built with **Vite** (dev server on :3000); component library\n  `openmetadata-ui-core-components` — the **UntitledUI + Tailwind v4** (`tw:` prefix, react-aria-components)\n  go-forward design system; legacy stack is Ant Design + Less (deprecated). Machine-readable design-system\n  specs: `openmetadata-ui/src/main/resources/ui/specs/` (read `specs/README.md` before UI work).\n- **Ingestion**: Python (`>=3.10`, no pinned ceiling; **CI runs 3.10**) + Pydantic 2.x, 75+ connectors.\n- **Database**: MySQL (default) or PostgreSQL. **Search**: Elasticsearch 7.17+ or OpenSearch 2.6+.\n- **Infrastructure**: Apache Airflow for ingestion orchestration.\n\n## Environment setup (every session)\n\n- **Python venv is REQUIRED before any Python work, `make generate`, or `make install_dev*`:**\n  ```bash\n  source env/bin/activate          # first time: python3.11 -m venv env\n  python --version                 # expect 3.10.x/3.11.x\n  ```\n  In a Claude Code **worktree** the venv is NOT copied — create one\n  (`python3.11 -m venv env && source env/bin/activate && cd ingestion && make install_dev`) or\n  symlink the main repo's (`ln -s /path/to/main-repo/env env`).\n- **One-call setup (macOS + Linux)**: `make dev_setup` (or `./scripts/dev_setup.sh`) does everything\n  below — toolchain, venv, generation, UI deps, pre-commit — and is idempotent. `make dev_check`\n  diagnoses an existing checkout without changing it. See the `dev-setup` skill.\n- **First-time bootstrap** (from the **repo root** — `make generate` is a root-only target; it does\n  not exist under `ingestion/`):\n  ```bash\n  make prerequisites\n  source env/bin/activate && cd ingestion && make install_dev_env && cd ..\n  make generate                    # regenerate models after any schema change\n  make yarn_install_cache\n  make install_test precommit_install   # activate the commit-time format/license gate (pre-commit)\n  ```\n  The last line installs the `pre-commit` hooks (`.pre-commit-config.yaml`): on `git commit` they run\n  Java format (spotless), Python format (ruff), UI format (prettier), design-token, and Apache-2.0\n  license checks on your changed files, matching CI. Do not skip them with `--no-verify`.\n- **Java**: Java 21; use `mvn`. **Frontend**: use `yarn` (never `npm`); frontend root is `openmetadata-ui/src/main/resources/ui/`.\n- **Docker dev services**: `docker compose -f docker/development/docker-compose.yml up -d`.\n\n## Repository layout\n\nMaven modules (reactor order is computed from the graph, not this list):\n\n- `openmetadata-spec/` — JSON Schemas + generated POJOs; the schema-first source of truth\n- `openmetadata-sdk/` — Java client SDK\n- `common/` — shared utilities (`CommonUtil`, etc.)\n- `openmetadata-shaded-deps/` — ES/OS clients relocated behind `es.*`/`os.*` (do not edit — see rules)\n- `openmetadata-service/` — core Java backend, REST APIs, repositories, migrations runner\n- `openmetadata-k8s-operator/` — Kubernetes operator\n- `openmetadata-integration-tests/` — backend API integration tests (`*IT.java`)\n- `openmetadata-mcp/` — MCP server\n- `openmetadata-ui-core-components/` — canonical React component library\n- `openmetadata-ui/src/main/resources/ui/` — React frontend application\n- `openmetadata-dist/` — packaging/distribution\n- `openmetadata-clients/` — client artifacts\n\nOther key trees: `ingestion/` (Python framework + connectors), `bootstrap/sql/` (DB migrations), `conf/` (configuration), `docker/` (local + prod deployment).\n\n## Hard cross-cutting constraints (apply to every session, all languages)\n\n**Secrets & security.** Never commit secrets — use environment variables or a secrets manager.\nAuth is JWT with OAuth2/SAML; RBAC lives in Java entities; config in `conf/openmetadata.yaml`.\n**Do not modify `.github/workflows/**` on your own** — CI workflows are a supply-chain surface; a\n`PreToolUse` hook blocks edits there unless the user explicitly authorizes them (by setting\n`CLAUDE_ALLOW_WORKFLOW_EDITS=1`). Ask first.\n\n**All caches MUST be bounded.** Never use a bare `dict` / `HashMap` / `Map` as a cache without an\nexplicit size cap — they grow with input and OOM on large catalogs/ingestions (only exception: the\nuser explicitly asks for unbounded). Pick a sane default (100–1000 entries); if unsure, ask.\nPython: `collections.OrderedDict` + `popitem(last=False)`, `@functools.lru_cache(maxsize=N)`, or\n`cachetools.LRUCache` (cache hits **and** misses). Java: Caffeine/Guava `maximumSize(N)`.\nTypeScript: `lru-cache`. Before adding a cache, check it isn't already cached a layer down (e.g.\n`OpenMetadata._search_es_entity` is already `@lru_cache(maxsize=512)`).\n\n**Comments explain *why*, never restate code.** Do NOT add comments that describe what obvious code\ndoes (`// Create user` before `createUser()`). Only comment complex business logic, non-obvious\nalgorithms/workarounds, public-API JavaDoc, or `TODO/FIXME` with a ticket reference. If code needs a\ncomment to be understood, refactor it to be clearer instead.\n\n**Testing philosophy.** Test real behavior, not mock wiring — if a test mocks 3+ of your own classes\nto verify a method call, it tests the wrong thing. Prefer integration tests over heavily-mocked unit\ntests (this project has real ITs: `OpenMetadataApplicationTest`, Docker, real OpenSearch). Mocks are\nfor boundaries (HTTP clients, third-party APIs), not internals. Ask \"what breaks if this test passes\nbut the code is wrong?\" — if the answer is \"nothing\", rewrite it. Assert on observable outcomes\n(API responses, DB state), not internal `verify()` calls.\n\n**License headers are per-module — copy one from a sibling file, never assume Apache.** UI TS/TSX:\nApache-2.0 (`yarn license-header-fix`). Python: `ingestion/` is **Collate Community License 1.0** (`ingestion/LICENSE`); `openmetadata-airflow-apis/` Python files use the same Collate header template.\nJava: Apache-2.0, most files carry none.\nOnly the UI is enforced — the `ui-license-header` pre-commit hook and CI `ui-checkstyle`; spotless\nand `py_format_check` never look at headers, so a wrong Python or Java header ships silently.\n\n**Schema-first.** JSON Schemas in `openmetadata-spec/` are the single source of truth; all generated\ncode (Java POJOs, Pydantic models, TS types) is derived. **Edit the schema, then regenerate — never\nhand-edit generated output.** Details in `.claude/rules/schema-first.md`.\n\n**Output style.** Clean code blocks, no unnecessary explanation; assume an experienced reader; focus\non functionality over education. Do not add unnecessary blank lines between prose and code blocks.\n\n**No wrappers around core-ui components.** If a wrapper component exists that wraps a core-ui component, skip it — use the `openmetadata-ui-core-components` component directly at the call site. Only create a wrapper if it adds genuine, non-trivial behaviour (custom hook logic, composed sub-components, domain-specific state). A wrapper that only passes props through is a maintenance liability: it hides which core component is in use and drifts from upstream updates.\n\n**Icons and assets: always go through the design-system layer.** Import icons from `@openmetadata/ui-core-components/icons`, never directly from `@untitledui/icons` — the barrel ships only the design team's own curated SVG set, so add a missing glyph there via `yarn icons:generate` (see the core-components `ICONS.md`) rather than reaching for `@untitledui/icons`. For the same reason, do not import SVG icons directly from `assets/` paths; use the designated abstraction instead.\n\n## Pointer index — when to reach for what\n\n### Path-scoped rules (`.claude/rules/*.md`, auto-load on matching files)\n\n| Rule file | Reach for it when you are editing… |\n|---|---|\n| `java.md` / `java-impact-map.md` | any `**/*.java` — style, spotless, no-wildcard, Kafka-grade method/class rules, ITs; own new code and ITs in `.github/java-tests/impact-map.json` before the PR |\n| `frontend-react.md` | UI `*.{ts,tsx}` — components, hooks, state, types, and the CI lint code-rules |\n| `frontend-styling.md` | UI `*.{ts,tsx,less,css}` — `tw:` prefix, design tokens, ring→border, token-audit |\n| `component-library.md` | UI `*.{ts,tsx}` — prefer `ui-core-components`, do not add Ant Design for new work |\n| `frontend-performance.md` | UI `*.{ts,tsx}` — waterfalls, barrel imports, re-renders, bundle discipline |\n| `frontend-permissions.md` | UI `*.{ts,tsx}` — `useEntityPermissions` and derived flags; never read a permission key directly |\n| `frontend-a11y.md` | UI `*.{ts,tsx}` — semantics over `div`+`role`, keyboard, focus, contrast, targets |\n| `i18n.md` | UI `*.{ts,tsx}` + `src/locale/**` — no string literals, `yarn i18n`, translate placeholders |\n| `frontend-playwright.md` | UI `playwright/**` — E2E test constraints |\n| `python-ingestion.md` | `ingestion/src/**/*.py` — pytest style, connector-specific-file rule, `model_str()` |\n| `schema-first.md` | `openmetadata-spec/.../schema/**` and any `generated/**` — regen, never hand-edit generated |\n| `migrations.md` | `bootstrap/sql/**` — append-only, native path, MySQL+Postgres, idempotent |\n\n### Repo coding conventions (read before writing non-trivial code)\n\n- `docs/design-patterns.md` — the design patterns this codebase uses idiomatically (Template Method\n  for repositories, Factory/Registry for dispatch, Strategy/Adapter/Observer, the ingestion\n  Source→Sink pipeline, …) with the canonical class to copy each from. Extend the established pattern\n  rather than inventing a parallel one.\n- `openmetadata-ui/src/main/resources/ui/DEVELOPER_HANDBOOK.md` — **the UI folder structure and file\n  naming spec.** Read before creating any new file under `openmetadata-ui/.../ui/src/`. Layers stay\n  top-level (`components/`, `pages/`, `rest/`, `utils/`, `hooks/`) and are grouped inside by\n  `domain/feature/`; new files use one stem with a role suffix (`GlossaryList.tsx`, `.types.ts`,\n  `.utils.ts`, `.test.tsx`). Legacy `.component.tsx`/`.interface.ts` files stay as they are.\n- `REVIEW.md` — **the review bar every PR is held to**: the logic defects, test gaps and flaky-test\n  shapes reviewers keep finding here. Read it before writing code; `pr-checklist` self-reviews against it.\n- `docs/decisions/` — dated records of the choices that shape the code. **When a choice looks\n  arbitrary, find its record before re-deciding it; a PR that makes a durable decision adds the\n  record in the same PR.** Cite as `ADR:<date>-<slug>`; format and triggers in its `README.md`.\n\n### Skills (`skills/<name>/`, linked into `.claude/skills/` and `.agents/skills/`; invoke by name)\n\n| Skill | Reach for it when… |\n|---|---|\n| `dev-setup` | setting up / repairing a dev environment, a fresh clone, or a new worktree |\n| `planning` | starting any non-trivial, multi-file feature or refactor |\n| `tdd` | implementing a feature or bug fix (RED→GREEN→REFACTOR) |\n| `systematic-debugging` | a failing test/build/runtime issue whose cause isn't obvious |\n| `test-enforcement` | before a PR — 90% changed-class coverage, ITs for new endpoints, Playwright for UI |\n| `java-affected-tests` | before a PR touching Java/schemas/migrations — runs the impacted unit tests + ITs (PR CI runs no ITs) |\n| `verification` | before claiming \"done\" — run real commands, show evidence |\n| `code-review` | reviewing a local diff before it is a PR — `REVIEW.md` as the bar, spec compliance then code quality |\n| `java-checkstyle` | after touching `.java` — runs `mvn spotless:apply` and verifies |\n| `ui-checkstyle` | after touching UI `*.{ts,tsx,js,jsx,json}` — the exact CI ESLint+Prettier+organize-imports pass |\n| `ui-core-components` | building UI layout/color before reaching for raw `<div>` + Tailwind |\n| `test-locally` | spinning up the full local Docker stack to test a change/connector |\n| `connector-standards` / `connector-building` / `connector-review` | building or reviewing an ingestion connector |\n| `playwright` / `writing-playwright-tests` / `playwright-validation` | authoring or validating Playwright E2E tests |\n| `pr-checklist` / `ui-pr-recording` | opening any PR — self-review against `REVIEW.md`, test evidence, the body; a UI feature PR also runs the build in Docker with sample data and uploads its screen recording |\n| `openmetadata-pr-review` | reviewing a real GitHub PR (number/URL/batch) — maintainer merge verdict: live diff, CI, meaningful-test rubric |\n\n> `openmetadata-workflow` is a meta-skill that routes tasks to the skills above; it is auto-loaded at\n> session start when the `openmetadata-skills` plugin is installed.\n\n### Harness integrity (CI, warnings-only)\n\nA CI workflow (harness-integrity.yml) runs `scripts/harness/check_harness.py` on PRs — also `make harness-check` locally.\nIt **warns, never blocks** (promote to a gate only with maintainer sign-off) when the agent-facing config decays:\n\n- **dead references** — a path, `make`/`yarn` target, or `mvn` goal named in this file,\n  ARCHITECTURE.md, `docs/index.md`, `.claude/rules/**`, or a SKILL.md that no longer resolves;\n- **one instruction file** — a `CLAUDE.md` or `copilot-instructions.md` that is not a link to its `AGENTS.md`, another\n  harness's own file (`GEMINI.md`, `.cursorrules`, …), a rule missing from the index, a chain over Codex's 32,768 bytes;\n- **skill symlinks** — a real file where a symlink into `skills/` is expected (`.claude/skills`,\n  `.agents/skills`), a skill missing from either of them, or two same-named SKILL.md that differ;\n- **doc-size budgets** — this file > 200 lines, ARCHITECTURE.md > 300, any single rule > 100;\n- **rule globs** — a `.claude/rules/**` `paths:` glob matching zero files;\n- **generated-doc freshness** — `docs/generated/**` out of date with its source;\n- **decision records** — a malformed record or a dangling `ADR:` citation (also a pre-commit hook).\n\n## Git commit conventions\n- Never add \"Co-Authored-By\" lines or any AI-attribution trailers to commit messages. \n- The commit is authored by me; you are a tool, not a co-author.\n","isInternal":false,"tokens":3928,"sizeBytes":15392},{"name":"CLAUDE.md","path":"CLAUDE.md","rawUrl":"https://raw.githubusercontent.com/open-metadata/OpenMetadata/HEAD/CLAUDE.md","title":"Claude Agent Guidelines & System Prompt","category":"claude-rule","format":"markdown","content":"# AGENTS.md\n\nAlways-loaded guidance for every session, whatever the harness — **the only instruction file:** every `CLAUDE.md` and\n`.github/copilot-instructions.md` is a symlink to the `AGENTS.md` beside it\n(ADR:2026-10-09-agents-md-is-the-one-instruction-file), so edit this file, never a copy. **Language- and path-specific\nrules live in `.claude/rules/*.md` (Claude Code auto-loads them on matching files; other harnesses read the matching\none before editing); procedures live in skills (loaded on invoke).** This file is the map — see the pointer index at\nthe bottom. Read [ARCHITECTURE.md](ARCHITECTURE.md) for the **system map** (modules, the request/ingestion/search\npaths, the invariants that hold); read [DEVELOPER.md](DEVELOPER.md) for **how to build, test, and add an entity or\nconnector** (deep dives + end-to-end checklists). Consult [docs/index.md](docs/index.md) — the **knowledge index** —\nto **find existing design, plan, and reference docs** for whatever area you're working on.\n\n## About OpenMetadata\n\nOpenMetadata is a unified metadata platform for data discovery, observability, and governance — a\nmulti-module project with a Java backend, a React/TypeScript frontend, a Python ingestion framework,\nand Docker infrastructure.\n\n## Stack at a glance\n\n- **Backend**: Java 21 + Dropwizard, multi-module Maven.\n- **Frontend**: React + TypeScript, built with **Vite** (dev server on :3000); component library\n  `openmetadata-ui-core-components` — the **UntitledUI + Tailwind v4** (`tw:` prefix, react-aria-components)\n  go-forward design system; legacy stack is Ant Design + Less (deprecated). Machine-readable design-system\n  specs: `openmetadata-ui/src/main/resources/ui/specs/` (read `specs/README.md` before UI work).\n- **Ingestion**: Python (`>=3.10`, no pinned ceiling; **CI runs 3.10**) + Pydantic 2.x, 75+ connectors.\n- **Database**: MySQL (default) or PostgreSQL. **Search**: Elasticsearch 7.17+ or OpenSearch 2.6+.\n- **Infrastructure**: Apache Airflow for ingestion orchestration.\n\n## Environment setup (every session)\n\n- **Python venv is REQUIRED before any Python work, `make generate`, or `make install_dev*`:**\n  ```bash\n  source env/bin/activate          # first time: python3.11 -m venv env\n  python --version                 # expect 3.10.x/3.11.x\n  ```\n  In a Claude Code **worktree** the venv is NOT copied — create one\n  (`python3.11 -m venv env && source env/bin/activate && cd ingestion && make install_dev`) or\n  symlink the main repo's (`ln -s /path/to/main-repo/env env`).\n- **One-call setup (macOS + Linux)**: `make dev_setup` (or `./scripts/dev_setup.sh`) does everything\n  below — toolchain, venv, generation, UI deps, pre-commit — and is idempotent. `make dev_check`\n  diagnoses an existing checkout without changing it. See the `dev-setup` skill.\n- **First-time bootstrap** (from the **repo root** — `make generate` is a root-only target; it does\n  not exist under `ingestion/`):\n  ```bash\n  make prerequisites\n  source env/bin/activate && cd ingestion && make install_dev_env && cd ..\n  make generate                    # regenerate models after any schema change\n  make yarn_install_cache\n  make install_test precommit_install   # activate the commit-time format/license gate (pre-commit)\n  ```\n  The last line installs the `pre-commit` hooks (`.pre-commit-config.yaml`): on `git commit` they run\n  Java format (spotless), Python format (ruff), UI format (prettier), design-token, and Apache-2.0\n  license checks on your changed files, matching CI. Do not skip them with `--no-verify`.\n- **Java**: Java 21; use `mvn`. **Frontend**: use `yarn` (never `npm`); frontend root is `openmetadata-ui/src/main/resources/ui/`.\n- **Docker dev services**: `docker compose -f docker/development/docker-compose.yml up -d`.\n\n## Repository layout\n\nMaven modules (reactor order is computed from the graph, not this list):\n\n- `openmetadata-spec/` — JSON Schemas + generated POJOs; the schema-first source of truth\n- `openmetadata-sdk/` — Java client SDK\n- `common/` — shared utilities (`CommonUtil`, etc.)\n- `openmetadata-shaded-deps/` — ES/OS clients relocated behind `es.*`/`os.*` (do not edit — see rules)\n- `openmetadata-service/` — core Java backend, REST APIs, repositories, migrations runner\n- `openmetadata-k8s-operator/` — Kubernetes operator\n- `openmetadata-integration-tests/` — backend API integration tests (`*IT.java`)\n- `openmetadata-mcp/` — MCP server\n- `openmetadata-ui-core-components/` — canonical React component library\n- `openmetadata-ui/src/main/resources/ui/` — React frontend application\n- `openmetadata-dist/` — packaging/distribution\n- `openmetadata-clients/` — client artifacts\n\nOther key trees: `ingestion/` (Python framework + connectors), `bootstrap/sql/` (DB migrations), `conf/` (configuration), `docker/` (local + prod deployment).\n\n## Hard cross-cutting constraints (apply to every session, all languages)\n\n**Secrets & security.** Never commit secrets — use environment variables or a secrets manager.\nAuth is JWT with OAuth2/SAML; RBAC lives in Java entities; config in `conf/openmetadata.yaml`.\n**Do not modify `.github/workflows/**` on your own** — CI workflows are a supply-chain surface; a\n`PreToolUse` hook blocks edits there unless the user explicitly authorizes them (by setting\n`CLAUDE_ALLOW_WORKFLOW_EDITS=1`). Ask first.\n\n**All caches MUST be bounded.** Never use a bare `dict` / `HashMap` / `Map` as a cache without an\nexplicit size cap — they grow with input and OOM on large catalogs/ingestions (only exception: the\nuser explicitly asks for unbounded). Pick a sane default (100–1000 entries); if unsure, ask.\nPython: `collections.OrderedDict` + `popitem(last=False)`, `@functools.lru_cache(maxsize=N)`, or\n`cachetools.LRUCache` (cache hits **and** misses). Java: Caffeine/Guava `maximumSize(N)`.\nTypeScript: `lru-cache`. Before adding a cache, check it isn't already cached a layer down (e.g.\n`OpenMetadata._search_es_entity` is already `@lru_cache(maxsize=512)`).\n\n**Comments explain *why*, never restate code.** Do NOT add comments that describe what obvious code\ndoes (`// Create user` before `createUser()`). Only comment complex business logic, non-obvious\nalgorithms/workarounds, public-API JavaDoc, or `TODO/FIXME` with a ticket reference. If code needs a\ncomment to be understood, refactor it to be clearer instead.\n\n**Testing philosophy.** Test real behavior, not mock wiring — if a test mocks 3+ of your own classes\nto verify a method call, it tests the wrong thing. Prefer integration tests over heavily-mocked unit\ntests (this project has real ITs: `OpenMetadataApplicationTest`, Docker, real OpenSearch). Mocks are\nfor boundaries (HTTP clients, third-party APIs), not internals. Ask \"what breaks if this test passes\nbut the code is wrong?\" — if the answer is \"nothing\", rewrite it. Assert on observable outcomes\n(API responses, DB state), not internal `verify()` calls.\n\n**License headers are per-module — copy one from a sibling file, never assume Apache.** UI TS/TSX:\nApache-2.0 (`yarn license-header-fix`). Python: `ingestion/` is **Collate Community License 1.0** (`ingestion/LICENSE`); `openmetadata-airflow-apis/` Python files use the same Collate header template.\nJava: Apache-2.0, most files carry none.\nOnly the UI is enforced — the `ui-license-header` pre-commit hook and CI `ui-checkstyle`; spotless\nand `py_format_check` never look at headers, so a wrong Python or Java header ships silently.\n\n**Schema-first.** JSON Schemas in `openmetadata-spec/` are the single source of truth; all generated\ncode (Java POJOs, Pydantic models, TS types) is derived. **Edit the schema, then regenerate — never\nhand-edit generated output.** Details in `.claude/rules/schema-first.md`.\n\n**Output style.** Clean code blocks, no unnecessary explanation; assume an experienced reader; focus\non functionality over education. Do not add unnecessary blank lines between prose and code blocks.\n\n**No wrappers around core-ui components.** If a wrapper component exists that wraps a core-ui component, skip it — use the `openmetadata-ui-core-components` component directly at the call site. Only create a wrapper if it adds genuine, non-trivial behaviour (custom hook logic, composed sub-components, domain-specific state). A wrapper that only passes props through is a maintenance liability: it hides which core component is in use and drifts from upstream updates.\n\n**Icons and assets: always go through the design-system layer.** Import icons from `@openmetadata/ui-core-components/icons`, never directly from `@untitledui/icons` — the barrel ships only the design team's own curated SVG set, so add a missing glyph there via `yarn icons:generate` (see the core-components `ICONS.md`) rather than reaching for `@untitledui/icons`. For the same reason, do not import SVG icons directly from `assets/` paths; use the designated abstraction instead.\n\n## Pointer index — when to reach for what\n\n### Path-scoped rules (`.claude/rules/*.md`, auto-load on matching files)\n\n| Rule file | Reach for it when you are editing… |\n|---|---|\n| `java.md` / `java-impact-map.md` | any `**/*.java` — style, spotless, no-wildcard, Kafka-grade method/class rules, ITs; own new code and ITs in `.github/java-tests/impact-map.json` before the PR |\n| `frontend-react.md` | UI `*.{ts,tsx}` — components, hooks, state, types, and the CI lint code-rules |\n| `frontend-styling.md` | UI `*.{ts,tsx,less,css}` — `tw:` prefix, design tokens, ring→border, token-audit |\n| `component-library.md` | UI `*.{ts,tsx}` — prefer `ui-core-components`, do not add Ant Design for new work |\n| `frontend-performance.md` | UI `*.{ts,tsx}` — waterfalls, barrel imports, re-renders, bundle discipline |\n| `frontend-permissions.md` | UI `*.{ts,tsx}` — `useEntityPermissions` and derived flags; never read a permission key directly |\n| `frontend-a11y.md` | UI `*.{ts,tsx}` — semantics over `div`+`role`, keyboard, focus, contrast, targets |\n| `i18n.md` | UI `*.{ts,tsx}` + `src/locale/**` — no string literals, `yarn i18n`, translate placeholders |\n| `frontend-playwright.md` | UI `playwright/**` — E2E test constraints |\n| `python-ingestion.md` | `ingestion/src/**/*.py` — pytest style, connector-specific-file rule, `model_str()` |\n| `schema-first.md` | `openmetadata-spec/.../schema/**` and any `generated/**` — regen, never hand-edit generated |\n| `migrations.md` | `bootstrap/sql/**` — append-only, native path, MySQL+Postgres, idempotent |\n\n### Repo coding conventions (read before writing non-trivial code)\n\n- `docs/design-patterns.md` — the design patterns this codebase uses idiomatically (Template Method\n  for repositories, Factory/Registry for dispatch, Strategy/Adapter/Observer, the ingestion\n  Source→Sink pipeline, …) with the canonical class to copy each from. Extend the established pattern\n  rather than inventing a parallel one.\n- `openmetadata-ui/src/main/resources/ui/DEVELOPER_HANDBOOK.md` — **the UI folder structure and file\n  naming spec.** Read before creating any new file under `openmetadata-ui/.../ui/src/`. Layers stay\n  top-level (`components/`, `pages/`, `rest/`, `utils/`, `hooks/`) and are grouped inside by\n  `domain/feature/`; new files use one stem with a role suffix (`GlossaryList.tsx`, `.types.ts`,\n  `.utils.ts`, `.test.tsx`). Legacy `.component.tsx`/`.interface.ts` files stay as they are.\n- `REVIEW.md` — **the review bar every PR is held to**: the logic defects, test gaps and flaky-test\n  shapes reviewers keep finding here. Read it before writing code; `pr-checklist` self-reviews against it.\n- `docs/decisions/` — dated records of the choices that shape the code. **When a choice looks\n  arbitrary, find its record before re-deciding it; a PR that makes a durable decision adds the\n  record in the same PR.** Cite as `ADR:<date>-<slug>`; format and triggers in its `README.md`.\n\n### Skills (`skills/<name>/`, linked into `.claude/skills/` and `.agents/skills/`; invoke by name)\n\n| Skill | Reach for it when… |\n|---|---|\n| `dev-setup` | setting up / repairing a dev environment, a fresh clone, or a new worktree |\n| `planning` | starting any non-trivial, multi-file feature or refactor |\n| `tdd` | implementing a feature or bug fix (RED→GREEN→REFACTOR) |\n| `systematic-debugging` | a failing test/build/runtime issue whose cause isn't obvious |\n| `test-enforcement` | before a PR — 90% changed-class coverage, ITs for new endpoints, Playwright for UI |\n| `java-affected-tests` | before a PR touching Java/schemas/migrations — runs the impacted unit tests + ITs (PR CI runs no ITs) |\n| `verification` | before claiming \"done\" — run real commands, show evidence |\n| `code-review` | reviewing a local diff before it is a PR — `REVIEW.md` as the bar, spec compliance then code quality |\n| `java-checkstyle` | after touching `.java` — runs `mvn spotless:apply` and verifies |\n| `ui-checkstyle` | after touching UI `*.{ts,tsx,js,jsx,json}` — the exact CI ESLint+Prettier+organize-imports pass |\n| `ui-core-components` | building UI layout/color before reaching for raw `<div>` + Tailwind |\n| `test-locally` | spinning up the full local Docker stack to test a change/connector |\n| `connector-standards` / `connector-building` / `connector-review` | building or reviewing an ingestion connector |\n| `playwright` / `writing-playwright-tests` / `playwright-validation` | authoring or validating Playwright E2E tests |\n| `pr-checklist` / `ui-pr-recording` | opening any PR — self-review against `REVIEW.md`, test evidence, the body; a UI feature PR also runs the build in Docker with sample data and uploads its screen recording |\n| `openmetadata-pr-review` | reviewing a real GitHub PR (number/URL/batch) — maintainer merge verdict: live diff, CI, meaningful-test rubric |\n\n> `openmetadata-workflow` is a meta-skill that routes tasks to the skills above; it is auto-loaded at\n> session start when the `openmetadata-skills` plugin is installed.\n\n### Harness integrity (CI, warnings-only)\n\nA CI workflow (harness-integrity.yml) runs `scripts/harness/check_harness.py` on PRs — also `make harness-check` locally.\nIt **warns, never blocks** (promote to a gate only with maintainer sign-off) when the agent-facing config decays:\n\n- **dead references** — a path, `make`/`yarn` target, or `mvn` goal named in this file,\n  ARCHITECTURE.md, `docs/index.md`, `.claude/rules/**`, or a SKILL.md that no longer resolves;\n- **one instruction file** — a `CLAUDE.md` or `copilot-instructions.md` that is not a link to its `AGENTS.md`, another\n  harness's own file (`GEMINI.md`, `.cursorrules`, …), a rule missing from the index, a chain over Codex's 32,768 bytes;\n- **skill symlinks** — a real file where a symlink into `skills/` is expected (`.claude/skills`,\n  `.agents/skills`), a skill missing from either of them, or two same-named SKILL.md that differ;\n- **doc-size budgets** — this file > 200 lines, ARCHITECTURE.md > 300, any single rule > 100;\n- **rule globs** — a `.claude/rules/**` `paths:` glob matching zero files;\n- **generated-doc freshness** — `docs/generated/**` out of date with its source;\n- **decision records** — a malformed record or a dangling `ADR:` citation (also a pre-commit hook).\n\n## Git commit conventions\n- Never add \"Co-Authored-By\" lines or any AI-attribution trailers to commit messages. \n- The commit is authored by me; you are a tool, not a co-author.\n","isInternal":false,"tokens":3928,"sizeBytes":15392},{"name":"copilot-instructions.md","path":".github/copilot-instructions.md","rawUrl":"https://raw.githubusercontent.com/open-metadata/OpenMetadata/HEAD/.github/copilot-instructions.md","title":"GitHub Copilot Instructions","category":"copilot-instructions","format":"markdown","content":"../AGENTS.md","isInternal":false,"tokens":4,"sizeBytes":12},{"name":"marketplace.json","path":".claude-plugin/marketplace.json","rawUrl":"https://raw.githubusercontent.com/open-metadata/OpenMetadata/HEAD/.claude-plugin/marketplace.json","title":"Claude Plugin Marketplace Catalog","category":"marketplace","format":"json","content":"# Claude Plugin Marketplace Catalog\n\nPath: `.claude-plugin/marketplace.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/open-metadata/OpenMetadata/HEAD/.claude-plugin/marketplace.json)","tokens":300,"sizeBytes":205},{"name":"plugin.json","path":".claude-plugin/plugin.json","rawUrl":"https://raw.githubusercontent.com/open-metadata/OpenMetadata/HEAD/.claude-plugin/plugin.json","title":"claude-plugin Plugin Manifest","category":"plugin-manifest","format":"json","content":"# claude-plugin Plugin Manifest\n\nPath: `.claude-plugin/plugin.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/open-metadata/OpenMetadata/HEAD/.claude-plugin/plugin.json)","tokens":300,"sizeBytes":191},{"name":"mcp.json","path":".cursor/mcp.json","rawUrl":"https://raw.githubusercontent.com/open-metadata/OpenMetadata/HEAD/.cursor/mcp.json","title":"Model Context Protocol (MCP) Configuration","category":"mcp-config","format":"json","content":"# Model Context Protocol (MCP) Configuration\n\nPath: `.cursor/mcp.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/open-metadata/OpenMetadata/HEAD/.cursor/mcp.json)","tokens":300,"sizeBytes":184}],"systemPromptSnippet":"<yakaai_skills repo=\"open-metadata/OpenMetadata\">\n<!-- File: AGENTS.md (Tokens: ~3928 | Category: root-instruction) -->\n# AGENTS.md\n\nAlways-loaded guidance for every session, whatever the harness — **the only instruction file:** every `CLAUDE.md` and\n`.github/copilot-instructions.md` is a symlink to the `AGENTS.md` beside it\n(ADR:2026-10-09-agents-md-is-the-one-instruction-file), so edit this file, never a copy. **Language- and path-specific\nrules live in `.claude/rules/*.md` (Claude Code auto-loads them on matching files; other harnesses read the matching\none before editing); procedures live in skills (loaded on invoke).** This file is the map — see the pointer index at\nthe bottom. Read [ARCHITECTURE.md](ARCHITECTURE.md) for the **system map** (modules, the request/ingestion/search\npaths, the invariants that hold); read [DEVELOPER.md](DEVELOPER.md) for **how to build, test, and add an entity or\nconnector** (deep dives + end-to-end checklists). Consult [docs/index.md](docs/index.md) — the **knowledge index** —\nto **find existing design, plan, and reference docs** for whatever area you're working on.\n\n## About OpenMetadata\n\nOpenMetadata is a unified metadata platform for data discovery, observability, and governance — a\nmulti-module project with a Java backend, a React/TypeScript frontend, a Python ingestion framework,\nand Docker infrastructure.\n\n## Stack at a glance\n\n- **Backend**: Java 21 + Dropwizard, multi-module Maven.\n- **Frontend**: React + TypeScript, built with **Vite** (dev server on :3000); component library\n  `openmetadata-ui-core-components` — the **UntitledUI + Tailwind v4** (`tw:` prefix, react-aria-components)\n  go-forward design system; legacy stack is Ant Design + Less (deprecated). Machine-readable design-system\n  specs: `openmetadata-ui/src/main/resources/ui/specs/` (read `specs/README.md` before UI work).\n- **Ingestion**: Python (`>=3.10`, no pinned ceiling; **CI runs 3.10**) + Pydantic 2.x, 75+ connectors.\n- **Database**: MySQL (default) or PostgreSQL. **Search**: Elasticsearch 7.17+ or OpenSearch 2.6+.\n- **Infrastructure**: Apache Airflow for ingestion orchestration.\n\n## Environment setup (every session)\n\n- **Python venv is REQUIRED before any Python work, `make generate`, or `make install_dev*`:**\n  ```bash\n  source env/bin/activate          # first time: python3.11 -m venv env\n  python --version                 # expect 3.10.x/3.11.x\n  ```\n  In a Claude Code **worktree** the venv is NOT copied — create one\n  (`python3.11 -m venv env && source env/bin/activate && cd ingestion && make install_dev`) or\n  symlink the main repo's (`ln -s /path/to/main-repo/env env`).\n- **One-call setup (macOS + Linux)**: `make dev_setup` (or `./scripts/dev_setup.sh`) does everything\n  below — toolchain, venv, generation, UI deps, pre-commit — and is idempotent. `make dev_check`\n  diagnoses an existing checkout without changing it. See the `dev-setup` skill.\n- **First-time bootstrap** (from the **repo root** — `make generate` is a root-only target; it does\n  not exist under `ingestion/`):\n  ```bash\n  make prerequisites\n  source env/bin/activate && cd ingestion && make install_dev_env && cd ..\n  make generate                    # regenerate models after any schema change\n  make yarn_install_cache\n  make install_test precommit_install   # activate the commit-time format/license gate (pre-commit)\n  ```\n  The last line installs the `pre-commit` hooks (`.pre-commit-config.yaml`): on `git commit` they run\n  Java format (spotless), Python format (ruff), UI format (prettier), design-token, and Apache-2.0\n  license checks on your changed files, matching CI. Do not skip them with `--no-verify`.\n- **Java**: Java 21; use `mvn`. **Frontend**: use `yarn` (never `npm`); frontend root is `openmetadata-ui/src/main/resources/ui/`.\n- **Docker dev services**: `docker compose -f docker/development/docker-compose.yml up -d`.\n\n## Repository layout\n\nMaven modules (reactor order is computed from the graph, not this list):\n\n- `openmetadata-spec/` — JSON Schemas + generated POJOs; the schema-first source of truth\n- `openmetadata-sdk/` — Java client SDK\n- `common/` — shared utilities (`CommonUtil`, etc.)\n- `openmetadata-shaded-deps/` — ES/OS clients relocated behind `es.*`/`os.*` (do not edit — see rules)\n- `openmetadata-service/` — core Java backend, REST APIs, repositories, migrations runner\n- `openmetadata-k8s-operator/` — Kubernetes operator\n- `openmetadata-integration-tests/` — backend API integration tests (`*IT.java`)\n- `openmetadata-mcp/` — MCP server\n- `openmetadata-ui-core-components/` — canonical React component library\n- `openmetadata-ui/src/main/resources/ui/` — React frontend application\n- `openmetadata-dist/` — packaging/distribution\n- `openmetadata-clients/` — client artifacts\n\nOther key trees: `ingestion/` (Python framework + connectors), `bootstrap/sql/` (DB migrations), `conf/` (configuration), `docker/` (local + prod deployment).\n\n## Hard cross-cutting constraints (apply to every session, all languages)\n\n**Secrets & security.** Never commit secrets — use environment variables or a secrets manager.\nAuth is JWT with OAuth2/SAML; RBAC lives in Java entities; config in `conf/openmetadata.yaml`.\n**Do not modify `.github/workflows/**` on your own** — CI workflows are a supply-chain surface; a\n`PreToolUse` hook blocks edits there unless the user explicitly authorizes them (by setting\n`CLAUDE_ALLOW_WORKFLOW_EDITS=1`). Ask first.\n\n**All caches MUST be bounded.** Never use a bare `dict` / `HashMap` / `Map` as a cache without an\nexplicit size cap — they grow with input and OOM on large catalogs/ingestions (only exception: the\nuser explicitly asks for unbounded). Pick a sane default (100–1000 entries); if unsure, ask.\nPython: `collections.OrderedDict` + `popitem(last=False)`, `@functools.lru_cache(maxsize=N)`, or\n`cachetools.LRUCache` (cache hits **and** misses). Java: Caffeine/Guava `maximumSize(N)`.\nTypeScript: `lru-cache`. Before adding a cache, check it isn't already cached a layer down (e.g.\n`OpenMetadata._search_es_entity` is already `@lru_cache(maxsize=512)`).\n\n**Comments explain *why*, never restate code.** Do NOT add comments that describe what obvious code\ndoes (`// Create user` before `createUser()`). Only comment complex business logic, non-obvious\nalgorithms/workarounds, public-API JavaDoc, or `TODO/FIXME` with a ticket reference. If code needs a\ncomment to be understood, refactor it to be clearer instead.\n\n**Testing philosophy.** Test real behavior, not mock wiring — if a test mocks 3+ of your own classes\nto verify a method call, it tests the wrong thing. Prefer integration tests over heavily-mocked unit\ntests (this project has real ITs: `OpenMetadataApplicationTest`, Docker, real OpenSearch). Mocks are\nfor boundaries (HTTP clients, third-party APIs), not internals. Ask \"what breaks if this test passes\nbut the code is wrong?\" — if the answer is \"nothing\", rewrite it. Assert on observable outcomes\n(API responses, DB state), not internal `verify()` calls.\n\n**License headers are per-module — copy one from a sibling file, never assume Apache.** UI TS/TSX:\nApache-2.0 (`yarn license-header-fix`). Python: `ingestion/` is **Collate Community License 1.0** (`ingestion/LICENSE`); `openmetadata-airflow-apis/` Python files use the same Collate header template.\nJava: Apache-2.0, most files carry none.\nOnly the UI is enforced — the `ui-license-header` pre-commit hook and CI `ui-checkstyle`; spotless\nand `py_format_check` never look at headers, so a wrong Python or Java header ships silently.\n\n**Schema-first.** JSON Schemas in `openmetadata-spec/` are the single source of truth; all generated\ncode (Java POJOs, Pydantic models, TS types) is derived. **Edit the schema, then regenerate — never\nhand-edit generated output.** Details in `.claude/rules/schema-first.md`.\n\n**Output style.** Clean code blocks, no unnecessary explanation; assume an experienced reader; focus\non functionality over education. Do not add unnecessary blank lines between prose and code blocks.\n\n**No wrappers around core-ui components.** If a wrapper component exists that wraps a core-ui component, skip it — use the `openmetadata-ui-core-components` component directly at the call site. Only create a wrapper if it adds genuine, non-trivial behaviour (custom hook logic, composed sub-components, domain-specific state). A wrapper that only passes props through is a maintenance liability: it hides which core component is in use and drifts from upstream updates.\n\n**Icons and assets: always go through the design-system layer.** Import icons from `@openmetadata/ui-core-components/icons`, never directly from `@untitledui/icons` — the barrel ships only the design team's own curated SVG set, so add a missing glyph there via `yarn icons:generate` (see the core-components `ICONS.md`) rather than reaching for `@untitledui/icons`. For the same reason, do not import SVG icons directly from `assets/` paths; use the designated abstraction instead.\n\n## Pointer index — when to reach for what\n\n### Path-scoped rules (`.claude/rules/*.md`, auto-load on matching files)\n\n| Rule file | Reach for it when you are editing… |\n|---|---|\n| `java.md` / `java-impact-map.md` | any `**/*.java` — style, spotless, no-wildcard, Kafka-grade method/class rules, ITs; own new code and ITs in `.github/java-tests/impact-map.json` before the PR |\n| `frontend-react.md` | UI `*.{ts,tsx}` — components, hooks, state, types, and the CI lint code-rules |\n| `frontend-styling.md` | UI `*.{ts,tsx,less,css}` — `tw:` prefix, design tokens, ring→border, token-audit |\n| `component-library.md` | UI `*.{ts,tsx}` — prefer `ui-core-components`, do not add Ant Design for new work |\n| `frontend-performance.md` | UI `*.{ts,tsx}` — waterfalls, barrel imports, re-renders, bundle discipline |\n| `frontend-permissions.md` | UI `*.{ts,tsx}` — `useEntityPermissions` and derived flags; never read a permission key directly |\n| `frontend-a11y.md` | UI `*.{ts,tsx}` — semantics over `div`+`role`, keyboard, focus, contrast, targets |\n| `i18n.md` | UI `*.{ts,tsx}` + `src/locale/**` — no string literals, `yarn i18n`, translate placeholders |\n| `frontend-playwright.md` | UI `playwright/**` — E2E test constraints |\n| `python-ingestion.md` | `ingestion/src/**/*.py` — pytest style, connector-specific-file rule, `model_str()` |\n| `schema-first.md` | `openmetadata-spec/.../schema/**` and any `generated/**` — regen, never hand-edit generated |\n| `migrations.md` | `bootstrap/sql/**` — append-only, native path, MySQL+Postgres, idempotent |\n\n### Repo coding conventions (read before writing non-trivial code)\n\n- `docs/design-patterns.md` — the design patterns this codebase uses idiomatically (Template Method\n  for repositories, Factory/Registry for dispatch, Strategy/Adapter/Observer, the ingestion\n  Source→Sink pipeline, …) with the canonical class to copy each from. Extend the established pattern\n  rather than inventing a parallel one.\n- `openmetadata-ui/src/main/resources/ui/DEVELOPER_HANDBOOK.md` — **the UI folder structure and file\n  naming spec.** Read before creating any new file under `openmetadata-ui/.../ui/src/`. Layers stay\n  top-level (`components/`, `pages/`, `rest/`, `utils/`, `hooks/`) and are grouped inside by\n  `domain/feature/`; new files use one stem with a role suffix (`GlossaryList.tsx`, `.types.ts`,\n  `.utils.ts`, `.test.tsx`). Legacy `.component.tsx`/`.interface.ts` files stay as they are.\n- `REVIEW.md` — **the review bar every PR is held to**: the logic defects, test gaps and flaky-test\n  shapes reviewers keep finding here. Read it before writing code; `pr-checklist` self-reviews against it.\n- `docs/decisions/` — dated records of the choices that shape the code. **When a choice looks\n  arbitrary, find its record before re-deciding it; a PR that makes a durable decision adds the\n  record in the same PR.** Cite as `ADR:<date>-<slug>`; format and triggers in its `README.md`.\n\n### Skills (`skills/<name>/`, linked into `.claude/skills/` and `.agents/skills/`; invoke by name)\n\n| Skill | Reach for it when… |\n|---|---|\n| `dev-setup` | setting up / repairing a dev environment, a fresh clone, or a new worktree |\n| `planning` | starting any non-trivial, multi-file feature or refactor |\n| `tdd` | implementing a feature or bug fix (RED→GREEN→REFACTOR) |\n| `systematic-debugging` | a failing test/build/runtime issue whose cause isn't obvious |\n| `test-enforcement` | before a PR — 90% changed-class coverage, ITs for new endpoints, Playwright for UI |\n| `java-affected-tests` | before a PR touching Java/schemas/migrations — runs the impacted unit tests + ITs (PR CI runs no ITs) |\n| `verification` | before claiming \"done\" — run real commands, show evidence |\n| `code-review` | reviewing a local diff before it is a PR — `REVIEW.md` as the bar, spec compliance then code quality |\n| `java-checkstyle` | after touching `.java` — runs `mvn spotless:apply` and verifies |\n| `ui-checkstyle` | after touching UI `*.{ts,tsx,js,jsx,json}` — the exact CI ESLint+Prettier+organize-imports pass |\n| `ui-core-components` | building UI layout/color before reaching for raw `<div>` + Tailwind |\n| `test-locally` | spinning up the full local Docker stack to test a change/connector |\n| `connector-standards` / `connector-building` / `connector-review` | building or reviewing an ingestion connector |\n| `playwright` / `writing-playwright-tests` / `playwright-validation` | authoring or validating Playwright E2E tests |\n| `pr-checklist` / `ui-pr-recording` | opening any PR — self-review against `REVIEW.md`, test evidence, the body; a UI feature PR also runs the build in Docker with sample data and uploads its screen recording |\n| `openmetadata-pr-review` | reviewing a real GitHub PR (number/URL/batch) — maintainer merge verdict: live diff, CI, meaningful-test rubric |\n\n> `openmetadata-workflow` is a meta-skill that routes tasks to the skills above; it is auto-loaded at\n> session start when the `openmetadata-skills` plugin is installed.\n\n### Harness integrity (CI, warnings-only)\n\nA CI workflow (harness-integrity.yml) runs `scripts/harness/check_harness.py` on PRs — also `make harness-check` locally.\nIt **warns, never blocks** (promote to a gate only with maintainer sign-off) when the agent-facing config decays:\n\n- **dead references** — a path, `make`/`yarn` target, or `mvn` goal named in this file,\n  ARCHITECTURE.md, `docs/index.md`, `.claude/rules/**`, or a SKILL.md that no longer resolves;\n- **one instruction file** — a `CLAUDE.md` or `copilot-instructions.md` that is not a link to its `AGENTS.md`, another\n  harness's own file (`GEMINI.md`, `.cursorrules`, …), a rule missing from the index, a chain over Codex's 32,768 bytes;\n- **skill symlinks** — a real file where a symlink into `skills/` is expected (`.claude/skills`,\n  `.agents/skills`), a skill missing from either of them, or two same-named SKILL.md that differ;\n- **doc-size budgets** — this file > 200 lines, ARCHITECTURE.md > 300, any single rule > 100;\n- **rule globs** — a `.claude/rules/**` `paths:` glob matching zero files;\n- **generated-doc freshness** — `docs/generated/**` out of date with its source;\n- **decision records** — a malformed record or a dangling `ADR:` citation (also a pre-commit hook).\n\n## Git commit conventions\n- Never add \"Co-Authored-By\" lines or any AI-attribution trailers to commit messages. \n- The commit is authored by me; you are a tool, not a co-author.\n\n<!-- File: CLAUDE.md (Tokens: ~3928 | Category: claude-rule) -->\n# AGENTS.md\n\nAlways-loaded guidance for every session, whatever the harness — **the only instruction file:** every `CLAUDE.md` and\n`.github/copilot-instructions.md` is a symlink to the `AGENTS.md` beside it\n(ADR:2026-10-09-agents-md-is-the-one-instruction-file), so edit this file, never a copy. **Language- and path-specific\nrules live in `.claude/rules/*.md` (Claude Code auto-loads them on matching files; other harnesses read the matching\none before editing); procedures live in skills (loaded on invoke).** This file is the map — see the pointer index at\nthe bottom. Read [ARCHITECTURE.md](ARCHITECTURE.md) for the **system map** (modules, the request/ingestion/search\npaths, the invariants that hold); read [DEVELOPER.md](DEVELOPER.md) for **how to build, test, and add an entity or\nconnector** (deep dives + end-to-end checklists). Consult [docs/index.md](docs/index.md) — the **knowledge index** —\nto **find existing design, plan, and reference docs** for whatever area you're working on.\n\n## About OpenMetadata\n\nOpenMetadata is a unified metadata platform for data discovery, observability, and governance — a\nmulti-module project with a Java backend, a React/TypeScript frontend, a Python ingestion framework,\nand Docker infrastructure.\n\n## Stack at a glance\n\n- **Backend**: Java 21 + Dropwizard, multi-module Maven.\n- **Frontend**: React + TypeScript, built with **Vite** (dev server on :3000); component library\n  `openmetadata-ui-core-components` — the **UntitledUI + Tailwind v4** (`tw:` prefix, react-aria-components)\n  go-forward design system; legacy stack is Ant Design + Less (deprecated). Machine-readable design-system\n  specs: `openmetadata-ui/src/main/resources/ui/specs/` (read `specs/README.md` before UI work).\n- **Ingestion**: Python (`>=3.10`, no pinned ceiling; **CI runs 3.10**) + Pydantic 2.x, 75+ connectors.\n- **Database**: MySQL (default) or PostgreSQL. **Search**: Elasticsearch 7.17+ or OpenSearch 2.6+.\n- **Infrastructure**: Apache Airflow for ingestion orchestration.\n\n## Environment setup (every session)\n\n- **Python venv is REQUIRED before any Python work, `make generate`, or `make install_dev*`:**\n  ```bash\n  source env/bin/activate          # first time: python3.11 -m venv env\n  python --version                 # expect 3.10.x/3.11.x\n  ```\n  In a Claude Code **worktree** the venv is NOT copied — create one\n  (`python3.11 -m venv env && source env/bin/activate && cd ingestion && make install_dev`) or\n  symlink the main repo's (`ln -s /path/to/main-repo/env env`).\n- **One-call setup (macOS + Linux)**: `make dev_setup` (or `./scripts/dev_setup.sh`) does everything\n  below — toolchain, venv, generation, UI deps, pre-commit — and is idempotent. `make dev_check`\n  diagnoses an existing checkout without changing it. See the `dev-setup` skill.\n- **First-time bootstrap** (from the **repo root** — `make generate` is a root-only target; it does\n  not exist under `ingestion/`):\n  ```bash\n  make prerequisites\n  source env/bin/activate && cd ingestion && make install_dev_env && cd ..\n  make generate                    # regenerate models after any schema change\n  make yarn_install_cache\n  make install_test precommit_install   # activate the commit-time format/license gate (pre-commit)\n  ```\n  The last line installs the `pre-commit` hooks (`.pre-commit-config.yaml`): on `git commit` they run\n  Java format (spotless), Python format (ruff), UI format (prettier), design-token, and Apache-2.0\n  license checks on your changed files, matching CI. Do not skip them with `--no-verify`.\n- **Java**: Java 21; use `mvn`. **Frontend**: use `yarn` (never `npm`); frontend root is `openmetadata-ui/src/main/resources/ui/`.\n- **Docker dev services**: `docker compose -f docker/development/docker-compose.yml up -d`.\n\n## Repository layout\n\nMaven modules (reactor order is computed from the graph, not this list):\n\n- `openmetadata-spec/` — JSON Schemas + generated POJOs; the schema-first source of truth\n- `openmetadata-sdk/` — Java client SDK\n- `common/` — shared utilities (`CommonUtil`, etc.)\n- `openmetadata-shaded-deps/` — ES/OS clients relocated behind `es.*`/`os.*` (do not edit — see rules)\n- `openmetadata-service/` — core Java backend, REST APIs, repositories, migrations runner\n- `openmetadata-k8s-operator/` — Kubernetes operator\n- `openmetadata-integration-tests/` — backend API integration tests (`*IT.java`)\n- `openmetadata-mcp/` — MCP server\n- `openmetadata-ui-core-components/` — canonical React component library\n- `openmetadata-ui/src/main/resources/ui/` — React frontend application\n- `openmetadata-dist/` — packaging/distribution\n- `openmetadata-clients/` — client artifacts\n\nOther key trees: `ingestion/` (Python framework + connectors), `bootstrap/sql/` (DB migrations), `conf/` (configuration), `docker/` (local + prod deployment).\n\n## Hard cross-cutting constraints (apply to every session, all languages)\n\n**Secrets & security.** Never commit secrets — use environment variables or a secrets manager.\nAuth is JWT with OAuth2/SAML; RBAC lives in Java entities; config in `conf/openmetadata.yaml`.\n**Do not modify `.github/workflows/**` on your own** — CI workflows are a supply-chain surface; a\n`PreToolUse` hook blocks edits there unless the user explicitly authorizes them (by setting\n`CLAUDE_ALLOW_WORKFLOW_EDITS=1`). Ask first.\n\n**All caches MUST be bounded.** Never use a bare `dict` / `HashMap` / `Map` as a cache without an\nexplicit size cap — they grow with input and OOM on large catalogs/ingestions (only exception: the\nuser explicitly asks for unbounded). Pick a sane default (100–1000 entries); if unsure, ask.\nPython: `collections.OrderedDict` + `popitem(last=False)`, `@functools.lru_cache(maxsize=N)`, or\n`cachetools.LRUCache` (cache hits **and** misses). Java: Caffeine/Guava `maximumSize(N)`.\nTypeScript: `lru-cache`. Before adding a cache, check it isn't already cached a layer down (e.g.\n`OpenMetadata._search_es_entity` is already `@lru_cache(maxsize=512)`).\n\n**Comments explain *why*, never restate code.** Do NOT add comments that describe what obvious code\ndoes (`// Create user` before `createUser()`). Only comment complex business logic, non-obvious\nalgorithms/workarounds, public-API JavaDoc, or `TODO/FIXME` with a ticket reference. If code needs a\ncomment to be understood, refactor it to be clearer instead.\n\n**Testing philosophy.** Test real behavior, not mock wiring — if a test mocks 3+ of your own classes\nto verify a method call, it tests the wrong thing. Prefer integration tests over heavily-mocked unit\ntests (this project has real ITs: `OpenMetadataApplicationTest`, Docker, real OpenSearch). Mocks are\nfor boundaries (HTTP clients, third-party APIs), not internals. Ask \"what breaks if this test passes\nbut the code is wrong?\" — if the answer is \"nothing\", rewrite it. Assert on observable outcomes\n(API responses, DB state), not internal `verify()` calls.\n\n**License headers are per-module — copy one from a sibling file, never assume Apache.** UI TS/TSX:\nApache-2.0 (`yarn license-header-fix`). Python: `ingestion/` is **Collate Community License 1.0** (`ingestion/LICENSE`); `openmetadata-airflow-apis/` Python files use the same Collate header template.\nJava: Apache-2.0, most files carry none.\nOnly the UI is enforced — the `ui-license-header` pre-commit hook and CI `ui-checkstyle`; spotless\nand `py_format_check` never look at headers, so a wrong Python or Java header ships silently.\n\n**Schema-first.** JSON Schemas in `openmetadata-spec/` are the single source of truth; all generated\ncode (Java POJOs, Pydantic models, TS types) is derived. **Edit the schema, then regenerate — never\nhand-edit generated output.** Details in `.claude/rules/schema-first.md`.\n\n**Output style.** Clean code blocks, no unnecessary explanation; assume an experienced reader; focus\non functionality over education. Do not add unnecessary blank lines between prose and code blocks.\n\n**No wrappers around core-ui components.** If a wrapper component exists that wraps a core-ui component, skip it — use the `openmetadata-ui-core-components` component directly at the call site. Only create a wrapper if it adds genuine, non-trivial behaviour (custom hook logic, composed sub-components, domain-specific state). A wrapper that only passes props through is a maintenance liability: it hides which core component is in use and drifts from upstream updates.\n\n**Icons and assets: always go through the design-system layer.** Import icons from `@openmetadata/ui-core-components/icons`, never directly from `@untitledui/icons` — the barrel ships only the design team's own curated SVG set, so add a missing glyph there via `yarn icons:generate` (see the core-components `ICONS.md`) rather than reaching for `@untitledui/icons`. For the same reason, do not import SVG icons directly from `assets/` paths; use the designated abstraction instead.\n\n## Pointer index — when to reach for what\n\n### Path-scoped rules (`.claude/rules/*.md`, auto-load on matching files)\n\n| Rule file | Reach for it when you are editing… |\n|---|---|\n| `java.md` / `java-impact-map.md` | any `**/*.java` — style, spotless, no-wildcard, Kafka-grade method/class rules, ITs; own new code and ITs in `.github/java-tests/impact-map.json` before the PR |\n| `frontend-react.md` | UI `*.{ts,tsx}` — components, hooks, state, types, and the CI lint code-rules |\n| `frontend-styling.md` | UI `*.{ts,tsx,less,css}` — `tw:` prefix, design tokens, ring→border, token-audit |\n| `component-library.md` | UI `*.{ts,tsx}` — prefer `ui-core-components`, do not add Ant Design for new work |\n| `frontend-performance.md` | UI `*.{ts,tsx}` — waterfalls, barrel imports, re-renders, bundle discipline |\n| `frontend-permissions.md` | UI `*.{ts,tsx}` — `useEntityPermissions` and derived flags; never read a permission key directly |\n| `frontend-a11y.md` | UI `*.{ts,tsx}` — semantics over `div`+`role`, keyboard, focus, contrast, targets |\n| `i18n.md` | UI `*.{ts,tsx}` + `src/locale/**` — no string literals, `yarn i18n`, translate placeholders |\n| `frontend-playwright.md` | UI `playwright/**` — E2E test constraints |\n| `python-ingestion.md` | `ingestion/src/**/*.py` — pytest style, connector-specific-file rule, `model_str()` |\n| `schema-first.md` | `openmetadata-spec/.../schema/**` and any `generated/**` — regen, never hand-edit generated |\n| `migrations.md` | `bootstrap/sql/**` — append-only, native path, MySQL+Postgres, idempotent |\n\n### Repo coding conventions (read before writing non-trivial code)\n\n- `docs/design-patterns.md` — the design patterns this codebase uses idiomatically (Template Method\n  for repositories, Factory/Registry for dispatch, Strategy/Adapter/Observer, the ingestion\n  Source→Sink pipeline, …) with the canonical class to copy each from. Extend the established pattern\n  rather than inventing a parallel one.\n- `openmetadata-ui/src/main/resources/ui/DEVELOPER_HANDBOOK.md` — **the UI folder structure and file\n  naming spec.** Read before creating any new file under `openmetadata-ui/.../ui/src/`. Layers stay\n  top-level (`components/`, `pages/`, `rest/`, `utils/`, `hooks/`) and are grouped inside by\n  `domain/feature/`; new files use one stem with a role suffix (`GlossaryList.tsx`, `.types.ts`,\n  `.utils.ts`, `.test.tsx`). Legacy `.component.tsx`/`.interface.ts` files stay as they are.\n- `REVIEW.md` — **the review bar every PR is held to**: the logic defects, test gaps and flaky-test\n  shapes reviewers keep finding here. Read it before writing code; `pr-checklist` self-reviews against it.\n- `docs/decisions/` — dated records of the choices that shape the code. **When a choice looks\n  arbitrary, find its record before re-deciding it; a PR that makes a durable decision adds the\n  record in the same PR.** Cite as `ADR:<date>-<slug>`; format and triggers in its `README.md`.\n\n### Skills (`skills/<name>/`, linked into `.claude/skills/` and `.agents/skills/`; invoke by name)\n\n| Skill | Reach for it when… |\n|---|---|\n| `dev-setup` | setting up / repairing a dev environment, a fresh clone, or a new worktree |\n| `planning` | starting any non-trivial, multi-file feature or refactor |\n| `tdd` | implementing a feature or bug fix (RED→GREEN→REFACTOR) |\n| `systematic-debugging` | a failing test/build/runtime issue whose cause isn't obvious |\n| `test-enforcement` | before a PR — 90% changed-class coverage, ITs for new endpoints, Playwright for UI |\n| `java-affected-tests` | before a PR touching Java/schemas/migrations — runs the impacted unit tests + ITs (PR CI runs no ITs) |\n| `verification` | before claiming \"done\" — run real commands, show evidence |\n| `code-review` | reviewing a local diff before it is a PR — `REVIEW.md` as the bar, spec compliance then code quality |\n| `java-checkstyle` | after touching `.java` — runs `mvn spotless:apply` and verifies |\n| `ui-checkstyle` | after touching UI `*.{ts,tsx,js,jsx,json}` — the exact CI ESLint+Prettier+organize-imports pass |\n| `ui-core-components` | building UI layout/color before reaching for raw `<div>` + Tailwind |\n| `test-locally` | spinning up the full local Docker stack to test a change/connector |\n| `connector-standards` / `connector-building` / `connector-review` | building or reviewing an ingestion connector |\n| `playwright` / `writing-playwright-tests` / `playwright-validation` | authoring or validating Playwright E2E tests |\n| `pr-checklist` / `ui-pr-recording` | opening any PR — self-review against `REVIEW.md`, test evidence, the body; a UI feature PR also runs the build in Docker with sample data and uploads its screen recording |\n| `openmetadata-pr-review` | reviewing a real GitHub PR (number/URL/batch) — maintainer merge verdict: live diff, CI, meaningful-test rubric |\n\n> `openmetadata-workflow` is a meta-skill that routes tasks to the skills above; it is auto-loaded at\n> session start when the `openmetadata-skills` plugin is installed.\n\n### Harness integrity (CI, warnings-only)\n\nA CI workflow (harness-integrity.yml) runs `scripts/harness/check_harness.py` on PRs — also `make harness-check` locally.\nIt **warns, never blocks** (promote to a gate only with maintainer sign-off) when the agent-facing config decays:\n\n- **dead references** — a path, `make`/`yarn` target, or `mvn` goal named in this file,\n  ARCHITECTURE.md, `docs/index.md`, `.claude/rules/**`, or a SKILL.md that no longer resolves;\n- **one instruction file** — a `CLAUDE.md` or `copilot-instructions.md` that is not a link to its `AGENTS.md`, another\n  harness's own file (`GEMINI.md`, `.cursorrules`, …), a rule missing from the index, a chain over Codex's 32,768 bytes;\n- **skill symlinks** — a real file where a symlink into `skills/` is expected (`.claude/skills`,\n  `.agents/skills`), a skill missing from either of them, or two same-named SKILL.md that differ;\n- **doc-size budgets** — this file > 200 lines, ARCHITECTURE.md > 300, any single rule > 100;\n- **rule globs** — a `.claude/rules/**` `paths:` glob matching zero files;\n- **generated-doc freshness** — `docs/generated/**` out of date with its source;\n- **decision records** — a malformed record or a dangling `ADR:` citation (also a pre-commit hook).\n\n## Git commit conventions\n- Never add \"Co-Authored-By\" lines or any AI-attribution trailers to commit messages. \n- The commit is authored by me; you are a tool, not a co-author.\n\n<!-- File: .github/copilot-instructions.md (Tokens: ~4 | Category: copilot-instructions) -->\n../AGENTS.md\n\n<!-- File: .claude-plugin/marketplace.json (Tokens: ~300 | Category: marketplace) -->\n# Claude Plugin Marketplace Catalog\n\nPath: `.claude-plugin/marketplace.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/open-metadata/OpenMetadata/HEAD/.claude-plugin/marketplace.json)\n\n<!-- File: .claude-plugin/plugin.json (Tokens: ~300 | Category: plugin-manifest) -->\n# claude-plugin Plugin Manifest\n\nPath: `.claude-plugin/plugin.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/open-metadata/OpenMetadata/HEAD/.claude-plugin/plugin.json)\n\n<!-- File: .cursor/mcp.json (Tokens: ~300 | Category: mcp-config) -->\n# Model Context Protocol (MCP) Configuration\n\nPath: `.cursor/mcp.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/open-metadata/OpenMetadata/HEAD/.cursor/mcp.json)\n</yakaai_skills>"}