From 20ad711bf05a853650a09ac6602d352b8fa4b624 Mon Sep 17 00:00:00 2001 From: Rae Sharp Date: Mon, 30 Mar 2026 13:41:45 -0400 Subject: [PATCH 1/3] add new skill --- .claude/skills/upbound-docs-gen/SKILL.md | 338 ++++++++++++++++++ .../skills/upbound-docs-gen/evals/evals.json | 55 +++ .../references/product-context.md | 128 +++++++ .../references/style-guide.md | 161 +++++++++ .../upbound-docs-gen/references/templates.md | 221 ++++++++++++ 5 files changed, 903 insertions(+) create mode 100644 .claude/skills/upbound-docs-gen/SKILL.md create mode 100644 .claude/skills/upbound-docs-gen/evals/evals.json create mode 100644 .claude/skills/upbound-docs-gen/references/product-context.md create mode 100644 .claude/skills/upbound-docs-gen/references/style-guide.md create mode 100644 .claude/skills/upbound-docs-gen/references/templates.md diff --git a/.claude/skills/upbound-docs-gen/SKILL.md b/.claude/skills/upbound-docs-gen/SKILL.md new file mode 100644 index 000000000..0685bcbc6 --- /dev/null +++ b/.claude/skills/upbound-docs-gen/SKILL.md @@ -0,0 +1,338 @@ +--- +name: upbound-docs-gen +description: > + Generates documentation for Upbound Spaces and UXP products following Upbound's established + style, voice, templates, and formatting standards. Use this skill whenever a user is: + - Writing new docs for a Spaces or UXP feature, concept, or workflow + - Asking for help drafting or structuring any documentation that will live in up-docs + - Describing a new feature, behavior change, or API surface and wanting to turn it into a doc + - Asking "how should I document X" or "write a doc for X" in the context of Upbound products + - Working on release notes, how-to guides, tutorials, concept docs, or troubleshooting content + This skill should trigger broadly — if the user is writing any kind of Upbound or Crossplane + documentation, even if they don't say "docs" explicitly, use this skill. +--- + +# Upbound Documentation Generator + +You help engineers and product managers write documentation for Upbound's Spaces and UXP products. Your output should be ready for human review — correct structure, compliant style, and real content filled in wherever possible based on what the user tells you. + +## Step 1: Understand what you're writing + +Ask the user for enough context to write well. You don't need to be exhaustive — 2-3 targeted questions is better than a lengthy interview. The key things to nail down: + +1. **What type of doc is this?** (concept, how-to, tutorial, troubleshooting, release notes, reference) +2. **What product and feature does it cover?** (Cloud Spaces, Self-Hosted Spaces, UXP, a specific CRD/API, CLI command, etc.) +3. **Who is the reader?** (platform engineer, developer, operator, admin — and their assumed knowledge level) +4. **What does the user already have?** (PR description, design doc, notes, a rough draft, just an idea) + +If the user gives you rich context upfront (e.g., pastes a PR description or feature spec), skip the questions you can answer from that context. + +## Step 2: Research the repo before drafting + +This is the most important step. Before writing anything, search the repo for related existing content. The docs repo is at https://github.com/upbound/docs + +**Why this matters:** The repo has rich, detailed docs for many features. If you skip this step, you'll produce a shallow stub that misses depth, structure, repo-specific components, and conventions that real docs in this codebase use. + +**What to look for:** + +1. **Does a doc already exist for this topic?** Search for the feature name across `docs/`, `cloud-spaces-docs/`, and `self-hosted-spaces-docs/`. If a doc exists and the user is adding to it or updating it, your output should be a diff/addition to that file — not a new file. + +2. **Are there closely related docs that set depth expectations?** If someone asks you to document "auto-upgrade for control planes," find the existing auto-upgrade doc and match its depth — number of channels covered, YAML examples, version support tables, kubectl output examples, etc. + +3. **What React components does this section use?** Browse nearby docs for imports and custom components. Common ones: + - `` or `` — plan-gating callouts at the top of the page + - `` / `` — multi-variant examples + - `` — shared content blocks + +4. **What's the sidebar weight convention in this directory?** Check neighboring files to pick a reasonable `weight`. + +Only after doing this research should you start writing. + +### Reading the engineering repo (optional but high-value) + +If the user provides a path to an engineering repo, a branch name, or a PR — and you have read access to it — run a targeted diff against main before drafting. This is the most reliable way to get complete, accurate field names, enum values, and defaults without relying on what the engineer remembered to mention. + +**When to do this:** The user says something like "here's the PR", "it's on branch `feat/shared-secret-store`", "the repo is at `~/upbound/spaces`", or pastes a link to a GitHub PR. + +**What to extract:** + +1. **CRD/API changes** — run `git diff main...HEAD -- '*.yaml' '*.go'` (or the branch name they give you) in the engineering repo. Look for: + - New fields added to CRD specs (`spec.versions[].schema.openAPIV3Schema`) + - `enum:` lists — these are the complete set of valid values + - `default:` values — always document these explicitly + - `required:` arrays — these fields must appear in every example + - `description:` strings on fields — often the clearest source of what a field does + +2. **Go type definitions** — if CRD YAML isn't present, search for the relevant Go struct. `+kubebuilder:validation:Enum` markers are authoritative for valid values. `// +optional` marks optional fields. + +3. **What NOT to use from the engineering repo:** + - Internal implementation details, algorithm logic, or architecture decisions — document the external behavior, not the internals + - Draft/WIP comments or TODO annotations — these aren't user-facing + - Test fixtures or example files that contradict the schema + +**How to apply it:** Use the extracted values to fill in your YAML examples, options tables, and any version or constraint notes. If the diff shows 4 enum values but the user only mentioned 2, include all 4 and note the source. If you find a `default:` value, call it out explicitly in prose ("defaults to `Stable` if not set"). + +If you don't have access to the engineering repo (no path given, no branch, no access), skip this section and note at the end of your draft that field completeness was based on user description only. + +## Step 3: Choose the right template + +Read `references/templates.md` for the full template bodies. Choose based on the user's intent: + +| Doc type | Use when | Template | +|---|---|---| +| **Concept** | Explaining what something is, how it works, when to use it | concept | +| **How-to** | Task-oriented: "how to configure X", "how to enable Y" | howto | +| **Tutorial** | Learning-oriented: end-to-end walkthrough with a goal | tutorial | +| **Troubleshooting** | Symptom → cause → solution for known problems | troubleshooting | +| **Release notes** | New version, what changed | See release notes section below | + +When the user isn't sure, ask. Or make a judgment call and tell them — it's easier for them to react to a choice than to make one from scratch. + +## Step 4: Write the doc + +### Frontmatter + +Every doc needs frontmatter. Include at minimum: + +```yaml +--- +title: Title of the doc (sentence case) +weight: +--- +``` + +Add `description` for pages likely to appear in search results. Add `sidebar_label` if the title is long. + +### Voice and style + +Read `references/style-guide.md` for the complete rules. The most important ones: + +- **Active voice.** "Upbound deploys the control plane" not "the control plane is deployed" +- **Present tense.** "Spaces uses" not "Spaces will use" +- **Sentence-case headings.** "Configure a control plane" not "Configure a Control Plane" +- **Direct, second person.** "You create a control plane" or "Create a control plane" +- **No jargon softeners.** Don't write "simply", "easily", "just", or "obviously" +- **Short sentences.** Aim for under 25 words per sentence +- **No Latin.** Write "for example" not "e.g.", "that is" not "i.e." +- **Code formatting.** Kubernetes resource kinds in `UpperCamelCase`; object names in `kebab-case`; use inline backticks for file paths, commands, and field names +- **Contractions are fine.** "Don't" is better than "do not" in most contexts + +### AI writing patterns to avoid + +Technical docs are especially prone to AI-sounding language. Actively scan your draft for these before presenting it. + +**Banned AI vocabulary** — these words appear disproportionately in AI-generated text. Replace them with plain alternatives: + +| Avoid | Use instead | +|---|---| +| additionally | also, and, next | +| align with | match, follow, work with | +| crucial / pivotal / key (adj) | important, required, critical | +| delve | look at, explore, examine | +| enhance / enhancing | improve, increase, add | +| foster / fostering | build, grow, support | +| highlight (verb) | show, call out, note | +| intricate / intricacies | complex, the details | +| landscape (abstract) | environment, ecosystem, area | +| showcase | show, demonstrate | +| tapestry | (delete — never use abstractly) | +| testament | proof, evidence | +| underscore (verb) | show, confirm | +| vibrant / robust | (delete — use specific facts) | + +**Inflated significance** — don't puff up importance. Say what something does, not what it represents. + +- Bad: "This marks a pivotal moment in how teams manage infrastructure at scale." +- Good: "This lets teams provision clusters without writing AWS CloudFormation." + +**Copula avoidance** — use `is`/`are`/`has`. Don't dress up simple facts. + +- Bad: "Spaces serves as the platform for running managed control planes." +- Good: "Spaces is the platform for running managed control planes." + +**Promotional language** — docs aren't marketing copy. Remove: `boasts`, `groundbreaking`, `powerful`, `seamless`, `intuitive`, `nestled`, `rich` (figurative), `breathtaking`, `stunning`. + +**Superficial -ing phrases** — watch for present participles tacked on to fake depth: "...ensuring that teams can...", "...highlighting the importance of...", "...reflecting the platform's commitment to...". Delete them or make the point directly. + +**Em dash overuse** — use em dashes sparingly. Two per page is plenty. Commas and periods usually work better. + +**Filler phrases** — delete on sight: +- "In order to" → "To" +- "It is important to note that" → (delete — just say the thing) +- "Due to the fact that" → "Because" +- "Has the ability to" → "Can" +- "At this point in time" → "Now" + +**Chatbot artifacts** — never leave these in a draft: +- "I hope this helps" +- "Here is a draft of..." +- "Let me know if you'd like me to expand on any section" +- "Great question!" +- "Certainly!" + +**Generic positive conclusions** — don't end docs with vague optimism. End with a specific next step or link. + +- Bad: "The future looks bright as teams continue their journey toward cloud-native excellence." +- Good: "See [upgrade channels](./auto-upgrade.md) for the next step." + +**Rule of three** — don't force ideas into groups of three. "EKS provisioning, RDS databases, and networking" is fine when there are genuinely three things. Don't manufacture a third item to complete a pattern. + +**Inline-header bullet lists** — avoid bolded labels followed by colons in every list item. Either use a table or write prose. + +- Bad: `- **Performance:** Optimized for low latency.` +- Good: Use a table, or fold it into a sentence. + +### Depth and completeness + +Match the depth of surrounding docs. A good doc for a configurable feature typically includes: + +- All valid values/options, not just the ones mentioned in the user's prompt +- At least one complete YAML example showing the full relevant spec (not just the field being changed) +- Expected output or verification steps (for example, `kubectl get ctp` output showing what success looks like) +- Edge cases or warnings relevant to specific options +- Links to related reference docs (CRD reference, CLI reference, version support tables) + +If the user gave you partial information (for example, only two of four channels), note what's missing and ask, or flag it as a placeholder. + +### Procedural steps + +How-to docs and tutorials must use numbered steps for any sequence of actions the reader performs. Don't replace numbered steps with prose paragraphs followed by code blocks — even if you find existing docs in the repo that do this. Numbered steps are the correct pattern and existing docs are being updated to match. + +Each step should start with a verb and stand alone as an instruction. Supporting explanation, code examples, and expected output go indented under the step: + +```markdown +1. Create a `ControlPlane` manifest. + + ```yaml + # example yaml + ``` + +2. Apply the manifest to your cluster. + + ```shell + kubectl apply -f control-plane.yaml + ``` + + The control plane appears with `READY: True` within a few minutes. +``` + +### Formatting conventions + +**Admonitions** — use sparingly for truly important information: +``` +:::tip +Helpful but optional information. +::: + +:::warning +Something that could cause data loss or unexpected behavior. +::: + +:::info +Neutral contextual information. +::: + +:::danger +Action that can't be undone. +::: +``` + +**Tabs** — use for content that varies by environment, provider, or approach: +```mdx +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + + + +...content... + + +...content... + + +``` + +**Code blocks** — always specify the language. Use `shell` for terminal commands, `yaml` for YAML, `bash` for scripts. + +**Internal links** — use Docusaurus relative syntax: +```markdown +[link text](./path/to/file.md) +``` + +**Images** — reference from `/static/images/`: +```markdown +![Alt text describing image](/images/path/to/image.png) +``` + +### Product context + +Read `references/product-context.md` for the full glossary and product structure. Key terms to get right: + +- **Spaces** — the platform for running managed control planes. Can be Cloud Spaces (Upbound-hosted) or Self-Hosted Spaces (customer-hosted) +- **UXP** — Upbound Crossplane, the enterprise Crossplane distribution +- **Control plane** — a fully isolated Crossplane instance. Referred to as "control plane" in prose (not MCP, not CTP) +- **Kubernetes resource kinds** — always `UpperCamelCase` (for example, `ControlPlane`, `SharedSecretStore`) +- Do not abbreviate Kubernetes as "k8s" in docs + +### Release notes format + +Release notes live in a **single file** at `docs/reference/release-notes/spaces.md`. New versions are prepended at the top (after the frontmatter). Do not create a separate file per version. + +The file starts with `` — all release note entries inherit this. The format for each version entry: + +```markdown +## vX.Y.Z + +### Release Date: YYYY-MM-DD + +#### Breaking Changes + +:::important +- **Field or behavior name**: what changed and what the user must do before upgrading. +::: + +#### Features + +**Feature name:** + +1-2 sentences on what it does and why it matters. Link to the full doc if one exists. + +#### Bug fixes + +- **Short label**: what was broken and what was fixed. + +#### Upgrade notes + +Any steps or constraints for upgrading from the previous version. +``` + +Notes: +- Use `:::important` (not `:::warning`) for breaking changes — this matches the existing file convention +- Section names use Title Case (`#### Breaking Changes`, `#### Features`, `#### Bug fixes`) — again, matching the file +- The version heading `## vX.Y.Z` is the identifier, not frontmatter +- Only include sections that apply — omit empty sections + +## Step 5: Present the output + +Produce a complete, ready-to-review markdown file. Fill in everything you can from the context the user gave you and your repo research. Use `{placeholder}` notation only for things genuinely unknown. + +After producing the draft: +1. State whether this is a new file or an edit to an existing one, and give the suggested file path +2. Call out any sections you left as placeholders and why +3. Note any Vale rules the draft might trip on (passive voice is the most common) +4. Offer to generate the paired doc type if it doesn't already exist (see below) +5. Ask if they want to adjust anything + +## Paired doc types + +Concept and how-to docs are natural pairs. After finishing either one, check whether the counterpart exists and offer to generate it: + +- **After a concept doc**: "Want me to also write a how-to for [the main task this concept enables]?" For example, a concept doc on control plane groups naturally pairs with how-tos for creating groups, managing access, and configuring shared secrets. +- **After a how-to**: "Want me to also write a concept doc explaining [the thing this guide operates on]?" For example, a how-to for enabling auto-upgrades pairs with a concept doc explaining what upgrade channels are and how the version support window works. + +Check the repo first (`docs/`, `cloud-spaces-docs/`, `self-hosted-spaces-docs/`) — if the paired doc already exists, point to it instead of offering to generate a duplicate. If it exists but is thin (stub-level content), offer to improve it rather than replace it. + +## What you're not doing + +- You're not running Vale or building the site — that's for the user to do locally +- You're not auto-generating CRD reference docs — those come from `npm run process-crds` diff --git a/.claude/skills/upbound-docs-gen/evals/evals.json b/.claude/skills/upbound-docs-gen/evals/evals.json new file mode 100644 index 000000000..096b81afb --- /dev/null +++ b/.claude/skills/upbound-docs-gen/evals/evals.json @@ -0,0 +1,55 @@ +{ + "skill_name": "upbound-docs-gen", + "evals": [ + { + "id": 0, + "prompt": "Hey, I just merged a PR that adds support for automatic control plane upgrades in Self-Hosted Spaces. When you configure it, you set `autoUpgrade.channel` in the ControlPlane spec to either `Stable` or `Rapid`. Can you write the how-to doc for enabling this?", + "expected_output": "A complete how-to guide markdown file with proper frontmatter, prerequisites section, numbered steps, code examples showing the ControlPlane spec with autoUpgrade.channel field, and a see-also section. Should follow Upbound style: active voice, present tense, sentence-case headings, proper code formatting.", + "files": [] + }, + { + "id": 1, + "prompt": "We need a concept doc explaining control plane groups — what they are, why you'd use them, and how they relate to individual control planes. Can you write it?", + "expected_output": "A concept doc with proper frontmatter, definition of control plane groups, use cases, relationship to individual control planes, and related resources. Should use correct Upbound terminology (ControlPlaneGroup kind, kebab-case names), active voice, and follow concept template structure.", + "files": [] + }, + { + "id": 2, + "prompt": "I need to write release notes for Spaces v1.12.0. Changes: new SharedSecretStore feature that lets control planes share secrets within a group; bug fix where control planes sometimes got stuck in Pending state after a node restart; breaking change: the `spec.crossplane.version` field is now required.", + "expected_output": "Release notes entry (not a separate file) matching the actual spaces.md format: ## vX.Y.Z version heading, #### subsections (Breaking Changes, Features, Bug fixes), :::important admonition for breaking changes, SharedSecretStore and spec.crossplane.version both mentioned.", + "assertions": [ + { + "id": "has-version-heading", + "text": "Document contains a `## v1.12.0` version heading (matching the single-file format)", + "type": "programmatic" + }, + { + "id": "has-breaking-changes-section", + "text": "Document contains a `#### Breaking Changes` section", + "type": "programmatic" + }, + { + "id": "important-admonition-in-breaking-changes", + "text": "`:::important` admonition appears in or near the breaking changes section", + "type": "programmatic" + }, + { + "id": "has-features-or-whats-changed", + "text": "Document contains a `#### Features`, `#### What's Changed`, or `#### What's new` section", + "type": "programmatic" + }, + { + "id": "SharedSecretStore-mentioned", + "text": "`SharedSecretStore` appears in the document", + "type": "programmatic" + }, + { + "id": "required-field-mentioned", + "text": "`spec.crossplane.version` appears in the document", + "type": "programmatic" + } + ], + "files": [] + } + ] +} diff --git a/.claude/skills/upbound-docs-gen/references/product-context.md b/.claude/skills/upbound-docs-gen/references/product-context.md new file mode 100644 index 000000000..d0408e59e --- /dev/null +++ b/.claude/skills/upbound-docs-gen/references/product-context.md @@ -0,0 +1,128 @@ +# Upbound Product Context + +Reference for accurate terminology and product structure in documentation. + +--- + +## Products + +### UXP — Upbound Crossplane + +Upbound's enterprise distribution of Crossplane. Use "UXP" after spelling out "Upbound Crossplane" on first use per page. Features include: +- Intelligent Control Planes (AI-powered reconciliation) +- Function Scale-to-Zero +- Pod Autoscaling +- Backup and Restore +- Enterprise add-ons and support + +UXP can run standalone on a customer's Kubernetes cluster, or hosted inside Spaces. + +### Spaces + +The hosting platform for managed Crossplane control planes. Spaces come in several variants: + +| Variant | Who operates it | Who manages the software | +|---|---|---| +| **Cloud Spaces** | Upbound | Upbound | +| **Dedicated Spaces** | Upbound (single-tenant) | Upbound | +| **Self-Hosted Spaces** | Customer | Customer | +| **Managed Spaces** | Customer (provides infra) | Upbound | + +In prose, refer to the specific variant when it matters. Use "Spaces" generically when a statement applies to all variants. + +--- + +## Core concepts + +### Control plane + +A fully isolated Crossplane instance managed within Spaces. In the API, represented by the `ControlPlane` kind. In CLI, often referenced as `ctp`. + +- Prefer "control plane" (lowercase) in prose +- Use `ControlPlane` when referring to the Kubernetes resource kind +- Don't use "MCP" (Managed Control Plane) as a general term — it's legacy Cloud Spaces terminology +- Don't use "CTP" in prose — it's a CLI abbreviation + +### Control plane group + +A logical grouping of control planes that share configuration. Represented by the `ControlPlaneGroup` kind. + +### Space + +A hosting environment, roughly analogous to a region or cluster, that contains control plane groups. Represented by the `Space` kind in the API. + +### Connector + +Mechanism for connecting a Self-Hosted Spaces installation to Upbound's management plane. + +### SharedSecretStore + +A CRD for sharing secrets between control planes within a group. + +--- + +## CLI and tooling + +- **`up` CLI** — the primary Upbound command-line tool +- **`kubectl`** — for direct cluster interactions +- **`helm`** — for installing Spaces + +Common CLI command patterns to document accurately: +```shell +up ctp create +up ctp get +up ctp delete +up group create +``` + +--- + +## Documentation structure + +The repo has three separate Docusaurus documentation spaces: + +| Space | Path | URL prefix | +|---|---|---| +| Main docs | `docs/` | `/` | +| Cloud Spaces docs | `cloud-spaces-docs/` | `/cloud-spaces/` | +| Self-Hosted Spaces docs | `self-hosted-spaces-docs/` | `/self-hosted-spaces/` | + +When generating docs, confirm with the user which space the content belongs in. This affects the file path and sidebar. + +### Main docs sections + +- `docs/getstarted/` — Introduction, quickstarts, first-run tutorials +- `docs/guides/` — Solution-focused and architectural guides +- `docs/manuals/uxp/` — UXP feature documentation +- `docs/manuals/cli/` — CLI reference and usage +- `docs/manuals/console/` — Web console documentation +- `docs/reference/` — Auto-generated API/CRD reference, Helm values, release notes + +### Cloud and Self-Hosted Spaces docs sections + +Both follow a similar pattern: +- `concepts/` — Conceptual documentation +- `how-to/` — Task-oriented guides +- `reference/` — API reference + +--- + +## Common external references + +When linking to related resources, these are the authoritative sources: +- Crossplane docs: `https://docs.crossplane.io` +- Kubernetes docs: `https://kubernetes.io/docs` +- Upbound marketplace: `https://marketplace.upbound.io` + +--- + +## Terminology to avoid + +| Avoid | Use instead | +|---|---| +| k8s | Kubernetes | +| MCP | control plane (or "managed control plane" only in Cloud Spaces context) | +| CTP | control plane | +| xp | Crossplane | +| Easy / simple / just | (omit or rephrase) | +| The user | You / the operator / the developer (be specific) | diff --git a/.claude/skills/upbound-docs-gen/references/style-guide.md b/.claude/skills/upbound-docs-gen/references/style-guide.md new file mode 100644 index 000000000..6581a76ad --- /dev/null +++ b/.claude/skills/upbound-docs-gen/references/style-guide.md @@ -0,0 +1,161 @@ +# Upbound Documentation Style Guide + +Source of truth: `README.md` and `CONTRIBUTING.md` in the up-docs repo. + +--- + +## Voice and tone + +- **Active voice.** Subject performs the action. + - ✓ "Upbound deploys the control plane" + - ✗ "The control plane is deployed by Upbound" +- **Present tense.** Avoid "will" unless genuinely future-tense. + - ✓ "Spaces creates a control plane" + - ✗ "Spaces will create a control plane" +- **Second person.** Address the reader as "you." +- **Contractions are encouraged.** "Don't", "it's", "you'll" — these read more naturally. +- **No jargon softeners.** Never use "easy", "simple", "just", "obviously", "straightforward". These minimize the reader's experience. +- **No Latin abbreviations.** Write "for example" not "e.g."; "that is" not "i.e."; avoid "etc." — list what you mean or say "and others". +- **No clichés.** "Robust", "seamless", "cutting-edge", "game-changer" — avoid. + +--- + +## Headings + +- Sentence case: "Configure a control plane" not "Configure a Control Plane" +- Start with a verb for task-oriented sections: "Create a group", "Enable GitOps" +- Don't use gerunds in headings: "Configure" not "Configuring" +- Limit to H2 and H3 in most docs; H4 and deeper usually means the structure needs rethinking + +--- + +## Sentences and paragraphs + +- Target under 25 words per sentence +- One idea per sentence +- No Oxford commas: "Spaces, UXP and Crossplane" not "Spaces, UXP, and Crossplane" +- Keep paragraphs short — 3-4 sentences max in most cases +- 80-character line wrapping in source files + +--- + +## Capitalization + +| Term | Correct | +|---|---| +| Upbound Crossplane | UXP (always spell out first use per page) | +| Crossplane | Always capitalized | +| Kubernetes | Always capitalized, never "k8s" | +| control plane | lowercase (noun) | +| Spaces | Capitalized as a product name | +| Cloud Spaces | Capitalized | +| Self-Hosted Spaces | Capitalized | +| Provider names | AWS, Azure, GCP (alphabetical order to avoid bias) | + +--- + +## Code and technical formatting + +**Kubernetes resource kinds** — `UpperCamelCase`: +- `ControlPlane`, `SharedSecretStore`, `CompositeResourceDefinition` + +**Object names and labels** — `kebab-case`: +- `my-control-plane`, `team-platform` + +**Inline code** (single backticks) for: +- File paths: `` `/etc/config.yaml` `` +- CLI commands: `` `up ctp create` `` +- Field names: `` `spec.parameters.region` `` +- Environment variables: `` `KUBECONFIG` `` + +**Placeholders** — angle brackets in code blocks: +```shell +up ctp create +``` + +**Code block language hints** — always specify: +- `yaml` for YAML +- `shell` for terminal commands +- `bash` for scripts +- `json` for JSON +- `console` or `text` for terminal output you're not asking them to run + +--- + +## Links + +Internal links — use Docusaurus relative syntax: +```markdown +[Configure a control plane](./configure-control-plane.md) +``` + +External links — use full URL: +```markdown +[Crossplane documentation](https://docs.crossplane.io) +``` + +Don't use "click here" or "here" as link text. The link text should describe the destination. + +--- + +## Lists + +- Use ordered lists for sequential steps +- Use unordered lists for non-sequential items +- Don't use lists for fewer than 3 items — use prose instead +- Start each list item with a capital letter +- No period at end of list items unless they're full sentences + +--- + +## Images + +- Place in `/static/images/` +- Reference as `/images/path/to/image.png` (not `/static/images/...`) +- Always include meaningful alt text +- Prefer diagrams that explain architecture or flow over screenshots + +--- + +## Vale enforcement + +Vale runs automatically in CI and blocks PRs with errors. These style guides are active: +- Google, Microsoft, ProseInt, Write-Good, GitLab, Alex, Upbound + +To disable a rule for a specific passage: +```markdown + +Text that trips the rule + +``` + +To disable all Vale for a section (e.g., template boilerplate): +```markdown + +... + +``` + +--- + +## Admonitions + +Use sparingly. Don't admonition-wrap things that should just be prose. + +``` +:::tip +A helpful shortcut or best practice. Optional. +::: + +:::info +Neutral context that doesn't fit in the main flow. +::: + +:::warning +Something that could cause confusion, data loss, or unexpected behavior. +::: + +:::danger +Irreversible action or serious consequence. +::: +``` diff --git a/.claude/skills/upbound-docs-gen/references/templates.md b/.claude/skills/upbound-docs-gen/references/templates.md new file mode 100644 index 000000000..57589a0c7 --- /dev/null +++ b/.claude/skills/upbound-docs-gen/references/templates.md @@ -0,0 +1,221 @@ +# Documentation Templates + +These are the canonical templates from `/templates/` in the up-docs repo. +Use them as the structural starting point. Fill in `{placeholder}` content from what the user provides. + +--- + +## Concept template + +```markdown +--- +title: {Title in sentence case} +weight: {number} +--- + +{Opening paragraph: what is this concept, why it matters, what this doc covers.} + +{Concept name} is {definition}. {Optional: key attributes as a brief list.} + +{Optional: add a diagram or architecture image here.} + +## Background + +{Optional: context, history, or motivation — why was this designed this way?} + +## Use cases + +{How does the reader benefit from understanding this concept? What does it enable?} + +- Use case 1 +- Use case 2 + +## {Optional: Comparison of alternatives} + +{Table or prose comparing options when there are meaningful tradeoffs.} + +## Related resources + +If you'd like to dive deeper or start using {concept}, see: + +**How-to guides** +- [Link text](./path.md) + +**Related concepts** +- [Link text](./path.md) +``` + +--- + +## How-to template + +```markdown +--- +title: {Title: verb phrase, sentence case — "Configure a control plane"} +weight: {number} +--- + +This guide explains how to {brief description of task}. + +{Optional: when and why you'd do this.} + +## Prerequisites + +Before you {task}, ensure: + +- Prerequisite 1 +- Prerequisite 2 + +## {Task name — verb phrase} + +{Optional: brief context if not obvious from title.} + +1. {Step. Start with a verb.} + + {Explanatory text.} + + ```yaml + # Code sample + ``` + + {Optional: what the successful result looks like.} + +2. {Step.} + + 2.1. {Substep} + + 2.2. {Substep} + +## See also + +- [{Related guide}](./path.md) +- [{Related concept}](./path.md) +``` + +--- + +## Tutorial template + +```markdown +--- +title: {Title describing what you'll build or achieve} +weight: {number} +--- + +In this tutorial, you'll {main task}. This tutorial is intended for {audience} who have basic knowledge of: + +- {Concept 1} +- {Concept 2} + +By the end of this tutorial, you'll be able to: + +- {Learning objective 1} +- {Learning objective 2} + +## Background + +{Optional: product context, what problem this solves, why this approach.} + +## Before you start + +Before starting, ensure you have: + +- {Prerequisite 1} +- {Prerequisite 2} + +## {Task name} + +To get started, {first action}. + +1. {Step. Start with a verb.} + + {Explanatory text.} + + ```yaml + # Code sample + ``` + +2. {Step.} + + a. {Substep} + + b. {Substep} + +## Summary + +In this tutorial, you learned how to: + +- {Summary point 1} +- {Summary point 2} + +## Next steps + +- [{Related tutorial or guide}](./path.md) +- [{Related tutorial or guide}](./path.md) +``` + +--- + +## Troubleshooting template + +```markdown +--- +title: Troubleshoot {product or feature} +weight: {number} +--- + +This guide covers common issues with {product or feature} and how to resolve them. + +## {Symptom — describe what the user observes, e.g., error message text} + +### Cause + +{What causes this symptom.} + +### Solution + +{Steps to fix it. Use an ordered list if multi-step.} + +1. Step +2. Step + +{What a successful resolution looks like.} + +### For more information + +- [Related guide](./path.md) +``` + +--- + +## Release notes entry format + +Release notes are entries prepended into `docs/reference/release-notes/spaces.md` — NOT separate files. Each entry follows this format: + +```markdown +## vX.Y.Z + +### Release Date: YYYY-MM-DD + +#### Breaking Changes + +:::important +- **Field or behavior name**: what changed and what the user must do before upgrading. +::: + +#### Features + +**Feature name:** + +1-2 sentences on what it does and why it matters. Link to full doc if one exists. + +#### Bug fixes + +- **Short label**: what was broken and what was fixed. + +#### Upgrade notes + +Any steps or constraints for upgrading from the previous version. +``` + +The file has `` at the top — all entries inherit Vale suppression. Only include sections that have content. From fa22e21680c3eb734ef0168442e4ef6e49346bcc Mon Sep 17 00:00:00 2001 From: Rae Sharp Date: Tue, 7 Apr 2026 10:45:38 -0400 Subject: [PATCH 2/3] Adds initial Hub docs --- docs/manuals/console/install-hub.md | 107 +++++++++++++++++++++ docs/manuals/console/overview.md | 138 ++++++++++++++++++++++++++++ 2 files changed, 245 insertions(+) create mode 100644 docs/manuals/console/install-hub.md create mode 100644 docs/manuals/console/overview.md diff --git a/docs/manuals/console/install-hub.md b/docs/manuals/console/install-hub.md new file mode 100644 index 000000000..720df32d0 --- /dev/null +++ b/docs/manuals/console/install-hub.md @@ -0,0 +1,107 @@ +--- +title: Install Hub +weight: 1 +description: Install a self-hosted Hub deployment on a Kubernetes cluster using Helm. +validation: + type: procedural + owner: docs@upbound.io + tags: + - procedural + - hub + - installation +--- + +This guide installs Hub on a Kubernetes cluster in self-hosted mode. If you use Upbound Cloud, Hub is pre-installed — see [Connect a control plane][connectCP] to register your first cluster. + +## Prerequisites + +- A Kubernetes cluster version 1.24 or later, with cluster-admin access +- [up CLI][upCLI] v1.x or later +- Helm 3.x +- An OIDC provider: AWS IAM, Google Cloud Identity, Azure Entra ID, or a compatible custom provider +- At least one UXP instance, Space, OSS Crossplane cluster, or Kubernetes cluster to connect after installation + +## Install Hub + +1. Add the Upbound Helm repository. + + ```shell + helm repo add upbound https://charts.upbound.io + helm repo update + ``` + +2. Create a namespace for Hub. + + ```shell + kubectl create namespace upbound-hub + ``` + +3. Configure your OIDC provider. + + ```shell + up hub configure + ``` + + Enter your OIDC issuer URL, client ID, and client secret when prompted. You can also set these values directly in a `values.yaml` file for the Helm install step. + +4. Install Hub. + + ```shell + helm install hub upbound/hub \ + --namespace upbound-hub \ + --values values.yaml + ``` + +5. Verify the installation. + + ```shell + kubectl rollout status deployment/hub -n upbound-hub + ``` + + Hub is ready when the output shows `successfully rolled out`. + +The Hub Console is available at the endpoint defined in your `values.yaml`. + +## Connect a control plane + +1. Create a Realm to group your control planes. + + ```shell + up hub realm create myteam + ``` + +2. Generate a registration token for the Realm. + + ```shell + up hub connect --realm myteam + ``` + + The command outputs a registration token. Copy it for the next step. + +3. Apply the token on the target control plane. + + ```shell + kubectl apply -f + ``` + +4. Verify the connection. + + ```shell + up hub connect list + ``` + + The control plane appears in the list with a `Connected` status. + +5. Open the Hub Console and go to **Control Plane APIs**. Your newly connected cluster is visible there. + +## Next steps + +- [Use the Hub Console][console] — Explore dashboards and resource views +- [Manage Realms][realms] — Configure access control and add control planes to Realms +- [Run global queries][queries] — Use `up query` to search resources across your fleet + +[connectCP]: ./connect-control-plane.md +[console]: ./console.md +[realms]: ./manage-realms.md +[queries]: ./run-queries.md +[upCLI]: /manuals/cli/overview diff --git a/docs/manuals/console/overview.md b/docs/manuals/console/overview.md new file mode 100644 index 000000000..e5ec03efe --- /dev/null +++ b/docs/manuals/console/overview.md @@ -0,0 +1,138 @@ +--- +title: Hub +weight: 1 +description: Hub is a centralized API platform that aggregates resource state and provides unified visibility across your control plane fleet. +validation: + type: conceptual + owner: docs@upbound.io + tags: + - conceptual + - hub + - platform +--- + +Hub is a centralized API platform for managing your entire control plane fleet. Connect UXP instances, Spaces, OSS Crossplane clusters, and generic Kubernetes environments to Hub, then query resources, monitor health, and enforce access control across all of them from a single API surface. + +## Why Hub + +Without Hub, managing multiple control planes means logging into each cluster separately, manually correlating resource state, and maintaining separate access controls per cluster. Hub addresses this by: + +- Aggregating resource state across all connected control planes into a single queryable API +- Mirroring each control plane's RBAC so users see only what they can access via `kubectl` +- Automatically indexing packages and APIs from OCI artifacts across your fleet +- Monitoring reconciliation health in real time across your entire estate + +## Architecture + +Hub has four main components. + +| Component | Purpose | +|---|---| +| Hub API | RESTful API groups for global queries, control plane management, and catalog indexing | +| Hub Syncer | Agent running on each connected control plane, continuously pushing resource state to Hub | +| Hub Console | Web UI for dashboards, resource exploration, and infrastructure management | +| Hub CLI | `up hub` commands for registering control planes, managing Realms, and running queries | + +### API groups + +Hub exposes three API groups: + +- **Global Resources API** (`/apis/controlplane/v1/query`) — Aggregates resource state across all connected control planes. Supports filtering by resource type, health, Realm, control plane name, and labels. +- **Control Plane API** (`/apis/controlplane/v1`) — Register, monitor, and manage control plane connections. +- **Catalog API** (`/apis/catalog/v1`) — Index packages, extract CRD and XRD schemas, and track API utilization across your fleet. + +### Data flow + +Hub Syncer agents run on each connected control plane and continuously send resource state to the Hub API. The Console and CLI query that centralized state. Users interact through the Console, the `up` CLI, or direct API calls. + +## Core concepts + +### Realms + +A Realm is a logical boundary that groups control planes and defines access control. Realms let you organize resources by team, environment, business unit, or security zone. + +Within a Realm, team members have one of three roles: + +| Role | Access | +|---|---| +| `admin` | Manage the Realm and assign control planes to it | +| `edit` | Create and update resources | +| `view` | Read-only access | + +Teams are created automatically from your OIDC provider's identity groups and assigned to Realms. Users only see the control planes and resources in their assigned Realms. + +### Control plane connections + +A control plane connection registers a Kubernetes cluster with Hub. Hub supports four connection types: + +- UXP instances +- Cloud or Self-Hosted Spaces +- OSS Crossplane clusters +- Generic Kubernetes clusters + +After registration, Hub Syncer runs on the connected control plane and syncs resource state continuously. If a control plane becomes temporarily unavailable, Hub continues to serve the last cached state and resumes syncing when the cluster recovers. + +### Catalog + +The Catalog automatically indexes all packages available across your connected control planes. Hub extracts CRD and XRD schemas from OCI artifacts and makes them queryable. + +| Catalog resource | Description | +|---|---| +| Package | A versioned collection of providers, functions, or configurations in an OCI registry | +| API | A CRD or XRD schema extracted from a package | +| Utilization | Metrics tracking how each API is actively used across your fleet | + +### Authorization model + +Hub mirrors the RBAC from each connected control plane. A user with view-only access on a control plane sees only the resources accessible to them via `kubectl` on that cluster — no separate Hub permission layer is required. + +Hub uses OIDC for authentication. Supported identity providers: + +- AWS Cognito and AWS IAM +- Google Cloud Identity +- Azure Entra ID +- Custom OIDC-compatible providers (self-hosted only) + +## Deployment modes + +Hub runs in two modes. + +| Aspect | Self-Hosted | Upbound Cloud | +|---|---|---| +| Hosting | Your Kubernetes cluster | Upbound-managed infrastructure | +| Authentication | Configurable OIDC | Upbound IAM | +| Connected control planes | UXP, Spaces, OSS Crossplane, generic Kubernetes | Cloud-managed Spaces only (beta) | +| Installation | Helm chart | Pre-installed | + +**Self-Hosted** gives you full control over OIDC configuration, infrastructure, and the ability to connect a mix of control plane types. Use self-hosted Hub if you need to integrate with a specific enterprise identity provider or manage Hub infrastructure yourself. + +**Upbound Cloud** is the fully managed option. If you already use Upbound Cloud and Upbound IAM, Hub is pre-installed and ready to use. + +### Community tier + +Every UXP instance ships with Hub components pre-installed. The Community tier is for single control plane deployments. It includes the full Hub API and Console, accessible locally from your control plane, at no cost. + +To connect additional control planes and use fleet-wide features, upgrade to the Standard tier or higher. + +## Known limitations (beta) + +The following features are not yet available: + +- Robot users and Personal Access Tokens (PATs) +- SCIM provisioning +- OIDC providers beyond AWS, GCP, and Azure (self-hosted) +- Intent-based and natural language resource discovery +- Non-Cloud Spaces connected to Upbound Cloud Hub +- Full Marketplace integration +- Multi-cluster Hub federation (single Hub per organization in beta) +- Full audit logging + +## Next steps + +- [Install Hub][installHub] — Set up a self-hosted Hub deployment +- [Connect a control plane][connectCP] — Register your first control plane with Hub +- [Hub Console][console] — Navigate dashboards and resource views + +[installHub]: ../howtos/install-hub.md +[connectCP]: ../howtos/connect-control-plane.md +[console]: ../howtos/console.md From a70d00877afd87e5a14e714bce87788242815057 Mon Sep 17 00:00:00 2001 From: Rae Sharp Date: Tue, 14 Apr 2026 12:22:52 -0400 Subject: [PATCH 3/3] remove unrelated files --- .claude/skills/upbound-docs-gen/SKILL.md | 338 ------------------ .../skills/upbound-docs-gen/evals/evals.json | 55 --- .../references/product-context.md | 128 ------- .../references/style-guide.md | 161 --------- .../upbound-docs-gen/references/templates.md | 221 ------------ 5 files changed, 903 deletions(-) delete mode 100644 .claude/skills/upbound-docs-gen/SKILL.md delete mode 100644 .claude/skills/upbound-docs-gen/evals/evals.json delete mode 100644 .claude/skills/upbound-docs-gen/references/product-context.md delete mode 100644 .claude/skills/upbound-docs-gen/references/style-guide.md delete mode 100644 .claude/skills/upbound-docs-gen/references/templates.md diff --git a/.claude/skills/upbound-docs-gen/SKILL.md b/.claude/skills/upbound-docs-gen/SKILL.md deleted file mode 100644 index 0685bcbc6..000000000 --- a/.claude/skills/upbound-docs-gen/SKILL.md +++ /dev/null @@ -1,338 +0,0 @@ ---- -name: upbound-docs-gen -description: > - Generates documentation for Upbound Spaces and UXP products following Upbound's established - style, voice, templates, and formatting standards. Use this skill whenever a user is: - - Writing new docs for a Spaces or UXP feature, concept, or workflow - - Asking for help drafting or structuring any documentation that will live in up-docs - - Describing a new feature, behavior change, or API surface and wanting to turn it into a doc - - Asking "how should I document X" or "write a doc for X" in the context of Upbound products - - Working on release notes, how-to guides, tutorials, concept docs, or troubleshooting content - This skill should trigger broadly — if the user is writing any kind of Upbound or Crossplane - documentation, even if they don't say "docs" explicitly, use this skill. ---- - -# Upbound Documentation Generator - -You help engineers and product managers write documentation for Upbound's Spaces and UXP products. Your output should be ready for human review — correct structure, compliant style, and real content filled in wherever possible based on what the user tells you. - -## Step 1: Understand what you're writing - -Ask the user for enough context to write well. You don't need to be exhaustive — 2-3 targeted questions is better than a lengthy interview. The key things to nail down: - -1. **What type of doc is this?** (concept, how-to, tutorial, troubleshooting, release notes, reference) -2. **What product and feature does it cover?** (Cloud Spaces, Self-Hosted Spaces, UXP, a specific CRD/API, CLI command, etc.) -3. **Who is the reader?** (platform engineer, developer, operator, admin — and their assumed knowledge level) -4. **What does the user already have?** (PR description, design doc, notes, a rough draft, just an idea) - -If the user gives you rich context upfront (e.g., pastes a PR description or feature spec), skip the questions you can answer from that context. - -## Step 2: Research the repo before drafting - -This is the most important step. Before writing anything, search the repo for related existing content. The docs repo is at https://github.com/upbound/docs - -**Why this matters:** The repo has rich, detailed docs for many features. If you skip this step, you'll produce a shallow stub that misses depth, structure, repo-specific components, and conventions that real docs in this codebase use. - -**What to look for:** - -1. **Does a doc already exist for this topic?** Search for the feature name across `docs/`, `cloud-spaces-docs/`, and `self-hosted-spaces-docs/`. If a doc exists and the user is adding to it or updating it, your output should be a diff/addition to that file — not a new file. - -2. **Are there closely related docs that set depth expectations?** If someone asks you to document "auto-upgrade for control planes," find the existing auto-upgrade doc and match its depth — number of channels covered, YAML examples, version support tables, kubectl output examples, etc. - -3. **What React components does this section use?** Browse nearby docs for imports and custom components. Common ones: - - `` or `` — plan-gating callouts at the top of the page - - `` / `` — multi-variant examples - - `` — shared content blocks - -4. **What's the sidebar weight convention in this directory?** Check neighboring files to pick a reasonable `weight`. - -Only after doing this research should you start writing. - -### Reading the engineering repo (optional but high-value) - -If the user provides a path to an engineering repo, a branch name, or a PR — and you have read access to it — run a targeted diff against main before drafting. This is the most reliable way to get complete, accurate field names, enum values, and defaults without relying on what the engineer remembered to mention. - -**When to do this:** The user says something like "here's the PR", "it's on branch `feat/shared-secret-store`", "the repo is at `~/upbound/spaces`", or pastes a link to a GitHub PR. - -**What to extract:** - -1. **CRD/API changes** — run `git diff main...HEAD -- '*.yaml' '*.go'` (or the branch name they give you) in the engineering repo. Look for: - - New fields added to CRD specs (`spec.versions[].schema.openAPIV3Schema`) - - `enum:` lists — these are the complete set of valid values - - `default:` values — always document these explicitly - - `required:` arrays — these fields must appear in every example - - `description:` strings on fields — often the clearest source of what a field does - -2. **Go type definitions** — if CRD YAML isn't present, search for the relevant Go struct. `+kubebuilder:validation:Enum` markers are authoritative for valid values. `// +optional` marks optional fields. - -3. **What NOT to use from the engineering repo:** - - Internal implementation details, algorithm logic, or architecture decisions — document the external behavior, not the internals - - Draft/WIP comments or TODO annotations — these aren't user-facing - - Test fixtures or example files that contradict the schema - -**How to apply it:** Use the extracted values to fill in your YAML examples, options tables, and any version or constraint notes. If the diff shows 4 enum values but the user only mentioned 2, include all 4 and note the source. If you find a `default:` value, call it out explicitly in prose ("defaults to `Stable` if not set"). - -If you don't have access to the engineering repo (no path given, no branch, no access), skip this section and note at the end of your draft that field completeness was based on user description only. - -## Step 3: Choose the right template - -Read `references/templates.md` for the full template bodies. Choose based on the user's intent: - -| Doc type | Use when | Template | -|---|---|---| -| **Concept** | Explaining what something is, how it works, when to use it | concept | -| **How-to** | Task-oriented: "how to configure X", "how to enable Y" | howto | -| **Tutorial** | Learning-oriented: end-to-end walkthrough with a goal | tutorial | -| **Troubleshooting** | Symptom → cause → solution for known problems | troubleshooting | -| **Release notes** | New version, what changed | See release notes section below | - -When the user isn't sure, ask. Or make a judgment call and tell them — it's easier for them to react to a choice than to make one from scratch. - -## Step 4: Write the doc - -### Frontmatter - -Every doc needs frontmatter. Include at minimum: - -```yaml ---- -title: Title of the doc (sentence case) -weight: ---- -``` - -Add `description` for pages likely to appear in search results. Add `sidebar_label` if the title is long. - -### Voice and style - -Read `references/style-guide.md` for the complete rules. The most important ones: - -- **Active voice.** "Upbound deploys the control plane" not "the control plane is deployed" -- **Present tense.** "Spaces uses" not "Spaces will use" -- **Sentence-case headings.** "Configure a control plane" not "Configure a Control Plane" -- **Direct, second person.** "You create a control plane" or "Create a control plane" -- **No jargon softeners.** Don't write "simply", "easily", "just", or "obviously" -- **Short sentences.** Aim for under 25 words per sentence -- **No Latin.** Write "for example" not "e.g.", "that is" not "i.e." -- **Code formatting.** Kubernetes resource kinds in `UpperCamelCase`; object names in `kebab-case`; use inline backticks for file paths, commands, and field names -- **Contractions are fine.** "Don't" is better than "do not" in most contexts - -### AI writing patterns to avoid - -Technical docs are especially prone to AI-sounding language. Actively scan your draft for these before presenting it. - -**Banned AI vocabulary** — these words appear disproportionately in AI-generated text. Replace them with plain alternatives: - -| Avoid | Use instead | -|---|---| -| additionally | also, and, next | -| align with | match, follow, work with | -| crucial / pivotal / key (adj) | important, required, critical | -| delve | look at, explore, examine | -| enhance / enhancing | improve, increase, add | -| foster / fostering | build, grow, support | -| highlight (verb) | show, call out, note | -| intricate / intricacies | complex, the details | -| landscape (abstract) | environment, ecosystem, area | -| showcase | show, demonstrate | -| tapestry | (delete — never use abstractly) | -| testament | proof, evidence | -| underscore (verb) | show, confirm | -| vibrant / robust | (delete — use specific facts) | - -**Inflated significance** — don't puff up importance. Say what something does, not what it represents. - -- Bad: "This marks a pivotal moment in how teams manage infrastructure at scale." -- Good: "This lets teams provision clusters without writing AWS CloudFormation." - -**Copula avoidance** — use `is`/`are`/`has`. Don't dress up simple facts. - -- Bad: "Spaces serves as the platform for running managed control planes." -- Good: "Spaces is the platform for running managed control planes." - -**Promotional language** — docs aren't marketing copy. Remove: `boasts`, `groundbreaking`, `powerful`, `seamless`, `intuitive`, `nestled`, `rich` (figurative), `breathtaking`, `stunning`. - -**Superficial -ing phrases** — watch for present participles tacked on to fake depth: "...ensuring that teams can...", "...highlighting the importance of...", "...reflecting the platform's commitment to...". Delete them or make the point directly. - -**Em dash overuse** — use em dashes sparingly. Two per page is plenty. Commas and periods usually work better. - -**Filler phrases** — delete on sight: -- "In order to" → "To" -- "It is important to note that" → (delete — just say the thing) -- "Due to the fact that" → "Because" -- "Has the ability to" → "Can" -- "At this point in time" → "Now" - -**Chatbot artifacts** — never leave these in a draft: -- "I hope this helps" -- "Here is a draft of..." -- "Let me know if you'd like me to expand on any section" -- "Great question!" -- "Certainly!" - -**Generic positive conclusions** — don't end docs with vague optimism. End with a specific next step or link. - -- Bad: "The future looks bright as teams continue their journey toward cloud-native excellence." -- Good: "See [upgrade channels](./auto-upgrade.md) for the next step." - -**Rule of three** — don't force ideas into groups of three. "EKS provisioning, RDS databases, and networking" is fine when there are genuinely three things. Don't manufacture a third item to complete a pattern. - -**Inline-header bullet lists** — avoid bolded labels followed by colons in every list item. Either use a table or write prose. - -- Bad: `- **Performance:** Optimized for low latency.` -- Good: Use a table, or fold it into a sentence. - -### Depth and completeness - -Match the depth of surrounding docs. A good doc for a configurable feature typically includes: - -- All valid values/options, not just the ones mentioned in the user's prompt -- At least one complete YAML example showing the full relevant spec (not just the field being changed) -- Expected output or verification steps (for example, `kubectl get ctp` output showing what success looks like) -- Edge cases or warnings relevant to specific options -- Links to related reference docs (CRD reference, CLI reference, version support tables) - -If the user gave you partial information (for example, only two of four channels), note what's missing and ask, or flag it as a placeholder. - -### Procedural steps - -How-to docs and tutorials must use numbered steps for any sequence of actions the reader performs. Don't replace numbered steps with prose paragraphs followed by code blocks — even if you find existing docs in the repo that do this. Numbered steps are the correct pattern and existing docs are being updated to match. - -Each step should start with a verb and stand alone as an instruction. Supporting explanation, code examples, and expected output go indented under the step: - -```markdown -1. Create a `ControlPlane` manifest. - - ```yaml - # example yaml - ``` - -2. Apply the manifest to your cluster. - - ```shell - kubectl apply -f control-plane.yaml - ``` - - The control plane appears with `READY: True` within a few minutes. -``` - -### Formatting conventions - -**Admonitions** — use sparingly for truly important information: -``` -:::tip -Helpful but optional information. -::: - -:::warning -Something that could cause data loss or unexpected behavior. -::: - -:::info -Neutral contextual information. -::: - -:::danger -Action that can't be undone. -::: -``` - -**Tabs** — use for content that varies by environment, provider, or approach: -```mdx -import Tabs from '@theme/Tabs'; -import TabItem from '@theme/TabItem'; - - - -...content... - - -...content... - - -``` - -**Code blocks** — always specify the language. Use `shell` for terminal commands, `yaml` for YAML, `bash` for scripts. - -**Internal links** — use Docusaurus relative syntax: -```markdown -[link text](./path/to/file.md) -``` - -**Images** — reference from `/static/images/`: -```markdown -![Alt text describing image](/images/path/to/image.png) -``` - -### Product context - -Read `references/product-context.md` for the full glossary and product structure. Key terms to get right: - -- **Spaces** — the platform for running managed control planes. Can be Cloud Spaces (Upbound-hosted) or Self-Hosted Spaces (customer-hosted) -- **UXP** — Upbound Crossplane, the enterprise Crossplane distribution -- **Control plane** — a fully isolated Crossplane instance. Referred to as "control plane" in prose (not MCP, not CTP) -- **Kubernetes resource kinds** — always `UpperCamelCase` (for example, `ControlPlane`, `SharedSecretStore`) -- Do not abbreviate Kubernetes as "k8s" in docs - -### Release notes format - -Release notes live in a **single file** at `docs/reference/release-notes/spaces.md`. New versions are prepended at the top (after the frontmatter). Do not create a separate file per version. - -The file starts with `` — all release note entries inherit this. The format for each version entry: - -```markdown -## vX.Y.Z - -### Release Date: YYYY-MM-DD - -#### Breaking Changes - -:::important -- **Field or behavior name**: what changed and what the user must do before upgrading. -::: - -#### Features - -**Feature name:** - -1-2 sentences on what it does and why it matters. Link to the full doc if one exists. - -#### Bug fixes - -- **Short label**: what was broken and what was fixed. - -#### Upgrade notes - -Any steps or constraints for upgrading from the previous version. -``` - -Notes: -- Use `:::important` (not `:::warning`) for breaking changes — this matches the existing file convention -- Section names use Title Case (`#### Breaking Changes`, `#### Features`, `#### Bug fixes`) — again, matching the file -- The version heading `## vX.Y.Z` is the identifier, not frontmatter -- Only include sections that apply — omit empty sections - -## Step 5: Present the output - -Produce a complete, ready-to-review markdown file. Fill in everything you can from the context the user gave you and your repo research. Use `{placeholder}` notation only for things genuinely unknown. - -After producing the draft: -1. State whether this is a new file or an edit to an existing one, and give the suggested file path -2. Call out any sections you left as placeholders and why -3. Note any Vale rules the draft might trip on (passive voice is the most common) -4. Offer to generate the paired doc type if it doesn't already exist (see below) -5. Ask if they want to adjust anything - -## Paired doc types - -Concept and how-to docs are natural pairs. After finishing either one, check whether the counterpart exists and offer to generate it: - -- **After a concept doc**: "Want me to also write a how-to for [the main task this concept enables]?" For example, a concept doc on control plane groups naturally pairs with how-tos for creating groups, managing access, and configuring shared secrets. -- **After a how-to**: "Want me to also write a concept doc explaining [the thing this guide operates on]?" For example, a how-to for enabling auto-upgrades pairs with a concept doc explaining what upgrade channels are and how the version support window works. - -Check the repo first (`docs/`, `cloud-spaces-docs/`, `self-hosted-spaces-docs/`) — if the paired doc already exists, point to it instead of offering to generate a duplicate. If it exists but is thin (stub-level content), offer to improve it rather than replace it. - -## What you're not doing - -- You're not running Vale or building the site — that's for the user to do locally -- You're not auto-generating CRD reference docs — those come from `npm run process-crds` diff --git a/.claude/skills/upbound-docs-gen/evals/evals.json b/.claude/skills/upbound-docs-gen/evals/evals.json deleted file mode 100644 index 096b81afb..000000000 --- a/.claude/skills/upbound-docs-gen/evals/evals.json +++ /dev/null @@ -1,55 +0,0 @@ -{ - "skill_name": "upbound-docs-gen", - "evals": [ - { - "id": 0, - "prompt": "Hey, I just merged a PR that adds support for automatic control plane upgrades in Self-Hosted Spaces. When you configure it, you set `autoUpgrade.channel` in the ControlPlane spec to either `Stable` or `Rapid`. Can you write the how-to doc for enabling this?", - "expected_output": "A complete how-to guide markdown file with proper frontmatter, prerequisites section, numbered steps, code examples showing the ControlPlane spec with autoUpgrade.channel field, and a see-also section. Should follow Upbound style: active voice, present tense, sentence-case headings, proper code formatting.", - "files": [] - }, - { - "id": 1, - "prompt": "We need a concept doc explaining control plane groups — what they are, why you'd use them, and how they relate to individual control planes. Can you write it?", - "expected_output": "A concept doc with proper frontmatter, definition of control plane groups, use cases, relationship to individual control planes, and related resources. Should use correct Upbound terminology (ControlPlaneGroup kind, kebab-case names), active voice, and follow concept template structure.", - "files": [] - }, - { - "id": 2, - "prompt": "I need to write release notes for Spaces v1.12.0. Changes: new SharedSecretStore feature that lets control planes share secrets within a group; bug fix where control planes sometimes got stuck in Pending state after a node restart; breaking change: the `spec.crossplane.version` field is now required.", - "expected_output": "Release notes entry (not a separate file) matching the actual spaces.md format: ## vX.Y.Z version heading, #### subsections (Breaking Changes, Features, Bug fixes), :::important admonition for breaking changes, SharedSecretStore and spec.crossplane.version both mentioned.", - "assertions": [ - { - "id": "has-version-heading", - "text": "Document contains a `## v1.12.0` version heading (matching the single-file format)", - "type": "programmatic" - }, - { - "id": "has-breaking-changes-section", - "text": "Document contains a `#### Breaking Changes` section", - "type": "programmatic" - }, - { - "id": "important-admonition-in-breaking-changes", - "text": "`:::important` admonition appears in or near the breaking changes section", - "type": "programmatic" - }, - { - "id": "has-features-or-whats-changed", - "text": "Document contains a `#### Features`, `#### What's Changed`, or `#### What's new` section", - "type": "programmatic" - }, - { - "id": "SharedSecretStore-mentioned", - "text": "`SharedSecretStore` appears in the document", - "type": "programmatic" - }, - { - "id": "required-field-mentioned", - "text": "`spec.crossplane.version` appears in the document", - "type": "programmatic" - } - ], - "files": [] - } - ] -} diff --git a/.claude/skills/upbound-docs-gen/references/product-context.md b/.claude/skills/upbound-docs-gen/references/product-context.md deleted file mode 100644 index d0408e59e..000000000 --- a/.claude/skills/upbound-docs-gen/references/product-context.md +++ /dev/null @@ -1,128 +0,0 @@ -# Upbound Product Context - -Reference for accurate terminology and product structure in documentation. - ---- - -## Products - -### UXP — Upbound Crossplane - -Upbound's enterprise distribution of Crossplane. Use "UXP" after spelling out "Upbound Crossplane" on first use per page. Features include: -- Intelligent Control Planes (AI-powered reconciliation) -- Function Scale-to-Zero -- Pod Autoscaling -- Backup and Restore -- Enterprise add-ons and support - -UXP can run standalone on a customer's Kubernetes cluster, or hosted inside Spaces. - -### Spaces - -The hosting platform for managed Crossplane control planes. Spaces come in several variants: - -| Variant | Who operates it | Who manages the software | -|---|---|---| -| **Cloud Spaces** | Upbound | Upbound | -| **Dedicated Spaces** | Upbound (single-tenant) | Upbound | -| **Self-Hosted Spaces** | Customer | Customer | -| **Managed Spaces** | Customer (provides infra) | Upbound | - -In prose, refer to the specific variant when it matters. Use "Spaces" generically when a statement applies to all variants. - ---- - -## Core concepts - -### Control plane - -A fully isolated Crossplane instance managed within Spaces. In the API, represented by the `ControlPlane` kind. In CLI, often referenced as `ctp`. - -- Prefer "control plane" (lowercase) in prose -- Use `ControlPlane` when referring to the Kubernetes resource kind -- Don't use "MCP" (Managed Control Plane) as a general term — it's legacy Cloud Spaces terminology -- Don't use "CTP" in prose — it's a CLI abbreviation - -### Control plane group - -A logical grouping of control planes that share configuration. Represented by the `ControlPlaneGroup` kind. - -### Space - -A hosting environment, roughly analogous to a region or cluster, that contains control plane groups. Represented by the `Space` kind in the API. - -### Connector - -Mechanism for connecting a Self-Hosted Spaces installation to Upbound's management plane. - -### SharedSecretStore - -A CRD for sharing secrets between control planes within a group. - ---- - -## CLI and tooling - -- **`up` CLI** — the primary Upbound command-line tool -- **`kubectl`** — for direct cluster interactions -- **`helm`** — for installing Spaces - -Common CLI command patterns to document accurately: -```shell -up ctp create -up ctp get -up ctp delete -up group create -``` - ---- - -## Documentation structure - -The repo has three separate Docusaurus documentation spaces: - -| Space | Path | URL prefix | -|---|---|---| -| Main docs | `docs/` | `/` | -| Cloud Spaces docs | `cloud-spaces-docs/` | `/cloud-spaces/` | -| Self-Hosted Spaces docs | `self-hosted-spaces-docs/` | `/self-hosted-spaces/` | - -When generating docs, confirm with the user which space the content belongs in. This affects the file path and sidebar. - -### Main docs sections - -- `docs/getstarted/` — Introduction, quickstarts, first-run tutorials -- `docs/guides/` — Solution-focused and architectural guides -- `docs/manuals/uxp/` — UXP feature documentation -- `docs/manuals/cli/` — CLI reference and usage -- `docs/manuals/console/` — Web console documentation -- `docs/reference/` — Auto-generated API/CRD reference, Helm values, release notes - -### Cloud and Self-Hosted Spaces docs sections - -Both follow a similar pattern: -- `concepts/` — Conceptual documentation -- `how-to/` — Task-oriented guides -- `reference/` — API reference - ---- - -## Common external references - -When linking to related resources, these are the authoritative sources: -- Crossplane docs: `https://docs.crossplane.io` -- Kubernetes docs: `https://kubernetes.io/docs` -- Upbound marketplace: `https://marketplace.upbound.io` - ---- - -## Terminology to avoid - -| Avoid | Use instead | -|---|---| -| k8s | Kubernetes | -| MCP | control plane (or "managed control plane" only in Cloud Spaces context) | -| CTP | control plane | -| xp | Crossplane | -| Easy / simple / just | (omit or rephrase) | -| The user | You / the operator / the developer (be specific) | diff --git a/.claude/skills/upbound-docs-gen/references/style-guide.md b/.claude/skills/upbound-docs-gen/references/style-guide.md deleted file mode 100644 index 6581a76ad..000000000 --- a/.claude/skills/upbound-docs-gen/references/style-guide.md +++ /dev/null @@ -1,161 +0,0 @@ -# Upbound Documentation Style Guide - -Source of truth: `README.md` and `CONTRIBUTING.md` in the up-docs repo. - ---- - -## Voice and tone - -- **Active voice.** Subject performs the action. - - ✓ "Upbound deploys the control plane" - - ✗ "The control plane is deployed by Upbound" -- **Present tense.** Avoid "will" unless genuinely future-tense. - - ✓ "Spaces creates a control plane" - - ✗ "Spaces will create a control plane" -- **Second person.** Address the reader as "you." -- **Contractions are encouraged.** "Don't", "it's", "you'll" — these read more naturally. -- **No jargon softeners.** Never use "easy", "simple", "just", "obviously", "straightforward". These minimize the reader's experience. -- **No Latin abbreviations.** Write "for example" not "e.g."; "that is" not "i.e."; avoid "etc." — list what you mean or say "and others". -- **No clichés.** "Robust", "seamless", "cutting-edge", "game-changer" — avoid. - ---- - -## Headings - -- Sentence case: "Configure a control plane" not "Configure a Control Plane" -- Start with a verb for task-oriented sections: "Create a group", "Enable GitOps" -- Don't use gerunds in headings: "Configure" not "Configuring" -- Limit to H2 and H3 in most docs; H4 and deeper usually means the structure needs rethinking - ---- - -## Sentences and paragraphs - -- Target under 25 words per sentence -- One idea per sentence -- No Oxford commas: "Spaces, UXP and Crossplane" not "Spaces, UXP, and Crossplane" -- Keep paragraphs short — 3-4 sentences max in most cases -- 80-character line wrapping in source files - ---- - -## Capitalization - -| Term | Correct | -|---|---| -| Upbound Crossplane | UXP (always spell out first use per page) | -| Crossplane | Always capitalized | -| Kubernetes | Always capitalized, never "k8s" | -| control plane | lowercase (noun) | -| Spaces | Capitalized as a product name | -| Cloud Spaces | Capitalized | -| Self-Hosted Spaces | Capitalized | -| Provider names | AWS, Azure, GCP (alphabetical order to avoid bias) | - ---- - -## Code and technical formatting - -**Kubernetes resource kinds** — `UpperCamelCase`: -- `ControlPlane`, `SharedSecretStore`, `CompositeResourceDefinition` - -**Object names and labels** — `kebab-case`: -- `my-control-plane`, `team-platform` - -**Inline code** (single backticks) for: -- File paths: `` `/etc/config.yaml` `` -- CLI commands: `` `up ctp create` `` -- Field names: `` `spec.parameters.region` `` -- Environment variables: `` `KUBECONFIG` `` - -**Placeholders** — angle brackets in code blocks: -```shell -up ctp create -``` - -**Code block language hints** — always specify: -- `yaml` for YAML -- `shell` for terminal commands -- `bash` for scripts -- `json` for JSON -- `console` or `text` for terminal output you're not asking them to run - ---- - -## Links - -Internal links — use Docusaurus relative syntax: -```markdown -[Configure a control plane](./configure-control-plane.md) -``` - -External links — use full URL: -```markdown -[Crossplane documentation](https://docs.crossplane.io) -``` - -Don't use "click here" or "here" as link text. The link text should describe the destination. - ---- - -## Lists - -- Use ordered lists for sequential steps -- Use unordered lists for non-sequential items -- Don't use lists for fewer than 3 items — use prose instead -- Start each list item with a capital letter -- No period at end of list items unless they're full sentences - ---- - -## Images - -- Place in `/static/images/` -- Reference as `/images/path/to/image.png` (not `/static/images/...`) -- Always include meaningful alt text -- Prefer diagrams that explain architecture or flow over screenshots - ---- - -## Vale enforcement - -Vale runs automatically in CI and blocks PRs with errors. These style guides are active: -- Google, Microsoft, ProseInt, Write-Good, GitLab, Alex, Upbound - -To disable a rule for a specific passage: -```markdown - -Text that trips the rule - -``` - -To disable all Vale for a section (e.g., template boilerplate): -```markdown - -... - -``` - ---- - -## Admonitions - -Use sparingly. Don't admonition-wrap things that should just be prose. - -``` -:::tip -A helpful shortcut or best practice. Optional. -::: - -:::info -Neutral context that doesn't fit in the main flow. -::: - -:::warning -Something that could cause confusion, data loss, or unexpected behavior. -::: - -:::danger -Irreversible action or serious consequence. -::: -``` diff --git a/.claude/skills/upbound-docs-gen/references/templates.md b/.claude/skills/upbound-docs-gen/references/templates.md deleted file mode 100644 index 57589a0c7..000000000 --- a/.claude/skills/upbound-docs-gen/references/templates.md +++ /dev/null @@ -1,221 +0,0 @@ -# Documentation Templates - -These are the canonical templates from `/templates/` in the up-docs repo. -Use them as the structural starting point. Fill in `{placeholder}` content from what the user provides. - ---- - -## Concept template - -```markdown ---- -title: {Title in sentence case} -weight: {number} ---- - -{Opening paragraph: what is this concept, why it matters, what this doc covers.} - -{Concept name} is {definition}. {Optional: key attributes as a brief list.} - -{Optional: add a diagram or architecture image here.} - -## Background - -{Optional: context, history, or motivation — why was this designed this way?} - -## Use cases - -{How does the reader benefit from understanding this concept? What does it enable?} - -- Use case 1 -- Use case 2 - -## {Optional: Comparison of alternatives} - -{Table or prose comparing options when there are meaningful tradeoffs.} - -## Related resources - -If you'd like to dive deeper or start using {concept}, see: - -**How-to guides** -- [Link text](./path.md) - -**Related concepts** -- [Link text](./path.md) -``` - ---- - -## How-to template - -```markdown ---- -title: {Title: verb phrase, sentence case — "Configure a control plane"} -weight: {number} ---- - -This guide explains how to {brief description of task}. - -{Optional: when and why you'd do this.} - -## Prerequisites - -Before you {task}, ensure: - -- Prerequisite 1 -- Prerequisite 2 - -## {Task name — verb phrase} - -{Optional: brief context if not obvious from title.} - -1. {Step. Start with a verb.} - - {Explanatory text.} - - ```yaml - # Code sample - ``` - - {Optional: what the successful result looks like.} - -2. {Step.} - - 2.1. {Substep} - - 2.2. {Substep} - -## See also - -- [{Related guide}](./path.md) -- [{Related concept}](./path.md) -``` - ---- - -## Tutorial template - -```markdown ---- -title: {Title describing what you'll build or achieve} -weight: {number} ---- - -In this tutorial, you'll {main task}. This tutorial is intended for {audience} who have basic knowledge of: - -- {Concept 1} -- {Concept 2} - -By the end of this tutorial, you'll be able to: - -- {Learning objective 1} -- {Learning objective 2} - -## Background - -{Optional: product context, what problem this solves, why this approach.} - -## Before you start - -Before starting, ensure you have: - -- {Prerequisite 1} -- {Prerequisite 2} - -## {Task name} - -To get started, {first action}. - -1. {Step. Start with a verb.} - - {Explanatory text.} - - ```yaml - # Code sample - ``` - -2. {Step.} - - a. {Substep} - - b. {Substep} - -## Summary - -In this tutorial, you learned how to: - -- {Summary point 1} -- {Summary point 2} - -## Next steps - -- [{Related tutorial or guide}](./path.md) -- [{Related tutorial or guide}](./path.md) -``` - ---- - -## Troubleshooting template - -```markdown ---- -title: Troubleshoot {product or feature} -weight: {number} ---- - -This guide covers common issues with {product or feature} and how to resolve them. - -## {Symptom — describe what the user observes, e.g., error message text} - -### Cause - -{What causes this symptom.} - -### Solution - -{Steps to fix it. Use an ordered list if multi-step.} - -1. Step -2. Step - -{What a successful resolution looks like.} - -### For more information - -- [Related guide](./path.md) -``` - ---- - -## Release notes entry format - -Release notes are entries prepended into `docs/reference/release-notes/spaces.md` — NOT separate files. Each entry follows this format: - -```markdown -## vX.Y.Z - -### Release Date: YYYY-MM-DD - -#### Breaking Changes - -:::important -- **Field or behavior name**: what changed and what the user must do before upgrading. -::: - -#### Features - -**Feature name:** - -1-2 sentences on what it does and why it matters. Link to full doc if one exists. - -#### Bug fixes - -- **Short label**: what was broken and what was fixed. - -#### Upgrade notes - -Any steps or constraints for upgrading from the previous version. -``` - -The file has `` at the top — all entries inherit Vale suppression. Only include sections that have content.