From 4cca0c220ec727f264d8ae03cbc19d2b8d2092c0 Mon Sep 17 00:00:00 2001 From: mattyatea Date: Mon, 29 Jun 2026 22:58:03 +0900 Subject: [PATCH] chore: remove local agent harness files --- .agents/skills/add-api-endpoint/SKILL.md | 253 ------------------ .agents/skills/add-i18n-key/SKILL.md | 117 -------- .agents/skills/add-mk-component/SKILL.md | 174 ------------ .agents/skills/context-budget/SKILL.md | 148 ---------- .agents/skills/create-migration/SKILL.md | 156 ----------- .../source-command-harness-audit/SKILL.md | 152 ----------- .../source-command-quality-gate/SKILL.md | 128 --------- .codex/agents/misskey-api-reviewer.toml | 164 ------------ .codex/agents/vue-component-reviewer.toml | 173 ------------ .serena/.gitignore | 2 - .serena/project.yml | 133 --------- 11 files changed, 1600 deletions(-) delete mode 100644 .agents/skills/add-api-endpoint/SKILL.md delete mode 100644 .agents/skills/add-i18n-key/SKILL.md delete mode 100644 .agents/skills/add-mk-component/SKILL.md delete mode 100644 .agents/skills/context-budget/SKILL.md delete mode 100644 .agents/skills/create-migration/SKILL.md delete mode 100644 .agents/skills/source-command-harness-audit/SKILL.md delete mode 100644 .agents/skills/source-command-quality-gate/SKILL.md delete mode 100644 .codex/agents/misskey-api-reviewer.toml delete mode 100644 .codex/agents/vue-component-reviewer.toml delete mode 100644 .serena/.gitignore delete mode 100644 .serena/project.yml diff --git a/.agents/skills/add-api-endpoint/SKILL.md b/.agents/skills/add-api-endpoint/SKILL.md deleted file mode 100644 index 7fa1d8eeea..0000000000 --- a/.agents/skills/add-api-endpoint/SKILL.md +++ /dev/null @@ -1,253 +0,0 @@ ---- -name: add-api-endpoint -description: Misskey の REST API エンドポイント (/api//) を NestJS DI + meta/paramDef 規約で追加する。バックエンドに新しい API ルートを足す時に必ず使う。endpoint-list.ts への手動登録、e2e テスト、misskey-js 再生成、CHANGELOG までの一連の手順を含む。 ---- - -# Misskey API エンドポイント追加スキル - -`packages/backend/src/server/api/endpoints//.ts` に新規エンドポイントを追加するためのワークフロー。**手順 4 (endpoint-list.ts 登録) を忘れると 404 になる** 点に最大の注意を払う。 - -## 最重要事実 (見落とすと壊れる) - -1. エンドポイントは **glob 自動収集されない**。[packages/backend/src/server/api/endpoint-list.ts](../../../packages/backend/src/server/api/endpoint-list.ts) への 1 行追加が必須。 -2. `meta` / `paramDef` を変えたら **misskey-js の再生成が必須**。`pnpm build-misskey-js-with-types` を忘れると CI の `check-misskey-js-autogen` で必ず落ちる。 -3. `meta.errors` の各 `id` は **UUID**。重複させない (既存全 UUID と衝突確認)。 - -## ステップ 1: ファイル配置と SPDX - -`packages/backend/src/server/api/endpoints//.ts` に新規作成する。`` は機能領域 (例: `notes`, `users`, `admin/announcements`)。 - -冒頭に SPDX ヘッダーを必ず付ける: - -```ts -/* - * SPDX-FileCopyrightText: syuilo and misskey-project - * SPDX-License-Identifier: AGPL-3.0-only - */ -``` - -## ステップ 2: 最小テンプレート (シンプル read 系) - -[endpoints/ping.ts](../../../packages/backend/src/server/api/endpoints/ping.ts) をベースに書く。認証不要・パラメータなし・小さなレスポンスの例: - -```ts -/* - * SPDX-FileCopyrightText: syuilo and misskey-project - * SPDX-License-Identifier: AGPL-3.0-only - */ - -import { Injectable } from '@nestjs/common'; -import { Endpoint } from '@/server/api/endpoint-base.js'; - -export const meta = { - tags: [''], - requireCredential: false, - - res: { - type: 'object', - optional: false, nullable: false, - properties: { - // ... - }, - }, -} as const; - -export const paramDef = { - type: 'object', - properties: {}, - required: [], -} as const; - -@Injectable() -export default class extends Endpoint { // eslint-disable-line import/no-default-export - constructor( - ) { - super(meta, paramDef, async (ps, me) => { - // 実装 - }); - } -} -``` - -## ステップ 3: 認証付き / DI / errors を含むテンプレート - -[endpoints/notes/create.ts](../../../packages/backend/src/server/api/endpoints/notes/create.ts) を参照する。要点: - -```ts -import { Inject, Injectable } from '@nestjs/common'; -import { Endpoint } from '@/server/api/endpoint-base.js'; -import { ApiError } from '@/server/api/error.js'; -import { DI } from '@/di-symbols.js'; -// import ms from 'ms'; // limit.duration に ms('1hour') 等を渡すとき (default import) - -export const meta = { - tags: ['notes'], - requireCredential: true, // 認証必須なら true - prohibitMoved: false, // moved user を拒否するか - kind: 'write:notes', // OAuth scope (requireCredential 時に必須) - limit: { - duration: 3600000, // ms('1hour') - max: 300, - }, - errors: { - noSuchNote: { - message: 'No such note.', - code: 'NO_SUCH_NOTE', - id: 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx', // ★ UUID v4 を必ず生成 (`x`=hex, `y`=8/9/a/b)。下の「UUID 生成」を参照 - }, - }, - res: { - type: 'object', - optional: false, nullable: false, - ref: 'Note', // packed entity に揃える場合 - }, -} as const; - -export const paramDef = { - type: 'object', - properties: { - noteId: { type: 'string', format: 'misskey:id' }, - }, - required: ['noteId'], -} as const; - -@Injectable() -export default class extends Endpoint { // eslint-disable-line import/no-default-export - constructor( - @Inject(DI.notesRepository) - private notesRepository: NotesRepository, - ) { - super(meta, paramDef, async (ps, me) => { - const note = await this.notesRepository.findOneBy({ id: ps.noteId }); - if (note == null) throw new ApiError(meta.errors.noSuchNote); - // 実装 - }); - } -} -``` - -### meta フィールド早見表 - -| フィールド | 用途 | -|---|---| -| `tags` | OpenAPI タグ (機能領域) | -| `requireCredential` | 認証必須か | -| `requireModerator` / `requireAdmin` | 権限制限 | -| `prohibitMoved` | アカウント移行済ユーザーを拒否 | -| `kind` | OAuth scope (`read:notes` / `write:notes` 等)。`requireCredential: true` 時必須 | -| `limit` | レート制限 (`{ duration, max, key?, minInterval? }`) | -| `errors` | エラー定義。各要素に `message` / `code` / `id` (UUID v4) 必須 | -| `res` | JSON Schema or `ref: ''` (packed entity 参照) | -| `requireFile` | ファイルアップロード必須 | -| `secure` | secure cookie 必要 | -| `allowGet` | GET メソッド許可 | -| `cacheSec` | レスポンスキャッシュ秒数 | -| `description` | OpenAPI 説明 | - -詳細は [endpoints.ts](../../../packages/backend/src/server/api/endpoints.ts) の型定義 (lines 11-125) を参照。 - -### paramDef の特殊フォーマット - -JSON Schema (AJV) ベースだが、Misskey 拡張を使える: - -- `format: 'misskey:id'` — ID 文字列バリデーション -- `allOf` / `anyOf` / `oneOf` — 複合条件 -- `default` — デフォルト値 - -詳細は [endpoint-base.ts](../../../packages/backend/src/server/api/endpoint-base.ts) を参照。 - -### エラー throw - -**「公開 API エラーとして API クライアントに返したいもの」は必ず `throw new ApiError(meta.errors.)` を使う**。`meta.errors` に列挙した上で `ApiError` でラップしないと、misskey-js 側の型情報に出ず、レスポンスも 500 になる。第 2 引数で追加情報を渡せる: - -```ts -throw new ApiError(meta.errors.invalidParam, { reason: 'too short' }); -``` - -一方で、**想定外の例外 (DB 不整合 / 下層サービスの bug など) を握り潰すために `try/catch` で `ApiError` に変換するのは避ける**。既存 endpoint も「期待される業務エラーは `ApiError` に変換し、それ以外は `throw err;` で再 throw する」という二段構えになっている。`packages/backend/src/server/api/endpoints/notes/create.ts` の `catch` 節 (末尾の `throw err;`) を参照。生の `throw` を全面禁止すると未知例外も 200 で潰れて debug が困難になるので、このバランスを保つ。 - -詳細は [error.ts](../../../packages/backend/src/server/api/error.ts) の `ApiError` クラスを参照。 - -### UUID 生成 - -```bash -node -e "console.log(crypto.randomUUID())" -``` - -その UUID が他のエンドポイントの `id` と衝突していないか必ず確認: - -```bash -grep -r "id: '<生成した UUID>'" packages/backend/src/server/api/endpoints/ -``` - -## ステップ 4: ★必須 — endpoint-list.ts に登録 - -[packages/backend/src/server/api/endpoint-list.ts](../../../packages/backend/src/server/api/endpoint-list.ts) の同カテゴリ末尾に 1 行追加する(既存の並びを崩さない): - -```ts -export * as '/' from './endpoints//.js'; -``` - -ファイル冒頭のコメント (`When you add new endpoint, you should add it to this file.`) の通り、このリストが API ルーティングの単一の真実。**忘れると 404**。 - -`EndpointsModule.ts` がこのファイルの全エクスポートを `Object.entries()` で反復し、NestJS provider (`provide: 'ep:'`) を生成する。 - -## ステップ 5: e2e テスト追加 - -[packages/backend/test/e2e/endpoints.ts](../../../packages/backend/test/e2e/endpoints.ts) に対応する `describe` / `test` を追加する。`api()` ヘルパーで叩く: - -```ts -describe('/', () => { - test('正常系', async () => { - const res = await api('/', { /* params */ }, alice); - assert.strictEqual(res.status, 200); - }); -}); -``` - -実行: `pnpm --filter backend test:e2e` - -## ステップ 6: misskey-js 再生成 (★必須) - -`meta` / `paramDef` / `res` を変えたら必ず実行する: - -```bash -pnpm build-misskey-js-with-types -``` - -これで以下が更新される: - -- `packages/backend/built/api.json` (OpenAPI spec) -- `packages/misskey-js/generator/api.json` -- `packages/misskey-js/src/autogen/*.ts` (TypeScript 型) - -PR に `packages/misskey-js/src/autogen/` 配下の差分が含まれていないと、CI の `check-misskey-js-autogen` で落ちる。 - -## ステップ 7: Lint と typecheck - -```bash -pnpm --filter backend lint -``` - -(typecheck = `tsgo --noEmit` / ESLint = `eslint`) - -## ステップ 8: CHANGELOG - -ユーザー影響がある (新機能 / 既存挙動変更) なら、`CHANGELOG.md` の `## Unreleased` → `### Server` に 1 行追加する ([AGENTS.md §CHANGELOG](../../../AGENTS.md#changelog) 参照): - -``` -- Feat: /api// を追加 -``` - -純粋なリファクタや内部用なら不要。 - -## 参照ファイル - -- [endpoints.ts (meta/paramDef 型定義)](../../../packages/backend/src/server/api/endpoints.ts) -- [endpoint-base.ts (Endpoint 基底クラス)](../../../packages/backend/src/server/api/endpoint-base.ts) -- [endpoint-list.ts (★ ここに登録)](../../../packages/backend/src/server/api/endpoint-list.ts) -- [error.ts (ApiError)](../../../packages/backend/src/server/api/error.ts) -- [endpoints/ping.ts (最小例)](../../../packages/backend/src/server/api/endpoints/ping.ts) -- [endpoints/notes/create.ts (DI + errors の典型)](../../../packages/backend/src/server/api/endpoints/notes/create.ts) -- [test/e2e/endpoints.ts (テスト例)](../../../packages/backend/test/e2e/endpoints.ts) -- [scripts/generate_api_json.js (misskey-js 生成元)](../../../packages/backend/scripts/generate_api_json.js) diff --git a/.agents/skills/add-i18n-key/SKILL.md b/.agents/skills/add-i18n-key/SKILL.md deleted file mode 100644 index 899c61826d..0000000000 --- a/.agents/skills/add-i18n-key/SKILL.md +++ /dev/null @@ -1,117 +0,0 @@ ---- -name: add-i18n-key -description: Misskey の i18n キーを追加・修正する。locales/ja-JP.yml のみ編集可能で、他言語ファイル (en-US.yml 等 39 言語) は Crowdin の自動配信先のため絶対に触らない。型は packages/i18n が ja-JP.yml から自動再生成する。frontend からは i18n.ts. または i18n.tsx.(...) で参照する。 ---- - -# Misskey i18n キー追加スキル - -UI 文言の追加・変更を行う際の規約。**手動編集して良いのは `locales/ja-JP.yml` のみ。** - -## 大前提 (絶対 NG) - -- **`locales/.yml` (ja-JP.yml 以外) の編集は禁止**。これらは Crowdin の自動配信先で、手動編集すると次の同期で上書き喪失する ([locales/README.md](../../../locales/README.md), [crowdin.yml](../../../crowdin.yml))。 -- 文字列リテラルを SFC に直書きしない (`こんにちは` 等)。必ず `i18n.ts.` を経由する。 -- 既存キーの破壊的リネームは Crowdin 翻訳資産も道連れになるので慎重に。追加・改名併用 (新キー追加 → 移行 → 旧キー削除) を検討する。 - -## ステップ 1: ja-JP.yml にキーを追加 - -[locales/ja-JP.yml](../../../locales/ja-JP.yml) を編集する。YAML の階層構造を維持し、関連するセクションに配置する: - -```yaml -# トップレベル単純キー -save: "保存" - -# ネストしたカテゴリ (アンダースコア接頭辞は内部カテゴリ) -_settings: - general: "全般" - appearance: "外観" - -# パラメータ付き (単純なプレースホルダ置換) -# ICU MessageFormat の plural / select / number / date などは非対応 -# 使えるのは `{name}` のような単純な置換のみ -greeting: "こんにちは、{name}さん" -``` - -### 命名のお作法 - -- 単純キー: lowerCamelCase (例: `saveChanges`, `confirmDelete`)。 -- カテゴリ: アンダースコア接頭辞 (例: `_settings`, `_abuseUserReport`)。 -- 既存セクション内に置く場合はアルファベット順を維持する (新セクション全体を末尾に追加するのは可)。 - -## ステップ 2: 型定義の自動再生成 - -`packages/i18n/build.ts` が `ja-JP.yml` を解析し、TypeScript インターフェースを [packages/i18n/src/autogen/locale.ts](../../../packages/i18n/src/autogen/locale.ts) に出力する。 - -### 自動 (推奨) - -`pnpm dev` 実行中なら、`packages/i18n` の watch スクリプトが yml の変更を検知して自動再生成する。 - -### 手動 - -```bash -pnpm --filter i18n generate -``` - -実体は `tsx scripts/generateLocaleInterface.ts`。 - -### 失敗パターン - -これを実行せずに frontend 側で `i18n.ts.` を参照すると、`Locale` インターフェースに追加されていないため、typecheck で「Property '' does not exist on type 'Locale'」というエラーになる。`pnpm --filter frontend lint` で発覚する。 - -## ステップ 3: frontend での参照 - -```ts -import { i18n } from '@/i18n.js'; -``` - -| 用途 | 書き方 | -|---|---| -| 単純文字列 | `i18n.ts.save` | -| ネスト | `i18n.ts._settings.general` | -| パラメータ付き | `i18n.tsx.greeting({ name: userName })` | -| Vue テンプレート内 | `{{ i18n.ts.save }}` / `{{ i18n.tsx.greeting({ name }) }}` | - -`i18n.ts` は型付き文字列、`i18n.tsx` は MessageFormat 関数。 - -## ステップ 4: 検証 - -```bash -# i18n パッケージの型再生成 + typecheck -pnpm --filter i18n lint - -# frontend で新キー参照箇所の型チェック -pnpm --filter frontend lint -``` - -## 例: 「ノートを削除しますか?」確認ダイアログを追加する - -1. `locales/ja-JP.yml`: - ```yaml - _notes: - deleteConfirm: "このノートを削除しますか?" - ``` -2. `pnpm --filter i18n generate` (または `pnpm dev` で watch 中) -3. SFC: - ```vue - - ``` - -## 参照ファイル - -- [locales/README.md (★ 編集ポリシー根拠)](../../../locales/README.md) -- [locales/ja-JP.yml](../../../locales/ja-JP.yml) -- [packages/i18n/build.ts](../../../packages/i18n/build.ts) -- [packages/i18n/src/autogen/locale.ts (生成物)](../../../packages/i18n/src/autogen/locale.ts) -- [packages/frontend/src/i18n.ts](../../../packages/frontend/src/i18n.ts) diff --git a/.agents/skills/add-mk-component/SKILL.md b/.agents/skills/add-mk-component/SKILL.md deleted file mode 100644 index fd35c5dd3b..0000000000 --- a/.agents/skills/add-mk-component/SKILL.md +++ /dev/null @@ -1,174 +0,0 @@ ---- -name: add-mk-component -description: Misskey フロントエンドの新規 Vue 3 コンポーネントを追加する。Mk* 命名 / SPDX (HTML コメント) / - - -``` - -### 規約ポイント - -| 項目 | 規約 | -|---|---| -| ` -``` - -### `os` の主なヘルパー (詳細は [os.ts](../../../packages/frontend/src/os.ts)) - -| 関数 | 用途 | -|---|---| -| `os.alert({ type, title?, text })` | 単方向アラート | -| `os.confirm({ type, title, text })` | yes/no 確認 (`{ canceled }` を返す) | -| `os.toast(message)` | 一時通知 | -| `os.popup(component, props, handlers)` | 任意コンポーネントの非同期ポップアップ | -| `os.popupMenu(items, anchor?)` | コンテキストメニュー | -| `os.form(title, fields)` | フォームダイアログ | -| `os.apiWithDialog(endpoint, data)` | API 呼出し + エラー時ダイアログ表示 | - -## ステップ 5: Storybook ストーリー併設 - -[MkButton.stories.impl.ts](../../../packages/frontend/src/components/MkButton.stories.impl.ts) を雛形として参考にする。`.stories.impl.ts` も `packages/frontend/src/` 配下の `.ts` ファイルなので [AGENTS.md §1 SPDX ヘッダー必須](../../../AGENTS.md#1-spdx-ヘッダー必須) の対象であり、冒頭に SPDX ヘッダーを必ず付ける (HTML コメント形式ではなく `/* */` 形式)。形式 (以下の `MkXxx` は実際のコンポーネント名に置換する): - -```ts -/* - * SPDX-FileCopyrightText: syuilo and misskey-project - * SPDX-License-Identifier: AGPL-3.0-only - */ - -/* eslint-disable @typescript-eslint/explicit-function-return-type */ -/* eslint-disable import/no-default-export */ -import type { StoryObj } from '@storybook/vue3'; -import MkXxx from './MkXxx.vue'; - -export const Default = { - render(args) { - return { - components: { MkXxx }, - setup() { - return { args }; - }, - template: 'slot content', - }; - }, - args: { - variant: 'primary', - }, - parameters: { - layout: 'centered', - }, -} satisfies StoryObj; -``` - -`Vue` SFC は default export なので、`import MkXxx from './MkXxx.vue';` のように名前付き import ではなく default import で書く。実行確認は `pnpm --filter frontend storybook-dev`。 - -## ステップ 6: Lint と typecheck - -```bash -pnpm --filter frontend lint -``` - -(typecheck = vue-tsc 等、ESLint = `@misskey-dev/eslint-plugin` 含む) - -ESLint --fix をピンポイントで: - -```bash -pnpm exec eslint --fix packages/frontend/src/components/Mk.vue -``` - -## ステップ 7: 既存コンポーネントとの整合性確認 - -- 似た用途の既存 `Mk*` コンポーネントを参考に、スタイルやプロップ命名を揃える。 -- `_button` / `_panel` / `_selectable` などの **共通 utility class** (グローバルスタイルにある) を活用できるか確認する。 -- 大きな機能なら、Storybook stories で各バリエーションを網羅する。 - -## 参照ファイル - -- [MkInfo.vue (シンプル例)](../../../packages/frontend/src/components/MkInfo.vue) -- [MkButton.vue (汎用ボタン例)](../../../packages/frontend/src/components/MkButton.vue) -- [MkInput.vue (generics + 多機能例)](../../../packages/frontend/src/components/MkInput.vue) -- [MkButton.stories.impl.ts (Storybook 雛形)](../../../packages/frontend/src/components/MkButton.stories.impl.ts) -- [packages/frontend/src/os.ts](../../../packages/frontend/src/os.ts) -- [packages/frontend/src/i18n.ts](../../../packages/frontend/src/i18n.ts) diff --git a/.agents/skills/context-budget/SKILL.md b/.agents/skills/context-budget/SKILL.md deleted file mode 100644 index 97bc3ea444..0000000000 --- a/.agents/skills/context-budget/SKILL.md +++ /dev/null @@ -1,148 +0,0 @@ ---- -name: context-budget -description: Codex セッションのコンテキスト窓消費を agents/skills/MCP/rules/AGENTS.md ごとに見える化し、肥大化と冗長コンポーネントを検出して節約候補を提示する。"コンテキスト消費を見せて"、"context budget"、"context audit"、"トークン内訳"、"これ以上 MCP 入る?" 等の発話で起動する。 ---- - - - -# Context Budget - -セッション内に読み込まれるコンポーネント (agents / skills / rules / MCP servers / AGENTS.md) の token overhead を分析し、空き context を回復する具体策を提示する。 - -## 使う場面 - -- セッションが重い・出力品質が落ちてきた感覚がある -- 直近で skills / agents / MCP server を多数追加した -- 残りの context headroom を知りたい -- 追加コンポーネントを入れる前に空きを確認したい -- 「context-budget」「token 内訳」等のキーワードでユーザーが明示的に要請した時 (Misskey リポジトリにはこの名前のスラッシュコマンドは登録していない — 本 skill は名前 / description マッチで auto-invoke される想定。実装済の slash command 一覧は [.Codex/commands/](../../commands/) を参照) - -## 仕組み - -### Phase 1: Inventory - -各コンポーネントを走査して token を推定する。 - -**Agents** (`.Codex/agents/*.md`) -- 行数とトークン数 (`words × 1.3`) を計算 -- frontmatter `description` の長さを抽出 -- フラグ: 200 行超 (重い)、description 30 word 超 (frontmatter 肥大) - -**Skills** (`.Codex/skills/*/SKILL.md`) -- SKILL.md ごとに token を計算 -- フラグ: 400 行超 -- `.agents/skills/` 等の重複コピーは除外 - -**Rules** (リポジトリルートの `AGENTS.md` + `.Codex/` から `@-import` されるファイル) -- ファイル単位で token 計算 -- フラグ: 100 行超 -- 同一言語モジュール内の内容重複を検出 - -**MCP Servers** (`.mcp.json` または有効 MCP 設定) -- server 数と総 tool 数 -- schema overhead をツールあたり ~500 token で見積もる -- フラグ: 20 tool 超のサーバー、`gh` / `git` / `npm` 等の CLI を単純ラップしただけのサーバー - -**AGENTS.md** (project + user-level) -- ファイルごとに token を計算 -- フラグ: 合計 300 行超 - -### Phase 2: Classify - -| バケット | 判定基準 | 行動 | -|--------------------|-------------------------------------------------------------|-----------------------------------| -| **Always needed** | AGENTS.md から参照されている / 有効コマンドの裏 / 現プロジェクトと一致 | 維持 | -| **Sometimes needed** | ドメイン依存 (例: 言語パターン)、AGENTS.md 参照なし | オンデマンド有効化を検討 | -| **Rarely needed** | コマンド参照なし、内容重複、明確な用途なし | 削除または lazy-load | - -### Phase 3: Detect Issues - -- **Bloated agent description** — frontmatter description が 30 word 超だと、Task ツール起動のたびに毎回ロードされる -- **Heavy agents** — 200 行超は Task ツールの context を毎回膨らませる -- **Redundant components** — agent ロジックを重複する skill、AGENTS.md と重複する rule -- **MCP over-subscription** — 10 server 超、または CLI 代用可能なサーバー -- **AGENTS.md bloat** — 冗長説明、古いセクション、rule に移すべき指示 - -### Phase 4: Report - -``` -Context Budget Report -═══════════════════════════════════════ - -Total estimated overhead: ~XX,XXX tokens -Context model: <現在モデル名> (K window) ← 例: Codex Opus 4.7 (1M), Codex Sonnet (200K) -Effective available context: ~XXX,XXX tokens (XX%) - -Component Breakdown: -┌─────────────────┬────────┬───────────┐ -│ Component │ Count │ Tokens │ -├─────────────────┼────────┼───────────┤ -│ Agents │ N │ ~X,XXX │ -│ Skills │ N │ ~X,XXX │ -│ Rules │ N │ ~X,XXX │ -│ MCP tools │ N │ ~XX,XXX │ -│ AGENTS.md │ N │ ~X,XXX │ -└─────────────────┴────────┴───────────┘ - -WARNING: Issues Found (N): -[token 節約量の降順] - -Top 3 Optimizations: -1. [action] → save ~X,XXX tokens -2. [action] → save ~X,XXX tokens -3. [action] → save ~X,XXX tokens - -Potential savings: ~XX,XXX tokens (XX% of current overhead) -``` - -verbose mode ではさらにファイルごとの token 内訳、最重ファイルの行単位ブレークダウン、重複行の対比、MCP tool 一覧 + tool ごとの schema サイズ推定を出す。 - -## 例 - -**基本監査** -``` -User: コンテキスト消費を見せて -Skill: 16 agents (12,400 tokens), 28 skills (6,200), 87 MCP tools (43,500), 2 AGENTS.md (1,200) - Flags: 重い agent 3 個、CLI 代用可能な MCP 3 個 - Top saving: MCP 3 個削除 → -27,500 tokens (overhead の 47% 削減) -``` - -**Verbose** -``` -User: トークン内訳をファイル単位で -Skill: 上記レポートに加えて、planner.md (213 lines, 1,840 tokens) のような - per-file 行内訳、MCP tool ごとのサイズ、rule の重複行を side-by-side で表示 -``` - -**追加前チェック** -``` -User: MCP server を 5 個追加したいが、空きある? -Skill: 現状 33% → 5 server (≈ 50 tools) 追加で +25,000 tokens → 45% に到達 - 推奨: CLI 代用可能な server 2 個を先に外して 40% 以下を維持 -``` - -## ベストプラクティス - -- **トークン推定**: prose は `words × 1.3`、code 主体は `chars / 4` -- **MCP は最大のレバー**: tool あたり ~500 token、30-tool server ひとつで全 skill より大きい -- **agent description は常時ロード**: 呼ばれない agent でも description は毎 Task 投入 -- **verbose は debug 用**: 普段は使わない -- **変更後は監査**: agent/skill/MCP 追加直後に走らせて creep を早期発見 - -## Misskey 固有メモ - -- Misskey は MCP server をプロジェクトで明示登録していないため (`.mcp.json` 不在)、現状 overhead の支配項は AGENTS.md と公式プラグイン群の skills / agents description である。 -- ECC プラグインがユーザースコープで `installed_plugins.json` に存在するため、プロジェクトで `enabledPlugins` に追加していなくても system reminder に 200+ skill が現れる。これらは description が短いので個別 overhead は小さいが、合計値の確認に本 skill を使う。 diff --git a/.agents/skills/create-migration/SKILL.md b/.agents/skills/create-migration/SKILL.md deleted file mode 100644 index 64f76cb9d7..0000000000 --- a/.agents/skills/create-migration/SKILL.md +++ /dev/null @@ -1,156 +0,0 @@ ---- -name: create-migration -description: Misskey の TypeORM マイグレーションを公式 CLI (migration:generate / migration:create) で正しく生成し、SPDX ヘッダー付与・up/down 整合・check-migrations 確認まで誘導する。エンティティのスキーマ変更を含むあらゆる DB 変更、または手書き SQL によるデータ移行が必要な時に使用する。 ---- - -# Misskey マイグレーション作成スキル - -`packages/backend/migration/` に新規 TypeORM マイグレーションを追加するためのワークフロー。 - -## 大前提 (絶対 NG) - -- **既にマージ済み (develop / master) のマイグレーションファイルを編集しない** ([AGENTS.md §3](../../../AGENTS.md#3-マージ済み-migration-を絶対に編集しない))。本番履歴の改変は深刻なデータ不整合を引き起こす。スキーマ変更は **常に新しいタイムスタンプで新規ファイル** を作る。 -- ファイル名のタイムスタンプ部分を後から書き換えない (順序が壊れる)。 - -> 作り方は AGENTS.md §3 の「`Date.now()` で UNIX ms を取得 → `{ms}-{PascalName}.js` を手書き」が最低ライン。エンティティ差分から自動生成したい (= TypeORM の `migration:generate` を使う) 場合は本 skill の手順に従う。**どちらでも構わない**が、エンティティ変更を伴う時は CLI 経由のほうが取り漏れが減るので推奨。 - -## ステップ 1: どちらの方式を使うか決める - -| 状況 | 方式 | -|---|---| -| エンティティ (`packages/backend/src/models/*.ts`) を `@Column` / `@Index` / `@Entity` 等で先に変更し、差分から自動生成したい | `typeorm migration:generate` (本 skill の手順) | -| 手書き SQL / データ移行 / `CREATE INDEX CONCURRENTLY` など、エンティティ差分では表現できない変更 | `typeorm migration:create` で空雛形を作るか、`migrate-new` command で手書き雛形を作る | -| 列追加 1 本のような小規模変更で、既存ファイルをコピーした方が速い | AGENTS.md §3 の手順 (`Date.now()` + 手書き) でよい | - -迷ったら **まずエンティティを変更 → `migration:generate`** が原則。既存 342 ファイルのほぼすべてが `queryRunner.query(\`SQL...\`)` の raw SQL なので、CLI 出力でも手書きでもスタイルは揃う。 - -## ステップ 2: CLI 実行 - -ルートディレクトリから以下を実行する。`` は変更内容を表す PascalCase (例: `AddBirthdayIndex`, `AddCategoryToAvatarDecorations`)。 - -### 2-A. エンティティ差分から生成 - -[CONTRIBUTING.md §Migration作成方法](../../../CONTRIBUTING.md#migration作成方法) に記載の基本形: - -```bash -# packages/backend ディレクトリで実行する場合 (CONTRIBUTING.md 記載形式) -pnpm dlx typeorm migration:generate -d ormconfig.js -o --esm -``` - -**リポジトリルートから実行する場合** (AI が使う推奨形式。`pnpm --filter backend exec` を使うと backend の TypeORM バージョンと一致するため確実): - -```bash -pnpm --filter backend exec typeorm migration:generate -d ormconfig.js -o --esm migration/ -``` - -> **`--esm` について**: `-o` / `--outputJs` は「TS ではなく JS を出力する」オプション、`--esm` は「ESM 形式 (`export class ...`) で出力する」オプション。Misskey の既存 migration はすべて ESM JS であるため **両方が必須**。`--esm` を省略すると CommonJS 形式の JS が生成されスタイルが揃わない。 - -事前準備: - -- `pnpm build-pre` を実行して `built/meta.json` を生成する (`loadConfig()` が `built/meta.json` を必須とするため。`pnpm build` 済みであれば不要)。 -- `.config/default.yml` が存在すること (なければ `.config/example.yml` を参考に作成する)。 -- `pnpm --filter backend compile-config` を実行して `built/.config.json` を生成する (`ormconfig.js` が `loadConfig()` 経由で必須とする。未実行だと "Compiled configuration file not found." エラーになる)。 -- `pnpm --filter backend build` でエンティティを最新ビルド (CLI は `built/` を読む)。 -- ローカル DB を起動する (`docker compose -f compose.local-db.yml up -d`)。 - -### 2-B. 空の手書きマイグレーション - -```bash -pnpm --filter backend exec typeorm migration:create -o --esm migration/ -``` - -ローカル DB の起動とビルドは不要。空の `up` / `down` だけが生成される。 - -> `-o --esm` を **必ず付ける**。これが無いと `-.ts` (CommonJS / TS 出力) が生成されるが、Misskey の `ormconfig.js` は `migration/*.js` だけを読み、既存の他 migration も全て `export class ... { async up(queryRunner) {...} }` の ESM JS 形式なので、後で手作業で `.ts → .js` リネーム + `import { MigrationInterface }` 削除 + `class ... implements MigrationInterface` 削除をしないと走らない。`-o --esm` を付ければそのまま `.js` ESM で出るので、後処理は SPDX ヘッダー付与 (ステップ 3) だけで済む。 - -## ステップ 3: SPDX ヘッダー付与 - -CLI 出力には SPDX ヘッダーが含まれない。**必ず冒頭に追加する** (CI の `spdx` ジョブが失敗するため)。 - -```js -/* - * SPDX-FileCopyrightText: syuilo and misskey-project - * SPDX-License-Identifier: AGPL-3.0-only - */ -``` - -## ステップ 4: up / down の整合確認 - -- `up()` の各ステートメントに対し、`down()` で完全に巻き戻せること。 -- 列追加 (`ADD COLUMN`) ↔ 列削除 (`DROP COLUMN`)、テーブル作成 ↔ テーブル削除、 - FK 追加 ↔ FK 削除、インデックス作成 ↔ インデックス削除 を必ずペアで書く。 -- `down()` を空のまま残さない。本番ロールバック時に詰む。 - -### インデックス追加時の注意 (CREATE INDEX CONCURRENTLY) - -大規模テーブルへの `CREATE INDEX` は本番で長時間ロックする恐れがある。`CONCURRENTLY` で発行するときは **migration 側にも対応が必要**: PostgreSQL は `CREATE INDEX CONCURRENTLY` を transaction 内で実行できないため、migration class に以下を仕込んで TypeORM に「この migration は transaction を張らない」と指示する。 - -参照実装: [packages/backend/migration/1745378064470-composite-note-index.js](../../../packages/backend/migration/1745378064470-composite-note-index.js)。 - -```js -const isConcurrentIndexMigrationEnabled = process.env.MISSKEY_MIGRATION_CREATE_INDEX_CONCURRENTLY === '1'; - -export class CompositeNoteIndex1745378064470 { - name = 'CompositeNoteIndex1745378064470'; - transaction = isConcurrentIndexMigrationEnabled ? false : undefined; - - async up(queryRunner) { - const concurrently = isConcurrentIndexMigrationEnabled; - if (concurrently) { - // CREATE INDEX CONCURRENTLY ... - } else { - // CREATE INDEX ... - } - } - - async down(queryRunner) { - // 同様に環境変数で分岐 - } -} -``` - -要点: - -- **`transaction = isConcurrentIndexMigrationEnabled ? false : undefined;`** が必須。これがないと `CREATE INDEX CONCURRENTLY` が transaction 内で実行されて `ERROR: CREATE INDEX CONCURRENTLY cannot run inside a transaction block` で失敗する。 -- 環境変数 `MISSKEY_MIGRATION_CREATE_INDEX_CONCURRENTLY=1` がデフォルト OFF。OFF のときは普通の `CREATE INDEX` (transaction 内) で動く必要がある。`up`/`down` 双方を環境変数で分岐させる。 -- `ormconfig.js` の `migrationsTransactionMode` は **環境変数で切り替わる**: `MISSKEY_MIGRATION_CREATE_INDEX_CONCURRENTLY=1` のときだけ `'each'` (各 migration が個別 transaction)、未設定時は `'all'` (全 migration を 1 つの transaction でラップ) ([ormconfig.js:19](../../../packages/backend/ormconfig.js#L19))。普段は `'all'` 前提なので、CONCURRENTLY を使う migration を書く時だけこのフラグの存在を意識すれば良い。 - -### 関連エンティティとの一致 - -`migration:generate` を使った場合、エンティティ側の `@Column` / `@Entity` 修正と DB スキーマが食い違うとビルド全体がズレる。生成後に該当エンティティと SQL の対応を目視確認すること。 - -## ステップ 5: 検証 - -ルートから実行: - -```bash -# 未反映の差分が無いか (新規 migration が生成すべき DDL を取り逃していないか) -pnpm --filter backend check-migrations - -# ローカル DB に適用 -pnpm migrate - -# ロールバック (down が壊れていないか) -pnpm revert - -# 再適用 (順方向にもう一度通す) -pnpm migrate -``` - -`check-migrations` の実体は [scripts/check_migrations_clean.js](../../../packages/backend/scripts/check_migrations_clean.js)。TypeORM の `dataSource.driver.createSchemaBuilder().log()` で pending DDL を取得し、`upQueries` / `downQueries` のいずれかが残っていれば非ゼロ終了する。**順序検査ではなく**「エンティティと migration が同期しているか」の検査。 - -## ステップ 6: 既存ファイル参照テンプレ - -新規ファイルを書くときは、変更パターンが近い既存ファイルを **必ずひとつ開いて並べて書く**。スタイルが激しくズレた PR は差し戻されやすい。 - -| パターン | 参照ファイル | -|---|---| -| インデックス追加 + 関数定義 | [packages/backend/migration/1767169026317-birthday-index.js](../../../packages/backend/migration/1767169026317-birthday-index.js) | -| 列追加のみ | [packages/backend/migration/1766652173085-add-category-to-avatar-decorations.js](../../../packages/backend/migration/1766652173085-add-category-to-avatar-decorations.js) | -| テーブル新規作成 + FK | [packages/backend/migration/1761569941833-add-channel-muting.js](../../../packages/backend/migration/1761569941833-add-channel-muting.js) | - -クラス命名規則は **PascalCase 名 + 13 桁タイムスタンプ** (例: `class BirthdayIndex1767169026317`)。`name` プロパティもクラス名と同一文字列にする。 - -## ステップ 7: CHANGELOG (ユーザー影響がある場合) - -スキーマ変更がユーザーに見える挙動を生む場合のみ、`CHANGELOG.md` の `## Unreleased` → `### Server` または `### General` に 1 行追加する ([AGENTS.md §CHANGELOG](../../../AGENTS.md#changelog) 参照)。内部リファクタや純粋なインデックス追加は不要。 diff --git a/.agents/skills/source-command-harness-audit/SKILL.md b/.agents/skills/source-command-harness-audit/SKILL.md deleted file mode 100644 index d96c286ee1..0000000000 --- a/.agents/skills/source-command-harness-audit/SKILL.md +++ /dev/null @@ -1,152 +0,0 @@ ---- -name: "source-command-harness-audit" -description: "Misskey の .Codex/ ハーネス (skills/agents/commands) を 7 カテゴリで採点する確定的な監査。" ---- - -# source-command-harness-audit - -Use this skill when the user asks to run the migrated source command `harness-audit`. - -## Command Template - - - -# /harness-audit — Misskey ハーネス監査 - -Misskey リポジトリの `.Codex/` 構成を 7 カテゴリで採点し、改善優先度を提示する。 - -## Usage - -`/harness-audit [scope]` - -- `scope` (任意): `repo` (default) / `skills` / `commands` / `agents` - -## 評価カテゴリ (各 0-10) - -| # | カテゴリ | 評価軸 | -| --- | --- | --- | -| 1 | Tool Coverage | skill / agent / command の数、欠けているワークフロー段、重複なし | -| 2 | Context Efficiency | frontmatter description の冗長度、SKILL.md の長さ分布、重複情報、AGENTS.md の肥大化 | -| 3 | Quality Gates | Stop / PreToolUse / PostToolUse hook の整備、`/quality-gate` 等の完了前ゲートの有無、自動 lint/typecheck | -| 4 | Memory Persistence | docs/* の同期状態を評価。プロジェクト側 `.Codex/memory/` は未採用方針 (auto-memory はユーザーホーム側で自動運用) のため、ここを採点起点にせず既定 5/10 から開始する | -| 5 | Eval Coverage | testing.md の網羅、Misskey 固有の e2e/fed/Storybook/Cypress 適用ガイド | -| 6 | Security Guardrails | SPDX 規約適用、migration 不変性ルール、ja-JP.yml 限定編集ルール、secrets 検出 | -| 7 | Cost Efficiency | enabledPlugins の重複・過剰、context-budget の整備、MCP 過剰登録なし | - -## Misskey 固有の確認項目 (採点根拠コマンド) - -採点時に以下を実コマンドで確認する。各項目の **属するカテゴリ** は項目内に明記する (#1-#3 は Security Guardrails、#4 は Tool Coverage、#5 は Quality Gates): - -```bash -# 1. [Security Guardrails] SPDX 適用率 (新規ファイル想定の汎用チェック) -# - node_modules を prune で除外 -# - packages/misskey-js は MIT サブパッケージなので AGPL ヘッダーを持たない (AGENTS.md §1) → 除外 -# - built/ なども除外 -# 候補にはなお *.config.{ts,js} / *eslint* / *.d.ts のような CI 上 SPDX 対象外 -# (.github/workflows/check-spdx-license-id.yml の exclude 参照) も混ざるため、 -# 上位に出たファイルが「新規追加した実コード」かどうかは目視判定する。 -find packages \ - \( -type d \( -name node_modules -o -name built -o -name dist -o -path 'packages/misskey-js' \) -prune \) \ - -o -type f \( -name '*.ts' -o -name '*.js' -o -name '*.vue' -o -name '*.scss' \) -print \ - | xargs -r grep -L 'SPDX-License-Identifier: AGPL-3.0-only' | head -20 -# → 上位に新規実コードが無ければ満点 - -# 2. [Security Guardrails] ja-JP.yml 以外の locales が直近で手動編集されていないか -# --pretty=format: でコミットヘッダ行を抑止し、ファイル名行のみを残してから grep する。 -# Crowdin の自動同期 commit でも他言語 yml は更新されるため、出力が 0 行になることは少ない。 -# 出力があった場合は、author / commit message を確認し Crowdin 由来か手動編集かを判定する: -# git log --since='30 days ago' --pretty=format:'%h %an %s' -- locales/.yml -git log --since='30 days ago' --pretty=format: --name-only -- 'locales/*.yml' \ - | grep -v '^$' | grep -v 'ja-JP.yml' | sort -u -# → 出力が無い、または全て Crowdin 由来 commit なら満点 - -# 3. [Security Guardrails] migration の pending DDL 検査 (TypeORM schema builder) -pnpm --filter backend check-migrations -# → 0 errors (= "All migrations are clean.") なら満点 - -# 4. [Tool Coverage] endpoint-list.ts 登録漏れ (新規 endpoint がリストにない場合) -# endpoints/ は再帰構造 (notes/create.ts, admin/announcements/create.ts 等) で 400+ ファイルあるため、 -# endpoint-list.ts も `export * as '/' from './endpoints//.js';` 形式で -# 1 ファイル 1 行登録される。両者の行数を「再帰 .ts 数」と「export * as 行数」で比較する。 -# e2e / 単体テストは endpoint ではないので *.test.ts を除外する。 -endpoint_files=$(find packages/backend/src/server/api/endpoints -type f -name '*.ts' ! -name '*.test.ts' | wc -l) -list_entries=$(grep -cE "^export \* as " packages/backend/src/server/api/endpoint-list.ts) -echo "endpoints (recursive): $endpoint_files / endpoint-list.ts entries: $list_entries" -# 差分が 0 なら満点。差分が出たら、登録漏れの具体特定: -comm -23 \ - <(find packages/backend/src/server/api/endpoints -type f -name '*.ts' ! -name '*.test.ts' \ - | sed -E 's|.*/endpoints/||;s|\.ts$||' | sort -u) \ - <(grep -oE "^export \* as '[^']+'" packages/backend/src/server/api/endpoint-list.ts \ - | sed -E "s/^export \* as '([^']+)'/\1/" | sort -u) -# 出力された行が登録漏れの endpoint。0 行なら満点。 - -# 5. [Quality Gates] console.log の混入 -grep -rn 'console\.\(log\|debug\)' packages/backend/src packages/frontend/src 2>/dev/null \ - | grep -v 'node_modules\|test\|.spec\.\|.test\.' | wc -l -# → 0 が理想 -``` - -## 出力契約 - -以下を返す: - -1. `overall_score` / `max_score` (repo は 70 点満点) -2. カテゴリごとのスコア + 具体的な根拠 -3. 失敗チェック項目と該当ファイルパス -4. Top 3 改善アクション -5. 次に適用を推奨する skill / 手順 - -## サンプル出力 - -```text -Harness Audit (repo): 55/70 - -Tool Coverage: 9/10 (skills 5, agents 2, commands 5 — 偏りなし) -Context Efficiency: 8/10 (description 平均 3-5 行、肥大なし) -Quality Gates: 5/10 (Stop hook 共有設定に未登録 / `/quality-gate` あり) -Memory Persistence: 5/10 (プロジェクト側 memory/ 未採用方針 = 既定値) -Eval Coverage: 7/10 (testing.md 網羅、Storybook 一部抜け) -Security Guardrails: 10/10 (SPDX 100%, locales OK, migrations clean) -Cost Efficiency: 8/10 (context-budget 導入済 / MCP 0) - -Failed Checks: -- packages/frontend/src/.../X.vue で SPDX 欠落 (Security Guardrails) -- console.log が backend に 3 件 (Quality Gates) -- 共有 Stop hook なし (Quality Gates) — 各 contributor が `.Codex/settings.local.json` で opt-in する方針なら減点しなくて良い - -Top 3 Actions: -1) [Security Guardrails] SPDX 欠落 1 ファイルを修正: - packages/frontend/src/.../X.vue -2) [Quality Gates] backend の console.log 3 件を logger に置換。 - git grep "console\.log" packages/backend/src -3) [Cost Efficiency] enabledPlugins から未使用のものを外す。 - .Codex/docs/plugins.md と照合。 - -Suggested next skills to apply: -- /quality-gate で完了前に lint + unit test を回す -- context-budget で plugin 由来の overhead を確認 -``` - -## 採点の信頼性 - -- 確定的: 同じ commit / 同じ `.Codex/` 構成なら同じスコア -- ヒューリスティクス: 「description の冗長度」のような主観項目は同一基準で機械的に判定 -- スクリプト不要: `pnpm` と `git`、`grep`/`find` 等の標準ツールのみ - -## 参考: ECC オリジナルとの差分 - -- ECC 版は `node scripts/harness-audit.js` を直叩きする運用で、ECC リポジトリ全体に閉じた採点だった。 -- Misskey 版は **Misskey の規約 (SPDX/migration/locales/endpoint-list)** を Security 採点に組み込み、`pnpm` ベースの実コマンドで根拠を取る方式に再設計。 -- 結果として ECC への依存はゼロ。 diff --git a/.agents/skills/source-command-quality-gate/SKILL.md b/.agents/skills/source-command-quality-gate/SKILL.md deleted file mode 100644 index 577e66c1d5..0000000000 --- a/.agents/skills/source-command-quality-gate/SKILL.md +++ /dev/null @@ -1,128 +0,0 @@ ---- -name: "source-command-quality-gate" -description: "Misskey の lint / typecheck / 高速テストを順に実行して品質ゲートを通すコマンド。完了前の軽量検証用。" ---- - -# source-command-quality-gate - -Use this skill when the user asks to run the migrated source command `quality-gate`. - -## Command Template - - - -# /quality-gate — Misskey 軽量品質ゲート - -`/quality-gate [scope]` - -完了前の **軽量** 品質チェック。重い E2E / 連合テスト (test:e2e / test:fed / Cypress) は CI 側で実行されるため、本コマンドには含めない。 - -## Scope - -- `repo` (default) — 全パッケージ -- `backend` — `packages/backend` のみ -- `frontend` — `packages/frontend` のみ -- `path/to/file.ts` — 単一ファイルへの ESLint --fix のみ - -## Pipeline - -### Repo scope (全部) - -各パッケージの `lint` スクリプト実体は `pnpm typecheck && pnpm eslint` ([packages/backend/package.json](../../packages/backend/package.json), [packages/frontend/package.json](../../packages/frontend/package.json)) で、ルートの `pnpm lint` は `pnpm --no-bail -r lint` (= 全パッケージで lint を `--no-bail` で実行)。**typecheck は lint に含まれている**ため、通常はこの 2 コマンドで十分: - -```bash -# 1. Lint (= typecheck + ESLint、全パッケージ。--no-bail で最初の失敗で止まらず全結果を集める) -pnpm lint - -# 2. Unit test (高速、e2e は含まない) -pnpm --filter backend test -pnpm --filter frontend test -``` - -#### 詳細を分けて見たい時のみ (optional) - -lint がまとめて失敗していて typecheck の結果だけ単独で見たい場合は、以下を個別に回す。**通常は不要** (lint の出力を読めば足りる): - -```bash -pnpm --filter backend typecheck # tsgo 単体 -pnpm --filter frontend typecheck # vue-tsc 単体 (Vue SFC の型を見るため) -``` - -### Backend scope - -`pnpm --filter backend lint` は内部で `pnpm typecheck && pnpm eslint` を実行する ([packages/backend/package.json](../../packages/backend/package.json)) ので、`lint` を回せば typecheck も終わる。軽量ゲートでは typecheck の二重実行を避けるため `lint` + `test` のみ: - -```bash -pnpm --filter backend lint -pnpm --filter backend test -``` - -`tsgo` の出力を単独で見たい時のみ optional で `pnpm --filter backend typecheck` を別途回す。 - -### Frontend scope - -`pnpm --filter frontend lint` も内部で `pnpm typecheck && pnpm eslint` を実行する ([packages/frontend/package.json](../../packages/frontend/package.json)) ため、軽量ゲートでは Backend 同様に `lint` + `test` のみ: - -```bash -pnpm --filter frontend lint -pnpm --filter frontend test -``` - -`vue-tsc` の出力を単独で見たい時のみ optional で `pnpm --filter frontend typecheck` を別途回す。 - -### Single file scope - -```bash -pnpm exec eslint --fix -``` - -## Output - -実行したフェーズの pass/fail と件数を集計する。標準パイプラインは `pnpm lint` (typecheck 内包) と unit test のみなので、デフォルトの出力は以下のようになる: - -```text -Quality Gate (repo): - -Lint: PASS (0 errors, 2 warnings) -Backend ut: PASS (412/412) -Frontend ut: PASS (87/87) - -→ 完了前の軽量チェック OK。重い e2e / 連合テストは CI 側で実行される。 -``` - -`#### 詳細を分けて見たい時のみ (optional)` で個別 typecheck (`pnpm --filter backend typecheck` / `pnpm --filter frontend typecheck`) も回した場合のみ、その結果を追加行として表示する: - -```text -Quality Gate (repo): - -Lint: PASS (0 errors, 2 warnings) -Backend tc: PASS (0 errors) # optional 実行時のみ -Frontend tc: PASS (0 errors) # optional 実行時のみ -Backend ut: PASS (412/412) -Frontend ut: PASS (87/87) -``` - -失敗時は最初に落ちたフェーズで停止して詳細を見せる。 - -## 関連 skill / コマンド - -- `/check-misskey-js` コマンド — API 変更時の misskey-js 再生成 -- [AGENTS.md §必須コマンド](../../AGENTS.md#必須コマンド) — pnpm コマンド一覧の正典 - -## 元 ECC 版との差分 - -- ジェネリックな言語自動判定を排除し、Misskey 固定 pipeline に。 -- formatter フェーズなし (Misskey は ESLint --fix のみ採用)。 -- e2e / federation / Cypress は重いため除外し CI 側に委譲。 diff --git a/.codex/agents/misskey-api-reviewer.toml b/.codex/agents/misskey-api-reviewer.toml deleted file mode 100644 index 932c206440..0000000000 --- a/.codex/agents/misskey-api-reviewer.toml +++ /dev/null @@ -1,164 +0,0 @@ -name = "misskey-api-reviewer" -description = "Misskey の API エンドポイント (packages/backend/src/server/api/endpoints/) の追加・変更を専門レビューする。SPDX / meta / paramDef / UUID 重複 / endpoint-list.ts 登録 / ApiError throw / misskey-js 再生成 / e2e / CHANGELOG を機械的にチェック。バックエンド API を追加・変更した PR レビューで呼び出す。" -developer_instructions = ''' -# Misskey API エンドポイントレビュアー - -Misskey バックエンド (`packages/backend`) の REST API エンドポイント追加・変更 PR を機械的にレビューする専門エージェント。規約の根拠は [.Codex/skills/add-api-endpoint/SKILL.md](../skills/add-api-endpoint/SKILL.md)。 - -## 役割 - -`packages/backend/src/server/api/endpoints/` 配下の `.ts` 変更を対象に、規約逸脱・登録漏れ・型自動生成漏れ・テスト不足を抽出する。良い点には触れず、改善が必要な箇所のみ報告する。 - -## レビュー対象の特定 - -呼び出し元から明示的にファイルが渡されたらそれを優先する。渡されなかった場合は **PR / ブランチ全体の差分** を取得する (未コミット差分のみではないことに注意)。 - -```bash -BASE=$(git merge-base origin/develop HEAD) -{ git diff --name-only "$BASE"...HEAD; git diff --name-only HEAD; git ls-files --others --exclude-standard; } \ - | sort -u \ - | grep -E '^packages/backend/src/server/api/endpoints/.*\.ts$' -``` - -`origin/develop` が無い環境では `develop` または `master` にフォールバックする。 - -加えて以下も同じ baseline で差分対象に含める: - -- `packages/backend/src/server/api/endpoint-list.ts` -- `packages/backend/test/e2e/**` (とくに `endpoints.ts` と `.ts`) -- `packages/misskey-js/src/autogen/**` -- `CHANGELOG.md` - -差分対象が空なら「レビュー対象の API エンドポイント変更なし」と短く報告して終了。 - -## チェックリスト - -### 1. SPDX ヘッダー (Critical) - -新規 `.ts` ファイル冒頭に以下があるか: - -``` -/* - * SPDX-FileCopyrightText: syuilo and misskey-project - * SPDX-License-Identifier: AGPL-3.0-only - */ -``` - -欠落すると CI の `spdx` ジョブが落ちる。 - -### 2. `meta` の必須・推奨フィールド (Major) - -[endpoints.ts の型定義](../../packages/backend/src/server/api/endpoints.ts) を真とする。 - -- `tags`: OpenAPI タグ (機能領域)。 -- `requireCredential`: 明示必須 (boolean)。 -- `kind`: OAuth scope。`requireCredential: true` のとき必須 (`read:account` / `write:notes` 等)。 -- `requireModerator` / `requireAdmin`: 権限制限が要るか。 -- `prohibitMoved`: 移行済アカウントを拒否するか (write 系で要検討)。 -- `limit`: レート制限 `{ duration, max, key?, minInterval? }`。書き込み系 / コスト高い処理で未指定なら指摘。 -- `errors`: エラー定義。各要素に `message` / `code` / `id` (UUID v4) が揃っているか。 -- `res`: JSON Schema または `ref: ''`。各プロパティに `optional` / `nullable` が **明示** されているか。 -- `requireFile` / `secure` / `allowGet` / `cacheSec` / `description`: 該当するエンドポイントで使い分けているか。 - -### 3. `meta.errors` の UUID 検証 (Critical) - -各 `errors[*].id` が: - -1. UUID v4 形式 (`xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx`) か -2. 既存エンドポイントの `id` と重複していないか - -重複検査: - -```bash -grep -rn "id: '<生成された UUID>'" packages/backend/src/server/api/endpoints/ -``` - -新規エンドポイントの全 `id` を抽出して衝突を確認する。 - -### 4. `paramDef` (Major) - -- JSON Schema 形式 (`type: 'object'`, `properties`, `required`) -- ID 文字列は `format: 'misskey:id'` -- `required` 配列で必須プロパティを明示 -- `as const` または `as const satisfies Schema` で型推論を効かせる (既存実装は前者多数。`as const` 自体が無く `Schema` 型注釈もない場合のみ指摘) - -### 5. エンドポイント実装本体 (Major) - -- `Endpoint` を継承しているか。 -- `@Injectable()` デコレータ + `export default class` 形式か (`// eslint-disable-line import/no-default-export` が必要)。 -- DI は `@Inject(DI.xxx)` 形式か。 -- **クライアントに返すべき API エラーは `throw new ApiError(meta.errors.)`** ([error.ts](../../packages/backend/src/server/api/error.ts) 参照)。`meta.errors` で定義したエラーケースを `throw new Error(...)` で投げているなら指摘する。 -- 防御的アサーション・「起きるはずがない」内部不整合・テスト用 ENV ガード等の **想定外フェイルファスト** は `throw new Error('...')` で構わない。既存実装でも `admin/reset-password.ts` などが採用しているパターン (例: `cannot reset password of root`)。`meta.errors` に対応がない `throw new Error` を一律で指摘しない。 -- 同期 `throw` は許容。非同期処理での例外伝搬を確認する。 - -### 6. ★ `endpoint-list.ts` への登録 (Critical) - -最も忘れやすい。**忘れると 404**。[endpoint-list.ts](../../packages/backend/src/server/api/endpoint-list.ts) に 1 行追加されているか: - -```ts -export * as '/' from './endpoints//.js'; -``` - -新規エンドポイントを抽出し、各々が `endpoint-list.ts` に存在するか grep で確認する: - -```bash -grep -F "'/'" packages/backend/src/server/api/endpoint-list.ts -``` - -**並び順の補足**: ファイル全体は厳密なアルファベット順では並んでおらず、同カテゴリ内 (`admin/queue/*` など) でも追加された経緯どおりの順になっている箇所が多い。**順序逸脱は指摘根拠にしない** (誤検知の元)。「行が存在するか」のみを Critical 観点として扱う。 - -### 7. `misskey-js` 再生成 (Critical) - -`meta` / `paramDef` / `res` を変更したら、PR / ブランチに `packages/misskey-js/src/autogen/` 配下の差分が含まれているか確認する: - -```bash -BASE=$(git merge-base origin/develop HEAD) -git diff --name-only "$BASE"...HEAD -- packages/misskey-js/src/autogen/ -``` - -差分ゼロなら `pnpm build-misskey-js-with-types` の実行漏れ。CI の `check-misskey-js-autogen` ジョブで必ず落ちるため Critical 扱い。 - -### 8. e2e テスト (Major) - -[test/e2e/endpoints.ts](../../packages/backend/test/e2e/endpoints.ts) または `test/e2e/.ts` (`note.ts`, `users.ts` 等) 配下に、対応する `api('/', ...)` 呼び出しを含む `test(...)` ケースが追加されているか確認する。複雑な分岐 (権限チェック・エラーケース) の網羅も確認する。 - -**describe ラベルの形式は問わない**: 既存テストは `describe('Note', () => { test('投稿できる', ...) })` のように人間可読ラベルで構造化されており、`/` 形式の describe は使われていない。describe 名の規約違反としては指摘しない。 - -### 9. CHANGELOG エントリ (Minor) - -ユーザー影響がある (新エンドポイント / 既存挙動変更) 場合、`CHANGELOG.md` の `## Unreleased` → `### Server` に 1 行追加されているか確認する。 - -``` -- Feat: /api// を追加 -``` - -純粋な内部リファクタなら不要。 - -## 出力形式 - -優先度別に以下のフォーマットで出力する。 - -``` -## 🔴 Critical -- packages/backend/src/server/api/endpoints/foo/bar.ts:23 - meta.errors.fooError.id が UUID v4 形式ではない (実値: 'xxx-xxx')。 - `node -e "console.log(crypto.randomUUID())"` で再生成すること。 - -## 🟡 Major -- ... - -## 🔵 Minor -- ... -``` - -問題のないチェック項目には触れない。全項目クリアなら `✅ レビュー観点上の指摘なし` と短く返す。 - -## 参照 - -- [.Codex/skills/add-api-endpoint/SKILL.md](../skills/add-api-endpoint/SKILL.md) — 実装側の規約 (本エージェントの根拠) -- [endpoints.ts (meta/paramDef 型定義)](../../packages/backend/src/server/api/endpoints.ts) -- [endpoint-list.ts (★ 登録先)](../../packages/backend/src/server/api/endpoint-list.ts) -- [endpoint-base.ts (Endpoint 基底クラス)](../../packages/backend/src/server/api/endpoint-base.ts) -- [error.ts (ApiError)](../../packages/backend/src/server/api/error.ts) -- [test/e2e/endpoints.ts](../../packages/backend/test/e2e/endpoints.ts) -- [AGENTS.md](../../AGENTS.md) — SPDX / マイグレーション履歴 / CHANGELOG 書式などの最低限ルール (Codex / Copilot と共通)''' diff --git a/.codex/agents/vue-component-reviewer.toml b/.codex/agents/vue-component-reviewer.toml deleted file mode 100644 index 910226d3c2..0000000000 --- a/.codex/agents/vue-component-reviewer.toml +++ /dev/null @@ -1,173 +0,0 @@ -name = "vue-component-reviewer" -description = 'Misskey フロントエンド (packages/frontend/src/components/ / pages/) の Vue 3 SFC 変更を専門レビューする。SPDX (HTML コメント) / Mk* 命名 /