docs: add test-the-docs skill and pm-the-docs universe lookup (#49913)

## I have read the CONTRIBUTING.md file.

YES

## What kind of change does this PR introduce?

Docs authoring skills / contributor enablement.

## What is the current behavior?

- The "Write the docs" bar asks for runnable examples, but skills stop
at lint/build (`/review-the-docs`) and do not execute inline MDX
snippets.
- Cross-repo product grounding depends on a single-repo read; there is
no skill guidance for `supabase/universe` when you have Supabase org
access.

## What is the new behavior?

- Adds `/test-the-docs` to run procedural snippets against a
Docker-isolated local stack (`supabase start` in a temp project), with
Verification table output.
- Teaches `/pm-the-docs` cross-repo product lookup
(`reference/universe-lookup.md`) with a capability gate: universe when
you have Supabase org access (or a local clone), otherwise a first-class
OSS public-search path. `ask-the-docs` stays docs-app only.
- Updates the checklist mirror, CONTRIBUTING skills table, and light
handoffs in `write-the-docs` / `review-the-docs`.

## Additional context

Vault "Write the docs" checklist updated separately; Linear document
needs a Claude-side delta sync after merge.

### Test plan

- [ ] Symlinks: `.claude/skills` is a Git symlink to
`../.agents/skills`; `.claude/skills/test-the-docs/SKILL.md` resolves
- [ ] No hardcoded personal absolute paths under `.agents/skills/`
- [ ] CONTRIBUTING lists skills including `/test-the-docs`
- [ ] `/pm-the-docs` references `universe-lookup.md` capability gate;
`/ask-the-docs` Related points there for product lookup
- [ ] OSS path: no universe clone / submodule init when `gh api
repos/supabase/universe` fails
- [ ] Docker up: dry-run `/test-the-docs` against one MDX page with
SQL/CLI (optional smoke)
- [ ] Docker down: skill documents graceful `deferred` (not silent skip)

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

- **New Features**
- Added documentation guidance for testing runnable examples in an
isolated local environment.
- Added cross-repository product lookup guidance, including capability
checks and source tracking.
- Added verification report templates with standardized results and
environment details.

- **Documentation**
  - Expanded authoring, review, self-review, and contribution guidance.
- Improved safety instructions for local snippet testing, including
credential protection and cleanup.
- Updated repository layout, tooling, links, and workflow references for
documentation skills.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Nik Richers <nik@validmind.ai>
This commit is contained in:
Nik RichersandNik Richers authored and GitHub committed 2026-09-04 00:34:45 +00:00
1 parent 24be387cdb
commit 0322720743
16 files changed
+720 -43

No files matched your search

+4 -1
View File
@@ -125,7 +125,10 @@ write it down.
- [`pm-the-docs`](../pm-the-docs/SKILL.md) — audience, stage, and
cross-cutting scope calls (Frame stage of the "Write the docs" checklist,
mirrored in `pm-the-docs`'s reference file).
mirrored in `pm-the-docs`'s reference file). Cross-repo **product** lookup
(universe) lives there, not in this skill.
- [`test-the-docs`](../test-the-docs/SKILL.md) — execute docs snippets against a
Docker-isolated local stack; verification report.
- [`work-linear-issue`](https://github.com/supabase/docs-agent-skills/blob/main/.claude/skills/work-linear-issue/SKILL.md) — implementing
assigned DOCS-\* tickets.
- [`review-the-docs`](../review-the-docs/SKILL.md) — reviewing open docs
+21 -9
View File
@@ -3,10 +3,12 @@ name: pm-the-docs
description: >-
Docs-PM decision support for the "Write the docs" authoring process —
makes audience, stage, and cross-cutting scope calls during the Frame
and Shape stages, and helps decide when a docs question needs to
self-serve vs. escalate to a docs PM. Use when framing a new docs page
or launch, deciding what product stage or audience a feature targets,
or judging whether a docs question needs PM sign-off.
and Shape stages (including cross-repo product lookup via universe when
accessible, else the public OSS path), and helps decide when a docs
question needs to self-serve vs. escalate to a docs PM. Use when framing
a new docs page or launch, deciding what product stage or audience a
feature targets, judging whether a docs question needs PM sign-off, or
confirming which product repos a launch spans.
---
# PM the docs
@@ -17,17 +19,26 @@ Backs the Frame and Shape stages of the "Write the docs" checklist (mirrored in
- Starting a new docs page or launch and need to state the product stage, audience, and "why" before drafting (Frame).
- Deciding content type, IA placement, or prerequisites for a page (Shape).
- Judging whether a launch spans multiple product repos (CLI, Auth, migrations, platform, …) — see [reference/universe-lookup.md](reference/universe-lookup.md).
- Unsure whether a docs question is self-serve or needs a docs PM's sign-off.
**Not for** drafting content itself (see [`write-the-docs`](../write-the-docs/SKILL.md)), restructuring existing pages (see [`edit-the-docs`](../edit-the-docs/SKILL.md)), or docs-app architecture/IA placement mechanics (see [`ask-the-docs`](../ask-the-docs/SKILL.md)).
**Not for** drafting content itself (see [`write-the-docs`](../write-the-docs/SKILL.md)), restructuring existing pages (see [`edit-the-docs`](../edit-the-docs/SKILL.md)), running snippets (see [`test-the-docs`](../test-the-docs/SKILL.md)), or docs-app architecture/IA placement mechanics (see [`ask-the-docs`](../ask-the-docs/SKILL.md)).
## Reference files
| File | What's inside |
| ------------------------------------------------------------------------------ | -------------------------------------------------------------------------- |
| [reference/write-the-docs-checklist.md](reference/write-the-docs-checklist.md) | Six-stage authoring checklist mirror |
| [reference/universe-lookup.md](reference/universe-lookup.md) | Cross-repo product lookup: capability gate, universe accelerator, OSS path |
## Answering a scope/stage/audience question
1. Read the relevant stage in [reference/write-the-docs-checklist.md](reference/write-the-docs-checklist.md) — its checkboxes state exactly what needs deciding.
2. Read whatever context exists for the feature: the linked issue/project, the PRD, the shipped code or PR. When code and PRD disagree, the code wins for behavior claims.
3. Answer the checklist's questions directly: product stage, audience and job-to-be-done, the one-line "why," content type, IA placement, prerequisites.
4. Distinguish **confirmed fact** (stated in the ticket/PRD/code) from **inference** (your best read) — flag inference explicitly rather than presenting it as settled.
5. If a decision is genuinely open at the org level (not a docs authoring call), say so and name who should decide instead of inventing an answer to look complete.
3. When scope may span services (CLI, Auth, migrations, Dashboard, platform, …), follow [reference/universe-lookup.md](reference/universe-lookup.md) **capability gate** before settling Frame/Shape; use universe only if accessible, otherwise the OSS path. Record which repos you searched.
4. Answer the checklist's questions directly: product stage, audience and job-to-be-done, the one-line "why," content type, IA placement, prerequisites.
5. Distinguish **confirmed fact** (stated in the ticket/PRD/code) from **inference** (your best read) — flag inference explicitly rather than presenting it as settled.
6. If a decision is genuinely open at the org level (not a docs authoring call), say so and name who should decide instead of inventing an answer to look complete.
## Self-serve vs. escalate
@@ -37,7 +48,8 @@ Escalate to your docs team's PM when scope or stage is unclear, you need a revie
## Related skills
- [`ask-the-docs`](../ask-the-docs/SKILL.md) — IA placement and docs-app architecture (Shape stage)
- [`ask-the-docs`](../ask-the-docs/SKILL.md) — IA placement and docs-app architecture (Shape stage). Cross-repo **product** lookup lives here in `universe-lookup.md`, not in `ask-the-docs`.
- [`write-the-docs`](../write-the-docs/SKILL.md) — drafting once Frame/Shape are settled
- [`test-the-docs`](../test-the-docs/SKILL.md) — run snippets against a Docker-isolated local stack; verification report
- [`edit-the-docs`](../edit-the-docs/SKILL.md) — restructure and improve existing pages
- [`review-the-docs`](../review-the-docs/SKILL.md) — self-review and PR review stages
@@ -0,0 +1,96 @@
# Cross-repo product lookup
Cross-repo product search for Frame/Shape when a feature may span services. Use during `/pm-the-docs`, not `/ask-the-docs` (`ask-the-docs` stays on `apps/docs` architecture).
**Cross-repo confirmation is required for everyone.** [`supabase/universe`](https://github.com/supabase/universe) is an optional accelerator when you have Supabase org access to that private meta-repo (and ideally a local clone). Contributors without that access use the OSS path below — that is a successful outcome, not a failure.
## Capability gate
Run this gate before any universe clone or submodule command.
```mermaid
flowchart TD
start[Cross-repo grounding needed]
clone{"Local universe root exists?"}
ghApi{"gh api repos/supabase/universe succeeds?"}
useUniverse[Use universe clone + rg in repos/]
ossPath[OSS path: public gh search + linked product repos]
start --> clone
clone -->|yes| useUniverse
clone -->|no| ghApi
ghApi -->|yes Supabase org access| useUniverse
ghApi -->|no 404/403| ossPath
```
### 1. Local clone?
Resolve the universe root in order (do not hardcode machine-specific absolute paths in committed files):
1. `$SUPABASE_UNIVERSE_ROOT` (if set)
2. `$HOME/GitHub/supabase/universe`
```bash
UNIVERSE_ROOT="${SUPABASE_UNIVERSE_ROOT:-$HOME/GitHub/supabase/universe}"
[[ -d "$UNIVERSE_ROOT/.git" || -f "$UNIVERSE_ROOT/.git" ]] && echo "local universe ok"
```
If that checkout exists → **accelerator path** (skip the `gh api` probe).
### 2. Else probe org access (read-only, no clone)
```bash
gh api repos/supabase/universe -q .full_name
```
| Result | Next step |
| ------ | --------- |
| Success (`supabase/universe`) | Accelerator path: you **may** clone with `--recurse-submodules` (or ask the user to), then search |
| 404, 403, or other failure | **OSS path only** — do **not** run `git clone` or `git submodule update` against universe |
## OSS path (always valid)
When the gate says universe is unavailable:
- Search public code: `gh search code --owner supabase '<query>'` (plus other public owners named in the ticket)
- Read any product repo already checked out or linked from Linear / the PR
- Prefer `supabase/supabase` in-tree sources when that is enough
- In the Frame/Shape summary, record `universe: unavailable (OSS)` and list the public sources used
Never treat missing universe access as a blocker or an incomplete Frame/Shape.
## Accelerator: universe (when accessible)
Prefer an existing local clone. Only init or update submodules after the gate succeeds:
```bash
cd "$UNIVERSE_ROOT"
git submodule update --init --recursive
```
Private submodules (`platform`, `branching`) may need a PAT. If those fail, note the gap and continue with public submodules plus the OSS search path.
### Where to look
Start from the universe README "Finding your way around" table, then `rg` inside the relevant submodule:
| Looking for… | Start in |
| ------------ | -------- |
| Schema, extensions, RLS | `repos/postgres/`, `repos/postgrest/`, `repos/pg-toolbelt/` |
| Auth flows | `repos/auth/`, `auth-js` under `repos/supabase-js/` |
| Realtime / Storage / Edge Functions | `repos/realtime/`, `repos/storage/`, `repos/edge-runtime/` |
| Dashboard / Studio | `repos/supabase/apps/studio` |
| Management API / hosted infra | `repos/platform/` (private) |
| CLI, local dev, `config.toml` | `repos/cli/` |
| Docs & self-hosting Compose | `repos/supabase/` (`apps/docs`, `docker/`) |
When scope is unknown, search initialized `repos/**` with a tight pattern rather than reading entire trees.
## How to use in Frame / Shape
1. Name the product surfaces the launch might touch (CLI, Auth, migrations, Dashboard, …).
2. Run the **capability gate**.
3. Resolve surfaces to repos (universe submodules **or** public search / linked checkouts).
4. Confirm with a short search whether behavior lives in one repo or several.
5. Record in the Frame/Shape summary: gate result (`universe: available` or `universe: unavailable (OSS)`), repos consulted, cross-cutting vs single-repo, and any gaps.
Always distinguish confirmed fact from inference.
@@ -1,61 +1,71 @@
# Write the docs
> Mirrors Supabase's proposed "Write the docs" process as of 2026-08-10. Process specifics may still evolve.
A practical six-stage checklist and quality standard for planning, drafting, and reviewing product documentation.
**P** = Product
**E** = Engineering
**Docs** = Docs team
## Authoring
Six short stages. Keep it lightweight; the point is to make good docs the default, not to add ceremony.
_Self-serve first ([agent skills](../../../../apps/docs/CONTRIBUTING.md#ai-agent-skills-for-docs-authoring)), ask your docs team's PM as needed._
## What good looks like
- The **why** is explicit: a reader learns what problem this solves and when to reach for it, not only the steps.
- The **content type is deliberate** and consistent within the page.
- The content **type is deliberate** and consistent within the page.
- **Audience and prerequisites** are stated up front.
- At least one **example is runnable and has been run** (commands, code, expected result).
- **Correct stage** is stated; limitations are named honestly.
- **Examples are runnable and have been tested** (commands, code, expected result) — verify with `/test-the-docs` against a Docker-isolated local stack, not production.
- **Correct stage** like GA is stated; limitations are named honestly.
- The page **lives in the right place** in the IA and links to and from related pages.
- Terminology and formatting match existing docs (defer to the style guide once one lands).
- Terminology and formatting match existing docs (and style guide once it lands).
## 1. Frame
### 1. Frame
_Skills:_ `ask-the-docs` to see how the surface works today; `pm-the-docs` for audience, stage, and cross-cutting scope calls.
_Skills:_ `/ask-the-docs` for how the docs surface works today; `/pm-the-docs` for audience, stage, and cross-cutting scope (cross-repo span via universe when accessible — see [universe-lookup.md](universe-lookup.md)).
- [ ] P: State the product stage (private/public alpha, beta, GA)
- [ ] P: Name the audience and the job they are trying to do
- [ ] P: Write one line on _why_ the feature exists (the problem it solves), not only what it does
## 2. Shape
### 2. Shape
_Skill:_ `ask-the-docs` for IA placement, architecture, and where content lives.
_Skill:_ `/ask-the-docs` for IA placement, architecture, and where content lives.
- [ ] P: Pick the content type(s): tutorial (learning), how-to (a task), reference (lookup), explanation (the why). Do not mix types on one page (refer to [Diátaxis](https://diataxis.fr/))
- [ ] P: Decide where the page lives in the existing IA and what links in and out (avoid orphan pages)
- [ ] P: List prerequisites and assumed knowledge up front
## 3. Draft
### 3. Draft
_Skill:_ `write-the-docs` to draft net-new content grounded in Linear and the code.
_Skill:_ `/write-the-docs` to draft net-new content grounded in Linear and the code (`/pm-the-docs` → universe when accessible, else public search / named product repos).
- [ ] P: Lead with the why and the outcome, then the how/what (product story first)
- [ ] P: Include at least one runnable, copy-pasteable example that you have actually run
- [ ] P: Include at least one runnable, copy-pasteable example that you have actually run (or will run in Self-review via `/test-the-docs`)
- [ ] P/E: Cross-repo behavior confirmed via universe when accessible, else public `gh search` / named product repos when the feature is not confined to `supabase/supabase` (lookup via `/pm-the-docs`, not `/ask-the-docs`)
- [ ] E: Contribute technical depth and verify accuracy (APIs, limits, edge cases)
- [ ] P: Call out the current stage inline and any known limitations
When the work is improving an existing page (restructure, reorder, connective text, brevity) rather than authoring net-new content, use `edit-the-docs` instead of `write-the-docs`.
When the work is improving an existing page (restructure, reorder, connective text, brevity) rather than authoring net-new content, use `/edit-the-docs` instead of `/write-the-docs`.
## 4. Self-review against the bar
### 4. Self-review against the bar
_Skill:_ `review-the-docs` — [Local self-review](../../review-the-docs/SKILL.md#local-self-review-no-open-pr) on your own branch before opening the PR.
_Skills:_ `/review-the-docs` for [local self-review](../../review-the-docs/SKILL.md#local-self-review-no-open-pr) before opening the PR; `/test-the-docs` to run snippets and produce a verification report.
- [ ] P/E: Check the draft against "What good looks like" above before opening the PR
- [ ] P/E: Follow authoring-experience standards and tooling when available
- [ ] P/E: `/test-the-docs` run; verification report ready for the PR body
- [ ] P/E: Follow Authoring Experience standards and tooling when available
## 5. PR review
### 5. PR review
_Skill:_ `review-the-docs` to triage, classify, verify the build, and report.
_Skill:_ `/review-the-docs` to triage, classify, verify the build, and report.
- [ ] P/E: Open the PR and request review per the rules of engagement
- [ ] Docs: Review against the published bar
## 6. Keep it honest
### 6. Keep it honest
- [ ] P: Keep the product launch checklist's "start on day 1" docs gate honest through ship (update as stage or behavior changes)
@@ -63,17 +73,12 @@ _Skill:_ `review-the-docs` to triage, classify, verify the build, and report.
**Self-serve when:** the checklist above is clear, standards exist, and you know the product stage and audience.
**Ask when:** scope or stage is unclear, you need a review path, the bar is ambiguous, or the launch docs touch cross-cutting surfaces (quickstarts, API keys, tutorials, onboarding, platform concepts).
**Ask when:** scope or stage is unclear, you need a review path, the bar is ambiguous, or the launch docs touch cross-cutting surfaces (quick starts, API keys, tutorials, onboarding, platform concepts).
**What to expect:** the docs PM is the point of contact for questions and review against the bar.
**What to expect:** the docs PM is the point of contact for questions, skills enablement, and review against the bar.
**Where to ping:** your team's PR-review channel and current docs PM — check your contributor guide for who that is today.
## Reference
## Resources
Role prefixes:
- **P** = Product. The product lead / area PM who writes the docs.
- **E** = Engineering. Contributes technical depth and verifies accuracy.
- **P/E** = Product and Engineering together.
- **Docs** = Docs team, the reviewer.
Skills for this checklist: [AI agent skills for docs authoring](../../../../apps/docs/CONTRIBUTING.md#ai-agent-skills-for-docs-authoring) (`/pm-the-docs`, `/ask-the-docs`, `/write-the-docs`, `/edit-the-docs`, `/test-the-docs`, `/review-the-docs`).
+4 -1
View File
@@ -69,7 +69,8 @@ pnpm build:reference-markdown # when reference pipeline changed
```
4. Spot-check frontmatter, internal links, and nav wiring for content changes.
5. Write a short **self-review note** (blockers vs nits) suitable to paste into the future PR body under a "Self-review" heading.
5. **Offer runnable verification** — for content/tutorial PRs with new or changed procedural fenced blocks, ask whether to run [`test-the-docs`](../test-the-docs/SKILL.md). Prerequisites are class-specific (Docker Compose stack profile for DB/API; examples profile for `example-app`). If accepted, include the verification report; if declined or a required prerequisite for that class is missing, record credible `deferred` reasons for those artifacts only. Do not reimplement sandbox execution here.
6. Write a short **self-review note** (blockers vs nits) suitable to paste into the future PR body under a "Self-review" heading.
Then open the PR and continue with open-PR review if a second pass is needed.
@@ -216,6 +217,7 @@ Checklist:
- [ ] `$CodeSample` paths match existing example directories
- [ ] Admonitions, tabs, and partial includes render sensibly in PR preview
- [ ] No accidental whitespace-only or empty sections where components were removed
- [ ] Offered [`test-the-docs`](../test-the-docs/SKILL.md) for new/changed procedural snippets; verification report present or credible `deferred` reasons recorded
Compare PR preview URL (from Vercel/deployment comment) against production for visual regressions when layout components are involved.
@@ -239,6 +241,7 @@ Checklist:
- [ ] MDX steps match example code after `pnpm codegen:examples` (if `$CodeSample` used)
- [ ] Env var names and Supabase client setup match current `@supabase/ssr` patterns
- [ ] Example pins catalog versions — no `"latest"` for in-repo packages
- [ ] Offered [`test-the-docs`](../test-the-docs/SKILL.md) for procedural tutorial steps (or `deferred` with reason)
- [ ] **Platform E2E** (when auth involved): SQL migration applied, auth flow walked, profiles verified — see `work-linear-issue` Phase 3
---
+96
View File
@@ -0,0 +1,96 @@
---
name: test-the-docs
description: >-
Execute runnable docs snippets and examples inside a disposable Docker Compose
sandbox (runner container + local Supabase stack via `supabase start`). Use
after Draft or during Self-review when asked to test the docs, fact-check
CLI/SQL/code samples, or produce a verification report for a docs PR.
Complements review-the-docs lint/build checks; does not replace them.
---
# Test the docs
Runs procedural docs content **inside disposable containers**, not on the host shell and not against production. Produces a verification report for the PR body / self-review note.
For lint, markdown rebuilds, example-app triage, and PR review, use [`review-the-docs`](../review-the-docs/SKILL.md). For Frame/Shape and cross-repo product lookup, use [`pm-the-docs`](../pm-the-docs/SKILL.md).
## When to invoke
- After Draft, before or during Self-review (checklist Stage 4).
- Standalone: "test the docs", "fact-check these snippets", "run the examples".
- Content or tutorial PRs that add or change procedural fenced blocks.
**Not for:** generated reference pages, docs-app architecture questions, or hosted/production projects.
## Core rules
1. **Never run against production.** Local stack or temp dir only.
2. **Never run MDX fences on the host shell.** Use the Compose sandbox — see [reference/sandbox-setup.md](reference/sandbox-setup.md) and [`sandbox/run.sh`](sandbox/run.sh).
3. **Proportional:** Tier A (one end-to-end path) is required; Tier B spot-checks new/changed procedural blocks, not every fence on every page.
4. **Product bugs** found while testing get linked or filed separately; fix docs only when the docs are wrong.
## Phases
### 1. Scope
From explicit MDX paths, or:
```bash
git diff --name-only master...HEAD -- 'apps/docs/content/**'
```
Skip generated reference output under `features/docs/generated/`.
### 2. Extract
List runnable artifacts from changed MDX:
- Fenced blocks: `bash`, `sh`, `sql`, `javascript`, `typescript`, `tsx`, `jsx`
- `$CodeSample` paths → treat as `example-app` (build under `examples/`)
- Skip: `mermaid`, incomplete illustrative fragments, partial-only includes
### 3. Classify
Assign each artifact a class per [reference/snippet-classes.md](reference/snippet-classes.md):
| Class | Action |
| --------------------- | ---------------------------------------------- |
| `runnable-local` | Run in temp stack / temp dir |
| `runnable-with-setup` | Run after documented setup (migrations, seed) |
| `example-app` | `npm install && npm run build` in `examples/…` |
| `illustrative-only` | No run required |
| `deferred` | Record reason; do not silently skip |
### 4. Sandbox setup
Follow [reference/sandbox-setup.md](reference/sandbox-setup.md) and drive lifecycle with [`sandbox/run.sh`](sandbox/run.sh):
1. Refuse if the **host** is running as root.
2. Require `docker` + `docker info` + `docker compose` on the host for any in-container run.
3. Gate profiles **per artifact class**:
- `runnable-local` / `runnable-with-setup` that need DB/API: `./sandbox/run.sh up-stack` (DinD + runner → `supabase init` / `supabase start` in `/work`).
- CLI-only blocks with no DB: still use a runner profile so fences stay off-host; skip `supabase start` when unused.
- `example-app`: `TTD_EXAMPLE_DIR=<repo>/examples/<app> ./sandbox/run.sh up-examples` (Node in runner; **no** DinD). Do **not** defer solely because the host lacks a global Supabase CLI.
4. Always `./sandbox/run.sh down` when finished (cleanup trap on the host session).
5. Capture connection **URLs only** inside the runner; never paste credential fields into notes or logs.
If a **required** prerequisite for that artifact is unavailable, mark that artifact `deferred` with the specific reason — never silent skip, and do not defer unrelated classes.
### 5. Execute
- **Tier A:** one copy-pasteable end-to-end path from the page.
- **Tier B:** each new/changed block classified `runnable-*` **or** `example-app` (build and record the result).
- Run every fence via `./sandbox/run.sh exec` or `exec-timeout` (never a bare host shell).
- Bound every artifact: default **60s** for shell / SQL / JS / TypeScript / `tsx` / `jsx`; allow longer for `example-app` install/build (e.g. **5m**). On timeout, kill the process **group** inside the runner, then record `fail` or `deferred` with reason.
- `curl` / `wget` only to filtered stack URLs (or page-documented local endpoints). `npm` / `npx` / `node` only for mounted `example-app` builds.
- Capture exit code, stdout/stderr (redact secrets), and observed vs expected behavior.
### 6. Report
Write a verification report per [reference/verification-report.md](reference/verification-report.md) for the PR body / self-review note.
## Related skills
- [`write-the-docs`](../write-the-docs/SKILL.md) — Draft; hands off here before PR
- [`review-the-docs`](../review-the-docs/SKILL.md) — lint/build/classify; consumes verification report
- [`pm-the-docs`](../pm-the-docs/SKILL.md) — Frame/Shape; universe for cross-repo product lookup
@@ -0,0 +1,83 @@
# Sandbox setup
Containerized local execution for `/test-the-docs`. The **host** only starts Docker Compose and tears it down. Every MDX fence (shell, SQL, JS/TS, example-app builds) runs **inside** the disposable `runner` container — never as a host shell.
Assets live in [`../sandbox/`](../sandbox/): `compose.yaml`, `Dockerfile`, `run.sh`.
## Threat model and guardrails
| Layer | What it does |
| ---------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Host | `docker compose` lifecycle only (`run.sh up-*` / `down`). No fence execution. |
| Runner container | Executes fences as non-root `runner` (uid 1001). No `$HOME` mount. Work dir is `/work`; optional read-only `/examples`. |
| DinD (`stack` profile) | Privileged `docker:dind` runs an isolated Docker daemon. `supabase start` creates stack containers **inside DinD**. The runner shares DinD’s network namespace (`network_mode: service:dind`) so `127.0.0.1` healthchecks and client URLs work. Residual risk: privileged DinD; mitigate with ephemeral project names and `run.sh down`. |
| Examples profile | No DinD and no docker.sock — Node-only builds. |
This skill is for docs authors and reviewers verifying intended content. It is not unattended CI over arbitrary hostile input.
Guardrails:
- **Fences in-container only.** Never run MDX fences on the host shell. Use `./sandbox/run.sh exec` or `exec-timeout`.
- **Local stack only.** Reject snippets that target hosted or production Supabase projects.
- **No secrets in notes.** Never paste `PUBLISHABLE_KEY`, `SECRET_KEY`, `JWT_SECRET`, `ANON_KEY`, `SERVICE_ROLE_KEY`, `S3_PROTOCOL_ACCESS_KEY_ID`, `S3_PROTOCOL_ACCESS_KEY_SECRET`, or other keys into the verification report, PR body, or chat logs. Capture **URLs only** from `supabase status -o env`.
- **`curl` / `wget`.** Only to URLs from the filtered status capture (`API_URL`, `DB_URL`, `DATABASE_URL`), or to local endpoints the page under test documents. Mark other targets `deferred`.
- **`npm` / `npx` / `node`.** Only for `example-app` artifacts. Mount the app read-only at `/examples`, copy into `/work/example`, then `npm install && npm run build` (or the page’s documented build). Arbitrary `node -e`, remote `npx`, or Node from unrelated bash fences → `deferred`.
- **Prefer page commands.** Run documented steps from the MDX under test.
- **Fail closed** when Docker/Compose prerequisites for that artifact class are missing (see skill Phase 4).
## Host prerequisites (fail closed)
```bash
if [[ "$(id -u)" = "0" ]]; then
echo "error: refuse to run as root" >&2
exit 1
fi
command -v docker >/dev/null || { echo "error: docker not found" >&2; exit 1; }
docker info >/dev/null 2>&1 || { echo "error: Docker is not running" >&2; exit 1; }
docker compose version >/dev/null || { echo "error: docker compose not available" >&2; exit 1; }
```
The host does **not** need a global `supabase` CLI or Node for stack/example runs; those tools live in the runner image. If Docker/Compose is unavailable, mark artifacts that need the runner `deferred`.
`run.sh` creates temp work/output dirs world-writable (`chmod 0777`) so the non-root runner (`uid 1001`) can write into the host bind mounts.
## Lifecycle (`run.sh`)
From `.agents/skills/test-the-docs/sandbox/`:
```bash
# Optional: pin dirs / project name for the session
eval "$(./run.sh env)"
# Stack profile: DinD + runner → supabase init/start inside /work
./run.sh up-stack
# Capture URLs only inside the runner (never log credential fields)
./run.sh exec -- bash -lc '
eval "$(supabase status -o env | grep -E "^(API_URL|DB_URL|DATABASE_URL)=")"
echo "API_URL is set (value omitted from logs)"
'
# Run a fence with a deadline (process group killed on timeout)
./run.sh exec-timeout 60 -- bash -lc 'eval "$(supabase status -o env | grep -E "^(API_URL|DB_URL|DATABASE_URL)=")"; psql "$DB_URL" -c "select 1"'
# Examples profile (no DinD): mount the app, then build
TTD_EXAMPLE_DIR=/path/to/repo/examples/auth/hono ./run.sh up-examples
./run.sh exec-timeout 300 -- bash -lc 'cd /work/example && npm install && npm run build'
# Always tear down
./run.sh down
```
## Profiles
| Profile | Services | Isolation | Use when |
| ---------- | ----------------------- | -------------------------------- | --------------------------------------------- |
| `stack` | `dind` + `runner-stack` | Privileged DinD; fences off-host | SQL, CLI, client calls against local Supabase |
| `examples` | `runner` | No Docker daemon in-sandbox | `example-app` install/build only |
Do not start the stack unless the artifact needs it.
## Teardown
Always `./run.sh down` (stops `supabase` project containers when possible, `compose down -v`, removes temp work/output dirs). Leave Docker Desktop running for the next session.
@@ -0,0 +1,28 @@
# Snippet classes
Classify each extracted artifact before running it.
| Class | Meaning | Run? |
| --------------------- | -------------------------------------------------------------------------------- | -------------------------------------- |
| `runnable-local` | Complete CLI, SQL, or script that works against a local stack or temp dir | Yes |
| `runnable-with-setup` | Needs migrations, seed data, `.env`, or prior steps from the same page | Yes, after setup |
| `example-app` | `$CodeSample` or path under `examples/` | Build (`npm install && npm run build`) |
| `illustrative-only` | Incomplete on purpose, omits required context, or is conceptual | No |
| `deferred` | Needs production, paid feature, destructive op, or missing required prerequisite | No — record reason |
## Safety
- Prefer read-only SQL and non-destructive CLI flags.
- Never target a linked hosted/production project from this skill.
- Do not print secrets (service role keys, PATs) into Verification notes or logs.
- Mark incomplete copy-paste blocks `illustrative-only` rather than forcing a run that cannot succeed.
- Execute fences only inside the Compose runner per [sandbox-setup.md](sandbox-setup.md). Restrict `curl`/`wget` to filtered stack URLs; restrict `npm`/`npx`/`node` to `example-app` mounts. Mark out-of-policy fences `deferred`.
## Language heuristics
| Fence | Typical class |
| ------------------------------------------- | --------------------------------------------------------------------------- |
| `sql` | `runnable-local` or `runnable-with-setup` if ordered migrations |
| `bash` / `sh` | `runnable-local` if self-contained; else `deferred` / `illustrative-only` |
| `javascript` / `typescript` / `tsx` / `jsx` | Often `illustrative-only` unless a full runnable script or example-app path |
| `mermaid` | Skip (not executable) |
@@ -0,0 +1,38 @@
# Verification report
Paste into the PR body or self-review note under a **Verification** heading.
## Template
```markdown
## Verification (`/test-the-docs`)
| Snippet / step | Class | Sandbox | Result | Notes |
| ----------------------------- | -------------- | --------------------------------- | -------- | ------------------------ |
| e.g. `create type …` SQL | runnable-local | Compose runner + `supabase start` | pass | |
| e.g. `supabase db diff` | runnable-local | Compose runner + local stack | fail | product bug → link issue |
| e.g. paid Dashboard-only step | deferred | — | deferred | needs hosted project |
**Tier A path:** <one-line description of the end-to-end path run>
**Environment:** Docker Desktop <version if known>; compose sandbox (`sandbox/run.sh`); fences in-container only
```
Do **not** put secrets (`JWT_SECRET`, `ANON_KEY`, `SERVICE_ROLE_KEY`, access tokens) in Notes or Environment.
## Results
| Result | Meaning |
| ---------- | -------------------------------------------------------------------- |
| `pass` | Command exited 0 and matched expected behavior |
| `fail` | Ran but wrong output / non-zero exit — docs wrong **or** product bug |
| `deferred` | Not run; reason required in Notes |
| `skipped` | Out of scope (`illustrative-only`) |
## Product bugs
If the snippet matches the code and still fails:
1. Prefer linking an existing issue in the owning repo.
2. Otherwise note the repro in the PR and file/follow up with the product owner.
3. Do not "fix" the docs to hide a real platform bug without calling it out.
@@ -0,0 +1 @@
# Keep empty bind-mount target for compose when no example is mounted.
@@ -0,0 +1,2 @@
.state/
!.empty/.keep
@@ -0,0 +1,34 @@
# Runner for /test-the-docs: executes MDX fences inside the container.
FROM node:22-bookworm-slim
ARG TARGETARCH
ARG SUPABASE_CLI_VERSION=2.39.2
RUN apt-get update && apt-get install -y --no-install-recommends \
ca-certificates \
curl \
postgresql-client \
&& rm -rf /var/lib/apt/lists/*
# Docker CLI only (daemon is DinD over TCP for stack profile)
COPY --from=docker:27-cli /usr/local/bin/docker /usr/local/bin/docker
RUN set -eux; \
arch="${TARGETARCH}"; \
case "${arch}" in \
amd64) cli_arch=amd64 ;; \
arm64) cli_arch=arm64 ;; \
*) cli_arch=amd64 ;; \
esac; \
curl -fsSL "https://github.com/supabase/cli/releases/download/v${SUPABASE_CLI_VERSION}/supabase_linux_${cli_arch}.tar.gz" \
| tar -xz -C /usr/local/bin supabase; \
chmod +x /usr/local/bin/supabase; \
supabase --version
RUN useradd --create-home --uid 1001 --shell /bin/bash runner \
&& mkdir -p /work /output /examples \
&& chown -R runner:runner /work /output /examples
USER runner
WORKDIR /work
CMD ["bash"]
@@ -0,0 +1,81 @@
# Disposable compose project for /test-the-docs.
# Host only starts/stops this project; MDX fences run inside the runner.
#
# Profiles:
# stack — privileged DinD + runner sharing DinD network (supabase start uses 127.0.0.1)
# examples — runner only; copies /examples into /work/example for npm install (no DinD)
services:
dind:
image: docker:27-dind
privileged: true
environment:
DOCKER_TLS_CERTDIR: ''
command: ['dockerd', '--host=tcp://0.0.0.0:2375', '--host=unix:///var/run/docker.sock']
healthcheck:
test: ['CMD', 'docker', 'info']
interval: 2s
timeout: 5s
retries: 30
start_period: 5s
profiles:
- stack
runner:
build:
context: .
dockerfile: Dockerfile
working_dir: /work
user: '1001:1001'
environment:
TTD_IN_CONTAINER: '1'
command: ['sleep', 'infinity']
volumes:
- type: bind
source: ${TTD_WORK_DIR:?set TTD_WORK_DIR}
target: /work
- type: bind
source: ${TTD_OUTPUT_DIR:?set TTD_OUTPUT_DIR}
target: /output
- type: bind
source: ${TTD_EXAMPLE_DIR:-./.empty}
target: /examples
read_only: true
networks:
- ttd
profiles:
- examples
runner-stack:
build:
context: .
dockerfile: Dockerfile
working_dir: /work
user: '1001:1001'
# Share DinD's network namespace so supabase healthchecks on 127.0.0.1 succeed
network_mode: 'service:dind'
environment:
TTD_IN_CONTAINER: '1'
DOCKER_HOST: tcp://127.0.0.1:2375
command: ['sleep', 'infinity']
volumes:
- type: bind
source: ${TTD_WORK_DIR:?set TTD_WORK_DIR}
target: /work
- type: bind
source: ${TTD_OUTPUT_DIR:?set TTD_OUTPUT_DIR}
target: /output
- type: bind
source: ${TTD_EXAMPLE_DIR:-./.empty}
target: /examples
read_only: true
depends_on:
dind:
condition: service_healthy
profiles:
- stack
networks:
ttd:
driver: bridge
name: ${TTD_NETWORK_NAME:-ttd-sandbox}
+189
View File
@@ -0,0 +1,189 @@
#!/usr/bin/env bash
# Host-side lifecycle for /test-the-docs sandbox.
# Starts a disposable compose project and execs fences inside the runner container.
# Usage:
# eval "$(./run.sh env)" # export TTD_* for the session
# ./run.sh up-stack # DinD + runner; supabase init/start in /work
# ./run.sh up-examples # runner only (no DinD); example-app builds in /work/example
# ./run.sh exec -- <cmd...> # run a command in the active runner
# ./run.sh exec-timeout 60 -- <cmd...>
# ./run.sh down # compose down -v and remove work/output dirs created by this script
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
COMPOSE_FILE="${SCRIPT_DIR}/compose.yaml"
die() {
echo "error: $*" >&2
exit 1
}
require_host_prereqs() {
if [[ "$(id -u)" = "0" ]]; then
die "refuse to run as root on the host"
fi
command -v docker >/dev/null || die "docker not found — install Docker Desktop"
docker info >/dev/null 2>&1 || die "Docker is not running — start Docker Desktop"
docker compose version >/dev/null 2>&1 || die "docker compose not available"
}
compose() {
docker compose -p "${TTD_PROJECT_NAME}" -f "${COMPOSE_FILE}" "$@"
}
runner_service() {
case "${TTD_PROFILE:-}" in
stack) echo runner-stack ;;
examples) echo runner ;;
*) die "TTD_PROFILE unset; run up-stack or up-examples first" ;;
esac
}
ensure_state_dir() {
mkdir -p "${SCRIPT_DIR}/.state"
}
write_env_file() {
ensure_state_dir
cat >"${SCRIPT_DIR}/.state/current.env" <<EOF
export TTD_PROJECT_NAME=$(printf '%q' "${TTD_PROJECT_NAME}")
export TTD_WORK_DIR=$(printf '%q' "${TTD_WORK_DIR}")
export TTD_OUTPUT_DIR=$(printf '%q' "${TTD_OUTPUT_DIR}")
export TTD_EXAMPLE_DIR=$(printf '%q' "${TTD_EXAMPLE_DIR}")
export TTD_NETWORK_NAME=$(printf '%q' "${TTD_NETWORK_NAME}")
export TTD_PROFILE=$(printf '%q' "${TTD_PROFILE}")
EOF
}
load_env_file() {
[[ -f "${SCRIPT_DIR}/.state/current.env" ]] || die "no active sandbox; run up-stack or up-examples first"
# shellcheck disable=SC1091
source "${SCRIPT_DIR}/.state/current.env"
}
cmd_env() {
require_host_prereqs
local stamp project work output
stamp="$(date +%Y%m%d%H%M%S)-$$"
project="ttd-${stamp}"
work="$(mktemp -d "${TMPDIR:-/tmp}/ttd-work.XXXXXX")"
output="$(mktemp -d "${TMPDIR:-/tmp}/ttd-out.XXXXXX")"
# World-writable so compose user 1001:1001 can write into host bind mounts
chmod 0777 "${work}" "${output}"
cat <<EOF
export TTD_PROJECT_NAME=$(printf '%q' "${project}")
export TTD_WORK_DIR=$(printf '%q' "${work}")
export TTD_OUTPUT_DIR=$(printf '%q' "${output}")
export TTD_EXAMPLE_DIR=$(printf '%q' "${TTD_EXAMPLE_DIR:-${SCRIPT_DIR}/.empty}")
export TTD_NETWORK_NAME=$(printf '%q' "${project}-net")
EOF
}
prepare_exports() {
require_host_prereqs
if [[ -z "${TTD_PROJECT_NAME:-}" || -z "${TTD_WORK_DIR:-}" || -z "${TTD_OUTPUT_DIR:-}" ]]; then
eval "$(cmd_env)"
fi
export TTD_EXAMPLE_DIR="${TTD_EXAMPLE_DIR:-${SCRIPT_DIR}/.empty}"
export TTD_NETWORK_NAME="${TTD_NETWORK_NAME:-${TTD_PROJECT_NAME}-net}"
mkdir -p "${TTD_WORK_DIR}" "${TTD_OUTPUT_DIR}"
# Re-apply in case dirs were pre-created without cmd_env chmod
chmod 0777 "${TTD_WORK_DIR}" "${TTD_OUTPUT_DIR}"
}
cmd_up_stack() {
prepare_exports
export TTD_PROFILE=stack
write_env_file
compose --profile stack build runner-stack
compose --profile stack up -d --remove-orphans dind runner-stack
# Wait until the runner can talk to DinD
compose --profile stack exec -T runner-stack bash -lc '
set -euo pipefail
for i in $(seq 1 60); do
if docker info >/dev/null 2>&1; then
break
fi
sleep 1
done
docker info >/dev/null
cd /work
if [[ ! -f supabase/config.toml ]]; then
printf 'n\nn\n' | supabase init
fi
supabase start
'
echo "sandbox ready: project=${TTD_PROJECT_NAME} work=${TTD_WORK_DIR} profile=stack (DinD)" >&2
}
cmd_up_examples() {
prepare_exports
export TTD_PROFILE=examples
write_env_file
compose --profile examples build runner
compose --profile examples up -d --remove-orphans runner
# Copy read-only mount into writable /work so npm can install without mutating the repo
compose --profile examples exec -T runner \
bash -lc 'rm -rf /work/example && mkdir -p /work/example && cp -a /examples/. /work/example/'
echo "sandbox ready: project=${TTD_PROJECT_NAME} work=${TTD_WORK_DIR} profile=examples (build in /work/example)" >&2
}
cmd_exec() {
load_env_file
local svc
svc="$(runner_service)"
compose --profile "${TTD_PROFILE}" exec -T "${svc}" "$@"
}
cmd_exec_timeout() {
load_env_file
local secs="$1"
shift
if [[ "${1:-}" == "--" ]]; then
shift
fi
local svc
svc="$(runner_service)"
compose --profile "${TTD_PROFILE}" exec -T "${svc}" \
timeout --foreground --signal=TERM --kill-after=5s "${secs}s" "$@"
}
cmd_down() {
if [[ -f "${SCRIPT_DIR}/.state/current.env" ]]; then
# shellcheck disable=SC1091
source "${SCRIPT_DIR}/.state/current.env"
else
die "no active sandbox state"
fi
if [[ "${TTD_PROFILE:-}" == "stack" ]]; then
compose --profile stack exec -T runner-stack bash -lc 'cd /work && supabase stop 2>/dev/null || true' 2>/dev/null || true
fi
compose --profile "${TTD_PROFILE:-stack}" down -v --remove-orphans 2>/dev/null || true
rm -rf "${TTD_WORK_DIR:-}" "${TTD_OUTPUT_DIR:-}" 2>/dev/null || true
rm -f "${SCRIPT_DIR}/.state/current.env"
echo "sandbox torn down: ${TTD_PROJECT_NAME:-unknown}" >&2
}
usage() {
sed -n '2,10p' "$0" | sed 's/^# //; s/^#//'
}
main() {
local cmd="${1:-}"
shift || true
case "${cmd}" in
env) cmd_env "$@" ;;
up-stack) cmd_up_stack "$@" ;;
up-examples) cmd_up_examples "$@" ;;
exec)
if [[ "${1:-}" == "--" ]]; then shift; fi
cmd_exec "$@"
;;
exec-timeout) cmd_exec_timeout "$@" ;;
down) cmd_down "$@" ;;
-h | --help | help | "") usage ;;
*) die "unknown command: ${cmd}" ;;
esac
}
main "$@"
+6 -1
View File
@@ -28,7 +28,7 @@ Four inputs, read in this sequence (sequence, not priority; Linear remains the p
1. **Style guide — voice/terminology reference.** Start with [`apps/docs/CONTRIBUTING.md`](../../../apps/docs/CONTRIBUTING.md) and [`apps/docs/WORD_LIST.md`](../../../apps/docs/WORD_LIST.md) for voice, structure, and terminology. If those don't cover the case, fall back to the nearest comparable existing page under `apps/docs/content/` and say explicitly: _"no dedicated style guide yet — following the precedent of `<page>`."_ See [reference/style-fallback.md](reference/style-fallback.md).
2. **Linear — the ticket and its product context.** Linear is an internal Supabase tool: preferred when available, not required for open-source contributors. When a Linear issue is available, pull it, then its parent project/initiative description too (PRD, PRFAQ, RFC, or initiative narrative) and any PM comments. Product framing/positioning language usually lives one level up from the ticket, in the parent project or initiative description rather than the ticket body. Distinguish scope the ticket actually commits to from aspirational language in the PRD. If there is no Linear issue and no prior Frame/Shape product-intent output, stop drafting: ask internal authors for a Linear URL, otherwise hand off to [`pm-the-docs`](../pm-the-docs/SKILL.md) (Frame) and [`ask-the-docs`](../ask-the-docs/SKILL.md) when Shape/IA is unsettled. Resume only after product intent exists — never invent positioning, and never run Frame/Shape inside this Draft skill.
3. **Code.** Read the actual implementation before writing a single behavior claim — the PRD describes intent, the code describes what shipped. Check the Linear issue/project first for a linked `supabase/supabase` PR — its diff and description are the most precise "what actually shipped" source, more precise than a general codebase read. If no PR is linked, locate the feature directly in `supabase/supabase` (or the product's own repo), and apply [`ask-the-docs`](../ask-the-docs/SKILL.md)'s reuse/minimalism lens: understand what exists before describing it. If code and PRD disagree, the code wins for behavior claims — flag the mismatch rather than silently picking one.
3. **Code.** Read the actual implementation before writing a single behavior claim — the PRD describes intent, the code describes what shipped. Check the Linear issue/project first for a linked `supabase/supabase` PR — its diff and description are the most precise "what actually shipped" source, more precise than a general codebase read. If no PR is linked, locate the feature directly in `supabase/supabase` (or the product's own repo), and apply [`ask-the-docs`](../ask-the-docs/SKILL.md)'s reuse/minimalism lens: understand what exists before describing it. When behavior spans services (CLI, Auth, migrations, platform, …), follow [`pm-the-docs`](../pm-the-docs/SKILL.md) → [universe-lookup](../pm-the-docs/reference/universe-lookup.md) **capability gate** (universe when accessible, else OSS public search / linked repos — not `ask-the-docs`). If code and PRD disagree, the code wins for behavior claims — flag the mismatch rather than silently picking one.
4. **Whatever else the author supplies.** Screenshots, example projects, related pages, Slack threads, a specific voice sample. Screenshots are for more than general context — use them to verify the _exact_ button/menu/field labels before writing instructional steps that reference them; a mismatched UI label is one of the easiest, most avoidable errors in a draft. Ask for these when the feature's user-facing shape is still unclear after 1–3, rather than guessing.
Summarize all four back to the requester before drafting: what's confirmed, what's product intent vs. shipped behavior, what's still a gap. Stop and ask if a real gap would change the draft's structure or scope.
@@ -67,6 +67,7 @@ Before handing off, confirm:
- [ ] Content type confirmed as Guide/Troubleshooting (not something that belongs in generated Reference instead)
- [ ] Nav placement and nav enablement both wired, not just the placement
- [ ] Internal links resolve; first-use of new terms/acronyms is defined
- [ ] If the draft has procedural snippets (CLI, SQL, client code, or example apps), **offered** to run [`test-the-docs`](../test-the-docs/SKILL.md) (optional; Docker Compose sandbox — stack profile for DB/API, examples profile for `example-app`)
- [ ] Future promises minimized where possible (timeless documentation principle)
- [ ] No unnecessary redundancy (same point restated multiple ways)
- [ ] Single-item lists avoided unless there's a specific reason
@@ -86,6 +87,8 @@ Re-read [`apps/docs/CONTRIBUTING.md`](../../../apps/docs/CONTRIBUTING.md) and [`
This skill stops at a reviewable draft. It does not open worktrees or PRs itself:
- **Offer** [`test-the-docs`](../test-the-docs/SKILL.md) when the draft includes runnable procedural snippets. Ask before starting verification. Gate prerequisites **per artifact class** (Docker Compose stack profile for DB/API artifacts; examples profile / Node in-runner for `example-app`). If declined, or a required prerequisite for that class is missing, record `deferred` for those artifacts only and continue. When accepted, attach the verification report to the PR body / self-review note.
- Then run [`review-the-docs`](../review-the-docs/SKILL.md) local self-review (lint/build/classify).
- Hand off to [`create-pull-request`](https://github.com/supabase/docs-agent-skills/blob/main/.claude/skills/create-pull-request/SKILL.md) (and [`work-linear-issue`](https://github.com/supabase/docs-agent-skills/blob/main/.claude/skills/work-linear-issue/SKILL.md) if the ticket needs a full worktree+PR flow) for the actual PR mechanics. Carry the Phase 1/2 flagged-assumptions list forward explicitly into that handoff — it belongs in the PR description (e.g. a "needs review" section) so a reviewer sees it, not just as an inline comment buried in the draft.
- If the feature is UI-driven and the PR will need screenshots/GIFs, flag [`proof-it-works`](https://github.com/supabase/docs-agent-skills/blob/main/.claude/skills/proof-it-works/SKILL.md) as the next step rather than capturing evidence here.
- Before opening the PR, run [`review-the-docs`](../review-the-docs/SKILL.md) local self-review: `pnpm lint:mdx`, `pnpm build:guides-markdown` where applicable, and anchor checks per [reference/drafting-mechanics.md](reference/drafting-mechanics.md).
@@ -98,6 +101,8 @@ This skill stops at a reviewable draft. It does not open worktrees or PRs itself
- Content-type gate detail: [reference/content-type-gate.md](reference/content-type-gate.md)
- Existing-page restructure/clarity: [`edit-the-docs`](../edit-the-docs/SKILL.md)
- "Write the docs" checklist (Draft stage): [`pm-the-docs`](../pm-the-docs/SKILL.md)'s [reference/write-the-docs-checklist.md](../pm-the-docs/reference/write-the-docs-checklist.md)
- Cross-repo product lookup: [`pm-the-docs`](../pm-the-docs/SKILL.md) → [universe-lookup](../pm-the-docs/reference/universe-lookup.md)
- Runnable verification: [`test-the-docs`](../test-the-docs/SKILL.md)
- Docs-app architecture/placement: [`ask-the-docs`](../ask-the-docs/SKILL.md), [`audit-docs-ia`](https://github.com/supabase/docs-agent-skills/blob/main/.claude/skills/audit-docs-ia/SKILL.md)
- PR mechanics: [`create-pull-request`](https://github.com/supabase/docs-agent-skills/blob/main/.claude/skills/create-pull-request/SKILL.md), [`work-linear-issue`](https://github.com/supabase/docs-agent-skills/blob/main/.claude/skills/work-linear-issue/SKILL.md)
- Screenshots/proof: [`proof-it-works`](https://github.com/supabase/docs-agent-skills/blob/main/.claude/skills/proof-it-works/SKILL.md)
+3 -2
View File
@@ -23,14 +23,15 @@ To make docs as clear as possible:
If you're using an AI coding agent (Claude Code, Codex, or anything else that reads `.agents/skills/`), this repo ships skills that back the [Write the docs](../../.agents/skills/pm-the-docs/reference/write-the-docs-checklist.md) authoring checklist.
Ask your agent for a skill by name (`write-the-docs`, `edit-the-docs`, `ask-the-docs`, `pm-the-docs`, `review-the-docs`); in Claude Code these are also available as `/name` slash commands.
Ask your agent for a skill by name (`pm-the-docs`, `ask-the-docs`, `write-the-docs`, `edit-the-docs`, `test-the-docs`, `review-the-docs`); in Claude Code these are also available as `/name` slash commands.
| Skill | Checklist stage | Use for |
| --- | --- | --- |
| [`pm-the-docs`](../../.agents/skills/pm-the-docs/SKILL.md) | Frame / Shape | Audience, product-stage, and cross-cutting scope calls |
| [`pm-the-docs`](../../.agents/skills/pm-the-docs/SKILL.md) | Frame / Shape | Audience, product-stage, and cross-cutting scope calls (universe when you have Supabase org access, else OSS path) |
| [`ask-the-docs`](../../.agents/skills/ask-the-docs/SKILL.md) | Frame / Shape | `apps/docs` architecture, IA placement, and where content lives |
| [`write-the-docs`](../../.agents/skills/write-the-docs/SKILL.md) | Draft | Drafting net-new content grounded in the code |
| [`edit-the-docs`](../../.agents/skills/edit-the-docs/SKILL.md) | Edit | Restructure and improve existing pages |
| [`test-the-docs`](../../.agents/skills/test-the-docs/SKILL.md) | Draft / Self-review | Execute docs snippets in a Docker-isolated local stack; verification report |
| [`review-the-docs`](../../.agents/skills/review-the-docs/SKILL.md) | Self-review / PR review | Checking a draft and PR triage/verification |
The canonical files live in `.agents/skills/`; `.claude/skills` is a Git symlink to that directory so Claude Code discovers them too.