--- # ── FRONT MATTER — the complete field reference for an OWNED skill ─────────── # The directory name IS the skill name, so `name:` is derived and omitted here. # Everything below is either REQUIRED (nothing else can produce it) or consumed # by something outside this repo. Nothing here is restated anywhere else. # # description REQUIRED. A ROUTING SIGNAL — it tells an agent whether to # load this skill BEFORE reading it, so it cannot be derived # from the body (a heading is a title; a first paragraph is # prose). Used for the entity description AND index.json. # when_to_use For the AGENT RUNTIME, not the catalog. Narrower trigger # phrasing than `description`. # allowed-tools For the AGENT RUNTIME: scopes what this skill may do. # Dropping it is a capability/safety regression. # disciplines Optional -> spec.disciplines. Free text, not an enum. # categories Optional -> spec.categories. # # DERIVED — never write these, they are computed at deploy: # name from this directory's name # owner, system from ../../_defaults.yaml (this org) # lifecycle from ../../../../_defaults.yaml (shared by all orgs) # agents same shared layer # source-location from this file's published URL # # Precedence if a value appears in more than one place, nearest wins: # .src.yaml > this front matter > the _defaults.yaml cascade # ───────────────────────────────────────────────────────────────────────────── description: Author and modify ai-stack Backstage catalog entities correctly. Use when adding a component, API, system, skill, rule, or MCP server to the catalog, or when a new entity fails to appear in the portal. when_to_use: "When adding or editing anything under roles/backstage/content/, or when a catalog entity does not show up after a deploy." allowed-tools: Read, Write, Edit, Glob, Grep disciplines: platform categories: catalog --- # ai-stack catalog conventions This skill is **owned by Backstage** — it is authored here, in `content/orgs//ai-resources/skills/catalog-conventions/`, and published to `/.well-known/skills/` by the deploy. It is the worked example of the "owned" authoring mode. ## Never hand-write derived values Three annotations are injected at deploy and must NOT appear in source: | Annotation | Derived from | |---|---| | `backstage.io/managed-by-location` | the file's own served URL | | `backstage.io/techdocs-ref` | whether `docs///` exists | | `backstage.io/source-location` | whether the skill's `SKILL.md` exists | Writing one by hand still wins (the escape hatch is preserved), but you almost never should — a typo fails **silently**, pointing at another entity with no error anywhere. ## Never hand-write AI entity YAML Do not create `kind: AiResource` or `spec.type: mcp-server` files. Write the minimal source of truth instead: | To add a… | Create | Minimum content | |---|---|---| | skill you own | `ai-resources/skills//SKILL.md` | front matter with `name` + `description` | | skill from elsewhere | `ai-resources/skills/.src.yaml` | `from:` + `path:` | | rule | `ai-resources/rules/.md` | front matter `category:` + a prose body | | MCP server | `ai-resources/mcp/.yaml` | `url:` | `_defaults.yaml` supplies owner/system/lifecycle/agents for all of them. ## Ownership `spec.owner` must be a real group. Prefer a Pocket ID-synced group so ownership resolves to current people automatically. ## Relations are declared once and stitched both ways Declare `dependsOn` / `providesApis` / `system` on the child. The catalog builds the reverse edge (`dependencyOf`, `apiProvidedBy`, `hasPart`) for you. Never list members on the parent. ## The failure mode to check first If an entity never appears and there is **no error anywhere**, its `kind` is almost certainly missing from `catalog.rules.allow` in `templates/app-config.local.yaml.j2`. That is how `Domain` and `AiResource` were both silently dropped.