@ai-support-agent/cli 0.1.32 → 0.1.33-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (74) hide show
  1. package/dist/alert-processor.d.ts +0 -8
  2. package/dist/alert-processor.d.ts.map +1 -1
  3. package/dist/alert-processor.js +5 -73
  4. package/dist/alert-processor.js.map +1 -1
  5. package/dist/api-client.d.ts +0 -4
  6. package/dist/api-client.d.ts.map +1 -1
  7. package/dist/api-client.js +0 -4
  8. package/dist/api-client.js.map +1 -1
  9. package/dist/commands/claude-code-args.d.ts +1 -0
  10. package/dist/commands/claude-code-args.d.ts.map +1 -1
  11. package/dist/commands/claude-code-args.js +3 -0
  12. package/dist/commands/claude-code-args.js.map +1 -1
  13. package/dist/commands/claude-code-runner.d.ts.map +1 -1
  14. package/dist/commands/claude-code-runner.js +2 -1
  15. package/dist/commands/claude-code-runner.js.map +1 -1
  16. package/dist/commands/plugin-dir.d.ts +20 -0
  17. package/dist/commands/plugin-dir.d.ts.map +1 -0
  18. package/dist/commands/plugin-dir.js +71 -0
  19. package/dist/commands/plugin-dir.js.map +1 -0
  20. package/dist/constants.d.ts +0 -1
  21. package/dist/constants.d.ts.map +1 -1
  22. package/dist/constants.js +0 -1
  23. package/dist/constants.js.map +1 -1
  24. package/dist/plugin/.claude-plugin/plugin.json +9 -0
  25. package/dist/plugin/LICENSE +26 -0
  26. package/dist/plugin/README.md +86 -0
  27. package/dist/plugin/SYNC.md +113 -0
  28. package/dist/plugin/agents/build-error-resolver.md +159 -0
  29. package/dist/plugin/agents/code-reviewer.md +277 -0
  30. package/dist/plugin/agents/django-reviewer.md +159 -0
  31. package/dist/plugin/agents/infra-reviewer.md +172 -0
  32. package/dist/plugin/agents/investigator.md +75 -0
  33. package/dist/plugin/agents/nextjs-reviewer.md +191 -0
  34. package/dist/plugin/agents/php-reviewer.md +167 -0
  35. package/dist/plugin/agents/planner.md +184 -0
  36. package/dist/plugin/agents/python-reviewer.md +161 -0
  37. package/dist/plugin/agents/react-reviewer.md +150 -0
  38. package/dist/plugin/agents/silent-failure-hunter.md +158 -0
  39. package/dist/plugin/agents/typescript-reviewer.md +179 -0
  40. package/dist/plugin/agents/ui-reviewer.md +203 -0
  41. package/dist/plugin/commands/add-feature.md +301 -0
  42. package/dist/plugin/commands/build-fix.md +47 -0
  43. package/dist/plugin/commands/code-review.md +228 -0
  44. package/dist/plugin/commands/fix-defect.md +393 -0
  45. package/dist/plugin/commands/learn-eval.md +94 -0
  46. package/dist/plugin/commands/learn.md +84 -0
  47. package/dist/plugin/commands/plan.md +211 -0
  48. package/dist/plugin/commands/test-coverage.md +64 -0
  49. package/dist/plugin/commands/update-docs.md +98 -0
  50. package/dist/plugin/hooks/hooks.json +59 -0
  51. package/dist/plugin/hooks/scripts/auto-format.sh +63 -0
  52. package/dist/plugin/hooks/scripts/check-secrets-before-commit.sh +50 -0
  53. package/dist/plugin/hooks/scripts/guard-dangerous-commands.sh +55 -0
  54. package/dist/plugin/hooks/scripts/on-command-resume.sh +112 -0
  55. package/dist/plugin/hooks/scripts/on-command-stop.sh +200 -0
  56. package/dist/plugin/hooks/scripts/protect-sensitive-files.sh +58 -0
  57. package/dist/plugin/rules/common/coding-guidelines.md +73 -0
  58. package/dist/plugin/rules/documentation/api-docs.md +46 -0
  59. package/dist/plugin/rules/documentation/docs-site.md +60 -0
  60. package/dist/plugin/rules/documentation/source-docs.md +89 -0
  61. package/dist/plugin/rules/documentation/test-docs.md +39 -0
  62. package/dist/plugin/rules/logging/logging-rules.md +83 -0
  63. package/dist/plugin/rules/php/coding-rules.md +40 -0
  64. package/dist/plugin/rules/python/coding-rules.md +40 -0
  65. package/dist/plugin/rules/typescript/coding-rules.md +45 -0
  66. package/dist/plugin/skills/api-design/SKILL.md +269 -0
  67. package/dist/plugin/skills/backend-patterns/SKILL.md +312 -0
  68. package/dist/plugin/skills/database-migrations/SKILL.md +323 -0
  69. package/dist/plugin/skills/docker-patterns/SKILL.md +308 -0
  70. package/dist/plugin/skills/docs-site/SKILL.md +341 -0
  71. package/dist/plugin/skills/e2e-testing/SKILL.md +334 -0
  72. package/dist/plugin/skills/frontend-patterns/SKILL.md +318 -0
  73. package/dist/plugin/skills/integration-testing/SKILL.md +273 -0
  74. package/package.json +2 -2
