diff --git a/.claude/skills/collection-compliance/SKILL.md b/.claude/skills/collection-compliance/SKILL.md new file mode 100644 index 00000000..3177d7aa --- /dev/null +++ b/.claude/skills/collection-compliance/SKILL.md @@ -0,0 +1,78 @@ +--- +name: collection-compliance +description: | + Diagnose and fix `.catalog/` validation failures (schema, roster, banners, sample workflows, JSON mirror). Use when: + - `make validate` or CI reports collection compliance errors + - A PR adds skills but catalog was not updated + - `collection.json` is out of sync with `collection.yaml` + - Catalog metadata/fragments might have drifted from README/CLAUDE/SKILL golden sources + + Remediation is via the create-collection workflow and `catalog_yaml_to_json.py`—not by weakening checks. +model: inherit +color: yellow +allowed-tools: Read Glob Grep Bash +--- + +# Collection compliance + +**Audience:** Contributors fixing `.catalog/` CI failures. + +**Goal:** Clear reported violations from `scripts/validate_collection_compliance.py` and `scripts/validate_collection_schema.py`, then perform AI semantic alignment review against golden sources. + +## Prerequisites + +- Run from repository root. +- Read [COLLECTION_SPEC.md](../../COLLECTION_SPEC.md). + +## When to Use + +- After `make validate-collection-compliance` fails locally or in GitHub Actions. + +## Workflow + +1. **Re-run** `uv run python scripts/validate_collection_compliance.py` and capture errors (pack path + message). + +2. **Classify** + - **Missing file** — create `.catalog/collection.yaml` via create-collection skill (or `uv run python scripts/bootstrap_catalog.py --pack ` for bootstrap baseline). + - **Schema** — align YAML with [catalog/schema.yaml](../../catalog/schema.yaml). + - **Roster** — every `skills//SKILL.md` must appear once under `contents.skills` or `contents.orchestration_skills` with `name == `. + - **Banner** — `collection.yaml` must mention `create-collection` and `Golden sources` in the opening `#` block. + - **`collection.json` drift** — run `uv run python scripts/catalog_yaml_to_json.py --pack ` or `make catalog-mirror-json`. + - **Fragment refs / length** — `deploy_and_use`, `documentation_section`, `mcp_section`, and `security_model` may be inline or a one-line `#fragment.md` under `.catalog/`. Refs must start with `#`. Inline monitored fields over **500** code points must move to a fragment on the **same** key. + - **Fragment provenance (`.catalog/*.md`)** — each referenced fragment must start with a leading HTML **``** block with the **same intent** as the `collection.yaml` banner: **create-collection** workflow and **Golden sources** (SKILL, README, CLAUDE, marketplace). See [COLLECTION_SPEC.md](../../COLLECTION_SPEC.md) **Provenance banners** (CI does not yet assert this text; fix when reviewing fragments). + - **Thin `deploy_and_use` (manual review)** — if the pack has **`mcps.json`** MCP servers, **`deploy_and_use`** (inline or **`#deploy_and_use.md`**) should meet [COLLECTION_SPEC.md](../../COLLECTION_SPEC.md) **install + env + MCP** (prerequisites, **`export`** for each **`${VAR}`** name, Lola **`path:`**, MCP notes, optional Claude/Cursor install). CI may not fail; fix via **create-collection** when reviewing PRs. + +3. **AI semantic alignment review (required)** + - Treat scripts as **structural guards only**; they do not fully verify semantic alignment. + - Compare each pack's catalog metadata and referenced fragments against golden sources: + - `skills/*/SKILL.md` (names, descriptions, scope, orchestration intent) + - `README.md` (installation, prerequisites, env variables, usage caveats) + - `CLAUDE.md` (persona, routing, global rules, MCP posture) + - `marketplace/rh-agentic-collection.yml` (module `path`, module name/description/tags) + - Fail review if any of these drift conditions are found: + - Installation steps differ in substance (for example Lola module IDs/paths mismatch) + - Required env vars in `mcps.json` are missing or inconsistent in `deploy_and_use` + - Skill inventory/routing intent in catalog contradicts `skills/` + `CLAUDE.md` + - Fragment prose overstates/understates capabilities versus README/skills + - Remediate via create-collection workflow and then regenerate JSON mirror. + +4. **Re-validate** — `make validate-collection-compliance`. + +## Dependencies + +- create-collection skill (sibling under `.cursor/skills/`) + +## Common Issues + +- **`skills_decision_guide` with no skills** — guide must be `[]` if the pack has no `skills/` tree. +- **Orchestration miscount** — move skills that delegate end-to-end flows to `orchestration_skills` per COLLECTION_SPEC judgment rules. +- **Install drift** — `README.md` and `.catalog/deploy_and_use(.md)` disagree on Lola commands/module IDs. +- **Env drift** — `${VAR}` names in `mcps.json` are not fully represented in `deploy_and_use`. + +## Example usage + +```bash +make validate-collection-compliance +uv run python scripts/catalog_yaml_to_json.py --pack rh-developer +make validate-collection-compliance +``` diff --git a/.claude/skills/create-collection/SKILL.md b/.claude/skills/create-collection/SKILL.md new file mode 100644 index 00000000..c832ec81 --- /dev/null +++ b/.claude/skills/create-collection/SKILL.md @@ -0,0 +1,85 @@ +--- +name: create-collection +description: | + Author or refresh `/.catalog/collection.yaml` and related `.catalog/` artifacts from golden sources (SKILL.md, README, CLAUDE.md, Lola marketplace). Use when: + - Adding a new pack or refreshing the collection catalog for GitHub Pages / tooling + - Aligning catalog narrative, sample workflows, and decision guide with skills on disk + - Preparing a PR after changing skills or marketplace metadata + + Outputs only under `/.catalog/` (never overwrite README, SKILL, CLAUDE, or marketplace YAML). +model: inherit +color: blue +allowed-tools: Read Glob Grep Bash +--- + +# Create collection catalog + +**Audience:** Maintainers and assistants updating per-pack `.catalog/` data. + +**Goal:** Produce a coherent `collection.yaml` that passes `make validate-collection-compliance`, using human judgment for synthesis—not a blind dump of frontmatter. + +## Prerequisites + +- Repository root as cwd. +- Read [COLLECTION_SPEC.md](../../COLLECTION_SPEC.md) and [catalog/schema.yaml](../../catalog/schema.yaml). +- Optional: run `uv run python scripts/scaffold_catalog.py ` for a stdout draft roster. + +## When to Use + +- New marketplace module or new pack directory needs `.catalog/`. +- Skills were added/removed/renamed and roster parity must match disk. +- Marketplace `description` / `version` changed and catalog should reflect it (still edit marketplace in git separately). + +## Workflow + +1. **Resolve pack** — directory name must appear in `union(marketplace/modules[].path, docs/plugins.json keys)` and exist on disk. + +2. **Read sources in order** (precedence): + - `skills/*/SKILL.md` (frontmatter + body for summaries and orchestration hints) + - `/README.md` + - `/CLAUDE.md` (intent routing → `skills_decision_guide` ideas) + - Matching row in `marketplace/rh-agentic-collection.yml` (`path` == pack) + +3. **Classify skills** — place each skill in `contents.skills` or `contents.orchestration_skills` using maintainer judgment. Optional hint: `metadata.collection.role: orchestration` in `SKILL.md` frontmatter. Names in YAML **must** match the `skills//` directory name. + +4. **Write `/.catalog/collection.yaml`** — start with the standard **# banner** (see COLLECTION_SPEC). Include every field required by [catalog/schema.yaml](../../catalog/schema.yaml). Keep inline strings under **500 Unicode code points** for monitored fields (`summary`, `documentation_section`, `mcp_section`, `security_model`, and inline **`deploy_and_use`**); otherwise move prose to a sibling **`.md`** and reference with **`#filename.md`** or **`deploy_and_use: #install.md`** (see COLLECTION_SPEC). + + **`deploy_and_use` / install prose:** Follow [COLLECTION_SPEC.md](../../COLLECTION_SPEC.md) **`deploy_and_use` content (install + env + MCP)**. If **`mcps.json`** defines MCP servers, document prerequisites, **`export`** lines for **every `${VAR}`** name used there, Lola + marketplace **`path:`**, optional Claude/Cursor install when those marketplaces are listed, and an MCP configuration subsection. Prefer **`deploy_and_use: '#deploy_and_use.md'`** plus **`deploy_and_use.md`** structured like **`rh-sre/.catalog/deploy_and_use.md`** (see **`rh-virt/.catalog/deploy_and_use.md`** for a kubeconfig-focused variant). + + **YAML multiline style (`|` literal blocks):** For `contents.description`, every **`summary_markdown`** (regular and orchestration skills), and every **`sample_workflows[].workflow`**, use a **literal block scalar** (`field: |`) instead of a single-quoted string that continues across many YAML lines with spacer blanks. Indent each body line one level deeper than the key line. Inside the block, keep **consecutive lines without empty lines** between the intro, `**Use when:**`, list items, and `**What it does:**` (and similar headings) unless you intentionally want extra paragraph breaks in rendered markdown—reference **`rh-sre`** and **`rh-developer`** `.catalog/collection.yaml` for the house style. Prose with apostrophes (e.g. *What's*) stays readable in `|` without `''` escaping. + +5. **Mirror JSON** — from repo root: `uv run python scripts/catalog_yaml_to_json.py --pack ` (or `make catalog-mirror-json`). + +6. **Self-review checklist** + - Every on-disk `skills//SKILL.md` appears exactly once in `skills` ∪ `orchestration_skills` (orchestration-only skills such as `/remediation` still live under `skills//`; list them **only** under `contents.orchestration_skills` when they orchestrate others). + - No `TODO:` / `TBD` in `sample_workflows.workflow`; each workflow includes `User:` and `-` bullets. + - `skills_decision_guide` empty if the pack has **no** skills; otherwise each `skill_to_use` matches a skill dir. + - `resources[].url` set; `embedded_doc` only if that path exists under the pack. + - **Install / deploy (`deploy_and_use`):** **inline** (≤ **500** code points) *or* one-line **`#deploy_and_use.md`** ref (see [COLLECTION_SPEC.md](../../COLLECTION_SPEC.md) **install + env + MCP**). If **`mcps.json`** has MCP servers: fragment (or inline) must include prerequisites, **`export`** examples for each **`${VAR}`** name from **`mcps.json`**, Lola/marketplace **`path:`**, and MCP configuration notes; add Claude Code / Cursor install when **`marketplaces`** lists them. Fragments use the HTML provenance banner. Use **`mcps.json`**, not `.mcp.json`. + - **Other long blocks:** use **`documentation_section`**, **`mcp_section`**, and **`security_model`** with either inline markdown (≤ **500** code points) or a one-line **`#fragment.md`** ref on that same key (same pattern as **`deploy_and_use`**). + - **Publication-style metadata (when useful):** `support_level`, `author`, `homepage`, `keywords`, `legal_resources` (URLs only). + - **`version` / listing fields:** Align `version` and core listing copy with the matching **`marketplace/rh-agentic-collection.yml`** row (`path` == pack); do not bump marketplace YAML from the catalog workflow. + - **Multiline fields:** `contents.description`, all **`summary_markdown`**, and all **`sample_workflows[].workflow`** use **`|`** block scalars (not long single-quoted multiline); content lines are compact unless extra blank lines are deliberate for markdown. + +7. **Validate** — `make validate-collection-compliance` before commit. + +## Dependencies + +- `make validate-collection-compliance` +- `uv run python scripts/scaffold_catalog.py ` (optional) + +## Common Issues + +- **CI: `collection.json` drift** — regenerate with `make catalog-mirror-json`. +- **Roster errors** — YAML `name` must equal the skill folder name, not a display alias. +- **Empty support pack** — if there are no `skills/`, use empty `skills`, `orchestration_skills`, and `skills_decision_guide: []`. +- **Unreadable multiline YAML** — replace spanning `'`…`'` blocks with **`field: |`** and indented lines; see step 4 **YAML multiline style**. +- **Thin `deploy_and_use`** — pack has **`mcps.json`** but catalog only says “see README”; add **Environment setup** (`export` for each **`${VAR}`**) and **MCP configuration** per COLLECTION_SPEC (use **`#deploy_and_use.md`** like **rh-sre** / **rh-virt**). + +## Example usage + +```bash +uv run python scripts/scaffold_catalog.py rh-sre +uv run python scripts/catalog_yaml_to_json.py --pack rh-sre +make validate-collection-compliance +``` diff --git a/.github/workflows/deploy-pages.yml b/.github/workflows/deploy-pages.yml index caf8041a..fac26579 100644 --- a/.github/workflows/deploy-pages.yml +++ b/.github/workflows/deploy-pages.yml @@ -10,6 +10,11 @@ on: - 'ocp-admin/**' - 'rh-support-engineer/**' - 'rh-virt/**' + - 'rh-automation/**' + - 'rh-ai-engineer/**' + - 'marketplace/**' + - 'catalog/**' + - '**/.catalog/**' - 'scripts/**' - 'docs/**' - '.github/workflows/deploy-pages.yml' diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 00000000..d37081ac --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,34 @@ +# See README.md "Git hooks (pre-commit)" for install. Aligns with CI: make validate + changed skill design. +default_install_hook_types: [pre-commit] + +repos: + - repo: https://github.com/gitleaks/gitleaks + rev: v8.18.4 + hooks: + # Uses gitleaks on PATH (install: brew install gitleaks, or run scripts/install-hooks.sh) + - id: gitleaks-system + + - repo: local + hooks: + - id: make-validate + name: make validate (structure + collection compliance) + entry: make validate + language: system + pass_filenames: false + files: | + (?x)^( + catalog/.*| + marketplace/.*| + scripts/(validate_structure|validate_collection_compliance|validate_collection_schema|collection_validate_lib|pack_registry|catalog_yaml_to_json)\.py| + (rh-[-a-z0-9]+|ocp-admin)/\.catalog/.*| + (rh-[-a-z0-9]+|ocp-admin)/skills/[^/]+/SKILL\.md| + (rh-[-a-z0-9]+|ocp-admin)/mcps\.json| + (rh-[-a-z0-9]+|ocp-admin)/CLAUDE\.md + ) + + - id: validate-skill-design-changed + name: make validate-skill-design-changed (Tier-2 skill design) + entry: make validate-skill-design-changed + language: system + pass_filenames: false + files: ^(rh-[-a-z0-9]+|ocp-admin)/skills/[^/]+/SKILL\.md$ diff --git a/CLAUDE.md b/CLAUDE.md index f0ff01a3..9bf79141 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -27,6 +27,7 @@ Each pack follows this structure: ├── CLAUDE.md # Claude Code instruction routing (persona, skills, rules) ├── README.md # Pack description, persona, target marketplaces ├── mcps.json # MCP server configurations (uses env vars for credentials) +├── .catalog/ # collection.yaml + collection.json (COLLECTION_SPEC.md, catalog/schema.yaml) ├── skills/ # Specialized task executors (including orchestration skills) │ └── / │ └── SKILL.md # Skill definition with YAML frontmatter @@ -51,6 +52,15 @@ Optional (not required for Lola): `.claude-plugin/plugin.json` — Claude Code p **Key Pattern**: Skills encapsulate tools; orchestration skills invoke other skills. Never call MCP tools directly - always go through skills. For end-to-end CVE remediation, use the `/remediation` skill which orchestrates 6 specialized skills. +### Repository catalog skills (`.catalog/`) + +Packs listed in `union(marketplace/rh-agentic-collection.yml modules[].path, docs/plugins.json keys)` maintain **`/.catalog/collection.yaml`** (and a deterministic **`collection.json`** mirror). Golden sources remain `SKILL.md`, `README.md`, `CLAUDE.md`, and marketplace YAML—**never** generated from catalog back into those files. + +- **`create-collection`** (`.claude/skills/create-collection/`) — workflow to author or refresh catalog YAML under `.catalog/`. +- **`collection-compliance`** (`.claude/skills/collection-compliance/`) — interpret `make validate-collection-compliance` failures and fix drift. + +Validation: `make validate` runs pack structure checks plus **collection compliance**. Human rules (inline vs fragment paths, optional `#` on paths): [COLLECTION_SPEC.md](COLLECTION_SPEC.md). Machine schema: [catalog/schema.yaml](catalog/schema.yaml). Pack list helper: [`scripts/pack_registry.py`](scripts/pack_registry.py). + ## Skill and Agent Requirements **CRITICAL:** EVERY SKILL and AGENT must comply with: diff --git a/COLLECTION_SPEC.md b/COLLECTION_SPEC.md new file mode 100644 index 00000000..1b2f0787 --- /dev/null +++ b/COLLECTION_SPEC.md @@ -0,0 +1,71 @@ +# Collection catalog specification + +This repository uses a **pack-local collection catalog**: curated metadata and summaries live under **`/.catalog/`** (YAML as the source of record, JSON as a deterministic mirror for consumers that prefer it). **Golden sources** are pack `SKILL.md` files, `README.md`, `CLAUDE.md`, and [`marketplace/rh-agentic-collection.yml`](marketplace/rh-agentic-collection.yml). Catalog files **describe** the collection for tooling and documentation; they are **authored** primarily via the [**create-collection**](.claude/skills/create-collection/SKILL.md) skill (assistant + maintainer + PR review) and must not overwrite READMEs or marketplace YAML. + +**Machine validation:** [`catalog/schema.yaml`](catalog/schema.yaml) (JSON Schema expressed in YAML) and [`scripts/validate_collection_compliance.py`](scripts/validate_collection_compliance.py). These checks are primarily structural and cannot fully evaluate semantic parity with golden-source docs. **Required review gate:** run an AI semantic alignment review (via [`.claude/skills/collection-compliance/SKILL.md`](.claude/skills/collection-compliance/SKILL.md)) to confirm catalog metadata/fragments remain aligned with `SKILL.md`, `README.md`, `CLAUDE.md`, and marketplace module metadata. **Pack list:** union of Lola marketplace `modules[].path` and keys of [`docs/plugins.json`](docs/plugins.json), limited to directories that exist on disk — see [`scripts/pack_registry.py`](scripts/pack_registry.py). + +## Layout + +| Path | Purpose | +|------|---------| +| `/.catalog/collection.yaml` | Canonical catalog document (YAML) | +| `/.catalog/collection.json` | Deterministic JSON mirror of YAML (regenerate with `make catalog-mirror-json`; CI fails on drift) | +| `/.catalog/*.md` | Optional prose fragments, **siblings of** `collection.yaml`. Reference them with **`#.md`** (quoted in YAML) **on the same logical field** as inline text would use—for example `documentation_section: '#docs.md'` or `deploy_and_use: '#install.md'`. If inline text exceeds **`CATALOG_INLINE_CHAR_LIMIT`** (500 Unicode code points; see `scripts/collection_validate_lib.py`), move prose into a fragment and set that field to the ref. | + +**Multiline YAML in `collection.yaml`:** For `contents.description`, each **`summary_markdown`**, and each **`sample_workflows[].workflow`**, authors should use YAML **literal block scalars** (`field: |`) with indented lines—see step 4 of the [**create-collection**](.claude/skills/create-collection/SKILL.md) skill (reference **`rh-sre`** / **`rh-developer`** `.catalog/collection.yaml`). CI does not assert this style; it is a maintainability convention. + +### External references (`#…md` on the same field) + +- **Path rule:** refs are **siblings of** `collection.yaml` inside **`/.catalog/`**. Write **`#install.md`**, not `#.catalog/install.md` (omit the `.catalog/` segment in the string). +- **One field, two shapes:** for **`deploy_and_use`**, **`documentation_section`**, **`mcp_section`**, and **`security_model`**, the value is either **inline** markdown or a **one-line** fragment ref **`#.md`**. +- **Monitored inline length:** for **`summary`**, **`documentation_section`**, **`mcp_section`**, and **`security_model`**, if the value is **inline** (not a `#…md` ref) and longer than **500 Unicode code points**, move the prose to a fragment file and set the **same field** to **`#.md`**. For **`deploy_and_use`**, the same limit applies when it is **inline** markdown (not a one-line ref). +- **`deploy_and_use` (two flavors):** (1) **Inline** — markdown in YAML, ≤ **500** code points unless you externalize. (2) **File ref** — one line only: **`#.md`** (same directory as `collection.yaml`). CI resolves the file under **`/.catalog/`**. +- **Fragment ref values:** must start with **`#`** (e.g. `#documentation_section.md`). Legacy `#.catalog/…` is accepted and normalized. + +### `deploy_and_use` content (install + env + MCP) + +Consumers read **`deploy_and_use`** (resolved from inline YAML or from **`#deploy_and_use.md`**) for marketplace install steps and operator setup. **CI does not yet cross-check `mcps.json` or README install parity;** reviewers enforce this section with the [**create-collection**](.claude/skills/create-collection/SKILL.md) and [**collection-compliance**](.claude/skills/collection-compliance/SKILL.md) workflows. + +**When `/mcps.json` defines one or more MCP servers**, the prose behind **`deploy_and_use`** (inline or fragment) **must** cover, in substance: + +1. **Prerequisites** — Cluster/product access, CLIs, operators, or accounts needed before install, aligned with **`README.md`** / **`CLAUDE.md`**. +2. **Environment setup** — Example **`export VAR=...`** (or host env equivalent) for **every** environment variable **name** referenced in **`mcps.json`** via **`${VAR}`** in `command`, `args`, or `env`. Variable **names** must match **`mcps.json`** exactly. State that secrets are never committed and must not be echoed in assistant output. +3. **MCP configuration** — Server definitions live in **`mcps.json`** at the pack root; use **`${...}`** placeholders only; briefly note isolation/network/credentials posture if it affects the user (see existing pack fragments). +4. **Installation** — At minimum **Lola** (`lola install -f `) and the module **`path:`** in **`marketplace/rh-agentic-collection.yml`**. If **`marketplaces`** in the catalog includes **Claude Code** or **Cursor**, include install notes for those hosts (copy the pattern from **`rh-sre/.catalog/deploy_and_use.md`**). + +**Layout recommendation:** Prefer **`deploy_and_use: '#deploy_and_use.md'`** and a sibling **`deploy_and_use.md`** so `collection.yaml` stays short. Use the **same section order** as **`rh-sre/.catalog/deploy_and_use.md`**: Prerequisites → Environment setup → Installation (Lola, then Claude Code / Cursor as applicable) → MCP configuration. For a kubeconfig-only MCP story, see **`rh-virt/.catalog/deploy_and_use.md`**. + +**Packs with no MCP servers** (or a trivial single-token env story): a compact **`deploy_and_use: |`** under **500** Unicode code points is acceptable if it still states Lola/repo install and defers detail to **`README.md`** where needed. + +**Plugin / install IDs:** default `id` equals the pack directory name. Overrides: **`rh-virt`** → `openshift-virtualization`; **`ocp-admin`** → `openshift-administration`. + +## Source precedence (pack-local) + +When multiple sources could supply the same logical field: + +1. **`skills/*/SKILL.md`** (per-skill `name`, `description`, body for `summary_markdown` hints) +2. **`/README.md`** +3. **`/CLAUDE.md`** (intent routing for decision-guide hints, personas) + +**Lola marketplace:** the module whose `path` equals `` supplies `version`, module `name`, module `description`, and `tags` for listing-oriented fields. **Never** write back to marketplace YAML from automation or the create-collection workflow. + +## Provenance banners + +| Artifact | Banner | +|----------|--------| +| `collection.yaml` | Leading `#` comment block: must mention **create-collection** workflow and **golden sources** (SKILL, README, CLAUDE, marketplace). | +| `.catalog/*.md` fragments | Leading HTML `` with the same intent. | +| `collection.json` | **No** embedded banner; **CI** regenerates from YAML and fails if the committed file differs. | + +## Orchestration vs regular skills + +**Primary:** maintainer / assistant judgment while following **create-collection**. **Optional:** `metadata.collection.role: orchestration` in `SKILL.md` frontmatter for clearer compliance checks — not required on every skill. + +## Completeness and CI + +All **required** schema fields must be present on merge to `main` (no empty placeholders, no `TODO:` / `TBD` in `sample_workflows.workflow`). Author field values so they stay aligned with **`CLAUDE.md`**, **`mcps.json`**, and **`README.md`** where those sources define behavior; fragment refs follow [External references](#external-references-md-on-the-same-field). CI runs **`make validate`** (includes structure + **collection compliance**). + +## Related + +- [`SKILL_DESIGN_PRINCIPLES.md`](SKILL_DESIGN_PRINCIPLES.md) — skill content (Tier 2) +- [`.claude/skills/collection-compliance/SKILL.md`](.claude/skills/collection-compliance/SKILL.md) — validation workflow diff --git a/Makefile b/Makefile index 5c5092ec..3cd91f1b 100644 --- a/Makefile +++ b/Makefile @@ -1,11 +1,14 @@ -.PHONY: help install validate validate-skill-design validate-skill-design-changed generate serve clean test test-full check-uv +.PHONY: help install validate validate-collection-schema validate-collection-compliance catalog-mirror-json validate-skill-design validate-skill-design-changed generate serve clean test test-full check-uv help: @echo "agentic-collections Documentation Generator" @echo "" @echo "Available targets:" @echo " install - Install Python dependencies (requires uv)" - @echo " validate - Validate pack structure (mcps.json, CLAUDE.md, frontmatter; plugin.json if present)" + @echo " validate - Pack structure + collection compliance (.catalog/)" + @echo " validate-collection-schema - Schema + roster + banners (subset of compliance)" + @echo " validate-collection-compliance - Full .catalog compliance (includes collection.json drift)" + @echo " catalog-mirror-json - Regenerate all .catalog/collection.json from YAML" @echo " validate-skill-design - Validate all skills (use PACK=rh-sre for a specific pack)" @echo " validate-skill-design-changed - Validate only changed skills (staged + unstaged, for local dev)" @echo " generate - Generate docs/data.json" @@ -31,14 +34,25 @@ check-uv: install: check-uv @echo "Installing Python dependencies with uv..." - @uv sync - @echo "Dependencies installed in isolated environment!" + @uv sync --group dev + @echo "Dependencies installed in isolated environment (includes dev: pre-commit for git hooks)!" validate: check-uv @echo "Validating agentic collection structure..." @uv run python scripts/validate_structure.py + @echo "Validating collection compliance (.catalog/)..." + @uv run python scripts/validate_collection_compliance.py @echo "✓ Validation passed!" +validate-collection-schema: check-uv + @uv run python scripts/validate_collection_schema.py + +validate-collection-compliance: check-uv + @uv run python scripts/validate_collection_compliance.py + +catalog-mirror-json: check-uv + @uv run python scripts/catalog_yaml_to_json.py --all + validate-skill-design: check-uv @uv run python scripts/validate_skill_design.py $(if $(PACK),$(PACK)) diff --git a/README.md b/README.md index 8eb2b919..6232d777 100644 --- a/README.md +++ b/README.md @@ -170,9 +170,14 @@ Generate and view documentation locally: # Install dependencies (first time only) make install -# Validate pack structure (mcps.json, CLAUDE.md, frontmatter; plugin.json if present) +# Validate pack structure + collection compliance (COLLECTION_SPEC.md, catalog/schema.yaml) make validate +# Optional: collection-only targets +# make validate-collection-schema +# make validate-collection-compliance +# make catalog-mirror-json # refresh .catalog/collection.json from YAML + # Validate skills against Design Principles (SKILL_DESIGN_PRINCIPLES.md) # Validate only changed skills (staged + unstaged) - recommended for local dev: make validate-skill-design-changed @@ -223,15 +228,20 @@ uv run python scripts/validate_skill_design.py --warnings-as-errors ## Security -This repository uses [gitleaks](https://github.com/gitleaks/gitleaks) to prevent accidental commits of sensitive data. +This repository uses [gitleaks](https://github.com/gitleaks/gitleaks) and the [pre-commit](https://pre-commit.com/) framework to block accidental secrets and to run scoped validation before commits. ### Quick Start ```bash -# Install gitleaks and pre-commit hook (one-time setup) +# One-time: Python deps + dev tools (includes pre-commit), then install the git hook +make install scripts/install-hooks.sh ``` +`scripts/install-hooks.sh` runs `uv sync` / `uv sync --group dev`, ensures `gitleaks` is available when possible, then `uv run pre-commit install`. It backs up a **non–pre-commit** `.git/hooks/pre-commit` (for example an old gitleaks-only hook) before replacing it. + +On commit, hooks defined in `.pre-commit-config.yaml` run: **gitleaks**, **`make validate`** when catalog/roster-related paths change, and **`make validate-skill-design-changed`** when pack `skills/*/SKILL.md` files change. CI still enforces the full checks in [`.github/workflows/compliance-check.yml`](.github/workflows/compliance-check.yml) (`make validate` and related jobs). + ### What's Protected - **API keys**: OpenAI, GitHub, AWS, Google Cloud diff --git a/SKILL_DESIGN_PRINCIPLES.md b/SKILL_DESIGN_PRINCIPLES.md index 7c5888df..6e951351 100644 --- a/SKILL_DESIGN_PRINCIPLES.md +++ b/SKILL_DESIGN_PRINCIPLES.md @@ -6,6 +6,8 @@ Repository-specific design principles for creating skills and agents in agentic **Distribution (Lola):** Packs are installed with the [Lola](https://github.com/RedHatProductSecurity/lola) package manager from the registry in [`marketplace/rh-agentic-collection.yml`](marketplace/rh-agentic-collection.yml). Layout and install flow are documented in [CLAUDE.md](CLAUDE.md) and the root [README.md](README.md). +**Collection catalog (pack-local):** Each pack may include **`/.catalog/collection.yaml`** and a **`collection.json`** mirror so tooling and docs can show a structured view of the collection. Authors follow [COLLECTION_SPEC.md](COLLECTION_SPEC.md) and the **create-collection** skill; field constraints are defined in **[`catalog/schema.yaml`](catalog/schema.yaml)** (JSON Schema in YAML). Pack **`SKILL.md`**, **`README.md`**, **`CLAUDE.md`**, and **`marketplace/rh-agentic-collection.yml`** stay the **sources of truth**; the catalog aggregates and summarizes them and does **not** replace or regenerate README or marketplace content. + **MCP configuration:** Use `/mcps.json` for MCP server definitions (never hardcode secrets; use `${VAR}` references). The deprecated filename `.mcp.json` is not used in this repository. **Optional Claude Code manifest:** `.claude-plugin/plugin.json` is optional—only needed for Claude Code–specific plugin publishing. It is not required for Lola installation or for Tier 2 skill content compliance. diff --git a/catalog/schema.yaml b/catalog/schema.yaml new file mode 100644 index 00000000..f86c9cdf --- /dev/null +++ b/catalog/schema.yaml @@ -0,0 +1,200 @@ +# Pack-local collection catalog — JSON Schema (Draft 2020-12), YAML encoding. +# Field semantics and authoring: COLLECTION_SPEC.md. Instance files: /.catalog/collection.yaml +# Fragments: sibling *.md of collection.yaml; reference as #name.md (quote in YAML). Inline monitored fields +# >500 code points must use a fragment; see COLLECTION_SPEC.md. Resolved by scripts/collection_validate_lib.py. + +$schema: https://json-schema.org/draft/2020-12/schema +$id: https://github.com/RHEcosystemAppEng/agentic-collections/catalog/schema.yaml +title: Agentic collection catalog +type: object +additionalProperties: true +required: +- id +- name +- provider +- version +- categories +- personas +- marketplaces +- description +- summary +- contents +- deploy_and_use +- mcp_section +- sample_workflows +- resources +properties: + id: + type: string + minLength: 1 + name: + type: string + minLength: 1 + provider: + type: string + minLength: 1 + version: + type: string + pattern: ^[0-9]+\.[0-9]+\.[0-9]+ + categories: + type: array + minItems: 1 + items: + type: string + minLength: 1 + personas: + type: array + minItems: 1 + items: + type: string + minLength: 1 + marketplaces: + type: array + minItems: 1 + items: + type: string + minLength: 1 + support_level: + type: string + description: + type: string + minLength: 1 + summary: + type: string + minLength: 1 + contents: + type: object + additionalProperties: true + required: + - description + - skills + - orchestration_skills + - skills_decision_guide + properties: + description: + type: string + minLength: 1 + skills: + type: array + items: + $ref: '#/$defs/catalogSkill' + orchestration_skills: + type: array + items: + $ref: '#/$defs/catalogSkill' + skills_decision_guide: + type: array + items: + $ref: '#/$defs/decisionGuideRow' + deploy_and_use: + type: string + minLength: 1 + description: > + Inline markdown (≤500 code points unless externalized) or a one-line fragment ref + '#filename.md' sibling under .catalog/. + documentation_section: + type: string + minLength: 1 + description: > + How documentation is organized; inline markdown or one-line '#fragment.md' under .catalog/ + (same convention as deploy_and_use). + mcp_section: + type: string + minLength: 1 + description: > + MCP usage summary; inline or '#fragment.md' under .catalog/. + security_model: + type: string + minLength: 1 + description: > + Security posture narrative; inline or '#fragment.md' under .catalog/. + sample_workflows: + type: array + minItems: 1 + items: + $ref: '#/$defs/sampleWorkflow' + resources: + type: array + minItems: 1 + items: + $ref: '#/$defs/resource' + legal_resources: + type: object + author: + type: object + homepage: + type: string + repository: + type: string + license: + type: string + keywords: + type: array + items: + type: string +$defs: + catalogSkill: + type: object + required: + - name + - description + - summary_markdown + additionalProperties: true + properties: + name: + type: string + minLength: 1 + description: + type: string + minLength: 1 + summary_markdown: + type: string + minLength: 1 + decisionGuideRow: + type: object + required: + - user_request + - skill_to_use + - reason + additionalProperties: false + properties: + user_request: + type: string + minLength: 1 + skill_to_use: + type: string + minLength: 1 + reason: + type: string + minLength: 1 + sampleWorkflow: + type: object + required: + - name + - workflow + additionalProperties: false + properties: + name: + type: string + minLength: 1 + workflow: + type: string + minLength: 10 + resource: + type: object + required: + - title + - description + - url + additionalProperties: true + properties: + title: + type: string + minLength: 1 + description: + type: string + url: + type: string + minLength: 1 + embedded_doc: + type: string diff --git a/docs/README.md b/docs/README.md index aff6265b..7a7a00f3 100644 --- a/docs/README.md +++ b/docs/README.md @@ -12,6 +12,8 @@ This directory contains the generated GitHub Pages site for agentic-collections. ## Local Development +From the repository root, install git hooks once (`make install` then `scripts/install-hooks.sh`) so commits run [pre-commit](https://pre-commit.com/) (gitleaks + scoped `make validate` / skill design checks); see the main [README.md](../README.md#security). + Run locally: ```bash python -m http.server 8000 @@ -31,10 +33,11 @@ This script parses all agentic collections and MCP configurations. ## Manual Updates To manually update the site: -1. Modify pack configurations (`mcps.json`, skills, agents; optional `.claude-plugin/plugin.json`) -2. Run `make generate` from the root directory -3. Commit the updated `docs/data.json` -4. Push to trigger GitHub Pages deployment +1. Modify pack configurations (`mcps.json`, skills, agents; optional `.claude-plugin/plugin.json`) and per-pack **`.catalog/collection.yaml`** when catalog metadata changes (see [COLLECTION_SPEC.md](../COLLECTION_SPEC.md) and [catalog/schema.yaml](../catalog/schema.yaml); use the **create-collection** / **collection-compliance** repo skills). +2. If you edit `collection.yaml`, refresh mirrors: `make catalog-mirror-json` from the repository root. +3. Run `make generate` from the root directory (runs `make validate` first when using `make test`). +4. Commit the updated `docs/data.json` and any `.catalog/` files. +5. Push to trigger GitHub Pages deployment. ## Security diff --git a/ocp-admin/.catalog/collection.json b/ocp-admin/.catalog/collection.json new file mode 100644 index 00000000..b44d9577 --- /dev/null +++ b/ocp-admin/.catalog/collection.json @@ -0,0 +1,106 @@ +{ + "author": { + "email": "eco-engineering@redhat.com", + "name": "Red Hat Ecosystem Engineering" + }, + "categories": [ + "Red Hat", + "Openshift", + "Administration", + "Management" + ], + "contents": { + "description": "The pack provides three skills for cluster lifecycle and fleet visibility on OpenShift, using Assisted Installer and OCM APIs\nwhere applicable and read-only cluster APIs for consolidated reports.\n", + "orchestration_skills": [], + "skills": [ + { + "description": "End-to-end OpenShift cluster creation using Red Hat Assisted Installer (SNO and HA; bare metal, vSphere, OCI, Nutanix).", + "name": "cluster-creator", + "summary_markdown": "Create and install OpenShift clusters through Assisted Installer with validation, host networking, and progress monitoring.\n**Use when:**\n- \"Create a new OpenShift cluster\"\n- \"Install OpenShift on my servers\"\n- \"Set up a single-node cluster\"\n**What it does:**\n- Drives Assisted Installer flows with explicit approval for VIPs, host roles, and install triggers.\n- Surfaces installation events and validation errors until the cluster reaches ready state.\n" + }, + { + "description": "List and inspect OpenShift clusters across self-managed (OCP, SNO) and managed service (ROSA, ARO, OSD) deployments.", + "name": "cluster-inventory", + "summary_markdown": "List clusters, versions, platforms, and status from OCM and Assisted Installer contexts using a single offline token workflow.\n**Use when:**\n- \"List all clusters\"\n- \"Show cluster status\"\n- \"What clusters are available?\"\n**What it does:**\n- Returns identifiers, versions, platforms, and creation metadata for fleet visibility.\n- Separates self-managed versus managed-service clusters for the right API path.\n" + }, + { + "description": "Consolidated health report across kubeconfig contexts, skipping non-OpenShift contexts by default.", + "name": "cluster-report", + "summary_markdown": "Aggregate node, namespace, and workload signals across contexts that resolve to real OpenShift clusters.\n**Use when:**\n- \"Health report across clusters\"\n- \"Fleet summary from kubeconfig\"\n- \"Compare resource usage between contexts\"\n**What it does:**\n- Verifies each context is OpenShift before collecting metrics to avoid kube API errors.\n- Summarizes capacity, GPU presence, and pod health for operations review.\n" + } + ], + "skills_decision_guide": [ + { + "reason": "Provisions SNO or HA clusters and monitors install through completion.", + "skill_to_use": "cluster-creator", + "user_request": "\"Create cluster\" or \"install OpenShift with Assisted Installer\"" + }, + { + "reason": "Inventory across managed and self-managed targets with consistent fields.", + "skill_to_use": "cluster-inventory", + "user_request": "\"List clusters\" or \"cluster status in OCM/ROSA\"" + }, + { + "reason": "Read-only aggregation after OpenShift context verification.", + "skill_to_use": "cluster-report", + "user_request": "\"Fleet health\" or \"multi-cluster report from kubeconfig\"" + } + ] + }, + "deploy_and_use": "#deploy_and_use.md", + "description": "Automation capabilities for OpenShift Container Platform cluster management, workload orchestration, security policies, and operational tasks.", + "homepage": "https://github.com/RHEcosystemAppEng/agentic-collections", + "id": "openshift-administration", + "keywords": [ + "openshift", + "assisted-installer", + "ocm", + "fleet", + "kubeconfig" + ], + "legal_resources": { + "license_agreement_url": "https://www.redhat.com/en/about/agreements", + "privacy_policy_url": "https://www.redhat.com/en/about/privacy-policy" + }, + "license": "Apache-2.0", + "marketplaces": [ + "Claude Code", + "Cursor" + ], + "mcp_section": "#mcp_section.md", + "name": "Red Hat OpenShift Administration Agentic Skills Collection", + "personas": [ + "OpenShift Administrator" + ], + "provider": "Red Hat", + "repository": "https://github.com/RHEcosystemAppEng/agentic-collections", + "resources": [ + { + "description": "Platform guides for administrators installing and operating OpenShift.", + "title": "OpenShift documentation", + "url": "https://docs.redhat.com/en/documentation/openshift_container_platform/" + }, + { + "description": "Source repository for these packs, skills, and catalog metadata.", + "title": "agentic-collections repository", + "url": "https://github.com/RHEcosystemAppEng/agentic-collections" + } + ], + "sample_workflows": [ + { + "name": "Assisted install then verify", + "workflow": "User: \"Create an HA cluster on bare metal and tell me when it is ready\"\n- `/cluster-creator` walks prerequisites, manifests, and installation monitoring with approvals at critical steps\n- `/cluster-inventory` confirms version and state once the API shows the new cluster\n" + }, + { + "name": "Fleet visibility", + "workflow": "User: \"List everything in my Red Hat account and flag stale check-ins\"\n- `/cluster-inventory` returns self-managed and managed clusters with metadata for triage\n" + }, + { + "name": "Multi-cluster health", + "workflow": "User: \"Summarize node and pod health for every OpenShift context in my kubeconfig\"\n- `/cluster-report` skips non-OpenShift contexts and aggregates signals for operators\n" + } + ], + "summary": "The ocp-admin collection covers Assisted Installer cluster creation, multi-cluster discovery across self-managed and managed\nOpenShift, and kubeconfig-backed fleet health reporting. Use CLAUDE.md intent routing to pick `/cluster-creator`,\n`/cluster-inventory`, or `/cluster-report`.\n", + "support_level": "Unknown", + "version": "0.1.0" +} diff --git a/ocp-admin/.catalog/collection.yaml b/ocp-admin/.catalog/collection.yaml new file mode 100644 index 00000000..f29aa075 --- /dev/null +++ b/ocp-admin/.catalog/collection.yaml @@ -0,0 +1,112 @@ +# Catalog: maintained via create-collection workflow (assistant + maintainer + PR review). +# Golden sources: skills/*/SKILL.md, README.md, CLAUDE.md, marketplace/rh-agentic-collection.yml +# Do not edit ad hoc — follow COLLECTION_SPEC.md and the create-collection skill. + +id: openshift-administration +name: Red Hat OpenShift Administration Agentic Skills Collection +provider: Red Hat +version: 0.1.0 +categories: +- Red Hat +- Openshift +- Administration +- Management +personas: +- OpenShift Administrator +marketplaces: +- Claude Code +- Cursor +support_level: Unknown +description: Automation capabilities for OpenShift Container Platform cluster management, workload orchestration, security + policies, and operational tasks. +summary: | + The ocp-admin collection covers Assisted Installer cluster creation, multi-cluster discovery across self-managed and managed + OpenShift, and kubeconfig-backed fleet health reporting. Use CLAUDE.md intent routing to pick `/cluster-creator`, + `/cluster-inventory`, or `/cluster-report`. +contents: + description: | + The pack provides three skills for cluster lifecycle and fleet visibility on OpenShift, using Assisted Installer and OCM APIs + where applicable and read-only cluster APIs for consolidated reports. + skills: + - name: cluster-creator + description: End-to-end OpenShift cluster creation using Red Hat Assisted Installer (SNO and HA; bare metal, vSphere, OCI, Nutanix). + summary_markdown: | + Create and install OpenShift clusters through Assisted Installer with validation, host networking, and progress monitoring. + **Use when:** + - "Create a new OpenShift cluster" + - "Install OpenShift on my servers" + - "Set up a single-node cluster" + **What it does:** + - Drives Assisted Installer flows with explicit approval for VIPs, host roles, and install triggers. + - Surfaces installation events and validation errors until the cluster reaches ready state. + - name: cluster-inventory + description: List and inspect OpenShift clusters across self-managed (OCP, SNO) and managed service (ROSA, ARO, OSD) deployments. + summary_markdown: | + List clusters, versions, platforms, and status from OCM and Assisted Installer contexts using a single offline token workflow. + **Use when:** + - "List all clusters" + - "Show cluster status" + - "What clusters are available?" + **What it does:** + - Returns identifiers, versions, platforms, and creation metadata for fleet visibility. + - Separates self-managed versus managed-service clusters for the right API path. + - name: cluster-report + description: Consolidated health report across kubeconfig contexts, skipping non-OpenShift contexts by default. + summary_markdown: | + Aggregate node, namespace, and workload signals across contexts that resolve to real OpenShift clusters. + **Use when:** + - "Health report across clusters" + - "Fleet summary from kubeconfig" + - "Compare resource usage between contexts" + **What it does:** + - Verifies each context is OpenShift before collecting metrics to avoid kube API errors. + - Summarizes capacity, GPU presence, and pod health for operations review. + orchestration_skills: [] + skills_decision_guide: + - user_request: '"Create cluster" or "install OpenShift with Assisted Installer"' + skill_to_use: cluster-creator + reason: Provisions SNO or HA clusters and monitors install through completion. + - user_request: '"List clusters" or "cluster status in OCM/ROSA"' + skill_to_use: cluster-inventory + reason: Inventory across managed and self-managed targets with consistent fields. + - user_request: '"Fleet health" or "multi-cluster report from kubeconfig"' + skill_to_use: cluster-report + reason: Read-only aggregation after OpenShift context verification. +mcp_section: '#mcp_section.md' +deploy_and_use: '#deploy_and_use.md' +sample_workflows: +- name: Assisted install then verify + workflow: | + User: "Create an HA cluster on bare metal and tell me when it is ready" + - `/cluster-creator` walks prerequisites, manifests, and installation monitoring with approvals at critical steps + - `/cluster-inventory` confirms version and state once the API shows the new cluster +- name: Fleet visibility + workflow: | + User: "List everything in my Red Hat account and flag stale check-ins" + - `/cluster-inventory` returns self-managed and managed clusters with metadata for triage +- name: Multi-cluster health + workflow: | + User: "Summarize node and pod health for every OpenShift context in my kubeconfig" + - `/cluster-report` skips non-OpenShift contexts and aggregates signals for operators +resources: +- title: OpenShift documentation + url: https://docs.redhat.com/en/documentation/openshift_container_platform/ + description: Platform guides for administrators installing and operating OpenShift. +- title: agentic-collections repository + url: https://github.com/RHEcosystemAppEng/agentic-collections + description: Source repository for these packs, skills, and catalog metadata. +legal_resources: + license_agreement_url: https://www.redhat.com/en/about/agreements + privacy_policy_url: https://www.redhat.com/en/about/privacy-policy +author: + name: Red Hat Ecosystem Engineering + email: eco-engineering@redhat.com +homepage: https://github.com/RHEcosystemAppEng/agentic-collections +repository: https://github.com/RHEcosystemAppEng/agentic-collections +license: Apache-2.0 +keywords: +- openshift +- assisted-installer +- ocm +- fleet +- kubeconfig diff --git a/ocp-admin/.catalog/deploy_and_use.md b/ocp-admin/.catalog/deploy_and_use.md new file mode 100644 index 00000000..c24b6863 --- /dev/null +++ b/ocp-admin/.catalog/deploy_and_use.md @@ -0,0 +1,54 @@ + + +### Prerequisites + +- Claude Code CLI or IDE extension (if using Claude Code) +- Podman (or Docker) for the container-based MCP servers in **`mcps.json`** +- Red Hat account with access to [cloud.redhat.com](https://cloud.redhat.com) for **cluster creation** and **inventory** flows +- **Offline token** from [OpenShift offline token](https://cloud.redhat.com/openshift/token) for Assisted Installer and OCM APIs +- For **`/cluster-report`**: valid **`KUBECONFIG`** with contexts that point at real OpenShift clusters (read-only MCP mode) + +### Environment setup + +Variable **names** must match **`mcps.json`** (use **`${...}`** placeholders only in git; never commit secrets). + +**Assisted Installer + managed clusters** (`openshift-self-managed`, `openshift-ocm-managed`): + +```bash +export OFFLINE_TOKEN="your-offline-api-token" +``` + +**Multi-cluster kube report** (`openshift-administration`): + +```bash +export KUBECONFIG="/path/to/your/kubeconfig" +``` + +### Installation (Lola) + +```bash +lola install -f ocp-admin +``` + +Module path: **`ocp-admin`** in **`marketplace/rh-agentic-collection.yml`**. See the root [README.md](../../README.md) for full prerequisites and MCP setup. + +### Installation (Claude Code) + +```bash +lola install -f ocp-admin -a claude-code +``` + +### Installation (Cursor) + +```bash +lola install -f ocp-admin -a cursor +``` + +### MCP configuration + +Servers are defined in **`mcps.json`** at the pack root: Assisted Installer / OCM (`OFFLINE_TOKEN`) and read-only OpenShift API (`KUBECONFIG`). Use **`${VAR}`** placeholders only; never print token or kubeconfig contents in chat output. + +**Linux vs macOS:** OpenShift MCP `podman` args may include user-namespace flags for `KUBECONFIG` mounts; adjust per the pack **README** if Podman runs in a VM. diff --git a/ocp-admin/.catalog/mcp_section.md b/ocp-admin/.catalog/mcp_section.md new file mode 100644 index 00000000..68c429e0 --- /dev/null +++ b/ocp-admin/.catalog/mcp_section.md @@ -0,0 +1,12 @@ + + +| Server | Role | +|--------|------| +| **openshift-self-managed** | Assisted Installer API for self-managed cluster lifecycle (OCP, SNO). | +| **openshift-ocm-managed** | OpenShift Cluster Manager API for managed service clusters (ROSA, ARO, OSD). | +| **openshift-administration** | Kubernetes/OpenShift operations for multi-context fleet reports; read-only where applicable. | + +Configure servers through **`mcps.json`**; skills must be invoked instead of calling MCP tools directly from the agent. diff --git a/pyproject.toml b/pyproject.toml index 06bb0f89..ef199931 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -7,3 +7,8 @@ dependencies = [ "PyYAML>=6.0", "jsonschema>=4.0", ] + +[dependency-groups] +dev = [ + "pre-commit>=4.0.0", +] diff --git a/rh-ai-engineer/.catalog/collection.json b/rh-ai-engineer/.catalog/collection.json new file mode 100644 index 00000000..69fe2caa --- /dev/null +++ b/rh-ai-engineer/.catalog/collection.json @@ -0,0 +1,173 @@ +{ + "author": { + "email": "eco-engineering@redhat.com", + "name": "Red Hat Ecosystem Engineering" + }, + "categories": [ + "AI Engineer", + "OpenShift AI", + "RHOAI", + "KServe", + "vLLM", + "NVIDIA NIM", + "Model serving", + "Inference", + "GPU" + ], + "contents": { + "description": "The pack provides 10 skills and 1 orchestration skill for OpenShift AI workflows on Red Hat platforms; see CLAUDE.md\nfor intent routing.\n", + "orchestration_skills": [ + { + "description": "Configure TrustyAI Guardrails Orchestrator for LLM input/output content safety on OpenShift AI.", + "name": "guardrails-config", + "summary_markdown": "Configure TrustyAI Guardrails Orchestrator for LLM input/output content safety on OpenShift AI.\n**Use when:**\n- \"Add guardrails to my LLM endpoint\"\n- \"Set up content safety for my model\"\n- \"Configure PII detection on my inference endpoint\"\n- \"Block prompt injection attacks\"\n**What it does:**\n- Deploys GuardrailsOrchestrator CRs, detector ConfigMaps, and policies for guarded endpoints.\n- Validates orchestrator and sidecar health; pairs with `/model-deploy` when an InferenceService needs a guarded route.\n" + } + ], + "skills": [ + { + "description": "Analyze AI model performance, GPU utilization, and cluster health on OpenShift AI.", + "name": "ai-observability", + "summary_markdown": "Analyze AI model performance, GPU utilization, and cluster health on OpenShift AI.\n**Use when:**\n- \"How is my model performing?\"\n- \"What GPUs are available in the cluster?\"\n- \"Show me inference latency for Llama\"\n- \"Check OpenShift cluster health metrics\"\n**What it does:**\n- Pulls metrics, GPU, vLLM, and tracing signals via the optional ai-observability MCP with OpenShift fallbacks.\n- Summarizes latency, throughput, and saturation for InferenceServices and cluster capacity.\n" + }, + { + "description": "Troubleshoot failed or slow InferenceService deployments on OpenShift AI.", + "name": "debug-inference", + "summary_markdown": "Troubleshoot failed or slow InferenceService deployments on OpenShift AI.\n**Use when:**\n- \"My InferenceService won't start\"\n- \"Model deployment is stuck\"\n- \"Inference endpoint returns errors\"\n- \"Model is slow / high latency\"\n**What it does:**\n- Traces InferenceService revisions, pods, events, and routes to localize image, quota, and runtime failures.\n- Suggests fixes and when to rerun `/model-deploy` after configuration or image changes.\n" + }, + { + "description": "Create and configure Data Science Projects on OpenShift AI with namespace setup, S3 data connections, pipeline server, and model serving enablement.", + "name": "ds-project-setup", + "summary_markdown": "Create and configure Data Science Projects on OpenShift AI with namespace setup, S3 data connections, pipeline server, and model serving enablement.\n**Use when:**\n- \"Create a data science project\"\n- \"Set up a new namespace for ML work\"\n- \"Add an S3 data connection to my project\"\n- \"Configure the pipeline server\"\n**What it does:**\n- Provisions DSP scaffolding, connections, DSPA / pipeline server, and model-serving enablement flags with checks.\n- Validates operators, RBAC, and storage prerequisites before binding external data or workbenches.\n" + }, + { + "description": "Deploy AI/ML models on OpenShift AI using KServe with vLLM, NVIDIA NIM, or Caikit+TGIS runtimes.", + "name": "model-deploy", + "summary_markdown": "Deploy AI/ML models on OpenShift AI using KServe with vLLM, NVIDIA NIM, or Caikit+TGIS runtimes.\n**Use when:**\n- \"Deploy Llama 3 on my cluster\"\n- \"Set up a vLLM inference endpoint\"\n- \"Deploy a model with NIM\"\n- \"Create an InferenceService for Granite\"\n**What it does:**\n- Applies InferenceService and supporting objects with redacted manifests and explicit approval gates.\n- Verifies runtime pods, routes, and readiness, then surfaces rollout errors for follow-up skills.\n" + }, + { + "description": "Configure TrustyAI model monitoring for bias detection and data drift on deployed InferenceServices.", + "name": "model-monitor", + "summary_markdown": "Configure TrustyAI model monitoring for bias detection and data drift on deployed InferenceServices.\n**Use when:**\n- \"Monitor my model for bias\"\n- \"Set up drift detection on my inference endpoint\"\n- \"Configure TrustyAI for my deployed model\"\n- \"Check if my model has fairness issues\"\n**What it does:**\n- Enables TrustyAI monitors, fairness metrics (SPD/DIR style signals), and drift dashboards for live endpoints.\n- Connects monitors to existing InferenceServices without replacing `/model-deploy` serving specs.\n" + }, + { + "description": "Register, version, and manage ML models in the OpenShift AI Model Registry.", + "name": "model-registry", + "summary_markdown": "Register, version, and manage ML models in the OpenShift AI Model Registry.\n**Use when:**\n- \"Register a new model in the registry\"\n- \"List registered models\"\n- \"What versions exist for my model?\"\n- \"Promote a model from dev to production\"\n**What it does:**\n- Captures metadata, artifacts, and version history in the Model Registry and catalog views.\n- Supports promotion labels and environment separation across data science projects.\n" + }, + { + "description": "Configure NVIDIA NIM platform on OpenShift AI for optimized model inference.", + "name": "nim-setup", + "summary_markdown": "Configure NVIDIA NIM platform on OpenShift AI for optimized model inference.\n**Use when:**\n- \"Set up NIM on my cluster\"\n- \"Configure NGC credentials for NIM\"\n- \"I want to deploy a NIM model but haven't set up the platform\"\n- \"Create the NIM Account CR\"\n**What it does:**\n- Installs NIM Account CRs, NGC pull credentials, and validates operator readiness for NIM-backed runtimes.\n- One-time prerequisite before `/model-deploy` selects a NIM runtime.\n" + }, + { + "description": "Create, run, schedule, and monitor Data Science Pipelines (Kubeflow Pipelines 2.0) on OpenShift AI.", + "name": "pipeline-manage", + "summary_markdown": "Create, run, schedule, and monitor Data Science Pipelines (Kubeflow Pipelines 2.0) on OpenShift AI.\n**Use when:**\n- \"Run a pipeline in my project\"\n- \"Schedule a recurring pipeline\"\n- \"Check my pipeline run status\"\n- \"List pipeline runs and their logs\"\n**What it does:**\n- Manages Pipeline definitions, runs, schedules, and log retrieval for DSPA / KFP 2.0 resources.\n- Surfaces DAG failures, pod errors, and rerun guidance for stuck steps.\n" + }, + { + "description": "Configure custom ServingRuntime CRs on OpenShift AI for model serving frameworks not covered by built-in runtimes.", + "name": "serving-runtime-config", + "summary_markdown": "Configure custom ServingRuntime CRs on OpenShift AI for model serving frameworks not covered by built-in runtimes.\n**Use when:**\n- \"Create a custom serving runtime\"\n- \"I need a runtime for ONNX / Triton / custom framework\"\n- \"Customize vLLM runtime parameters\"\n- \"What serving runtimes are available?\"\n**What it does:**\n- Authors or patches ServingRuntime CRs for custom frameworks and tuned vLLM stacks.\n- Checks for conflicts with cluster defaults before apply and documents required approvals.\n" + }, + { + "description": "Create and manage Jupyter notebook workbenches on OpenShift AI with image selection, resource configuration, PVC storage, and lifecycle management.", + "name": "workbench-manage", + "summary_markdown": "Create and manage Jupyter notebook workbenches on OpenShift AI with image selection, resource configuration, PVC storage, and lifecycle management.\n**Use when:**\n- \"Create a notebook workbench\"\n- \"Spin up a Jupyter environment for data science\"\n- \"Start / stop my workbench\"\n- \"What notebook images are available?\"\n**What it does:**\n- Provisions workbenches with image, CPU/RAM, and PVC sizing plus idle and storage policies.\n- Handles start/stop/delete with data-loss warnings when PVCs or workspaces are affected.\n" + } + ], + "skills_decision_guide": [ + { + "reason": "KServe deploys with vLLM, NIM, or Caikit+TGIS patterns.", + "skill_to_use": "model-deploy", + "user_request": "\"Deploy model\" or \"InferenceService\"" + }, + { + "reason": "Jupyter workbench lifecycle and storage on OpenShift AI.", + "skill_to_use": "workbench-manage", + "user_request": "\"Notebook\" or \"workbench\"" + }, + { + "reason": "Project, connections, pipeline server, and serving enablement.", + "skill_to_use": "ds-project-setup", + "user_request": "\"Data science project\" or \"DSPA\"" + }, + { + "reason": "Kubeflow Pipelines 2.0 runs, schedules, and logs.", + "skill_to_use": "pipeline-manage", + "user_request": "\"Pipeline run\" or \"schedule pipeline\"" + }, + { + "reason": "TrustyAI Guardrails Orchestrator for guarded endpoints.", + "skill_to_use": "guardrails-config", + "user_request": "\"Guardrails\" or \"PII on LLM endpoint\"" + }, + { + "reason": "Progressive diagnosis for InferenceService failures.", + "skill_to_use": "debug-inference", + "user_request": "\"Inference failing\" or \"CrashLoop model\"" + } + ] + }, + "deploy_and_use": "#deploy_and_use.md", + "description": "Skills for OpenShift AI (RHOAI)—data science projects, workbenches, KServe and NIM model serving, pipelines, observability, TrustyAI monitoring and guardrails, model registry, and inference troubleshooting.", + "homepage": "https://github.com/RHEcosystemAppEng/agentic-collections", + "id": "rh-ai-engineer", + "keywords": [ + "rhoai", + "openshift-ai", + "kserve", + "vllm", + "gpu", + "mlops" + ], + "legal_resources": { + "license_agreement_url": "https://www.redhat.com/en/about/agreements", + "privacy_policy_url": "https://www.redhat.com/en/about/privacy-policy" + }, + "license": "Apache-2.0", + "marketplaces": [ + "Claude Code", + "Cursor" + ], + "mcp_section": "#mcp_section.md", + "name": "Red Hat OpenShift AI Engineering Agentic Collection", + "personas": [ + "Red Hat platform engineer" + ], + "provider": "Red Hat", + "repository": "https://github.com/RHEcosystemAppEng/agentic-collections", + "resources": [ + { + "description": "Product docs for RHOAI operators and workflows.", + "title": "OpenShift AI documentation", + "url": "https://docs.redhat.com/en/documentation/red_hat_openshift_ai/" + }, + { + "description": "Model serving patterns used with OpenShift AI.", + "title": "KServe", + "url": "https://kserve.github.io/website/latest/" + }, + { + "description": "Source for this pack and catalog metadata.", + "title": "agentic-collections repository", + "url": "https://github.com/RHEcosystemAppEng/agentic-collections" + } + ], + "sample_workflows": [ + { + "name": "Project to model on OpenShift AI", + "workflow": "User: \"Stand up a project and deploy Granite with a route\"\n- `/ds-project-setup` prepares namespace, connections, and pipeline server\n- `/model-deploy` creates InferenceService with chosen runtime and exposes the endpoint\n- `/ai-observability` checks latency and GPU utilization after rollout\n" + }, + { + "name": "NIM path", + "workflow": "User: \"I want NIM inference for Llama\"\n- `/nim-setup` configures the NIM Account and prerequisites once\n- `/model-deploy` targets NIM runtime and validates pods\n- `/debug-inference` if the rollout stalls or errors\n" + }, + { + "name": "Guarded LLM endpoint", + "workflow": "User: \"Add PII and toxicity checks to my served model\"\n- `/model-deploy` ensures a stable InferenceService baseline\n- `/guardrails-config` installs orchestrator, detectors, and policies\n- `/model-monitor` if bias or drift checks are also required\n" + } + ], + "summary": "The rh-ai-engineer collection covers OpenShift AI projects, workbenches, model deploy, pipelines, NIM, monitoring,\nguardrails, and inference troubleshooting across 11 skills.\n", + "support_level": "Unknown", + "version": "0.1.0" +} diff --git a/rh-ai-engineer/.catalog/collection.yaml b/rh-ai-engineer/.catalog/collection.yaml new file mode 100644 index 00000000..26badcd5 --- /dev/null +++ b/rh-ai-engineer/.catalog/collection.yaml @@ -0,0 +1,233 @@ +# Catalog: maintained via create-collection workflow (assistant + maintainer + PR review). +# Golden sources: skills/*/SKILL.md, README.md, CLAUDE.md, marketplace/rh-agentic-collection.yml +# Do not edit ad hoc — follow COLLECTION_SPEC.md and the create-collection skill. + +id: rh-ai-engineer +name: Red Hat OpenShift AI Engineering Agentic Collection +provider: Red Hat +version: 0.1.0 +categories: +- AI Engineer +- OpenShift AI +- RHOAI +- KServe +- vLLM +- NVIDIA NIM +- Model serving +- Inference +- GPU +personas: +- Red Hat platform engineer +marketplaces: +- Claude Code +- Cursor +support_level: Unknown +description: Skills for OpenShift AI (RHOAI)—data science projects, workbenches, KServe and NIM model serving, pipelines, + observability, TrustyAI monitoring and guardrails, model registry, and inference troubleshooting. +summary: | + The rh-ai-engineer collection covers OpenShift AI projects, workbenches, model deploy, pipelines, NIM, monitoring, + guardrails, and inference troubleshooting across 11 skills. +contents: + description: | + The pack provides 10 skills and 1 orchestration skill for OpenShift AI workflows on Red Hat platforms; see CLAUDE.md + for intent routing. + skills: + - name: ai-observability + description: Analyze AI model performance, GPU utilization, and cluster health on OpenShift AI. + summary_markdown: | + Analyze AI model performance, GPU utilization, and cluster health on OpenShift AI. + **Use when:** + - "How is my model performing?" + - "What GPUs are available in the cluster?" + - "Show me inference latency for Llama" + - "Check OpenShift cluster health metrics" + **What it does:** + - Pulls metrics, GPU, vLLM, and tracing signals via the optional ai-observability MCP with OpenShift fallbacks. + - Summarizes latency, throughput, and saturation for InferenceServices and cluster capacity. + - name: debug-inference + description: Troubleshoot failed or slow InferenceService deployments on OpenShift AI. + summary_markdown: | + Troubleshoot failed or slow InferenceService deployments on OpenShift AI. + **Use when:** + - "My InferenceService won't start" + - "Model deployment is stuck" + - "Inference endpoint returns errors" + - "Model is slow / high latency" + **What it does:** + - Traces InferenceService revisions, pods, events, and routes to localize image, quota, and runtime failures. + - Suggests fixes and when to rerun `/model-deploy` after configuration or image changes. + - name: ds-project-setup + description: Create and configure Data Science Projects on OpenShift AI with namespace setup, S3 data connections, pipeline server, and model serving enablement. + summary_markdown: | + Create and configure Data Science Projects on OpenShift AI with namespace setup, S3 data connections, pipeline server, and model serving enablement. + **Use when:** + - "Create a data science project" + - "Set up a new namespace for ML work" + - "Add an S3 data connection to my project" + - "Configure the pipeline server" + **What it does:** + - Provisions DSP scaffolding, connections, DSPA / pipeline server, and model-serving enablement flags with checks. + - Validates operators, RBAC, and storage prerequisites before binding external data or workbenches. + - name: model-deploy + description: Deploy AI/ML models on OpenShift AI using KServe with vLLM, NVIDIA NIM, or Caikit+TGIS runtimes. + summary_markdown: | + Deploy AI/ML models on OpenShift AI using KServe with vLLM, NVIDIA NIM, or Caikit+TGIS runtimes. + **Use when:** + - "Deploy Llama 3 on my cluster" + - "Set up a vLLM inference endpoint" + - "Deploy a model with NIM" + - "Create an InferenceService for Granite" + **What it does:** + - Applies InferenceService and supporting objects with redacted manifests and explicit approval gates. + - Verifies runtime pods, routes, and readiness, then surfaces rollout errors for follow-up skills. + - name: model-monitor + description: Configure TrustyAI model monitoring for bias detection and data drift on deployed InferenceServices. + summary_markdown: | + Configure TrustyAI model monitoring for bias detection and data drift on deployed InferenceServices. + **Use when:** + - "Monitor my model for bias" + - "Set up drift detection on my inference endpoint" + - "Configure TrustyAI for my deployed model" + - "Check if my model has fairness issues" + **What it does:** + - Enables TrustyAI monitors, fairness metrics (SPD/DIR style signals), and drift dashboards for live endpoints. + - Connects monitors to existing InferenceServices without replacing `/model-deploy` serving specs. + - name: model-registry + description: Register, version, and manage ML models in the OpenShift AI Model Registry. + summary_markdown: | + Register, version, and manage ML models in the OpenShift AI Model Registry. + **Use when:** + - "Register a new model in the registry" + - "List registered models" + - "What versions exist for my model?" + - "Promote a model from dev to production" + **What it does:** + - Captures metadata, artifacts, and version history in the Model Registry and catalog views. + - Supports promotion labels and environment separation across data science projects. + - name: nim-setup + description: Configure NVIDIA NIM platform on OpenShift AI for optimized model inference. + summary_markdown: | + Configure NVIDIA NIM platform on OpenShift AI for optimized model inference. + **Use when:** + - "Set up NIM on my cluster" + - "Configure NGC credentials for NIM" + - "I want to deploy a NIM model but haven't set up the platform" + - "Create the NIM Account CR" + **What it does:** + - Installs NIM Account CRs, NGC pull credentials, and validates operator readiness for NIM-backed runtimes. + - One-time prerequisite before `/model-deploy` selects a NIM runtime. + - name: pipeline-manage + description: Create, run, schedule, and monitor Data Science Pipelines (Kubeflow Pipelines 2.0) on OpenShift AI. + summary_markdown: | + Create, run, schedule, and monitor Data Science Pipelines (Kubeflow Pipelines 2.0) on OpenShift AI. + **Use when:** + - "Run a pipeline in my project" + - "Schedule a recurring pipeline" + - "Check my pipeline run status" + - "List pipeline runs and their logs" + **What it does:** + - Manages Pipeline definitions, runs, schedules, and log retrieval for DSPA / KFP 2.0 resources. + - Surfaces DAG failures, pod errors, and rerun guidance for stuck steps. + - name: serving-runtime-config + description: Configure custom ServingRuntime CRs on OpenShift AI for model serving frameworks not covered by built-in runtimes. + summary_markdown: | + Configure custom ServingRuntime CRs on OpenShift AI for model serving frameworks not covered by built-in runtimes. + **Use when:** + - "Create a custom serving runtime" + - "I need a runtime for ONNX / Triton / custom framework" + - "Customize vLLM runtime parameters" + - "What serving runtimes are available?" + **What it does:** + - Authors or patches ServingRuntime CRs for custom frameworks and tuned vLLM stacks. + - Checks for conflicts with cluster defaults before apply and documents required approvals. + - name: workbench-manage + description: Create and manage Jupyter notebook workbenches on OpenShift AI with image selection, resource configuration, PVC storage, and lifecycle management. + summary_markdown: | + Create and manage Jupyter notebook workbenches on OpenShift AI with image selection, resource configuration, PVC storage, and lifecycle management. + **Use when:** + - "Create a notebook workbench" + - "Spin up a Jupyter environment for data science" + - "Start / stop my workbench" + - "What notebook images are available?" + **What it does:** + - Provisions workbenches with image, CPU/RAM, and PVC sizing plus idle and storage policies. + - Handles start/stop/delete with data-loss warnings when PVCs or workspaces are affected. + orchestration_skills: + - name: guardrails-config + description: Configure TrustyAI Guardrails Orchestrator for LLM input/output content safety on OpenShift AI. + summary_markdown: | + Configure TrustyAI Guardrails Orchestrator for LLM input/output content safety on OpenShift AI. + **Use when:** + - "Add guardrails to my LLM endpoint" + - "Set up content safety for my model" + - "Configure PII detection on my inference endpoint" + - "Block prompt injection attacks" + **What it does:** + - Deploys GuardrailsOrchestrator CRs, detector ConfigMaps, and policies for guarded endpoints. + - Validates orchestrator and sidecar health; pairs with `/model-deploy` when an InferenceService needs a guarded route. + skills_decision_guide: + - user_request: '"Deploy model" or "InferenceService"' + skill_to_use: model-deploy + reason: KServe deploys with vLLM, NIM, or Caikit+TGIS patterns. + - user_request: '"Notebook" or "workbench"' + skill_to_use: workbench-manage + reason: Jupyter workbench lifecycle and storage on OpenShift AI. + - user_request: '"Data science project" or "DSPA"' + skill_to_use: ds-project-setup + reason: Project, connections, pipeline server, and serving enablement. + - user_request: '"Pipeline run" or "schedule pipeline"' + skill_to_use: pipeline-manage + reason: Kubeflow Pipelines 2.0 runs, schedules, and logs. + - user_request: '"Guardrails" or "PII on LLM endpoint"' + skill_to_use: guardrails-config + reason: TrustyAI Guardrails Orchestrator for guarded endpoints. + - user_request: '"Inference failing" or "CrashLoop model"' + skill_to_use: debug-inference + reason: Progressive diagnosis for InferenceService failures. +mcp_section: '#mcp_section.md' +deploy_and_use: '#deploy_and_use.md' +sample_workflows: +- name: Project to model on OpenShift AI + workflow: | + User: "Stand up a project and deploy Granite with a route" + - `/ds-project-setup` prepares namespace, connections, and pipeline server + - `/model-deploy` creates InferenceService with chosen runtime and exposes the endpoint + - `/ai-observability` checks latency and GPU utilization after rollout +- name: NIM path + workflow: | + User: "I want NIM inference for Llama" + - `/nim-setup` configures the NIM Account and prerequisites once + - `/model-deploy` targets NIM runtime and validates pods + - `/debug-inference` if the rollout stalls or errors +- name: Guarded LLM endpoint + workflow: | + User: "Add PII and toxicity checks to my served model" + - `/model-deploy` ensures a stable InferenceService baseline + - `/guardrails-config` installs orchestrator, detectors, and policies + - `/model-monitor` if bias or drift checks are also required +resources: +- title: OpenShift AI documentation + url: https://docs.redhat.com/en/documentation/red_hat_openshift_ai/ + description: Product docs for RHOAI operators and workflows. +- title: KServe + url: https://kserve.github.io/website/latest/ + description: Model serving patterns used with OpenShift AI. +- title: agentic-collections repository + url: https://github.com/RHEcosystemAppEng/agentic-collections + description: Source for this pack and catalog metadata. +legal_resources: + license_agreement_url: https://www.redhat.com/en/about/agreements + privacy_policy_url: https://www.redhat.com/en/about/privacy-policy +author: + name: Red Hat Ecosystem Engineering + email: eco-engineering@redhat.com +homepage: https://github.com/RHEcosystemAppEng/agentic-collections +repository: https://github.com/RHEcosystemAppEng/agentic-collections +license: Apache-2.0 +keywords: +- rhoai +- openshift-ai +- kserve +- vllm +- gpu +- mlops diff --git a/rh-ai-engineer/.catalog/deploy_and_use.md b/rh-ai-engineer/.catalog/deploy_and_use.md new file mode 100644 index 00000000..be741568 --- /dev/null +++ b/rh-ai-engineer/.catalog/deploy_and_use.md @@ -0,0 +1,60 @@ + + +### Prerequisites + +- Claude Code CLI or IDE extension (if using Claude Code) +- OpenShift cluster with **OpenShift AI (RHOAI)** installed and namespaces where you will work +- **`oc`** / **`kubectl`** access and a kubeconfig for the **`openshift`** and **`rhoai`** MCP flows +- Podman (recommended) for the containerized **OpenShift** MCP, or adjust per README for your OS +- Optional: **AI Observability** MCP deployed on-cluster (see **`mcps.json`** description URL) for GPU / vLLM / tracing helpers + +### Environment setup + +Names must match **`mcps.json`**. Do not commit secrets. + +**Cluster API (OpenShift MCP + rhoai stdio transport):** + +```bash +export KUBECONFIG="/path/to/your/kubeconfig" +``` + +The **`rhoai`** server maps **`RHOAI_MCP_KUBECONFIG_PATH`** to **`${KUBECONFIG}`** in **`mcps.json`**—set **`KUBECONFIG`** once for both. + +**`RHOAI_MCP_TRANSPORT`** is set to **`stdio`** in **`mcps.json`** (fixed for this pack). You do not need to export or override it unless you maintain a forked **`mcps.json`**. + +**AI Observability MCP (optional HTTP MCP):** + +```bash +export AI_OBSERVABILITY_MCP_URL="https://your-ai-observability-route.openshift-ai.svc.cluster.local:8080" +``` + +Omit or leave unset if you rely on **`openshift`** / **`rhoai`** only; skills should degrade gracefully when observability tools are unavailable. + +### Installation (Lola) + +```bash +lola install -f rh-ai-engineer +``` + +Module path: **`rh-ai-engineer`** in **`marketplace/rh-agentic-collection.yml`**. See the root [README.md](../../README.md) for full setup. + +### Installation (Claude Code) + +```bash +lola install -f rh-ai-engineer -a claude-code +``` + +### Installation (Cursor) + +```bash +lola install -f rh-ai-engineer -a cursor +``` + +### MCP configuration + +Servers are defined in **`mcps.json`**: **`openshift`** (Podman + **`KUBECONFIG`** mount), **`rhoai`** (**`uvx`** transport using **`KUBECONFIG`**), and optional **`ai-observability`** (**`AI_OBSERVABILITY_MCP_URL`**). Use **`${...}`** placeholders only; never echo kubeconfig or token contents. + +**Linux vs macOS:** the **`openshift`** entry may add user-namespace flags for `KUBECONFIG` readability on Linux; on macOS Podman-in-VM may require README adjustments. diff --git a/rh-ai-engineer/.catalog/mcp_section.md b/rh-ai-engineer/.catalog/mcp_section.md new file mode 100644 index 00000000..097127af --- /dev/null +++ b/rh-ai-engineer/.catalog/mcp_section.md @@ -0,0 +1,12 @@ + + +| Server | Role | +|--------|------| +| **openshift** | Kubernetes resource operations, pod logs, events — baseline cluster access. | +| **rhoai** | RHOAI-focused convenience APIs; skills may fall back to **openshift** when needed. | +| **ai-observability** | GPU metrics, vLLM analysis, tracing — optional when configured. | + +Configure servers through **`mcps.json`**; skills must be invoked instead of calling MCP tools directly from the agent. diff --git a/rh-ai-engineer/README.md b/rh-ai-engineer/README.md index 7bd84e1f..202e7644 100644 --- a/rh-ai-engineer/README.md +++ b/rh-ai-engineer/README.md @@ -27,6 +27,7 @@ Automation tools for AI/ML engineers working with Red Hat OpenShift AI (RHOAI). ### Environment Variables - `KUBECONFIG` - Path to Kubernetes configuration file - `AI_OBSERVABILITY_MCP_URL` (optional) - URL for the AI Observability MCP server +- `RHOAI_MCP_TRANSPORT` - Declared in **`mcps.json`** as **`stdio`** for the **`rhoai`** server; no export needed unless you maintain a customized **`mcps.json`** ### Cluster Requirements - OpenShift cluster with Red Hat OpenShift AI operator installed diff --git a/rh-automation/.catalog/collection.json b/rh-automation/.catalog/collection.json new file mode 100644 index 00000000..024dd8e2 --- /dev/null +++ b/rh-automation/.catalog/collection.json @@ -0,0 +1,160 @@ +{ + "author": { + "email": "eco-engineering@redhat.com", + "name": "Red Hat Ecosystem Engineering" + }, + "categories": [ + "Ansible", + "Aap", + "Automation", + "Red Hat", + "Governance", + "Troubleshooting", + "Execution" + ], + "contents": { + "description": "The pack provides 8 skills and 3 orchestration skills for rh automation workflows on Red Hat platforms; see CLAUDE.md for intent routing.\n", + "orchestration_skills": [ + { + "description": "Orchestrates forensic analysis of failed jobs with event extraction, host correlation, and resolution advisory.", + "name": "forensic-troubleshooter", + "summary_markdown": "Orchestrates forensic analysis of failed jobs with event extraction, host correlation, and resolution advisory.\n**Use when:**\n- \"Job #X failed\"\n- \"Analyze the failure\"\n- \"Root cause analysis of job #X\"\n**What it does:**\n- Runs the documented workflow with MCP access only through the skill and required confirmations.\n- Aligns with CLAUDE.md chaining when users need follow-on skills.\n" + }, + { + "description": "Orchestrates AAP governance readiness assessments -- full platform audit or scoped to specific domains.", + "name": "governance-assessor", + "summary_markdown": "Orchestrates AAP governance readiness assessments -- full platform audit or scoped to specific domains.\n**Use when:**\n- \"What should I fix before executing jobs?\"\n- \"See CLAUDE.md intent routing\"\n- \"See CLAUDE.md intent routing\"\n**What it does:**\n- Runs the documented workflow with MCP access only through the skill and required confirmations.\n- Aligns with CLAUDE.md chaining when users need follow-on skills.\n" + }, + { + "description": "Orchestrates governed job execution with risk analysis, check mode, approval, and rollback.", + "name": "governance-executor", + "summary_markdown": "Orchestrates governed job execution with risk analysis, check mode, approval, and rollback.\n**Use when:**\n- \"Execute job template X\"\n- \"See CLAUDE.md intent routing\"\n- \"See CLAUDE.md intent routing\"\n**What it does:**\n- Runs the documented workflow with MCP access only through the skill and required confirmations.\n- Aligns with CLAUDE.md chaining when users need follow-on skills.\n" + } + ], + "skills": [ + { + "description": "Validate that required AAP MCP servers are accessible before executing automation skills.", + "name": "aap-mcp-validator", + "summary_markdown": "Validate that required AAP MCP servers are accessible before executing automation skills.\n**Use when:**\n- \"Validate AAP MCP\"\n- \"Verify AAP connection\"\n- \"See CLAUDE.md intent routing\"\n**What it does:**\n- Runs the documented workflow with MCP access only through the skill and required confirmations.\n- Aligns with CLAUDE.md chaining when users need follow-on skills.\n" + }, + { + "description": "Analyze execution risk by classifying inventory, scanning extra_vars for secrets, and assessing scope.", + "name": "execution-risk-analyzer", + "summary_markdown": "Analyze execution risk by classifying inventory, scanning extra_vars for secrets, and assessing scope.\n**Use when:**\n- \"Execute on production\"\n- \"Is this execution safe?\"\n- \"Check execution risk\"\n- \"Validate the execution target\"\n**What it does:**\n- Runs the documented workflow with MCP access only through the skill and required confirmations.\n- Aligns with CLAUDE.md chaining when users need follow-on skills.\n" + }, + { + "description": "Generate concise execution audit reports tracking documents consulted, MCP tools used, decisions made, and outcomes.", + "name": "execution-summary", + "summary_markdown": "Generate concise execution audit reports tracking documents consulted, MCP tools used, decisions made, and outcomes.\n**Use when:**\n- \"Generate execution summary\"\n- \"Create execution report\"\n- \"Show workflow audit trail\"\n**What it does:**\n- Runs the documented workflow with MCP access only through the skill and required confirmations.\n- Aligns with CLAUDE.md chaining when users need follow-on skills.\n" + }, + { + "description": "Assess AAP platform governance readiness -- full 7-domain audit or scoped to specific domains.", + "name": "governance-readiness-assessor", + "summary_markdown": "Assess AAP platform governance readiness -- full 7-domain audit or scoped to specific domains.\n**Use when:**\n- \"What should I fix before executing jobs?\"\n- \"Assess my AAP configuration\"\n- \"See CLAUDE.md intent routing\"\n**What it does:**\n- Runs the documented workflow with MCP access only through the skill and required confirmations.\n- Aligns with CLAUDE.md chaining when users need follow-on skills.\n" + }, + { + "description": "Execute governed job launches with check mode, approval gates, phased rollout, and rollback.", + "name": "governed-job-launcher", + "summary_markdown": "Execute governed job launches with check mode, approval gates, phased rollout, and rollback.\n**Use when:**\n- \"Launch with check mode first\"\n- \"Execute the job\"\n- \"Rollback the failed job\"\n**What it does:**\n- Runs the documented workflow with MCP access only through the skill and required confirmations.\n- Aligns with CLAUDE.md chaining when users need follow-on skills.\n" + }, + { + "description": "Correlate job failures with host system facts to determine platform drift and resource issues.", + "name": "host-fact-inspector", + "summary_markdown": "Correlate job failures with host system facts to determine platform drift and resource issues.\n**Use when:**\n- \"Check the system facts for failed hosts\"\n- \"Is the host healthy?\"\n- \"Why is the service failing on this host?\"\n**What it does:**\n- Runs the documented workflow with MCP access only through the skill and required confirmations.\n- Aligns with CLAUDE.md chaining when users need follow-on skills.\n" + }, + { + "description": "Extract and analyze failure events from AAP jobs to classify errors and reconstruct failure timelines.", + "name": "job-failure-analyzer", + "summary_markdown": "Extract and analyze failure events from AAP jobs to classify errors and reconstruct failure timelines.\n**Use when:**\n- \"Job #X failed\"\n- \"Analyze the failed job\"\n- \"Show me the failure details\"\n**What it does:**\n- Runs the documented workflow with MCP access only through the skill and required confirmations.\n- Aligns with CLAUDE.md chaining when users need follow-on skills.\n" + }, + { + "description": "Provide Red Hat documentation-backed resolution recommendations for classified job errors.", + "name": "resolution-advisor", + "summary_markdown": "Provide Red Hat documentation-backed resolution recommendations for classified job errors.\n**Use when:**\n- \"What does Red Hat recommend for this error?\"\n- \"What's the fix for privilege escalation timeout?\"\n- \"Is this a known AAP issue?\"\n**What it does:**\n- Runs the documented workflow with MCP access only through the skill and required confirmations.\n- Aligns with CLAUDE.md chaining when users need follow-on skills.\n" + } + ], + "skills_decision_guide": [ + { + "reason": "End-to-end governance assessment with summaries.", + "skill_to_use": "governance-assessor", + "user_request": "\"Governance audit\" or \"production readiness\"" + }, + { + "reason": "Validator, risk analysis, governed launch, and summary.", + "skill_to_use": "governance-executor", + "user_request": "\"Run job template\" with approvals" + }, + { + "reason": "Failure analysis, host facts, resolution advice, summary.", + "skill_to_use": "forensic-troubleshooter", + "user_request": "\"Job failed\" root cause" + }, + { + "reason": "Connectivity and tool checks before other AAP skills.", + "skill_to_use": "aap-mcp-validator", + "user_request": "\"Validate AAP MCP\"" + }, + { + "reason": "Inventory class, extra_vars scan, scope assessment.", + "skill_to_use": "execution-risk-analyzer", + "user_request": "\"Is execution safe?\"" + } + ] + }, + "deploy_and_use": "#deploy_and_use.md", + "description": "Ansible Automation Platform governance, execution safety, and forensic troubleshooting tools for Red Hat automation engineers.", + "homepage": "https://github.com/RHEcosystemAppEng/agentic-collections", + "id": "rh-automation", + "keywords": [ + "ansible", + "aap", + "governance", + "automation", + "job-template" + ], + "legal_resources": { + "license_agreement_url": "https://www.redhat.com/en/about/agreements", + "privacy_policy_url": "https://www.redhat.com/en/about/privacy-policy" + }, + "license": "Apache-2.0", + "marketplaces": [ + "Claude Code", + "Cursor" + ], + "mcp_section": "#mcp_section.md", + "name": "Red Hat Automation Agentic Skills Collection", + "personas": [ + "Red Hat platform engineer" + ], + "provider": "Red Hat", + "repository": "https://github.com/RHEcosystemAppEng/agentic-collections", + "resources": [ + { + "description": "Official AAP documentation for controllers and execution.", + "title": "Red Hat Ansible Automation Platform", + "url": "https://docs.redhat.com/en/documentation/red_hat_ansible_automation_platform/" + }, + { + "description": "Source for this pack and catalog metadata.", + "title": "agentic-collections repository", + "url": "https://github.com/RHEcosystemAppEng/agentic-collections" + } + ], + "sample_workflows": [ + { + "name": "Governed production deploy", + "workflow": "User: \"Deploy this job template to production with checks\"\n- `/governance-executor` validates MCP, analyzes risk, offers check mode, and launches with approvals\n- `/execution-summary` captures the audit trail afterward\n" + }, + { + "name": "Forensics after failure", + "workflow": "User: \"Job 8841 failed on finance inventory — what happened?\"\n- `/forensic-troubleshooter` walks failure analysis, host facts, and doc-backed fixes\n- `/resolution-advisor` context is included inside that orchestration path\n" + }, + { + "name": "Manual validator then launch", + "workflow": "User: \"I only want risk analysis before I approve launch\"\n- `/aap-mcp-validator` confirms MCP reachability\n- `/execution-risk-analyzer` classifies targets and variables\n- `/governed-job-launcher` runs with the agreed mode and gates\n" + } + ], + "summary": "The rh-automation collection ships 11 catalogued skills for Red Hat automation workflows described in README and CLAUDE.md; orchestration entries coordinate sub-skills with explicit approvals.\n", + "support_level": "Unknown", + "version": "0.1.0" +} diff --git a/rh-automation/.catalog/collection.yaml b/rh-automation/.catalog/collection.yaml new file mode 100644 index 00000000..5f1c17b5 --- /dev/null +++ b/rh-automation/.catalog/collection.yaml @@ -0,0 +1,209 @@ +# Catalog: maintained via create-collection workflow (assistant + maintainer + PR review). +# Golden sources: skills/*/SKILL.md, README.md, CLAUDE.md, marketplace/rh-agentic-collection.yml +# Do not edit ad hoc — follow COLLECTION_SPEC.md and the create-collection skill. + +id: rh-automation +name: Red Hat Automation Agentic Skills Collection +provider: Red Hat +version: 0.1.0 +categories: +- Ansible +- Aap +- Automation +- Red Hat +- Governance +- Troubleshooting +- Execution +personas: +- Red Hat platform engineer +marketplaces: +- Claude Code +- Cursor +support_level: Unknown +description: "Ansible Automation Platform governance, execution safety, and forensic troubleshooting tools for Red Hat automation engineers." +summary: | + The rh-automation collection ships 11 catalogued skills for Red Hat automation workflows described in README and CLAUDE.md; orchestration entries coordinate sub-skills with explicit approvals. +contents: + description: | + The pack provides 8 skills and 3 orchestration skills for rh automation workflows on Red Hat platforms; see CLAUDE.md for intent routing. + skills: + - name: aap-mcp-validator + description: "Validate that required AAP MCP servers are accessible before executing automation skills." + summary_markdown: | + Validate that required AAP MCP servers are accessible before executing automation skills. + **Use when:** + - "Validate AAP MCP" + - "Verify AAP connection" + - "See CLAUDE.md intent routing" + **What it does:** + - Runs the documented workflow with MCP access only through the skill and required confirmations. + - Aligns with CLAUDE.md chaining when users need follow-on skills. + - name: execution-risk-analyzer + description: "Analyze execution risk by classifying inventory, scanning extra_vars for secrets, and assessing scope." + summary_markdown: | + Analyze execution risk by classifying inventory, scanning extra_vars for secrets, and assessing scope. + **Use when:** + - "Execute on production" + - "Is this execution safe?" + - "Check execution risk" + - "Validate the execution target" + **What it does:** + - Runs the documented workflow with MCP access only through the skill and required confirmations. + - Aligns with CLAUDE.md chaining when users need follow-on skills. + - name: execution-summary + description: "Generate concise execution audit reports tracking documents consulted, MCP tools used, decisions made, and outcomes." + summary_markdown: | + Generate concise execution audit reports tracking documents consulted, MCP tools used, decisions made, and outcomes. + **Use when:** + - "Generate execution summary" + - "Create execution report" + - "Show workflow audit trail" + **What it does:** + - Runs the documented workflow with MCP access only through the skill and required confirmations. + - Aligns with CLAUDE.md chaining when users need follow-on skills. + - name: governance-readiness-assessor + description: "Assess AAP platform governance readiness -- full 7-domain audit or scoped to specific domains." + summary_markdown: | + Assess AAP platform governance readiness -- full 7-domain audit or scoped to specific domains. + **Use when:** + - "What should I fix before executing jobs?" + - "Assess my AAP configuration" + - "See CLAUDE.md intent routing" + **What it does:** + - Runs the documented workflow with MCP access only through the skill and required confirmations. + - Aligns with CLAUDE.md chaining when users need follow-on skills. + - name: governed-job-launcher + description: "Execute governed job launches with check mode, approval gates, phased rollout, and rollback." + summary_markdown: | + Execute governed job launches with check mode, approval gates, phased rollout, and rollback. + **Use when:** + - "Launch with check mode first" + - "Execute the job" + - "Rollback the failed job" + **What it does:** + - Runs the documented workflow with MCP access only through the skill and required confirmations. + - Aligns with CLAUDE.md chaining when users need follow-on skills. + - name: host-fact-inspector + description: "Correlate job failures with host system facts to determine platform drift and resource issues." + summary_markdown: | + Correlate job failures with host system facts to determine platform drift and resource issues. + **Use when:** + - "Check the system facts for failed hosts" + - "Is the host healthy?" + - "Why is the service failing on this host?" + **What it does:** + - Runs the documented workflow with MCP access only through the skill and required confirmations. + - Aligns with CLAUDE.md chaining when users need follow-on skills. + - name: job-failure-analyzer + description: "Extract and analyze failure events from AAP jobs to classify errors and reconstruct failure timelines." + summary_markdown: | + Extract and analyze failure events from AAP jobs to classify errors and reconstruct failure timelines. + **Use when:** + - "Job #X failed" + - "Analyze the failed job" + - "Show me the failure details" + **What it does:** + - Runs the documented workflow with MCP access only through the skill and required confirmations. + - Aligns with CLAUDE.md chaining when users need follow-on skills. + - name: resolution-advisor + description: "Provide Red Hat documentation-backed resolution recommendations for classified job errors." + summary_markdown: | + Provide Red Hat documentation-backed resolution recommendations for classified job errors. + **Use when:** + - "What does Red Hat recommend for this error?" + - "What's the fix for privilege escalation timeout?" + - "Is this a known AAP issue?" + **What it does:** + - Runs the documented workflow with MCP access only through the skill and required confirmations. + - Aligns with CLAUDE.md chaining when users need follow-on skills. + orchestration_skills: + - name: forensic-troubleshooter + description: "Orchestrates forensic analysis of failed jobs with event extraction, host correlation, and resolution advisory." + summary_markdown: | + Orchestrates forensic analysis of failed jobs with event extraction, host correlation, and resolution advisory. + **Use when:** + - "Job #X failed" + - "Analyze the failure" + - "Root cause analysis of job #X" + **What it does:** + - Runs the documented workflow with MCP access only through the skill and required confirmations. + - Aligns with CLAUDE.md chaining when users need follow-on skills. + - name: governance-assessor + description: "Orchestrates AAP governance readiness assessments -- full platform audit or scoped to specific domains." + summary_markdown: | + Orchestrates AAP governance readiness assessments -- full platform audit or scoped to specific domains. + **Use when:** + - "What should I fix before executing jobs?" + - "See CLAUDE.md intent routing" + - "See CLAUDE.md intent routing" + **What it does:** + - Runs the documented workflow with MCP access only through the skill and required confirmations. + - Aligns with CLAUDE.md chaining when users need follow-on skills. + - name: governance-executor + description: "Orchestrates governed job execution with risk analysis, check mode, approval, and rollback." + summary_markdown: | + Orchestrates governed job execution with risk analysis, check mode, approval, and rollback. + **Use when:** + - "Execute job template X" + - "See CLAUDE.md intent routing" + - "See CLAUDE.md intent routing" + **What it does:** + - Runs the documented workflow with MCP access only through the skill and required confirmations. + - Aligns with CLAUDE.md chaining when users need follow-on skills. + skills_decision_guide: + - user_request: "\"Governance audit\" or \"production readiness\"" + skill_to_use: governance-assessor + reason: "End-to-end governance assessment with summaries." + - user_request: "\"Run job template\" with approvals" + skill_to_use: governance-executor + reason: "Validator, risk analysis, governed launch, and summary." + - user_request: "\"Job failed\" root cause" + skill_to_use: forensic-troubleshooter + reason: "Failure analysis, host facts, resolution advice, summary." + - user_request: "\"Validate AAP MCP\"" + skill_to_use: aap-mcp-validator + reason: "Connectivity and tool checks before other AAP skills." + - user_request: "\"Is execution safe?\"" + skill_to_use: execution-risk-analyzer + reason: "Inventory class, extra_vars scan, scope assessment." +mcp_section: '#mcp_section.md' +deploy_and_use: '#deploy_and_use.md' +sample_workflows: +- name: "Governed production deploy" + workflow: | + User: "Deploy this job template to production with checks" + - `/governance-executor` validates MCP, analyzes risk, offers check mode, and launches with approvals + - `/execution-summary` captures the audit trail afterward +- name: "Forensics after failure" + workflow: | + User: "Job 8841 failed on finance inventory — what happened?" + - `/forensic-troubleshooter` walks failure analysis, host facts, and doc-backed fixes + - `/resolution-advisor` context is included inside that orchestration path +- name: "Manual validator then launch" + workflow: | + User: "I only want risk analysis before I approve launch" + - `/aap-mcp-validator` confirms MCP reachability + - `/execution-risk-analyzer` classifies targets and variables + - `/governed-job-launcher` runs with the agreed mode and gates +resources: +- title: "Red Hat Ansible Automation Platform" + url: https://docs.redhat.com/en/documentation/red_hat_ansible_automation_platform/ + description: "Official AAP documentation for controllers and execution." +- title: "agentic-collections repository" + url: https://github.com/RHEcosystemAppEng/agentic-collections + description: "Source for this pack and catalog metadata." +legal_resources: + license_agreement_url: https://www.redhat.com/en/about/agreements + privacy_policy_url: https://www.redhat.com/en/about/privacy-policy +author: + name: Red Hat Ecosystem Engineering + email: eco-engineering@redhat.com +homepage: https://github.com/RHEcosystemAppEng/agentic-collections +repository: https://github.com/RHEcosystemAppEng/agentic-collections +license: Apache-2.0 +keywords: +- ansible +- aap +- governance +- automation +- job-template diff --git a/rh-automation/.catalog/deploy_and_use.md b/rh-automation/.catalog/deploy_and_use.md new file mode 100644 index 00000000..1a1b3fde --- /dev/null +++ b/rh-automation/.catalog/deploy_and_use.md @@ -0,0 +1,45 @@ + + +### Prerequisites + +- Claude Code CLI or IDE extension (if using Claude Code) +- Ansible Automation Platform **controller** reachable over HTTPS from the workstation running the assistant +- API token with permissions appropriate for job, inventory, configuration, security, monitoring, and user APIs used by the pack + +### Environment setup + +All HTTP MCP endpoints in **`mcps.json`** derive from the same host and bearer token. **Names must match `mcps.json` exactly.** + +```bash +export AAP_MCP_SERVER="your-aap-controller-hostname.example.com" +export AAP_API_TOKEN="your-controller-api-token" +``` + +Do **not** commit real hostnames or tokens; **`mcps.json`** must keep **`${AAP_MCP_SERVER}`** and **`${AAP_API_TOKEN}`** placeholders only. + +### Installation (Lola) + +```bash +lola install -f rh-automation +``` + +Module path: **`rh-automation`** in **`marketplace/rh-agentic-collection.yml`**. See the root [README.md](../../README.md) for marketplace setup. + +### Installation (Claude Code) + +```bash +lola install -f rh-automation -a claude-code +``` + +### Installation (Cursor) + +```bash +lola install -f rh-automation -a cursor +``` + +### MCP configuration + +Six **HTTP** MCP servers are listed under **`mcpServers`** in **`mcps.json`** (job, inventory, configuration, security-compliance, system-monitoring, user-management). Each uses **`https://${AAP_MCP_SERVER}/...`** and **`Bearer ${AAP_API_TOKEN}`**. Skills wrap these endpoints—do not call them directly from the assistant. diff --git a/rh-automation/.catalog/mcp_section.md b/rh-automation/.catalog/mcp_section.md new file mode 100644 index 00000000..f605ca86 --- /dev/null +++ b/rh-automation/.catalog/mcp_section.md @@ -0,0 +1,15 @@ + + +| Server | Role | +|--------|------| +| **aap-mcp-job-management** | Job templates, launches, events, workflows, approvals. | +| **aap-mcp-inventory-management** | Inventories, hosts, groups, host facts. | +| **aap-mcp-configuration** | Execution environments, notifications, platform settings. | +| **aap-mcp-security-compliance** | Credentials, credential types, compliance checks. | +| **aap-mcp-system-monitoring** | Instance groups, activity, mesh topology, platform status. | +| **aap-mcp-user-management** | Users, teams, organizations, RBAC. | + +Configure servers through **`mcps.json`**; skills must be invoked instead of calling MCP tools directly from the agent. diff --git a/rh-developer/.catalog/collection.json b/rh-developer/.catalog/collection.json new file mode 100644 index 00000000..2f5c377c --- /dev/null +++ b/rh-developer/.catalog/collection.json @@ -0,0 +1,227 @@ +{ + "author": { + "email": "eco-engineering@redhat.com", + "name": "Red Hat Ecosystem Engineering" + }, + "categories": [ + "Application development", + "OpenShift", + "Containers", + "Automation" + ], + "contents": { + "description": "The pack provides 14 skills for developer workflows on OpenShift and RHEL, including one orchestration skill\nfor end-to-end containerize-and-deploy.\n", + "orchestration_skills": [ + { + "description": "End-to-end containerize and deploy", + "name": "containerize-deploy", + "summary_markdown": "Guided workflow from source to running application on OpenShift or RHEL with checkpoints.\n**Use when:**\n- \"Deploy my app end to end\"\n- \"Take me from repo to running service\"\n**What it does:**\n- Phase: detect project and target environment.\n- Phase: choose OpenShift (S2I / Helm / Podman) or RHEL path.\n- Invokes specialized skills with explicit user approvals between phases.\n" + } + ], + "skills": [ + { + "description": "Project and runtime detection", + "name": "detect-project", + "summary_markdown": "Analyze repositories and local trees to detect language, framework, and runtime signals.\n**Use when:**\n- \"What language is this repo?\"\n- \"Scan my project for frameworks\"\n- \"Identify runtime from source\"\n**What it does:**\n- Reads project files and optional GitHub context.\n- Summarizes stack signals for build and deploy skills.\n" + }, + { + "description": "Image and builder recommendations", + "name": "recommend-image", + "summary_markdown": "Recommend S2I builder or base images aligned with Red Hat guidance.\n**Use when:**\n- \"Which S2I image for Node?\"\n- \"Best UBI image for this app?\"\n**What it does:**\n- Uses image selection criteria and builder catalog patterns.\n- Prepares inputs for `/s2i-build`.\n" + }, + { + "description": "Source-to-image builds", + "name": "s2i-build", + "summary_markdown": "Build container images on OpenShift using S2I / BuildConfig flows.\n**Use when:**\n- \"S2I build this repo\"\n- \"Create a BuildConfig\"\n- \"Build image from source\"\n**What it does:**\n- Validates inputs, drives build logs, surfaces common build failures.\n- Pairs with `/debug-build` on failure.\n" + }, + { + "description": "OpenShift deployment", + "name": "deploy", + "summary_markdown": "Deploy images to OpenShift with Deployment, Service, and Route.\n**Use when:**\n- \"Deploy to OpenShift\"\n- \"Expose my app with a Route\"\n**What it does:**\n- Generates manifests with approval gates.\n- Coordinates with cluster MCP safely.\n" + }, + { + "description": "Helm-based deployment", + "name": "helm-deploy", + "summary_markdown": "Install or upgrade Helm charts on OpenShift.\n**Use when:**\n- \"Helm install my chart\"\n- \"Upgrade release with new values\"\n**What it does:**\n- Validates chart paths and values.\n- Reports release status and common Helm errors.\n" + }, + { + "description": "RHEL / SSH deployment", + "name": "rhel-deploy", + "summary_markdown": "Deploy to standalone RHEL/Fedora hosts via SSH and systemd/Podman patterns.\n**Use when:**\n- \"Deploy on RHEL over SSH\"\n- \"systemd unit for my container\"\n**What it does:**\n- Uses SSH and host workflows from pack docs.\n- Optional Lightspeed context when configured.\n" + }, + { + "description": "Environment validation", + "name": "validate-environment", + "summary_markdown": "Verify local tools and cluster connectivity before deploy or debug work.\n**Use when:**\n- \"Check oc and helm\"\n- \"Validate my environment\"\n**What it does:**\n- Checks binaries, kubeconfig reachability, and common misconfigurations.\n" + }, + { + "description": "OpenShift build diagnostics", + "name": "debug-build", + "summary_markdown": "Diagnose BuildConfig / S2I / image build failures.\n**Use when:**\n- \"Build failed on OpenShift\"\n- \"ImagePullBackOff during build\"\n**What it does:**\n- Collects build logs and events.\n- Suggests fixes and retries with `/s2i-build`.\n" + }, + { + "description": "Pod diagnostics", + "name": "debug-pod", + "summary_markdown": "Diagnose running pod failures on OpenShift.\n**Use when:**\n- \"CrashLoopBackOff\"\n- \"Pod pending\"\n- \"OOMKilled pod\"\n**What it does:**\n- Inspects status, events, current/previous logs.\n- Coordinates with `/debug-network` when needed.\n" + }, + { + "description": "Tekton / pipeline diagnostics", + "name": "debug-pipeline", + "summary_markdown": "Diagnose PipelineRun and TaskRun failures.\n**Use when:**\n- \"PipelineRun failed\"\n- \"Tekton step error\"\n**What it does:**\n- Surfaces pipeline logs and workspace issues.\n- Guides toward green reruns.\n" + }, + { + "description": "Cluster networking diagnostics", + "name": "debug-network", + "summary_markdown": "Diagnose Services, Routes, DNS, and NetworkPolicy issues.\n**Use when:**\n- \"Service not reachable\"\n- \"Route returns 503\"\n**What it does:**\n- Traces endpoints and policies.\n- Feeds back into `/deploy` verification.\n" + }, + { + "description": "Local container diagnostics", + "name": "debug-container", + "summary_markdown": "Diagnose Podman/Docker local container failures.\n**Use when:**\n- \"Container exits immediately locally\"\n- \"Cannot pull image locally\"\n**What it does:**\n- Inspects local container state and logs.\n- Complements OpenShift debug skills.\n" + }, + { + "description": "RHEL host diagnostics", + "name": "debug-rhel", + "summary_markdown": "Diagnose systemd, SELinux, firewall, and resource issues on RHEL hosts.\n**Use when:**\n- \"SELinux denial\"\n- \"systemd service failed on host\"\n**What it does:**\n- Uses journal and policy signals.\n- Optional Lightspeed insights when available.\n" + } + ], + "skills_decision_guide": [ + { + "reason": "Creates workload, Service, and Route with confirmation gates.", + "skill_to_use": "deploy", + "user_request": "\"Deploy to OpenShift\" or \"expose my image\"" + }, + { + "reason": "Helm-focused install/upgrade with values and release checks.", + "skill_to_use": "helm-deploy", + "user_request": "\"Helm install\" or \"upgrade my chart\"" + }, + { + "reason": "OpenShift-native build flow before `/deploy`.", + "skill_to_use": "s2i-build", + "user_request": "\"S2I build\" or \"BuildConfig from source\"" + }, + { + "reason": "Orchestrates detect → strategy → deploy with checkpoints.", + "skill_to_use": "containerize-deploy", + "user_request": "\"From repo to running app\" or \"full deploy workflow\"" + }, + { + "reason": "Pod logs, events, and resource pressure analysis.", + "skill_to_use": "debug-pod", + "user_request": "\"CrashLoopBackOff\" or \"pod not starting\"" + }, + { + "reason": "Build logs and BuildConfig diagnosis.", + "skill_to_use": "debug-build", + "user_request": "\"Build failed\" or \"S2I error\"" + }, + { + "reason": "Pre-flight before deploy or heavy debug.", + "skill_to_use": "validate-environment", + "user_request": "\"Check my tools\" or \"validate cluster access\"" + } + ] + }, + "deploy_and_use": "#deploy_and_use.md", + "description": "Plugins for building and deploying applications on Red Hat platforms.", + "documentation_section": "#documentation_section.md", + "homepage": "https://github.com/RHEcosystemAppEng/agentic-collections", + "id": "rh-developer", + "keywords": [ + "developer", + "openshift", + "rhel", + "s2i", + "containerization", + "deployment", + "helm", + "podman" + ], + "legal_resources": { + "license_agreement_url": "https://www.redhat.com/en/about/agreements", + "privacy_policy_url": "https://www.redhat.com/en/about/privacy-policy" + }, + "license": "Apache-2.0", + "marketplaces": [ + "Claude Code", + "Cursor" + ], + "mcp_section": "#mcp_section.md", + "name": "Red Hat Developer Agentic Collection", + "personas": [ + "Application developer" + ], + "provider": "Red Hat", + "repository": "https://github.com/RHEcosystemAppEng/agentic-collections", + "resources": [ + { + "description": "OpenShift platform guides for developers and administrators.", + "embedded_doc": "docs/prerequisites.md", + "title": "OpenShift documentation", + "url": "https://docs.redhat.com/en/documentation/openshift_container_platform/" + }, + { + "description": "Helm install, upgrade, and chart authoring.", + "embedded_doc": "docs/dynamic-validation.md", + "title": "Helm documentation", + "url": "https://helm.sh/docs/" + }, + { + "description": "OpenShift builds and S2I concepts.", + "embedded_doc": "docs/builder-images.md", + "title": "Source-to-Image (S2I)", + "url": "https://docs.openshift.com/container-platform/latest/cicd/builds/understanding-image-builds.html" + }, + { + "description": "UBI and base image guidance.", + "embedded_doc": "docs/image-selection-criteria.md", + "title": "Red Hat Universal Base Images", + "url": "https://developers.redhat.com/products/rhel/ubi" + }, + { + "description": "Local container workflows used by the pack.", + "embedded_doc": "docs/debugging-patterns.md", + "title": "Podman", + "url": "https://docs.podman.io/" + }, + { + "description": "Pack policy for confirmations and destructive actions.", + "embedded_doc": "docs/human-in-the-loop.md", + "title": "Human-in-the-loop (pack)", + "url": "https://github.com/RHEcosystemAppEng/agentic-collections" + }, + { + "description": "SSH/systemd patterns for `/rhel-deploy`.", + "embedded_doc": "docs/rhel-deployment.md", + "title": "RHEL deployment notes (pack)", + "url": "https://github.com/RHEcosystemAppEng/agentic-collections" + } + ], + "sample_workflows": [ + { + "name": "S2I path: detect → image → build → deploy", + "workflow": "User: \"I have a Node app in this repo; put it on OpenShift\"\n- `/detect-project` identifies the stack\n- `/recommend-image` picks a builder (optional)\n- `/s2i-build` creates the image\n- `/deploy` rolls out Deployment, Service, and Route with approval\n" + }, + { + "name": "Helm install on cluster", + "workflow": "User: \"Install this Helm chart into namespace apps\"\n- `/validate-environment` checks `oc`/`helm`\n- `/helm-deploy` installs or upgrades the chart and reports release status\n" + }, + { + "name": "End-to-end with checkpoints", + "workflow": "User: \"Take my Python service from source to running on the cluster\"\n- `/containerize-deploy` walks phases with confirmations between detect, strategy, and deploy steps\n" + }, + { + "name": "Build failure then retry", + "workflow": "User: \"S2I build failed with ImagePullBackOff\"\n- `/debug-build` gathers build and registry signals\n- User applies fix; `/s2i-build` retries with updated inputs\n" + }, + { + "name": "Pod triage", + "workflow": "User: \"My pod keeps restarting\"\n- `/debug-pod` inspects events and logs\n- If networking suspected, `/debug-network` narrows DNS/Route/Service issues\n" + } + ], + "security_model": "#security_model.md", + "summary": "The rh-developer collection provides skills to detect projects, build images (S2I/Helm), deploy to OpenShift or RHEL, validate environments, and debug builds, pods, pipelines, networks, and hosts.", + "support_level": "Unknown", + "version": "0.1.0" +} diff --git a/rh-developer/.catalog/collection.yaml b/rh-developer/.catalog/collection.yaml new file mode 100644 index 00000000..ec9376b9 --- /dev/null +++ b/rh-developer/.catalog/collection.yaml @@ -0,0 +1,271 @@ +# Catalog: maintained via create-collection workflow (assistant + maintainer + PR review). +# Golden sources: skills/*/SKILL.md, README.md, CLAUDE.md, marketplace/rh-agentic-collection.yml +# Do not edit ad hoc — follow COLLECTION_SPEC.md and the create-collection skill. + +id: rh-developer +name: Red Hat Developer Agentic Collection +provider: Red Hat +version: 0.1.0 +categories: +- Application development +- OpenShift +- Containers +- Automation +personas: +- Application developer +marketplaces: +- Claude Code +- Cursor +support_level: Unknown +description: Plugins for building and deploying applications on Red Hat platforms. +summary: The rh-developer collection provides skills to detect projects, build images (S2I/Helm), deploy to OpenShift or RHEL, + validate environments, and debug builds, pods, pipelines, networks, and hosts. +contents: + description: | + The pack provides 14 skills for developer workflows on OpenShift and RHEL, including one orchestration skill + for end-to-end containerize-and-deploy. + skills: + - name: detect-project + description: Project and runtime detection + summary_markdown: | + Analyze repositories and local trees to detect language, framework, and runtime signals. + **Use when:** + - "What language is this repo?" + - "Scan my project for frameworks" + - "Identify runtime from source" + **What it does:** + - Reads project files and optional GitHub context. + - Summarizes stack signals for build and deploy skills. + - name: recommend-image + description: Image and builder recommendations + summary_markdown: | + Recommend S2I builder or base images aligned with Red Hat guidance. + **Use when:** + - "Which S2I image for Node?" + - "Best UBI image for this app?" + **What it does:** + - Uses image selection criteria and builder catalog patterns. + - Prepares inputs for `/s2i-build`. + - name: s2i-build + description: Source-to-image builds + summary_markdown: | + Build container images on OpenShift using S2I / BuildConfig flows. + **Use when:** + - "S2I build this repo" + - "Create a BuildConfig" + - "Build image from source" + **What it does:** + - Validates inputs, drives build logs, surfaces common build failures. + - Pairs with `/debug-build` on failure. + - name: deploy + description: OpenShift deployment + summary_markdown: | + Deploy images to OpenShift with Deployment, Service, and Route. + **Use when:** + - "Deploy to OpenShift" + - "Expose my app with a Route" + **What it does:** + - Generates manifests with approval gates. + - Coordinates with cluster MCP safely. + - name: helm-deploy + description: Helm-based deployment + summary_markdown: | + Install or upgrade Helm charts on OpenShift. + **Use when:** + - "Helm install my chart" + - "Upgrade release with new values" + **What it does:** + - Validates chart paths and values. + - Reports release status and common Helm errors. + - name: rhel-deploy + description: RHEL / SSH deployment + summary_markdown: | + Deploy to standalone RHEL/Fedora hosts via SSH and systemd/Podman patterns. + **Use when:** + - "Deploy on RHEL over SSH" + - "systemd unit for my container" + **What it does:** + - Uses SSH and host workflows from pack docs. + - Optional Lightspeed context when configured. + - name: validate-environment + description: Environment validation + summary_markdown: | + Verify local tools and cluster connectivity before deploy or debug work. + **Use when:** + - "Check oc and helm" + - "Validate my environment" + **What it does:** + - Checks binaries, kubeconfig reachability, and common misconfigurations. + - name: debug-build + description: OpenShift build diagnostics + summary_markdown: | + Diagnose BuildConfig / S2I / image build failures. + **Use when:** + - "Build failed on OpenShift" + - "ImagePullBackOff during build" + **What it does:** + - Collects build logs and events. + - Suggests fixes and retries with `/s2i-build`. + - name: debug-pod + description: Pod diagnostics + summary_markdown: | + Diagnose running pod failures on OpenShift. + **Use when:** + - "CrashLoopBackOff" + - "Pod pending" + - "OOMKilled pod" + **What it does:** + - Inspects status, events, current/previous logs. + - Coordinates with `/debug-network` when needed. + - name: debug-pipeline + description: Tekton / pipeline diagnostics + summary_markdown: | + Diagnose PipelineRun and TaskRun failures. + **Use when:** + - "PipelineRun failed" + - "Tekton step error" + **What it does:** + - Surfaces pipeline logs and workspace issues. + - Guides toward green reruns. + - name: debug-network + description: Cluster networking diagnostics + summary_markdown: | + Diagnose Services, Routes, DNS, and NetworkPolicy issues. + **Use when:** + - "Service not reachable" + - "Route returns 503" + **What it does:** + - Traces endpoints and policies. + - Feeds back into `/deploy` verification. + - name: debug-container + description: Local container diagnostics + summary_markdown: | + Diagnose Podman/Docker local container failures. + **Use when:** + - "Container exits immediately locally" + - "Cannot pull image locally" + **What it does:** + - Inspects local container state and logs. + - Complements OpenShift debug skills. + - name: debug-rhel + description: RHEL host diagnostics + summary_markdown: | + Diagnose systemd, SELinux, firewall, and resource issues on RHEL hosts. + **Use when:** + - "SELinux denial" + - "systemd service failed on host" + **What it does:** + - Uses journal and policy signals. + - Optional Lightspeed insights when available. + orchestration_skills: + - name: containerize-deploy + description: End-to-end containerize and deploy + summary_markdown: | + Guided workflow from source to running application on OpenShift or RHEL with checkpoints. + **Use when:** + - "Deploy my app end to end" + - "Take me from repo to running service" + **What it does:** + - Phase: detect project and target environment. + - Phase: choose OpenShift (S2I / Helm / Podman) or RHEL path. + - Invokes specialized skills with explicit user approvals between phases. + skills_decision_guide: + - user_request: '"Deploy to OpenShift" or "expose my image"' + skill_to_use: deploy + reason: Creates workload, Service, and Route with confirmation gates. + - user_request: '"Helm install" or "upgrade my chart"' + skill_to_use: helm-deploy + reason: Helm-focused install/upgrade with values and release checks. + - user_request: '"S2I build" or "BuildConfig from source"' + skill_to_use: s2i-build + reason: OpenShift-native build flow before `/deploy`. + - user_request: '"From repo to running app" or "full deploy workflow"' + skill_to_use: containerize-deploy + reason: Orchestrates detect → strategy → deploy with checkpoints. + - user_request: '"CrashLoopBackOff" or "pod not starting"' + skill_to_use: debug-pod + reason: Pod logs, events, and resource pressure analysis. + - user_request: '"Build failed" or "S2I error"' + skill_to_use: debug-build + reason: Build logs and BuildConfig diagnosis. + - user_request: '"Check my tools" or "validate cluster access"' + skill_to_use: validate-environment + reason: Pre-flight before deploy or heavy debug. +deploy_and_use: '#deploy_and_use.md' +documentation_section: '#documentation_section.md' +mcp_section: '#mcp_section.md' +security_model: '#security_model.md' +sample_workflows: +- name: 'S2I path: detect → image → build → deploy' + workflow: | + User: "I have a Node app in this repo; put it on OpenShift" + - `/detect-project` identifies the stack + - `/recommend-image` picks a builder (optional) + - `/s2i-build` creates the image + - `/deploy` rolls out Deployment, Service, and Route with approval +- name: Helm install on cluster + workflow: | + User: "Install this Helm chart into namespace apps" + - `/validate-environment` checks `oc`/`helm` + - `/helm-deploy` installs or upgrades the chart and reports release status +- name: End-to-end with checkpoints + workflow: | + User: "Take my Python service from source to running on the cluster" + - `/containerize-deploy` walks phases with confirmations between detect, strategy, and deploy steps +- name: Build failure then retry + workflow: | + User: "S2I build failed with ImagePullBackOff" + - `/debug-build` gathers build and registry signals + - User applies fix; `/s2i-build` retries with updated inputs +- name: Pod triage + workflow: | + User: "My pod keeps restarting" + - `/debug-pod` inspects events and logs + - If networking suspected, `/debug-network` narrows DNS/Route/Service issues +resources: +- title: OpenShift documentation + url: https://docs.redhat.com/en/documentation/openshift_container_platform/ + description: OpenShift platform guides for developers and administrators. + embedded_doc: docs/prerequisites.md +- title: Helm documentation + url: https://helm.sh/docs/ + description: Helm install, upgrade, and chart authoring. + embedded_doc: docs/dynamic-validation.md +- title: Source-to-Image (S2I) + url: https://docs.openshift.com/container-platform/latest/cicd/builds/understanding-image-builds.html + description: OpenShift builds and S2I concepts. + embedded_doc: docs/builder-images.md +- title: Red Hat Universal Base Images + url: https://developers.redhat.com/products/rhel/ubi + description: UBI and base image guidance. + embedded_doc: docs/image-selection-criteria.md +- title: Podman + url: https://docs.podman.io/ + description: Local container workflows used by the pack. + embedded_doc: docs/debugging-patterns.md +- title: Human-in-the-loop (pack) + url: https://github.com/RHEcosystemAppEng/agentic-collections + description: Pack policy for confirmations and destructive actions. + embedded_doc: docs/human-in-the-loop.md +- title: RHEL deployment notes (pack) + url: https://github.com/RHEcosystemAppEng/agentic-collections + description: SSH/systemd patterns for `/rhel-deploy`. + embedded_doc: docs/rhel-deployment.md +legal_resources: + license_agreement_url: https://www.redhat.com/en/about/agreements + privacy_policy_url: https://www.redhat.com/en/about/privacy-policy +author: + name: Red Hat Ecosystem Engineering + email: eco-engineering@redhat.com +homepage: https://github.com/RHEcosystemAppEng/agentic-collections +repository: https://github.com/RHEcosystemAppEng/agentic-collections +license: Apache-2.0 +keywords: +- developer +- openshift +- rhel +- s2i +- containerization +- deployment +- helm +- podman diff --git a/rh-developer/.catalog/deploy_and_use.md b/rh-developer/.catalog/deploy_and_use.md new file mode 100644 index 00000000..1223a49c --- /dev/null +++ b/rh-developer/.catalog/deploy_and_use.md @@ -0,0 +1,60 @@ + + +### Prerequisites + +- OpenShift cluster access (`oc`, valid `KUBECONFIG`) for OpenShift flows +- Podman (local builds and MCP) +- Optional: `GITHUB_PERSONAL_ACCESS_TOKEN` for GitHub-backed project detection +- Optional: Red Hat Lightspeed credentials for `/rhel-deploy` and `/debug-rhel` advisor paths + +### Environment setup + +Variable **names** must match **`mcps.json`**. Do not commit secrets or print values in assistant output. + +**OpenShift + local tooling:** + +```bash +export KUBECONFIG="/path/to/your/kubeconfig" +``` + +**GitHub MCP (optional):** + +```bash +export GITHUB_PERSONAL_ACCESS_TOKEN="your-github-token" +``` + +**Red Hat Lightspeed MCP (optional):** + +```bash +export LIGHTSPEED_CLIENT_ID="your-service-account-client-id" +export LIGHTSPEED_CLIENT_SECRET="your-service-account-client-secret" +``` + +### Install (Lola) + +```bash +lola install -f rh-developer +``` + +Module path: `rh-developer` in `marketplace/rh-agentic-collection.yml`. See the root [README.md](../../README.md) for full prerequisites and MCP notes. + +### Installation (Claude Code) + +```bash +lola install -f rh-developer -a claude-code +``` + +### Installation (Cursor) + +```bash +lola install -f rh-developer -a cursor +``` + +### MCP configuration + +Servers are defined in **`mcps.json`** at the pack root. Use **`${VAR}`** placeholders only. + +**Note (Linux vs macOS):** the OpenShift MCP `Podman` invocation may include user-namespace flags for `KUBECONFIG` readability; on macOS Podman-in-VM may require adjusting `mcps.json` per the pack README. diff --git a/rh-developer/.catalog/documentation_section.md b/rh-developer/.catalog/documentation_section.md new file mode 100644 index 00000000..bea3a80a --- /dev/null +++ b/rh-developer/.catalog/documentation_section.md @@ -0,0 +1,18 @@ + + +### Why use skills instead of raw MCP tools? + +- **Safety** — skills enforce confirmation before creates/updates/deletes and redact secrets. +- **Recovery** — standardized debug skills (`/debug-pod`, `/debug-build`, …) chain to remediation steps. +- **Consistency** — workflows follow pack docs (human-in-the-loop, image selection, RHEL patterns). + +### Pack documentation + +See **`docs/`** for deep dives: `prerequisites.md`, `human-in-the-loop.md`, `image-selection-criteria.md`, `builder-images.md`, `rhel-deployment.md`, `debugging-patterns.md`. + +### Routing + +Use **`CLAUDE.md`** intent routing to pick a single skill; use **`/containerize-deploy`** when the user wants an end-to-end guided path with checkpoints. diff --git a/rh-developer/.catalog/mcp_section.md b/rh-developer/.catalog/mcp_section.md new file mode 100644 index 00000000..b416ad93 --- /dev/null +++ b/rh-developer/.catalog/mcp_section.md @@ -0,0 +1,13 @@ + + +| Server | Role | +|--------|------| +| **openshift** | Cluster CRUD, logs, events, Helm — primary for OpenShift deploy and debug skills. | +| **podman** | Local image/build workflows used by S2I and container skills. | +| **github** | Repository analysis for `/detect-project` when sources are on GitHub. | +| **lightspeed-mcp** | Optional Insights-style data for RHEL-focused flows. | + +Configure in **`mcps.json`**; invoke skills rather than MCP tools directly from the agent. diff --git a/rh-developer/.catalog/security_model.md b/rh-developer/.catalog/security_model.md new file mode 100644 index 00000000..63e9122e --- /dev/null +++ b/rh-developer/.catalog/security_model.md @@ -0,0 +1,8 @@ + + +- Never echo tokens, kubeconfig contents, or registry passwords — only whether variables appear set. +- Confirm manifests and impact before mutating cluster or host resources; no silent deletes. +- Prefer **`/validate-environment`** before first deploy on a new machine or cluster context. diff --git a/rh-sre/.catalog/collection.json b/rh-sre/.catalog/collection.json new file mode 100644 index 00000000..f6d98352 --- /dev/null +++ b/rh-sre/.catalog/collection.json @@ -0,0 +1,222 @@ +{ + "author": { + "email": "eco-engineering@redhat.com", + "name": "Red Hat Ecosystem Engineering" + }, + "categories": [ + "Site Reliability", + "Security" + ], + "contents": { + "description": "The pack provides 13 skills for common SRE operations, including one orchestration skill for end-to-end remediation.\n", + "orchestration_skills": [ + { + "description": "End-to-End CVE Remediation", + "name": "remediation", + "summary_markdown": "The remediation skill orchestrates 6 specialized skills to provide complete CVE remediation workflows.\n**Use when:**\n- Remediate CVE-2024-1234 on system abc-123\n- Create and execute a remediation playbook for CVE-X\n- Patch these 5 CVEs on all production servers\n**Workflow:**\n0. Validate MCP (mcp-lightspeed-validator, mcp-aap-validator)\n1. Impact (cve-impact skill, if needed)\n2. Validate CVE (cve-validation skill)\n3. Gather Context (system-context skill)\n4. Generate Playbook (playbook-generator skill)\n5. Execute (playbook-executor skill, with user confirmation)\n6. Verify (remediation-verifier skill)\n**Capabilities:**\n- Single CVE on single system\n- Batch remediation (multiple CVEs, multiple systems)\n- Cross-environment patching (dev → staging → prod)\n- Automated job tracking and reporting\n- Partial failure handling\n" + } + ], + "skills": [ + { + "description": "System Discovery and Fleet Management", + "name": "fleet-inventory", + "summary_markdown": "Query and display Red Hat Lightspeed managed system inventory.\n**Use when:**\n- Show the managed fleet\n- List all RHEL 8 systems\n- What systems are registered in Lightspeed?\n**What it does:**\n- Retrieves all registered systems\n- Groups by RHEL version and environment\n- Shows system health and check-in status\n- Identifies stale systems\n" + }, + { + "description": "CVE Discovery and Risk Assessment", + "name": "cve-impact", + "summary_markdown": "Analyze CVE impact across the fleet without immediate remediation.\n**Use when:**\n- What are the most critical vulnerabilities?\n- Show CVEs affecting my systems\n- List high-severity CVEs\n**What it does:**\n- Lists CVEs by severity (Critical/Important)\n- Sorts by CVSS score\n- Shows affected system counts\n- Provides priority recommendations\n" + }, + { + "description": "CVE Verification", + "name": "cve-validation", + "summary_markdown": "Validate CVE existence and remediation availability.\n**Use when:**\n- Is CVE-2024-1234 valid?\n- Does CVE-X have a remediation?\n- What's the CVSS score for CVE-Y?\n**What it does:**\n- Verifies CVE in Red Hat database\n- Checks remediation availability\n- Returns CVE metadata and severity\n" + }, + { + "description": "System Information Gathering", + "name": "system-context", + "summary_markdown": "Collect detailed system information from Red Hat Lightspeed.\n**Use when:**\n- What systems are affected by CVE-X?\n- Show me details for server-01\n- Get system profile for these hosts\n**What it does:**\n- Retrieves system details\n- Shows installed packages\n- Displays configuration data\n- Maps CVE-to-system relationships\n" + }, + { + "description": "Ansible Playbook Creation", + "name": "playbook-generator", + "summary_markdown": "Generate Ansible remediation playbooks following Red Hat best practices. **Only generates playbooks; does not execute them.** Use `/playbook-executor` to run playbooks.\n**Use when:**\n- Create a remediation playbook for CVE-X\n- Generate Ansible playbook to patch CVE-Y\n**What it does:**\n- Calls Red Hat Lightspeed remediation API\n- Generates production-ready Ansible playbooks\n- Includes error handling and rollback steps\n- Follows Red Hat standards\n" + }, + { + "description": "AAP Playbook Execution", + "name": "playbook-executor", + "summary_markdown": "Execute Ansible playbooks via AAP with dry-run, real-time monitoring, and reporting.\n**Use when:**\n- Execute this remediation playbook\n- Run the playbook and monitor status\n**What it does:**\n- Launches jobs via AAP MCP (job_templates_launch_retrieve)\n- Performs Git Flow (commit, push, sync) when playbook path differs from template\n- Monitors job status (PENDING → RUNNING → COMPLETED)\n- Reports execution results\n**Note:** Requires AAP MCP servers configured and job templates created (use job-template-creator skill).\n" + }, + { + "description": "Remediation Verification", + "name": "remediation-verifier", + "summary_markdown": "Verify that CVE remediations were successfully applied.\n**Use when:**\n- Check if CVE-X was patched on server-01\n- Verify remediation status\n**What it does:**\n- Queries current CVE status\n- Verifies package updates\n- Confirms remediation success\n" + }, + { + "description": "Lightspeed MCP Server Validation", + "name": "mcp-lightspeed-validator", + "summary_markdown": "Validate Red Hat Lightspeed MCP server configuration and connectivity.\n**Use when:**\n- Validate Lightspeed MCP\n- Check if Lightspeed is configured\n- Verify Lightspeed connection\n- Other skills need to verify lightspeed-mcp availability\n**What it does:**\n- Checks MCP server configuration in mcps.json\n- Verifies environment variables (LIGHTSPEED_CLIENT_ID, LIGHTSPEED_CLIENT_SECRET)\n- Tests server connectivity and tool availability\n- Reports validation status (PASSED/PARTIAL/FAILED)\n" + }, + { + "description": "AAP MCP Server Validation", + "name": "mcp-aap-validator", + "summary_markdown": "Validate AAP MCP server configuration and connectivity.\n**Use when:**\n- Validate AAP MCP\n- Check if AAP is configured\n- Verify AAP connection\n- Other skills need to verify AAP MCP server availability\n**What it does:**\n- Checks both AAP MCP servers (job-management, inventory-management)\n- Verifies environment variables (AAP_MCP_SERVER, AAP_API_TOKEN)\n- Tests server connectivity and authentication\n- Reports validation status (PASSED/PARTIAL/FAILED)\n" + }, + { + "description": "Workflow Execution Report", + "name": "execution-summary", + "summary_markdown": "Generate concise execution reports for audit and learning purposes.\n**Use when:**\n- Generate execution summary\n- Create execution report\n- Summarize what was used\n- Show execution summary\n**What it does:**\n- Analyzes conversation history\n- Extracts agents, skills, tools, and docs used\n- Formats in machine-readable format\n- Provides audit trail for workflows\n" + }, + { + "description": "AAP Job Template Creation", + "name": "job-template-creator", + "summary_markdown": "Create AAP job templates for executing Ansible playbooks through Ansible Automation Platform.\n**Use when:**\n- Create a job template for this playbook\n- Set up a template to run remediation playbooks\n- Configure AAP to execute this playbook\n**What it does:**\n- Lists available projects and inventories\n- Provides instructions for template creation (Web UI or API)\n- Verifies template creation\n- Prepares for AAP-based playbook execution\n" + }, + { + "description": "AAP Job Template Remediation Validation", + "name": "job-template-remediation-validator", + "summary_markdown": "Verify an AAP job template meets requirements for executing CVE remediation playbooks.\n**Use when:**\n- Does this job template support remediation playbooks?\n- Validate job template X for CVE remediation\n- Check if template is ready for playbook-executor\n**What it does:**\n- Validates required fields (inventory, project, playbook, credentials, privilege escalation)\n- Checks recommended options (ask variables/limit on launch)\n- Verifies project and inventory exist\n- Reports PASSED / PASSED WITH WARNINGS / FAILED\n" + } + ], + "skills_decision_guide": [ + { + "reason": "Discovers and displays Lightspeed-managed system inventory.", + "skill_to_use": "fleet-inventory", + "user_request": "\"Show the managed fleet\" or \"List RHEL systems\"" + }, + { + "reason": "Analyzes CVE impact across the fleet without immediate remediation.", + "skill_to_use": "cve-impact", + "user_request": "\"What are the most critical CVEs?\" or \"Show CVEs affecting my systems\"" + }, + { + "reason": "Orchestrates full workflow (validate → context → playbook → execute → verify).", + "skill_to_use": "remediation", + "user_request": "\"Remediate CVE-2024-1234 on system abc-123\" or \"Patch these CVEs on production\"" + }, + { + "reason": "Generates Ansible playbook only; use playbook-executor to run it.", + "skill_to_use": "playbook-generator", + "user_request": "\"Create a remediation playbook for CVE-X\" (no execution yet)" + }, + { + "reason": "Validates AAP job template for CVE remediation requirements.", + "skill_to_use": "job-template-remediation-validator", + "user_request": "\"Does this job template support remediation playbooks?\"" + } + ] + }, + "deploy_and_use": "#deploy_and_use.md", + "description": "Site reliability engineering tools and automation for managing Red Hat platforms and infrastructure.", + "documentation_section": "#documentation_section.md", + "homepage": "https://github.com/RHEcosystemAppEng/agentic-collections", + "id": "rh-sre", + "keywords": [ + "sre", + "red-hat", + "platforms", + "products", + "automation" + ], + "legal_resources": { + "license_agreement_url": "https://www.redhat.com/en/about/agreements", + "privacy_policy_url": "https://www.redhat.com/en/about/privacy-policy" + }, + "license": "Apache-2.0", + "marketplaces": [ + "Claude Code", + "Cursor" + ], + "mcp_section": "#mcp_section.md", + "name": "Red Hat SRE Agentic Collection", + "personas": [ + "Site Reliability Engineer" + ], + "provider": "Red Hat", + "repository": "https://github.com/RHEcosystemAppEng/agentic-collections", + "resources": [ + { + "description": "Red Hat Insights and Lightspeed console for fleet and vulnerability management.", + "title": "Red Hat Lightspeed", + "url": "https://console.redhat.com/insights" + }, + { + "description": "Creating remediation plans, playbook generation.", + "embedded_doc": "docs/ansible/cve-remediation-templates.md", + "title": "Red Hat Lightspeed Remediations Guide", + "url": "https://docs.redhat.com/en/documentation/red_hat_lightspeed/1-latest/html-single/red_hat_lightspeed_remediations_guide/index" + }, + { + "description": "MCP server used by this collection; parameter reference.", + "embedded_doc": "docs/references/lightspeed-mcp-parameters.md", + "title": "Red Hat Lightspeed MCP", + "url": "https://github.com/RedHatInsights/insights-mcp" + }, + { + "description": "CVE identification, classification, threat intelligence.", + "embedded_doc": "docs/insights/vulnerability-logic.md", + "title": "Assessing and Monitoring Security Vulnerabilities on RHEL Systems", + "url": "https://docs.redhat.com/en/documentation/red_hat_lightspeed/1-latest/html/assessing_and_monitoring_security_vulnerabilities_on_rhel_systems/vuln-cves_vuln-overview" + }, + { + "description": "DNF commands, updating packages, repository management.", + "embedded_doc": "docs/rhel/package-management.md", + "title": "Managing Software with the DNF Tool (RHEL 9)", + "url": "https://docs.redhat.com/en/documentation/red_hat_enterprise_linux/9/html-single/managing_software_with_the_dnf_tool/index" + }, + { + "description": "Red Hat severity ratings, CVSS usage.", + "embedded_doc": "docs/references/cvss-scoring.md", + "title": "Severity Ratings (Red Hat Customer Portal)", + "url": "https://access.redhat.com/security/updates/classification" + }, + { + "description": "AAP 2.6 docs; projects, job templates, playbook integration.", + "embedded_doc": "docs/ansible/playbook-integration-aap.md", + "title": "Red Hat Ansible Automation Platform Documentation", + "url": "https://docs.redhat.com/en/documentation/red_hat_ansible_automation_platform/2.6" + }, + { + "description": "Job templates, check mode, dry-run execution.", + "embedded_doc": "docs/ansible/aap-job-execution.md", + "title": "AAP Job Execution", + "url": "https://docs.redhat.com/en/documentation/red_hat_ansible_automation_platform/2.6/html/using_automation_execution/controller-job-templates" + }, + { + "description": "AAP product overview for playbook execution.", + "title": "Ansible Automation Platform", + "url": "https://www.redhat.com/en/technologies/management/ansible" + }, + { + "description": "AAP API reference for job and inventory management.", + "title": "AAP REST API Documentation", + "url": "https://docs.redhat.com/en/documentation/red_hat_ansible_automation_platform/" + } + ], + "sample_workflows": [ + { + "name": "Fleet Discovery → CVE Analysis → Remediation", + "workflow": "User: \"Show the managed fleet\"\n- fleet-inventory skill lists all systems\nUser: \"What are the critical CVEs affecting these systems?\"\n- cve-impact skill analyzes vulnerabilities\nUser: \"Remediate CVE-2024-1234 on all RHEL 8 production systems\"\n- remediation skill orchestrates end-to-end remediation\n" + }, + { + "name": "Emergency CVE Patching", + "workflow": "User: \"URGENT: CVE-2024-CRITICAL has CVSS 9.8 - create emergency remediation playbooks for all production systems\"\n- remediation skill:\n - Validates CVE (cve-validation skill)\n - Lists production systems (system-context skill)\n - Generates playbook (playbook-generator skill)\n - Provides execution instructions\n - Offers automated execution option\n" + }, + { + "name": "Batch Remediation with Verification", + "workflow": "User: \"Create and execute remediation playbooks for CVE-X, CVE-Y, CVE-Z on systems server-01, server-02, server-03\"\n- remediation skill:\n - Validates all CVEs\n - Gathers system context\n - Generates consolidated playbook\n - Asks for execution approval\n - Executes and monitors job status\n - Verifies remediation success (remediation-verifier skill)\n" + }, + { + "name": "Account-Level CVE Discovery", + "workflow": "User: \"What are the critical vulnerabilities on my account?\"\n- cve-impact skill with account-level parameters\n- Lists critical CVEs across the fleet, filters by severity and remediation availability\n" + }, + { + "name": "Playbook Execution with Dry-Run", + "workflow": "User: \"Execute the CVE remediation playbook\"\n- playbook-executor skill:\n - Validates AAP prerequisites\n - Lists and selects job template\n - Offers dry-run first (check mode)\n - Proceeds to actual execution after approval\n - Monitors job status and reports results\n" + } + ], + "security_model": "#security_model.md", + "summary": "The rh-sre collection provides skills for site reliability tasks.", + "support_level": "Unknown", + "version": "0.1.0" +} diff --git a/rh-sre/.catalog/collection.yaml b/rh-sre/.catalog/collection.yaml new file mode 100644 index 00000000..29eb9cf3 --- /dev/null +++ b/rh-sre/.catalog/collection.yaml @@ -0,0 +1,316 @@ +# Catalog: maintained via create-collection workflow (assistant + maintainer + PR review). +# Golden sources: skills/*/SKILL.md, README.md, CLAUDE.md, marketplace/rh-agentic-collection.yml +# Do not edit ad hoc — follow COLLECTION_SPEC.md and the create-collection skill. + +id: rh-sre +name: Red Hat SRE Agentic Collection +provider: Red Hat +version: 0.1.0 +categories: +- Site Reliability +- Security +personas: +- Site Reliability Engineer +marketplaces: +- Claude Code +- Cursor +support_level: Unknown +description: Site reliability engineering tools and automation for managing Red Hat platforms and infrastructure. +summary: The rh-sre collection provides skills for site reliability tasks. +contents: + description: | + The pack provides 13 skills for common SRE operations, including one orchestration skill for end-to-end remediation. + skills: + - name: fleet-inventory + description: System Discovery and Fleet Management + summary_markdown: | + Query and display Red Hat Lightspeed managed system inventory. + **Use when:** + - Show the managed fleet + - List all RHEL 8 systems + - What systems are registered in Lightspeed? + **What it does:** + - Retrieves all registered systems + - Groups by RHEL version and environment + - Shows system health and check-in status + - Identifies stale systems + - name: cve-impact + description: CVE Discovery and Risk Assessment + summary_markdown: | + Analyze CVE impact across the fleet without immediate remediation. + **Use when:** + - What are the most critical vulnerabilities? + - Show CVEs affecting my systems + - List high-severity CVEs + **What it does:** + - Lists CVEs by severity (Critical/Important) + - Sorts by CVSS score + - Shows affected system counts + - Provides priority recommendations + - name: cve-validation + description: CVE Verification + summary_markdown: | + Validate CVE existence and remediation availability. + **Use when:** + - Is CVE-2024-1234 valid? + - Does CVE-X have a remediation? + - What's the CVSS score for CVE-Y? + **What it does:** + - Verifies CVE in Red Hat database + - Checks remediation availability + - Returns CVE metadata and severity + - name: system-context + description: System Information Gathering + summary_markdown: | + Collect detailed system information from Red Hat Lightspeed. + **Use when:** + - What systems are affected by CVE-X? + - Show me details for server-01 + - Get system profile for these hosts + **What it does:** + - Retrieves system details + - Shows installed packages + - Displays configuration data + - Maps CVE-to-system relationships + - name: playbook-generator + description: Ansible Playbook Creation + summary_markdown: | + Generate Ansible remediation playbooks following Red Hat best practices. **Only generates playbooks; does not execute them.** Use `/playbook-executor` to run playbooks. + **Use when:** + - Create a remediation playbook for CVE-X + - Generate Ansible playbook to patch CVE-Y + **What it does:** + - Calls Red Hat Lightspeed remediation API + - Generates production-ready Ansible playbooks + - Includes error handling and rollback steps + - Follows Red Hat standards + - name: playbook-executor + description: AAP Playbook Execution + summary_markdown: | + Execute Ansible playbooks via AAP with dry-run, real-time monitoring, and reporting. + **Use when:** + - Execute this remediation playbook + - Run the playbook and monitor status + **What it does:** + - Launches jobs via AAP MCP (job_templates_launch_retrieve) + - Performs Git Flow (commit, push, sync) when playbook path differs from template + - Monitors job status (PENDING → RUNNING → COMPLETED) + - Reports execution results + **Note:** Requires AAP MCP servers configured and job templates created (use job-template-creator skill). + - name: remediation-verifier + description: Remediation Verification + summary_markdown: | + Verify that CVE remediations were successfully applied. + **Use when:** + - Check if CVE-X was patched on server-01 + - Verify remediation status + **What it does:** + - Queries current CVE status + - Verifies package updates + - Confirms remediation success + - name: mcp-lightspeed-validator + description: Lightspeed MCP Server Validation + summary_markdown: | + Validate Red Hat Lightspeed MCP server configuration and connectivity. + **Use when:** + - Validate Lightspeed MCP + - Check if Lightspeed is configured + - Verify Lightspeed connection + - Other skills need to verify lightspeed-mcp availability + **What it does:** + - Checks MCP server configuration in mcps.json + - Verifies environment variables (LIGHTSPEED_CLIENT_ID, LIGHTSPEED_CLIENT_SECRET) + - Tests server connectivity and tool availability + - Reports validation status (PASSED/PARTIAL/FAILED) + - name: mcp-aap-validator + description: AAP MCP Server Validation + summary_markdown: | + Validate AAP MCP server configuration and connectivity. + **Use when:** + - Validate AAP MCP + - Check if AAP is configured + - Verify AAP connection + - Other skills need to verify AAP MCP server availability + **What it does:** + - Checks both AAP MCP servers (job-management, inventory-management) + - Verifies environment variables (AAP_MCP_SERVER, AAP_API_TOKEN) + - Tests server connectivity and authentication + - Reports validation status (PASSED/PARTIAL/FAILED) + - name: execution-summary + description: Workflow Execution Report + summary_markdown: | + Generate concise execution reports for audit and learning purposes. + **Use when:** + - Generate execution summary + - Create execution report + - Summarize what was used + - Show execution summary + **What it does:** + - Analyzes conversation history + - Extracts agents, skills, tools, and docs used + - Formats in machine-readable format + - Provides audit trail for workflows + - name: job-template-creator + description: AAP Job Template Creation + summary_markdown: | + Create AAP job templates for executing Ansible playbooks through Ansible Automation Platform. + **Use when:** + - Create a job template for this playbook + - Set up a template to run remediation playbooks + - Configure AAP to execute this playbook + **What it does:** + - Lists available projects and inventories + - Provides instructions for template creation (Web UI or API) + - Verifies template creation + - Prepares for AAP-based playbook execution + - name: job-template-remediation-validator + description: AAP Job Template Remediation Validation + summary_markdown: | + Verify an AAP job template meets requirements for executing CVE remediation playbooks. + **Use when:** + - Does this job template support remediation playbooks? + - Validate job template X for CVE remediation + - Check if template is ready for playbook-executor + **What it does:** + - Validates required fields (inventory, project, playbook, credentials, privilege escalation) + - Checks recommended options (ask variables/limit on launch) + - Verifies project and inventory exist + - Reports PASSED / PASSED WITH WARNINGS / FAILED + orchestration_skills: + - name: remediation + description: End-to-End CVE Remediation + summary_markdown: | + The remediation skill orchestrates 6 specialized skills to provide complete CVE remediation workflows. + **Use when:** + - Remediate CVE-2024-1234 on system abc-123 + - Create and execute a remediation playbook for CVE-X + - Patch these 5 CVEs on all production servers + **Workflow:** + 0. Validate MCP (mcp-lightspeed-validator, mcp-aap-validator) + 1. Impact (cve-impact skill, if needed) + 2. Validate CVE (cve-validation skill) + 3. Gather Context (system-context skill) + 4. Generate Playbook (playbook-generator skill) + 5. Execute (playbook-executor skill, with user confirmation) + 6. Verify (remediation-verifier skill) + **Capabilities:** + - Single CVE on single system + - Batch remediation (multiple CVEs, multiple systems) + - Cross-environment patching (dev → staging → prod) + - Automated job tracking and reporting + - Partial failure handling + skills_decision_guide: + - user_request: '"Show the managed fleet" or "List RHEL systems"' + skill_to_use: fleet-inventory + reason: Discovers and displays Lightspeed-managed system inventory. + - user_request: '"What are the most critical CVEs?" or "Show CVEs affecting my systems"' + skill_to_use: cve-impact + reason: Analyzes CVE impact across the fleet without immediate remediation. + - user_request: '"Remediate CVE-2024-1234 on system abc-123" or "Patch these CVEs on production"' + skill_to_use: remediation + reason: Orchestrates full workflow (validate → context → playbook → execute → verify). + - user_request: '"Create a remediation playbook for CVE-X" (no execution yet)' + skill_to_use: playbook-generator + reason: Generates Ansible playbook only; use playbook-executor to run it. + - user_request: '"Does this job template support remediation playbooks?"' + skill_to_use: job-template-remediation-validator + reason: Validates AAP job template for CVE remediation requirements. +deploy_and_use: '#deploy_and_use.md' +sample_workflows: +- name: Fleet Discovery → CVE Analysis → Remediation + workflow: | + User: "Show the managed fleet" + - fleet-inventory skill lists all systems + User: "What are the critical CVEs affecting these systems?" + - cve-impact skill analyzes vulnerabilities + User: "Remediate CVE-2024-1234 on all RHEL 8 production systems" + - remediation skill orchestrates end-to-end remediation +- name: Emergency CVE Patching + workflow: | + User: "URGENT: CVE-2024-CRITICAL has CVSS 9.8 - create emergency remediation playbooks for all production systems" + - remediation skill: + - Validates CVE (cve-validation skill) + - Lists production systems (system-context skill) + - Generates playbook (playbook-generator skill) + - Provides execution instructions + - Offers automated execution option +- name: Batch Remediation with Verification + workflow: | + User: "Create and execute remediation playbooks for CVE-X, CVE-Y, CVE-Z on systems server-01, server-02, server-03" + - remediation skill: + - Validates all CVEs + - Gathers system context + - Generates consolidated playbook + - Asks for execution approval + - Executes and monitors job status + - Verifies remediation success (remediation-verifier skill) +- name: Account-Level CVE Discovery + workflow: | + User: "What are the critical vulnerabilities on my account?" + - cve-impact skill with account-level parameters + - Lists critical CVEs across the fleet, filters by severity and remediation availability +- name: Playbook Execution with Dry-Run + workflow: | + User: "Execute the CVE remediation playbook" + - playbook-executor skill: + - Validates AAP prerequisites + - Lists and selects job template + - Offers dry-run first (check mode) + - Proceeds to actual execution after approval + - Monitors job status and reports results +resources: +- title: Red Hat Lightspeed + url: https://console.redhat.com/insights + description: Red Hat Insights and Lightspeed console for fleet and vulnerability management. +- title: Red Hat Lightspeed Remediations Guide + url: https://docs.redhat.com/en/documentation/red_hat_lightspeed/1-latest/html-single/red_hat_lightspeed_remediations_guide/index + description: Creating remediation plans, playbook generation. + embedded_doc: docs/ansible/cve-remediation-templates.md +- title: Red Hat Lightspeed MCP + url: https://github.com/RedHatInsights/insights-mcp + description: MCP server used by this collection; parameter reference. + embedded_doc: docs/references/lightspeed-mcp-parameters.md +- title: Assessing and Monitoring Security Vulnerabilities on RHEL Systems + url: https://docs.redhat.com/en/documentation/red_hat_lightspeed/1-latest/html/assessing_and_monitoring_security_vulnerabilities_on_rhel_systems/vuln-cves_vuln-overview + description: CVE identification, classification, threat intelligence. + embedded_doc: docs/insights/vulnerability-logic.md +- title: Managing Software with the DNF Tool (RHEL 9) + url: https://docs.redhat.com/en/documentation/red_hat_enterprise_linux/9/html-single/managing_software_with_the_dnf_tool/index + description: DNF commands, updating packages, repository management. + embedded_doc: docs/rhel/package-management.md +- title: Severity Ratings (Red Hat Customer Portal) + url: https://access.redhat.com/security/updates/classification + description: Red Hat severity ratings, CVSS usage. + embedded_doc: docs/references/cvss-scoring.md +- title: Red Hat Ansible Automation Platform Documentation + url: https://docs.redhat.com/en/documentation/red_hat_ansible_automation_platform/2.6 + description: AAP 2.6 docs; projects, job templates, playbook integration. + embedded_doc: docs/ansible/playbook-integration-aap.md +- title: AAP Job Execution + url: https://docs.redhat.com/en/documentation/red_hat_ansible_automation_platform/2.6/html/using_automation_execution/controller-job-templates + description: Job templates, check mode, dry-run execution. + embedded_doc: docs/ansible/aap-job-execution.md +- title: Ansible Automation Platform + url: https://www.redhat.com/en/technologies/management/ansible + description: AAP product overview for playbook execution. +- title: AAP REST API Documentation + url: https://docs.redhat.com/en/documentation/red_hat_ansible_automation_platform/ + description: AAP API reference for job and inventory management. +legal_resources: + license_agreement_url: https://www.redhat.com/en/about/agreements + privacy_policy_url: https://www.redhat.com/en/about/privacy-policy +author: + name: Red Hat Ecosystem Engineering + email: eco-engineering@redhat.com +homepage: https://github.com/RHEcosystemAppEng/agentic-collections +repository: https://github.com/RHEcosystemAppEng/agentic-collections +license: Apache-2.0 +keywords: +- sre +- red-hat +- platforms +- products +- automation +documentation_section: '#documentation_section.md' +mcp_section: '#mcp_section.md' +security_model: '#security_model.md' diff --git a/rh-sre/.catalog/deploy_and_use.md b/rh-sre/.catalog/deploy_and_use.md new file mode 100644 index 00000000..ab05de82 --- /dev/null +++ b/rh-sre/.catalog/deploy_and_use.md @@ -0,0 +1,52 @@ + + +### Prerequisites + +- Claude Code CLI or IDE extension (if using Claude Code) +- Podman or Docker installed (for container-based MCP servers) +- Red Hat Lightspeed service account ([console](https://console.redhat.com/)) + +### Environment setup + +Configure Red Hat Lightspeed credentials (names must match **`mcps.json`**): + +```bash +export LIGHTSPEED_CLIENT_ID="your-service-account-client-id" +export LIGHTSPEED_CLIENT_SECRET="your-service-account-client-secret" +``` + +For Ansible Automation Platform MCP (optional, for playbook execution flows): + +```bash +export AAP_MCP_SERVER="your-aap-controller-hostname" +export AAP_API_TOKEN="your-api-token" +``` + +### Installation (Lola) + +From a checkout of this repository, install the pack with [Lola](https://github.com/RedHatProductSecurity/lola) using the registry file at the repo root: + +```bash +lola install -f rh-sre +``` + +The module is declared in **`marketplace/rh-agentic-collection.yml`** (`path: rh-sre`). See the root [README.md](../../README.md) for marketplace setup. + +### Installation (Claude Code) + +```bash +lola install -f rh-sre -a claude-code +``` + +### Installation (Cursor) + +```bash +lola install -f rh-sre -a cursor +``` + +### MCP configuration + +Server definitions live in **`mcps.json`** at the pack root. Use **`${VAR}`** placeholders only; never commit secrets. diff --git a/rh-sre/.catalog/documentation_section.md b/rh-sre/.catalog/documentation_section.md new file mode 100644 index 00000000..fa32b1fa --- /dev/null +++ b/rh-sre/.catalog/documentation_section.md @@ -0,0 +1,20 @@ + + +### Why use this collection instead of calling MCP tools directly? + +- **Reliability** — Skills apply validation gates (CVE IDs, inventory, AAP connectivity) before expensive operations. +- **Safety** — Human-in-the-loop for remediation plans, playbook execution, and broad job launches. +- **Consistency** — Documented workflows, error handling, and follow-up skills (for example `/remediation` vs ad hoc tool calls). +- **Troubleshooting** — Skills bundle recovery paths; use `/mcp-lightspeed-validator` and `/mcp-aap-validator` when prerequisites fail. + +### In-repository documentation + +This pack ships an AI-oriented knowledge base under **`docs/`**. Start at **[docs/INDEX.md](docs/INDEX.md)** and use **`docs/.ai-index/`** (semantic index, task mapping) for token-efficient discovery. + +### Configuration and architecture + +- Environment variables for Lightspeed and AAP are declared only as `${VAR}` placeholders in **`mcps.json`**. +- Orchestration (**`/remediation`**) chains impact, validation, context, playbook generation, execution, and verification; see pack **CLAUDE.md** for routing when you need a single step only. diff --git a/rh-sre/.catalog/mcp_section.md b/rh-sre/.catalog/mcp_section.md new file mode 100644 index 00000000..7f20179c --- /dev/null +++ b/rh-sre/.catalog/mcp_section.md @@ -0,0 +1,12 @@ + + +| Server | Role | +|--------|------| +| **lightspeed-mcp** | CVEs, inventory, remediation inputs, playbook-related Lightspeed workflows. | +| **aap-mcp-job-management** | Job templates, projects, launches, execution status. | +| **aap-mcp-inventory-management** | Inventories and hosts for execution planning. | + +Configure servers through **`mcps.json`**; skills must be invoked instead of calling MCP tools directly from the agent. diff --git a/rh-sre/.catalog/security_model.md b/rh-sre/.catalog/security_model.md new file mode 100644 index 00000000..8b1be467 --- /dev/null +++ b/rh-sre/.catalog/security_model.md @@ -0,0 +1,8 @@ + + +- Do **not** expose `LIGHTSPEED_CLIENT_ID`, `LIGHTSPEED_CLIENT_SECRET`, AAP tokens, or any API credentials in chat—only whether they appear configured. +- Require explicit user approval before running remediation playbooks or destructive changes at scale. +- Prefer **`/remediation`** for end-to-end CVE response so validation and verification steps are not skipped accidentally. diff --git a/rh-virt/.catalog/collection.json b/rh-virt/.catalog/collection.json new file mode 100644 index 00000000..a0d073d6 --- /dev/null +++ b/rh-virt/.catalog/collection.json @@ -0,0 +1,157 @@ +{ + "author": { + "email": "eco-engineering@redhat.com", + "name": "Red Hat Ecosystem Engineering" + }, + "categories": [ + "Red Hat", + "Kubevirt", + "Openshift", + "Virtualization", + "Virt" + ], + "contents": { + "description": "The pack provides 10 skills for rh virt workflows on Red Hat platforms; see CLAUDE.md for intent routing.\n", + "orchestration_skills": [], + "skills": [ + { + "description": "Clone existing virtual machines for testing, scaling, or creating templates.", + "name": "vm-clone", + "summary_markdown": "Clone existing virtual machines for testing, scaling, or creating templates.\n**Use when:**\n- \"Clone VM [source] to [target]\"\n- \"Create a copy of VM [name]\"\n- \"Duplicate VM [name] for testing\"\n- \"Create 3 copies of template-vm\"\n**What it does:**\n- Runs the documented workflow with MCP access only through the skill and required confirmations.\n- Aligns with CLAUDE.md chaining when users need follow-on skills.\n" + }, + { + "description": "Create new virtual machines in OpenShift Virtualization with automatic instance type resolution and OS selection.", + "name": "vm-create", + "summary_markdown": "Create new virtual machines in OpenShift Virtualization with automatic instance type resolution and OS selection.\n**Use when:**\n- \"Create a new VM\"\n- \"Deploy a virtual machine with [OS]\"\n- \"Set up a VM in namespace [name]\"\n- \"Provision a [size] VM\"\n**What it does:**\n- Runs the documented workflow with MCP access only through the skill and required confirmations.\n- Aligns with CLAUDE.md chaining when users need follow-on skills.\n" + }, + { + "description": "Permanently delete virtual machines and their associated resources from OpenShift Virtualization.", + "name": "vm-delete", + "summary_markdown": "Permanently delete virtual machines and their associated resources from OpenShift Virtualization.\n**Use when:**\n- \"Delete VM [name]\"\n- \"Remove virtual machine [name]\"\n- \"Destroy VM [name]\"\n- \"Clean up VM [name]\"\n**What it does:**\n- Runs the documented workflow with MCP access only through the skill and required confirmations.\n- Aligns with CLAUDE.md chaining when users need follow-on skills.\n" + }, + { + "description": "List and view virtual machines across namespaces with status, resource usage, and health information.", + "name": "vm-inventory", + "summary_markdown": "List and view virtual machines across namespaces with status, resource usage, and health information.\n**Use when:**\n- \"List all VMs\"\n- \"Show VMs in namespace [name]\"\n- \"What VMs are running?\"\n- \"Get details of VM [name]\"\n**What it does:**\n- Runs the documented workflow with MCP access only through the skill and required confirmations.\n- Aligns with CLAUDE.md chaining when users need follow-on skills.\n" + }, + { + "description": "Manage virtual machine lifecycle operations including start, stop, and restart.", + "name": "vm-lifecycle-manager", + "summary_markdown": "Manage virtual machine lifecycle operations including start, stop, and restart.\n**Use when:**\n- \"Start VM [name]\"\n- \"Stop the virtual machine [name]\"\n- \"Restart VM [name]\"\n- \"Power on/off VM [name]\"\n**What it does:**\n- Runs the documented workflow with MCP access only through the skill and required confirmations.\n- Aligns with CLAUDE.md chaining when users need follow-on skills.\n" + }, + { + "description": "Orchestrate VM migrations across cluster nodes for load balancing, maintenance, and resource optimization.", + "name": "vm-rebalance", + "summary_markdown": "Orchestrate VM migrations across cluster nodes for load balancing, maintenance, and resource optimization.\n**Use when:**\n- \"Move VM database-01 to worker-03\"\n- \"Rebalance VMs to optimize CPU load\"\n- \"Drain worker-02 for maintenance\"\n- \"Automatically rebalance the cluster\"\n**What it does:**\n- Runs the documented workflow with MCP access only through the skill and required confirmations.\n- Aligns with CLAUDE.md chaining when users need follow-on skills.\n" + }, + { + "description": "Create virtual machine snapshots for backup and recovery.", + "name": "vm-snapshot-create", + "summary_markdown": "Create virtual machine snapshots for backup and recovery.\n**Use when:**\n- \"Create a snapshot of VM [name]\"\n- \"Backup VM [name] before upgrade\"\n- \"Take a snapshot of [vm]\"\n**What it does:**\n- Runs the documented workflow with MCP access only through the skill and required confirmations.\n- Aligns with CLAUDE.md chaining when users need follow-on skills.\n" + }, + { + "description": "Permanently delete virtual machine snapshots to free storage space.", + "name": "vm-snapshot-delete", + "summary_markdown": "Permanently delete virtual machine snapshots to free storage space.\n**Use when:**\n- \"Delete snapshot [snapshot-name]\"\n- \"Remove old snapshots for VM [name]\"\n- \"Free up snapshot storage\"\n**What it does:**\n- Runs the documented workflow with MCP access only through the skill and required confirmations.\n- Aligns with CLAUDE.md chaining when users need follow-on skills.\n" + }, + { + "description": "List virtual machine snapshots across namespaces with status, age, and recovery information.", + "name": "vm-snapshot-list", + "summary_markdown": "List virtual machine snapshots across namespaces with status, age, and recovery information.\n**Use when:**\n- \"List snapshots for VM [name]\"\n- \"Show snapshots in namespace [name]\"\n- \"What snapshots exist for [vm]?\"\n**What it does:**\n- Runs the documented workflow with MCP access only through the skill and required confirmations.\n- Aligns with CLAUDE.md chaining when users need follow-on skills.\n" + }, + { + "description": "Restore virtual machines from snapshots with strict safety confirmations to prevent data loss.", + "name": "vm-snapshot-restore", + "summary_markdown": "Restore virtual machines from snapshots with strict safety confirmations to prevent data loss.\n**Use when:**\n- \"Restore VM [name] from snapshot [snapshot-name]\"\n- \"Roll back VM [name] to snapshot\"\n- \"Recover VM [name] from backup\"\n**What it does:**\n- Runs the documented workflow with MCP access only through the skill and required confirmations.\n- Aligns with CLAUDE.md chaining when users need follow-on skills.\n" + } + ], + "skills_decision_guide": [ + { + "reason": "Instance types, OS selection, and OpenShift Virtualization CRs.", + "skill_to_use": "vm-create", + "user_request": "\"Create VM\"" + }, + { + "reason": "Namespace-scoped inventory and status.", + "skill_to_use": "vm-inventory", + "user_request": "\"List VMs\"" + }, + { + "reason": "Validated snapshot creation for recovery points.", + "skill_to_use": "vm-snapshot-create", + "user_request": "\"Snapshot\" backup" + }, + { + "reason": "Stop VM and restore with confirmations.", + "skill_to_use": "vm-snapshot-restore", + "user_request": "\"Restore snapshot\"" + }, + { + "reason": "Migrations for load and maintenance.", + "skill_to_use": "vm-rebalance", + "user_request": "\"Rebalance\" or \"drain node\"" + } + ] + }, + "deploy_and_use": "#deploy_and_use.md", + "description": "Virtual machine management and automation for OpenShift Virtualization and KubeVirt workloads.", + "homepage": "https://github.com/RHEcosystemAppEng/agentic-collections", + "id": "openshift-virtualization", + "keywords": [ + "kubevirt", + "openshift-virtualization", + "vm", + "migration", + "snapshot" + ], + "legal_resources": { + "license_agreement_url": "https://www.redhat.com/en/about/agreements", + "privacy_policy_url": "https://www.redhat.com/en/about/privacy-policy" + }, + "license": "Apache-2.0", + "marketplaces": [ + "Claude Code", + "Cursor" + ], + "mcp_section": "#mcp_section.md", + "name": "Red Hat OpenShift Virtualization Agentic Collection", + "personas": [ + "Red Hat platform engineer" + ], + "provider": "Red Hat", + "repository": "https://github.com/RHEcosystemAppEng/agentic-collections", + "resources": [ + { + "description": "Official docs for VMs, storage, and live migration.", + "title": "OpenShift Virtualization", + "url": "https://docs.redhat.com/en/documentation/openshift_container_platform/latest/html/virtualization/" + }, + { + "description": "KubeVirt concepts underlying OpenShift Virtualization.", + "title": "KubeVirt user guide", + "url": "https://kubevirt.io/user-guide/" + }, + { + "description": "Source for this pack and catalog metadata.", + "title": "agentic-collections repository", + "url": "https://github.com/RHEcosystemAppEng/agentic-collections" + } + ], + "sample_workflows": [ + { + "name": "Create and verify VM", + "workflow": "User: \"Create a small RHEL VM in my team namespace\"\n- `/vm-create` resolves instance type and OS and applies the VirtualMachine spec with approval\n- `/vm-inventory` confirms the VM is running with expected resources\n" + }, + { + "name": "Snapshot before change", + "workflow": "User: \"Snapshot database-vm before the maintenance window\"\n- `/vm-snapshot-create` validates storage class and guest agent readiness\n- `/vm-lifecycle-manager` stops the VM if the restore path requires it later\n" + }, + { + "name": "Maintenance drain", + "workflow": "User: \"Drain worker-04 and move VMs safely\"\n- `/vm-rebalance` plans migrations for load or node maintenance\n- `/vm-inventory` verifies placement after moves complete\n" + } + ], + "summary": "The rh-virt collection ships 10 skills for OpenShift Virtualization operations with confirmations on destructive steps.\n", + "support_level": "Unknown", + "version": "0.1.0" +} diff --git a/rh-virt/.catalog/collection.yaml b/rh-virt/.catalog/collection.yaml new file mode 100644 index 00000000..4a68c6fb --- /dev/null +++ b/rh-virt/.catalog/collection.yaml @@ -0,0 +1,203 @@ +# Catalog: maintained via create-collection workflow (assistant + maintainer + PR review). +# Golden sources: skills/*/SKILL.md, README.md, CLAUDE.md, marketplace/rh-agentic-collection.yml +# Do not edit ad hoc — follow COLLECTION_SPEC.md and the create-collection skill. + +id: openshift-virtualization +name: Red Hat OpenShift Virtualization Agentic Collection +provider: Red Hat +version: 0.1.0 +categories: +- Red Hat +- Kubevirt +- Openshift +- Virtualization +- Virt +personas: +- Red Hat platform engineer +marketplaces: +- Claude Code +- Cursor +support_level: Unknown +description: "Virtual machine management and automation for OpenShift Virtualization and KubeVirt workloads." +summary: | + The rh-virt collection ships 10 skills for OpenShift Virtualization operations with confirmations on destructive steps. +contents: + description: | + The pack provides 10 skills for rh virt workflows on Red Hat platforms; see CLAUDE.md for intent routing. + skills: + - name: vm-clone + description: "Clone existing virtual machines for testing, scaling, or creating templates." + summary_markdown: | + Clone existing virtual machines for testing, scaling, or creating templates. + **Use when:** + - "Clone VM [source] to [target]" + - "Create a copy of VM [name]" + - "Duplicate VM [name] for testing" + - "Create 3 copies of template-vm" + **What it does:** + - Runs the documented workflow with MCP access only through the skill and required confirmations. + - Aligns with CLAUDE.md chaining when users need follow-on skills. + - name: vm-create + description: "Create new virtual machines in OpenShift Virtualization with automatic instance type resolution and OS selection." + summary_markdown: | + Create new virtual machines in OpenShift Virtualization with automatic instance type resolution and OS selection. + **Use when:** + - "Create a new VM" + - "Deploy a virtual machine with [OS]" + - "Set up a VM in namespace [name]" + - "Provision a [size] VM" + **What it does:** + - Runs the documented workflow with MCP access only through the skill and required confirmations. + - Aligns with CLAUDE.md chaining when users need follow-on skills. + - name: vm-delete + description: "Permanently delete virtual machines and their associated resources from OpenShift Virtualization." + summary_markdown: | + Permanently delete virtual machines and their associated resources from OpenShift Virtualization. + **Use when:** + - "Delete VM [name]" + - "Remove virtual machine [name]" + - "Destroy VM [name]" + - "Clean up VM [name]" + **What it does:** + - Runs the documented workflow with MCP access only through the skill and required confirmations. + - Aligns with CLAUDE.md chaining when users need follow-on skills. + - name: vm-inventory + description: "List and view virtual machines across namespaces with status, resource usage, and health information." + summary_markdown: | + List and view virtual machines across namespaces with status, resource usage, and health information. + **Use when:** + - "List all VMs" + - "Show VMs in namespace [name]" + - "What VMs are running?" + - "Get details of VM [name]" + **What it does:** + - Runs the documented workflow with MCP access only through the skill and required confirmations. + - Aligns with CLAUDE.md chaining when users need follow-on skills. + - name: vm-lifecycle-manager + description: "Manage virtual machine lifecycle operations including start, stop, and restart." + summary_markdown: | + Manage virtual machine lifecycle operations including start, stop, and restart. + **Use when:** + - "Start VM [name]" + - "Stop the virtual machine [name]" + - "Restart VM [name]" + - "Power on/off VM [name]" + **What it does:** + - Runs the documented workflow with MCP access only through the skill and required confirmations. + - Aligns with CLAUDE.md chaining when users need follow-on skills. + - name: vm-rebalance + description: "Orchestrate VM migrations across cluster nodes for load balancing, maintenance, and resource optimization." + summary_markdown: | + Orchestrate VM migrations across cluster nodes for load balancing, maintenance, and resource optimization. + **Use when:** + - "Move VM database-01 to worker-03" + - "Rebalance VMs to optimize CPU load" + - "Drain worker-02 for maintenance" + - "Automatically rebalance the cluster" + **What it does:** + - Runs the documented workflow with MCP access only through the skill and required confirmations. + - Aligns with CLAUDE.md chaining when users need follow-on skills. + - name: vm-snapshot-create + description: "Create virtual machine snapshots for backup and recovery." + summary_markdown: | + Create virtual machine snapshots for backup and recovery. + **Use when:** + - "Create a snapshot of VM [name]" + - "Backup VM [name] before upgrade" + - "Take a snapshot of [vm]" + **What it does:** + - Runs the documented workflow with MCP access only through the skill and required confirmations. + - Aligns with CLAUDE.md chaining when users need follow-on skills. + - name: vm-snapshot-delete + description: "Permanently delete virtual machine snapshots to free storage space." + summary_markdown: | + Permanently delete virtual machine snapshots to free storage space. + **Use when:** + - "Delete snapshot [snapshot-name]" + - "Remove old snapshots for VM [name]" + - "Free up snapshot storage" + **What it does:** + - Runs the documented workflow with MCP access only through the skill and required confirmations. + - Aligns with CLAUDE.md chaining when users need follow-on skills. + - name: vm-snapshot-list + description: "List virtual machine snapshots across namespaces with status, age, and recovery information." + summary_markdown: | + List virtual machine snapshots across namespaces with status, age, and recovery information. + **Use when:** + - "List snapshots for VM [name]" + - "Show snapshots in namespace [name]" + - "What snapshots exist for [vm]?" + **What it does:** + - Runs the documented workflow with MCP access only through the skill and required confirmations. + - Aligns with CLAUDE.md chaining when users need follow-on skills. + - name: vm-snapshot-restore + description: "Restore virtual machines from snapshots with strict safety confirmations to prevent data loss." + summary_markdown: | + Restore virtual machines from snapshots with strict safety confirmations to prevent data loss. + **Use when:** + - "Restore VM [name] from snapshot [snapshot-name]" + - "Roll back VM [name] to snapshot" + - "Recover VM [name] from backup" + **What it does:** + - Runs the documented workflow with MCP access only through the skill and required confirmations. + - Aligns with CLAUDE.md chaining when users need follow-on skills. + orchestration_skills: [] + skills_decision_guide: + - user_request: "\"Create VM\"" + skill_to_use: vm-create + reason: "Instance types, OS selection, and OpenShift Virtualization CRs." + - user_request: "\"List VMs\"" + skill_to_use: vm-inventory + reason: "Namespace-scoped inventory and status." + - user_request: "\"Snapshot\" backup" + skill_to_use: vm-snapshot-create + reason: "Validated snapshot creation for recovery points." + - user_request: "\"Restore snapshot\"" + skill_to_use: vm-snapshot-restore + reason: "Stop VM and restore with confirmations." + - user_request: "\"Rebalance\" or \"drain node\"" + skill_to_use: vm-rebalance + reason: "Migrations for load and maintenance." +mcp_section: '#mcp_section.md' +deploy_and_use: '#deploy_and_use.md' +sample_workflows: +- name: "Create and verify VM" + workflow: | + User: "Create a small RHEL VM in my team namespace" + - `/vm-create` resolves instance type and OS and applies the VirtualMachine spec with approval + - `/vm-inventory` confirms the VM is running with expected resources +- name: "Snapshot before change" + workflow: | + User: "Snapshot database-vm before the maintenance window" + - `/vm-snapshot-create` validates storage class and guest agent readiness + - `/vm-lifecycle-manager` stops the VM if the restore path requires it later +- name: "Maintenance drain" + workflow: | + User: "Drain worker-04 and move VMs safely" + - `/vm-rebalance` plans migrations for load or node maintenance + - `/vm-inventory` verifies placement after moves complete +resources: +- title: "OpenShift Virtualization" + url: https://docs.redhat.com/en/documentation/openshift_container_platform/latest/html/virtualization/ + description: "Official docs for VMs, storage, and live migration." +- title: "KubeVirt user guide" + url: https://kubevirt.io/user-guide/ + description: "KubeVirt concepts underlying OpenShift Virtualization." +- title: "agentic-collections repository" + url: https://github.com/RHEcosystemAppEng/agentic-collections + description: "Source for this pack and catalog metadata." +legal_resources: + license_agreement_url: https://www.redhat.com/en/about/agreements + privacy_policy_url: https://www.redhat.com/en/about/privacy-policy +author: + name: Red Hat Ecosystem Engineering + email: eco-engineering@redhat.com +homepage: https://github.com/RHEcosystemAppEng/agentic-collections +repository: https://github.com/RHEcosystemAppEng/agentic-collections +license: Apache-2.0 +keywords: +- kubevirt +- openshift-virtualization +- vm +- migration +- snapshot diff --git a/rh-virt/.catalog/deploy_and_use.md b/rh-virt/.catalog/deploy_and_use.md new file mode 100644 index 00000000..a2823863 --- /dev/null +++ b/rh-virt/.catalog/deploy_and_use.md @@ -0,0 +1,57 @@ + + +### Prerequisites + +- Claude Code CLI or IDE extension (if using Claude Code) +- Podman (or Docker) for the container-based MCP server defined in **`mcps.json`** +- OpenShift cluster (**>= 4.19**) with the **OpenShift Virtualization** operator installed +- A kubeconfig with RBAC sufficient for VirtualMachine and related KubeVirt resources in target namespaces + +### Environment setup + +Point **`KUBECONFIG`** at a kubeconfig file the MCP container can read (names must match **`mcps.json`**): + +```bash +export KUBECONFIG="/path/to/your/kubeconfig" +``` + +Verify the API sees KubeVirt / VM objects (optional smoke check): + +```bash +oc get virtualmachines -A +# or +kubectl get vms -A +``` + +The pack **`mcps.json`** mounts `${KUBECONFIG}` read-only into the MCP container and passes **`${KUBECONFIG}`** in `env` — use placeholders only in git; never commit kubeconfig contents or secrets. + +If you build the OpenShift MCP image locally instead of pulling a published image, follow **Building the MCP Server Container Image** in the pack **[README.md](../../README.md)**. + +### Installation (Lola) + +From a checkout of this repository, install the pack with [Lola](https://github.com/RedHatProductSecurity/lola): + +```bash +lola install -f rh-virt +``` + +The module is declared in **`marketplace/rh-agentic-collection.yml`** (`path: rh-virt`). See the root [README.md](../../README.md) for marketplace setup. + +### Installation (Claude Code) + +```bash +lola install -f rh-virt -a claude-code +``` + +### Installation (Cursor) + +```bash +lola install -f rh-virt -a cursor +``` + +### MCP configuration + +Server definitions live in **`mcps.json`** at the pack root (`openshift-virtualization` server, **`--toolsets`** includes **`kubevirt`**). Use **`${VAR}`** placeholders only; never commit secrets. diff --git a/rh-virt/.catalog/mcp_section.md b/rh-virt/.catalog/mcp_section.md new file mode 100644 index 00000000..0ae104a3 --- /dev/null +++ b/rh-virt/.catalog/mcp_section.md @@ -0,0 +1,10 @@ + + +| Server | Role | +|--------|------| +| **openshift-virtualization** | KubeVirt and OpenShift Virtualization VM, snapshot, and migration workflows via the Kubernetes/OpenShift API. | + +Configure servers through **`mcps.json`** (e.g. **`KUBECONFIG`**); skills must be invoked instead of calling MCP tools directly from the agent. diff --git a/scripts/bootstrap_catalog.py b/scripts/bootstrap_catalog.py new file mode 100644 index 00000000..a427eff8 --- /dev/null +++ b/scripts/bootstrap_catalog.py @@ -0,0 +1,202 @@ +#!/usr/bin/env python3 +""" +Bootstrap /.catalog/collection.yaml for every union-registry pack (initial CI-friendly content). + +Intended for first-time repo setup; refine catalogs via the create-collection skill and PRs. +Does not modify README, SKILL, CLAUDE, or marketplace files. +""" + +from __future__ import annotations + +import argparse +import sys +from pathlib import Path +from typing import Any, Dict, List, Tuple + +import yaml + +import pack_registry +from generate_pack_data import parse_yaml_frontmatter + +REPO_ROOT = Path(__file__).resolve().parent.parent + +CATALOG_YAML_BANNER = """# Catalog: maintained via create-collection workflow (assistant + maintainer + PR review). +# Golden sources: skills/*/SKILL.md, README.md, CLAUDE.md, marketplace/rh-agentic-collection.yml +# Do not edit ad hoc — follow COLLECTION_SPEC.md and the create-collection skill. +""" + +PACK_CATALOG_IDS = { + "rh-virt": "openshift-virtualization", + "ocp-admin": "openshift-administration", +} + + +def _flatten_description(desc: Any) -> str: + if desc is None: + return "" + if isinstance(desc, list): + desc = "\n".join(str(x) for x in desc) + return " ".join(str(desc).split()) + + +def _is_orchestration(fm: Dict[str, Any]) -> bool: + d = _flatten_description(fm.get("description")).lower() + if "orchestrat" in d: + return True + meta = fm.get("metadata") or {} + if isinstance(meta, dict): + coll = meta.get("collection") + if isinstance(coll, dict) and str(coll.get("role", "")).lower() == "orchestration": + return True + return False + + +def _skill_entries(pack_dir: str, root: Path) -> Tuple[List[Dict[str, Any]], List[Dict[str, Any]]]: + regular: List[Dict[str, Any]] = [] + orch: List[Dict[str, Any]] = [] + skills_dir = root / pack_dir / "skills" + if not skills_dir.is_dir(): + return regular, orch + for skill_md in sorted(skills_dir.glob("*/SKILL.md")): + fm = parse_yaml_frontmatter(skill_md) + dirname = skill_md.parent.name + # Catalog skill name must match directory name (roster parity / compliance). + name = dirname + desc = _flatten_description(fm.get("description")) + if len(desc) > 220: + desc = desc[:217] + "..." + sm = ( + f"**Use when:** See the skill description and CLAUDE.md intent routing.\n\n" + f"**What it does:** {desc or 'See SKILL.md for workflow and prerequisites.'}" + ) + entry = {"name": name, "description": desc or f"Skill `{name}` in pack `{pack_dir}`.", "summary_markdown": sm} + if _is_orchestration(fm): + orch.append(entry) + else: + regular.append(entry) + return regular, orch + + +def _decision_rows(pack_dir: str, regular: List[Dict[str, Any]], orch: List[Dict[str, Any]]) -> List[Dict[str, str]]: + rows: List[Dict[str, str]] = [] + for s in (orch + regular)[:5]: + rows.append( + { + "user_request": f'User: "I need help related to {s["name"]}"', + "skill_to_use": s["name"], + "reason": f"Use `{s['name']}` for workflows described in that skill and in CLAUDE.md.", + } + ) + return rows + + +def build_collection_data(pack_dir: str, root: Path) -> Dict[str, Any]: + mod = pack_registry.load_marketplace_module_by_path(pack_dir, root) + title = pack_registry.load_plugin_title(pack_dir, root) or (mod or {}).get("name") or pack_dir + version = (mod or {}).get("version") or "0.1.0" + mod_desc = _flatten_description((mod or {}).get("description")) or f"Agentic collection `{pack_dir}`." + tags = (mod or {}).get("tags") or [] + categories: List[str] = [] + seen_cat: set[str] = set() + for t in tags: + c = str(t).replace("-", " ").strip().title() + if c and c not in seen_cat: + seen_cat.add(c) + categories.append(c) + if len(categories) >= 6: + break + if not categories: + categories = ["Red Hat", "Automation"] + personas = ["Red Hat platform engineer"] + regular, orch = _skill_entries(pack_dir, root) + contents_desc = ( + f"The pack provides {len(regular)} skills" + + (f" and {len(orch)} orchestration skills" if orch else "") + + f" under `{pack_dir}` for Red Hat platforms." + ) + sample_workflows = [ + { + "name": "Choose the right skill", + "workflow": ( + 'User: "I have a task for this collection"\n' + "- Open CLAUDE.md intent routing and match your request to a skill name.\n" + "- Invoke that skill and follow its workflow and prerequisites.\n" + ), + } + ] + resources = [ + { + "title": "agentic-collections repository", + "description": "Source repository for these packs and skills.", + "url": "https://github.com/RHEcosystemAppEng/agentic-collections", + } + ] + deploy_and_use = ( + "## Install (Lola)\n\n" + "Add the marketplace and install this module from `marketplace/rh-agentic-collection.yml` " + f"(path `{pack_dir}`). See the pack `README.md` for prerequisites, MCP env vars, and safety notes.\n" + ) + summary = ( + f"- **Pack:** `{pack_dir}`\n" + f"- **Focus:** {mod_desc[:280]}{'...' if len(mod_desc) > 280 else ''}\n" + "- **Skills:** see `.catalog/collection.yaml` contents for the authoritative list.\n" + ) + return { + "id": PACK_CATALOG_IDS.get(pack_dir, pack_dir), + "name": title, + "provider": "Red Hat", + "version": version, + "categories": categories, + "personas": personas, + "marketplaces": ["Claude Code", "Cursor"], + "description": mod_desc, + "summary": summary, + "contents": { + "description": contents_desc, + "skills": regular, + "orchestration_skills": orch, + "skills_decision_guide": _decision_rows(pack_dir, regular, orch), + }, + "deploy_and_use": deploy_and_use, + "sample_workflows": sample_workflows, + "resources": resources, + "repository": "https://github.com/RHEcosystemAppEng/agentic-collections", + "license": "Apache-2.0", + } + + +def write_pack(pack_dir: str, root: Path, force: bool) -> None: + out_y = root / pack_dir / ".catalog" / "collection.yaml" + if out_y.exists() and not force: + print(f"skip {pack_dir} (exists, use --force)") + return + data = build_collection_data(pack_dir, root) + out_y.parent.mkdir(parents=True, exist_ok=True) + body = yaml.dump( + data, + default_flow_style=False, + allow_unicode=True, + sort_keys=False, + width=120, + ) + out_y.write_text(CATALOG_YAML_BANNER.rstrip() + "\n\n" + body, encoding="utf-8") + print(f"wrote {out_y.relative_to(root)}") + + +def main() -> int: + ap = argparse.ArgumentParser() + ap.add_argument("--pack", help="Only this pack") + ap.add_argument("--force", action="store_true", help="Overwrite existing collection.yaml") + args = ap.parse_args() + root = REPO_ROOT + packs = [args.pack] if args.pack else pack_registry.get_union_pack_dirs(root) + for p in packs: + if not (root / p).is_dir(): + print(f"skip missing dir: {p}", file=sys.stderr) + continue + write_pack(p, root, args.force) + return 0 + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/scripts/catalog_yaml_to_json.py b/scripts/catalog_yaml_to_json.py new file mode 100644 index 00000000..2d95ce4b --- /dev/null +++ b/scripts/catalog_yaml_to_json.py @@ -0,0 +1,55 @@ +#!/usr/bin/env python3 +"""Write deterministic .catalog/collection.json from .catalog/collection.yaml.""" + +from __future__ import annotations + +import argparse +import sys +from pathlib import Path + +import yaml + +import collection_validate_lib as cvl +import pack_registry + + +def mirror_pack(pack_dir: str, root: Path, dry_run: bool = False) -> None: + ypath = root / pack_dir / ".catalog" / "collection.yaml" + jpath = root / pack_dir / ".catalog" / "collection.json" + if not ypath.exists(): + raise FileNotFoundError(f"Missing {ypath}") + with open(ypath, "r", encoding="utf-8") as f: + data = yaml.safe_load(f) + text = cvl.collection_json_dumps(data) + if dry_run: + print(text, end="") + return + jpath.parent.mkdir(parents=True, exist_ok=True) + jpath.write_text(text, encoding="utf-8") + print(f"Wrote {jpath.relative_to(root)}") + + +def main() -> int: + parser = argparse.ArgumentParser() + parser.add_argument("--pack", help="Single pack directory name") + parser.add_argument("--all", action="store_true", help="All union registry packs with collection.yaml") + parser.add_argument("--dry-run", action="store_true") + args = parser.parse_args() + root = Path(__file__).resolve().parent.parent + try: + if args.all: + for p in pack_registry.get_union_pack_dirs(root): + if (root / p / ".catalog" / "collection.yaml").exists(): + mirror_pack(p, root, dry_run=args.dry_run) + elif args.pack: + mirror_pack(args.pack, root, dry_run=args.dry_run) + else: + parser.error("Provide --pack NAME or --all") + except Exception as e: + print(str(e), file=sys.stderr) + return 1 + return 0 + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/scripts/collection_validate_lib.py b/scripts/collection_validate_lib.py new file mode 100644 index 00000000..aaa14143 --- /dev/null +++ b/scripts/collection_validate_lib.py @@ -0,0 +1,399 @@ +""" +Shared validation for /.catalog/collection.yaml (JSON Schema in catalog/schema.yaml, roster, banners, +#fragment refs on top-level prose fields, JSON mirror). +Used by validate_collection_schema.py and validate_collection_compliance.py. +""" + +from __future__ import annotations + +import json +import re +from pathlib import Path +from typing import Any, Dict, List, Optional, Set, Tuple + +import yaml +from jsonschema import Draft202012Validator + +import pack_registry + +REPO_ROOT = Path(__file__).resolve().parent.parent +SCHEMA_YAML_PATH = REPO_ROOT / "catalog" / "schema.yaml" + +YAML_BANNER_MARKERS = ("create-collection", "Golden sources") + +FORBIDDEN_WORKFLOW_TOKENS = ("TODO:", "TBD", "FIXME:", "Extract from README") + +# Inline prose in collection.yaml longer than this must move to a sibling .md and use a #fragment ref. +CATALOG_INLINE_CHAR_LIMIT = 500 + +# Top-level keys: if present as inline strings, length is checked (skills blocks excluded). +CATALOG_INLINE_LENGTH_KEYS = ("documentation_section", "mcp_section", "security_model", "summary") + +# Deprecated: use documentation_section / mcp_section / security_model with inline or #fragment.md (same as deploy_and_use). +DEPRECATED_CATALOG_FILE_KEYS = ( + "documentation_section_file", + "mcp_section_file", + "security_model_file", +) + +_SCHEMA_CACHE: Optional[Dict[str, Any]] = None +_VALIDATOR_CACHE: Optional[Draft202012Validator] = None + + +def normalize_external_file_ref(ref: str) -> str: + """Strip leading ``#`` and optional ``.catalog/`` prefix; remainder is a path under ``/.catalog/``.""" + s = ref.strip() + if s.startswith("#"): + s = s[1:].lstrip() + if len(s) >= 9 and s[:9].lower() == ".catalog/": + s = s[9:] + return s + + +def catalog_fragment_rel_path(value: str) -> Optional[str]: + """If ``value`` is a one-line ``#name.md`` ref (sibling of ``collection.yaml``), return relative path; else ``None``.""" + s = value.strip() + if "\n" in s or "\r" in s: + return None + m = re.fullmatch(r"#\s*(?:\.catalog/)?([\w./-]+\.md)\s*", s, flags=re.IGNORECASE) + if not m: + return None + rel = m.group(1) + if ".." in rel or rel.startswith("/"): + return None + return rel + + +def deploy_and_use_external_rel_path(value: str) -> Optional[str]: + """If ``deploy_and_use`` is file-ref flavor, return path under ``.catalog/``; else ``None`` (inline markdown).""" + return catalog_fragment_rel_path(value) + + +def _load_schema() -> Dict[str, Any]: + global _SCHEMA_CACHE, _VALIDATOR_CACHE + if _SCHEMA_CACHE is not None: + return _SCHEMA_CACHE + path = SCHEMA_YAML_PATH if SCHEMA_YAML_PATH.exists() else None + if not path: + raise FileNotFoundError(f"Missing catalog schema at {SCHEMA_YAML_PATH}") + with open(path, "r", encoding="utf-8") as f: + _SCHEMA_CACHE = yaml.safe_load(f) + Draft202012Validator.check_schema(_SCHEMA_CACHE) + _VALIDATOR_CACHE = Draft202012Validator(_SCHEMA_CACHE) + return _SCHEMA_CACHE + + +def get_validator() -> Draft202012Validator: + _load_schema() + assert _VALIDATOR_CACHE is not None + return _VALIDATOR_CACHE + + +def collection_json_dumps(data: Any) -> str: + """Deterministic JSON text for collection.json (must match committed file).""" + return json.dumps(data, ensure_ascii=False, sort_keys=True, indent=2) + "\n" + + +def read_yaml_catalog(pack_dir: str, root: Optional[Path] = None) -> Tuple[Optional[Dict[str, Any]], List[str]]: + root = root or REPO_ROOT + p = root / pack_dir / ".catalog" / "collection.yaml" + if not p.exists(): + return None, [f"{pack_dir}: missing {p.relative_to(root)}"] + try: + with open(p, "r", encoding="utf-8") as f: + raw = f.read() + data = yaml.safe_load(raw) + if not isinstance(data, dict): + return None, [f"{pack_dir}: collection.yaml must parse to a mapping"] + return data, [] + except Exception as e: + return None, [f"{pack_dir}: failed to parse collection.yaml: {e}"] + + +def validate_yaml_banner(pack_dir: str, root: Optional[Path] = None) -> List[str]: + root = root or REPO_ROOT + p = root / pack_dir / ".catalog" / "collection.yaml" + if not p.exists(): + return [] + try: + text = p.read_text(encoding="utf-8") + except OSError as e: + return [f"{pack_dir}: cannot read collection.yaml: {e}"] + head = "\n".join(text.splitlines()[:40]) + missing = [m for m in YAML_BANNER_MARKERS if m not in head] + if missing: + return [ + f"{pack_dir}: collection.yaml must start with a # comment banner mentioning: " + + ", ".join(YAML_BANNER_MARKERS) + ] + return [] + + +def validate_deprecated_catalog_file_keys(pack_dir: str, data: Dict[str, Any]) -> List[str]: + """Reject legacy ``*_file`` split keys; prose fields use the same key for inline or ``#fragment.md``.""" + errs: List[str] = [] + for k in DEPRECATED_CATALOG_FILE_KEYS: + if k in data and data[k] is not None and str(data[k]).strip() != "": + base = k[: -len("_file")] + errs.append( + f"{pack_dir}: deprecated key {k!r}; use {base!r} with inline markdown or " + f"a one-line fragment ref like '#{base}.md' (same pattern as deploy_and_use; see COLLECTION_SPEC.md)." + ) + return errs + + +def _collect_top_level_catalog_fragment_refs(data: Dict[str, Any]) -> List[str]: + """Fragment refs on top-level fields that may be inline markdown or #sibling.md (like deploy_and_use).""" + refs: List[str] = [] + for key in ("documentation_section", "mcp_section", "security_model", "deploy_and_use"): + v = data.get(key) + if isinstance(v, str) and v.strip() and catalog_fragment_rel_path(v): + refs.append(v.strip()) + return refs + + +def validate_file_refs(pack_dir: str, data: Dict[str, Any], root: Optional[Path] = None) -> List[str]: + root = root or REPO_ROOT + refs = _collect_top_level_catalog_fragment_refs(data) + errs: List[str] = [] + pack_root = root / pack_dir + catalog_dir = (pack_root / ".catalog").resolve() + for ref in refs: + if not ref.strip().startswith("#"): + errs.append( + f"{pack_dir}: fragment ref must start with '#' (e.g. #install.md), got {ref!r}" + ) + continue + path_part = normalize_external_file_ref(ref) + if not path_part: + errs.append(f"{pack_dir}: empty fragment path after normalizing {ref!r}") + continue + if ".." in path_part or path_part.startswith("/"): + errs.append(f"{pack_dir}: invalid fragment path {ref!r}") + continue + target = (catalog_dir / path_part).resolve() + try: + target.relative_to(catalog_dir) + except ValueError: + errs.append(f"{pack_dir}: fragment {ref!r} escapes .catalog/ directory") + continue + if not target.is_file(): + errs.append(f"{pack_dir}: missing fragment file {path_part} (from {ref!r})") + return errs + + +def validate_embedded_docs(pack_dir: str, data: Dict[str, Any], root: Optional[Path] = None) -> List[str]: + root = root or REPO_ROOT + errs: List[str] = [] + pack_root = root / pack_dir + for i, r in enumerate(data.get("resources") or []): + if not isinstance(r, dict): + continue + ed = r.get("embedded_doc") + if not ed or not str(ed).strip(): + continue + rel = str(ed).strip() + target = (pack_root / rel).resolve() + if not target.is_file(): + errs.append(f"{pack_dir}: resources[{i}].embedded_doc missing file {rel}") + return errs + + +def list_disk_skill_names(pack_dir: str, root: Optional[Path] = None) -> List[str]: + root = root or REPO_ROOT + skills_dir = root / pack_dir / "skills" + if not skills_dir.is_dir(): + return [] + names = sorted(p.name for p in skills_dir.iterdir() if p.is_dir() and (p / "SKILL.md").is_file()) + return names + + +def catalog_skill_names(data: Dict[str, Any]) -> Tuple[List[str], List[str]]: + contents = data.get("contents") or {} + if not isinstance(contents, dict): + return [], [] + reg: List[str] = [] + orch: List[str] = [] + for s in contents.get("skills") or []: + if isinstance(s, dict) and s.get("name"): + reg.append(str(s["name"])) + for s in contents.get("orchestration_skills") or []: + if isinstance(s, dict) and s.get("name"): + orch.append(str(s["name"])) + return reg, orch + + +def validate_skill_roster(pack_dir: str, data: Dict[str, Any], root: Optional[Path] = None) -> List[str]: + disk = set(list_disk_skill_names(pack_dir, root)) + reg, orch = catalog_skill_names(data) + yaml_names = reg + orch + errs: List[str] = [] + + if len(yaml_names) != len(set(yaml_names)): + errs.append(f"{pack_dir}: duplicate skill name in contents.skills / orchestration_skills") + + seen = set(reg) | set(orch) + for n in reg + orch: + if n not in disk: + errs.append(f"{pack_dir}: YAML lists skill {n!r} with no skills/{n}/SKILL.md on disk") + + for d in disk: + if d not in seen: + errs.append(f"{pack_dir}: on-disk skill {d!r} missing from collection.yaml contents") + return errs + + +def validate_json_mirror(pack_dir: str, data: Dict[str, Any], root: Optional[Path] = None) -> List[str]: + root = root or REPO_ROOT + json_path = root / pack_dir / ".catalog" / "collection.json" + if not json_path.exists(): + return [f"{pack_dir}: missing .catalog/collection.json (run make catalog-mirror-json)"] + expected = collection_json_dumps(data) + actual = json_path.read_text(encoding="utf-8") + if actual != expected: + return [ + f"{pack_dir}: .catalog/collection.json is out of sync with collection.yaml " + f"(run: uv run python scripts/catalog_yaml_to_json.py --pack {pack_dir})" + ] + return [] + + +def validate_schema_instance(pack_dir: str, data: Dict[str, Any]) -> List[str]: + v = get_validator() + errs = [f"{pack_dir}: schema: {'/'.join(str(x) for x in e.path)}: {e.message}" for e in v.iter_errors(data)] + return errs + + +def validate_pack_iteration3( + pack_dir: str, root: Optional[Path] = None, check_banner: bool = True +) -> List[str]: + """Iteration 3: schema + fragment refs + roster + optional YAML banner (no collection.json mirror).""" + root = root or REPO_ROOT + data, errs = read_yaml_catalog(pack_dir, root) + if errs or data is None: + return errs + out: List[str] = [] + out.extend(validate_deprecated_catalog_file_keys(pack_dir, data)) + out.extend(validate_schema_instance(pack_dir, data)) + out.extend(validate_file_refs(pack_dir, data, root)) + out.extend(validate_skill_roster(pack_dir, data, root)) + if check_banner: + out.extend(validate_yaml_banner(pack_dir, root)) + return out + + +def validate_pack_iteration5(pack_dir: str, root: Optional[Path] = None) -> List[str]: + """Full collection compliance: Iteration 3 + semantic rules + JSON mirror drift.""" + root = root or REPO_ROOT + errs = validate_pack_iteration3(pack_dir, root, check_banner=True) + data, e = read_yaml_catalog(pack_dir, root) + errs.extend(e) + if data: + errs.extend(validate_pack_catalog_compliance_extra(pack_dir, data, root)) + errs.extend(validate_json_mirror(pack_dir, data, root)) + return errs + + +def validate_pack_catalog_compliance_extra(pack_dir: str, data: Dict[str, Any], root: Optional[Path] = None) -> List[str]: + """Iteration 5 semantic checks.""" + root = root or REPO_ROOT + errs: List[str] = [] + contents = data.get("contents") + if isinstance(contents, dict): + for group, label in ( + (contents.get("skills") or [], "contents.skills"), + (contents.get("orchestration_skills") or [], "contents.orchestration_skills"), + ): + for i, s in enumerate(group): + if not isinstance(s, dict): + continue + name = s.get("name") + desc = (s.get("description") or "").strip() + sm = (s.get("summary_markdown") or "").strip() + if not name or not desc: + errs.append(f"{pack_dir}: {label}[{i}] requires name and description") + if len(sm) < 20: + errs.append(f"{pack_dir}: {label}[{i}] summary_markdown too short (<20 chars)") + skill_md = (root / pack_dir / "skills" / str(name) / "SKILL.md") + if not skill_md.is_file(): + errs.append( + f"{pack_dir}: {label}[{i}] name {name!r} must match skills// directory " + f"(missing {skill_md.relative_to(root)})" + ) + + disk_skill_names = set(list_disk_skill_names(pack_dir, root)) + guide = (contents or {}).get("skills_decision_guide") or [] + if not disk_skill_names and guide: + errs.append(f"{pack_dir}: skills_decision_guide must be empty when the pack has no skills/") + for i, row in enumerate(guide): + if not isinstance(row, dict): + continue + st = row.get("skill_to_use") + if disk_skill_names and st and st not in disk_skill_names: + errs.append(f"{pack_dir}: skills_decision_guide[{i}] skill_to_use {st!r} not a known skill dir") + + for i, wf in enumerate(data.get("sample_workflows") or []): + if not isinstance(wf, dict): + continue + w = (wf.get("workflow") or "") + for tok in FORBIDDEN_WORKFLOW_TOKENS: + if tok in w: + errs.append(f"{pack_dir}: sample_workflows[{i}] contains forbidden token {tok!r}") + if "User:" not in w and 'User: "' not in w: + errs.append(f"{pack_dir}: sample_workflows[{i}] workflow must include User: line") + if "-" not in w: + errs.append(f"{pack_dir}: sample_workflows[{i}] workflow must use bullet lines (-)") + + errs.extend(validate_embedded_docs(pack_dir, data, root)) + errs.extend(validate_catalog_inline_length(pack_dir, data)) + errs.extend(validate_json_mirror(pack_dir, data, root)) + return errs + + +def validate_catalog_inline_length(pack_dir: str, data: Dict[str, Any]) -> List[str]: + """Require long prose to use a #fragment .md ref (sibling of collection.yaml), not huge inline strings.""" + errs: List[str] = [] + for key in CATALOG_INLINE_LENGTH_KEYS: + val = data.get(key) + if not isinstance(val, str): + continue + if catalog_fragment_rel_path(val): + continue + if len(val) > CATALOG_INLINE_CHAR_LIMIT: + errs.append( + f"{pack_dir}: {key} is {len(val)} chars (limit {CATALOG_INLINE_CHAR_LIMIT}); " + f"move prose to a sibling .md under .catalog/ and set {key}: '#.md' " + f"(same pattern as deploy_and_use)." + ) + dau = data.get("deploy_and_use") + if isinstance(dau, str) and not deploy_and_use_external_rel_path(dau): + if len(dau) > CATALOG_INLINE_CHAR_LIMIT: + errs.append( + f"{pack_dir}: deploy_and_use is {len(dau)} chars inline (limit {CATALOG_INLINE_CHAR_LIMIT}); " + "use markdown in a sibling .md and deploy_and_use: #.md" + ) + return errs + + +def validate_all_iteration3(root: Optional[Path] = None, check_banner: bool = True) -> List[str]: + root = root or REPO_ROOT + all_errs: List[str] = [] + for pack in pack_registry.get_union_pack_dirs(root): + cat = root / pack / ".catalog" / "collection.yaml" + if not cat.exists(): + all_errs.append(f"{pack}: missing .catalog/collection.yaml") + continue + all_errs.extend(validate_pack_iteration3(pack, root, check_banner=check_banner)) + return all_errs + + +def validate_all_iteration5(root: Optional[Path] = None) -> List[str]: + root = root or REPO_ROOT + all_errs: List[str] = [] + for pack in pack_registry.get_union_pack_dirs(root): + cat = root / pack / ".catalog" / "collection.yaml" + if not cat.exists(): + all_errs.append(f"{pack}: missing .catalog/collection.yaml") + continue + all_errs.extend(validate_pack_iteration5(pack, root)) + return all_errs diff --git a/scripts/generate_pack_data.py b/scripts/generate_pack_data.py index 3ff4fe20..45125c3b 100644 --- a/scripts/generate_pack_data.py +++ b/scripts/generate_pack_data.py @@ -10,12 +10,12 @@ from typing import Dict, List, Any import yaml -# List of agentic packs to parse -PACK_DIRS = ['rh-sre', 'rh-developer', 'ocp-admin', 'rh-support-engineer', 'rh-virt', 'rh-ai-engineer', 'rh-automation'] +import pack_registry -# Packs omitted from docs/data.json and the static documentation site -DOCS_EXCLUDED_PACKS = frozenset({'rh-support-engineer'}) -DOCS_PACK_DIRS = [d for d in PACK_DIRS if d not in DOCS_EXCLUDED_PACKS] +# Union registry (marketplace ∪ plugins.json); docs site uses subset helper +PACK_DIRS = pack_registry.get_union_pack_dirs() +DOCS_EXCLUDED_PACKS = pack_registry.DOCS_EXCLUDED_PACKS +DOCS_PACK_DIRS = pack_registry.get_docs_pack_dirs() def parse_yaml_frontmatter(file_path: Path) -> Dict[str, Any]: diff --git a/scripts/install-hooks.sh b/scripts/install-hooks.sh index 5ad17409..6eab5000 100755 --- a/scripts/install-hooks.sh +++ b/scripts/install-hooks.sh @@ -1,145 +1,90 @@ #!/usr/bin/env bash # -# Install gitleaks pre-commit hook +# Install the repository git pre-commit hook via the pre-commit framework. # -# This script sets up gitleaks to run automatically before each commit -# to prevent sensitive data from being committed. +# This replaces the legacy behavior that wrote a gitleaks-only hook into +# .git/hooks/pre-commit. The single hook now delegates to pre-commit, which +# runs gitleaks plus scoped validation (see .pre-commit-config.yaml). # set -euo pipefail -# Colors +ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" +cd "$ROOT" + RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' NC='\033[0m' echo "=========================================" -echo "Gitleaks Pre-Commit Hook Installation" +echo "Git hooks (pre-commit)" echo "=========================================" echo "" -# Check if we're in a git repository if [ ! -d ".git" ]; then echo -e "${RED}Error: Not a git repository${NC}" - echo "Run this script from the repository root" + echo "Run this script from the repository root (or use: scripts/install-hooks.sh from root)." exit 1 fi -# Check if gitleaks is installed -if ! command -v gitleaks >/dev/null 2>&1; then - echo -e "${YELLOW}Gitleaks not found.${NC} Installing..." - echo "" - - # Detect OS and install - if [[ "$OSTYPE" == "darwin"* ]]; then - # macOS - if command -v brew >/dev/null 2>&1; then - echo "Installing via Homebrew..." - brew install gitleaks - else - echo -e "${RED}Error: Homebrew not found${NC}" - echo "Install gitleaks manually: https://github.com/gitleaks/gitleaks#installation" - exit 1 - fi - elif [[ "$OSTYPE" == "linux-gnu"* ]]; then - # Linux - echo "Downloading gitleaks binary..." - GITLEAKS_VERSION="8.18.2" - ARCH=$(uname -m) - - if [ "$ARCH" = "x86_64" ]; then - ARCH="x64" - elif [ "$ARCH" = "aarch64" ]; then - ARCH="arm64" - fi - - curl -sSfL "https://github.com/gitleaks/gitleaks/releases/download/v${GITLEAKS_VERSION}/gitleaks_${GITLEAKS_VERSION}_linux_${ARCH}.tar.gz" | \ - tar -xz -C /tmp - sudo mv /tmp/gitleaks /usr/local/bin/ - sudo chmod +x /usr/local/bin/gitleaks - else - echo -e "${RED}Error: Unsupported OS${NC}" - echo "Install gitleaks manually: https://github.com/gitleaks/gitleaks#installation" - exit 1 - fi -else - echo -e "${GREEN}✓${NC} Gitleaks already installed: $(gitleaks version)" +if ! command -v uv >/dev/null 2>&1; then + echo -e "${RED}Error: uv not found${NC}" + echo "Install uv: https://docs.astral.sh/uv/getting-started/installation/" + exit 1 fi +echo "Syncing dependencies (includes dev group: pre-commit)..." +uv sync --group dev echo "" -# Create pre-commit hook HOOK_FILE=".git/hooks/pre-commit" - -# Backup existing hook if present -if [ -f "$HOOK_FILE" ]; then +if [ -f "$HOOK_FILE" ] && ! grep -q 'pre-commit' "$HOOK_FILE" 2>/dev/null; then BACKUP="${HOOK_FILE}.backup-$(date +%Y%m%d-%H%M%S)" - echo -e "${YELLOW}Backing up existing hook to: $BACKUP${NC}" + echo -e "${YELLOW}Backing up existing pre-commit hook (non-pre-commit) to:${NC} $BACKUP" mv "$HOOK_FILE" "$BACKUP" + echo "The previous hook (e.g. gitleaks-only) is preserved; pre-commit will own the hook now." + echo "" fi -# Write gitleaks pre-commit hook -cat > "$HOOK_FILE" << 'EOF' -#!/usr/bin/env bash -# -# Gitleaks pre-commit hook -# Scans staged changes for secrets before allowing commit -# - -set -e - -# Run gitleaks on staged changes -if ! gitleaks protect --staged --redact --verbose; then - echo "" - echo "=========================================" - echo "🚨 COMMIT BLOCKED - Secrets Detected" - echo "=========================================" - echo "" - echo "Gitleaks found potential secrets in your staged changes." +if ! command -v gitleaks >/dev/null 2>&1; then + echo -e "${YELLOW}Gitleaks not found on PATH.${NC} The gitleaks-system hook needs it." + echo "Install one of:" + echo " - macOS: brew install gitleaks" + echo " - https://github.com/gitleaks/gitleaks#installation" echo "" - echo "To fix:" - echo " 1. Remove hardcoded secrets" - echo " 2. Use environment variables: \${ENV_VAR}" - echo " 3. Review .gitleaks.toml for allowed patterns" + if [[ "${OSTYPE:-}" == darwin* ]] && command -v brew >/dev/null 2>&1; then + echo "Installing gitleaks via Homebrew..." + brew install gitleaks + else + echo -e "${YELLOW}Skipping automatic gitleaks install (unsupported OS or no brew).${NC}" + echo "Install gitleaks, then re-run: scripts/install-hooks.sh" + fi echo "" - echo "To bypass (DANGEROUS - only for test fixtures):" - echo " git commit --no-verify" +else + echo -e "${GREEN}✓${NC} Gitleaks: $(gitleaks version 2>/dev/null || echo ok)" echo "" - echo "For help: See SECURITY.md" - echo "=========================================" - exit 1 fi -echo "✓ No secrets detected" -exit 0 -EOF - -chmod +x "$HOOK_FILE" - -echo -e "${GREEN}✓${NC} Pre-commit hook installed: $HOOK_FILE" +echo "Installing pre-commit hook (writes .git/hooks/pre-commit)..." +uv run pre-commit install echo "" -# Verify configuration exists if [ ! -f ".gitleaks.toml" ]; then echo -e "${YELLOW}Warning: .gitleaks.toml not found${NC}" - echo "Gitleaks will use default rules only" else echo -e "${GREEN}✓${NC} Configuration found: .gitleaks.toml" fi echo "" echo "=========================================" -echo "Installation Complete" +echo "Done" echo "=========================================" +echo "On commit, pre-commit runs (see .pre-commit-config.yaml):" +echo " - gitleaks (secrets)" +echo " - make validate (when roster/catalog-related paths change)" +echo " - make validate-skill-design-changed (when pack SKILL.md files change)" echo "" -echo "Test the hook:" -echo " 1. Make a test commit with a secret" -echo " 2. Hook should block it" -echo "" -echo "Manual scan:" -echo " gitleaks detect --source . --verbose" -echo "" -echo "Update hook:" -echo " Re-run this script: scripts/install-hooks.sh" +echo "CI source of truth for collection checks: .github/workflows/compliance-check.yml (make validate)." +echo "Manual: pre-commit run --all-files" echo "" diff --git a/scripts/pack_registry.py b/scripts/pack_registry.py new file mode 100644 index 00000000..836b6a4b --- /dev/null +++ b/scripts/pack_registry.py @@ -0,0 +1,111 @@ +""" +Resolve the set of agentic pack directories from Lola marketplace + docs/plugins.json. + +Policy (union): include every ``modules[].path`` from ``marketplace/rh-agentic-collection.yml`` +and every key from ``docs/plugins.json``, keeping only directory names that exist on disk. +""" + +from __future__ import annotations + +import json +from pathlib import Path +from typing import Any, Dict, List, Optional, Set + +import yaml + +DEFAULT_MARKETPLACE = Path("marketplace/rh-agentic-collection.yml") +DEFAULT_PLUGINS_JSON = Path("docs/plugins.json") + + +def _repo_root() -> Path: + return Path(__file__).resolve().parent.parent + + +def load_marketplace_module_paths(marketplace_path: Optional[Path] = None) -> List[str]: + path = marketplace_path or (_repo_root() / DEFAULT_MARKETPLACE) + if not path.exists(): + return [] + with open(path, "r", encoding="utf-8") as f: + data = yaml.safe_load(f) or {} + modules = data.get("modules") or [] + out: List[str] = [] + for mod in modules: + p = mod.get("path") + if isinstance(p, str) and p.strip(): + out.append(p.strip().strip("/")) + return out + + +def load_plugins_json_keys(plugins_path: Optional[Path] = None) -> List[str]: + path = plugins_path or (_repo_root() / DEFAULT_PLUGINS_JSON) + if not path.exists(): + return [] + with open(path, "r", encoding="utf-8") as f: + data = json.load(f) + if not isinstance(data, dict): + return [] + return sorted(data.keys()) + + +def get_union_pack_dirs( + repo_root: Optional[Path] = None, + marketplace_path: Optional[Path] = None, + plugins_path: Optional[Path] = None, +) -> List[str]: + """ + Sorted unique pack directory names that exist under repo root and appear in + marketplace and/or docs/plugins.json union. + """ + root = repo_root or _repo_root() + names: Set[str] = set() + names.update(load_marketplace_module_paths(marketplace_path)) + names.update(load_plugins_json_keys(plugins_path)) + existing: List[str] = [] + for name in sorted(names): + if (root / name).is_dir(): + existing.append(name) + return existing + + +def load_marketplace_module_by_path( + pack_dir: str, + repo_root: Optional[Path] = None, + marketplace_path: Optional[Path] = None, +) -> Optional[Dict[str, Any]]: + """Return the marketplace module dict for a pack path, or None.""" + root = repo_root or _repo_root() + path = marketplace_path or (root / DEFAULT_MARKETPLACE) + if not path.exists(): + return None + with open(path, "r", encoding="utf-8") as f: + data = yaml.safe_load(f) or {} + for mod in data.get("modules") or []: + if mod.get("path") == pack_dir: + return mod + return None + + +def load_plugin_title(pack_dir: str, repo_root: Optional[Path] = None) -> Optional[str]: + root = repo_root or _repo_root() + p = root / DEFAULT_PLUGINS_JSON + if not p.exists(): + return None + with open(p, "r", encoding="utf-8") as f: + data = json.load(f) + entry = data.get(pack_dir) + if isinstance(entry, dict): + t = entry.get("title") + if isinstance(t, str): + return t + return None + + +# Packs excluded from docs/data.json site generation only (not excluded from .catalog requirement). +DOCS_EXCLUDED_PACKS: frozenset[str] = frozenset({"rh-support-engineer"}) + + +def get_docs_pack_dirs( + repo_root: Optional[Path] = None, +) -> List[str]: + """Pack dirs included in GitHub Pages data.json (subset of union).""" + return [p for p in get_union_pack_dirs(repo_root) if p not in DOCS_EXCLUDED_PACKS] diff --git a/scripts/scaffold_catalog.py b/scripts/scaffold_catalog.py new file mode 100644 index 00000000..4a47d6c2 --- /dev/null +++ b/scripts/scaffold_catalog.py @@ -0,0 +1,48 @@ +#!/usr/bin/env python3 +"""Print a draft skill roster and marketplace hints for create-collection (stdout only).""" + +from __future__ import annotations + +import argparse +import sys +from pathlib import Path + +import pack_registry +from generate_pack_data import parse_yaml_frontmatter + + +def main() -> int: + parser = argparse.ArgumentParser() + parser.add_argument("pack", help="Pack directory name") + args = parser.parse_args() + root = Path(__file__).resolve().parent.parent + pack = args.pack + if not (root / pack).is_dir(): + print(f"No such pack: {pack}", file=sys.stderr) + return 1 + mod = pack_registry.load_marketplace_module_by_path(pack, root) + title = pack_registry.load_plugin_title(pack, root) or pack + print(f"# Draft scaffold for `{pack}`\n") + print(f"**Display title:** {title}") + if mod: + print(f"**Marketplace name:** {mod.get('name')}") + print(f"**Version:** {mod.get('version')}") + print(f"**Description:** {mod.get('description')}") + print(f"**Tags:** {mod.get('tags')}") + print("\n## skills/*/SKILL.md\n") + skills_dir = root / pack / "skills" + if not skills_dir.is_dir(): + print("(no skills directory)") + return 0 + for skill_md in sorted(skills_dir.glob("*/SKILL.md")): + fm = parse_yaml_frontmatter(skill_md) + name = fm.get("name", skill_md.parent.name) + desc = fm.get("description", "") + if isinstance(desc, str): + desc = " ".join(desc.split())[:400] + print(f"- **{name}** (`{skill_md.parent.name}/`)\n {desc}\n") + return 0 + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/scripts/test_local.sh b/scripts/test_local.sh index 6ce79602..870cf4d7 100755 --- a/scripts/test_local.sh +++ b/scripts/test_local.sh @@ -132,11 +132,15 @@ with open('docs/data.json') as f: data = json.load(f) # Check for non-variable env values (should all be uppercase with underscores) -for server in data['mcp_servers']: - for env_var in server.get('env', []): - if not env_var.isupper() or '_' not in env_var: - print(f"Suspicious env var: {env_var} in {server['name']}") - sys.exit(1) + for server in data['mcp_servers']: + for env_var in server.get('env', []): + # Accept standard placeholder-style names: UPPER_SNAKE or all-caps (e.g. KUBECONFIG) + if not env_var.isupper(): + print(f"Suspicious env var: {env_var} in {server['name']}") + sys.exit(1) + if not (env_var.replace("_", "").isalnum() and env_var.replace("_", "").isupper()): + print(f"Suspicious env var: {env_var} in {server['name']}") + sys.exit(1) print("OK", end='') EOF diff --git a/scripts/validate_collection_compliance.py b/scripts/validate_collection_compliance.py new file mode 100644 index 00000000..ab327044 --- /dev/null +++ b/scripts/validate_collection_compliance.py @@ -0,0 +1,23 @@ +#!/usr/bin/env python3 +"""Full collection compliance (Iteration 3 + semantic rules + collection.json mirror drift).""" + +import sys +from pathlib import Path + +import collection_validate_lib as cvl + + +def main() -> int: + root = Path(__file__).resolve().parent.parent + errs = cvl.validate_all_iteration5(root) + if errs: + print("Collection compliance failed:", file=sys.stderr) + for e in errs: + print(f" • {e}", file=sys.stderr) + return 1 + print("✓ Collection compliance passed") + return 0 + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/scripts/validate_collection_schema.py b/scripts/validate_collection_schema.py new file mode 100644 index 00000000..8c028d0c --- /dev/null +++ b/scripts/validate_collection_schema.py @@ -0,0 +1,23 @@ +#!/usr/bin/env python3 +"""Iteration 3: validate .catalog/collection.yaml (presence, schema, roster, #fragment refs, YAML banner).""" + +import sys +from pathlib import Path + +import collection_validate_lib as cvl + + +def main() -> int: + root = Path(__file__).resolve().parent.parent + errs = cvl.validate_all_iteration3(root, check_banner=True) + if errs: + print("Collection schema validation failed:", file=sys.stderr) + for e in errs: + print(f" • {e}", file=sys.stderr) + return 1 + print("✓ Collection schema validation passed") + return 0 + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/scripts/validate_structure.py b/scripts/validate_structure.py index 369b0f5c..f60caa7f 100644 --- a/scripts/validate_structure.py +++ b/scripts/validate_structure.py @@ -12,8 +12,10 @@ from typing import List import re -# List of agentic collections to validate -PACK_DIRS = ['rh-sre', 'rh-developer', 'ocp-admin', 'rh-support-engineer', 'rh-virt', 'rh-ai-engineer', 'rh-automation'] +import pack_registry + +# Union of Lola marketplace paths and docs/plugins.json keys (existing dirs only) +PACK_DIRS = pack_registry.get_union_pack_dirs() def validate_plugin_json(pack_dir: str) -> List[str]: diff --git a/uv.lock b/uv.lock index 9e071254..343aebea 100644 --- a/uv.lock +++ b/uv.lock @@ -1,5 +1,5 @@ version = 1 -revision = 2 +revision = 3 requires-python = ">=3.11" [[package]] @@ -11,12 +11,20 @@ dependencies = [ { name = "pyyaml" }, ] +[package.dev-dependencies] +dev = [ + { name = "pre-commit" }, +] + [package.metadata] requires-dist = [ { name = "jsonschema", specifier = ">=4.0" }, { name = "pyyaml", specifier = ">=6.0" }, ] +[package.metadata.requires-dev] +dev = [{ name = "pre-commit", specifier = ">=4.0.0" }] + [[package]] name = "attrs" version = "25.4.0" @@ -26,6 +34,42 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/3a/2a/7cc015f5b9f5db42b7d48157e23356022889fc354a2813c15934b7cb5c0e/attrs-25.4.0-py3-none-any.whl", hash = "sha256:adcf7e2a1fb3b36ac48d97835bb6d8ade15b8dcce26aba8bf1d14847b57a3373", size = 67615, upload-time = "2025-10-06T13:54:43.17Z" }, ] +[[package]] +name = "cfgv" +version = "3.5.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/4e/b5/721b8799b04bf9afe054a3899c6cf4e880fcf8563cc71c15610242490a0c/cfgv-3.5.0.tar.gz", hash = "sha256:d5b1034354820651caa73ede66a6294d6e95c1b00acc5e9b098e917404669132", size = 7334, upload-time = "2025-11-19T20:55:51.612Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/db/3c/33bac158f8ab7f89b2e59426d5fe2e4f63f7ed25df84c036890172b412b5/cfgv-3.5.0-py2.py3-none-any.whl", hash = "sha256:a8dc6b26ad22ff227d2634a65cb388215ce6cc96bbcc5cfde7641ae87e8dacc0", size = 7445, upload-time = "2025-11-19T20:55:50.744Z" }, +] + +[[package]] +name = "distlib" +version = "0.4.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/96/8e/709914eb2b5749865801041647dc7f4e6d00b549cfe88b65ca192995f07c/distlib-0.4.0.tar.gz", hash = "sha256:feec40075be03a04501a973d81f633735b4b69f98b05450592310c0f401a4e0d", size = 614605, upload-time = "2025-07-17T16:52:00.465Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/33/6b/e0547afaf41bf2c42e52430072fa5658766e3d65bd4b03a563d1b6336f57/distlib-0.4.0-py2.py3-none-any.whl", hash = "sha256:9659f7d87e46584a30b5780e43ac7a2143098441670ff0a49d5f9034c54a6c16", size = 469047, upload-time = "2025-07-17T16:51:58.613Z" }, +] + +[[package]] +name = "filelock" +version = "3.25.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/94/b8/00651a0f559862f3bb7d6f7477b192afe3f583cc5e26403b44e59a55ab34/filelock-3.25.2.tar.gz", hash = "sha256:b64ece2b38f4ca29dd3e810287aa8c48182bbecd1ae6e9ae126c9b35f1382694", size = 40480, upload-time = "2026-03-11T20:45:38.487Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a4/a5/842ae8f0c08b61d6484b52f99a03510a3a72d23141942d216ebe81fefbce/filelock-3.25.2-py3-none-any.whl", hash = "sha256:ca8afb0da15f229774c9ad1b455ed96e85a81373065fb10446672f64444ddf70", size = 26759, upload-time = "2026-03-11T20:45:37.437Z" }, +] + +[[package]] +name = "identify" +version = "2.6.18" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/46/c4/7fb4db12296cdb11893d61c92048fe617ee853f8523b9b296ac03b43757e/identify-2.6.18.tar.gz", hash = "sha256:873ac56a5e3fd63e7438a7ecbc4d91aca692eb3fefa4534db2b7913f3fc352fd", size = 99580, upload-time = "2026-03-15T18:39:50.319Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/46/33/92ef41c6fad0233e41d3d84ba8e8ad18d1780f1e5d99b3c683e6d7f98b63/identify-2.6.18-py2.py3-none-any.whl", hash = "sha256:8db9d3c8ea9079db92cafb0ebf97abdc09d52e97f4dcf773a2e694048b7cd737", size = 99394, upload-time = "2026-03-15T18:39:48.915Z" }, +] + [[package]] name = "jsonschema" version = "4.26.0" @@ -53,6 +97,53 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/41/45/1a4ed80516f02155c51f51e8cedb3c1902296743db0bbc66608a0db2814f/jsonschema_specifications-2025.9.1-py3-none-any.whl", hash = "sha256:98802fee3a11ee76ecaca44429fda8a41bff98b00a0f2838151b113f210cc6fe", size = 18437, upload-time = "2025-09-08T01:34:57.871Z" }, ] +[[package]] +name = "nodeenv" +version = "1.10.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/24/bf/d1bda4f6168e0b2e9e5958945e01910052158313224ada5ce1fb2e1113b8/nodeenv-1.10.0.tar.gz", hash = "sha256:996c191ad80897d076bdfba80a41994c2b47c68e224c542b48feba42ba00f8bb", size = 55611, upload-time = "2025-12-20T14:08:54.006Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/88/b2/d0896bdcdc8d28a7fc5717c305f1a861c26e18c05047949fb371034d98bd/nodeenv-1.10.0-py2.py3-none-any.whl", hash = "sha256:5bb13e3eed2923615535339b3c620e76779af4cb4c6a90deccc9e36b274d3827", size = 23438, upload-time = "2025-12-20T14:08:52.782Z" }, +] + +[[package]] +name = "platformdirs" +version = "4.9.6" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/9f/4a/0883b8e3802965322523f0b200ecf33d31f10991d0401162f4b23c698b42/platformdirs-4.9.6.tar.gz", hash = "sha256:3bfa75b0ad0db84096ae777218481852c0ebc6c727b3168c1b9e0118e458cf0a", size = 29400, upload-time = "2026-04-09T00:04:10.812Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/75/a6/a0a304dc33b49145b21f4808d763822111e67d1c3a32b524a1baf947b6e1/platformdirs-4.9.6-py3-none-any.whl", hash = "sha256:e61adb1d5e5cb3441b4b7710bea7e4c12250ca49439228cc1021c00dcfac0917", size = 21348, upload-time = "2026-04-09T00:04:09.463Z" }, +] + +[[package]] +name = "pre-commit" +version = "4.5.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "cfgv" }, + { name = "identify" }, + { name = "nodeenv" }, + { name = "pyyaml" }, + { name = "virtualenv" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/40/f1/6d86a29246dfd2e9b6237f0b5823717f60cad94d47ddc26afa916d21f525/pre_commit-4.5.1.tar.gz", hash = "sha256:eb545fcff725875197837263e977ea257a402056661f09dae08e4b149b030a61", size = 198232, upload-time = "2025-12-16T21:14:33.552Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/5d/19/fd3ef348460c80af7bb4669ea7926651d1f95c23ff2df18b9d24bab4f3fa/pre_commit-4.5.1-py2.py3-none-any.whl", hash = "sha256:3b3afd891e97337708c1674210f8eba659b52a38ea5f822ff142d10786221f77", size = 226437, upload-time = "2025-12-16T21:14:32.409Z" }, +] + +[[package]] +name = "python-discovery" +version = "1.2.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "filelock" }, + { name = "platformdirs" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/de/ef/3bae0e537cfe91e8431efcba4434463d2c5a65f5a89edd47c6cf2f03c55f/python_discovery-1.2.2.tar.gz", hash = "sha256:876e9c57139eb757cb5878cbdd9ae5379e5d96266c99ef731119e04fffe533bb", size = 58872, upload-time = "2026-04-07T17:28:49.249Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d8/db/795879cc3ddfe338599bddea6388cc5100b088db0a4caf6e6c1af1c27e04/python_discovery-1.2.2-py3-none-any.whl", hash = "sha256:e1ae95d9af875e78f15e19aed0c6137ab1bb49c200f21f5061786490c9585c7a", size = 31894, upload-time = "2026-04-07T17:28:48.09Z" }, +] + [[package]] name = "pyyaml" version = "6.0.3" @@ -238,3 +329,18 @@ sdist = { url = "https://files.pythonhosted.org/packages/72/94/1a15dd82efb362ac8 wheels = [ { url = "https://files.pythonhosted.org/packages/18/67/36e9267722cc04a6b9f15c7f3441c2363321a3ea07da7ae0c0707beb2a9c/typing_extensions-4.15.0-py3-none-any.whl", hash = "sha256:f0fa19c6845758ab08074a0cfa8b7aecb71c999ca73d62883bc25cc018c4e548", size = 44614, upload-time = "2025-08-25T13:49:24.86Z" }, ] + +[[package]] +name = "virtualenv" +version = "21.2.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "distlib" }, + { name = "filelock" }, + { name = "platformdirs" }, + { name = "python-discovery" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/97/c5/aff062c66b42e2183201a7ace10c6b2e959a9a16525c8e8ca8e59410d27a/virtualenv-21.2.1.tar.gz", hash = "sha256:b66ffe81301766c0d5e2208fc3576652c59d44e7b731fc5f5ed701c9b537fa78", size = 5844770, upload-time = "2026-04-09T18:47:11.482Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/20/0e/f083a76cb590e60dff3868779558eefefb8dfb7c9ed020babc7aa014ccbf/virtualenv-21.2.1-py3-none-any.whl", hash = "sha256:bd16b49c53562b28cf1a3ad2f36edb805ad71301dee70ddc449e5c88a9f919a2", size = 5828326, upload-time = "2026-04-09T18:47:09.331Z" }, +]