Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
44 changes: 44 additions & 0 deletions .claude/skills/CONVENTIONS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# Shared Conventions

Rules that apply across all skills. Each SKILL.md references this file instead of repeating these.

---

## Scope

- **Stay inside the target package directory.** Do not read files outside of it unless explicitly told to.
- **Do not invent features.** Only document or test what source code confirms exists.

## Code Examples

- Use **TypeScript** in all code examples.
- Keep examples minimal — just enough to show the point, no boilerplate.

## Testing

- **Use real Fastify instances. Do NOT mock Fastify.** Plugins are side-effect functions — mocking the instance means testing nothing.
- **Do NOT mock base-library plugins** (e.g., `@fastify/swagger`, `@fastify/multipart`). The point of the integration layer tests is to catch breakage from dependency upgrades. Mock only our own modules (migrations, sub-plugins we authored).
- **Always close Fastify instances in `afterEach`** to avoid resource leaks.
- **Use Vitest** (`import from "vitest"`). The project already has it configured.
- **Test what WE wrote, not what third-party libraries do.** Ask: "Does this verify code our team wrote, or that a third-party library works?"
- **Name tests by behavior**, not implementation. GOOD: `"decorates instance with default documentation path"` BAD: `"line 23 sets routePrefix"`

### Known Fastify 5 Gotchas

These patterns have been validated in this monorepo. Follow them to avoid known pitfalls:

1. **`hasContentTypeParser("*")` returns false** even when a `*` catch-all parser is registered in Fastify 5. Use a behavioural test instead: inject a request with an unusual content-type and assert the status is not 415.
2. **Asserting `vi.fn()` plugin calls**: always include `expect.any(Function)` as the third argument — Fastify calls plugins as `plugin(fastify, options, done)`.
3. **`Readable.from(["string"])` emits strings, not Buffers.** `Buffer.concat` will throw. Use `Readable.from([Buffer.from("string")])` instead.
4. **Verify `@fastify/multipart`** with `fastify.hasContentTypeParser("multipart/form-data")`, not `getSchema("fileSchema")` — `sharedSchemaId` does not expose a schema via `fastify.getSchema`.

## Base Library Documentation

- **Do not repeat base library documentation in detail.** Link to their docs.
- **For doc links:** use the library's official docs URL. If unsure, use the npm page: `https://www.npmjs.com/package/{package-name}`.
- **List only the delta** for partial/modified passthroughs — what we change, not what we preserve.

## Reference Packages

- `packages/firebase` — has FEATURES.md and comprehensive tests
- `packages/config` — has GUIDE.md as the format reference
82 changes: 82 additions & 0 deletions .claude/skills/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
# Skills

Slash commands for analyzing, documenting, and testing Fastify plugin packages.

All skills share conventions defined in [CONVENTIONS.md](CONVENTIONS.md) — testing rules, code example standards, Fastify 5 gotchas, and base library documentation patterns.

## Dependency Graph

Skills automatically invoke their prerequisites. You do not need to chain them manually.

```
/analyze-package (no dependencies — reads source code)
/write-docs (runs /analyze-package if needed)
/write-developer-docs (runs /analyze-package if needed)
/write-tests (runs /write-docs if FEATURES.md missing)
```

Orchestrator skills run the full chain:

```
/package-developer-docs → /analyze-package → /write-developer-docs
/package-full → /analyze-package → /write-docs → /write-developer-docs → /write-tests
```

## Available Skills

| Skill | Description | Produces |
| -------------------------------- | --------------------------------------------------------- | --------------------------------------- |
| `/analyze-package <path>` | Explore source code and classify it as "ours" vs "theirs" | `ANALYSIS.md`, analysis in conversation |
| `/write-docs <path>` | Create/update FEATURES.md and GUIDE.md | `FEATURES.md`, `GUIDE.md` |
| `/write-developer-docs <path>` | Create/update README.md for developer evaluation | `README.md` |
| `/write-tests <path>` | Write and run unit tests | `src/__test__/*.test.ts` |
| `/package-developer-docs <path>` | Orchestrator: analyze → developer-docs | Analysis + `README.md` |
| `/package-full <path>` | Orchestrator: analyze → docs → developer-docs → tests | All docs + tests |

## Usage

### Full pipeline (new package)

```
/package-full packages/my-plugin
```

Runs analyze → docs → developer-docs → tests in order. Use this when starting from scratch.

### Individual skills (self-sufficient)

Each skill auto-invokes its prerequisites if needed. Run any skill standalone:

```
/write-docs packages/my-plugin # auto-runs /analyze-package first
/write-developer-docs packages/my-plugin # auto-runs /analyze-package first
/write-tests packages/my-plugin # auto-runs /write-docs if FEATURES.md missing
```

### Reusing analysis in one conversation

If you run `/analyze-package` first, downstream skills detect the existing analysis and skip re-running it:

```
/analyze-package packages/my-plugin # explore and classify code
/write-docs packages/my-plugin # reuses analysis above (no re-run)
/write-developer-docs packages/my-plugin # reuses analysis above (no re-run)
```