@@ -0,0 +1,308 @@
1
+ ---
2
+ name: docker-patterns
3
+ description: A collection of Docker / Docker Compose best practices covering multi-stage builds, layer caching, image size reduction, security, healthchecks, and Compose-based dev environment setup. Reference this when creating, modifying, or reviewing a Dockerfile or docker-compose.yml.
4
+ ---
5
+
6
+ # Docker Patterns
7
+
8
+ A skill that captures the decision criteria for writing Dockerfiles and Docker Compose files.
9
+ When starting from scratch, work through this order: base image selection → stage separation → cache optimization → security → healthchecks.
10
+
11
+ ## Multi-Stage Builds
12
+
13
+ Separate the build stage from the runtime stage so that build-only tooling (compilers, devDependencies, the Composer binary, etc.) never ends up in the runtime image.
14
+
15
+ Benefits:
16
+ - The runtime image is smaller, which speeds up distribution and deployment
17
+ - Vulnerabilities originating from build tools don't linger in the runtime environment
18
+ - Source code and intermediate build artifacts can't leak into the final image
19
+
20
+ ### Node.js example
21
+
22
+ ```dockerfile
23
+ # Good: use devDependencies in the build stage, hand only the build output to runtime
24
+ FROM node:22-slim AS build
25
+ WORKDIR /app
26
+ COPY package.json package-lock.json ./
27
+ RUN npm ci
28
+ COPY . .
29
+ RUN npm run build
30
+
31
+ FROM node:22-slim AS runtime
32
+ WORKDIR /app
33
+ ENV NODE_ENV=production
34
+ COPY package.json package-lock.json ./
35
+ RUN npm ci --omit=dev
36
+ COPY --from=build /app/dist ./dist
37
+ USER node
38
+ CMD ["node", "dist/main.js"]
39
+ ```
40
+
41
+ ### Python example
42
+
43
+ ```dockerfile
44
+ # Good: copy only the installed dependency output into the runtime stage
45
+ FROM python:3.12-slim AS build
46
+ WORKDIR /app
47
+ RUN apt-get update && apt-get install -y --no-install-recommends build-essential \
48
+ && rm -rf /var/lib/apt/lists/*
49
+ COPY requirements.txt ./
50
+ RUN pip install --prefix=/install --no-cache-dir -r requirements.txt
51
+
52
+ FROM python:3.12-slim AS runtime
53
+ WORKDIR /app
54
+ COPY --from=build /install /usr/local
55
+ COPY . .
56
+ RUN useradd --create-home --shell /usr/sbin/nologin appuser
57
+ USER appuser
58
+ CMD ["python", "-m", "app"]
59
+ ```
60
+
61
+ Keep compiler packages such as build-essential confined to the build stage. Only bring the artifacts installed via `--prefix` into the runtime stage.
62
+
63
+ ### PHP-FPM example
64
+
65
+ ```dockerfile
66
+ # Good: resolve dependencies in a composer stage, ship only vendor/ into the runtime image
67
+ FROM composer:2 AS vendor
68
+ WORKDIR /app
69
+ COPY composer.json composer.lock ./
70
+ RUN composer install --no-dev --prefer-dist --no-scripts --no-interaction
71
+
72
+ FROM php:8.3-fpm AS runtime
73
+ WORKDIR /var/www/html
74
+ RUN docker-php-ext-install pdo_mysql opcache
75
+ COPY --from=vendor /app/vendor ./vendor
76
+ COPY . .
77
+ RUN chown -R www-data:www-data /var/www/html
78
+ USER www-data
79
+ CMD ["php-fpm"]
80
+ ```
81
+
82
+ This keeps the (tens-of-MB) Composer binary and any dev-only dependencies excluded via `--no-dev` out of the runtime image.
83
+
84
+ ## Layer Caching
85
+
86
+ Docker caches layers individually and re-executes every layer from the point where the copied content first changes. Dependency manifests (lock files) change far less often than source code, so copy them in on their own first, letting the dependency-install step ride the cache.
87
+
88
+ ```dockerfile
89
+ # Bad: even a one-line source change forces npm ci to run every time
90
+ COPY . .
91
+ RUN npm ci
92
+
93
+ # Good: npm ci stays cached as long as the lock file doesn't change
94
+ COPY package.json package-lock.json ./
95
+ RUN npm ci
96
+ COPY . .
97
+ ```
98
+
99
+ Files to copy first, by language:
100
+ - Node.js: package.json and package-lock.json (or pnpm-lock.yaml / yarn.lock)
101
+ - Python: requirements.txt (or pyproject.toml plus poetry.lock / uv.lock)
102
+ - PHP: composer.json and composer.lock
103
+
104
+ Additional notes:
105
+ - Always combine `apt-get update` and `apt-get install` into a single `RUN`. Splitting them lets a stale package-list layer get reused, causing the install to fail or pull outdated versions.
106
+ - Place instructions that change less often earlier in the Dockerfile.
107
+
108
+ ## Reducing Image Size
109
+
110
+ ### Choosing between slim and alpine
111
+
112
+ - slim (Debian-based): the default choice. glibc-compatible, so native extensions and prebuilt binaries work out of the box.
113
+ - alpine (musl-based): reserve this for when you truly need the smallest possible size. Watch out for:
114
+ - Prebuilt binaries that assume glibc may not run under musl libc
115
+ - Python loses access to manylinux wheels, forcing a source build that's slower and often needs extras like build-base
116
+ - Node.js native modules (sharp, bcrypt, etc.) may also need rebuilding
117
+ - Subtle behavioral differences (e.g., DNS resolution) that are hard to debug
118
+
119
+ When in doubt, choose slim. Reserve alpine for cases with no native dependencies, or where image size constraints are strict.
120
+
121
+ ### .dockerignore
122
+
123
+ Keeps the build context small and prevents unwanted or sensitive files from leaking into the image. Always place one at the project root.
124
+
125
+ ```
126
+ # baseline .dockerignore
127
+ .git
128
+ node_modules
129
+ vendor
130
+ __pycache__
131
+ *.log
132
+ .env
133
+ .env.*
134
+ dist
135
+ coverage
136
+ Dockerfile
137
+ docker-compose*.yml
138
+ ```
139
+
140
+ Without a `.dockerignore`, a Dockerfile using `COPY . .` will bake `.env` and `.git` straight into the image.
141
+
142
+ ## Security
143
+
144
+ ### Run as a non-root user
145
+
146
+ Running the container process as root widens the blast radius if a vulnerability is exploited.
147
+
148
+ ```dockerfile
149
+ # Bad: no USER directive (runs as root)
150
+ CMD ["node", "server.js"]
151
+
152
+ # Good: use the user bundled with the official image (node for Node.js, www-data for php-fpm)
153
+ USER node
154
+ CMD ["node", "server.js"]
155
+ ```
156
+
157
+ For images that don't ship a ready-made user, create one with `useradd` (see the Python example above). `chown` any directories that need write access before switching `USER`.
158
+
159
+ ### Never bake secrets into the image
160
+
161
+ Secrets passed via ARG / ENV / COPY can be recovered from `docker history` or by inspecting layers. Removing a file with `rm` in a later layer does not remove it from earlier layers.
162
+
163
+ ```dockerfile
164
+ # Bad: the build-arg value persists in the image history
165
+ ARG NPM_TOKEN
166
+ RUN echo "//registry.npmjs.org/:_authToken=${NPM_TOKEN}" > .npmrc \
167
+ && npm ci && rm .npmrc
168
+
169
+ # Good: BuildKit secret mounts never land in a layer
170
+ RUN --mount=type=secret,id=npmrc,target=/root/.npmrc npm ci
171
+ ```
172
+
173
+ Pass the secret at build time with something like `docker build --secret id=npmrc,src=$HOME/.npmrc .`. For runtime secrets, use environment variables (Compose's `env_file`) or a secrets-management backend, and add `.env` files to both `.dockerignore` and `.gitignore`.
174
+
175
+ ### Pin versions (never use `latest`)
176
+
177
+ ```dockerfile
178
+ # Bad: content changes depending on when the image is pulled, breaking reproducibility
179
+ FROM node:latest
180
+ FROM python
181
+
182
+ # Good: pin at least major.minor
183
+ FROM node:22-slim
184
+ FROM python:3.12-slim
185
+
186
+ # Good: pin by digest when you need strict reproducibility
187
+ FROM node:22-slim@sha256:<digest>
188
+ ```
189
+
190
+ Pin versions for apt/pip packages too whenever reproducibility matters.
191
+
192
+ ## Healthchecks
193
+
194
+ ### Dockerfile HEALTHCHECK
195
+
196
+ ```dockerfile
197
+ # Good: poll the app's health endpoint on a schedule
198
+ HEALTHCHECK --interval=30s --timeout=3s --start-period=10s --retries=3 \
199
+ CMD curl -fsS http://localhost:3000/healthz || exit 1
200
+ ```
201
+
202
+ On slim-family images that lack `curl`, fall back to `wget` or a check written in the language runtime itself (e.g. `CMD ["node", "healthcheck.js"]`).
203
+
204
+ ### Compose healthcheck and depends_on
205
+
206
+ By default, `depends_on` only guarantees *startup order*, not readiness. To wait until a database is actually ready to accept connections, combine `healthcheck` with a `condition`.
207
+
208
+ ```yaml
209
+ services:
210
+ db:
211
+ image: postgres:16
212
+ healthcheck:
213
+ test: ["CMD-SHELL", "pg_isready -U app"]
214
+ interval: 5s
215
+ timeout: 3s
216
+ retries: 10
217
+ start_period: 10s
218
+
219
+ api:
220
+ build: .
221
+ depends_on:
222
+ db:
223
+ condition: service_healthy # don't start api until db is healthy
224
+ ```
225
+
226
+ Condition types:
227
+ - `service_started`: wait only for the container to start (default)
228
+ - `service_healthy`: wait until the healthcheck succeeds
229
+ - `service_completed_successfully`: wait for a one-shot task (e.g. a migration) to exit successfully
230
+
231
+ ## Compose-Based Development Environments
232
+
233
+ ### Choosing between volume types
234
+
235
+ - Named volumes: for persistent data you want to survive container rebuilds, such as database data
236
+ - Bind mounts: for things like source code, where you want host-side edits reflected immediately
237
+
238
+ ```yaml
239
+ services:
240
+ api:
241
+ build: .
242
+ volumes:
243
+ - .:/app # source via bind mount (for hot reload)
244
+ - /app/node_modules # don't let the host's node_modules overwrite the container's
245
+ db:
246
+ image: postgres:16
247
+ volumes:
248
+ - db-data:/var/lib/postgresql/data # data via named volume
249
+
250
+ volumes:
251
+ db-data:
252
+ ```
253
+
254
+ ### Override files
255
+
256
+ Keep the base definition in `docker-compose.yml`, and isolate dev-only differences (bind mounts, debug ports, dev commands) in `docker-compose.override.yml`. Since `docker compose up` merges the override file automatically, production and CI should explicitly pass `-f docker-compose.yml` only, excluding the dev-only overrides.
257
+
258
+ ### Bind ports to localhost
259
+
260
+ ```yaml
261
+ # Bad: exposed on all interfaces, reachable from the LAN or beyond
262
+ ports:
263
+ - "5432:5432"
264
+
265
+ # Good: bind a dev database to the loopback interface only
266
+ ports:
267
+ - "127.0.0.1:5432:5432"
268
+ ```
269
+
270
+ For services the host never needs to reach directly, skip `ports` entirely and rely on container-to-container communication (via service-name resolution).
271
+
272
+ ### Network isolation
273
+
274
+ Minimize the reachable surface. Put only the reverse proxy on the outward-facing network, and keep the database reachable solely from the app.
275
+
276
+ ```yaml
277
+ services:
278
+ proxy:
279
+ networks: [frontend]
280
+ api:
281
+ networks: [frontend, backend]
282
+ db:
283
+ networks: [backend] # unreachable from proxy
284
+
285
+ networks:
286
+ frontend:
287
+ backend:
288
+ ```
289
+
290
+ ## Anti-Patterns
291
+
292
+ - Specifying a base image as `FROM xxx:latest` (breaks reproducibility)
293
+ - Writing `COPY . .` before the dependency-install step (invalidates the cache on every build)
294
+ - Running `COPY . .` without a `.dockerignore` (leaks `.git` or `.env` into the image)
295
+ - Passing secrets via ARG / ENV (recoverable from `docker history`)
296
+ - Running the app as root because `USER` was never set
297
+ - Splitting `apt-get update` and `apt-get install` into separate `RUN` instructions
298
+ - Leaving the apt cache (`/var/lib/apt/lists`) or pip cache in the image instead of clearing it
299
+ - Cramming multiple processes into one container (app + cron + nginx, etc.)
300
+ - Assuming `depends_on` alone guarantees the database is ready (no `condition` specified)
301
+ - Exposing a dev database port on `0.0.0.0`
302
+ - Reaching for alpine without considering native extension compatibility
303
+ - Writing logs to a file instead of stdout/stderr (let the runtime handle log collection)
304
+ - Running `git clone` inside the image instead of `COPY`-ing through the build context
305
+
306
+ ## Related
307
+
308
+ - Use `/code-review` when reviewing Dockerfile / Compose file changes
@@ -0,0 +1,341 @@
1
+ ---
2
+ name: docs-site
3
+ description: A pattern library for building and operating a documentation site with Docusaurus. Covers i18n (ja/en) structure, automatic OpenAPI generation from NestJS, wiring OpenAPI/TypeDoc output into Docusaurus, type and client generation with openapi-typescript / orval, templates for hand-written reference pages, and CI freshness checks. Use this when setting up a new documentation site, adding pages, updating API references, syncing translations, or building a type-generation pipeline.
4
+ ---
5
+
6
+ # docs-site: Docusaurus documentation site patterns
7
+
8
+ This skill is a pattern library focused on "how to build it." The authoritative source for the conventions themselves lives in `rules/documentation/` (aimed at repository maintainers); this skill assumes those conventions are already settled and provides the implementation steps.
9
+
10
+ ## Baseline conventions assumed here
11
+
12
+ - Locales are `ja` (default) + `en`. Hand-written guides must exist in both languages. Auto-generated reference pages exist only in the default locale.
13
+ - NestJS APIs are documented by auto-generating from OpenAPI (hand-transcribing is not allowed). For TS libraries, prefer TypeDoc auto-generation. Python / PHP are handled with hand-written templates plus a consistency check.
14
+ - Hand-written reference pages must include a `source: src/path/file.ts#functionName` key in the frontmatter.
15
+ - Links to tests use a repository-absolute URL anchored to the default branch (never pin to a commit SHA).
16
+
17
+ ## 1. Basic Docusaurus i18n setup
18
+
19
+ ### docusaurus.config.js
20
+
21
+ ```js
22
+ // docusaurus.config.js (excerpt)
23
+ module.exports = {
24
+ title: 'Docs',
25
+ url: 'https://docs.example.com',
26
+ baseUrl: '/',
27
+ i18n: {
28
+ defaultLocale: 'ja', // default locale is ja
29
+ locales: ['ja', 'en'],
30
+ },
31
+ themeConfig: {
32
+ navbar: {
33
+ // always include a locale-switcher dropdown
34
+ items: [{ type: 'localeDropdown', position: 'right' }],
35
+ },
36
+ },
37
+ };
38
+ ```
39
+
40
+ ### Directory structure
41
+
42
+ The source-of-truth content for the default locale (ja) lives under `docs/`, and the en translation mirrors the same structure under `i18n/en/`.
43
+
44
+ ```text
45
+ docs/
46
+ guides/getting-started.md # ja original (source of truth)
47
+ i18n/
48
+ en/
49
+ docusaurus-plugin-content-docs/
50
+ current/
51
+ guides/getting-started.md # en translation (same relative path as docs/)
52
+ code.json # translations for UI strings
53
+ ```
54
+
55
+ ### Translation workflow
56
+
57
+ ```bash
58
+ # 1. Generate translation files for UI strings / sidebar labels (for en)
59
+ npm run write-translations -- --locale en
60
+
61
+ # 2. Place the en translation of a hand-written guide under i18n/en/.../current/
62
+ # at the same relative path, then translate it
63
+ cp docs/guides/getting-started.md \
64
+ i18n/en/docusaurus-plugin-content-docs/current/guides/getting-started.md
65
+
66
+ # 3. Run the dev server per locale to check it (dev server serves one locale at a time)
67
+ npm run start -- --locale en
68
+
69
+ # 4. A production build verifies all locales together
70
+ npm run build
71
+ ```
72
+
73
+ Whenever the original (ja) content is updated, update the en translation in the same PR. Auto-generated reference pages (from OpenAPI / TypeDoc) exist only in the default locale — do not copy them into `i18n/en/`.
74
+
75
+ ## 2. Generating OpenAPI output from NestJS
76
+
77
+ Prepare a generation-only script that doesn't depend on the server actually listening. It's important that this can run in CI without opening a port.
78
+
79
+ ```ts
80
+ // scripts/generate-openapi.ts
81
+ import { NestFactory } from '@nestjs/core';
82
+ import { DocumentBuilder, SwaggerModule } from '@nestjs/swagger';
83
+ import { writeFileSync } from 'fs';
84
+ import { AppModule } from '../src/app.module';
85
+
86
+ async function generate() {
87
+ // Build only the application context, without calling listen()
88
+ const app = await NestFactory.create(AppModule, { logger: false });
89
+
90
+ const config = new DocumentBuilder()
91
+ .setTitle('API').setVersion('1.0.0').addBearerAuth()
92
+ .build();
93
+
94
+ const document = SwaggerModule.createDocument(app, config);
95
+ writeFileSync('openapi.json', JSON.stringify(document, null, 2));
96
+
97
+ await app.close();
98
+ }
99
+
100
+ generate();
101
+ ```
102
+
103
+ ```jsonc
104
+ // package.json (excerpt)
105
+ { "scripts": { "openapi:generate": "ts-node scripts/generate-openapi.ts" } }
106
+ ```
107
+
108
+ Enabling the `@nestjs/swagger` CLI plugin lets it auto-infer `@ApiProperty` from DTO properties, which reduces missing-decorator mistakes.
109
+
110
+ ```jsonc
111
+ // nest-cli.json
112
+ {
113
+ "sourceRoot": "src",
114
+ "compilerOptions": {
115
+ "plugins": [
116
+ { "name": "@nestjs/swagger", "options": { "introspectComments": true } }
117
+ ]
118
+ }
119
+ }
120
+ ```
121
+
122
+ ## 3. Pulling OpenAPI into Docusaurus
123
+
124
+ Use `docusaurus-plugin-openapi-docs` to generate MDX pages from `openapi.json`.
125
+
126
+ ```js
127
+ // docusaurus.config.js (excerpt)
128
+ module.exports = {
129
+ plugins: [
130
+ [
131
+ 'docusaurus-plugin-openapi-docs',
132
+ {
133
+ id: 'api',
134
+ docsPluginId: 'classic',
135
+ config: {
136
+ myApi: {
137
+ specPath: 'openapi.json', // the generated spec
138
+ outputDir: 'docs/api', // output location (default locale only)
139
+ sidebarOptions: {
140
+ groupPathsBy: 'tag', // group by tag
141
+ categoryLinkSource: 'tag',
142
+ },
143
+ },
144
+ },
145
+ },
146
+ ],
147
+ ],
148
+ themes: ['docusaurus-theme-openapi-docs'],
149
+ };
150
+ ```
151
+
152
+ ```js
153
+ // sidebars.js (excerpt): pull in the generated sidebar
154
+ module.exports = {
155
+ docs: [
156
+ { type: 'category', label: 'Guides', items: [{ type: 'autogenerated', dirName: 'guides' }] },
157
+ { type: 'category', label: 'API Reference', items: require('./docs/api/sidebar.js') },
158
+ ],
159
+ };
160
+ ```
161
+
162
+ ```bash
163
+ # Regenerate (run this every time the API changes; clear old pages before rebuilding)
164
+ npm run openapi:generate # in the API repository
165
+ npx docusaurus clean-api-docs myApi # remove existing generated output
166
+ npx docusaurus gen-api-docs myApi # regenerate
167
+ ```
168
+
169
+ The generated `docs/api/` content is served only in the default locale (the ja site) — do not create a translated copy under `i18n/en/`, and do not hand-edit it.
170
+
171
+ ## 4. Generating Next.js types and clients from OpenAPI
172
+
173
+ Use `openapi-typescript` if you only need types, or `orval` if you also want a fetch client. In both cases, standardize the output location as `src/generated/`.
174
+
175
+ ```jsonc
176
+ // package.json (excerpt): generate types only
177
+ { "scripts": { "codegen:types": "openapi-typescript ../api/openapi.json -o src/generated/api-types.ts" } }
178
+ ```
179
+
180
+ ```ts
181
+ // orval.config.ts: generate both types and client
182
+ import { defineConfig } from 'orval';
183
+
184
+ export default defineConfig({
185
+ myApi: {
186
+ input: '../api/openapi.json',
187
+ output: {
188
+ target: 'src/generated/api-client.ts',
189
+ client: 'fetch', // use 'react-query' if you're using React Query
190
+ clean: true, // remove stale files on regeneration
191
+ },
192
+ },
193
+ });
194
+ ```
195
+
196
+ Enforce the "no hand-editing" rule with a two-pronged approach: exclude generated files from lint, and detect regeneration drift in CI (see section 7).
197
+
198
+ ```jsonc
199
+ // .eslintrc.json (excerpt): don't lint generated output — this signals it isn't meant to be hand-edited
200
+ {
201
+ "ignorePatterns": ["src/generated/**"]
202
+ }
203
+ ```
204
+
205
+ `src/generated/` should still be committed (so reviewers can see the diff), but a PR containing manual edits to it will fail the CI freshness check.
206
+
207
+ ## 5. Pulling TypeDoc into Docusaurus
208
+
209
+ ```js
210
+ // docusaurus.config.js (excerpt)
211
+ module.exports = {
212
+ plugins: [
213
+ [
214
+ 'docusaurus-plugin-typedoc',
215
+ {
216
+ entryPoints: ['../packages/sdk/src/index.ts'],
217
+ tsconfig: '../packages/sdk/tsconfig.json',
218
+ out: 'docs/sdk', // output location (default locale only)
219
+ sidebar: { autoConfiguration: true },
220
+ },
221
+ ],
222
+ ],
223
+ };
224
+ ```
225
+
226
+ ```js
227
+ // sidebars.js (excerpt): pull in the sidebar generated by TypeDoc
228
+ module.exports = {
229
+ docs: [
230
+ { type: 'category', label: 'SDK Reference', items: require('./docs/sdk/typedoc-sidebar.cjs') },
231
+ ],
232
+ };
233
+ ```
234
+
235
+ Embed links to tests via `@see` in TSDoc comments. Links should use an absolute URL anchored to the default branch (never pin to a SHA).
236
+
237
+ ```ts
238
+ /**
239
+ * Calculates the order total including tax.
240
+ * @param items - array of order line items
241
+ * @see {@link https://github.com/example-org/sdk/blob/main/test/order.spec.ts | order.spec.ts test cases}
242
+ */
243
+ export function calcOrderTotal(items: OrderItem[]): number { /* ... */ }
244
+ ```
245
+
246
+ ## 6. Full template for a hand-written function reference
247
+
248
+ For languages such as Python / PHP where auto-generation isn't available. The `source` frontmatter key is required so the consistency check (`/update-docs`) can trace back to the implementation.
249
+
250
+ ```markdown
251
+ ---
252
+ id: calc-order-total
253
+ title: calc_order_total
254
+ source: src/services/order.py#calc_order_total
255
+ ---
256
+
257
+ ## Overview
258
+
259
+ Calculates the tax-inclusive total from an array of order line items.
260
+
261
+ ## Signature
262
+
263
+ \`\`\`python
264
+ def calc_order_total(items: list[OrderItem], tax_rate: Decimal = Decimal("0.10")) -> int
265
+ \`\`\`
266
+
267
+ ## Parameters
268
+
269
+ | Name | Type | Required | Description |
270
+ | --- | --- | --- | --- |
271
+ | items | list[OrderItem] | Yes | Array of order line items. An empty array is allowed |
272
+ | tax_rate | Decimal | No | Tax rate. Defaults to 0.10 |
273
+
274
+ ## Output
275
+
276
+ The tax-inclusive total (in yen, as an int). Returns 0 for an empty array.
277
+
278
+ ## Errors
279
+
280
+ | Exception | Code | Condition |
281
+ | --- | --- | --- |
282
+ | ValueError | E_NEGATIVE_PRICE | A line item has a negative unit price |
283
+ | ValueError | E_INVALID_TAX_RATE | tax_rate is less than 0 or greater than or equal to 1 |
284
+
285
+ ## Example
286
+
287
+ \`\`\`python
288
+ total = calc_order_total(items, tax_rate=Decimal("0.10")) # => 1100
289
+ \`\`\`
290
+
291
+ ## Tests
292
+
293
+ - [tests/services/test_order.py](https://github.com/example-org/shop-api/blob/main/tests/services/test_order.py)
294
+ ```
295
+
296
+ As with hand-written guides, this kind of reference page should also be prepared in both ja and en. When the implementation changes, use the `source` key as the anchor for finding and updating the corresponding page.
297
+
298
+ ## 7. Example CI freshness check implementation
299
+
300
+ The principle is: "regenerate it, and fail if there's a diff." Apply this to both `openapi.json` and the generated client.
301
+
302
+ ```yaml
303
+ # .github/workflows/docs-freshness.yml
304
+ name: docs-freshness
305
+ on: [pull_request]
306
+
307
+ jobs:
308
+ freshness:
309
+ runs-on: ubuntu-latest
310
+ steps:
311
+ - uses: actions/checkout@v4
312
+ - uses: actions/setup-node@v4
313
+ with: { node-version: 20, cache: npm }
314
+ - run: npm ci
315
+ # Regenerate openapi.json and check it matches what's committed
316
+ - run: npm run openapi:generate
317
+ - run: git diff --exit-code openapi.json
318
+ # Regenerate the client/types and check src/generated/ has no diff
319
+ - run: npm run codegen:types && npx orval
320
+ - run: git diff --exit-code src/generated/
321
+ ```
322
+
323
+ The same idea applies in GitLab CI — just line up "regenerate → `git diff --exit-code`" as script steps in the job.
324
+
325
+ This check catches both failure modes: (a) a PR that changed the API but forgot to update `openapi.json`, and (b) a PR that hand-edited generated output.
326
+
327
+ ## 8. Anti-patterns
328
+
329
+ | Anti-pattern | Problem | Do this instead |
330
+ | --- | --- | --- |
331
+ | Hand-writing API response types | Falls out of sync with API changes; types and reality drift apart | Generate into `src/generated/` with openapi-typescript / orval |
332
+ | Hand-editing generated output (`docs/api`, `src/generated/`) | Gets wiped out on the next regeneration, and fails the CI freshness check anyway | Edit the source of truth (decorators, TSDoc, the spec) and regenerate |
333
+ | Test links pinned to a commit SHA | Keeps pointing at old code and drifts from the current state | Use an absolute URL anchored to the default branch |
334
+ | Leaving translations behind (only updating the ja original) | English readers keep seeing stale information | Update ja and en together in the same PR for hand-written guides |
335
+ | Orphan pages missing from the sidebar | Unreachable except via search; nobody knows they exist | Always register pages in sidebars.js (either autogenerated or explicit) |
336
+
337
+ ## Related
338
+
339
+ - Source of truth for conventions: `rules/documentation/` (for repository maintainers)
340
+ - API design guidance itself: the api-design skill
341
+ - Running the implementation/documentation consistency check: `/update-docs`