diff --git a/.claude/skills/capability-matrix/SKILL.md b/.claude/skills/capability-matrix/SKILL.md new file mode 100644 index 0000000..c022191 --- /dev/null +++ b/.claude/skills/capability-matrix/SKILL.md @@ -0,0 +1,115 @@ +--- +name: capability-matrix +description: Helps maintain the Supabase SDK capability matrix in capabilities/*.yaml and specs/ — naming a new feature ID, picking or creating a group, checking for duplicate or semantically-overlapping capabilities, spotting naming drift within a group, suggesting when a spec file is warranted, and noting platform-specific behavior. Use whenever a capability YAML or spec file is being added or edited, before opening a PR that touches capabilities/, or when asked to review/audit the matrix, check for duplicates, or suggest groupings. This is an advisory pass, not a gate — it complements `npm run validate`, it doesn't replace it. +--- + +# Capability Matrix Maintenance + +This repo is the canonical registry of features across Supabase's client SDKs +(`capabilities/*.yaml`). The JSON Schema and `npm run validate` already catch +everything mechanical: malformed IDs, area/filename mismatches, exact +duplicate IDs, orphaned spec files. What they can't catch is judgment — +whether a new feature is *actually* new, whether its name reads naturally +next to its siblings, whether it's filed under the right group. That +judgment is what this skill provides. + +This is a local, advisory pass. There is no CI bot version of this — findings +are suggestions for the person editing the file to accept, adjust, or ignore. +Don't present anything as a hard requirement. + +## Step 0: run the mechanical checks first + +Before spending any judgment calls, run the deterministic validator so you're +not duplicating what it already guarantees: + +```bash +cd scripts/capability-matrix && npm run validate +``` + +This confirms schema conformance, `area` field matches the filename, IDs +follow the `..` pattern, no two features +share an exact ID, and every spec file maps to a real feature. If this +fails, fix that first — the checks below assume a structurally valid file. + +## Step 1: read for context, not just the diff + +Read the *whole* target area file (`capabilities/.yaml`), not just the +new/changed entry — group names and sibling features are the only baseline +for judging naming and grouping consistency. If the new feature could +plausibly overlap another area (e.g. something touching both `realtime` and +`database`, or `client` and `auth` session handling), skim that file too. + +## Step 2: semantic duplicates + +`npm run validate` only catches identical IDs. Read every feature's `name` + +`description` in the same area (and group, if cross-area overlap looks +possible) and ask: does this describe behavior another entry already +covers, just worded differently? Common patterns to watch for: + +- Same underlying API call described from two angles (e.g. a "set" feature + and a separate "update" feature that hit the same endpoint) +- A new entry that's actually a narrower case of an existing one (should it + be a note on the existing feature instead of a new ID?) +- Copy-pasted description with only the verb changed + +If you find a likely duplicate, name both IDs and describe the overlap — +don't assume which one should win; that's the author's call. + +## Step 3: naming consistency + +The schema enforces the `..` shape via regex, but not +whether the words chosen fit. Compare the new feature's `id`/`name` against +its siblings in the same `group`: + +- Verb choice — if the group already uses `create`/`delete`/`list` for + parallel operations, a new `add_x` or `remove_x` reads inconsistent. + (See `CONTRIBUTING.md`'s "Choosing a feature ID" section for the + verb-object convention.) +- Admin/scoped variants should be namespaced the way existing ones are + (`auth.admin.delete_user`, not `auth.delete_user_admin`). +- `name` (the human-readable title) should match the tone of sibling + entries in the same group — not suddenly more/less verbose or technical. + +## Step 4: grouping + +- Does the feature's `group` field point to a group that actually fits, or + is it forcing a fit into the nearest existing one? If several recent + features don't cleanly fit any group, say so and suggest a new group + entry under `groups:` at the top of the file. +- Conversely, flag a group that's accumulated features with little in + common — that's a sign it should split. +- A feature with no `group` at all is valid (it's optional) but worth a + second look — is that intentional, or was a fitting group just missed? + +## Step 5: spec suggestion + +Spec files (`specs///.md`) are optional, +but valuable when a feature has real behavioral complexity: multiple named +error conditions, branching behavior, side effects, or prerequisites. The +directory always mirrors the feature `id`'s own segments — e.g. +`auth.mfa.challenge` lives at `auth/mfa/challenge.md` — regardless of what +that feature's optional `group` field currently says; the two can diverge +when a feature has been regrouped for display without renaming its `id`. +If the new feature's `description` hints at real complexity and no spec +exists, suggest creating one from `specs/TEMPLATE.md`. Don't suggest a spec +for a simple getter/setter with an already-complete one-line description. + +## Step 6: platform-scope notes + +There is no schema field for "this only applies to mobile/web SDKs" — that +nuance (biometric auth, secure enclave storage, browser-only APIs like +`localStorage`) is expected to live in prose, not structured data. If a +feature's behavior is inherently platform-scoped, suggest a line either in +the feature's `description` or, if it has a spec, in the spec's `## Notes` +section. Point out *why* it matters: SDKs that don't apply can declare +`not_applicable` in their `sdk-compliance.yaml`, but only if the constraint +is documented somewhere a maintainer would see it. + +## Presenting findings + +Group findings by step, lead with the ones most likely to need a real +change (duplicates, then naming, then grouping, then spec/platform notes). +For each finding, name the specific IDs involved and explain the reasoning +in one or two sentences — enough for the author to judge it themselves. +Skip steps that have nothing to report; don't manufacture a finding to fill +out every section. If everything looks clean, say so briefly and move on. diff --git a/.github/workflows/validate-capabilities.yml b/.github/workflows/validate-capabilities.yml index 20bc67d..46a2993 100644 --- a/.github/workflows/validate-capabilities.yml +++ b/.github/workflows/validate-capabilities.yml @@ -6,6 +6,7 @@ on: pull_request: paths: - "capabilities/**" + - "specs/**" - "schema/**" - "scripts/capability-matrix/**" - "scripts/dart_symbol_extractor/**" diff --git a/.gitignore b/.gitignore index dcdfc9f..cdd3b6e 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,7 @@ # Claude Code internal state (worktree metadata, session files) -.claude/ +.claude/* +# ...except committed project skills +!.claude/skills/ # Generated site output site/