### Common scenarios

| Scenario | What to run |
| ---------------------------------- | ---------------------------------- |
| New package, need everything | `/package-full` |
| Just need README for evaluation | `/package-developer-docs` |
| Docs exist, just need tests | `/write-tests` |
| Source changed, update docs only | `/write-docs` |
| Want to understand a package first | `/analyze-package` |
| Tests broke after dependency bump | `/write-tests` (fix/rewrite tests) |

## Reference packages

- `packages/firebase` — has FEATURES.md and comprehensive tests
- `packages/config` — has GUIDE.md as the format reference
110 changes: 110 additions & 0 deletions .claude/skills/analyze-package/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
---
name: analyze-package
description: Explore a Fastify plugin package and produce a structured analysis classifying code as "ours" vs "theirs" with passthrough behavior. Use this skill whenever the user asks to analyze, understand, break down, or explore a package — e.g., "what does packages/auth do?", "break down this plugin", "analyze packages/config". Also triggers as a prerequisite for /write-docs, /write-developer-docs, and /write-tests.
argument-hint: [package-path]
effort: low
---

# Analyze a Fastify Plugin Package

Analyze the package at: `$ARGUMENTS`

If no path is provided, use the current working directory.

Read `.claude/skills/CONVENTIONS.md` now before starting any analysis.

---

## Step 1: Read the Package

Read `src/plugin.ts` and `src/index.ts` first — these are the entry points. Then follow their imports to read only the files they reference. Do not read every file blindly; large packages will exhaust context.

Also read these files if they exist:

- `package.json`
- `README.md`
- `FEATURES.md`
- `GUIDE.md`
- Any existing tests in `src/__test__/`

From these files, identify: dependencies, exports, types, decorators, hooks, plugins, defaults, and conditional logic.

---

## Step 2: Classify Code — "Ours" vs "Theirs"

Go through each function and code block. Classify:

- **"Ours"**: Logic we wrote — conditionals, defaults, decorators, transformations, validation, option merging, utility functions, hooks, error handling, logging
- **"Theirs"**: Direct calls to third-party libraries with no transformation (e.g., just passing options through to `@fastify/swagger`)

**Example of a good classification:**

```
// OURS — conditional decorator with default value
if (opts.enableMetrics !== false) {
fastify.decorate("metrics", { enabled: true, prefix: opts.prefix ?? "/metrics" });
}

// THEIRS — direct passthrough, no transformation
await fastify.register(fastifySwagger, opts.swagger);
```

---

## Step 3: Passthrough Analysis

For each dependency the package wraps, answer:

1. **Are all config options passed through?** Check if types come from the base library or if we define a subset.
2. **Do we transform, filter, or override any options?** Look for modifications before passing to the base library.
3. **Do we restrict any base library features?**
4. **What do we add on top?** List every feature our code adds.

### Output format

Print a section titled `## Base Library Passthrough Analysis` with a subsection per dependency:

```
### @scope/library-name — [FULL PASSTHROUGH | PARTIAL PASSTHROUGH | MODIFIED]

- Options type: [imported from base library | custom subset]
- Options passed: [unmodified | transformed — describe how]
- Features restricted: [none | list them]
- Features added: [list them]
```

---

## Step 4: Summary

Print a structured summary listing:

- Every function/export with a one-line description
- Every decorator added
- Every hook registered
- Every conditional branch (feature flags, enable/disable logic)
- Default values

### Completeness checklist

Your analysis is complete when you have:

- [ ] Classified every public export as "ours" or "theirs"
- [ ] Listed every Fastify decorator added
- [ ] Listed every Fastify hook registered
- [ ] Identified every conditional branch (enable/disable flags, feature toggles)
- [ ] Documented default values for all options we define
- [ ] Produced a passthrough classification for every wrapped dependency

If any item is missing, go back and fill it in before finishing.

### Save as ANALYSIS.md

Once the checklist is complete, write the full analysis to `ANALYSIS.md` in the package root. This file is the persistent handoff to downstream skills — it means `/write-docs`, `/write-developer-docs`, and `/write-tests` can read your analysis from disk instead of re-running it.

The file content is the same as what you printed: passthrough analysis + summary. Add this comment as the first line:

```
<!-- Package analysis — produced by /analyze-package. Do not edit manually. -->
```
53 changes: 53 additions & 0 deletions .claude/skills/evals/evals.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
{
"skill_name": "fastify-plugin-skills",
"evals": [
{
"id": 1,
"prompt": "analyze packages/config — I want to understand what this plugin does and what's ours vs what comes from base libraries",
"expected_output": "Structured analysis with ours/theirs classification, passthrough analysis per dependency, decorator list, hook list, conditional branches, and default values. Should complete the checklist.",
"files": [],
"expectations": [
"Output contains a '## Base Library Passthrough Analysis' section",
"Classifies at least one export as 'ours' (our code)",
"Produces a passthrough classification (FULL PASSTHROUGH, PARTIAL PASSTHROUGH, or MODIFIED) for each wrapped dependency",
"Lists at least one Fastify decorator added by the plugin",
"Documents conditional branches or default values",
"Does NOT claim to read files outside the packages/config directory",
"Completeness checklist items are addressed (decorators, hooks, conditional branches, defaults)"
]
},
{
"id": 2,
"prompt": "document packages/config — create FEATURES.md and GUIDE.md for the config plugin",
"expected_output": "FEATURES.md with numbered features grouped by category, and GUIDE.md with setup, base library section, features with examples, and use cases. Should auto-run /analyze-package first.",
"files": [],
"expectations": [
"FEATURES.md is created",
"GUIDE.md is created",
"FEATURES.md starts with the required HTML comment about structured feature inventory",
"FEATURES.md features are numbered sequentially (1., 2., 3. or ## 1.)",
"FEATURES.md does NOT list base library features — only features our code adds",
"GUIDE.md contains a Setup section showing plugin registration",
"GUIDE.md contains at least 3 TypeScript code examples",
"GUIDE.md does NOT contain empty sections or placeholder N/A text",
"Analysis was performed before writing (evidence of ours/theirs classification in the approach)"
]
},
{
"id": 3,
"prompt": "write tests for packages/config — I need unit tests covering the plugin behavior",
"expected_output": "Test files in src/__test__/ using Vitest with real Fastify instances. Tests should pass.",
"files": [],
"expectations": [
"At least one test file created in src/__test__/",
"Tests import Fastify and create real instances (no vi.mock of Fastify)",
"Every test group has afterEach closing the Fastify instance",
"Tests cover conditional logic branches (if/else, enable/disable flags)",
"Tests verify at least one decorator exists on the Fastify instance",
"Tests do NOT mock the base library plugins (env-schema or similar)",
"All tests pass — test_results.txt shows no failures",
"Number of tests is between 5 and 20 (appropriate scope)"
]
}
]
}
37 changes: 37 additions & 0 deletions .claude/skills/package-developer-docs/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
---
name: package-developer-docs
description: Run analysis then generate developer-facing README.md for a Fastify plugin package. Use this skill when the user wants a README with analysis — e.g., "create a README for packages/auth", "I need developer docs for this plugin".
argument-hint: [package-path]
effort: medium
---

# Package Developer Docs Pipeline

Generate developer-facing documentation for: `$ARGUMENTS`

If no path is provided, use the current working directory.

This skill runs two steps in sequence. Complete each step fully before starting the next.

---

## Step 1: Analyze the Package

Run `/analyze-package $ARGUMENTS` and wait for it to complete.

---

## Step 2: Write README.md

Run `/write-developer-docs $ARGUMENTS` and wait for it to complete. It will use the analysis from Step 1.

---

## Output Summary

When both steps are complete, print:

- Passthrough classifications per dependency
- Number of base library sections written
- Number of high-level features listed
- Whether FEATURES.md and GUIDE.md exist (for linking)
65 changes: 65 additions & 0 deletions .claude/skills/package-full/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
---
name: package-full
description: Run the full analysis, documentation, and test-writing pipeline for a Fastify plugin package. Use this skill when the user wants everything done for a package — analysis, FEATURES.md, GUIDE.md, README.md, and tests — e.g., "set up packages/auth from scratch", "full pipeline for this plugin", "document and test packages/config".
argument-hint: [package-path]
effort: high
---

# Full Package Pipeline

Run the complete pipeline for: `$ARGUMENTS`

If no path is provided, use the current working directory.

Follow the shared conventions in `.claude/skills/CONVENTIONS.md`. Read that file before starting.

This skill runs four phases in sequence. Complete each phase fully before starting the next. All phases operate on the same package directory.

---

## Phase 1: Analyze the Package

Run `/analyze-package $ARGUMENTS` and wait for it to complete.

This produces the structured analysis (ours vs theirs classification, passthrough analysis, summary) that all subsequent phases depend on.

---

## Phase 2: Write FEATURES.md and GUIDE.md

Run `/write-docs $ARGUMENTS` and wait for it to complete.

This produces FEATURES.md (structured feature inventory for test generation) and GUIDE.md (comprehensive developer guide).

---

## Phase 3: Write README.md

Run `/write-developer-docs $ARGUMENTS` and wait for it to complete.

This produces the developer-facing README.md with passthrough classifications, key features, and usage guidelines.

---

## Phase 4: Write and Run Tests

Run `/write-tests $ARGUMENTS` and wait for it to complete.

This uses FEATURES.md from Phase 2 to determine what to test, writes the tests, runs them, and fixes any failures.

---

## Output Summary

When all four phases are complete, print a combined summary:

- Number of features documented in FEATURES.md
- Number of features covered in GUIDE.md
- Number of use cases in GUIDE.md
- Passthrough classifications per dependency
- Number of base library sections in README.md
- Number of high-level features in README.md
- Whether Usage Guidelines section was written
- Number of tests written
- Test results (pass/fail)
- Any concerns found
Loading
Loading