From ae6e77a7856b29ff83bee3989c9653d494d6f750 Mon Sep 17 00:00:00 2001 From: "takemi.ohama" Date: Sat, 27 Jun 2026 22:48:00 +0000 Subject: [PATCH 01/10] =?UTF-8?q?Fix:=20ndf=E3=83=97=E3=83=A9=E3=82=B0?= =?UTF-8?q?=E3=82=A4=E3=83=B3=E3=82=92Codex=E5=AF=BE=E5=BF=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .agents/plugins/marketplace.json | 20 ++ README.md | 33 +- docs/project-overview.md | 17 +- plugins/ndf/.codex-plugin/plugin.json | 7 + plugins/ndf/README.md | 22 +- plugins/ndf/hooks/codex-hooks.json | 16 + plugins/ndf/hooks/hooks.json | 7 +- plugins/ndf/scripts/codex-slack-notify.js | 294 ++++++++++++++++++ .../ndf/skills/branch-fix-strategy/SKILL.md | 2 +- plugins/ndf/skills/browser-test/SKILL.md | 2 +- plugins/ndf/skills/cherry-pick-pr/SKILL.md | 2 +- plugins/ndf/skills/clean/SKILL.md | 2 +- plugins/ndf/skills/codex/SKILL.md | 2 +- plugins/ndf/skills/cross-review/SKILL.md | 2 +- .../ndf/skills/data-analyst-export/SKILL.md | 2 +- .../data-analyst-sql-optimization/SKILL.md | 2 +- plugins/ndf/skills/deepwiki-transfer/SKILL.md | 2 +- plugins/ndf/skills/deploy/SKILL.md | 2 +- .../skills/docker-container-access/SKILL.md | 2 +- plugins/ndf/skills/fix/SKILL.md | 2 +- plugins/ndf/skills/gemini/SKILL.md | 2 +- plugins/ndf/skills/git-gh-operations/SKILL.md | 2 +- plugins/ndf/skills/google-auth/SKILL.md | 2 +- plugins/ndf/skills/google-chat/SKILL.md | 2 +- plugins/ndf/skills/google-drive/SKILL.md | 2 +- .../ndf/skills/implementation-plan/SKILL.md | 2 +- .../ndf/skills/investigation-rules/SKILL.md | 2 +- .../ndf/skills/issue-plan-strategy/SKILL.md | 2 +- plugins/ndf/skills/knowledge-reorg/SKILL.md | 2 +- .../ndf/skills/logging-guidelines/SKILL.md | 2 +- plugins/ndf/skills/markdown-writing/SKILL.md | 2 +- plugins/ndf/skills/mcp-builder/SKILL.md | 2 +- plugins/ndf/skills/merged/SKILL.md | 2 +- .../ndf/skills/ml-model-structure/SKILL.md | 2 +- plugins/ndf/skills/ndf-policies/SKILL.md | 10 +- .../official-skills-autoloader/SKILL.md | 2 +- .../playwright-browser-connect/SKILL.md | 2 +- .../skills/playwright-evidence-drive/SKILL.md | 2 +- .../ndf/skills/playwright-execution/SKILL.md | 2 +- .../ndf/skills/playwright-kit-ops/SKILL.md | 2 +- plugins/ndf/skills/playwright-report/SKILL.md | 2 +- .../skills/playwright-scenario-test/SKILL.md | 2 +- .../playwright-script-creation/SKILL.md | 2 +- .../skills/playwright-test-planning/SKILL.md | 2 +- plugins/ndf/skills/pr-tests/SKILL.md | 2 +- plugins/ndf/skills/pr/SKILL.md | 2 +- plugins/ndf/skills/problem-solving/SKILL.md | 2 +- plugins/ndf/skills/python-execution/SKILL.md | 2 +- plugins/ndf/skills/qa-security-scan/SKILL.md | 2 +- .../ndf/skills/resolve-pr-comments/SKILL.md | 2 +- plugins/ndf/skills/review-branch/SKILL.md | 2 +- .../ndf/skills/review-pr-comments/SKILL.md | 2 +- plugins/ndf/skills/review/SKILL.md | 2 +- plugins/ndf/skills/skill-stats/SKILL.md | 2 +- plugins/ndf/skills/statusline/SKILL.md | 2 +- plugins/ndf/skills/sync-main/SKILL.md | 2 +- 56 files changed, 448 insertions(+), 72 deletions(-) create mode 100644 .agents/plugins/marketplace.json create mode 100644 plugins/ndf/.codex-plugin/plugin.json create mode 100644 plugins/ndf/hooks/codex-hooks.json create mode 100755 plugins/ndf/scripts/codex-slack-notify.js diff --git a/.agents/plugins/marketplace.json b/.agents/plugins/marketplace.json new file mode 100644 index 00000000..959f663c --- /dev/null +++ b/.agents/plugins/marketplace.json @@ -0,0 +1,20 @@ +{ + "name": "ai-plugins", + "plugins": [ + { + "name": "ndf", + "source": { + "source": "local", + "path": "./plugins/ndf" + }, + "policy": { + "installation": "AVAILABLE", + "authentication": "ON_INSTALL" + }, + "category": "Productivity", + "interface": { + "displayName": "NDF" + } + } + ] +} diff --git a/README.md b/README.md index 81e77bf0..591b1c95 100644 --- a/README.md +++ b/README.md @@ -1,14 +1,14 @@ # AI Plugins -Claude CodeプラグインおよびKiro CLI向けのスキル・MCP設定を共有するための内部マーケットプレイスです。 +Claude Code / Codex / Kiro CLI向けのスキル・MCP設定を共有するための内部マーケットプレイスです。 ## 概要 -このマーケットプレイスは、チーム全体でAI開発ツール(Claude Code / Kiro CLI)の導入を加速するための事前設定されたプラグインを提供します。 +このマーケットプレイスは、チーム全体でAI開発ツール(Claude Code / Codex / Kiro CLI)の導入を加速するための事前設定されたプラグインを提供します。 -**NDFプラグイン v4.13.0** は、以下の機能を**オールインワン**で提供する統合プラグインです: +**NDFプラグイン v4.16.1** は、以下の機能を**オールインワン**で提供する統合プラグインです: -- **47個のSkills**: +- **48個のSkills**: - PR/レビューワークフロー (13): pr, pr-tests, fix, review, review-branch, review-pr-comments, resolve-pr-comments, cherry-pick-pr, deploy, sync-main, merged, clean, browser-test - 原則・ガイドライン (9): ndf-policies, branch-fix-strategy, implementation-plan, investigation-rules, problem-solving, logging-guidelines, markdown-writing, issue-plan-strategy, ml-model-structure - データ分析・品質・環境 (12): data-analyst-sql-optimization, data-analyst-export, qa-security-scan, python-execution, docker-container-access, git-gh-operations, google-auth, codex, deepwiki-transfer, knowledge-reorg, mcp-builder, official-skills-autoloader @@ -38,6 +38,20 @@ Claude CodeプラグインおよびKiro CLI向けのスキル・MCP設定を共 /plugin install ndf@ai-plugins ``` +### Codex + +```bash +codex plugin marketplace add https://github.com/devbasex/ai-plugins +codex plugin add ndf@ai-plugins +``` + +ローカルで検証する場合: + +```bash +codex plugin marketplace add ./local/path/to/ai-plugins +codex plugin add ndf@ai-plugins +``` + ### Kiro CLI #### 1. リポジトリをクローン @@ -83,7 +97,7 @@ kiro-cli chat | プラグイン名 | バージョン | 説明 | 詳細 | |------------|----------|------|------| -| **ndf** | 4.13.0 | Claude Code / Kiro CLI開発環境を**オールインワン**で強化する統合プラグイン。8個の専門エージェント(director、data-analyst、corder、researcher、qa、debugger、devops-engineer、code-reviewer)、47個のSkills(PR/レビューワークフロー、原則・ガイドライン、MLモデル構造標準、データ分析、品質、Playwright E2E(CDPリモート接続・Google Driveエビデンス保管含む)、Google連携、AIクロスレビュー、Codex CLI連携、skill利用統計など)、SessionStartフック(transcript保持期間自動管理)、Stopフック(AI要約生成+Slack通知)を提供。v4.0.0 で Codex MCP サーバを廃止し、`/ndf:codex` skill + `corder` エージェント経由の CLI 直接実行に一本化。 | [README](./plugins/ndf/README.md) | +| **ndf** | 4.16.1 | Claude Code / Codex / Kiro CLI開発環境を**オールインワン**で強化する統合プラグイン。8個の専門エージェント(director、data-analyst、corder、researcher、qa、debugger、devops-engineer、code-reviewer)、48個のSkills(PR/レビューワークフロー、原則・ガイドライン、MLモデル構造標準、データ分析、品質、Playwright E2E(CDPリモート接続・Google Driveエビデンス保管含む)、Google連携、AIクロスレビュー、Codex CLI連携、skill利用統計など)、SessionStartフック(transcript保持期間自動管理)、Stopフック(AI要約生成+Slack通知)を提供。v4.0.0 で Codex MCP サーバを廃止し、`/ndf:codex` skill + `corder` エージェント経由の CLI 直接実行に一本化。 | [README](./plugins/ndf/README.md) | ## 開発ガイドライン @@ -93,12 +107,17 @@ kiro-cli chat ``` ai-plugins/ +├── .agents/ +│ └── plugins/ +│ └── marketplace.json # Codexマーケットプレイスメタデータ ├── .claude-plugin/ -│ └── marketplace.json # マーケットプレイスメタデータ +│ └── marketplace.json # Claude Codeマーケットプレイスメタデータ ├── plugins/ │ └── {plugin-name}/ +│ ├── .codex-plugin/ +│ │ └── plugin.json # Codexプラグインメタデータ │ ├── .claude-plugin/ -│ │ └── plugin.json # プラグインメタデータ(必須) +│ │ └── plugin.json # Claude Codeプラグインメタデータ │ ├── commands/ # スラッシュコマンド (*.md) │ ├── agents/ # サブエージェント (*.md) │ └── skills/ # プロジェクトスキル diff --git a/docs/project-overview.md b/docs/project-overview.md index 06923deb..0427953a 100644 --- a/docs/project-overview.md +++ b/docs/project-overview.md @@ -2,7 +2,7 @@ ## プロジェクトの目的 -Claude Codeプラグインマーケットプレイス(内部用)として、チーム全体でClaude Codeの導入を加速するための事前設定されたプラグインを提供する。 +Claude Code / Codex プラグインマーケットプレイス(内部用)として、チーム全体でAI開発ツールの導入を加速するための事前設定されたプラグインを提供する。 ## リポジトリ情報 @@ -22,8 +22,11 @@ Claude Codeプラグインマーケットプレイス(内部用)として、 ``` ai-plugins/ +├── .agents/ +│ └── plugins/ +│ └── marketplace.json # Codexマーケットプレイスメタデータ ├── .claude-plugin/ -│ └── marketplace.json # マーケットプレイスメタデータ +│ └── marketplace.json # Claude Codeマーケットプレイスメタデータ ├── plugins/ │ ├── ndf/ # NDFプラグイン(メイン) │ ├── mcp-serena/ # Serena MCPプラグイン @@ -37,12 +40,18 @@ ai-plugins/ ## インストール方法 -### マーケットプレイスの追加 +### Codex +```bash +codex plugin marketplace add https://github.com/devbasex/ai-plugins +codex plugin add ndf@ai-plugins +``` + +### Claude Code: マーケットプレイスの追加 ```bash /plugin marketplace add https://github.com/devbasex/ai-plugins ``` -### プラグインのインストール +### Claude Code: プラグインのインストール ```bash /plugin install ndf@ai-plugins ``` diff --git a/plugins/ndf/.codex-plugin/plugin.json b/plugins/ndf/.codex-plugin/plugin.json new file mode 100644 index 00000000..b978a7e6 --- /dev/null +++ b/plugins/ndf/.codex-plugin/plugin.json @@ -0,0 +1,7 @@ +{ + "name": "ndf", + "version": "4.16.1", + "description": "NDF workflows for PRs, reviews, testing, data analysis, Google integrations, and external AI delegation.", + "skills": "./skills/", + "hooks": "./hooks/codex-hooks.json" +} diff --git a/plugins/ndf/README.md b/plugins/ndf/README.md index a88f709e..4c2f550a 100644 --- a/plugins/ndf/README.md +++ b/plugins/ndf/README.md @@ -1,6 +1,6 @@ # NDF Plugin -Claude Code開発環境を**オールインワン**で強化する統合プラグインです。 +Claude Code / Codex開発環境を**オールインワン**で強化する統合プラグインです。 ## 概要 @@ -67,6 +67,26 @@ GitHub、Context7 MCPは公式プラグインとして提供されています /plugin install ndf@ai-plugins ``` +### Codexでのインストール + +```bash +codex plugin marketplace add https://github.com/devbasex/ai-plugins +codex plugin add ndf@ai-plugins +``` + +Codex版ではSkillsに加えて、Codex向けSlack終了通知hookを同梱します。通知は明示的に `NDF_CODEX_SLACK_NOTIFY=true` を設定した場合のみ送信されます。Claude Code向けのstatusline設定、transcript保持期間設定、Claude CLIによるSlack要約通知hookはCodexでは自動有効化しません。 + +Codex向けSlack通知を使う場合は、Claude Code向けSlack通知と同じ環境変数を使います。プロジェクトの `.env` などに以下を設定してください。 + +```bash +NDF_CODEX_SLACK_NOTIFY=true +SLACK_BOT_TOKEN=xoxb-... +SLACK_CHANNEL_ID=C0123456789 +SLACK_USER_MENTION=<@U0123456789> # オプション +``` + +Codexのhookは初回実行前に `/hooks` で信頼設定が必要です。 + ### ステップ3: .envファイルの作成 プロジェクトルートに `.env` ファイルを作成し、必要な認証情報を設定します。 diff --git a/plugins/ndf/hooks/codex-hooks.json b/plugins/ndf/hooks/codex-hooks.json new file mode 100644 index 00000000..282d0e18 --- /dev/null +++ b/plugins/ndf/hooks/codex-hooks.json @@ -0,0 +1,16 @@ +{ + "hooks": { + "Stop": [ + { + "hooks": [ + { + "type": "command", + "command": "node ${PLUGIN_ROOT}/scripts/codex-slack-notify.js", + "timeout": 15, + "statusMessage": "Sending Codex completion notification" + } + ] + } + ] + } +} diff --git a/plugins/ndf/hooks/hooks.json b/plugins/ndf/hooks/hooks.json index 2433473d..9f5c2b0c 100644 --- a/plugins/ndf/hooks/hooks.json +++ b/plugins/ndf/hooks/hooks.json @@ -1,5 +1,4 @@ { - "description": "NDF Plugin hooks: transcript retention guard, default statusline, and Slack notifications", "hooks": { "SessionStart": [ { @@ -8,14 +7,14 @@ "hooks": [ { "type": "command", - "command": "bash ${CLAUDE_PLUGIN_ROOT}/scripts/ensure-retention.sh", + "command": "bash ${PLUGIN_ROOT:-${CLAUDE_PLUGIN_ROOT}}/scripts/ensure-retention.sh", "description": "NDF: ensure transcript retention >= 90 days", "continueOnError": true, "suppressOutput": false }, { "type": "command", - "command": "bash ${CLAUDE_PLUGIN_ROOT}/scripts/statusline-switch.sh ensure", + "command": "bash ${PLUGIN_ROOT:-${CLAUDE_PLUGIN_ROOT}}/scripts/statusline-switch.sh ensure", "description": "NDF: set default statusline when none is configured", "continueOnError": true, "suppressOutput": false @@ -28,7 +27,7 @@ "hooks": [ { "type": "command", - "command": "node ${CLAUDE_PLUGIN_ROOT}/scripts/slack-notify.js session_end", + "command": "node ${PLUGIN_ROOT:-${CLAUDE_PLUGIN_ROOT}}/scripts/slack-notify.js session_end", "description": "Send Slack notification when Claude Code exits" } ] diff --git a/plugins/ndf/scripts/codex-slack-notify.js b/plugins/ndf/scripts/codex-slack-notify.js new file mode 100755 index 00000000..14577027 --- /dev/null +++ b/plugins/ndf/scripts/codex-slack-notify.js @@ -0,0 +1,294 @@ +#!/usr/bin/env node +/** + * Slack notification script for Codex Stop hooks. + * + * Opt-in only: set NDF_CODEX_SLACK_NOTIFY=true plus the same Slack variables + * used by the Claude Code hook: SLACK_BOT_TOKEN, SLACK_CHANNEL_ID, and + * optional SLACK_USER_MENTION. The script avoids model calls and summarizes + * from Codex's local session JSONL when available. + */ + +const fs = require('fs'); +const path = require('path'); +const https = require('https'); +const { spawnSync } = require('child_process'); +const os = require('os'); +const crypto = require('crypto'); + +const CONFIG = { + MAX_SESSION_FILES: 80, + MAX_LINES: 240, + MAX_TEXT: 180, + LOCK_TIMEOUT_MS: 30000, + COOLDOWN_MS: 5000, + FALLBACK_SUMMARY: 'Codexの作業が完了しました', + LOG_DIR: path.join(process.env.CODEX_HOME || path.join(os.homedir(), '.codex'), 'log'), +}; + +const RUN_ID = crypto.randomBytes(4).toString('hex'); + +const isEnabled = () => /^(1|true|yes|on)$/i.test(process.env.NDF_CODEX_SLACK_NOTIFY || ''); +const isDebug = () => /^(1|true|yes|on)$/i.test(process.env.DEBUG_CODEX_SLACK_NOTIFY || ''); + +function log(message, ...args) { + if (!isDebug()) return; + const line = `[${new Date().toISOString()}] [codex-slack:${RUN_ID}] ${message} ${args.map(String).join(' ')}\n`; + process.stderr.write(line); + try { + fs.mkdirSync(CONFIG.LOG_DIR, { recursive: true }); + fs.appendFileSync(path.join(CONFIG.LOG_DIR, 'ndf-codex-slack-notify.log'), line); + } catch (_) { + // Debug logging must never break hook execution. + } +} + +function safeJsonParse(text) { + try { + return JSON.parse(text); + } catch (_) { + return null; + } +} + +async function readStdinJson() { + if (process.stdin.isTTY) return {}; + let input = ''; + for await (const chunk of process.stdin) input += chunk; + log('stdin bytes:', input.length); + return safeJsonParse(input) || {}; +} + +function loadEnvFile() { + let current = process.cwd(); + while (current && current !== path.dirname(current)) { + const envFile = path.join(current, '.env'); + if (fs.existsSync(envFile)) { + for (const rawLine of fs.readFileSync(envFile, 'utf8').split('\n')) { + const line = rawLine.trim(); + if (!line || line.startsWith('#')) continue; + const match = line.match(/^([^=]+)=(.*)$/); + if (!match) continue; + const key = match[1].trim(); + let value = match[2].trim(); + if ((value.startsWith('"') && value.endsWith('"')) || (value.startsWith("'") && value.endsWith("'"))) { + value = value.slice(1, -1); + } + process.env[key] ??= value; + } + return; + } + if (fs.existsSync(path.join(current, '.git'))) return; + current = path.dirname(current); + } +} + +function lockPath() { + const id = `${process.cwd()}:${process.env.CODEX_SESSION_ID || ''}`; + const hash = crypto.createHash('sha256').update(id).digest('hex').slice(0, 12); + return path.join(os.tmpdir(), `ndf-codex-slack-${hash}.lock`); +} + +function acquireLock() { + const file = lockPath(); + const now = Date.now(); + const existing = fs.existsSync(file) ? safeJsonParse(fs.readFileSync(file, 'utf8')) : null; + if (existing?.completedAt && now - existing.completedAt < CONFIG.COOLDOWN_MS) return false; + if (existing?.timestamp && !existing.completedAt && now - existing.timestamp < CONFIG.LOCK_TIMEOUT_MS) return false; + fs.writeFileSync(file, JSON.stringify({ pid: process.pid, timestamp: now, completedAt: null })); + return true; +} + +function releaseLock() { + const file = lockPath(); + const data = fs.existsSync(file) ? safeJsonParse(fs.readFileSync(file, 'utf8')) || {} : {}; + data.completedAt = Date.now(); + fs.writeFileSync(file, JSON.stringify(data)); +} + +function gitValue(args, fallback = '') { + const result = spawnSync('git', args, { cwd: process.cwd(), encoding: 'utf8' }); + return result.status === 0 ? result.stdout.trim() : fallback; +} + +function repoInfo() { + const root = gitValue(['rev-parse', '--show-toplevel'], process.cwd()); + const branch = gitValue(['branch', '--show-current'], ''); + return { + name: path.basename(root || process.cwd()), + root, + branch, + }; +} + +function codexHome() { + return process.env.CODEX_HOME || path.join(os.homedir(), '.codex'); +} + +function findSessionFiles() { + const base = path.join(codexHome(), 'sessions'); + if (!fs.existsSync(base)) return []; + const files = []; + const stack = [base]; + while (stack.length) { + const dir = stack.pop(); + for (const entry of fs.readdirSync(dir, { withFileTypes: true })) { + const p = path.join(dir, entry.name); + if (entry.isDirectory()) stack.push(p); + else if (entry.isFile() && entry.name.endsWith('.jsonl')) { + files.push({ path: p, mtimeMs: fs.statSync(p).mtimeMs }); + } + } + } + return files.sort((a, b) => b.mtimeMs - a.mtimeMs).slice(0, CONFIG.MAX_SESSION_FILES); +} + +function textFromContent(content) { + if (typeof content === 'string') return content; + if (Array.isArray(content)) { + return content.map((item) => item?.text || item?.content || '').filter(Boolean).join('\n'); + } + if (content && typeof content === 'object') return content.text || content.message || ''; + return ''; +} + +function textFromItem(item) { + const payload = item?.payload || {}; + if (payload.type === 'message') { + return textFromContent(payload.content); + } + if (payload.type === 'agent_message') return payload.message || ''; + if (item.type === 'event_msg' && payload.message) return payload.message; + return ''; +} + +function summarizeText(text) { + const oneLine = String(text || '') + .replace(/```[\s\S]*?```/g, '') + .replace(/\s+/g, ' ') + .trim(); + if (!oneLine) return null; + return oneLine.length > CONFIG.MAX_TEXT ? `${oneLine.slice(0, CONFIG.MAX_TEXT - 1)}…` : oneLine; +} + +function readSessionSummary(hookInput) { + const explicitPath = hookInput.transcript_path || hookInput.session_path || hookInput.session_file; + const candidates = explicitPath ? [{ path: explicitPath }] : findSessionFiles(); + const cwd = hookInput.cwd || process.cwd(); + const sessionId = hookInput.session_id || hookInput.thread_id || process.env.CODEX_SESSION_ID || ''; + + for (const candidate of candidates) { + if (!candidate.path || !fs.existsSync(candidate.path)) continue; + const lines = fs.readFileSync(candidate.path, 'utf8').trim().split('\n').slice(-CONFIG.MAX_LINES); + const parsed = lines.map(safeJsonParse).filter(Boolean); + const meta = parsed.find((item) => item.type === 'session_meta')?.payload || {}; + if (!explicitPath && meta.cwd && meta.cwd !== cwd) continue; + if (!explicitPath && sessionId && meta.session_id && meta.session_id !== sessionId) continue; + + const final = [...parsed].reverse().find((item) => { + const payload = item.payload || {}; + return payload.phase === 'final_answer' || payload.type === 'agent_message'; + }); + const user = [...parsed].reverse().find((item) => { + const payload = item.payload || {}; + return payload.type === 'message' && payload.role === 'user'; + }); + const tokenEvent = [...parsed].reverse().find((item) => item.type === 'event_msg' && item.payload?.type === 'token_count'); + + return { + sessionId: meta.session_id || sessionId, + summary: summarizeText(textFromItem(final)) || summarizeText(textFromItem(user)), + model: meta.model || meta.model_slug || '', + tokenInfo: tokenEvent?.payload?.info || null, + file: candidate.path, + }; + } + + return { sessionId, summary: null, model: '', tokenInfo: null, file: null }; +} + +function formatTokenInfo(info) { + const usage = info?.total_token_usage || info?.last_token_usage; + const window = info?.model_context_window; + if (!usage?.total_tokens || !window) return ''; + const pct = Math.round((usage.total_tokens / window) * 100); + return `tokens: ${usage.total_tokens}/${window} (${pct}%)`; +} + +function formatMessage(repo, session) { + const mention = process.env.SLACK_USER_MENTION ? `${process.env.SLACK_USER_MENTION} ` : ''; + const parts = [ + `${mention}[${repo.name}] Codex: ${session.summary || CONFIG.FALLBACK_SUMMARY}`, + repo.branch ? `branch: ${repo.branch}` : '', + session.model ? `model: ${session.model}` : '', + formatTokenInfo(session.tokenInfo), + session.sessionId ? `session: ${session.sessionId}` : '', + `cwd: ${process.cwd()}`, + ].filter(Boolean); + return parts.join('\n'); +} + +function postSlack(text) { + const token = process.env.SLACK_BOT_TOKEN; + const channel = process.env.SLACK_CHANNEL_ID; + if (!token || !channel) return Promise.resolve(false); + + return new Promise((resolve) => { + const body = JSON.stringify({ channel, text }); + const req = https.request({ + hostname: 'slack.com', + port: 443, + path: '/api/chat.postMessage', + method: 'POST', + headers: { + Authorization: `Bearer ${token}`, + 'Content-Type': 'application/json; charset=utf-8', + 'Content-Length': Buffer.byteLength(body), + }, + }, (res) => { + let response = ''; + res.on('data', (chunk) => { response += chunk; }); + res.on('end', () => { + const json = safeJsonParse(response); + log('slack ok:', json?.ok, 'error:', json?.error || ''); + resolve(json?.ok === true); + }); + }); + req.on('error', (error) => { + log('slack error:', error.message); + resolve(false); + }); + req.write(body); + req.end(); + }); +} + +async function main() { + loadEnvFile(); + if (!isEnabled()) { + log('disabled'); + return; + } + if (!process.env.SLACK_BOT_TOKEN || !process.env.SLACK_CHANNEL_ID) { + log('missing slack env'); + return; + } + if (!acquireLock()) { + log('lock rejected'); + return; + } + try { + const hookInput = await readStdinJson(); + const repo = repoInfo(); + const session = readSessionSummary(hookInput); + const text = formatMessage(repo, session); + await postSlack(text); + } finally { + releaseLock(); + } +} + +main().catch((error) => { + log('fatal:', error.stack || error.message); + releaseLock(); + process.exit(0); +}); diff --git a/plugins/ndf/skills/branch-fix-strategy/SKILL.md b/plugins/ndf/skills/branch-fix-strategy/SKILL.md index f33a8d51..852f05d7 100644 --- a/plugins/ndf/skills/branch-fix-strategy/SKILL.md +++ b/plugins/ndf/skills/branch-fix-strategy/SKILL.md @@ -1,6 +1,6 @@ --- name: branch-fix-strategy -description: "修正を複数ブランチに適用する際のブランチ戦略。featureブランチへの先行commitとcherry-pickによる短命branchへの適用手順。環境別branch(qa/staging/epsilon等)への修正適用時に参照する。" +description: "複数ブランチへ同じ修正を適用する戦略。" when_to_use: "同じ修正を複数ブランチ (qa/staging/release等) に適用する必要があるとき。Triggers: 'cherry-pick', '環境ブランチに修正適用', 'qaに反映', 'stagingに反映', 'release branchへ', 'multi-branch fix', 'apply to qa/staging'" --- diff --git a/plugins/ndf/skills/browser-test/SKILL.md b/plugins/ndf/skills/browser-test/SKILL.md index 2872178b..e0c744b7 100644 --- a/plugins/ndf/skills/browser-test/SKILL.md +++ b/plugins/ndf/skills/browser-test/SKILL.md @@ -1,6 +1,6 @@ --- name: browser-test -description: "ブラウザで動作確認を実行する。Playwright MCP または Chrome DevTools MCP を利用可能な場合に自動化。Webアプリの機能検証・回帰確認用。" +description: "ブラウザでWebアプリの動作確認を行う。" argument-hint: "[url]" disable-model-invocation: true allowed-tools: diff --git a/plugins/ndf/skills/cherry-pick-pr/SKILL.md b/plugins/ndf/skills/cherry-pick-pr/SKILL.md index bc93e2df..4b14e6c2 100644 --- a/plugins/ndf/skills/cherry-pick-pr/SKILL.md +++ b/plugins/ndf/skills/cherry-pick-pr/SKILL.md @@ -1,6 +1,6 @@ --- name: cherry-pick-pr -description: "featureブランチのコミットを別ベースブランチ(qa/staging/release等)へcherry-pick PR する。main汚染を避けるための短命ブランチ経由PR作成ワークフロー。" +description: "featureコミットを環境ブランチへcherry-pick PRする。" argument-hint: " (例: qa/staging, release/v2)" disable-model-invocation: true allowed-tools: diff --git a/plugins/ndf/skills/clean/SKILL.md b/plugins/ndf/skills/clean/SKILL.md index 1bc16f82..9cb1d235 100644 --- a/plugins/ndf/skills/clean/SKILL.md +++ b/plugins/ndf/skills/clean/SKILL.md @@ -1,6 +1,6 @@ --- name: clean -description: "mainマージ済みブランチをローカル/リモート一括削除する" +description: "mainマージ済みブランチを削除する。" disable-model-invocation: true allowed-tools: - Bash diff --git a/plugins/ndf/skills/codex/SKILL.md b/plugins/ndf/skills/codex/SKILL.md index 3bda1e98..35f7dfa2 100644 --- a/plugins/ndf/skills/codex/SKILL.md +++ b/plugins/ndf/skills/codex/SKILL.md @@ -1,6 +1,6 @@ --- name: codex -description: "codex CLI (OpenAI Codex) を直接実行してコード生成・レビュー・調査を外部AIに委譲する手順。`codex exec` をバックグラウンド実行する。サンドボックス制約の回避、stdin/stderr経路、バックグラウンド待機パターンを扱う。" +description: "Codex CLIへコード生成・レビュー・調査を委譲する。" when_to_use: "外部 AI へコード生成 / レビュー / 調査を委譲したいとき。Triggers: 'codexで調査', 'codexレビュー', '第二意見レビュー', 'codex exec', 'external AI review'" --- diff --git a/plugins/ndf/skills/cross-review/SKILL.md b/plugins/ndf/skills/cross-review/SKILL.md index 8ba321aa..1472b12f 100644 --- a/plugins/ndf/skills/cross-review/SKILL.md +++ b/plugins/ndf/skills/cross-review/SKILL.md @@ -1,6 +1,6 @@ --- name: cross-review -description: "PR を codex / gemini 両方にレビューさせ、両方 APPROVE まで /ndf:review → /ndf:fix を自動ループ。サブエージェント分離・PR ローテーション・nit 集約でメイン context 消費を最小化" +description: "Codex/GeminiのPRクロスレビューを自動ループする。" argument-hint: "[PR番号] [--max-rounds N] [--rotate-after K] [--rotate-mode light|squash] [--only codex|gemini]" disable-model-invocation: true allowed-tools: diff --git a/plugins/ndf/skills/data-analyst-export/SKILL.md b/plugins/ndf/skills/data-analyst-export/SKILL.md index a25e4911..abf62eee 100644 --- a/plugins/ndf/skills/data-analyst-export/SKILL.md +++ b/plugins/ndf/skills/data-analyst-export/SKILL.md @@ -1,6 +1,6 @@ --- name: data-analyst-export -description: "Export query results to various formats (CSV, JSON, Excel, Markdown tables) with proper formatting and headers. CSV (custom delimiters), JSON (pretty-print), Excel (multi-sheet/formatting), Markdown tables for docs." +description: "分析結果をCSV/JSON/Excel/Markdownへ出力する。" when_to_use: "Use when saving analysis results to files. Triggers: 'export data', 'save results', 'output CSV', 'output JSON', 'output Excel', 'データ出力', '結果保存', 'エクスポート'" allowed-tools: - Write diff --git a/plugins/ndf/skills/data-analyst-sql-optimization/SKILL.md b/plugins/ndf/skills/data-analyst-sql-optimization/SKILL.md index 8bd96f05..021a6435 100644 --- a/plugins/ndf/skills/data-analyst-sql-optimization/SKILL.md +++ b/plugins/ndf/skills/data-analyst-sql-optimization/SKILL.md @@ -1,6 +1,6 @@ --- name: data-analyst-sql-optimization -description: "Apply SQL optimization patterns: index usage, query rewriting, JOIN/subquery optimization, window functions, N+1 elimination." +description: "SQL最適化とスロークエリ改善を行う。" when_to_use: "Use when improving query performance or analyzing slow queries. Triggers: 'optimize SQL', 'slow query', 'improve performance', 'SQL最適化', 'クエリ改善', 'パフォーマンス向上'" --- diff --git a/plugins/ndf/skills/deepwiki-transfer/SKILL.md b/plugins/ndf/skills/deepwiki-transfer/SKILL.md index fa103acc..969dcab0 100644 --- a/plugins/ndf/skills/deepwiki-transfer/SKILL.md +++ b/plugins/ndf/skills/deepwiki-transfer/SKILL.md @@ -1,6 +1,6 @@ --- name: deepwiki-transfer -description: "DeepWiki (Devin MCP) のドキュメント内容を対象リポジトリの Markdown ファイルとして転載する。セクション構成維持・番号付きファイル分割・GFM 準拠補正・日本語翻訳 (オプション) まで自動処理。" +description: "DeepWiki内容をMarkdownへ転載する。" when_to_use: "DeepWiki から Markdown としてコンテンツを取得・転載したいとき。Triggers: 'deepwiki transfer', 'deepwiki転載', 'wiki転載', 'リポジトリドキュメント取得', 'DeepWikiからMarkdown', 'transfer wiki contents'" disable-model-invocation: true allowed-tools: diff --git a/plugins/ndf/skills/deploy/SKILL.md b/plugins/ndf/skills/deploy/SKILL.md index 29d847ac..c855e259 100644 --- a/plugins/ndf/skills/deploy/SKILL.md +++ b/plugins/ndf/skills/deploy/SKILL.md @@ -1,6 +1,6 @@ --- name: deploy -description: "現在のfeatureブランチを環境ブランチ(qa/staging等)へデプロイPRを作成する。featureブランチ全体をorigin/main取り込み済みのdeployブランチ経由でPRする。cherry-pick-prと異なり、部分選択でなくブランチ全体を適用する用途。" +description: "featureブランチ全体を環境ブランチへPRする。" argument-hint: " (例: qa/staging, release/v2)" disable-model-invocation: true allowed-tools: diff --git a/plugins/ndf/skills/docker-container-access/SKILL.md b/plugins/ndf/skills/docker-container-access/SKILL.md index 3829dc57..97f50744 100644 --- a/plugins/ndf/skills/docker-container-access/SKILL.md +++ b/plugins/ndf/skills/docker-container-access/SKILL.md @@ -1,6 +1,6 @@ --- name: docker-container-access -description: "Docker コンテナへのアクセス方法を判定し、適切な接続コマンドを提供する。DinD/DooD 環境の自動検出、bind mount の注意点と代替手段、curl / Playwright MCP での接続例を扱う。" +description: "Dockerコンテナへの接続方法を判定する。" when_to_use: "Docker / コンテナへのアクセス・localhost 接続不可・DinD/DooD 環境判定が必要なとき。Triggers: 'docker access', 'container connect', 'localhost not working', 'DinD', 'DooD', 'Docker接続', 'コンテナアクセス', 'curl container'" allowed-tools: - Read diff --git a/plugins/ndf/skills/fix/SKILL.md b/plugins/ndf/skills/fix/SKILL.md index 652cfa2e..6ab4be3e 100644 --- a/plugins/ndf/skills/fix/SKILL.md +++ b/plugins/ndf/skills/fix/SKILL.md @@ -1,6 +1,6 @@ --- name: fix -description: "PRのレビューコメントを確認し、優先度に応じてコード修正を実行する。サブエージェント (general-purpose) 起動にも対応。--defer-nit / --severity-min で対応範囲を制御。" +description: "PRレビューコメントに対応してコード修正する。" when_to_use: "PRレビューコメント (codex/gemini/人間) の指摘を実際にコード修正で対応したいとき。review-pr-comments で分類した後の修正フェーズに使う。Triggers: 'PRコメント対応', 'PRレビュー修正', 'PR fix', 'review feedback fix', 'コメントに対応して修正'" argument-hint: "[PR番号] [--defer-nit] [--severity-min critical|major|minor]" allowed-tools: diff --git a/plugins/ndf/skills/gemini/SKILL.md b/plugins/ndf/skills/gemini/SKILL.md index 40e6dc7c..5c0a80c1 100644 --- a/plugins/ndf/skills/gemini/SKILL.md +++ b/plugins/ndf/skills/gemini/SKILL.md @@ -1,6 +1,6 @@ --- name: gemini -description: "gemini CLI (Google Gemini) を直接実行してコード生成・レビュー・調査を外部AIに委譲する手順。`gemini -p` を非対話モードで実行し、stdout で最終結果を回収する。" +description: "Gemini CLIへコード生成・レビュー・調査を委譲する。" when_to_use: "外部 AI (Gemini)へコード生成 / レビュー / 調査を委譲したいとき。Triggers: 'geminiで調査', 'geminiレビュー', '第二意見レビュー (Gemini)', 'gemini exec', 'external AI review (Gemini)'" --- diff --git a/plugins/ndf/skills/git-gh-operations/SKILL.md b/plugins/ndf/skills/git-gh-operations/SKILL.md index 7cf2dca8..397dbafd 100644 --- a/plugins/ndf/skills/git-gh-operations/SKILL.md +++ b/plugins/ndf/skills/git-gh-operations/SKILL.md @@ -1,6 +1,6 @@ --- name: git-gh-operations -description: "git / gh コマンド実行時の共通エラーパターンと正しい操作方法。CWD 問題、パス解決ルール、gh CLI / GitHub API の正しい使い方、過去のエラー事例と対策を扱う。" +description: "git/ghコマンドのエラー対処と操作手順。" when_to_use: "git / gh コマンドでエラーが出た or 操作方法に迷うとき。Triggers: 'git add', 'git commit', 'git push', 'gh pr', 'gh api', 'GitHub操作', 'gitエラー', 'fatal:', 'pathspec'" allowed-tools: - Bash diff --git a/plugins/ndf/skills/google-auth/SKILL.md b/plugins/ndf/skills/google-auth/SKILL.md index fe432ee6..5d5c55b3 100644 --- a/plugins/ndf/skills/google-auth/SKILL.md +++ b/plugins/ndf/skills/google-auth/SKILL.md @@ -1,6 +1,6 @@ --- name: google-auth -description: "Google API (Sheets, Drive, Apps Script, Chat, Calendar 等) の OAuth2 認証ヘルパ。単一トークンファイルで複数 API のスコープを一元管理し、CLI / Python ライブラリ両方として使える。" +description: "Google APIのOAuth2認証を支援する。" when_to_use: "Google API の OAuth2 認証が必要なときに自動参照。Triggers: 'Google認証', 'OAuth', 'google_token', 'spreadsheets', 'Google API', 'client_secret'" allowed-tools: - Read diff --git a/plugins/ndf/skills/google-chat/SKILL.md b/plugins/ndf/skills/google-chat/SKILL.md index 82a21069..b85be05a 100644 --- a/plugins/ndf/skills/google-chat/SKILL.md +++ b/plugins/ndf/skills/google-chat/SKILL.md @@ -1,6 +1,6 @@ --- name: google-chat -description: "Google Chat API でスペースのメッセージ読み取り・スペース一覧を取得する。WebFetch は認証付き Chat ページに非対応のため、Chat API + OAuth2 ユーザー認証で取得する (認証は ndf:google-auth に委譲)。" +description: "Google Chat APIでスペースやメッセージを取得する。" when_to_use: "Google Chat スペースのメッセージ取得・スペース一覧が必要なとき。Triggers: 'Google Chat', 'chat.spaces', 'chat.messages', 'Chatスペース', 'メッセージ取得', 'チャット履歴'" allowed-tools: - Read diff --git a/plugins/ndf/skills/google-drive/SKILL.md b/plugins/ndf/skills/google-drive/SKILL.md index 198c2bfa..80e07948 100644 --- a/plugins/ndf/skills/google-drive/SKILL.md +++ b/plugins/ndf/skills/google-drive/SKILL.md @@ -1,6 +1,6 @@ --- name: google-drive -description: "Google Drive / Google Docs API でファイルのエクスポート・ダウンロード・アップロード (公開共有リンク付与) を行う。認証は ndf:google-auth に委譲。" +description: "Google Drive/Docs APIでファイル操作する。" when_to_use: "Google Drive / Docs のファイル操作が必要なとき。Triggers: 'Google Drive', 'Google Docs', 'drive.file', 'ファイルエクスポート', 'ダウンロード', 'アップロード', '公開共有リンク'" allowed-tools: - Read diff --git a/plugins/ndf/skills/implementation-plan/SKILL.md b/plugins/ndf/skills/implementation-plan/SKILL.md index 3f56284b..f1ac0e10 100644 --- a/plugins/ndf/skills/implementation-plan/SKILL.md +++ b/plugins/ndf/skills/implementation-plan/SKILL.md @@ -1,6 +1,6 @@ --- name: implementation-plan -description: "実装プランファイル作成・更新の手順。実装開始時およびPR作成時にissues/配下の実装プランの有無を確認し、なければ会話履歴・git log・git diffから生成する。複数ファイル変更・新規機能追加・DBマイグレーション伴う変更が対象。" +description: "実装プランファイルを作成・更新する。" when_to_use: "実装開始時 / PR作成時に実装プランの作成・更新が必要なとき。複数ファイル変更・新機能追加・DBマイグレーションを含む変更で自動参照。Triggers: '実装プラン', '実装を開始', 'PR作成', 'implementation plan', 'plan first', '設計書を作成', 'issues/に追加'" --- diff --git a/plugins/ndf/skills/investigation-rules/SKILL.md b/plugins/ndf/skills/investigation-rules/SKILL.md index 2bbdae33..3956ee19 100644 --- a/plugins/ndf/skills/investigation-rules/SKILL.md +++ b/plugins/ndf/skills/investigation-rules/SKILL.md @@ -1,6 +1,6 @@ --- name: investigation-rules -description: "調査レポート作成のルール。否定的結論のエビデンス要件、残課題の記載フォーマット、ハルシネーション防止のための裏取り原則を扱う。DB調査に限らずコードベース調査・仕様調査一般に適用。" +description: "調査レポート作成と裏取りのルール。" when_to_use: "調査・デバッグ・不具合レポートを作成するとき。「ない」「該当なし」等の否定的結論を出すときは必ず参照。Triggers: '調査', 'デバッグ', '不具合レポート', '原因調査', 'investigation', 'root cause', 'カラムがない', '該当コードがない', 'データがない'" --- diff --git a/plugins/ndf/skills/issue-plan-strategy/SKILL.md b/plugins/ndf/skills/issue-plan-strategy/SKILL.md index 6c0dec50..fe7d8f83 100644 --- a/plugins/ndf/skills/issue-plan-strategy/SKILL.md +++ b/plugins/ndf/skills/issue-plan-strategy/SKILL.md @@ -1,6 +1,6 @@ --- name: issue-plan-strategy -description: "1 つの issue に対する plan(企画書・設計書) 作成、および plan 実行(実装)時のブランチ・worktree・Draft PR・レビュー運用を一括で扱うワークフロー。issue ファイル/URL を引数に取るスラッシュコマンドとしても、issue から plan 作成依頼を受けた時 / 既存 plan の実装依頼を受けた時の自動発動 skill としても利用可能。" +description: "issueからplan作成・実装運用まで扱う。" when_to_use: "issue → plan 作成 / 既存 plan の実装 (実行) を依頼されたとき。複数 PR に分割される設計や、release branch + 個別 PR + worktree 運用が必要なときに参照する。Triggers: 'issueのplanを作って', 'PLANxxの設計', '設計書を起こして', 'このplanを実装して', 'PLANxxを実装', 'planを実行', 'release branch 作って実装開始', 'multi-PR で進めて'" argument-hint: "[issue-path-or-url] (例: issues/i16.md, https://github.com/org/repo/issues/123)" allowed-tools: diff --git a/plugins/ndf/skills/knowledge-reorg/SKILL.md b/plugins/ndf/skills/knowledge-reorg/SKILL.md index f75f8e46..d124faf4 100644 --- a/plugins/ndf/skills/knowledge-reorg/SKILL.md +++ b/plugins/ndf/skills/knowledge-reorg/SKILL.md @@ -1,6 +1,6 @@ --- name: knowledge-reorg -description: "AGENTS.mdとSkillsを「AI Agent Knowledge Architecture Policy」に基づいて整理・再構成する" +description: "AGENTS.mdとSkillsを知識ポリシーで再構成する。" argument-hint: "[--target AGENTS.md|skills|docs|all] [--dry-run] [--migrate-memory]" disable-model-invocation: true allowed-tools: diff --git a/plugins/ndf/skills/logging-guidelines/SKILL.md b/plugins/ndf/skills/logging-guidelines/SKILL.md index 4c3ffc87..45df0ba4 100644 --- a/plugins/ndf/skills/logging-guidelines/SKILL.md +++ b/plugins/ndf/skills/logging-guidelines/SKILL.md @@ -1,6 +1,6 @@ --- name: logging-guidelines -description: "ログを追加・修正する際のガイドライン。ログレベルの選択基準、ループ内ログの制御、エラー蓄積パターン、機密情報の扱いを扱う。言語/FW非依存の原則。" +description: "ログ追加・修正時の設計ガイドライン。" when_to_use: "コードにログを追加・修正・整理するとき。Triggers: 'ログ追加', 'log追加', 'logger', 'logging', 'ログレベル', 'log level', 'デバッグログ', 'エラーログ', 'logger.info', 'logger.error', 'print文をログに'" --- diff --git a/plugins/ndf/skills/markdown-writing/SKILL.md b/plugins/ndf/skills/markdown-writing/SKILL.md index 1c6fe439..d3d23907 100644 --- a/plugins/ndf/skills/markdown-writing/SKILL.md +++ b/plugins/ndf/skills/markdown-writing/SKILL.md @@ -1,6 +1,6 @@ --- name: markdown-writing -description: "Markdown 文書作成時の重要なルール。図表は mermaid/plantUML を使用 (ASCII ART 禁止、ツリー構造のみ例外)、概ね 300 行以内、超える場合は順序 prefix (01-, 02-, ...) 付きで分割する。" +description: "Markdown文書と図表を書くためのルール。" when_to_use: "Markdown 文書 / 図表を作成 / 編集するとき。Triggers: 'Markdown作成', 'ドキュメント作成', '文書作成', '図を描く', 'mermaid', 'create document', 'write docs'" allowed-tools: - Read diff --git a/plugins/ndf/skills/mcp-builder/SKILL.md b/plugins/ndf/skills/mcp-builder/SKILL.md index 8a1a77a4..71c72205 100644 --- a/plugins/ndf/skills/mcp-builder/SKILL.md +++ b/plugins/ndf/skills/mcp-builder/SKILL.md @@ -1,6 +1,6 @@ --- name: mcp-builder -description: Guide for creating high-quality MCP (Model Context Protocol) servers that enable LLMs to interact with external services through well-designed tools. Use when building MCP servers to integrate external APIs or services, whether in Python (FastMCP) or Node/TypeScript (MCP SDK). +description: "MCPサーバーを設計・実装する。" license: Complete terms in LICENSE.txt --- diff --git a/plugins/ndf/skills/merged/SKILL.md b/plugins/ndf/skills/merged/SKILL.md index 202450c3..1183a8e0 100644 --- a/plugins/ndf/skills/merged/SKILL.md +++ b/plugins/ndf/skills/merged/SKILL.md @@ -1,6 +1,6 @@ --- name: merged -description: "PRマージ後のクリーンアップを実行する(main更新、ブランチ削除)" +description: "PRマージ後のmain更新とブランチ削除を行う。" argument-hint: "[PR番号]" disable-model-invocation: true allowed-tools: diff --git a/plugins/ndf/skills/ml-model-structure/SKILL.md b/plugins/ndf/skills/ml-model-structure/SKILL.md index 2f3bca13..b557c7e5 100644 --- a/plugins/ndf/skills/ml-model-structure/SKILL.md +++ b/plugins/ndf/skills/ml-model-structure/SKILL.md @@ -1,6 +1,6 @@ --- name: ml-model-structure -description: "機械学習モデルの構築・再学習・推論API(SageMaker等)開発における標準ディレクトリ構造と実装方法。版ごとに自己完結する構造 (vN/) + 版内 feature SSoT (features.py) + 推論コンテナ規約で、train/serve skew を版内で防ぎ champion/challenger の並行運用に備える。新しいモデルを作る・再学習する・推論コンテナを書く・モデルをバージョン管理するときは、フラットに連番スクリプトを置く前に必ず本スキルを参照すること。" +description: "MLモデル開発の標準ディレクトリ構造を適用する。" when_to_use: "機械学習モデルの新規構築・再学習・推論API/コンテナ開発・モデルのバージョン管理/並行運用を行うとき。analysis/ 配下に学習スクリプトや推論コードを配置する設計判断が必要なとき。Triggers: 'モデル構築', 'モデル再学習', 'モデルのバージョン管理', '推論コンテナ', '推論API', 'SageMaker', 'feature SSoT', 'train/serve skew', 'analysis ディレクトリ', 'champion challenger', '並行運用'" allowed-tools: - Read diff --git a/plugins/ndf/skills/ndf-policies/SKILL.md b/plugins/ndf/skills/ndf-policies/SKILL.md index e88bcb68..99dbbd1f 100644 --- a/plugins/ndf/skills/ndf-policies/SKILL.md +++ b/plugins/ndf/skills/ndf-policies/SKILL.md @@ -1,14 +1,6 @@ --- name: ndf-policies -description: | - NDFプラグインの基本ポリシー。 - 応答・ドキュメント・コミットメッセージは日本語。 - mainブランチへの直接push/merge禁止(featureブランチ+PR必須)。 - commit/push/PR mergeはユーザー確認後に実行。 - コンテキスト節約: ファイル全体を読む前にSerenaのシンボル概要を確認。 - 複雑タスクはndf:directorに委譲。専門タスクは対応エージェントに直接委譲。 - 知識はdocs/に、手順はskills/に配置(AGENTS.mdを肥大化させない)。 - Serena memoryは使用禁止。知識管理は3層構造(AGENTS.md/docs/skills)で行う。 +description: "NDFプラグインの基本ポリシー。" user-invocable: false --- diff --git a/plugins/ndf/skills/official-skills-autoloader/SKILL.md b/plugins/ndf/skills/official-skills-autoloader/SKILL.md index 723c2521..ca969381 100644 --- a/plugins/ndf/skills/official-skills-autoloader/SKILL.md +++ b/plugins/ndf/skills/official-skills-autoloader/SKILL.md @@ -1,6 +1,6 @@ --- name: official-skills-autoloader -description: "Anthropic 公式 Skill (docx/pptx/xlsx/pdf 等) が必要な作業で、未インストール時に自動でダウンロードして使用する。" +description: "公式Skillsを必要時に自動準備して使う。" when_to_use: "Use when user requests Word/Excel/PowerPoint/PDF creation/editing, frontend design, webapp testing, or other tasks handled by Anthropic's official skills collection. Triggers: 'Word作成', 'Excel出力', 'スライド生成', 'PDF作成', '.docx', '.pptx', '.xlsx', '.pdf', 'create docx', 'generate excel', 'make slides', 'create pdf'." allowed-tools: - Bash diff --git a/plugins/ndf/skills/playwright-browser-connect/SKILL.md b/plugins/ndf/skills/playwright-browser-connect/SKILL.md index 4b7ed0c5..6efb8bdc 100644 --- a/plugins/ndf/skills/playwright-browser-connect/SKILL.md +++ b/plugins/ndf/skills/playwright-browser-connect/SKILL.md @@ -1,6 +1,6 @@ --- name: playwright-browser-connect -description: "Playwright E2E テストのブラウザ接続先を構成する。ローカル Chromium / Windows リモート Chrome (CDP) / macOS リモート Chrome (CDP) の 3 パターンをサポートし、scenario.config.yaml の browser: セクションで宣言的に切り替える。" +description: "Playwrightのブラウザ接続先を構成する。" when_to_use: "E2E テストのブラウザ接続先を設定・変更するとき / remote Chrome に CDP で接続したいとき / WSL2 Docker から Windows Chrome を操作したいとき / macOS ホストの Chrome を使いたいとき。Triggers: 'ブラウザ接続', 'remote chrome', 'CDP接続', 'connectOverCDP', 'リモートブラウザ', 'Windows Chrome', 'macOS Chrome', 'mac Chrome', 'browser connect', 'cdp endpoint', 'remote debugging', 'コンテナからホスト Chrome 起動', 'host.docker.internal'" allowed-tools: - Read diff --git a/plugins/ndf/skills/playwright-evidence-drive/SKILL.md b/plugins/ndf/skills/playwright-evidence-drive/SKILL.md index 667fd14b..3d733e40 100644 --- a/plugins/ndf/skills/playwright-evidence-drive/SKILL.md +++ b/plugins/ndf/skills/playwright-evidence-drive/SKILL.md @@ -1,6 +1,6 @@ --- name: playwright-evidence-drive -description: "Playwright E2E テスト後のエビデンス一式 (動画/trace/HAR/report.md) を Google Drive に保管し、共有リンクを生成する。自動アップロード (--pwk-drive-folder) と手動アップロード (scripts) の両方をサポート。report.md → Google Docs 変換 + Drive リンク埋め込みも対応。" +description: "Playwright証跡をGoogle Driveへ保管する。" when_to_use: "テストエビデンスを Google Drive に保管・共有したいとき / テスト結果を Google Docs としてチームに配布したいとき / Drive 上のエビデンスリンクを report に埋め込みたいとき。Triggers: 'Drive にアップロード', 'Drive 共有', 'エビデンス保管', 'evidence drive', 'pwk-drive-folder', 'テスト結果共有', 'Google Drive エビデンス', 'trace アップロード', '動画アップロード', 'report を Docs に', 'エビデンス配布'" allowed-tools: - Read diff --git a/plugins/ndf/skills/playwright-execution/SKILL.md b/plugins/ndf/skills/playwright-execution/SKILL.md index 0011abf3..a80bc7f6 100644 --- a/plugins/ndf/skills/playwright-execution/SKILL.md +++ b/plugins/ndf/skills/playwright-execution/SKILL.md @@ -1,6 +1,6 @@ --- name: playwright-execution -description: "Playwright E2E テストの実行 + エビデンス収集 (video/trace/screenshot/HAR) + overlay (赤丸カーソル+字幕) + 品質計測 (axe-core/Web Vitals/body_check) を統合した実行フェーズスキル。動画はデフォルト ON。" +description: "Playwright E2Eを実行し証跡と品質指標を収集する。" when_to_use: "E2E テストの実行 / エビデンス収集 / 動画エビデンス / accessibility チェック / Core Web Vitals 計測が必要なとき。テストスクリプト作成済みであることが前提。Triggers: 'E2E テスト実行', 'テスト実行', '動画エビデンス', 'エビデンス収集', 'テスト証跡', 'a11y テスト', 'accessibility テスト', 'axe-core', 'WCAG', 'Core Web Vitals', 'Web Vitals', 'LCP', 'CLS', 'body_check', 'overlay', '字幕', 'カーソル'" allowed-tools: - Read diff --git a/plugins/ndf/skills/playwright-kit-ops/SKILL.md b/plugins/ndf/skills/playwright-kit-ops/SKILL.md index b3ff459a..efef7e94 100644 --- a/plugins/ndf/skills/playwright-kit-ops/SKILL.md +++ b/plugins/ndf/skills/playwright-kit-ops/SKILL.md @@ -1,6 +1,6 @@ --- name: playwright-kit-ops -description: "playwright_kit の操作に特化した実行エージェント。プロジェクト初期化 (init_project)、テスト実行、page role 分類、a11y/CWV 単発スキャン、エビデンスアップロードなど、playwright_kit のスクリプト群を実行する。" +description: "playwright_kitの初期化・実行・証跡操作を行う。" when_to_use: "playwright_kit のスクリプトを実行するとき / E2E テストプロジェクトの初期化 / page role 自動分類 / 単発 a11y・CWV スキャン / Google Drive エビデンスアップロードが必要なとき。Triggers: 'init_project', 'プロジェクト初期化', 'classify_page_role', 'run_a11y_scan', 'check_cwv', 'upload_evidence', 'record_scenario', 'playwright_kit 実行'" allowed-tools: - Read diff --git a/plugins/ndf/skills/playwright-report/SKILL.md b/plugins/ndf/skills/playwright-report/SKILL.md index 8da2568a..5393cb45 100644 --- a/plugins/ndf/skills/playwright-report/SKILL.md +++ b/plugins/ndf/skills/playwright-report/SKILL.md @@ -1,6 +1,6 @@ --- name: playwright-report -description: "Playwright テスト結果の Markdown レポート自動生成。テスト結果サマリ・エビデンスリンク・失敗詳細を report.md にまとめる。" +description: "Playwrightテスト結果レポートを生成する。" when_to_use: "テストレポートの生成 / テスト結果の共有が必要なとき。Triggers: 'テストレポート', 'report.md', 'テスト結果', 'テスト報告書', 'レポート生成', 'テスト結果まとめ'" allowed-tools: - Read diff --git a/plugins/ndf/skills/playwright-scenario-test/SKILL.md b/plugins/ndf/skills/playwright-scenario-test/SKILL.md index b38f5950..a3f3be01 100644 --- a/plugins/ndf/skills/playwright-scenario-test/SKILL.md +++ b/plugins/ndf/skills/playwright-scenario-test/SKILL.md @@ -1,6 +1,6 @@ --- name: playwright-scenario-test -description: "pytest-playwright ベースのフル E2E テストフレームワーク統括。テスト計画・スクリプト作成・エビデンス付きテスト実行・レポート生成の 4 フェーズを組み合わせた包括的なテストワークフローを提供する。個別機能のみ必要な場合は各専門 skill を直接参照。" +description: "pytest-playwrightのフルE2Eワークフローを統括する。" when_to_use: "フル E2E テストワークフロー (計画→スクリプト→実行→レポート) を一貫して行うとき / pytest-playwright 拡張 fixture (pwk_*) の全体像を把握したいとき / init_project.sh でプロジェクトをセットアップするとき。Triggers: 'pytest-playwright', 'pwk_role', 'pwk_evidence', 'init_project', 'シナリオテスト一式', 'フル E2E'" allowed-tools: - Read diff --git a/plugins/ndf/skills/playwright-script-creation/SKILL.md b/plugins/ndf/skills/playwright-script-creation/SKILL.md index 9c259f96..24e43bdc 100644 --- a/plugins/ndf/skills/playwright-script-creation/SKILL.md +++ b/plugins/ndf/skills/playwright-script-creation/SKILL.md @@ -1,6 +1,6 @@ --- name: playwright-script-creation -description: "再現可能な E2E テストスクリプトを作成するガイド。テンプレートを起点にテストコードを実装し、再現可能性レビューを経てからテスト実行フェーズに進む。ndf plugin 非依存で動作する。" +description: "再現可能なE2Eテストスクリプトを作成する。" when_to_use: "E2E テストスクリプトの作成 / テストコードの実装 / テストテンプレートからのスクリプト生成が必要なとき。Triggers: 'テストスクリプト作成', 'テストコード作成', 'テスト実装', 'テストを書く', 'シナリオ作成', 'codegen', 'テンプレートからテスト', 'playwright codegen'" allowed-tools: - Read diff --git a/plugins/ndf/skills/playwright-test-planning/SKILL.md b/plugins/ndf/skills/playwright-test-planning/SKILL.md index 2bb6a587..bd59aa0a 100644 --- a/plugins/ndf/skills/playwright-test-planning/SKILL.md +++ b/plugins/ndf/skills/playwright-test-planning/SKILL.md @@ -1,6 +1,6 @@ --- name: playwright-test-planning -description: "HTSM / ISTQB / FEW HICCUPPS に基づく E2E テスト計画立案。page role 分類 + role 別チェックリストでテスト項目を網羅的に洗い出す。" +description: "E2Eテスト計画とpage role分類を行う。" when_to_use: "E2E テストの計画立案 / page role 分類 / テスト技法の選定 / チェックリスト活用が必要なとき。Triggers: 'テスト計画', 'テスト計画立案', 'page role', 'HTSM', 'ISTQB', 'FEW HICCUPPS', 'チェックリスト', 'テスト技法', 'テスト設計'" allowed-tools: - Read diff --git a/plugins/ndf/skills/pr-tests/SKILL.md b/plugins/ndf/skills/pr-tests/SKILL.md index 18aceea3..cdc04506 100644 --- a/plugins/ndf/skills/pr-tests/SKILL.md +++ b/plugins/ndf/skills/pr-tests/SKILL.md @@ -1,6 +1,6 @@ --- name: pr-tests -description: "PRのTest Planを自動実行し、結果をPRコメントに反映する" +description: "PRのTest Planを実行し結果をコメントする。" argument-hint: "[PR番号]" disable-model-invocation: true allowed-tools: diff --git a/plugins/ndf/skills/pr/SKILL.md b/plugins/ndf/skills/pr/SKILL.md index 8583afea..9e8c6701 100644 --- a/plugins/ndf/skills/pr/SKILL.md +++ b/plugins/ndf/skills/pr/SKILL.md @@ -1,6 +1,6 @@ --- name: pr -description: "commit, push, PR作成(または既存PR説明更新)を一括実行するワークフローコマンド。--draft指定でドラフトPR、base非mainの場合はcherry-pick-prに誘導する。" +description: "commit/push/PR作成またはPR説明更新を行う。" argument-hint: "[--draft] [base-branch] or [commit-message]" disable-model-invocation: true allowed-tools: diff --git a/plugins/ndf/skills/problem-solving/SKILL.md b/plugins/ndf/skills/problem-solving/SKILL.md index 5be9d229..331a0df2 100644 --- a/plugins/ndf/skills/problem-solving/SKILL.md +++ b/plugins/ndf/skills/problem-solving/SKILL.md @@ -1,6 +1,6 @@ --- name: problem-solving -description: "データ不整合・バグ・障害の問題解決ガイドライン。根本原因分析の手順、上流修正優先の原則、ハルシネーション防止チェック、データとコードの整合性検証、多層防御の考え方を扱う。" +description: "不整合・バグ・障害の根本原因を解く。" when_to_use: "データ不整合 / バグ / 障害対応時に自動参照。「つじつま合わせ」を避けて上流で直す判断が必要なとき。Triggers: 'バグ修正', 'データ不整合', '障害対応', '根本原因', 'root cause analysis', 'data inconsistency', 'incident', '上流で直す', 'patch vs fix'" --- diff --git a/plugins/ndf/skills/python-execution/SKILL.md b/plugins/ndf/skills/python-execution/SKILL.md index 55f90bfa..98b98172 100644 --- a/plugins/ndf/skills/python-execution/SKILL.md +++ b/plugins/ndf/skills/python-execution/SKILL.md @@ -1,6 +1,6 @@ --- name: python-execution -description: "Python 実行環境を自動判定し、適切なコマンドで Python コードを実行する。uv / venv / システム Python を自動検出し、uv 環境のセットアップガイドも含む。" +description: "Python実行環境を判定して適切に実行する。" when_to_use: "Python スクリプトを実行 / セットアップするとき。Triggers: 'python', 'uv', 'スクリプト', 'python環境'" allowed-tools: - Read diff --git a/plugins/ndf/skills/qa-security-scan/SKILL.md b/plugins/ndf/skills/qa-security-scan/SKILL.md index ca1fa27b..4fe78289 100644 --- a/plugins/ndf/skills/qa-security-scan/SKILL.md +++ b/plugins/ndf/skills/qa-security-scan/SKILL.md @@ -1,6 +1,6 @@ --- name: qa-security-scan -description: "Security scanning templates and checklists for OWASP Top 10, authentication, authorization, data protection. Includes remediation, auth/authz testing, data protection verification, security report generation." +description: "OWASP観点でセキュリティ検証する。" when_to_use: "Use when conducting security testing or vulnerability assessment. Triggers: 'security scan', 'vulnerability check', 'OWASP', 'security test', 'セキュリティスキャン', '脆弱性チェック', 'セキュリティテスト'" --- diff --git a/plugins/ndf/skills/resolve-pr-comments/SKILL.md b/plugins/ndf/skills/resolve-pr-comments/SKILL.md index 38d1c84d..6246d900 100644 --- a/plugins/ndf/skills/resolve-pr-comments/SKILL.md +++ b/plugins/ndf/skills/resolve-pr-comments/SKILL.md @@ -1,6 +1,6 @@ --- name: resolve-pr-comments -description: "対応済みPRコメントに返信し、スレッドをresolvedにする。/ndf:fixで修正完了後のクロージング作業。修正は行わず、コメント返信とresolve操作のみ実行する。" +description: "対応済みPRコメントへ返信しresolveする。" argument-hint: "[PR番号]" disable-model-invocation: true allowed-tools: diff --git a/plugins/ndf/skills/review-branch/SKILL.md b/plugins/ndf/skills/review-branch/SKILL.md index be447dd9..41fc5e5e 100644 --- a/plugins/ndf/skills/review-branch/SKILL.md +++ b/plugins/ndf/skills/review-branch/SKILL.md @@ -1,6 +1,6 @@ --- name: review-branch -description: "現在のブランチの実装をmainとの差分でレビューする。PR作成前のセルフレビュー用途。コード品質・セキュリティ・パフォーマンス・テストの観点でフィードバックを返す。修正は行わずレビュー結果のみ報告 (READ-ONLY)。" +description: "現在ブランチをmainとの差分でレビューする。" when_to_use: "PR作成前にローカルブランチの実装をセルフレビューしたいとき。Triggers: 'ブランチをレビュー', 'PR前にレビュー', 'セルフレビュー', 'review my branch', 'review before PR', 'self review', 'pre-PR review'" argument-hint: "[focus-area] (例: security, performance, tests)" allowed-tools: diff --git a/plugins/ndf/skills/review-pr-comments/SKILL.md b/plugins/ndf/skills/review-pr-comments/SKILL.md index 52b03186..3aac971a 100644 --- a/plugins/ndf/skills/review-pr-comments/SKILL.md +++ b/plugins/ndf/skills/review-pr-comments/SKILL.md @@ -1,6 +1,6 @@ --- name: review-pr-comments -description: "既存PRの全コメントを確認し、対応可否を判定する(READ-ONLY)。修正は一切行わず、重大/改善推奨/軽微/参考/別PR対応に分類する。/ndf:fixで修正する前の優先度判定用。" +description: "既存PRコメントを読み優先度分類する。" when_to_use: "既存PRのレビューコメントを分類・優先度判定したいとき (修正前)。Triggers: 'PRコメントを確認', 'PRコメントを分類', 'コメント対応の優先度', 'PR comments review', 'classify PR comments', 'PRレビュー結果を見て'" argument-hint: "[PR番号]" allowed-tools: diff --git a/plugins/ndf/skills/review/SKILL.md b/plugins/ndf/skills/review/SKILL.md index dfce1fda..6a3f40bb 100644 --- a/plugins/ndf/skills/review/SKILL.md +++ b/plugins/ndf/skills/review/SKILL.md @@ -1,6 +1,6 @@ --- name: review -description: "PRを専門家としてレビューし、Approve/Request Changesを判定する。第二引数で外部AI(codex / gemini)への委譲も可能" +description: "PRをレビューしApprove/Request Changesを判定する。" argument-hint: "[PR番号] [AIエージェント(codex|gemini)]" disable-model-invocation: true allowed-tools: diff --git a/plugins/ndf/skills/skill-stats/SKILL.md b/plugins/ndf/skills/skill-stats/SKILL.md index 9780602a..30a75989 100644 --- a/plugins/ndf/skills/skill-stats/SKILL.md +++ b/plugins/ndf/skills/skill-stats/SKILL.md @@ -1,6 +1,6 @@ --- name: skill-stats -description: "Claude Code の transcript を集計して Skill 利用統計を算出する。呼び出し数、関連話題出現数、ヒット率を出力。特定 skill の利用傾向分析や新規 skill 候補の発見に使う。" +description: "Claude Code transcriptからSkill利用統計を出す。" when_to_use: "Skill 利用統計 / hit rate を算出したいとき。Triggers: 'skill stats', 'skill統計', 'skill利用分析', 'skill usage', 'skill hit rate'" allowed-tools: - Bash diff --git a/plugins/ndf/skills/statusline/SKILL.md b/plugins/ndf/skills/statusline/SKILL.md index eb613659..e83ad590 100644 --- a/plugins/ndf/skills/statusline/SKILL.md +++ b/plugins/ndf/skills/statusline/SKILL.md @@ -1,6 +1,6 @@ --- name: statusline -description: "NDF標準statusline(コンテナ名/ホスト名 + project_dir + コンテキスト使用率)への切り替え・復元・状態確認を行う" +description: "NDF標準statuslineを切替・復元・確認する。" when_to_use: "statuslineを切り替え/復元/確認したいとき。Triggers: 'statusline', 'ステータスライン', 'statusline 切り替え', 'statusline 戻す'" disable-model-invocation: true allowed-tools: diff --git a/plugins/ndf/skills/sync-main/SKILL.md b/plugins/ndf/skills/sync-main/SKILL.md index cb439fe7..83f09b97 100644 --- a/plugins/ndf/skills/sync-main/SKILL.md +++ b/plugins/ndf/skills/sync-main/SKILL.md @@ -1,6 +1,6 @@ --- name: sync-main -description: "最新のデフォルトブランチ(main/master)を現在のブランチに取り込むワークフロー。feature branchをmainに追従させる際に使用。" +description: "現在ブランチに最新main/masterを取り込む。" disable-model-invocation: true allowed-tools: - Bash From f45808576f369e7e19e23a0e99becae3d8ca9080 Mon Sep 17 00:00:00 2001 From: "takemi.ohama" Date: Sat, 27 Jun 2026 22:54:02 +0000 Subject: [PATCH 02/10] =?UTF-8?q?Update:=20Skill=20description=E3=82=92?= =?UTF-8?q?=E8=8B=B1=E8=AA=9E=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- plugins/ndf/skills/branch-fix-strategy/SKILL.md | 2 +- plugins/ndf/skills/browser-test/SKILL.md | 2 +- plugins/ndf/skills/cherry-pick-pr/SKILL.md | 2 +- plugins/ndf/skills/clean/SKILL.md | 2 +- plugins/ndf/skills/codex/SKILL.md | 2 +- plugins/ndf/skills/cross-review/SKILL.md | 2 +- plugins/ndf/skills/data-analyst-export/SKILL.md | 2 +- plugins/ndf/skills/data-analyst-sql-optimization/SKILL.md | 2 +- plugins/ndf/skills/deepwiki-transfer/SKILL.md | 2 +- plugins/ndf/skills/deploy/SKILL.md | 2 +- plugins/ndf/skills/docker-container-access/SKILL.md | 2 +- plugins/ndf/skills/fix/SKILL.md | 2 +- plugins/ndf/skills/gemini/SKILL.md | 2 +- plugins/ndf/skills/git-gh-operations/SKILL.md | 2 +- plugins/ndf/skills/google-auth/SKILL.md | 2 +- plugins/ndf/skills/google-chat/SKILL.md | 2 +- plugins/ndf/skills/google-drive/SKILL.md | 2 +- plugins/ndf/skills/implementation-plan/SKILL.md | 2 +- plugins/ndf/skills/investigation-rules/SKILL.md | 2 +- plugins/ndf/skills/issue-plan-strategy/SKILL.md | 2 +- plugins/ndf/skills/knowledge-reorg/SKILL.md | 2 +- plugins/ndf/skills/logging-guidelines/SKILL.md | 2 +- plugins/ndf/skills/markdown-writing/SKILL.md | 2 +- plugins/ndf/skills/mcp-builder/SKILL.md | 2 +- plugins/ndf/skills/merged/SKILL.md | 2 +- plugins/ndf/skills/ml-model-structure/SKILL.md | 2 +- plugins/ndf/skills/ndf-policies/SKILL.md | 2 +- plugins/ndf/skills/official-skills-autoloader/SKILL.md | 2 +- plugins/ndf/skills/playwright-browser-connect/SKILL.md | 2 +- plugins/ndf/skills/playwright-evidence-drive/SKILL.md | 2 +- plugins/ndf/skills/playwright-execution/SKILL.md | 2 +- plugins/ndf/skills/playwright-kit-ops/SKILL.md | 2 +- plugins/ndf/skills/playwright-report/SKILL.md | 2 +- plugins/ndf/skills/playwright-scenario-test/SKILL.md | 2 +- plugins/ndf/skills/playwright-script-creation/SKILL.md | 2 +- plugins/ndf/skills/playwright-test-planning/SKILL.md | 2 +- plugins/ndf/skills/pr-tests/SKILL.md | 2 +- plugins/ndf/skills/pr/SKILL.md | 2 +- plugins/ndf/skills/problem-solving/SKILL.md | 2 +- plugins/ndf/skills/python-execution/SKILL.md | 2 +- plugins/ndf/skills/qa-security-scan/SKILL.md | 2 +- plugins/ndf/skills/resolve-pr-comments/SKILL.md | 2 +- plugins/ndf/skills/review-branch/SKILL.md | 2 +- plugins/ndf/skills/review-pr-comments/SKILL.md | 2 +- plugins/ndf/skills/review/SKILL.md | 2 +- plugins/ndf/skills/skill-stats/SKILL.md | 2 +- plugins/ndf/skills/statusline/SKILL.md | 2 +- plugins/ndf/skills/sync-main/SKILL.md | 2 +- 48 files changed, 48 insertions(+), 48 deletions(-) diff --git a/plugins/ndf/skills/branch-fix-strategy/SKILL.md b/plugins/ndf/skills/branch-fix-strategy/SKILL.md index 852f05d7..a4714a34 100644 --- a/plugins/ndf/skills/branch-fix-strategy/SKILL.md +++ b/plugins/ndf/skills/branch-fix-strategy/SKILL.md @@ -1,6 +1,6 @@ --- name: branch-fix-strategy -description: "複数ブランチへ同じ修正を適用する戦略。" +description: "Plan multi-branch fixes and cherry-picks." when_to_use: "同じ修正を複数ブランチ (qa/staging/release等) に適用する必要があるとき。Triggers: 'cherry-pick', '環境ブランチに修正適用', 'qaに反映', 'stagingに反映', 'release branchへ', 'multi-branch fix', 'apply to qa/staging'" --- diff --git a/plugins/ndf/skills/browser-test/SKILL.md b/plugins/ndf/skills/browser-test/SKILL.md index e0c744b7..97eb0c82 100644 --- a/plugins/ndf/skills/browser-test/SKILL.md +++ b/plugins/ndf/skills/browser-test/SKILL.md @@ -1,6 +1,6 @@ --- name: browser-test -description: "ブラウザでWebアプリの動作確認を行う。" +description: "Run browser smoke tests for web apps." argument-hint: "[url]" disable-model-invocation: true allowed-tools: diff --git a/plugins/ndf/skills/cherry-pick-pr/SKILL.md b/plugins/ndf/skills/cherry-pick-pr/SKILL.md index 4b14e6c2..b5dc1341 100644 --- a/plugins/ndf/skills/cherry-pick-pr/SKILL.md +++ b/plugins/ndf/skills/cherry-pick-pr/SKILL.md @@ -1,6 +1,6 @@ --- name: cherry-pick-pr -description: "featureコミットを環境ブランチへcherry-pick PRする。" +description: "Create cherry-pick PRs for environment branches." argument-hint: " (例: qa/staging, release/v2)" disable-model-invocation: true allowed-tools: diff --git a/plugins/ndf/skills/clean/SKILL.md b/plugins/ndf/skills/clean/SKILL.md index 9cb1d235..2f75e54e 100644 --- a/plugins/ndf/skills/clean/SKILL.md +++ b/plugins/ndf/skills/clean/SKILL.md @@ -1,6 +1,6 @@ --- name: clean -description: "mainマージ済みブランチを削除する。" +description: "Delete local and remote merged branches." disable-model-invocation: true allowed-tools: - Bash diff --git a/plugins/ndf/skills/codex/SKILL.md b/plugins/ndf/skills/codex/SKILL.md index 35f7dfa2..80060a83 100644 --- a/plugins/ndf/skills/codex/SKILL.md +++ b/plugins/ndf/skills/codex/SKILL.md @@ -1,6 +1,6 @@ --- name: codex -description: "Codex CLIへコード生成・レビュー・調査を委譲する。" +description: "Delegate coding, review, or research to Codex CLI." when_to_use: "外部 AI へコード生成 / レビュー / 調査を委譲したいとき。Triggers: 'codexで調査', 'codexレビュー', '第二意見レビュー', 'codex exec', 'external AI review'" --- diff --git a/plugins/ndf/skills/cross-review/SKILL.md b/plugins/ndf/skills/cross-review/SKILL.md index 1472b12f..bc27fd86 100644 --- a/plugins/ndf/skills/cross-review/SKILL.md +++ b/plugins/ndf/skills/cross-review/SKILL.md @@ -1,6 +1,6 @@ --- name: cross-review -description: "Codex/GeminiのPRクロスレビューを自動ループする。" +description: "Run iterative Codex and Gemini PR reviews." argument-hint: "[PR番号] [--max-rounds N] [--rotate-after K] [--rotate-mode light|squash] [--only codex|gemini]" disable-model-invocation: true allowed-tools: diff --git a/plugins/ndf/skills/data-analyst-export/SKILL.md b/plugins/ndf/skills/data-analyst-export/SKILL.md index abf62eee..59e6a2d8 100644 --- a/plugins/ndf/skills/data-analyst-export/SKILL.md +++ b/plugins/ndf/skills/data-analyst-export/SKILL.md @@ -1,6 +1,6 @@ --- name: data-analyst-export -description: "分析結果をCSV/JSON/Excel/Markdownへ出力する。" +description: "Export analysis results to CSV, JSON, Excel, or Markdown." when_to_use: "Use when saving analysis results to files. Triggers: 'export data', 'save results', 'output CSV', 'output JSON', 'output Excel', 'データ出力', '結果保存', 'エクスポート'" allowed-tools: - Write diff --git a/plugins/ndf/skills/data-analyst-sql-optimization/SKILL.md b/plugins/ndf/skills/data-analyst-sql-optimization/SKILL.md index 021a6435..740130c4 100644 --- a/plugins/ndf/skills/data-analyst-sql-optimization/SKILL.md +++ b/plugins/ndf/skills/data-analyst-sql-optimization/SKILL.md @@ -1,6 +1,6 @@ --- name: data-analyst-sql-optimization -description: "SQL最適化とスロークエリ改善を行う。" +description: "Optimize SQL queries and slow database workloads." when_to_use: "Use when improving query performance or analyzing slow queries. Triggers: 'optimize SQL', 'slow query', 'improve performance', 'SQL最適化', 'クエリ改善', 'パフォーマンス向上'" --- diff --git a/plugins/ndf/skills/deepwiki-transfer/SKILL.md b/plugins/ndf/skills/deepwiki-transfer/SKILL.md index 969dcab0..c2933b7c 100644 --- a/plugins/ndf/skills/deepwiki-transfer/SKILL.md +++ b/plugins/ndf/skills/deepwiki-transfer/SKILL.md @@ -1,6 +1,6 @@ --- name: deepwiki-transfer -description: "DeepWiki内容をMarkdownへ転載する。" +description: "Transfer DeepWiki content into Markdown docs." when_to_use: "DeepWiki から Markdown としてコンテンツを取得・転載したいとき。Triggers: 'deepwiki transfer', 'deepwiki転載', 'wiki転載', 'リポジトリドキュメント取得', 'DeepWikiからMarkdown', 'transfer wiki contents'" disable-model-invocation: true allowed-tools: diff --git a/plugins/ndf/skills/deploy/SKILL.md b/plugins/ndf/skills/deploy/SKILL.md index c855e259..769919d7 100644 --- a/plugins/ndf/skills/deploy/SKILL.md +++ b/plugins/ndf/skills/deploy/SKILL.md @@ -1,6 +1,6 @@ --- name: deploy -description: "featureブランチ全体を環境ブランチへPRする。" +description: "Create deploy PRs from feature to environment branches." argument-hint: " (例: qa/staging, release/v2)" disable-model-invocation: true allowed-tools: diff --git a/plugins/ndf/skills/docker-container-access/SKILL.md b/plugins/ndf/skills/docker-container-access/SKILL.md index 97f50744..eadd1ffe 100644 --- a/plugins/ndf/skills/docker-container-access/SKILL.md +++ b/plugins/ndf/skills/docker-container-access/SKILL.md @@ -1,6 +1,6 @@ --- name: docker-container-access -description: "Dockerコンテナへの接続方法を判定する。" +description: "Diagnose Docker container access and localhost routing." when_to_use: "Docker / コンテナへのアクセス・localhost 接続不可・DinD/DooD 環境判定が必要なとき。Triggers: 'docker access', 'container connect', 'localhost not working', 'DinD', 'DooD', 'Docker接続', 'コンテナアクセス', 'curl container'" allowed-tools: - Read diff --git a/plugins/ndf/skills/fix/SKILL.md b/plugins/ndf/skills/fix/SKILL.md index 6ab4be3e..d64b97f0 100644 --- a/plugins/ndf/skills/fix/SKILL.md +++ b/plugins/ndf/skills/fix/SKILL.md @@ -1,6 +1,6 @@ --- name: fix -description: "PRレビューコメントに対応してコード修正する。" +description: "Fix actionable PR review comments." when_to_use: "PRレビューコメント (codex/gemini/人間) の指摘を実際にコード修正で対応したいとき。review-pr-comments で分類した後の修正フェーズに使う。Triggers: 'PRコメント対応', 'PRレビュー修正', 'PR fix', 'review feedback fix', 'コメントに対応して修正'" argument-hint: "[PR番号] [--defer-nit] [--severity-min critical|major|minor]" allowed-tools: diff --git a/plugins/ndf/skills/gemini/SKILL.md b/plugins/ndf/skills/gemini/SKILL.md index 5c0a80c1..e2156ed8 100644 --- a/plugins/ndf/skills/gemini/SKILL.md +++ b/plugins/ndf/skills/gemini/SKILL.md @@ -1,6 +1,6 @@ --- name: gemini -description: "Gemini CLIへコード生成・レビュー・調査を委譲する。" +description: "Delegate coding, review, or research to Gemini CLI." when_to_use: "外部 AI (Gemini)へコード生成 / レビュー / 調査を委譲したいとき。Triggers: 'geminiで調査', 'geminiレビュー', '第二意見レビュー (Gemini)', 'gemini exec', 'external AI review (Gemini)'" --- diff --git a/plugins/ndf/skills/git-gh-operations/SKILL.md b/plugins/ndf/skills/git-gh-operations/SKILL.md index 397dbafd..68b8a7a0 100644 --- a/plugins/ndf/skills/git-gh-operations/SKILL.md +++ b/plugins/ndf/skills/git-gh-operations/SKILL.md @@ -1,6 +1,6 @@ --- name: git-gh-operations -description: "git/ghコマンドのエラー対処と操作手順。" +description: "Resolve git and GitHub CLI operation errors." when_to_use: "git / gh コマンドでエラーが出た or 操作方法に迷うとき。Triggers: 'git add', 'git commit', 'git push', 'gh pr', 'gh api', 'GitHub操作', 'gitエラー', 'fatal:', 'pathspec'" allowed-tools: - Bash diff --git a/plugins/ndf/skills/google-auth/SKILL.md b/plugins/ndf/skills/google-auth/SKILL.md index 5d5c55b3..006019db 100644 --- a/plugins/ndf/skills/google-auth/SKILL.md +++ b/plugins/ndf/skills/google-auth/SKILL.md @@ -1,6 +1,6 @@ --- name: google-auth -description: "Google APIのOAuth2認証を支援する。" +description: "Set up OAuth for Google APIs." when_to_use: "Google API の OAuth2 認証が必要なときに自動参照。Triggers: 'Google認証', 'OAuth', 'google_token', 'spreadsheets', 'Google API', 'client_secret'" allowed-tools: - Read diff --git a/plugins/ndf/skills/google-chat/SKILL.md b/plugins/ndf/skills/google-chat/SKILL.md index b85be05a..cffb61cf 100644 --- a/plugins/ndf/skills/google-chat/SKILL.md +++ b/plugins/ndf/skills/google-chat/SKILL.md @@ -1,6 +1,6 @@ --- name: google-chat -description: "Google Chat APIでスペースやメッセージを取得する。" +description: "Read Google Chat spaces and messages." when_to_use: "Google Chat スペースのメッセージ取得・スペース一覧が必要なとき。Triggers: 'Google Chat', 'chat.spaces', 'chat.messages', 'Chatスペース', 'メッセージ取得', 'チャット履歴'" allowed-tools: - Read diff --git a/plugins/ndf/skills/google-drive/SKILL.md b/plugins/ndf/skills/google-drive/SKILL.md index 80e07948..48f287d3 100644 --- a/plugins/ndf/skills/google-drive/SKILL.md +++ b/plugins/ndf/skills/google-drive/SKILL.md @@ -1,6 +1,6 @@ --- name: google-drive -description: "Google Drive/Docs APIでファイル操作する。" +description: "Export, download, upload, and share Google Drive files." when_to_use: "Google Drive / Docs のファイル操作が必要なとき。Triggers: 'Google Drive', 'Google Docs', 'drive.file', 'ファイルエクスポート', 'ダウンロード', 'アップロード', '公開共有リンク'" allowed-tools: - Read diff --git a/plugins/ndf/skills/implementation-plan/SKILL.md b/plugins/ndf/skills/implementation-plan/SKILL.md index f1ac0e10..0e0a1307 100644 --- a/plugins/ndf/skills/implementation-plan/SKILL.md +++ b/plugins/ndf/skills/implementation-plan/SKILL.md @@ -1,6 +1,6 @@ --- name: implementation-plan -description: "実装プランファイルを作成・更新する。" +description: "Create or update implementation plan files." when_to_use: "実装開始時 / PR作成時に実装プランの作成・更新が必要なとき。複数ファイル変更・新機能追加・DBマイグレーションを含む変更で自動参照。Triggers: '実装プラン', '実装を開始', 'PR作成', 'implementation plan', 'plan first', '設計書を作成', 'issues/に追加'" --- diff --git a/plugins/ndf/skills/investigation-rules/SKILL.md b/plugins/ndf/skills/investigation-rules/SKILL.md index 3956ee19..a4757a83 100644 --- a/plugins/ndf/skills/investigation-rules/SKILL.md +++ b/plugins/ndf/skills/investigation-rules/SKILL.md @@ -1,6 +1,6 @@ --- name: investigation-rules -description: "調査レポート作成と裏取りのルール。" +description: "Write evidence-backed investigation and debug reports." when_to_use: "調査・デバッグ・不具合レポートを作成するとき。「ない」「該当なし」等の否定的結論を出すときは必ず参照。Triggers: '調査', 'デバッグ', '不具合レポート', '原因調査', 'investigation', 'root cause', 'カラムがない', '該当コードがない', 'データがない'" --- diff --git a/plugins/ndf/skills/issue-plan-strategy/SKILL.md b/plugins/ndf/skills/issue-plan-strategy/SKILL.md index fe7d8f83..4275a379 100644 --- a/plugins/ndf/skills/issue-plan-strategy/SKILL.md +++ b/plugins/ndf/skills/issue-plan-strategy/SKILL.md @@ -1,6 +1,6 @@ --- name: issue-plan-strategy -description: "issueからplan作成・実装運用まで扱う。" +description: "Turn issues into plans and implementation workflows." when_to_use: "issue → plan 作成 / 既存 plan の実装 (実行) を依頼されたとき。複数 PR に分割される設計や、release branch + 個別 PR + worktree 運用が必要なときに参照する。Triggers: 'issueのplanを作って', 'PLANxxの設計', '設計書を起こして', 'このplanを実装して', 'PLANxxを実装', 'planを実行', 'release branch 作って実装開始', 'multi-PR で進めて'" argument-hint: "[issue-path-or-url] (例: issues/i16.md, https://github.com/org/repo/issues/123)" allowed-tools: diff --git a/plugins/ndf/skills/knowledge-reorg/SKILL.md b/plugins/ndf/skills/knowledge-reorg/SKILL.md index d124faf4..1541f052 100644 --- a/plugins/ndf/skills/knowledge-reorg/SKILL.md +++ b/plugins/ndf/skills/knowledge-reorg/SKILL.md @@ -1,6 +1,6 @@ --- name: knowledge-reorg -description: "AGENTS.mdとSkillsを知識ポリシーで再構成する。" +description: "Reorganize AGENTS, docs, and Skills knowledge." argument-hint: "[--target AGENTS.md|skills|docs|all] [--dry-run] [--migrate-memory]" disable-model-invocation: true allowed-tools: diff --git a/plugins/ndf/skills/logging-guidelines/SKILL.md b/plugins/ndf/skills/logging-guidelines/SKILL.md index 45df0ba4..007b9691 100644 --- a/plugins/ndf/skills/logging-guidelines/SKILL.md +++ b/plugins/ndf/skills/logging-guidelines/SKILL.md @@ -1,6 +1,6 @@ --- name: logging-guidelines -description: "ログ追加・修正時の設計ガイドライン。" +description: "Design safe and useful application logging." when_to_use: "コードにログを追加・修正・整理するとき。Triggers: 'ログ追加', 'log追加', 'logger', 'logging', 'ログレベル', 'log level', 'デバッグログ', 'エラーログ', 'logger.info', 'logger.error', 'print文をログに'" --- diff --git a/plugins/ndf/skills/markdown-writing/SKILL.md b/plugins/ndf/skills/markdown-writing/SKILL.md index d3d23907..56b35839 100644 --- a/plugins/ndf/skills/markdown-writing/SKILL.md +++ b/plugins/ndf/skills/markdown-writing/SKILL.md @@ -1,6 +1,6 @@ --- name: markdown-writing -description: "Markdown文書と図表を書くためのルール。" +description: "Write Markdown docs, diagrams, and split files." when_to_use: "Markdown 文書 / 図表を作成 / 編集するとき。Triggers: 'Markdown作成', 'ドキュメント作成', '文書作成', '図を描く', 'mermaid', 'create document', 'write docs'" allowed-tools: - Read diff --git a/plugins/ndf/skills/mcp-builder/SKILL.md b/plugins/ndf/skills/mcp-builder/SKILL.md index 71c72205..1290f77e 100644 --- a/plugins/ndf/skills/mcp-builder/SKILL.md +++ b/plugins/ndf/skills/mcp-builder/SKILL.md @@ -1,6 +1,6 @@ --- name: mcp-builder -description: "MCPサーバーを設計・実装する。" +description: "Build high-quality MCP servers." license: Complete terms in LICENSE.txt --- diff --git a/plugins/ndf/skills/merged/SKILL.md b/plugins/ndf/skills/merged/SKILL.md index 1183a8e0..06af6f2a 100644 --- a/plugins/ndf/skills/merged/SKILL.md +++ b/plugins/ndf/skills/merged/SKILL.md @@ -1,6 +1,6 @@ --- name: merged -description: "PRマージ後のmain更新とブランチ削除を行う。" +description: "Clean up after a PR is merged." argument-hint: "[PR番号]" disable-model-invocation: true allowed-tools: diff --git a/plugins/ndf/skills/ml-model-structure/SKILL.md b/plugins/ndf/skills/ml-model-structure/SKILL.md index b557c7e5..d0138589 100644 --- a/plugins/ndf/skills/ml-model-structure/SKILL.md +++ b/plugins/ndf/skills/ml-model-structure/SKILL.md @@ -1,6 +1,6 @@ --- name: ml-model-structure -description: "MLモデル開発の標準ディレクトリ構造を適用する。" +description: "Structure ML training, inference, and versioned models." when_to_use: "機械学習モデルの新規構築・再学習・推論API/コンテナ開発・モデルのバージョン管理/並行運用を行うとき。analysis/ 配下に学習スクリプトや推論コードを配置する設計判断が必要なとき。Triggers: 'モデル構築', 'モデル再学習', 'モデルのバージョン管理', '推論コンテナ', '推論API', 'SageMaker', 'feature SSoT', 'train/serve skew', 'analysis ディレクトリ', 'champion challenger', '並行運用'" allowed-tools: - Read diff --git a/plugins/ndf/skills/ndf-policies/SKILL.md b/plugins/ndf/skills/ndf-policies/SKILL.md index 99dbbd1f..eb25c338 100644 --- a/plugins/ndf/skills/ndf-policies/SKILL.md +++ b/plugins/ndf/skills/ndf-policies/SKILL.md @@ -1,6 +1,6 @@ --- name: ndf-policies -description: "NDFプラグインの基本ポリシー。" +description: "Apply core NDF project policies." user-invocable: false --- diff --git a/plugins/ndf/skills/official-skills-autoloader/SKILL.md b/plugins/ndf/skills/official-skills-autoloader/SKILL.md index ca969381..a184bbea 100644 --- a/plugins/ndf/skills/official-skills-autoloader/SKILL.md +++ b/plugins/ndf/skills/official-skills-autoloader/SKILL.md @@ -1,6 +1,6 @@ --- name: official-skills-autoloader -description: "公式Skillsを必要時に自動準備して使う。" +description: "Install and use official document Skills on demand." when_to_use: "Use when user requests Word/Excel/PowerPoint/PDF creation/editing, frontend design, webapp testing, or other tasks handled by Anthropic's official skills collection. Triggers: 'Word作成', 'Excel出力', 'スライド生成', 'PDF作成', '.docx', '.pptx', '.xlsx', '.pdf', 'create docx', 'generate excel', 'make slides', 'create pdf'." allowed-tools: - Bash diff --git a/plugins/ndf/skills/playwright-browser-connect/SKILL.md b/plugins/ndf/skills/playwright-browser-connect/SKILL.md index 6efb8bdc..0607b6cc 100644 --- a/plugins/ndf/skills/playwright-browser-connect/SKILL.md +++ b/plugins/ndf/skills/playwright-browser-connect/SKILL.md @@ -1,6 +1,6 @@ --- name: playwright-browser-connect -description: "Playwrightのブラウザ接続先を構成する。" +description: "Configure Playwright browser and CDP connections." when_to_use: "E2E テストのブラウザ接続先を設定・変更するとき / remote Chrome に CDP で接続したいとき / WSL2 Docker から Windows Chrome を操作したいとき / macOS ホストの Chrome を使いたいとき。Triggers: 'ブラウザ接続', 'remote chrome', 'CDP接続', 'connectOverCDP', 'リモートブラウザ', 'Windows Chrome', 'macOS Chrome', 'mac Chrome', 'browser connect', 'cdp endpoint', 'remote debugging', 'コンテナからホスト Chrome 起動', 'host.docker.internal'" allowed-tools: - Read diff --git a/plugins/ndf/skills/playwright-evidence-drive/SKILL.md b/plugins/ndf/skills/playwright-evidence-drive/SKILL.md index 3d733e40..43a7d46a 100644 --- a/plugins/ndf/skills/playwright-evidence-drive/SKILL.md +++ b/plugins/ndf/skills/playwright-evidence-drive/SKILL.md @@ -1,6 +1,6 @@ --- name: playwright-evidence-drive -description: "Playwright証跡をGoogle Driveへ保管する。" +description: "Upload Playwright evidence to Google Drive." when_to_use: "テストエビデンスを Google Drive に保管・共有したいとき / テスト結果を Google Docs としてチームに配布したいとき / Drive 上のエビデンスリンクを report に埋め込みたいとき。Triggers: 'Drive にアップロード', 'Drive 共有', 'エビデンス保管', 'evidence drive', 'pwk-drive-folder', 'テスト結果共有', 'Google Drive エビデンス', 'trace アップロード', '動画アップロード', 'report を Docs に', 'エビデンス配布'" allowed-tools: - Read diff --git a/plugins/ndf/skills/playwright-execution/SKILL.md b/plugins/ndf/skills/playwright-execution/SKILL.md index a80bc7f6..f99970cd 100644 --- a/plugins/ndf/skills/playwright-execution/SKILL.md +++ b/plugins/ndf/skills/playwright-execution/SKILL.md @@ -1,6 +1,6 @@ --- name: playwright-execution -description: "Playwright E2Eを実行し証跡と品質指標を収集する。" +description: "Run Playwright E2E tests with evidence and metrics." when_to_use: "E2E テストの実行 / エビデンス収集 / 動画エビデンス / accessibility チェック / Core Web Vitals 計測が必要なとき。テストスクリプト作成済みであることが前提。Triggers: 'E2E テスト実行', 'テスト実行', '動画エビデンス', 'エビデンス収集', 'テスト証跡', 'a11y テスト', 'accessibility テスト', 'axe-core', 'WCAG', 'Core Web Vitals', 'Web Vitals', 'LCP', 'CLS', 'body_check', 'overlay', '字幕', 'カーソル'" allowed-tools: - Read diff --git a/plugins/ndf/skills/playwright-kit-ops/SKILL.md b/plugins/ndf/skills/playwright-kit-ops/SKILL.md index efef7e94..3332ba64 100644 --- a/plugins/ndf/skills/playwright-kit-ops/SKILL.md +++ b/plugins/ndf/skills/playwright-kit-ops/SKILL.md @@ -1,6 +1,6 @@ --- name: playwright-kit-ops -description: "playwright_kitの初期化・実行・証跡操作を行う。" +description: "Operate playwright_kit setup, scans, and evidence tools." when_to_use: "playwright_kit のスクリプトを実行するとき / E2E テストプロジェクトの初期化 / page role 自動分類 / 単発 a11y・CWV スキャン / Google Drive エビデンスアップロードが必要なとき。Triggers: 'init_project', 'プロジェクト初期化', 'classify_page_role', 'run_a11y_scan', 'check_cwv', 'upload_evidence', 'record_scenario', 'playwright_kit 実行'" allowed-tools: - Read diff --git a/plugins/ndf/skills/playwright-report/SKILL.md b/plugins/ndf/skills/playwright-report/SKILL.md index 5393cb45..2f8897a7 100644 --- a/plugins/ndf/skills/playwright-report/SKILL.md +++ b/plugins/ndf/skills/playwright-report/SKILL.md @@ -1,6 +1,6 @@ --- name: playwright-report -description: "Playwrightテスト結果レポートを生成する。" +description: "Generate Playwright test result reports." when_to_use: "テストレポートの生成 / テスト結果の共有が必要なとき。Triggers: 'テストレポート', 'report.md', 'テスト結果', 'テスト報告書', 'レポート生成', 'テスト結果まとめ'" allowed-tools: - Read diff --git a/plugins/ndf/skills/playwright-scenario-test/SKILL.md b/plugins/ndf/skills/playwright-scenario-test/SKILL.md index a3f3be01..3edfc45a 100644 --- a/plugins/ndf/skills/playwright-scenario-test/SKILL.md +++ b/plugins/ndf/skills/playwright-scenario-test/SKILL.md @@ -1,6 +1,6 @@ --- name: playwright-scenario-test -description: "pytest-playwrightのフルE2Eワークフローを統括する。" +description: "Orchestrate full pytest-playwright scenario testing." when_to_use: "フル E2E テストワークフロー (計画→スクリプト→実行→レポート) を一貫して行うとき / pytest-playwright 拡張 fixture (pwk_*) の全体像を把握したいとき / init_project.sh でプロジェクトをセットアップするとき。Triggers: 'pytest-playwright', 'pwk_role', 'pwk_evidence', 'init_project', 'シナリオテスト一式', 'フル E2E'" allowed-tools: - Read diff --git a/plugins/ndf/skills/playwright-script-creation/SKILL.md b/plugins/ndf/skills/playwright-script-creation/SKILL.md index 24e43bdc..a42c0a8f 100644 --- a/plugins/ndf/skills/playwright-script-creation/SKILL.md +++ b/plugins/ndf/skills/playwright-script-creation/SKILL.md @@ -1,6 +1,6 @@ --- name: playwright-script-creation -description: "再現可能なE2Eテストスクリプトを作成する。" +description: "Create reproducible Playwright E2E test scripts." when_to_use: "E2E テストスクリプトの作成 / テストコードの実装 / テストテンプレートからのスクリプト生成が必要なとき。Triggers: 'テストスクリプト作成', 'テストコード作成', 'テスト実装', 'テストを書く', 'シナリオ作成', 'codegen', 'テンプレートからテスト', 'playwright codegen'" allowed-tools: - Read diff --git a/plugins/ndf/skills/playwright-test-planning/SKILL.md b/plugins/ndf/skills/playwright-test-planning/SKILL.md index bd59aa0a..a0810adc 100644 --- a/plugins/ndf/skills/playwright-test-planning/SKILL.md +++ b/plugins/ndf/skills/playwright-test-planning/SKILL.md @@ -1,6 +1,6 @@ --- name: playwright-test-planning -description: "E2Eテスト計画とpage role分類を行う。" +description: "Plan E2E tests and classify page roles." when_to_use: "E2E テストの計画立案 / page role 分類 / テスト技法の選定 / チェックリスト活用が必要なとき。Triggers: 'テスト計画', 'テスト計画立案', 'page role', 'HTSM', 'ISTQB', 'FEW HICCUPPS', 'チェックリスト', 'テスト技法', 'テスト設計'" allowed-tools: - Read diff --git a/plugins/ndf/skills/pr-tests/SKILL.md b/plugins/ndf/skills/pr-tests/SKILL.md index cdc04506..39f13de3 100644 --- a/plugins/ndf/skills/pr-tests/SKILL.md +++ b/plugins/ndf/skills/pr-tests/SKILL.md @@ -1,6 +1,6 @@ --- name: pr-tests -description: "PRのTest Planを実行し結果をコメントする。" +description: "Run PR test plans and comment results." argument-hint: "[PR番号]" disable-model-invocation: true allowed-tools: diff --git a/plugins/ndf/skills/pr/SKILL.md b/plugins/ndf/skills/pr/SKILL.md index 9e8c6701..22000e4c 100644 --- a/plugins/ndf/skills/pr/SKILL.md +++ b/plugins/ndf/skills/pr/SKILL.md @@ -1,6 +1,6 @@ --- name: pr -description: "commit/push/PR作成またはPR説明更新を行う。" +description: "Commit, push, and create or update PRs." argument-hint: "[--draft] [base-branch] or [commit-message]" disable-model-invocation: true allowed-tools: diff --git a/plugins/ndf/skills/problem-solving/SKILL.md b/plugins/ndf/skills/problem-solving/SKILL.md index 331a0df2..1b3c1108 100644 --- a/plugins/ndf/skills/problem-solving/SKILL.md +++ b/plugins/ndf/skills/problem-solving/SKILL.md @@ -1,6 +1,6 @@ --- name: problem-solving -description: "不整合・バグ・障害の根本原因を解く。" +description: "Solve bugs, incidents, and data inconsistencies at root cause." when_to_use: "データ不整合 / バグ / 障害対応時に自動参照。「つじつま合わせ」を避けて上流で直す判断が必要なとき。Triggers: 'バグ修正', 'データ不整合', '障害対応', '根本原因', 'root cause analysis', 'data inconsistency', 'incident', '上流で直す', 'patch vs fix'" --- diff --git a/plugins/ndf/skills/python-execution/SKILL.md b/plugins/ndf/skills/python-execution/SKILL.md index 98b98172..a07705aa 100644 --- a/plugins/ndf/skills/python-execution/SKILL.md +++ b/plugins/ndf/skills/python-execution/SKILL.md @@ -1,6 +1,6 @@ --- name: python-execution -description: "Python実行環境を判定して適切に実行する。" +description: "Detect and run the right Python environment." when_to_use: "Python スクリプトを実行 / セットアップするとき。Triggers: 'python', 'uv', 'スクリプト', 'python環境'" allowed-tools: - Read diff --git a/plugins/ndf/skills/qa-security-scan/SKILL.md b/plugins/ndf/skills/qa-security-scan/SKILL.md index 4fe78289..f8e86e93 100644 --- a/plugins/ndf/skills/qa-security-scan/SKILL.md +++ b/plugins/ndf/skills/qa-security-scan/SKILL.md @@ -1,6 +1,6 @@ --- name: qa-security-scan -description: "OWASP観点でセキュリティ検証する。" +description: "Run OWASP-focused security checks." when_to_use: "Use when conducting security testing or vulnerability assessment. Triggers: 'security scan', 'vulnerability check', 'OWASP', 'security test', 'セキュリティスキャン', '脆弱性チェック', 'セキュリティテスト'" --- diff --git a/plugins/ndf/skills/resolve-pr-comments/SKILL.md b/plugins/ndf/skills/resolve-pr-comments/SKILL.md index 6246d900..433a72d6 100644 --- a/plugins/ndf/skills/resolve-pr-comments/SKILL.md +++ b/plugins/ndf/skills/resolve-pr-comments/SKILL.md @@ -1,6 +1,6 @@ --- name: resolve-pr-comments -description: "対応済みPRコメントへ返信しresolveする。" +description: "Reply to and resolve fixed PR comments." argument-hint: "[PR番号]" disable-model-invocation: true allowed-tools: diff --git a/plugins/ndf/skills/review-branch/SKILL.md b/plugins/ndf/skills/review-branch/SKILL.md index 41fc5e5e..951e5ea1 100644 --- a/plugins/ndf/skills/review-branch/SKILL.md +++ b/plugins/ndf/skills/review-branch/SKILL.md @@ -1,6 +1,6 @@ --- name: review-branch -description: "現在ブランチをmainとの差分でレビューする。" +description: "Review the current branch before opening a PR." when_to_use: "PR作成前にローカルブランチの実装をセルフレビューしたいとき。Triggers: 'ブランチをレビュー', 'PR前にレビュー', 'セルフレビュー', 'review my branch', 'review before PR', 'self review', 'pre-PR review'" argument-hint: "[focus-area] (例: security, performance, tests)" allowed-tools: diff --git a/plugins/ndf/skills/review-pr-comments/SKILL.md b/plugins/ndf/skills/review-pr-comments/SKILL.md index 3aac971a..f6dc5643 100644 --- a/plugins/ndf/skills/review-pr-comments/SKILL.md +++ b/plugins/ndf/skills/review-pr-comments/SKILL.md @@ -1,6 +1,6 @@ --- name: review-pr-comments -description: "既存PRコメントを読み優先度分類する。" +description: "Classify existing PR comments before fixing." when_to_use: "既存PRのレビューコメントを分類・優先度判定したいとき (修正前)。Triggers: 'PRコメントを確認', 'PRコメントを分類', 'コメント対応の優先度', 'PR comments review', 'classify PR comments', 'PRレビュー結果を見て'" argument-hint: "[PR番号]" allowed-tools: diff --git a/plugins/ndf/skills/review/SKILL.md b/plugins/ndf/skills/review/SKILL.md index 6a3f40bb..cfb920ba 100644 --- a/plugins/ndf/skills/review/SKILL.md +++ b/plugins/ndf/skills/review/SKILL.md @@ -1,6 +1,6 @@ --- name: review -description: "PRをレビューしApprove/Request Changesを判定する。" +description: "Review PRs and post approve or changes verdicts." argument-hint: "[PR番号] [AIエージェント(codex|gemini)]" disable-model-invocation: true allowed-tools: diff --git a/plugins/ndf/skills/skill-stats/SKILL.md b/plugins/ndf/skills/skill-stats/SKILL.md index 30a75989..f89b6135 100644 --- a/plugins/ndf/skills/skill-stats/SKILL.md +++ b/plugins/ndf/skills/skill-stats/SKILL.md @@ -1,6 +1,6 @@ --- name: skill-stats -description: "Claude Code transcriptからSkill利用統計を出す。" +description: "Analyze Skill usage from Claude Code transcripts." when_to_use: "Skill 利用統計 / hit rate を算出したいとき。Triggers: 'skill stats', 'skill統計', 'skill利用分析', 'skill usage', 'skill hit rate'" allowed-tools: - Bash diff --git a/plugins/ndf/skills/statusline/SKILL.md b/plugins/ndf/skills/statusline/SKILL.md index e83ad590..52d5288f 100644 --- a/plugins/ndf/skills/statusline/SKILL.md +++ b/plugins/ndf/skills/statusline/SKILL.md @@ -1,6 +1,6 @@ --- name: statusline -description: "NDF標準statuslineを切替・復元・確認する。" +description: "Switch, restore, or inspect the NDF statusline." when_to_use: "statuslineを切り替え/復元/確認したいとき。Triggers: 'statusline', 'ステータスライン', 'statusline 切り替え', 'statusline 戻す'" disable-model-invocation: true allowed-tools: diff --git a/plugins/ndf/skills/sync-main/SKILL.md b/plugins/ndf/skills/sync-main/SKILL.md index 83f09b97..87aa2230 100644 --- a/plugins/ndf/skills/sync-main/SKILL.md +++ b/plugins/ndf/skills/sync-main/SKILL.md @@ -1,6 +1,6 @@ --- name: sync-main -description: "現在ブランチに最新main/masterを取り込む。" +description: "Sync the current branch with main or master." disable-model-invocation: true allowed-tools: - Bash From 0ed1a2f1f1109fcbe737d1762f270cc14a16174b Mon Sep 17 00:00:00 2001 From: "takemi.ohama" Date: Sat, 27 Jun 2026 23:13:01 +0000 Subject: [PATCH 03/10] =?UTF-8?q?Update:=20Claude=E3=81=A8Codex=E3=81=AESk?= =?UTF-8?q?ill=E6=A7=8B=E6=88=90=E3=82=92=E5=88=86=E9=9B=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 11 +- docs/ndf-plugin-reference.md | 7 +- docs/project-overview.md | 4 + plugins/ndf/.claude-plugin/plugin.json | 76 +-- plugins/ndf/.codex-plugin/plugin.json | 2 +- plugins/ndf/AGENTS.md | 70 +-- plugins/ndf/README.md | 8 +- .../branch-fix-strategy/SKILL.md | 87 ++++ .../ndf/skills-claude/browser-test/SKILL.md | 159 ++++++ .../ndf/skills-claude/cherry-pick-pr/SKILL.md | 120 +++++ plugins/ndf/skills-claude/clean/SKILL.md | 20 + plugins/ndf/skills-claude/codex/SKILL.md | 473 ++++++++++++++++++ plugins/ndf/skills-claude/deploy/SKILL.md | 114 +++++ .../01-environment-detection.md | 84 ++++ .../docker-container-access/02-dood-access.md | 134 +++++ .../03-troubleshooting.md | 63 +++ .../docker-container-access/SKILL.md | 76 +++ plugins/ndf/skills-claude/fix/SKILL.md | 303 +++++++++++ .../fix/scripts/fetch-pr-comments.sh | 47 ++ .../git-gh-operations/01-common-errors.md | 145 ++++++ .../skills-claude/git-gh-operations/SKILL.md | 228 +++++++++ .../implementation-plan/SKILL.md | 98 ++++ .../investigation-rules/SKILL.md | 105 ++++ .../issue-plan-strategy/SKILL.md | 335 +++++++++++++ .../skills-claude/logging-guidelines/SKILL.md | 112 +++++ .../markdown-writing/01-diagram-guide.md | 144 ++++++ .../skills-claude/markdown-writing/SKILL.md | 58 +++ plugins/ndf/skills-claude/merged/SKILL.md | 29 ++ .../ndf/skills-claude/ndf-policies/SKILL.md | 10 + plugins/ndf/skills-claude/pr-tests/SKILL.md | 31 ++ plugins/ndf/skills-claude/pr/SKILL.md | 161 ++++++ .../skills-claude/problem-solving/SKILL.md | 162 ++++++ .../python-execution/01-uv-setup.md | 85 ++++ .../python-execution/02-troubleshooting.md | 112 +++++ .../skills-claude/python-execution/SKILL.md | 86 ++++ .../resolve-pr-comments/SKILL.md | 146 ++++++ .../ndf/skills-claude/review-branch/SKILL.md | 129 +++++ .../skills-claude/review-pr-comments/SKILL.md | 110 ++++ plugins/ndf/skills-claude/review/SKILL.md | 337 +++++++++++++ plugins/ndf/skills-claude/statusline/SKILL.md | 49 ++ .../statusline/tests/__init__.py | 0 .../tests/test_statusline_switch.py | 150 ++++++ plugins/ndf/skills-claude/sync-main/SKILL.md | 48 ++ .../skills-codex/branch-fix-strategy/SKILL.md | 87 ++++ .../ndf/skills-codex/cherry-pick-pr/SKILL.md | 120 +++++ plugins/ndf/skills-codex/clean/SKILL.md | 20 + plugins/ndf/skills-codex/deploy/SKILL.md | 114 +++++ .../01-environment-detection.md | 84 ++++ .../docker-container-access/02-dood-access.md | 134 +++++ .../03-troubleshooting.md | 63 +++ .../docker-container-access/SKILL.md | 76 +++ plugins/ndf/skills-codex/fix/SKILL.md | 303 +++++++++++ .../fix/scripts/fetch-pr-comments.sh | 47 ++ .../git-gh-operations/01-common-errors.md | 145 ++++++ .../skills-codex/git-gh-operations/SKILL.md | 228 +++++++++ .../skills-codex/implementation-plan/SKILL.md | 98 ++++ .../skills-codex/investigation-rules/SKILL.md | 105 ++++ .../skills-codex/issue-plan-strategy/SKILL.md | 335 +++++++++++++ .../skills-codex/logging-guidelines/SKILL.md | 112 +++++ .../markdown-writing/01-diagram-guide.md | 144 ++++++ .../skills-codex/markdown-writing/SKILL.md | 58 +++ plugins/ndf/skills-codex/merged/SKILL.md | 29 ++ .../ndf/skills-codex/ndf-policies/SKILL.md | 10 + .../playwright-execution/SKILL.md | 101 ++++ .../skills-codex/playwright-report/SKILL.md | 55 ++ .../playwright-script-creation/SKILL.md | 108 ++++ .../playwright-test-planning/SKILL.md | 97 ++++ .../docs/01-methodology.md | 148 ++++++ .../docs/02-page-roles.md | 207 ++++++++ .../docs/03-test-techniques.md | 284 +++++++++++ .../docs/04-playwright-mapping.md | 249 +++++++++ .../docs/05-bug-report.md | 207 ++++++++ .../docs/06-pytest-playwright.md | 246 +++++++++ .../playwright-test-planning/docs/README.md | 79 +++ .../docs/checklists/checklist-auth.md | 148 ++++++ .../checklists/checklist-cart-checkout.md | 158 ++++++ .../docs/checklists/checklist-common.md | 129 +++++ .../docs/checklists/checklist-dashboard.md | 124 +++++ .../docs/checklists/checklist-edit.md | 156 ++++++ .../docs/checklists/checklist-form.md | 160 ++++++ .../docs/checklists/checklist-item.md | 120 +++++ .../docs/checklists/checklist-list.md | Bin 0 -> 6301 bytes .../docs/checklists/checklist-lp.md | 97 ++++ .../docs/checklists/checklist-modal-wizard.md | 161 ++++++ .../docs/checklists/checklist-search.md | 134 +++++ plugins/ndf/skills-codex/pr-tests/SKILL.md | 31 ++ plugins/ndf/skills-codex/pr/SKILL.md | 161 ++++++ .../ndf/skills-codex/problem-solving/SKILL.md | 162 ++++++ .../python-execution/01-uv-setup.md | 85 ++++ .../python-execution/02-troubleshooting.md | 112 +++++ .../skills-codex/python-execution/SKILL.md | 86 ++++ .../skills-codex/resolve-pr-comments/SKILL.md | 146 ++++++ .../ndf/skills-codex/review-branch/SKILL.md | 129 +++++ .../skills-codex/review-pr-comments/SKILL.md | 110 ++++ plugins/ndf/skills-codex/review/SKILL.md | 337 +++++++++++++ plugins/ndf/skills-codex/sync-main/SKILL.md | 48 ++ plugins/ndf/skills-optional/README.md | 43 ++ plugins/ndf/skills/fix/SKILL.md | 2 +- .../ndf/skills/review-pr-comments/SKILL.md | 2 +- scripts/install-kiro.sh | 8 +- 100 files changed, 11549 insertions(+), 121 deletions(-) create mode 100644 plugins/ndf/skills-claude/branch-fix-strategy/SKILL.md create mode 100644 plugins/ndf/skills-claude/browser-test/SKILL.md create mode 100644 plugins/ndf/skills-claude/cherry-pick-pr/SKILL.md create mode 100644 plugins/ndf/skills-claude/clean/SKILL.md create mode 100644 plugins/ndf/skills-claude/codex/SKILL.md create mode 100644 plugins/ndf/skills-claude/deploy/SKILL.md create mode 100644 plugins/ndf/skills-claude/docker-container-access/01-environment-detection.md create mode 100644 plugins/ndf/skills-claude/docker-container-access/02-dood-access.md create mode 100644 plugins/ndf/skills-claude/docker-container-access/03-troubleshooting.md create mode 100644 plugins/ndf/skills-claude/docker-container-access/SKILL.md create mode 100644 plugins/ndf/skills-claude/fix/SKILL.md create mode 100755 plugins/ndf/skills-claude/fix/scripts/fetch-pr-comments.sh create mode 100644 plugins/ndf/skills-claude/git-gh-operations/01-common-errors.md create mode 100644 plugins/ndf/skills-claude/git-gh-operations/SKILL.md create mode 100644 plugins/ndf/skills-claude/implementation-plan/SKILL.md create mode 100644 plugins/ndf/skills-claude/investigation-rules/SKILL.md create mode 100644 plugins/ndf/skills-claude/issue-plan-strategy/SKILL.md create mode 100644 plugins/ndf/skills-claude/logging-guidelines/SKILL.md create mode 100644 plugins/ndf/skills-claude/markdown-writing/01-diagram-guide.md create mode 100644 plugins/ndf/skills-claude/markdown-writing/SKILL.md create mode 100644 plugins/ndf/skills-claude/merged/SKILL.md create mode 100644 plugins/ndf/skills-claude/ndf-policies/SKILL.md create mode 100644 plugins/ndf/skills-claude/pr-tests/SKILL.md create mode 100644 plugins/ndf/skills-claude/pr/SKILL.md create mode 100644 plugins/ndf/skills-claude/problem-solving/SKILL.md create mode 100644 plugins/ndf/skills-claude/python-execution/01-uv-setup.md create mode 100644 plugins/ndf/skills-claude/python-execution/02-troubleshooting.md create mode 100644 plugins/ndf/skills-claude/python-execution/SKILL.md create mode 100644 plugins/ndf/skills-claude/resolve-pr-comments/SKILL.md create mode 100644 plugins/ndf/skills-claude/review-branch/SKILL.md create mode 100644 plugins/ndf/skills-claude/review-pr-comments/SKILL.md create mode 100644 plugins/ndf/skills-claude/review/SKILL.md create mode 100644 plugins/ndf/skills-claude/statusline/SKILL.md create mode 100644 plugins/ndf/skills-claude/statusline/tests/__init__.py create mode 100644 plugins/ndf/skills-claude/statusline/tests/test_statusline_switch.py create mode 100644 plugins/ndf/skills-claude/sync-main/SKILL.md create mode 100644 plugins/ndf/skills-codex/branch-fix-strategy/SKILL.md create mode 100644 plugins/ndf/skills-codex/cherry-pick-pr/SKILL.md create mode 100644 plugins/ndf/skills-codex/clean/SKILL.md create mode 100644 plugins/ndf/skills-codex/deploy/SKILL.md create mode 100644 plugins/ndf/skills-codex/docker-container-access/01-environment-detection.md create mode 100644 plugins/ndf/skills-codex/docker-container-access/02-dood-access.md create mode 100644 plugins/ndf/skills-codex/docker-container-access/03-troubleshooting.md create mode 100644 plugins/ndf/skills-codex/docker-container-access/SKILL.md create mode 100644 plugins/ndf/skills-codex/fix/SKILL.md create mode 100755 plugins/ndf/skills-codex/fix/scripts/fetch-pr-comments.sh create mode 100644 plugins/ndf/skills-codex/git-gh-operations/01-common-errors.md create mode 100644 plugins/ndf/skills-codex/git-gh-operations/SKILL.md create mode 100644 plugins/ndf/skills-codex/implementation-plan/SKILL.md create mode 100644 plugins/ndf/skills-codex/investigation-rules/SKILL.md create mode 100644 plugins/ndf/skills-codex/issue-plan-strategy/SKILL.md create mode 100644 plugins/ndf/skills-codex/logging-guidelines/SKILL.md create mode 100644 plugins/ndf/skills-codex/markdown-writing/01-diagram-guide.md create mode 100644 plugins/ndf/skills-codex/markdown-writing/SKILL.md create mode 100644 plugins/ndf/skills-codex/merged/SKILL.md create mode 100644 plugins/ndf/skills-codex/ndf-policies/SKILL.md create mode 100644 plugins/ndf/skills-codex/playwright-execution/SKILL.md create mode 100644 plugins/ndf/skills-codex/playwright-report/SKILL.md create mode 100644 plugins/ndf/skills-codex/playwright-script-creation/SKILL.md create mode 100644 plugins/ndf/skills-codex/playwright-test-planning/SKILL.md create mode 100644 plugins/ndf/skills-codex/playwright-test-planning/docs/01-methodology.md create mode 100644 plugins/ndf/skills-codex/playwright-test-planning/docs/02-page-roles.md create mode 100644 plugins/ndf/skills-codex/playwright-test-planning/docs/03-test-techniques.md create mode 100644 plugins/ndf/skills-codex/playwright-test-planning/docs/04-playwright-mapping.md create mode 100644 plugins/ndf/skills-codex/playwright-test-planning/docs/05-bug-report.md create mode 100644 plugins/ndf/skills-codex/playwright-test-planning/docs/06-pytest-playwright.md create mode 100644 plugins/ndf/skills-codex/playwright-test-planning/docs/README.md create mode 100644 plugins/ndf/skills-codex/playwright-test-planning/docs/checklists/checklist-auth.md create mode 100644 plugins/ndf/skills-codex/playwright-test-planning/docs/checklists/checklist-cart-checkout.md create mode 100644 plugins/ndf/skills-codex/playwright-test-planning/docs/checklists/checklist-common.md create mode 100644 plugins/ndf/skills-codex/playwright-test-planning/docs/checklists/checklist-dashboard.md create mode 100644 plugins/ndf/skills-codex/playwright-test-planning/docs/checklists/checklist-edit.md create mode 100644 plugins/ndf/skills-codex/playwright-test-planning/docs/checklists/checklist-form.md create mode 100644 plugins/ndf/skills-codex/playwright-test-planning/docs/checklists/checklist-item.md create mode 100644 plugins/ndf/skills-codex/playwright-test-planning/docs/checklists/checklist-list.md create mode 100644 plugins/ndf/skills-codex/playwright-test-planning/docs/checklists/checklist-lp.md create mode 100644 plugins/ndf/skills-codex/playwright-test-planning/docs/checklists/checklist-modal-wizard.md create mode 100644 plugins/ndf/skills-codex/playwright-test-planning/docs/checklists/checklist-search.md create mode 100644 plugins/ndf/skills-codex/pr-tests/SKILL.md create mode 100644 plugins/ndf/skills-codex/pr/SKILL.md create mode 100644 plugins/ndf/skills-codex/problem-solving/SKILL.md create mode 100644 plugins/ndf/skills-codex/python-execution/01-uv-setup.md create mode 100644 plugins/ndf/skills-codex/python-execution/02-troubleshooting.md create mode 100644 plugins/ndf/skills-codex/python-execution/SKILL.md create mode 100644 plugins/ndf/skills-codex/resolve-pr-comments/SKILL.md create mode 100644 plugins/ndf/skills-codex/review-branch/SKILL.md create mode 100644 plugins/ndf/skills-codex/review-pr-comments/SKILL.md create mode 100644 plugins/ndf/skills-codex/review/SKILL.md create mode 100644 plugins/ndf/skills-codex/sync-main/SKILL.md create mode 100644 plugins/ndf/skills-optional/README.md diff --git a/README.md b/README.md index 591b1c95..1494a80d 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,8 @@ Claude Code / Codex / Kiro CLI向けのスキル・MCP設定を共有するた **NDFプラグイン v4.16.1** は、以下の機能を**オールインワン**で提供する統合プラグインです: -- **48個のSkills**: +- **公開Skills**: Claude Code/Kiro向け core 26個、Codex向け core 27個に分離。`skills-optional/` にランタイム別の除外候補を整理。 +- **元Skills(48個)**: - PR/レビューワークフロー (13): pr, pr-tests, fix, review, review-branch, review-pr-comments, resolve-pr-comments, cherry-pick-pr, deploy, sync-main, merged, clean, browser-test - 原則・ガイドライン (9): ndf-policies, branch-fix-strategy, implementation-plan, investigation-rules, problem-solving, logging-guidelines, markdown-writing, issue-plan-strategy, ml-model-structure - データ分析・品質・環境 (12): data-analyst-sql-optimization, data-analyst-export, qa-security-scan, python-execution, docker-container-access, git-gh-operations, google-auth, codex, deepwiki-transfer, knowledge-reorg, mcp-builder, official-skills-autoloader @@ -97,7 +98,7 @@ kiro-cli chat | プラグイン名 | バージョン | 説明 | 詳細 | |------------|----------|------|------| -| **ndf** | 4.16.1 | Claude Code / Codex / Kiro CLI開発環境を**オールインワン**で強化する統合プラグイン。8個の専門エージェント(director、data-analyst、corder、researcher、qa、debugger、devops-engineer、code-reviewer)、48個のSkills(PR/レビューワークフロー、原則・ガイドライン、MLモデル構造標準、データ分析、品質、Playwright E2E(CDPリモート接続・Google Driveエビデンス保管含む)、Google連携、AIクロスレビュー、Codex CLI連携、skill利用統計など)、SessionStartフック(transcript保持期間自動管理)、Stopフック(AI要約生成+Slack通知)を提供。v4.0.0 で Codex MCP サーバを廃止し、`/ndf:codex` skill + `corder` エージェント経由の CLI 直接実行に一本化。 | [README](./plugins/ndf/README.md) | +| **ndf** | 4.16.1 | Claude Code / Codex / Kiro CLI開発環境を**オールインワン**で強化する統合プラグイン。8個の専門エージェント(director、data-analyst、corder、researcher、qa、debugger、devops-engineer、code-reviewer)、公開Skills(Claude Code/Kiro向け core 26個、Codex向け core 27個)、SessionStartフック(transcript保持期間自動管理)、Stopフック(AI要約生成+Slack通知)を提供。v4.0.0 で Codex MCP サーバを廃止し、`/ndf:codex` skill + `corder` エージェント経由の CLI 直接実行に一本化。 | [README](./plugins/ndf/README.md) | ## 開発ガイドライン @@ -118,9 +119,11 @@ ai-plugins/ │ │ └── plugin.json # Codexプラグインメタデータ │ ├── .claude-plugin/ │ │ └── plugin.json # Claude Codeプラグインメタデータ -│ ├── commands/ # スラッシュコマンド (*.md) │ ├── agents/ # サブエージェント (*.md) -│ └── skills/ # プロジェクトスキル +│ ├── skills/ # 全Skillの実体 +│ ├── skills-claude/ # Claude Code/Kiro向け公開Skill +│ ├── skills-codex/ # Codex向け公開Skill +│ └── skills-optional/ # ランタイム別除外候補リスト │ └── {skill-name}/ │ └── SKILL.md # エントリポイント(必須) ├── README.md diff --git a/docs/ndf-plugin-reference.md b/docs/ndf-plugin-reference.md index c9bf22da..316209e9 100644 --- a/docs/ndf-plugin-reference.md +++ b/docs/ndf-plugin-reference.md @@ -2,7 +2,7 @@ ## 概要 -NDF プラグインは、Claude Code / Kiro CLI 向けのオールインワン開発支援プラグイン。エージェント、Skills、フックを統合して提供する。 +NDF プラグインは、Claude Code / Codex / Kiro CLI 向けのオールインワン開発支援プラグイン。エージェント、Skills、フックを統合して提供する。 **現行バージョン**: **v4.16.1** — statusline: NDF 由来の旧コピー(マーカー付き / レガシー `statusline-command.sh`)を `settings.json` が指す場合、SessionStart で正規パス(`~/.claude/ndf-statusline.sh`)へ自動移行しバージョンアップ追従を回復(ユーザー独自 statusline は誤検出ガードで保護)。**v4.16.0** で statusline の `[ctx:` 固定ラベルを利用モデル表示名(例 `Opus 4.8`)に置換(取得不可時は `ctx` にフォールバック)。**v4.15.0** で cross-review の worktree 生成先を非永続領域 `<システム tmpdir>/ndf-worktrees/--/pr` に変更(永続 volume 消費・他リポジトリの PR 番号衝突・残骸流用事故を解消。`NDF_WORKTREE_BASE` env で明示オーバーライド可)。**v4.14.0** で `statusline` skill とデフォルト statusline 設定 hook を追加(47→48個)。statusLine 未設定時のみ NDF 標準 statusline(コンテナ名/ホスト名 + project_dir + コンテキスト使用率)を自動設定し、`/ndf:statusline set|restore|status` で切り替え・復元できる。**v4.13.0** で `issue-plan-strategy` の release PR body を self-contained 必須化。**v4.12.0** で Playwright E2E に `/ndf:playwright-browser-connect`(CDP リモートブラウザ接続)と `/ndf:playwright-evidence-drive`(Google Drive エビデンスアーカイブ)の 2 skill を追加(45→47個)。直前の **v4.11.0** で `/ndf:cross-review` の堅牢性改善(monitor.py の EARLY_ERROR 誤検知を解消: テスト用文字列リテラル / grep 形式ソース引用行を benign 自動判定し、ループ終了時の最終スイープで残 open review thread を全 Resolve)を実施。**v4.10.0** で `ml-model-structure` skill(MLモデル構築・推論API開発の標準ディレクトリ構造: 版内feature SSoT / train↔serve契約)を追加。`/ndf:fix` の修正ポリシー刷新(minor/nit のうち performance/readability/duplication は積極修正、+30 行超は要問い合わせ)、CI 完了待ち廃止、PR範囲外 flaky テストも修正対象。`/ndf:cross-review` 内のサブエージェントプロンプトも同期。重要度ラベルは AI agent の付与を鵜呑みにせず独自再判定。完了報告には PR URL 必須。詳細は [CHANGELOG.md](../plugins/ndf/CHANGELOG.md)。`/ndf:codex` skill + `corder` エージェント経由の Codex CLI 直接実行に一本化、Serena MCP は別プラグイン `mcp-serena` に分離済み、Playwright シナリオ E2E、Google Drive / Chat 連携 skill を提供。 @@ -20,7 +20,10 @@ plugins/ndf/ │ ├── statusline-switch.sh # statusline の導入・切替・復元 (ensure/set/restore/status) │ └── slack-notify.js # Slack通知スクリプト ├── agents/ # 専門エージェント(8個) -├── skills/ # Skills(48個) +├── skills/ # 全Skill実体(48個) +├── skills-claude/ # Claude Code/Kiro向け公開Skill(core 26個) +├── skills-codex/ # Codex向け公開Skill(core 27個) +├── skills-optional/ # ランタイム別除外候補リスト ├── CLAUDE.md # プラグイン開発者向けガイド └── README.md # 利用者向けドキュメント ``` diff --git a/docs/project-overview.md b/docs/project-overview.md index 0427953a..c128ee71 100644 --- a/docs/project-overview.md +++ b/docs/project-overview.md @@ -29,6 +29,10 @@ ai-plugins/ │ └── marketplace.json # Claude Codeマーケットプレイスメタデータ ├── plugins/ │ ├── ndf/ # NDFプラグイン(メイン) +│ │ ├── skills/ # 全Skill実体 +│ │ ├── skills-claude/ # Claude Code/Kiro向け公開Skill +│ │ ├── skills-codex/ # Codex向け公開Skill +│ │ └── skills-optional/ # ランタイム別除外候補リスト │ ├── mcp-serena/ # Serena MCPプラグイン │ └── {plugin-name}/ # その他のプラグイン ├── docs/ # リポジトリ知識 diff --git a/plugins/ndf/.claude-plugin/plugin.json b/plugins/ndf/.claude-plugin/plugin.json index 032af723..0ef63d5a 100644 --- a/plugins/ndf/.claude-plugin/plugin.json +++ b/plugins/ndf/.claude-plugin/plugin.json @@ -1,7 +1,7 @@ { "name": "ndf", "version": "4.16.1", - "description": "Integrated plugin with 8 specialized agents (model-tiered: opus/sonnet/haiku), 48 skills including official mcp-builder, on-demand loader for Anthropic official skills, generic workflow/principle skills, ML model structure standard (ml-model-structure), skill usage statistics, pytest-playwright E2E testing split into 7 focused skills (test-planning, script-creation, execution, report, kit-ops, browser-connect, evidence-drive) + orchestrator with video-by-default evidence, CDP remote browser support, and Google Drive evidence archival, Google Drive/Chat integration, and Codex CLI integration via /ndf:codex skill. Transcript retention is automatically kept at >= 90 days. Default statusline (container/host name + project dir + context usage) is set when none is configured, switchable via /ndf:statusline. Serena MCP is a separate plugin (mcp-serena).", + "description": "Integrated plugin with 8 specialized agents and a focused core skill set for PR/review workflows, implementation planning, debugging principles, statusline, browser smoke testing, and Codex CLI delegation. Additional niche skills remain under skills-optional for maintainers. Transcript retention is automatically kept at >= 90 days. Default statusline is set when none is configured.", "author": { "name": "takemi-ohama", "url": "https://github.com/takemi-ohama" @@ -28,53 +28,31 @@ "./agents/code-reviewer.md" ], "skills": [ - "./skills/pr", - "./skills/pr-tests", - "./skills/fix", - "./skills/review", - "./skills/merged", - "./skills/clean", - "./skills/ndf-policies", - "./skills/data-analyst-sql-optimization", - "./skills/data-analyst-export", - "./skills/qa-security-scan", - "./skills/markdown-writing", - "./skills/python-execution", - "./skills/docker-container-access", - "./skills/deepwiki-transfer", - "./skills/knowledge-reorg", - "./skills/git-gh-operations", - "./skills/google-auth", - "./skills/mcp-builder", - "./skills/official-skills-autoloader", - "./skills/branch-fix-strategy", - "./skills/implementation-plan", - "./skills/investigation-rules", - "./skills/problem-solving", - "./skills/logging-guidelines", - "./skills/sync-main", - "./skills/cherry-pick-pr", - "./skills/deploy", - "./skills/review-branch", - "./skills/review-pr-comments", - "./skills/resolve-pr-comments", - "./skills/browser-test", - "./skills/codex", - "./skills/skill-stats", - "./skills/statusline", - "./skills/playwright-test-planning", - "./skills/playwright-script-creation", - "./skills/playwright-execution", - "./skills/playwright-report", - "./skills/playwright-kit-ops", - "./skills/playwright-browser-connect", - "./skills/playwright-evidence-drive", - "./skills/playwright-scenario-test", - "./skills/google-drive", - "./skills/google-chat", - "./skills/gemini", - "./skills/cross-review", - "./skills/issue-plan-strategy", - "./skills/ml-model-structure" + "./skills-claude/pr", + "./skills-claude/pr-tests", + "./skills-claude/fix", + "./skills-claude/review", + "./skills-claude/merged", + "./skills-claude/clean", + "./skills-claude/ndf-policies", + "./skills-claude/markdown-writing", + "./skills-claude/python-execution", + "./skills-claude/docker-container-access", + "./skills-claude/git-gh-operations", + "./skills-claude/branch-fix-strategy", + "./skills-claude/implementation-plan", + "./skills-claude/investigation-rules", + "./skills-claude/problem-solving", + "./skills-claude/logging-guidelines", + "./skills-claude/sync-main", + "./skills-claude/cherry-pick-pr", + "./skills-claude/deploy", + "./skills-claude/review-branch", + "./skills-claude/review-pr-comments", + "./skills-claude/resolve-pr-comments", + "./skills-claude/browser-test", + "./skills-claude/codex", + "./skills-claude/statusline", + "./skills-claude/issue-plan-strategy" ] } diff --git a/plugins/ndf/.codex-plugin/plugin.json b/plugins/ndf/.codex-plugin/plugin.json index b978a7e6..5e88f971 100644 --- a/plugins/ndf/.codex-plugin/plugin.json +++ b/plugins/ndf/.codex-plugin/plugin.json @@ -2,6 +2,6 @@ "name": "ndf", "version": "4.16.1", "description": "NDF workflows for PRs, reviews, testing, data analysis, Google integrations, and external AI delegation.", - "skills": "./skills/", + "skills": "./skills-codex/", "hooks": "./hooks/codex-hooks.json" } diff --git a/plugins/ndf/AGENTS.md b/plugins/ndf/AGENTS.md index aa32aa2a..6df4ae71 100644 --- a/plugins/ndf/AGENTS.md +++ b/plugins/ndf/AGENTS.md @@ -7,7 +7,7 @@ ## プラグイン情報 - **名前**: ndf -- **現在バージョン**: 4.4.0 +- **現在バージョン**: 4.16.1 - **種類**: 統合プラグイン(Skills + Agents + Hooks / v4.0.0 で Codex MCP 廃止) - **リポジトリ**: https://github.com/devbasex/ai-plugins @@ -25,9 +25,11 @@ plugins/ndf/ ├── .claude-plugin/ │ └── plugin.json # プラグインメタデータ -├── .mcp.json # MCPサーバー定義(Codex CLI) +├── .codex-plugin/ +│ └── plugin.json # Codexプラグインメタデータ ├── hooks/ -│ └── hooks.json # プロジェクトフック定義 +│ ├── hooks.json # Claude Codeプロジェクトフック定義 +│ └── codex-hooks.json # Codex hook定義 ├── scripts/ │ └── slack-notify.js # Slack通知スクリプト ├── agents/ # サブエージェント(8個、モデル階層化) @@ -39,48 +41,10 @@ plugins/ndf/ │ ├── debugger.md # sonnet: 根本原因分析 │ ├── devops-engineer.md # sonnet: Docker/CI/K8s │ └── code-reviewer.md # sonnet: diff/PRレビュー -├── skills/ # スキル(39個) -│ # PRワークフロー系 -│ ├── pr/ # commit+push+PR作成/更新 -│ ├── pr-tests/ # Test Plan自動実行 -│ ├── fix/ # PRコメント修正対応 -│ ├── review/ # PR単位レビュー(Approve/RC判定) -│ ├── review-branch/ # ローカル差分レビュー(PR前) -│ ├── review-pr-comments/ # PRコメント分類(READ-ONLY) -│ ├── resolve-pr-comments/ # 対応済みコメント返信+Resolve -│ ├── cherry-pick-pr/ # 環境ブランチへのcherry-pick PR -│ ├── deploy/ # 環境ブランチへのデプロイPR -│ ├── sync-main/ # main取り込み -│ ├── merged/ # マージ後クリーンアップ -│ ├── clean/ # マージ済みブランチ一括削除 -│ # 原則・ガイドライン系 -│ ├── ndf-policies/ # ポリシー常時注入 -│ ├── branch-fix-strategy/ # ブランチ修正適用戦略 -│ ├── issue-plan-strategy/ # issue→plan→multi-PR ワークフロー (release branch + draft PR + worktree) -│ ├── implementation-plan/ # 実装プラン管理(issues/) -│ ├── investigation-rules/ # 調査時のエビデンス主義 -│ ├── problem-solving/ # 根本原因分析・多層防御 -│ ├── logging-guidelines/ # ログ運用ガイドライン(言語非依存) -│ # データ分析・品質 -│ ├── data-analyst-sql-optimization/ -│ ├── data-analyst-export/ -│ ├── qa-security-scan/ -│ # ドキュメント・環境 -│ ├── markdown-writing/ -│ ├── python-execution/ -│ ├── docker-container-access/ -│ ├── deepwiki-transfer/ -│ ├── knowledge-reorg/ -│ ├── git-gh-operations/ -│ ├── google-auth/ -│ ├── browser-test/ # ブラウザ動作確認(Playwright/Chrome DevTools) -│ ├── codex/ # Codex CLI直接実行(MCP版との使い分け) -│ ├── playwright-scenario-test/ # Playwright+curl Web シナリオE2E並列ランナー -│ ├── google-drive/ # Google Drive エクスポート/DL/UP(google-auth依存) -│ ├── google-chat/ # Google Chat メッセージ取得(google-auth依存) -│ # Anthropic公式連携 -│ ├── mcp-builder/ # Anthropic公式(Apache-2.0) -│ └── official-skills-autoloader/ # 公式Skill自動ロード +├── skills/ # 全Skill実体(48個) +├── skills-claude/ # Claude Code/Kiro向け公開Skill(core 26個) +├── skills-codex/ # Codex向け公開Skill(core 27個) +├── skills-optional/ # ランタイム別除外候補リスト ├── AGENTS.md # このファイル(開発者向け) └── README.md # プラグイン説明書 ``` @@ -90,9 +54,11 @@ plugins/ndf/ ### 新しいスキルの追加 1. `skills/{skill-name}/SKILL.md` を作成(YAMLフロントマター必須) -2. `plugin.json` の `skills` 配列に `"./skills/{skill-name}"` を追加 -3. `plugin.json` のバージョンをMINOR上げ -4. テスト・コミット +2. Claude Code/Kiroで初期公開する場合は `skills-claude/{skill-name}` にコピーし、`.claude-plugin/plugin.json` の `skills` 配列に `"./skills-claude/{skill-name}"` を追加 +3. Codexで初期公開する場合は `skills-codex/{skill-name}` にコピーする(`.codex-plugin/plugin.json` は `./skills-codex/` ディレクトリを参照) +4. 低頻度・保守用に留める場合は `skills-optional/README.md` の候補リストへ追加 +5. plugin.json のバージョンをMINOR上げ +6. テスト・コミット ### 新しいサブエージェントの追加 @@ -100,19 +66,12 @@ plugins/ndf/ 2. `plugin.json` の `agents` 配列に追加 3. バージョンMINOR上げ → テスト・コミット -### MCPサーバーの追加・更新 - -1. `.mcp.json` の `mcpServers` に追加 -2. README.mdに説明追加 -3. バージョン更新 → テスト・コミット - ## 検証チェックリスト - [ ] plugin.jsonが有効なJSON - [ ] バージョン番号が適切にインクリメント - [ ] すべてのスキル/エージェントファイルが存在 - [ ] YAMLフロントマターが正しい -- [ ] .mcp.jsonが有効なJSON - [ ] README.md が最新 ## トラブルシューティング @@ -121,7 +80,6 @@ plugins/ndf/ |------|------| | エージェントが認識されない | plugin.jsonのagents配列、ファイルパス、YAMLフロントマターを確認 | | スキルが表示されない | plugin.jsonのskills配列、SKILL.mdのフロントマターを確認、`/plugin reload ndf` | -| MCPサーバーが起動しない | .mcp.jsonの構文、コマンドパス、環境変数を確認 | | フックが動作しない | hooks.jsonの構文、スクリプト実行権限を確認 | ## 開発履歴 diff --git a/plugins/ndf/README.md b/plugins/ndf/README.md index 4c2f550a..e290c69b 100644 --- a/plugins/ndf/README.md +++ b/plugins/ndf/README.md @@ -4,10 +4,10 @@ Claude Code / Codex開発環境を**オールインワン**で強化する統合 ## 概要 -このプラグイン1つで、以下の**すべて**の機能を利用できます: +このプラグイン1つで、以下の機能を利用できます: 1. **コアMCP**: なし (v4.0.0 で Codex MCP 廃止 / Serena MCP は `mcp-serena` プラグインに分離) -2. **Skills**: 48個(PR/コードレビュー系ワークフロー13個 + 原則・ガイドライン9個 (issue→multi-PR 戦略・MLモデル構造標準含む) + データ分析/品質/環境系12個 + Playwright E2E 8個 (CDPリモート接続・Google Driveエビデンス保管含む) + Google Drive/Chat 連携2個 + AI クロスレビュー2個 (cross-review / gemini) + 運用系2個 (skill-stats / statusline)) +2. **Skills**: Claude Code/Kiro向け core 26個、Codex向け core 27個を公開。元の48個は `skills/` に保持し、ランタイム別の除外候補は `skills-optional/README.md` で管理。 3. **専門エージェント**: 8つの特化型AIエージェント(director、data-analyst、corder、researcher、qa、debugger、devops-engineer、code-reviewer) 4. **自動フック**: Slack通知、デフォルトstatusline設定(未設定時のみ) @@ -76,6 +76,8 @@ codex plugin add ndf@ai-plugins Codex版ではSkillsに加えて、Codex向けSlack終了通知hookを同梱します。通知は明示的に `NDF_CODEX_SLACK_NOTIFY=true` を設定した場合のみ送信されます。Claude Code向けのstatusline設定、transcript保持期間設定、Claude CLIによるSlack要約通知hookはCodexでは自動有効化しません。 +Claude Code/Kiro版で初期表示するSkillsは、PR運用・レビュー・調査・実装計画・browser smoke test・statusline・Codex CLI委譲などの core 26個に絞っています。Codex版は、Codex自体からの再委譲・Claude専用statusline・Claude transcript統計を外し、代わりに最小Playwright 4個を含めた core 27個にしています。Google連携、DeepWiki転送、MLモデル構造、AIクロスレビュー、高度なPlaywright連携などは通常利用時のskills context budgetを圧迫しないよう初期公開から外し、`skills-optional/README.md` に整理しています。 + Codex向けSlack通知を使う場合は、Claude Code向けSlack通知と同じ環境変数を使います。プロジェクトの `.env` などに以下を設定してください。 ```bash @@ -791,7 +793,7 @@ NDFプラグインと併用することで、以下の機能が追加されま | プラグイン | 役割 | |-----------|------| -| **NDFプラグイン** | MCP統合、スキル(48個)、専門エージェント | +| **NDFプラグイン** | MCP統合、公開スキル(Claude/Kiro core 26個、Codex core 27個)、専門エージェント | | **affaan-mプラグイン** | コンテキスト管理、品質保証、TDDワークフロー | 詳細は[affaan-mプラグインREADME](../affaan-m/README.md)を参照してください。 diff --git a/plugins/ndf/skills-claude/branch-fix-strategy/SKILL.md b/plugins/ndf/skills-claude/branch-fix-strategy/SKILL.md new file mode 100644 index 00000000..a4714a34 --- /dev/null +++ b/plugins/ndf/skills-claude/branch-fix-strategy/SKILL.md @@ -0,0 +1,87 @@ +--- +name: branch-fix-strategy +description: "Plan multi-branch fixes and cherry-picks." +when_to_use: "同じ修正を複数ブランチ (qa/staging/release等) に適用する必要があるとき。Triggers: 'cherry-pick', '環境ブランチに修正適用', 'qaに反映', 'stagingに反映', 'release branchへ', 'multi-branch fix', 'apply to qa/staging'" +--- + +# ブランチ修正適用戦略 + +## 適用タイミング + +- featureブランチの修正を `qa/*`, `staging/*`, `release/*` 等の環境ブランチにも適用する必要がある場合 +- 同じ修正を複数ブランチに並行適用する場面全般 + +## 核心ルール + +### 1. 修正は feature ブランチに先に commit → cherry-pick で環境ブランチへ + +``` +✅ feature に commit → cherry-pick して短命ブランチ → 環境ブランチへ PR +❌ 短命ブランチに先に commit → feature に手作業で再実装(二重作業・不整合リスク) +``` + +### 2. 環境ブランチを feature ブランチに merge しない(main 汚染禁止) + +``` +❌ feature/xxx ← merge qa/staging(conflict 解消目的でも禁止) +``` + +環境ブランチを featureブランチにmergeすると、後で `feature → main` のPRに環境固有コードが混入する。 + +### 3. origin/main を必ず取り込む + +短命ブランチを push する前に必ず `git merge origin/main` する。CI で最新 main 必須の Workflow があるため。 + +### 4. マージ済みブランチに push しない + +環境ブランチ向けの短命ブランチに push する前に `gh pr list --head ` で PR 状態を確認する。マージ済みなら新ブランチ + 新 PR を作成する(サフィックス `-v2`, `-v3` を付ける)。 + +## 実行手順 + +`/ndf:cherry-pick-pr ` で自動化されている。手動で行う場合のみ以下を参照。 + +```bash +# 1. feature ブランチで修正を commit +git checkout feature/xxx +git add && git commit -m "fix: 修正内容" +git log --oneline -1 # commit hash を記録 + +# 2. 短命ブランチを作成 +git fetch origin qa/staging +git checkout -b feature/xxx-for-staging origin/qa/staging + +# 3. origin/main を取り込む(必須) +git fetch origin main +git merge origin/main --no-edit + +# 4. cherry-pick(-x で元 commit hash を参照に残す) +git cherry-pick -x + +# 5. push して PR 作成 +git push -u origin feature/xxx-for-staging +gh pr create --base qa/staging --title "fix: 修正内容(staging検証用)" + +# 6. 元のブランチに戻る +git checkout feature/xxx +``` + +## なぜこの順序が重要か + +| 観点 | 正しい順序 | 誤った順序 | +|------|-----------|-----------| +| 単一ソース | feature ブランチが唯一の正 | 二箇所で実装 | +| 一貫性 | cherry-pick で完全一致 | 手書き差分でズレる | +| 追跡性 | `-x` で元 commit が明記 | 関連 commit 不明確 | + +## revert 操作の注意 + +revertの連鎖(revert → reapply → revert...)ではなく、**最終的なあるべき状態を直接コミット**するのが望ましい。履歴上の意図が明確になり、後の cherry-pick も簡単になる。 + +## 関連コマンド・スキル + +| リソース | 用途 | +|---------|------| +| `/ndf:cherry-pick-pr` | cherry-pick + 短命ブランチ + origin/main 取り込み + PR 作成を自動化 | +| `/ndf:pr` | 通常のPR作成。非 main ベースは `cherry-pick-pr` に誘導される | +| `/ndf:sync-main` | 現在のブランチに最新 main を取り込む | +| `/ndf:deploy` | 環境ブランチへのデプロイPR作成(ブランチ全体をmerge main経由で適用) | diff --git a/plugins/ndf/skills-claude/browser-test/SKILL.md b/plugins/ndf/skills-claude/browser-test/SKILL.md new file mode 100644 index 00000000..97eb0c82 --- /dev/null +++ b/plugins/ndf/skills-claude/browser-test/SKILL.md @@ -0,0 +1,159 @@ +--- +name: browser-test +description: "Run browser smoke tests for web apps." +argument-hint: "[url]" +disable-model-invocation: true +allowed-tools: + - Bash + - mcp__playwright__browser_navigate + - mcp__playwright__browser_snapshot + - mcp__playwright__browser_click + - mcp__playwright__browser_fill_form + - mcp__playwright__browser_take_screenshot + - mcp__playwright__browser_type + - mcp__playwright__browser_evaluate + - mcp__playwright__browser_console_messages + - mcp__playwright__browser_wait_for + - mcp__playwright__browser_tabs + - mcp__playwright__browser_navigate_back + - mcp__playwright__browser_close + - mcp__playwright__browser_resize + - mcp__playwright__browser_handle_dialog + - mcp__playwright__browser_press_key + - mcp__playwright__browser_hover + - mcp__playwright__browser_select_option + - mcp__playwright__browser_drag + - mcp__playwright__browser_network_requests + - mcp__playwright__browser_file_upload + - mcp__playwright__browser_install + - mcp__chrome-devtools__navigate_page + - mcp__chrome-devtools__take_snapshot + - mcp__chrome-devtools__click + - mcp__chrome-devtools__fill_form + - mcp__chrome-devtools__take_screenshot + - mcp__chrome-devtools__type + - mcp__chrome-devtools__evaluate_script + - mcp__chrome-devtools__list_console_messages + - mcp__chrome-devtools__wait_for + - mcp__chrome-devtools__list_pages + - mcp__chrome-devtools__new_page + - mcp__chrome-devtools__select_page + - mcp__chrome-devtools__close_page + - mcp__chrome-devtools__navigate_page_history + - mcp__chrome-devtools__resize_page + - mcp__chrome-devtools__handle_dialog + - mcp__chrome-devtools__hover + - mcp__chrome-devtools__drag + - mcp__chrome-devtools__list_network_requests + - mcp__chrome-devtools__get_network_request + - mcp__chrome-devtools__upload_file + - mcp__chrome-devtools__emulate_network + - mcp__chrome-devtools__emulate_cpu + - mcp__chrome-devtools__performance_start_trace + - mcp__chrome-devtools__performance_stop_trace + - mcp__chrome-devtools__performance_analyze_insight +--- + +# ブラウザ動作確認コマンド + +現在のブランチで実装されたWeb機能をブラウザで動作確認する。Playwright MCP または Chrome DevTools MCP を利用可能な方を自動選択する。 + +## 前提条件(重要) + +このコマンドは以下のいずれかのMCPサーバが必要: + +- **Playwright MCP**: 自動的にブラウザを起動(要Playwrightインストール) +- **Chrome DevTools MCP**: 既に開いているChromeを操作(Chromeをデバッグモードで起動しておく必要あり) + +どちらも利用できない環境では、手動確認手順を案内する。 + +## 使用方法 + +``` +/ndf:browser-test # 現在のブランチの実装を確認 +/ndf:browser-test http://localhost:8080 # 特定URLを確認 +``` + +## MCPの使い分け + +### Playwright MCP +- 自動的にブラウザを起動 +- 複数ブラウザ対応 (Chromium/Firefox/WebKit) +- 利用可能なら第一選択 + +### Chrome DevTools MCP +- 既に開いているChromeブラウザを操作 +- Chrome デバッグモードでの起動が必要: + - macOS: `/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome --remote-debugging-port=9222` + - Windows: `chrome.exe --remote-debugging-port=9222` + - Linux: `google-chrome --remote-debugging-port=9222` +- DevTools統合でパフォーマンス分析可能 + +## 処理フロー + +### 1. アプリケーション起動確認 + +プロジェクトで使っている起動方法に応じて確認: + +```bash +# Docker Compose の場合 +docker compose ps + +# ネイティブ起動の場合 +curl -fsS http://localhost:/health || echo "NOT RUNNING" +``` + +起動していない場合は、起動手順をユーザーに案内。 + +### 2. ブラウザアクセスと認証 + +- 指定URL(または `/` )にアクセス +- 必要に応じてログイン(資格情報はプロジェクト固有、事前に取得しておく) + +### 3. 機能画面への遷移 + +実装された機能に応じて適切な画面に遷移する。 + +### 4. 動作確認 + +必要に応じて以下の操作を実行: + +- フォーム入力 +- ボタンクリック +- データ表示の確認 +- コンソールエラーの確認 +- ネットワークリクエストの確認 +- スクリーンショット(明示的に指示された場合のみ) + +### 5. 結果報告 + +```markdown +## 動作確認結果 + +### 実施項目 +- [x] ログイン +- [x] 機能画面表示 +- [x] フォーム送信 +- [x] 結果表示 + +### 確認事項 +- コンソールエラー: なし +- ネットワークエラー: なし +- 期待結果との一致: ok + +### 気になる点 +- ...(あれば) +``` + +## 注意事項 + +- **事前にアプリケーション起動が必要** +- **ログイン情報**: プロジェクトの `.env.example` / README 等から確認。機密情報として扱う +- **スクリーンショット**: 必要な場合のみ明示的に指示されたときに取得 +- **Chrome DevTools使用時**: Chromeをデバッグモードで起動しておく必要あり +- **MCP未インストール環境**: 手動での確認手順を案内する + +## 関連 + +- `/ndf:review-branch` — 変更差分のコードレビュー +- `/ndf:pr-tests` — PR Test Plan の自動実行 diff --git a/plugins/ndf/skills-claude/cherry-pick-pr/SKILL.md b/plugins/ndf/skills-claude/cherry-pick-pr/SKILL.md new file mode 100644 index 00000000..b5dc1341 --- /dev/null +++ b/plugins/ndf/skills-claude/cherry-pick-pr/SKILL.md @@ -0,0 +1,120 @@ +--- +name: cherry-pick-pr +description: "Create cherry-pick PRs for environment branches." +argument-hint: " (例: qa/staging, release/v2)" +disable-model-invocation: true +allowed-tools: + - Bash + - Read + - Grep +--- + +# cherry-pick PR 作成コマンド + +featureブランチから指定ベースブランチへ、短命ブランチ経由で cherry-pick PR を作成する。`feature → main` の PR にベースブランチ固有コードが混入するのを防ぐ。 + +## 使用方法 + +``` +/ndf:cherry-pick-pr qa/staging +/ndf:cherry-pick-pr release/v2 +``` + +## なぜ必要か + +featureブランチに環境ブランチ(`qa/staging`等)を merge して conflict を解消すると、`feature → main` の PR に環境ブランチ固有のコードが混入する(main汚染)。短命ブランチ + cherry-pick で、必要なコミットだけを対象ブランチに届ける。 + +詳細な原則は `/ndf:branch-fix-strategy` スキル参照。 + +## 処理フロー + +### 1. 引数・現状確認 +- 引数からベースブランチ名を取得(必須。未指定なら確認) +- `git branch --show-current` で現在ブランチを取得 + +### 2. 既存PRのマージ済みチェック(必須) + +同じベースブランチ向けの短命ブランチに既存PRがないか確認する。 + +```bash +# 同名パターンのブランチでマージ済みPRがないか確認 +gh pr list --head "-for-" --state merged \ + --json number,mergedAt --jq '.[]' +``` + +マージ済みPRが見つかった場合、**同じブランチ名は使えない**。サフィックスを付ける(例: `-v2`, `-v3`)。 + +### 3. コミット一覧の確認 + +```bash +git log --oneline main..HEAD +``` + +ユーザーに cherry-pick 対象コミットを確認(全コミット or 選択)。 + +### 4. 短命ブランチ作成 + +```bash +git fetch origin +git checkout -b -for- origin/ +``` + +- ``: ベースブランチのスラッシュ以降(例: `qa/staging` → `staging`) +- 例: `feature/add-auth-for-staging` + +### 5. origin/main を取り込む(必須) + +```bash +git fetch origin main +git merge origin/main --no-edit +``` + +CIで最新main必須のWorkflowがあるため、取り込み忘れるとconflictやCIエラーになる。 + +### 6. cherry-pick 実行 + +```bash +git cherry-pick -x ... +``` + +`-x` オプションで元のcommit hashが参照として残り、追跡性が向上する。 + +conflict が発生した場合: +- `git diff --name-only --diff-filter=U` でconflictファイル一覧 +- 解消を試み、ユーザーに確認後 `git cherry-pick --continue` + +### 7. push して PR 作成 + +```bash +git push -u origin +gh pr create --base --title "<タイトル>" --body "$(cat <<'EOF' +## Summary +- feature/xxx からcherry-pickした<環境名>向けPR +- 元コミット: + +## Test plan +- [ ] <環境名>で動作確認 + + +EOF +)" +``` + +### 8. 元ブランチに戻る + +```bash +git checkout +``` + +## 注意事項 + +- 短命ブランチは PR マージ後に削除してよい +- `feature → main` の PR には影響しない +- ベースブランチを feature ブランチに merge するのは **禁止**(main汚染の原因) +- `-x` オプションで元commit参照を残す(追跡性) + +## 関連 + +- `/ndf:branch-fix-strategy` — なぜこの手順が必要かの原則 +- `/ndf:pr` — 通常のPR作成(base=main) +- `/ndf:deploy` — ブランチ全体を環境へデプロイ(cherry-pickとは別用途) diff --git a/plugins/ndf/skills-claude/clean/SKILL.md b/plugins/ndf/skills-claude/clean/SKILL.md new file mode 100644 index 00000000..2f75e54e --- /dev/null +++ b/plugins/ndf/skills-claude/clean/SKILL.md @@ -0,0 +1,20 @@ +--- +name: clean +description: "Delete local and remote merged branches." +disable-model-invocation: true +allowed-tools: + - Bash +--- + +# ブランチクリーンアップコマンド + +mainマージ済みブランチをローカル/リモート削除。 + +## 手順 + +1. `git branch --merged main`確認 +2. main・現在ブランチ除外 +3. `git branch -d ` +4. `git push origin --delete ` + +**注意**: 削除前確認・main除外・現在ブランチ除外 diff --git a/plugins/ndf/skills-claude/codex/SKILL.md b/plugins/ndf/skills-claude/codex/SKILL.md new file mode 100644 index 00000000..80060a83 --- /dev/null +++ b/plugins/ndf/skills-claude/codex/SKILL.md @@ -0,0 +1,473 @@ +--- +name: codex +description: "Delegate coding, review, or research to Codex CLI." +when_to_use: "外部 AI へコード生成 / レビュー / 調査を委譲したいとき。Triggers: 'codexで調査', 'codexレビュー', '第二意見レビュー', 'codex exec', 'external AI review'" +--- + +# Codex 外部AI委譲スキル + +## 概要 + +`codex` CLI(OpenAI Codex、通常は `/usr/bin/codex` または `npm` 経由でインストール)を直接実行して、コード生成・独立レビュー・コードベース調査を外部AIに委譲するためのスキル。 + +ローカルファイルの逐語照合レビューや大規模コードベース調査に向いている。 + +## NDFとの関係 + +- NDFプラグインの `corder` エージェントはこの skill の手順に従って Codex CLI を呼び出す +- v4.0.0 で Codex MCP サーバは廃止。`mcp__codex__*` ツールは存在しない +- 使い分け: 軽量な独立レビュー → `corder` エージェントに委譲。手順の詳細を自分で制御したい or 複雑なプロンプトを出したい → 本 skill を参照して直接 `codex exec` 起動 + +## いつ使うか + +### 使うべきケース +- **独立第二意見レビュー**: 設計書・PR・仕様書を外部AIにレビューさせる(メインエージェントの思考バイアスを避ける) +- **コードベース逐語照合**: 「行番号・関数名・重複箇所の件数」を正確に突き合わせる必要がある場合 +- **長時間の調査タスク**: 複数ファイル横断で5〜10分以上かかる調査 +- **実装タスクの並列化**: メインエージェントで他作業を進めつつ、別タスクを codex に走らせたい場合 + +### 使わないべきケース +- 短時間(1〜2分以内)で済むタスク → メインエージェントで直接対応 +- ユーザとの対話が必要な設計相談 → Plan Mode等で対話しながら進める +- 単純な質問回答 → WebFetch / WebSearch で足りる +- 機密情報を含むコード → 外部API送信の可否を確認してから + +## 前提条件 + +```bash +# インストール確認 +which codex +codex --version + +# ログイン状態確認(初回のみ必要) +codex login +``` + +未インストールの場合は以下でセットアップ: + +```bash +# npm 経由 +npm install -g @openai/codex + +# 動作確認 +codex exec --help +``` + +## 基本実行パターン + +### 1. サンドボックス制約(重要) + +codex のデフォルトサンドボックスは `bubblewrap (bwrap)` に依存する。以下の環境では bwrap が動作せず、`exec` で実行するシェルコマンドがすべて失敗する: + +- **WSL2**(カーネルで `unprivileged_userns_clone` が無効) +- **一部の devcontainer / Docker 環境**(user namespace 非対応) + +該当環境では **`--dangerously-bypass-approvals-and-sandbox` を付けて起動**する必要がある。 + +```bash +# ❌ サンドボックス有効(bwrap 失敗で exec コマンドが全滅) +codex exec -s read-only -C "$PWD" + +# ✅ サンドボックスバイパス(外側が既にコンテナ等で隔離されている前提) +codex exec --dangerously-bypass-approvals-and-sandbox -C "$PWD" +``` + +**判断基準**: 既にDocker / devcontainer / VM / CIランナー等で外部的にサンドボックスされているなら `--dangerously-bypass-approvals-and-sandbox` は実用上安全。ホスト直接実行でコード全書き換えされたくない場合はフラグを付けずに対処(後述「bwrap代替」)。 + +#### bwrap 代替の有効化(ホスト直接実行時) + +```bash +# Debian/Ubuntu 系でホスト user namespace を有効化 +sudo sysctl kernel.unprivileged_userns_clone=1 + +# 永続化 +echo 'kernel.unprivileged_userns_clone=1' | sudo tee /etc/sysctl.d/00-local-userns.conf +``` + +### 2. プロンプトは一時ファイル経由で渡す + +長いプロンプトをシェル引数に渡すとエスケープ地獄になるので、**一時ファイル経由でstdinに流す**のが基本。 + +```bash +# Step 1: プロンプトを一時ファイルに書く +cat > /tmp/codex-prompt.md <<'EOF' +## タスク +以下のファイルを読み込み、設計意図とコードの整合性をレビューしてください。 + +## 対象ファイル(絶対パスで指定) +/absolute/path/to/design.md + +## 出力形式 +Markdown で標準出力に吐いてください。 +EOF + +# Step 2: codex exec に stdin で流す(バックグラウンド実行) +codex exec --dangerously-bypass-approvals-and-sandbox -C "$PWD" \ + < /tmp/codex-prompt.md \ + > /tmp/codex-output.md \ + 2> /tmp/codex-err.log & +``` + +**エージェントからの書き方**: ファイル書き込みツールで `/tmp/codex-prompt.md` を作ってから、シェル実行ツールの「バックグラウンド実行」オプションで codex を起動する。 + +### 3. 出力ストリームの扱い + +codex CLI の出力構造: + +| ストリーム | 内容 | +|---|---| +| **stdout** | **最終 assistant message のみ**(Markdown本文)。出ないことがある(後述) | +| **stderr** | プロンプトのエコー + 実行したコマンドと結果 + codexの思考プロセス + `^tokens used$` sentinel | + +**実務上の扱い**: +- 最終成果物が欲しい → `stdout` をそのまま採用…**ただし stdout が空になるケースがあるので必ずファイル出力も併用**(下記 3.5 参照) +- codexが何を調べたか追跡したい → `stderr` をデバッグ用に保存 + +```bash +codex exec ... > /tmp/codex-output.md 2> /tmp/codex-err.log +# 成果物 = /tmp/codex-output.md(stdout が空でないことを必ず確認) +# デバッグ = /tmp/codex-err.log(大きめ、数千行になる) +``` + +### 3.5 最終出力をファイル経由で保証する(重要) + +**Codex CLI(特に `gpt-5-codex` / 高 reasoning_effort)は、長時間調査の末に** +**最終 assistant message を返さずにセッションを終えることがある**。 +このとき stdout は空のままになり、stderr のイベントログ(数十万バイト)には +コードを実際に読んだ痕跡だけが残る。`^tokens used$` は出ているのに stdout が空、という状態。 + +**根本対策: プロンプトに「最終結果は指定ファイルへ書き出すこと」を必須化する。** +Codex は最終 message を返さなくても `apply_patch` ツールでファイルを作成できるため、 +ファイル経由なら確実に結果を回収できる。 + +#### プロンプトに必ず含める指示(テンプレート) + +```markdown +## 出力先(必須) + +最終的なレビュー / 調査結果を以下のファイルに **必ず書き出してください**: + +`/tmp/codex-output-.md` + +書き出しは `apply_patch` で新規ファイル作成してください。 +**stdout への出力だけでは不十分です**(セッション終了で失われる場合があるため)。 +書き出し後、念のため stdout にも同じ内容を出力してください(冪等で問題ありません)。 +``` + +#### 回収側の安全パターン + +```bash +# 1. ファイルが存在するかを最優先で確認(stdout が空でもこちらに本文が残る) +OUTPUT_FILE=/tmp/codex-output-pr13734-review.md +if [ -s "$OUTPUT_FILE" ]; then + cat "$OUTPUT_FILE" +elif [ -s /tmp/codex-stdout.md ]; then + # 2. ファイルがなければ stdout フォールバック + cat /tmp/codex-stdout.md +else + # 3. どちらも空なら stderr の末尾から拾う最後の手段 + echo "WARN: Codex の最終出力を回収できませんでした。stderr 末尾を確認してください:" >&2 + tail -200 /tmp/codex-err.log +fi +``` + +#### 補助対策 + +- **`reasoning_effort` を `medium` に下げる** (`--config reasoning.effort=medium`) + `high` だと思考に偏って最終 message を返さなくなる頻度が上がる +- **`--json` モードでイベント採取** (`codex exec --json`) + JSON Lines で `event.type=assistant_message` を grep すれば確実に取れる +- **強制 summary 指示**: プロンプト末尾に「最後に必ず assistant message として 1 回出力すること、tool 呼び出しのみで終了しないこと」を明記 + +### 4. バックグラウンド実行 + 待機パターン + +codex は **5〜10分かかることが普通**。多くのエージェントハーネスはシェル実行に2〜3分のタイムアウトを課すので、**必ずバックグラウンド実行**する。 + +```bash +# 1. プロンプトファイル書き出し(ファイル書き込みツール) +# -> /tmp/codex-prompt.md + +# 2. codex をバックグラウンドで起動(`&` でシェル自体は即時終了) +codex exec --dangerously-bypass-approvals-and-sandbox -C "$PWD" \ + < /tmp/codex-prompt.md \ + > /tmp/codex-output.md \ + 2> /tmp/codex-err.log & + +# 3. PID を控える +echo "PID: $!" + +# 4. 待機(他の作業を進める or スケジューラで再開) + +# 5. 完了検知 — ps -p は zombie に騙される。stderr の "tokens used" sentinel を見る +until grep -q '^tokens used$' /tmp/codex-err.log 2>/dev/null; do + sleep 30 +done +``` + +**⚠️ 罠**: `&` でバックグラウンド実行するとラッパーシェルは即終了し「タスク完了通知」が発火するが、codex 本体はまだ動いている。**`ps -p $PID` は zombie (defunct) も 0 を返す** ため `until ! ps -p $PID` は永久ループになりうる。`grep -q '^tokens used$' /tmp/codex-err.log` を脱出条件にする (codex が最終回答を吐き終わると stderr 末尾に必ず出る sentinel)。 + +### 5. 待機間隔のチューニング + +エージェントの context cache TTL は通常5分。これを超えると prompt cache がミスして再送料金が発生する: + +- **短い間隔**: 60〜270秒(TTL=5分内に収まる、軽量) +- **長い間隔**: 1200秒以上(1回のキャッシュミスを長時間で償却) +- **避けるべき**: 300秒前後(キャッシュミス+短時間の最悪) + +codex の典型実行時間(5〜10分)に対しては **270秒ポーリング** か **1200秒一括待ち** の二択。 + +### 6. プロセス確認・ログ追跡 + +```bash +# 完了したか (stderr 末尾の "tokens used" が最も信頼できる) +grep -q '^tokens used$' /tmp/codex-err.log && echo DONE + +# 最新の作業内容を覗く +tail -30 /tmp/codex-err.log +``` + +## プロンプト設計のコツ + +### 必須要素 +1. **対象ファイルの絶対パス**(codexは `nl -ba`, `sed -n`, `rg` 等でファイルを読むため) +2. **調査観点を具体化**(箇条書きで3〜5項目に絞る) +3. **出力形式の指定**(Markdownテンプレートを提示) +4. **スコープ外の明示**(codexが脱線しないため) +5. **最終出力先ファイルの指定(必須)**: `/tmp/codex-output-.md` のような明示パスへ + **`apply_patch` で必ず書き出させる**。stdout だけに頼ると最終 message が落ちて空になる事故が起きる(3.5 節参照) +6. **stdout にも同内容を吐く指示**: ファイル書き出し後、念のため stdout にもエコーさせる(冪等) + +### レビュー依頼テンプレート + +```markdown +あなたは<役割(例: シニアバックエンドエンジニア / セキュリティレビュアー)>として、 +以下をレビューしてください。 + +## 対象ファイル(必ず最初に読むこと) +`/absolute/path/to/target.md` + +## 観点 +1. <観点1: 例「仕様とコードの整合性」> +2. <観点2: 例「既存APIとの後方互換性」> + +## 調査対象コード(必要に応じて読む) +- `src/...` +- `lib/...` + +## 背景コンテキスト +- <プロジェクト概要> +- <関連PR / Issue番号> +- <既存レビューで対応済みの事項(重複指摘を避けるため)> + +## 出力形式 + +以下を Markdown で**`/tmp/codex-output-.md` に必ず書き出してください** +(`apply_patch` で新規ファイル作成)。書き出し後、stdout にも同内容を出力してください。 +**stdout のみへの出力は不可**(セッション終了時に失われる場合があるため): + +# <タイトル> + +## 総評 +## 1. <観点1> に関する指摘 +### 1.1 正確な主張 +### 1.2 訂正推奨 +## 2. <観点2> に関する指摘 +## 3. 追加提案 +## 4. 承認可否 + +**必須**: 行番号・ファイルパスに紐付けて具体的に指摘してください。400〜500行程度、日本語で出力してください。 +**必須**: tool 呼び出しのみで終了せず、最後に必ず assistant message として 1 回出力してください。 +``` + +### コード生成依頼テンプレート + +```markdown +以下の実装タスクを実行してください。 + +## タスク +<具体的な実装内容> + +## 制約 +- <技術制約: 言語バージョン、依存ライブラリ> +- <コーディング規約: ESLint / Prettier / rustfmt等> +- <テスト要件: ユニットテスト必須等> + +## 対象ファイル +- <既存ファイルのパス> +- <新規ファイルのパス案> + +## 背景 +<なぜこの実装が必要か、設計判断の経緯> + +## 完了基準 +- [ ] テストがパスする +- [ ] 型チェック / lint がパスする +- [ ] <追加の受け入れ条件> + +**必須**: ファイル編集は実際に行い、最後に変更ファイル一覧と要点を +`/tmp/codex-output-.md` に書き出してください(`apply_patch` で新規作成)。 +書き出し後、stdout にも同内容を出力してください。 +**stdout のみへの出力は不可**(セッション終了時に失われる場合があるため)。 +tool 呼び出しのみで終了せず、最後に必ず assistant message として 1 回出力してください。 +``` + +## 実例: レビュー依頼の完全フロー + +```bash +# === 1. プロンプト書き出し === +# ポイント: 最終出力先ファイルをプロンプト内で明示し、apply_patch で書かせる +FINAL=/tmp/codex-output-api-v2-review.md + +cat > /tmp/review-prompt.md < /tmp/codex-stdout.md \ + 2> /tmp/codex-err.log & + +PID=$! +echo "codex PID: $PID" + +# === 3. 完了確認(^tokens used$ sentinel を待つ) === +until grep -q '^tokens used$' /tmp/codex-err.log 2>/dev/null; do + sleep 30 +done +echo DONE + +# === 4. 成果物を安全に回収(ファイル優先 → stdout fallback) === +if [ -s "$FINAL" ]; then + cp "$FINAL" ./review-result.md + echo "✅ Codex 書き出しファイルから回収" +elif [ -s /tmp/codex-stdout.md ]; then + cp /tmp/codex-stdout.md ./review-result.md + echo "⚠ stdout からフォールバック回収(ファイル書き出しなし)" +else + echo "❌ Codex の最終出力を回収できませんでした。stderr 末尾を確認してください:" >&2 + tail -200 /tmp/codex-err.log + exit 1 +fi +``` + +## トラブルシューティング + +### Q1. stdoutが空でstderrに大量のexecログだけある +**原因**: codex がまだ最終回答を出す前に停止した、または **最終 assistant message を出さずにセッションが終わった**(gpt-5-codex の高 reasoning_effort で発生しやすい既知挙動)。 + +**対処**: +- `grep -q '^tokens used$' /tmp/codex-err.log` で終了 sentinel が出ているか確認(まだなら動作中なので追加待機) +- 出ているのに stdout が空 → セッション終了で最終 message が失われたケース。**3.5 節「最終出力をファイル経由で保証する」のパターンでリトライ必須**: + - プロンプトに `apply_patch` で `/tmp/codex-output-.md` へ必ず書き出させる指示を追加 + - 回収側は「ファイル → stdout → stderr」の三段フォールバックで取りこぼしを防ぐ + - 補助で `--config reasoning.effort=medium` も付けると最終 message を返す傾向が上がる + +### Q2. `bwrap: No permissions to create a new namespace` で exec 失敗 +**原因**: `--dangerously-bypass-approvals-and-sandbox` を付け忘れ、かつ環境が user namespace 非対応。 + +**対処**: +- フラグを追加して再実行 +- `-s read-only` / `-s workspace-write` も bwrap を使うので同じ結果になる点に注意 +- ホストで user namespace を有効化する方法は「サンドボックス制約」節を参照 + +### Q3. codexが「ファイルを読めません」と返してくる +**原因**: +- サンドボックス有効でファイル読み取りに失敗 +- プロンプトで相対パスを指定し、codexの cwd が想定と違った + +**対処**: +- `--dangerously-bypass-approvals-and-sandbox` を追加 +- プロンプトには**絶対パス**を書く +- `-C ` で cwd を明示 + +### Q4. タスク完了通知が来たのに出力が空 / wait loop が抜けない +**原因**: `&` で起動したラッパーシェルが先に終了して通知が出ているだけで、codex 本体は動作中。または既に終わっているが zombie (defunct) として残っており `ps -p $PID` が 0 を返し続けている。 + +**対処**: 検知を「PID の存在」ではなく **stderr の `^tokens used$` sentinel** で行う。codex は最終回答を吐き終えると必ずこの行を stderr に書く。 + +```bash +# ❌ 永久ループ化しうる +until ! ps -p $PID; do sleep 30; done + +# ✅ zombie 安全 +until grep -q '^tokens used$' /tmp/codex-err.log 2>/dev/null; do + sleep 30 +done +``` + +### Q5. codex実行が15分以上かかる +**原因**: プロンプトで広すぎる調査範囲を指定した、または codex が探索ループに入った。 + +**対処**: +- プロンプトで「読むべきファイル」を明示リスト化 +- スコープ外を明記(「〇〇には踏み込まない」) +- 必要なら `kill ` で打ち切り、プロンプトを絞り込んで再実行 + +### Q6. stdoutの末尾が途切れている +**原因**: codex がトークン上限に達した可能性。 + +**対処**: プロンプトで「400行以内」など出力サイズを指定。または観点を絞って再実行。 + +### Q7. 認証エラー (`Unauthorized` / `token expired`) +**原因**: ログインセッション失効。 + +**対処**: +```bash +codex logout +codex login +``` + +## corder エージェント経由との使い分け + +本スキルは CLI を直接呼び出す詳細手順を記述している。簡易に独立レビューを取りたいだけなら `corder` エージェントに委譲した方が手間が少ない: + +| 観点 | corder エージェント | 本スキルで直接 CLI 起動 | +|---|---|---| +| 使い勝手 | `Agent(subagent_type: "corder", ...)` で委譲するだけ | プロンプト書き出し・バックグラウンド起動・PID 管理を自分で制御 | +| プロンプト制御 | corder 側で整形 | 自由に設計可 | +| バックグラウンド実行 | agent 側が制御 | `&` で非同期化、他作業と並列 | +| スケジュール連携 | 難しい | `/schedule` / `Monitor` と組み合わせやすい | + +**指針**: 迷ったら corder 経由。プロンプト細部や非同期タイミングを自分で握りたい場合のみ本スキルの手順で直接起動。 + +## 既知の制約とコスト + +1. **サンドボックス非対応環境**: `--dangerously-bypass-approvals-and-sandbox` で回避必須 +2. **stderrに全思考が書かれる**: 数千行になりうるので必ず `2> /tmp/...` にリダイレクト +3. **ログイン状態**: 初回は `codex login` が必要。未ログインだと即座に失敗する +4. **セッション復旧**: 長時間ジョブで親エージェントが再起動した場合、`codex resume` でセッション再開可能 +5. **APIコスト**: トークン従量課金のため、短時間で済むタスクには使わない。1セッションで数千〜数万トークン消費することがある +6. **機密情報**: 外部APIにコードが送信されるため、社外秘コードの扱いは組織ポリシーに従うこと + +## 関連 + +- **NDF `corder` エージェント**: 本スキルの手順で Codex CLI を呼び出す独立レビュー担当 (v4.0.0 以降は MCP ではなく CLI 経由) +- **OpenAI Codex CLI公式ドキュメント**: `codex --help` / `codex exec --help` +- **他のAI委譲方法**: `gemini`, `claude`, `ollama` 等のCLI も同様のパターンで利用可 diff --git a/plugins/ndf/skills-claude/deploy/SKILL.md b/plugins/ndf/skills-claude/deploy/SKILL.md new file mode 100644 index 00000000..769919d7 --- /dev/null +++ b/plugins/ndf/skills-claude/deploy/SKILL.md @@ -0,0 +1,114 @@ +--- +name: deploy +description: "Create deploy PRs from feature to environment branches." +argument-hint: " (例: qa/staging, release/v2)" +disable-model-invocation: true +allowed-tools: + - Bash + - Read +--- + +# 環境デプロイPR作成コマンド + +現在のfeatureブランチを指定した環境ブランチへデプロイするためのPRを作成する。`{feature}_to_{env}` という命名のdeployブランチを作成し、最新 origin/main を取り込んでから環境ブランチへPRを出す。 + +## 使用方法 + +``` +/ndf:deploy qa/staging +/ndf:deploy release/v2 +``` + +## cherry-pick-pr との使い分け + +| 観点 | cherry-pick-pr | deploy | +|---|---|---| +| 適用範囲 | featureブランチの**一部コミット**を選択 | featureブランチ**全体**を適用 | +| ブランチ戦略 | 環境ブランチから短命ブランチ派生 | featureブランチから deploy ブランチ派生 | +| main取り込み | 必須 | 必須 | +| 用途 | 特定修正のみ検証環境に届けたい | feature機能全体を環境で検証したい | + +## 処理フロー + +### 1. バリデーション + +```bash +CURRENT_BRANCH=$(git branch --show-current) +[[ "$CURRENT_BRANCH" == "main" || "$CURRENT_BRANCH" == "master" ]] && \ + echo "❌ Error: デフォルトブランチからデプロイできません" && exit 1 +``` + +### 2. deployブランチ名の導出 + +```bash +FEATURE_BRANCH=$(git branch --show-current) +# 環境名を抽出: "qa/staging" → "staging", "release/v2" → "v2" +ENV_SUFFIX=$(echo "$ARGUMENTS" | sed 's|.*/||') +DEPLOY_BRANCH="${FEATURE_BRANCH}_to_${ENV_SUFFIX}" +``` + +### 3. 既存PRチェック + +```bash +EXISTING_PR=$(gh pr list --head "$DEPLOY_BRANCH" --base "$ARGUMENTS" \ + --json number,url --jq '.[0].url // empty') +if [[ -n "$EXISTING_PR" ]]; then + echo "✅ PR already exists: $EXISTING_PR" + exit 0 +fi +``` + +既存PRがあれば更新は「deployブランチにpushする」だけで済むため、再作成しない。 + +### 4. deployブランチ作成 + main取り込み + +```bash +git fetch origin main +git checkout -b "$DEPLOY_BRANCH" +git merge origin/main --no-edit || { + echo "❌ main とのmerge conflict。手動解決が必要です" + git merge --abort + git checkout "$FEATURE_BRANCH" + git branch -D "$DEPLOY_BRANCH" + exit 1 +} +``` + +### 5. push + PR作成 + +```bash +git push -u origin "$DEPLOY_BRANCH" +gh pr create --base "$ARGUMENTS" --head "$DEPLOY_BRANCH" \ + --title "$DEPLOY_BRANCH → $ARGUMENTS" \ + --body "$(cat <<'EOF' +## Summary +- 環境デプロイ用PR +- 元ブランチ: $FEATURE_BRANCH +- main取り込み済み + +## Test plan +- [ ] $ARGUMENTS 環境で動作確認 + + +EOF +)" +``` + +### 6. 元ブランチに復帰 + +```bash +git checkout "$FEATURE_BRANCH" +``` + +## 注意事項 + +- デフォルトブランチからの実行は禁止 +- main取り込みで conflict が出た場合、deployブランチを削除して戻る(featureブランチ側を先に同期すべき) +- deployブランチは PR マージ後に削除してよい +- 環境ブランチへの再デプロイは「同じ deployブランチに push」でPRが更新される + +## 関連 + +- `/ndf:cherry-pick-pr` — 一部コミットだけを環境に届ける場合 +- `/ndf:branch-fix-strategy` — ブランチ運用戦略の原則 +- `/ndf:sync-main` — featureブランチに main を取り込む diff --git a/plugins/ndf/skills-claude/docker-container-access/01-environment-detection.md b/plugins/ndf/skills-claude/docker-container-access/01-environment-detection.md new file mode 100644 index 00000000..51941bcc --- /dev/null +++ b/plugins/ndf/skills-claude/docker-container-access/01-environment-detection.md @@ -0,0 +1,84 @@ +# 環境判定ガイド + +## Step 1: 自身の環境を確認 + +```bash +# 自分がコンテナ内で動作しているか確認 +cat /proc/1/cgroup 2>/dev/null | grep -q docker && echo "コンテナ内" || echo "ホスト環境" + +# または +[ -f /.dockerenv ] && echo "コンテナ内" || echo "ホスト環境" +``` + +## Step 2: Docker環境の種類を判定 + +自身がコンテナ内の場合、以下のいずれかの環境です: + +| 環境 | 説明 | 判定方法 | +|-----|------|---------| +| **DinD** (Docker in Docker) | コンテナ内に独立したDockerデーモン | `docker info`でDocker rootが`/var/lib/docker` | +| **DooD** (Docker outside of Docker) | ホストのDockerソケットを共有 | `/var/run/docker.sock`がマウントされている | + +```bash +# DooD判定: docker.sockがマウントされているか +ls -la /var/run/docker.sock 2>/dev/null && echo "DooD環境の可能性" || echo "DinDまたはホスト環境" + +# Docker rootディレクトリの確認 +docker info 2>/dev/null | grep "Docker Root Dir" +``` + +## DinD環境でのアクセス + +DinD環境では、**localhost**で他のコンテナにアクセスできます。 + +### 特徴 +- コンテナ内に独立したDockerデーモンが動作 +- ネットワークは通常のDocker環境と同じ +- `localhost:ポート`でアクセス可能 + +### アクセス例 + +```bash +# Webサーバーへのアクセス +curl http://localhost:8080 + +# データベースへの接続 +mysql -h localhost -P 3306 -u user -p + +# Playwright MCPでのアクセス +# URL: http://localhost:3000 +``` + +## 環境判定スクリプト + +```bash +#!/bin/bash +# Docker環境判定スクリプト + +echo "=== Docker環境判定 ===" + +# 自分がコンテナ内かチェック +if [ -f /.dockerenv ] || grep -q docker /proc/1/cgroup 2>/dev/null; then + echo "実行環境: Dockerコンテナ内" + + # DinD/DooD判定 + if [ -S /var/run/docker.sock ]; then + echo "Docker形式: DooD (Docker outside of Docker)" + echo "" + echo "→ 他のコンテナへのアクセスにはコンテナ名を使用してください" + echo "→ bind mountはホストのパスを参照するため注意が必要です" + else + echo "Docker形式: DinD (Docker in Docker)" + echo "" + echo "→ localhostで他のコンテナにアクセス可能です" + fi +else + echo "実行環境: ホストマシン" + echo "" + echo "→ 通常のDocker操作が可能です" +fi + +echo "" +echo "=== 利用可能なコンテナ ===" +docker ps --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}" 2>/dev/null || echo "Dockerが利用できません" +``` diff --git a/plugins/ndf/skills-claude/docker-container-access/02-dood-access.md b/plugins/ndf/skills-claude/docker-container-access/02-dood-access.md new file mode 100644 index 00000000..d19fc967 --- /dev/null +++ b/plugins/ndf/skills-claude/docker-container-access/02-dood-access.md @@ -0,0 +1,134 @@ +# DooD環境でのアクセスガイド + +## 特徴 + +- ホストのDockerデーモンを共有 +- localhostはホストマシンを指す(他のコンテナではない) +- コンテナ間通信はDockerネットワーク経由 + +## アクセス方法 + +### 1. コンテナ名でアクセス(同一ネットワーク内) + +```bash +# コンテナ名を確認 +docker ps --format "table {{.Names}}\t{{.Ports}}" + +# コンテナ名でアクセス +curl http://my-web-container:8080 + +# docker-composeの場合、サービス名でアクセス +curl http://web:8080 +``` + +### 2. Dockerネットワーク経由 + +```bash +# ネットワーク一覧を確認 +docker network ls + +# 特定ネットワークのコンテナを確認 +docker network inspect bridge --format '{{range .Containers}}{{.Name}} {{.IPv4Address}}{{"\n"}}{{end}}' + +# IPアドレスでアクセス +curl http://172.17.0.2:8080 +``` + +### 3. 同一ネットワークへの参加 + +```bash +# 自分のコンテナを対象コンテナと同じネットワークに接続 +docker network connect my-network $(hostname) + +# その後、コンテナ名でアクセス可能 +curl http://target-container:8080 +``` + +## curlでのアクセス例 + +```bash +# NG: localhostは使えない +curl http://localhost:8080 # → Connection refused + +# OK: コンテナ名を使用 +curl http://my-app-container:8080 + +# OK: docker-composeのサービス名 +curl http://api:3000 + +# OK: コンテナのIPアドレス +CONTAINER_IP=$(docker inspect -f '{{range.NetworkSettings.Networks}}{{.IPAddress}}{{end}}' my-container) +curl http://${CONTAINER_IP}:8080 +``` + +## Playwright MCP / Chrome DevTools MCP + +```bash +# DooD環境では、コンテナ名またはIPを使用 +# URL: http://web-container:3000 (コンテナ名) +# URL: http://172.17.0.3:3000 (IP) +``` + +--- + +## bind mountの注意点 + +### 問題 + +DooD環境では、`docker run -v`や`docker-compose`のbind mountは**ホストマシンのパス**を参照します。開発コンテナ内のパスではありません。 + +```yaml +# NG: DooD環境では期待通りに動作しない +volumes: + - ./local-dir:/app/data # ホストの./local-dirを参照してしまう +``` + +### 解決策 + +#### 1. Dockerfileでコピー(推奨) + +```dockerfile +FROM node:18 +WORKDIR /app +COPY . . +RUN npm install +CMD ["npm", "start"] +``` + +#### 2. 名前付きボリュームを使用 + +```bash +# ボリュームを作成 +docker volume create my-data + +# ファイルをボリュームにコピー +docker run --rm -v my-data:/data -v $(pwd):/src alpine cp -r /src/. /data/ + +# ボリュームをマウントしてコンテナ起動 +docker run -v my-data:/app/data my-image +``` + +#### 3. docker cpを使用 + +```bash +# コンテナにファイルをコピー +docker cp ./local-file.txt my-container:/app/ + +# コンテナからファイルを取得 +docker cp my-container:/app/output.txt ./ +``` + +### docker-compose.yml での対応 + +```yaml +# DooD環境対応版 +version: '3.8' +services: + app: + build: . # Dockerfileでファイルをコピー + volumes: + - app-data:/app/data # 名前付きボリューム使用 + +volumes: + app-data: +``` diff --git a/plugins/ndf/skills-claude/docker-container-access/03-troubleshooting.md b/plugins/ndf/skills-claude/docker-container-access/03-troubleshooting.md new file mode 100644 index 00000000..0acac32c --- /dev/null +++ b/plugins/ndf/skills-claude/docker-container-access/03-troubleshooting.md @@ -0,0 +1,63 @@ +# トラブルシューティング + +## Q: `curl: (7) Failed to connect to localhost port 8080` + +**原因**: DooD環境でlocalhostを使用している + +**解決策**: +```bash +# コンテナ名またはIPを使用 +docker ps # コンテナ名を確認 +curl http://container-name:8080 +``` + +## Q: bind mountしたファイルが見えない + +**原因**: DooD環境ではホストのパスを参照している + +**解決策**: +```bash +# docker cpでコピー +docker cp ./file.txt container:/app/ + +# または名前付きボリュームを使用 +``` + +## Q: コンテナ間で通信できない + +**原因**: 異なるDockerネットワークに所属している + +**解決策**: +```bash +# 同じネットワークに接続 +docker network connect my-network container-a +docker network connect my-network container-b +``` + +## Q: docker.sockへのアクセス権限がない + +**解決策**: +```bash +# docker グループに追加(要再ログイン) +sudo usermod -aG docker $USER + +# または一時的に権限付与 +sudo chmod 666 /var/run/docker.sock +``` + +--- + +# ベストプラクティス + +## DO(推奨) + +- **コンテナアクセス前に環境を判定する** +- **DooD環境ではコンテナ名/サービス名を使用する** +- **ファイル共有はDockerfileのCOPYまたは名前付きボリュームを使用** +- **docker-composeではサービス名でアクセス** + +## DON'T(非推奨) + +- **環境を確認せずにlocalhostを使用する** +- **DooD環境でbind mountに依存する** +- **IPアドレスをハードコードする(変わる可能性がある)** diff --git a/plugins/ndf/skills-claude/docker-container-access/SKILL.md b/plugins/ndf/skills-claude/docker-container-access/SKILL.md new file mode 100644 index 00000000..eadd1ffe --- /dev/null +++ b/plugins/ndf/skills-claude/docker-container-access/SKILL.md @@ -0,0 +1,76 @@ +--- +name: docker-container-access +description: "Diagnose Docker container access and localhost routing." +when_to_use: "Docker / コンテナへのアクセス・localhost 接続不可・DinD/DooD 環境判定が必要なとき。Triggers: 'docker access', 'container connect', 'localhost not working', 'DinD', 'DooD', 'Docker接続', 'コンテナアクセス', 'curl container'" +allowed-tools: + - Read + - Bash + - Glob +--- + +# Docker Container Access Skill + +## 概要 + +ローカル開発環境がDocker開発コンテナ上で動作している場合、他のDockerコンテナへのアクセス方法が通常と異なります。このスキルでは、環境を判定し、適切なアクセス方法を選択するためのガイドラインを提供します。 + +## クイックリファレンス + +``` +環境判定 → アクセス方法 +──────────────────────────────── +ホスト環境 → localhost:port +DinD環境 → localhost:port +DooD環境 → container-name:port または IP:port + +ファイル共有(DooD環境) +──────────────────────────────── +Dockerfile COPY → 推奨(ビルド時にコピー) +名前付きボリューム → 推奨(永続化が必要な場合) +docker cp → OK(一時的なコピー) +bind mount → NG(ホストのパスを参照) +``` + +## 環境判定(最初に実行) + +```bash +# 自分がコンテナ内か確認 +[ -f /.dockerenv ] && echo "コンテナ内" || echo "ホスト環境" + +# DooD判定 +ls -la /var/run/docker.sock 2>/dev/null && echo "DooD環境" || echo "DinDまたはホスト" +``` + +| 環境 | 説明 | コンテナへのアクセス | +|-----|------|-------------------| +| **ホスト** | 通常のDocker環境 | `localhost:port` | +| **DinD** | コンテナ内に独立したDockerデーモン | `localhost:port` | +| **DooD** | ホストのDockerソケットを共有 | `container-name:port` | + +## 詳細ガイド + +詳細は以下のファイルを参照してください: + +| ファイル | 内容 | +|---------|------| +| `01-environment-detection.md` | 環境判定の詳細、判定スクリプト | +| `02-dood-access.md` | DooD環境でのアクセス方法、bind mount注意点 | +| `03-troubleshooting.md` | トラブルシューティング、ベストプラクティス | + +## よくある問題(簡易版) + +| 症状 | 原因 | 解決策 | +|-----|------|--------| +| `localhost`で接続できない | DooD環境 | コンテナ名を使用 | +| bind mountしたファイルが見えない | DooD環境 | `docker cp`または名前付きボリューム | +| コンテナ間で通信できない | 別ネットワーク | 同じネットワークに接続 | + +## 関連Skill + +- **python-execution**: Python実行環境の判定 +- **corder-code-templates**: Dockerfileテンプレート + +## 関連リソース + +- [Docker Networking](https://docs.docker.com/network/) +- [Docker in Docker](https://hub.docker.com/_/docker) diff --git a/plugins/ndf/skills-claude/fix/SKILL.md b/plugins/ndf/skills-claude/fix/SKILL.md new file mode 100644 index 00000000..92471ddd --- /dev/null +++ b/plugins/ndf/skills-claude/fix/SKILL.md @@ -0,0 +1,303 @@ +--- +name: fix +description: "Fix actionable PR review comments." +when_to_use: "PRレビューコメント (codex/gemini/人間) の指摘を実際にコード修正で対応したいとき。review-pr-comments で分類した後の修正フェーズに使う。Triggers: 'PRコメント対応', 'PRレビュー修正', 'PR fix', 'review feedback fix', 'コメントに対応して修正'" +argument-hint: "[PR番号] [--defer-nit] [--severity-min critical|major|minor]" +allowed-tools: + - Bash + - Read + - Edit + - Write + - Glob + - Grep +--- + +# PR修正コマンド + +直前PR、または引数で指定されたPRのreview comment確認・修正対応実行。 + +## 起動モード + +このスキルは **メインセッション直接実行** と **サブエージェント (`general-purpose`) 起動** の両方に対応する。 +長丁場のクロスレビューループ(`/ndf:cross-review`)からは **必ずサブエージェント経由で起動** されることを想定: + +```python +# メインからの起動例(cross-review が内部でこれを行う) +Agent( + subagent_type="general-purpose", + description="Fix PR review comments (sub-agent)", + prompt=""" +/ndf:fix --defer-nit を実行してください。 + +PR: +リポジトリ: +重要度ポリシー: critical/major/minor は修正、nit は deferred として残す +完了後の戻り値: 件数サマリ + 修正コミット SHA + 残 nit リスト +""" +) +``` + +サブエージェント側ではこの SKILL.md を読み込んで、自己完結で +**修正 → コミット → push → reply → Resolve Conversation** まで実行する。 +メインへの戻り値は最小限のサマリのみ。 + +## 引数 + +| 引数 | 意味 | 既定 | +|---|---|---| +| `[PR番号]` | 対象 PR | 直前 PR | +| `--defer-nit` | nit 指摘は修正せず deferred としてリスト出力 | OFF | +| `--severity-min LEVEL` | 指定重要度未満は無視(`critical` / `major` / `minor`) | `minor` (= minor 以上を修正) | + +## 重要度ベースの自動修正ポリシー + +`[重要度 / カテゴリ]` プレフィックス(`/ndf:review` 出力規約)で分類。 +**ただし重要度ラベルを鵜呑みにしない** — 各指摘ごとにコード/仕様を独自に調査し、 +本来の重要度を判定し直してから下表の動作を適用する(bot のラベリングは参考値に過ぎない)。 + +| 重要度 | 動作 | ユーザ問い合わせ | +|---|---|---| +| `critical` | **必ず自動修正** | なし | +| `major` | **必ず自動修正** | なし | +| `minor` / `nit` (パフォーマンス・可読性・重複コード排除) | **このPRで修正対応**。特にトータル行数が減る方向の修正は積極的に実施 | なし | +| `minor` / `nit` (上記カテゴリ、修正範囲が +30 行を超えそう) | ユーザ問い合わせ | あり | +| `minor` (その他) | 自動修正(明らかな改善のみ)。判断が割れるなら `nit` として deferred 扱い | なし | +| `nit` (その他) | `--defer-nit` 指定時は **修正せず deferred リスト** に追加。最後にまとめてユーザ問い合わせ | あり(最後に1回) | + +**重要度の独自判定**: +- AI agent (CodeRabbit / Copilot 等) が `nit` と付けていても、実体がパフォーマンス改善や重複排除なら **minor/nit カテゴリ修正対象** として扱う +- 逆に AI agent が `critical` と付けていても、実害がないスタイル指摘なら `nit` 相当に格下げして deferred 化してよい +- 重要度はカテゴリ(performance/readability/duplication/security/style/etc)と合わせて、コード本体を読んだ上で判定する + +**指摘の正否判断**: +- ロジック・仕様逸脱・セキュリティ: コード/仕様を確認してから修正可否判断 +- bot 指摘で **明らかに誤読** している場合(例: 意図的な変数展開を「クオート不足」と指摘する等): 修正しない、reply で理由説明 +- 仕様判断が必要な指摘(API 変更、互換性破壊など): ユーザ問い合わせ対象(critical でもエスカレーション) + +**自動判断できない場合の取り扱い** (context 節約のため安易に user に投げない): +- 仕様文書(docs/, README)を読んで判断する +- 既存テストを読んで挙動を確認する +- 関連する他コードの慣例を確認する +- それでも不明なら deferred リストに「要ユーザ判断」として記録、最後にまとめて問い合わせ + +## 手順 + +1. review comment取得 + 重要度を**独自に再判定**(AI agent のラベルは参考値) +2. **CIエラー確認**(`gh pr checks ` で **現時点の** 失敗ジョブを検出) + - **完了待ちはしない**。実行中(PENDING/IN_PROGRESS)のチェックは無視して次ステップへ進む + - 直近で失敗(FAILURE)状態のジョブのみを修正対象に取り込む +3. 修正対象を確定: + - `critical` / `major` → 全件修正対象 + - `minor` / `nit` (パフォーマンス・可読性・重複排除) → 修正対象。+30行超なら **deferred + ユーザ問い合わせ** + - `minor` (その他) → 修正対象(明らかでないものは `deferred[]` へ) + - `nit` (その他、`--defer-nit` 時) → `deferred[]` のみ、修正しない + - CIエラー → 全件修正対象(PRテスト範囲外の **flaky テストも見つけ次第修正**) +4. 問題点修正 + - **コード行数が減る方向の修正は積極的に実施**(重複排除、不要分岐除去 等) +5. **コミット前の再確認**(修正作業中に状況が変わっている可能性への対応) + - **review comment再取得**: 作業中に新しいコメントが追加されていないか確認 + - **CI状態再確認**: 現時点の状態だけ確認(完了待ちはしない)。新しい失敗が出ていれば対象に取り込む + - 新しい指摘/失敗があれば手順3に戻る +6. コミット・プッシュ +7. PRにSummaryコメントを追加(対応した件数 + deferred 件数を明記) +8. 対応したインラインコメントに個別に返信 +9. **deferred スレッドには `[deferred / nit]` のラベル付き返信** を投稿(resolve はしない) +10. reviewerに再レビューを依頼 +11. 対応完了したインラインコメントを「Resolve Conversation」にする(`resolveReviewThread` mutation) + - resolve した thread_id / comment_id / path / line を `resolved_threads[]` に記録 + - `deferred` / `rejected` の thread は Resolve しない(次ラウンドで再評価するため) +12. **戻り値ファイルを書き出す**: `/tmp/fix-pr<番号>-result.json` (後述「戻り値フォーマット」参照) + - `ci_failed_checks` には `gh pr checks --json name,state` から `state=FAILURE` の name を抽出して列挙 + - push 直後の CI 再実行結果は**待たない**ため、戻り値の `ci_status` は push 時点での既知失敗のみを反映する + +- 4〜6はgit、1〜2/5と7以降はgithub mcpまたはghを利用 + +**flakyテストの扱い**: PR の変更範囲外で発生している flaky テストも、見つけ次第このPRで修正する。 +flaky を放置するとリポジトリ全体のコード品質が下がり、後続 PR の CI 信頼性も損なわれるため。 + +## CIエラーチェック + +### 失敗ジョブの検出 + +```bash +# PRの全チェック状態を確認(FAIL/PASS/PENDING) +gh pr checks + +# JSON形式で詳細取得 +gh pr checks --json name,state,link,completedAt + +# 失敗ジョブのみ抽出 +gh pr checks --json name,state | \ + python3 -c "import json,sys; [print(c['name']) for c in json.load(sys.stdin) if c['state']=='FAILURE']" + +# 実行中ジョブのみ抽出(状態スナップショット用。完了は待たない) +gh pr checks --json name,state | \ + python3 -c "import json,sys; [print(c['name']) for c in json.load(sys.stdin) if c['state'] in ('PENDING','IN_PROGRESS','QUEUED')]" +``` + +### CI完了待ちはしない + +このスキルでは **CI 完了待ちは行わない**(`gh pr checks --watch` 等は使わない)。 +- 各チェックポイントでは「現時点で FAILURE のジョブ」のみを取り込んで修正する +- push 後の CI 再実行結果も待たない(待機中に context を消費しないため) +- ただし `gh pr checks --json name,state` での **状態スナップショット取得は実施** + し、戻り値の `ci_status` / `ci_failed_checks` に反映する + +### 失敗ログの取得 + +```bash +# ワークフロー実行ID取得 +RUN_ID=$(gh run list --branch --limit 1 --json databaseId --jq '.[0].databaseId // empty') +[ -z "$RUN_ID" ] && { echo "No CI run found for this branch"; exit 0; } + +# 失敗ステップのログだけ表示(効率的) +gh run view $RUN_ID --log-failed + +# 特定ジョブのログ +gh run view $RUN_ID --job --log +``` + +### CIエラーの分類と対応方針 + +| エラー種別 | 対応方針 | +|---|---| +| **lint/format** | 自動修正ツール実行(`ruff`, `prettier`, `eslint --fix` 等)→ コミット | +| **型チェック** | 型定義・アノテーションを修正。無視コメントは原則禁止(根本対応) | +| **テスト失敗** | 失敗テストを読み、実装/テストどちらが正しいか判断してから修正。テスト側の問題なら仕様確認 | +| **ビルドエラー** | 依存関係・構文・設定ファイルを確認 | +| **依存脆弱性** | 可能ならバージョン更新、無理なら除外ルール追加(理由明記) | +| **タイムアウト/flaky** | retry設定、テスト分割、リトライ追加。**PR範囲外の flaky も見つけ次第修正**(放置でリポジトリ全体の品質劣化を招くため) | +| **インフラ一時障害** | 再実行で解消することがあるため `gh run rerun $RUN_ID` を先に試す | + +### review指摘との統合 + +review指摘とCIエラーは**同じPRで一緒に修正**する: +- 同じファイル・機能に関する指摘とCIエラーは1コミットにまとめる +- 独立しているなら別コミットに分離(git log で追いやすい) + +## ghコマンド例 + +### PR コメント一括取得 (3 ソース) + +```bash +# インラインコメント / レビュー body / PR レベルコメントを一括取得 +FETCH_SCRIPT="${PLUGIN_ROOT:-${CLAUDE_PLUGIN_ROOT}}/skills/fix/scripts/fetch-pr-comments.sh" +"$FETCH_SCRIPT" +``` + +### コメントへの返信 + +```bash +# PRのレビューコメント一覧を取得 (インラインコメントのみ) +gh api repos/{owner}/{repo}/pulls/{pr_number}/comments + +# 特定のコメントに返信(in_reply_to にコメントIDを指定) +gh api repos/{owner}/{repo}/pulls/{pr_number}/comments \ + -f body="修正しました。" \ + -F in_reply_to={comment_id} +``` + +### Resolve Conversation + +```bash +# GraphQL APIでスレッドをresolveする +gh api graphql -f query=' + mutation { + resolveReviewThread(input: {threadId: "{thread_node_id}"}) { + thread { isResolved } + } + } +' +``` + +### thread_node_idの取得方法 + +```bash +# PRのレビュースレッド一覧を取得(node_id含む) +gh api graphql -f query=' + query { + repository(owner: "{owner}", name: "{repo}") { + pullRequest(number: {pr_number}) { + reviewThreads(first: 100) { + nodes { + id + isResolved + comments(first: 1) { + nodes { body } + } + } + } + } + } + } +' +``` + +**方針**: +- 品質・可読性・セキュリティ向上、既存機能影響なし +- 指摘がすべて正しいとは限らない。修正前に仕様を調査し、実施の可否を判断すること +- 未対応の場合はその理由をコメントに書き込む + +## 戻り値フォーマット(必須) + +サブエージェント呼び出し時の context 節約のため、**実行結果は `/tmp/fix-pr<番号>-result.json` に書き出す**: + +```json +{ + "pr": 67, + "fix_commit": "abc1234", + "ci_status": "SUCCESS" | "FAILURE" | "PENDING" | "NONE", + "ci_failed_checks": [], + "ci_note": null, + "fixed_count": 5, + "by_severity": {"critical": 1, "major": 2, "minor": 2, "nit": 0}, + "resolved_threads": [ + { + "thread_id": "PRRT_...", + "comment_id": 3222849090, + "path": "src/foo.py", + "line": 42 + } + ], + "deferred": [ + { + "comment_id": 3222849090, + "thread_id": "PRRT_...", + "path": "src/foo.py", + "line": 42, + "severity": "nit", + "category": "style", + "summary": "末尾セミコロンの有無", + "reason_for_deferral": "好みの範囲。プロジェクト規約と齟齬なし" + } + ], + "rejected": [ + { + "comment_id": 3222849090, + "summary": "heredoc を <<'JSON' にせよ", + "reason_for_rejection": "$SHA を意図的に展開する必要があり、クオート化すると逆に壊れる" + } + ], + "summary_comment_url": "https://github.com/.../pull/67#issuecomment-..." +} +``` + +**フィールド説明**: + +- `ci_failed_checks` — `ci_status = FAILURE` のとき、失敗した check 名の配列。`/ndf:cross-review` 側で code-related (`pint/larastan/test/build/lint/type`) と meta-only (`check_pr_requirements/assignees/reviewers/labels`) を分類し、メタチェックのみ失敗ならループ継続する +- `ci_note` — code-related ではない CI 失敗の補足。例: `"メタチェックのみ失敗: check_pr_requirements — Assignees 未設定"` +- `resolved_threads` — 手順 11 で `resolveReviewThread` mutation を実行したスレッド一覧。`deferred` / `rejected` の thread は **Resolve しない**(再評価のため) + +サブエージェントとして起動された場合は、この JSON をメインに返すサマリの基礎とする。 + +## 作業完了報告(必須) + +メイン or PR への報告内容(戻り値ファイルから抽出): +- 対応した指摘の件数(重要度別: critical/major/minor/nit) +- **deferred 件数**(主に nit、最後にユーザ問い合わせ予定) +- **rejected 件数**(bot 指摘が不適切で修正しなかった件、各々理由付き) +- **対応したCIエラーの一覧**(ジョブ名、エラー内容、修正方法) +- **対応した flaky テストの一覧**(PR範囲外も含む) +- 修正コミット SHA / 修正ファイル一覧 +- 戻り値ファイルパス: `/tmp/fix-pr<番号>-result.json` +- **PR URL を最後に必ず記載**(例: `https://github.com///pull/<番号>`) diff --git a/plugins/ndf/skills-claude/fix/scripts/fetch-pr-comments.sh b/plugins/ndf/skills-claude/fix/scripts/fetch-pr-comments.sh new file mode 100755 index 00000000..aa7f97fe --- /dev/null +++ b/plugins/ndf/skills-claude/fix/scripts/fetch-pr-comments.sh @@ -0,0 +1,47 @@ +#!/usr/bin/env bash +# Usage: fetch-pr-comments.sh +# 3 ソース (インラインコメント / レビュー body / PR レベルコメント) を一括取得し、 +# タグ付き行単位で stdout に出力する。 +# 全ソース取得失敗時は非 0 で終了する(0件取得と取得失敗を区別)。 +set -uo pipefail + +if [[ $# -lt 2 ]] || [[ -z "${1:-}" ]] || [[ -z "${2:-}" ]]; then + echo "ERROR: 引数が不足しています。Usage: $0 " >&2 + exit 1 +fi + +REPO="$1" +PR="$2" + +FAIL_COUNT=0 + +# 1. インラインコメント (diff の特定行に紐づく) +# 本文全体を保持する。改行は \n エスケープして 1 行に収める。 +# gh api --jq は内部で jq -r 相当だが、環境差を吸収するため明示的に jq -r へパイプする。 +if ! gh api "repos/${REPO}/pulls/${PR}/comments" --paginate \ + | jq -r '.[] | "\(.path // "?"):\(.line // .original_line // "?") [\(.user.login)] \(.body // "" | gsub("\n"; "\\n") | gsub("```"; "` ` `"))"'; then + echo "WARNING: インラインコメントの取得に失敗しました (repos/${REPO}/pulls/${PR}/comments)" >&2 + (( FAIL_COUNT += 1 )) || true +fi + +# 2. レビュー body (CHANGES_REQUESTED / COMMENTED 等の総評) +# 本文全体を保持する。改行は \n エスケープして 1 行に収める。 +if ! gh api "repos/${REPO}/pulls/${PR}/reviews" --paginate \ + | jq -r '.[] | select(.body != null and .body != "") | "[REVIEW-BODY] [\(.user.login)] state=\(.state) \(.body | gsub("\n"; "\\n") | gsub("```"; "` ` `"))"'; then + echo "WARNING: レビュー body の取得に失敗しました (repos/${REPO}/pulls/${PR}/reviews)" >&2 + (( FAIL_COUNT += 1 )) || true +fi + +# 3. PR レベルコメント (Conversation タブの通常コメント) +# 本文全体を保持する。改行は \n エスケープして 1 行に収める。 +if ! gh api "repos/${REPO}/issues/${PR}/comments" --paginate \ + | jq -r '.[] | "[PR-COMMENT] [\(.user.login)] \(.body // "" | gsub("\n"; "\\n") | gsub("```"; "` ` `"))"'; then + echo "WARNING: PR レベルコメントの取得に失敗しました (repos/${REPO}/issues/${PR}/comments)" >&2 + (( FAIL_COUNT += 1 )) || true +fi + +# 全ソース失敗時のみ非 0 で終了(認証切れ等の検出) +if (( FAIL_COUNT >= 3 )); then + echo "ERROR: 全 3 ソースの取得に失敗しました" >&2 + exit 1 +fi diff --git a/plugins/ndf/skills-claude/git-gh-operations/01-common-errors.md b/plugins/ndf/skills-claude/git-gh-operations/01-common-errors.md new file mode 100644 index 00000000..a7afa445 --- /dev/null +++ b/plugins/ndf/skills-claude/git-gh-operations/01-common-errors.md @@ -0,0 +1,145 @@ +# Git / gh 共通エラー事例集 + +## 1. git add pathspec エラー + +### 事象 +``` +fatal: pathspec 'lambda-batch/CarImageProcessingPipeline/src/foo.py' did not match any files +``` + +### 原因 +CWD が `/work/repo/lambda-batch/CarImageProcessingPipeline/` なのに、 +リポジトリルートからの相対パスで `git add` した。 + +`git status` はリポジトリルートからの相対パスで表示するが、 +`git add` は CWD からの相対パスで解決する。 + +### 予防策 +```bash +# Step 1: CWD確認 +pwd +# => /work/repo/lambda-batch/CarImageProcessingPipeline/ + +# Step 2: git status の出力を確認 +git status +# modified: lambda-batch/CarImageProcessingPipeline/src/foo.py +# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +# これはリポジトリルートからの相対パス + +# Step 3: CWD からの相対パスに変換 +git add src/foo.py +# または +git add . # CWD以下のすべての変更 +``` + +## 2. gh api 404 エラー + +### 事象 +``` +gh api repos/owner/repo/pulls/comments/123/replies -f body='message' +# => 404 Not Found +``` + +### 原因 +POST メソッドが必要な API エンドポイントに GET でアクセスした。 +`gh api` はデフォルトで GET を使用する。 + +### 修正 +```bash +gh api -X POST repos/owner/repo/pulls/comments/123/replies -f body='message' +``` + +## 3. GitHub 自己 Approve エラー + +### 事象 +``` +Could not approve for pull request review. Can not approve your own pull request +``` + +### 原因 +GitHub はセキュリティ上、自分で作成した PR を APPROVE できない。 + +### 対策 +```bash +# pending review を削除してから COMMENT として再送信 +# method: "delete_pending" → method: "create" + event: "COMMENT" +``` + +## 4. AWS CLI [$LATEST] パースエラー + +### 事象 +``` +Unknown options: , , , +``` + +### 原因 +CloudWatch ログストリーム名に含まれる `[$LATEST]` が +`--query` JMESPath パーサーや shell の glob として解釈される。 + +### 対策 +```bash +# シングルクォートで囲んでも --query との組み合わせで問題が出る +# --output json + python パースが最も安全 +aws logs get-log-events \ + --log-group-name "/aws/lambda/func-name" \ + --log-stream-name '2026/02/18/[$LATEST]abc123' \ + --output json | python3 -c " +import sys, json +data = json.loads(sys.stdin.read()) +for e in data['events']: + print(e['message'].strip()) +" +``` + +## 5. git commit メッセージの特殊文字 + +### 事象 +コミットメッセージに日本語や改行が含まれるとエスケープ問題が発生。 + +### 対策 +常に HEREDOC 形式を使用: +```bash +git commit -m "$(cat <<'EOF' +日本語メッセージ + +詳細説明 + +Co-Authored-By: Claude Opus 4.6 +EOF +)" +``` + +注意: `<<'EOF'` (シングルクォート付き)で変数展開を抑制する。 + +## 6. gh pr checks が exit code 1 で止まる + +### 事象 +``` +gh pr checks 11765 2>&1 +# => チェック結果は表示されるが、1つでもfailがあると exit code 1 で終了 +# => Claude Code が「コマンド失敗」と判定して処理を中断 +``` + +### 原因 +`gh pr checks` は CI チェックに失敗があると非0の exit code を返す仕様。 +Claude Code の Bash ツールはコマンドの exit code が 0 以外だとエラーとして扱う。 + +### 対策 +常に `|| true` を付けて exit code を 0 にする: +```bash +# チェック一覧を取得(failがあっても止まらない) +gh pr checks 11765 2>&1 || true + +# --watch で完了待ちする場合も同様 +gh pr checks 11765 --watch 2>&1 || true + +# 失敗のみフィルタする場合 +gh pr checks 11765 2>&1 | grep -i fail || true +``` + +### 補足 +同様の問題が発生する gh コマンド: +- `gh run view RUN_ID --log-failed` (失敗ログ取得時) +- `gh pr diff` (差分が大きい場合にパイプ破損) + +いずれも `2>&1 || true` を付けることで安全に実行できる。 diff --git a/plugins/ndf/skills-claude/git-gh-operations/SKILL.md b/plugins/ndf/skills-claude/git-gh-operations/SKILL.md new file mode 100644 index 00000000..68b8a7a0 --- /dev/null +++ b/plugins/ndf/skills-claude/git-gh-operations/SKILL.md @@ -0,0 +1,228 @@ +--- +name: git-gh-operations +description: "Resolve git and GitHub CLI operation errors." +when_to_use: "git / gh コマンドでエラーが出た or 操作方法に迷うとき。Triggers: 'git add', 'git commit', 'git push', 'gh pr', 'gh api', 'GitHub操作', 'gitエラー', 'fatal:', 'pathspec'" +allowed-tools: + - Bash + - Read +--- + +# Git / gh 操作スキル + +## 最重要ルール: CWD とパスの整合性 + +git コマンドはすべて **CWD からの相対パス** で解決される。 +操作前に必ず `pwd` で CWD を確認すること。 + +### パターン1: CWDがサブディレクトリの場合 + +``` +# CWD: /work/repo/lambda-batch/MyProject/ +# リポジトリルート: /work/repo/ + +# NG: リポジトリルートからのパスを指定 +git add lambda-batch/MyProject/src/foo.py +# => fatal: pathspec did not match any files + +# OK: CWDからの相対パスを指定 +git add src/foo.py + +# OK: 絶対パスを指定 +git add /work/repo/lambda-batch/MyProject/src/foo.py +``` + +### パターン2: 安全な方法 + +```bash +# 方法A: git -C でリポジトリルートを指定 +git -C /work/repo add lambda-batch/MyProject/src/foo.py + +# 方法B: CWD を変更せずに絶対パスを使用 +git add "$(git rev-parse --show-toplevel)/lambda-batch/MyProject/src/foo.py" + +# 方法C(推奨): CWDからの相対パスを使用 +# まず pwd で確認してからパスを組み立てる +``` + +## git 操作チェックリスト + +### git add の前に + +1. `pwd` で CWD を確認 +2. `git status` で変更ファイルのパスを確認(表示されるパスはリポジトリルートからの相対パス) +3. `git status` の出力パスと CWD の関係を計算してから `git add` する + +### git commit の前に + +1. `git diff --cached` でステージング内容を確認 +2. HEREDOC形式でメッセージを渡す(改行・特殊文字の問題回避) + +```bash +git commit -m "$(cat <<'EOF' +コミットメッセージ + +Co-Authored-By: Claude Opus 4.6 +EOF +)" +``` + +## gh CLI / GitHub API の注意点 + +### パラメータ: `-f` vs `-F` + +```bash +# -f: 文字列パラメータ +gh api repos/OWNER/REPO/pulls/PR/comments -f body="テキスト" + +# -F: 非文字列パラメータ(数値、boolean、null、ファイル) +gh api repos/OWNER/REPO/pulls/PR/comments -F in_reply_to=2826074026 + +# 混在OK +gh api repos/OWNER/REPO/pulls/PR/comments -f body="返信テキスト" -F in_reply_to=2826074026 +``` + +### PRレビューコメントの取得 + +```bash +# コメント一覧を取得(id, path, body の先頭を表示) +gh api repos/OWNER/REPO/pulls/PR/comments \ + --jq '.[] | {id: .id, path: .path, body: (.body | split("\n")[0][:80])}' +``` + +### PRレビューコメントへの返信 + +```bash +# NG: /replies エンドポイントは存在しない(404になる) +gh api repos/OWNER/REPO/pulls/comments/{id}/replies -f body='...' +# => 404 Not Found + +# NG: -X POST を付けても同じ(エンドポイント自体が存在しない) +gh api -X POST repos/OWNER/REPO/pulls/comments/{id}/replies -f body='...' +# => 404 Not Found + +# OK: in_reply_to パラメータを使って新規コメントとして投稿 +gh api repos/OWNER/REPO/pulls/PR/comments \ + -f body="返信テキスト" \ + -F in_reply_to=COMMENT_ID +``` + +### レビュースレッドの Resolve(GraphQL) + +```bash +# 1. 未解決スレッドのID一覧を取得 +gh api graphql -f query=' +query { + repository(owner: "OWNER", name: "REPO") { + pullRequest(number: PR) { + reviewThreads(first: 50) { + nodes { + id + isResolved + comments(first: 1) { + nodes { path body } + } + } + } + } + } +}' --jq '.data.repository.pullRequest.reviewThreads.nodes[] | select(.isResolved == false) | {id, path: .comments.nodes[0].path}' + +# 2. スレッドを Resolve +gh api graphql -f query=' +mutation { + resolveReviewThread(input: {threadId: "PRRT_xxx"}) { + thread { isResolved } + } +}' +``` + +### PR の CI チェック結果 + +`gh pr checks` は1つでもfailがあると **exit code 1** で終了する。 +Claude Codeではコマンド失敗と判定されて処理が止まるため、必ず `|| true` を付ける。 + +```bash +# NG: failがあるとexit code 1で止まる +gh pr checks PR --repo OWNER/REPO + +# OK: exit codeを常に0にして出力を取得 +gh pr checks PR --repo OWNER/REPO 2>&1 || true + +# OK: 失敗のみフィルタ +gh pr checks PR --repo OWNER/REPO 2>&1 | grep -i fail || true +``` + +#### 重要: CIの完了を待ってはいけない + +- `--watch` や完了までのポーリングは **禁止**。現在のステータスを一度スナップショットするだけでよい。 +- チェックが `in_progress` / `queued` / `pending` の場合は **完了を待たず次のステップへ進む**。 +- 対応対象は **コード修正で直せるfailのみ**。以下のような「ステータス確認系」チェックは無視する: + - `check_pr_requirements` 等、PR要件・メタ情報のみ検証するもの + - Lint/テストに非依存なラベル/タイトル/説明チェック + - 外部サービス起因で自己修復するトランジェントなfail(再実行で直るもの) +- 対応する: ビルド失敗・テスト失敗・型エラー・lint違反など、**リポジトリ内コードの修正で解消可能なもの**。 + +```bash +# 失敗ジョブのログ(エラー行のみ抽出) +gh run view RUN_ID --repo OWNER/REPO --log-failed 2>&1 \ + | grep -E '(FAIL|Error|Tests:)' | head -20 || true +``` + +### 自分のPRは Approve できない + +``` +# GitHub の制約: 自分で作成した PR に APPROVE レビューは不可 +# => "Can not approve your own pull request" +# 対策: event を "COMMENT" に変更して送信 +``` + +### PR作成時の body は HEREDOC + +```bash +# NG: \n がリテラルで混入する可能性 +gh pr create --title "タイトル" --body "行1\n行2" + +# OK: HEREDOC形式 +gh pr create --title "タイトル" --body "$(cat <<'EOF' +## Summary +- 変更内容 + +## Test plan +- [ ] テスト項目 +EOF +)" +``` + +## AWS CLI の注意点 + +### CloudWatch ログストリーム名の [$LATEST] + +```bash +# NG: --query で [$LATEST] を含む文字列がパースエラー +aws logs get-log-events --query 'events[*].message' --output text + +# OK: --output json にして python でパース +aws logs get-log-events --output json | python3 -c " +import sys,json +data = json.loads(sys.stdin.read()) +for e in data['events']: + print(e['message'].strip()) +" +``` + +## エラー事例集 + +| エラーメッセージ | 原因 | 対策 | +|----------------|------|------| +| `fatal: pathspec '...' did not match any files` | CWD とパスの不一致 | `pwd` 確認後、CWD相対パスで指定 | +| `404 Not Found` (gh api replies) | `/comments/{id}/replies` は存在しない | `in_reply_to` パラメータで投稿 | +| `422 Unprocessable` (gh api) | `-f` で数値を渡した | 数値は `-F` を使う | +| `Can not approve your own pull request` | 自己 Approve 不可 | `COMMENT` イベントに変更 | +| `gh pr checks` が exit code 1 | 1つでもfailがあると非0終了 | `gh pr checks ... 2>&1 \|\| true` | +| `Unknown options: , , ,` (aws cli) | `[$LATEST]` のシェルエスケープ | `--output json` + python パース | + +## 詳細ガイド + +| ファイル | 内容 | 参照タイミング | +|---------|------|--------------| +| `01-common-errors.md` | 詳細なエラー事例と再現手順 | エラー発生時 | diff --git a/plugins/ndf/skills-claude/implementation-plan/SKILL.md b/plugins/ndf/skills-claude/implementation-plan/SKILL.md new file mode 100644 index 00000000..0e0a1307 --- /dev/null +++ b/plugins/ndf/skills-claude/implementation-plan/SKILL.md @@ -0,0 +1,98 @@ +--- +name: implementation-plan +description: "Create or update implementation plan files." +when_to_use: "実装開始時 / PR作成時に実装プランの作成・更新が必要なとき。複数ファイル変更・新機能追加・DBマイグレーションを含む変更で自動参照。Triggers: '実装プラン', '実装を開始', 'PR作成', 'implementation plan', 'plan first', '設計書を作成', 'issues/に追加'" +--- + +# 実装プランガイド + +## 基本方針 + +実装の開始時およびPR作成時に、`issues/` 配下に実装プランファイルが存在するか確認し、なければ作成する。プランを残すことで後任エンジニアや将来の自分が変更意図を追跡できる。 + +## 実装プランが必要なケース + +以下のいずれかに該当する場合は作成する: + +- 複数ファイルにまたがる変更 +- 新規機能の追加 +- 既存ロジックの大幅な変更 +- DBマイグレーションを伴う変更 +- 複数のタスクに分解できる作業 + +## 実装プランが不要なケース + +以下のような軽微な変更では不要: + +- typo修正、文言変更 +- 設定値の変更のみ +- 1ファイルで完結する軽微な修正 +- フォーマッター適用のみ +- ドキュメントのみの更新 + +判断に迷う場合はユーザーに確認する。 + +## ファイル配置・命名 + +- パス: `issues/` +- ファイル名に日本語は含めないこと(Git/CI/検索ツール互換性のため) +- タスクIDがある場合: `issues/TASK-1234_concise-description.md` +- タスクIDがない場合: `issues/{feature-name}.md` + +## PR作成時のプランファイル生成 + +PR作成時に `issues/` にプランファイルが存在しない場合、以下の情報源からプランファイルを生成する: + +1. **会話履歴** - それまでのやりとりから要件・背景・方針を抽出 +2. **git log** - コミット履歴からタスクの流れと変更概要を把握 +3. **git diff** - 実際の変更内容から修正対象ファイルと変更内容を特定 + +これらを組み合わせて、下記フォーマットに沿ったプランファイルを作成してからPRを作成する。 + +## プランのフォーマット + +```markdown +# {タスクID}: {機能名/修正内容} + +## 関連リンク +(Issue/チケット/設計ドキュメントがあれば記載) + +## 概要 +- 何を実装・修正するのか + +## 問題・背景 +- なぜこの変更が必要なのか(該当する場合) + +## 修正対象 +- 変更対象のファイルパス一覧 + +## タスク分解 + +### Task 1: {タスク名} +- **対象ファイル:** 変更対象のファイルパス +- **変更内容:** 具体的な変更内容 + +### Task 2: {タスク名} +- **対象ファイル:** 変更対象のファイルパス +- **変更内容:** 具体的な変更内容 + +## 影響範囲 +- 変更による影響を受ける機能やファイル + +## テスト計画 +- [ ] {実装した機能が正しく動作することの確認} +- [ ] {既存機能にリグレッションがないことの確認} +``` + +## ワークフロー + +1. 実装の依頼を受けたら、まずプランが必要か判断する +2. 必要な場合は `issues/` にプランファイルを作成してから実装を開始する +3. PR作成時にプランファイルが存在しない場合、必要であれば会話履歴・git log・git diffからプランファイルを生成してからPRを作成する + +## プランと PR Body の関係 + +- プランファイル = 「なぜ」「どう分解するか」を残す永続的な記録 +- PR body = 「何をやったか」「どうテストするか」のレビュー用サマリ + +同じ内容をコピーせず、PR bodyでは「詳細は `issues/xxx.md` 参照」と誘導してもよい。 diff --git a/plugins/ndf/skills-claude/investigation-rules/SKILL.md b/plugins/ndf/skills-claude/investigation-rules/SKILL.md new file mode 100644 index 00000000..a4757a83 --- /dev/null +++ b/plugins/ndf/skills-claude/investigation-rules/SKILL.md @@ -0,0 +1,105 @@ +--- +name: investigation-rules +description: "Write evidence-backed investigation and debug reports." +when_to_use: "調査・デバッグ・不具合レポートを作成するとき。「ない」「該当なし」等の否定的結論を出すときは必ず参照。Triggers: '調査', 'デバッグ', '不具合レポート', '原因調査', 'investigation', 'root cause', 'カラムがない', '該当コードがない', 'データがない'" +--- + +# 調査レポート作成ルール + +不具合調査・データ調査・仕様調査でレポートを作成する際のルール。コード読解だけに頼らず、必ず実行結果・出力・実データで裏取りする。 + +## 否定的結論にはエビデンス必須 + +「カラムがない」「データがない」「関数が呼ばれていない」「該当コードがない」等の **否定的な結論** を書く場合、**必ず実行結果をエビデンスとして添付すること**。 + +### なぜこのルールが必要か + +AIは「もっともらしいが間違った推論」をしがちで、コード読解だけで「ない」と断定して誤判断を招きやすい。事例として、外部テーブルの一部カラムだけを見て「該当カラムなし」と結論づけたが、実際には別名のカラムにデータが存在していた、という判断ミスが典型。 + +### 具体的な裏取り方法 + +| 主張の種類 | 必須エビデンス | +|-----------|--------------| +| DB: カラムが存在しない | `SHOW COLUMNS FROM table_name` / `DESCRIBE` の結果 | +| DB: データが存在しない | `SELECT COUNT(*) FROM table WHERE ...` の結果 | +| DB: テーブルが存在しない | `SHOW TABLES LIKE '%keyword%'` の結果 | +| コード: 関数/シンボルが存在しない | `grep -rn 'name' .` / LSP検索 / Serena `find_symbol` の結果 | +| コード: 呼び出し箇所がない | `find_referencing_symbols` / `grep` の結果 | +| 設定: 値が存在しない | 設定ファイルのdiff / `env` / `config` コマンド出力 | +| ログ: エラーが出ていない | `grep` / 検索ツールのクエリと結果期間 | + +### レポートへの記載例 + +```markdown +### 残課題 + +| 課題 | 概要 | エビデンス | 優先度 | +|------|------|-----------|--------| +| 外部API の retry 未実装 | Xクライアントで retry ハンドリングが無い | `grep -rn "retry\|Retry" src/client/x/` → 0件 | 中 | +| status=deleted の件数 | 論理削除レコードが残存 | `SELECT COUNT(*) FROM ... WHERE status='deleted'` → 2,341件 | 低 | +``` + +### やってはいけないこと + +- コードを読んだだけで「このカラムは存在しない」と断定する +- 1つのテーブル/ファイルだけ見て「データに問題はない」と結論づける +- 外部テーブルの一部のカラムだけ見て「他にはない」と判断する(全カラムを確認する) +- エビデンスなしで残課題の優先度を「低」にする(誤判断の典型) + +## 外部データ調査の原則 + +外部API/外部テーブル/サードパーティデータソースを調査する際は、**全体構造を必ず確認する**。 + +```sql +-- まず全体像を把握する +SHOW COLUMNS FROM external_source_table; + +-- 次に対象カラムのデータ分布を確認する +SELECT column_name, COUNT(*) FROM table GROUP BY column_name; +``` + +外部データは外部システム由来でカラム名・値域が予測しづらいため、コードから逆引きするだけでは見落とす。 + +## ハルシネーション防止チェックリスト + +推論で埋めず、必ず以下を実行して裏取りする: + +| チェック項目 | 方法 | +|------------|------| +| カラム/フィールドが存在するか | `SHOW COLUMNS` / スキーマ定義ファイルを開く | +| データが存在するか | `SELECT COUNT(*) WHERE ...` / サンプルレコード取得 | +| 型が一致するか | DB定義とアプリコード両方を確認(Eloquent `$casts`、dataclass型等) | +| FK/制約が存在するか | マイグレーション履歴を追跡(追加→削除→再追加の変遷を確認) | +| 論理削除ポリシーは何か | `SoftDeletes` / `deleted_at` の有無を確認 | +| 環境差異がないか | dev/staging/prod で同じクエリを実行して比較 | + +## 調査結果の書き方テンプレート + +```markdown +## 症状 +何がどう間違っているか(定量的に、エビデンス付きで) + +## 調査経緯 +1. 仮説1: xxx → クエリ/コマンドで確認 → 否定/肯定 +2. 仮説2: yyy → ... + +## 根本原因 +コードレベルでどこが問題か(ファイル名:行番号で特定) + +## エビデンス +``` +SQL/コマンド実行結果をそのまま貼る +``` + +## 修正方針 +どのフェーズで何を直すか(多層防御の観点) + +## 検証手順 +修正後にどう確認するか(回帰テスト含む) +``` + +SQLクエリ結果・コマンド出力をそのまま貼り、「コードを読んだ推測」と「実行して確認した事実」を明確に区別する。 + +## 関連スキル + +- `/ndf:problem-solving` — 根本原因分析と多層防御の原則 diff --git a/plugins/ndf/skills-claude/issue-plan-strategy/SKILL.md b/plugins/ndf/skills-claude/issue-plan-strategy/SKILL.md new file mode 100644 index 00000000..4275a379 --- /dev/null +++ b/plugins/ndf/skills-claude/issue-plan-strategy/SKILL.md @@ -0,0 +1,335 @@ +--- +name: issue-plan-strategy +description: "Turn issues into plans and implementation workflows." +when_to_use: "issue → plan 作成 / 既存 plan の実装 (実行) を依頼されたとき。複数 PR に分割される設計や、release branch + 個別 PR + worktree 運用が必要なときに参照する。Triggers: 'issueのplanを作って', 'PLANxxの設計', '設計書を起こして', 'このplanを実装して', 'PLANxxを実装', 'planを実行', 'release branch 作って実装開始', 'multi-PR で進めて'" +argument-hint: "[issue-path-or-url] (例: issues/i16.md, https://github.com/org/repo/issues/123)" +allowed-tools: + - Bash + - Read + - Write + - Edit + - Glob + - Grep +--- + +# issue → plan → multi-PR ワークフロー + +1 つの issue から plan を作る際、推奨される PR が複数に分かれることは日常的に発生する。本 skill はその際の **release ブランチ + 個別 PR ブランチ + Draft PR 先行作成 + git worktree 並行開発 + レビュー運用** の標準フローを規定する。 + +本 skill は **plan の作成フェーズと plan の実行(実装)フェーズの両方** をカバーする。同じワークフローが「設計を起こす段階」と「設計に従って実装する段階」を貫通することで、作成者と実装者(あるいは将来の自分)が同じ手順を共有できる。 + +## 発動条件 + +| トリガ | 例 | 入る Step | +|---|---|---| +| スラッシュコマンド (引数あり) | `/ndf:issue-plan-strategy issues/foo.md`、`/ndf:issue-plan-strategy https://github.com/org/repo/issues/123` | Step 0 から | +| スラッシュコマンド (引数なし) | `/ndf:issue-plan-strategy` (現在ブランチで作業中の issue/plan を解析) | Step 0 から | +| 自動発動 (作成系) | 「この issue の plan を作って」「設計書を起こして」「PLAN42 の設計を起こして」 | Step 1〜2 | +| 自動発動 (実行系) | 「この plan を実装して」「PLAN42 を実行して」「multi-PR で進めて」「release branch を切って実装開始」 | Step 0 → 既存 plan を読み → Step 3 以降 | + +引数で渡された issue / plan は **ファイルパス / URL / 番号** いずれでも受け付ける: + +- ファイルパス (`issues/PLANxx_*.md`): 直接 Read +- GitHub Issue URL / `#番号`: `gh issue view --json title,body,labels` で取得 +- それ以外の文字列: そのまま issue 本文として扱う + +## Step 0: 作成フェーズか実行フェーズか判定 + +最初に **既に plan ファイルが存在するか** で判定する。skill 内で `Glob` を使うのが第一選択 (例: `Glob('issues/*PLAN42*')`)。shell で確認する場合は: + +```bash +# issues/ 配下に該当 plan があるか (PLAN42 / feature-name 部分は実値に置換) +find issues/ -maxdepth 1 -iname '*PLAN42*' -o -iname '*feature-name*' +``` + +| 状況 | 進むフェーズ | +|---|---| +| plan ファイルがない / issue しかない | **作成フェーズ** (Step 1〜2 へ) | +| plan ファイルがあり、release branch がない | **実行フェーズ・初期化** (Step 3 へ) | +| release branch も Draft PR も既にある | **実行フェーズ・継続** (Step 5 以降。worktree / 並行開発 / レビュー / merge を進める) | + +実行フェーズで入った場合、既存 plan の **「PR 分割計画」セクション**を必ず Read してから Step 3 以降の自動化判断に使う。 + +## 全体フロー + +``` + ┌─ 作成フェーズ ──────────────────────────────────────┐ +issue 取得 ─┤ │ + │ plan 作成 (必要なら plan モード) ─ 単一PR? ─ YES ─▶ implementation-plan + /ndf:pr で完了 + │ │ + │ NO + └──────────────────────────────────────────┼──────────┘ + ▼ + ┌─ 実行フェーズ ──────────────────────────────────────┐ +既存 plan ─▶│ Step 3: release branch 作成 + Draft release PR │ + │ Step 4: 個別 PR ブランチ作成 + 各 Draft PR (release base) + │ Step 5: git worktree で並行開発 (依存関係を考慮) │ + │ Step 6: 個別 PR ごとに /ndf:review or /ndf:cross-review + │ → /ndf:fix → merge into release │ + │ Step 7: release ブランチで結合テスト相当のレビュー │ + │ Step 8: release PR body 最終化 → Ready & merge │ + └─────────────────────────────────────────────────────┘ +``` + +QA / staging 等の検証環境向けには、個別 PR or release PR 単位で `/ndf:cherry-pick-pr` を別途実行する (Step 9)。 + +実行フェーズに途中から入った場合は、対応する Step の途中再開で構わない。各 Step の冒頭で **既に存在するブランチ / PR / worktree を `git branch -a` / `gh pr list` / `git worktree list` で確認**してから作業に入る。 + +## Step 1: issue 取得と plan 作成 (作成フェーズ専用) + +> 実行フェーズで入った場合はこの Step をスキップし、既存 plan を Read して Step 3 へ進む。 + +1. 引数を解釈して issue 本文を取得する +2. `issues/` 配下に plan ファイルが既に存在するか `Glob` で確認する +3. なければ `/ndf:implementation-plan` の **プランフォーマット**に従って plan ファイルを作成する + - ファイル名は英数 (例: `issues/PLAN42_multi-pr-refactor.md`) + - 内容に「複数 PR に分割する根拠」「PR 単位と依存関係」を必ず含める +4. 設計判断が重い場合は **Claude Code の plan モード** (ExitPlanMode を用いる読み取り専用フェーズ) に切り替えて十分検討してから実装へ進む + +plan の構造は `/ndf:implementation-plan` を参照。本 skill では multi-PR を前提に **以下のセクションを追加**する: + +```markdown +## PR 分割計画 + +| PR # | branch 名 | 概要 | 依存 | 並行可否 | +|---|---|---|---|---| +| 1 | feature/PLAN42-schema | スキーマ追加 | なし | ○ | +| 2 | feature/PLAN42-api | API 実装 | PR1 | × (PR1 merge 後) | +| 3 | feature/PLAN42-ui | UI 実装 | PR1 | ○ (mock で開始可) | + +release branch: `release/PLAN42` +base branch: `main` +``` + +## Step 2: 単一 PR で足りるか判定 + +plan を書いた結果が以下のいずれかなら **release ブランチを作らず**、`/ndf:implementation-plan` + `/ndf:pr` の通常フローに切り替える: + +- 変更ファイルが 1〜2 個で結合度が低い +- 1 PR で安全に review 可能 (差分 ~500 行以内が目安) +- 依存関係のある複数タスクが存在しない + +複数 PR が妥当な場合 (スキーマ + API + UI、機能追加 + マイグレーション、複数モジュール横断 等) のみ Step 3 に進む。 + +## Step 3: release ブランチ + Draft PR 先行作成 (実行フェーズの開始点) + +> 実行フェーズで自動発動した場合の最初の自動化対象。既に `release/` ブランチや Draft PR が存在する場合は作成をスキップし、Step 4 へ進む。 + +### release ブランチ作成 + +```bash +git fetch origin +git checkout -b release/ origin/ +git push -u origin release/ +``` + +### レビュアー視点の原則 (release PR body の大前提) + +個別 PR はセルフレビュー (`/ndf:cross-review` 等) で merge される。**人間のレビュアーが見るのは release PR だけ**であり、個別 PR の存在をレビュアーに意識させてはならない。したがって: + +- release PR の body は **self-contained 必須**: 「何のために」(背景・解決したい課題) と「何を」(release ブランチ全体としての変更内容) を、**個別 PR を一切参照せずに**理解できる粒度で書く +- 個別 PR リンクの列挙を body の本文にしない。開発中の進捗管理に使う場合は `
` 折りたたみ内の補足情報に格下げする +- `/ndf:cross-review` の light rotation と同じ原則を適用する: 現状の差分・実装を反映し、内部用語 (PLAN-ID 運用、round、rotated 等) をレビュアー向け本文に漏らさない + +### release → default の Draft PR を先行作成 + +```bash +gh pr create \ + --base \ + --head release/ \ + --draft \ + --title "release: <概要>" \ + --body "$(cat <<'EOF' +## Summary +- (背景) なぜこの変更が必要か / 解決したい課題 +- (変更内容) release ブランチ全体として何をするか +- plan: issues/_xxx.md + +## Test plan (結合観点のみ) +- [ ] 個別 PR では検出できない結合テスト項目 + +
+開発用: 個別 PR 進捗 (レビュー対象外) + +- [ ] # PR1: ... +- [ ] # PR2: ... +- [ ] # PR3: ... + +
+ + +EOF +)" +``` + +Draft 作成時点では実装が進んでいないため body は plan ベースの暫定でよいが、Ready for review 前に **実装の最終形を反映した body へ最終化**する (Step 8 参照)。 + +release PR を **先に作る理由**: PR 番号が確定し、個別 PR の説明から参照できるため。 + +## Step 4: 個別 PR ブランチ + Draft PR 先行作成 + +> 既存ブランチは `git branch -a | grep "feature/-"` で確認し、未作成のものだけ作る。Draft PR の存在は `gh pr list --base release/ --state all` で確認。 + +各 PR について **同じパターンで先に Draft PR まで作る**: + +```bash +# release ブランチを base に個別ブランチを切る +git fetch origin release/ +git checkout -b feature/- origin/release/ + +# 空コミットで push して Draft PR を作る (base=release と HEAD が同一だと +# gh pr create が "No commits between ..." で失敗するため、差分ゼロのまま PR +# 作成のトリガにする目的で `--allow-empty` を使う) +git commit --allow-empty -m "chore: - Draft PR 作成" +git push -u origin feature/- + +gh pr create \ + --base release/ \ + --head feature/- \ + --draft \ + --title "feat: - <概要>" \ + --body "$(cat <<'EOF' +## Summary +- plan: issues/_xxx.md +- release PR: # +- 担当範囲: + +## Test plan +- [ ] ... + + +EOF +)" +``` + +完了後 release PR の本文を `gh pr edit` で更新し、`
` 内の開発用チェックリストに個別 PR 番号を埋める (body 本文には書かない)。 + +## Step 5: git worktree で並行開発 + +並行可能 (依存なし or mock で先行可) な PR は **git worktree** で同時に開く: + +```bash +# repo ルート (default branch のまま) で +git worktree add ../--schema feature/-schema +git worktree add ../--ui feature/-ui + +# それぞれの worktree で別ターミナル / 別エージェントを起動 +``` + +ガイドライン: + +- **依存のある PR は順次着手**する (PR1 merge → PR2 開始) +- 並行 PR 間で同じファイルを触る場合は事前にレビュー観点で分担を明確化する +- 終わった worktree は `git worktree remove ` で片付ける +- Claude Code から並行開発を指示する場合、Agent tool の `isolation: "worktree"` も検討する + +## Step 6: 個別 PR のレビュー + +**レビューは原則個別 PR 単位**で行う: + +| 用途 | コマンド | +|---|---| +| PR 作成前のセルフレビュー | `/ndf:review-branch` | +| GitHub 上の単体レビュー | `/ndf:review ` | +| codex + gemini 両方の収束ループ | `/ndf:cross-review ` | +| 指摘の修正 | `/ndf:fix ` | + +個別 PR が APPROVE → Draft 解除 → release ブランチへ merge (squash 推奨)。 + +## Step 7: release ブランチのレビュー (結合テスト相当のみ) + +release ブランチへの merge が一通り進んだ段階で: + +- **個別 PR で見た観点を再レビューしない** +- **結合テスト相当**の観点のみレビューする: + - PR 間の API / 型 / スキーマ整合 + - 設定値の重複・矛盾 + - migration の順序依存 + - E2E シナリオ (`/ndf:playwright-scenario-test` の活用) +- ここで個別 PR 範囲のバグが見つかった場合は、**release PR にコメントせず**、該当の個別 PR (既に merge 済みなら新しい修正 PR を release 配下に作成) 側に指摘を書き込み、修正ループを回す +- release PR には integration 観点の指摘のみ残す + +## Step 8: release PR body の最終化と release → default の merge + +### body の最終化 (Ready for review の前に必須) + +個別 PR が全て merge されたら、**Draft 解除の前に** release PR の body を実装の最終形を反映した self-contained な内容へ更新する: + +```bash +# release ブランチ全体の差分を確認して body を書き直す +git fetch origin +git diff origin/...origin/release/ --stat +gh pr edit --title "..." --body "..." +``` + +最終化のチェック観点 (Step 3 のレビュアー視点の原則を満たすこと): + +- [ ] 「何のために」「何を」が個別 PR や plan ファイルを辿らずに理解できる +- [ ] 実装中の方針変更・スコープ増減が body に反映されている +- [ ] 個別 PR への参照が本文に残っていない (`
` 内の開発用情報は残してよい) +- [ ] 内部用語 (round、rotated 等) が漏れていない + +### Draft 解除と merge + +release PR が APPROVE されたら: + +```bash +# Draft 解除 +gh pr ready +# merge: 個別 PR が既に squash 済みで release ブランチに並んでいるため、 +# main 側でも個別 PR 単位の commit を追跡できる `--merge` (merge commit 保持) +# が既定として推奨。プロジェクト規約で線形履歴必須なら `--rebase`、 +# それ以外で commit 数を 1 本にしたい場合のみ `--squash`。 +gh pr merge --merge --delete-branch +``` + +merge 後は plan ファイル末尾に「完了サマリ」(マージ済み PR 番号 / 検証結果) を追記してクローズ化する。 + +## Step 9: 検証環境 (qa/staging 等) への適用 + +QA / staging 検証は **個別 PR 単位** or **release ブランチ単位** のどちらでも OK。 +`/ndf:cherry-pick-pr` は Claude Code 内の slash command なので、shell ではなく +Claude Code セッション上で実行する点に注意。 + +個別 PR 単位で qa に反映する場合: + +```text +# (Claude Code 内で実行する slash command) +/ndf:cherry-pick-pr qa/staging +``` + +release ブランチごと qa に反映する場合 (まとまった検証が必要な場合): + +```bash +# 1. shell で release ブランチに切り替え +git checkout release/ +``` + +```text +# 2. (Claude Code 内で実行する slash command) +/ndf:cherry-pick-pr qa/staging +``` + +詳細は `/ndf:cherry-pick-pr` と `/ndf:branch-fix-strategy` を参照。`feature → main` 系 PR を汚染しないため、検証ブランチ向けは必ず短命ブランチ経由で扱う。 + +## アンチパターン + +| ❌ やってはいけないこと | 理由 | +|---|---| +| release ブランチを作らず巨大な 1 PR で出す | レビュー困難・revert 困難・並行開発不可 | +| 個別 PR の base を default にする | release で統合する意味が失われ、partial merge が default を汚染する | +| 個別 PR Draft 作成を実装後に回す | PR 番号が未確定でクロス参照や CI 待機の段取りが組めない | +| release PR で個別 PR 範囲の指摘を解決しようとする | 該当 PR が既に閉じている場合、コミット意図がずれる | +| release PR の body を個別 PR リンクの列挙だけにする | レビュアーは release PR 単体で変更を把握できず、個別 PR や plan を辿ることになる。body は self-contained 必須 (Step 3 / Step 8) | +| body 最終化せずに Ready for review にする | Draft 作成時の plan ベースの暫定 body のままだと実装の最終形と乖離する | +| 検証ブランチを feature/release に merge する | `feature → main` PR への汚染 (詳細: `/ndf:branch-fix-strategy`) | + +## 関連 skill + +- `/ndf:implementation-plan` — plan ファイルのフォーマット (本 skill が依存) +- `/ndf:branch-fix-strategy` — ブランチ汚染を避ける原則 +- `/ndf:pr` — 通常の PR 作成 / 更新 +- `/ndf:cherry-pick-pr` — 検証ブランチへの cherry-pick PR +- `/ndf:review` / `/ndf:review-branch` / `/ndf:cross-review` — レビュー +- `/ndf:fix` / `/ndf:resolve-pr-comments` — コメント対応 +- `/ndf:playwright-scenario-test` — release ブランチでの E2E 結合テスト diff --git a/plugins/ndf/skills-claude/logging-guidelines/SKILL.md b/plugins/ndf/skills-claude/logging-guidelines/SKILL.md new file mode 100644 index 00000000..007b9691 --- /dev/null +++ b/plugins/ndf/skills-claude/logging-guidelines/SKILL.md @@ -0,0 +1,112 @@ +--- +name: logging-guidelines +description: "Design safe and useful application logging." +when_to_use: "コードにログを追加・修正・整理するとき。Triggers: 'ログ追加', 'log追加', 'logger', 'logging', 'ログレベル', 'log level', 'デバッグログ', 'エラーログ', 'logger.info', 'logger.error', 'print文をログに'" +--- + +# ログ運用ガイドライン + +コードにログを追加・修正する際は、以下のルールに従うこと。言語/フレームワークに依存しない原則として記述している。 + +## ログレベルの選択基準 + +| レベル | 用途 | 本番出力(推奨) | +|--------|------|---------------| +| `error` | 例外発生、処理失敗 | o | +| `warning` | データ不備でスキップ、処理継続可能な異常 | o | +| `info` | バッチ開始/完了、重要なビジネスイベント | 環境による(本番off推奨) | +| `debug` | 開発向けデバッグ情報 | x | + +**推奨**: 本番は `LOG_LEVEL=warning` 以上。info/debug は開発・ステージングのみで出力する。 + +## 使用を避けるログレベル + +以下は用途が曖昧または過剰なため、明示的な運用規則がない限り使わない: + +- `notice` — error/warning/info と区別が曖昧 +- `critical`, `alert`, `emergency` — 通常のアプリには過剰。運用規則として「PagerDuty起動基準」などが定義されていない限り使わない + +## ループ内ログのルール + +### 原則: ループ内では info/warning を出力しない + +ループ内で1件ずつログを出力すると、大量データ処理時にログが爆発する。ループ後にサマリーとしてまとめて出力すること。 + +### サマリーログ化パターン(擬似コード) + +``` +# NG: ループ内で1件ずつ出力 +for item in items: + log.info("処理完了", id=item.id) + +# OK: ループ後にまとめて出力 +processed_count = 0 +for item in items: + # 処理... + processed_count += 1 +log.info("バッチ処理完了", processed_count=processed_count) +``` + +### エラー蓄積パターン + +ループ内で例外が発生し処理を継続する場合は、エラー情報を蓄積してループ後にまとめて報告する。先頭N件のみ含めることで、ログサイズ爆発を防ぐ。 + +``` +errors = [] +for item in items: + try: + process(item) + except Exception as e: + errors.append({"id": item.id, "error": str(e)}) + +if errors: + log.error( + "処理で一部失敗", + total_count=len(items), + failed_count=len(errors), + sample_errors=errors[:10], # 先頭10件のみ + ) +``` + +### ループ内 debug も必要最小限 + +ループ内での debug 出力は、他に代替手段がなく調査に不可欠な場合のみ許容。デフォルトは「ループ外で件数サマリ」を基本とする。 + +## 例外処理のルール + +1. **例外は最上位でログ出力** — エントリポイント(コマンド/コントローラー/ジョブ)で catch してログ出力 +2. **再スロー時はログ不要** — 上位で出力されるため二重出力を避ける +3. **例外を握りつぶさない** — catch後に何も報告せず続行するのは禁止 +4. **広めの例外型で捕捉** — 言語の最上位例外型(Python `Exception`、PHP `Throwable`、Java `Throwable` 等)でトップレベル catch する + +## 必須ルール + +1. **コンテキスト情報を含める** — 調査に必要なID等を構造化ログとして渡す +2. **機密情報を含めない** — パスワード、トークン、クレジットカード番号、個人特定情報は禁止 +3. **メッセージは明確に** — 何が起きたか分かる言葉で記述(プロジェクトの言語ポリシーに従う) +4. **ロガー呼び出しを統一** — プロジェクトで統一ファサード/クライアントを使う(例: Laravel は `Log::`, Python は `logging.getLogger(__name__)`) +5. **グローバル/暗黙の名前空間を使わない** — 明示的にimport/useする + +## ログとメトリクスの使い分け + +- **ログ**: 個別のイベント、エラー、コンテキスト情報(構造化ログ) +- **メトリクス**: 件数、レイテンシ、成功/失敗率の集計(Prometheus/DataDog等) +- **トレース**: リクエスト横断の実行フロー(OpenTelemetry等) + +ループ件数カウントなどは、ログではなくメトリクスに寄せるのが望ましい場合が多い。 + +## アンチパターン一覧 + +| アンチパターン | 問題 | +|--------------|------| +| `log.info("")` / 空メッセージ | 意図が伝わらない | +| `log.error(e)` のみ | スタックトレース/contextが欠ける | +| 機密情報をそのままログに入れる | 情報漏洩リスク | +| ループ内で毎回 info 出力 | ログ爆発 | +| try/except で握りつぶし、何も報告しない | 障害の気配を消す | +| 複数行の ASCII ART をログに含める | grep/集計が困難 | + +## 関連スキル + +- `/ndf:problem-solving` — ログから根本原因を特定する手順 +- `/ndf:investigation-rules` — ログをエビデンスとして扱う際の注意点 diff --git a/plugins/ndf/skills-claude/markdown-writing/01-diagram-guide.md b/plugins/ndf/skills-claude/markdown-writing/01-diagram-guide.md new file mode 100644 index 00000000..db40f52b --- /dev/null +++ b/plugins/ndf/skills-claude/markdown-writing/01-diagram-guide.md @@ -0,0 +1,144 @@ +# 図表作成ガイド + +## mermaid 記法 + +### フローチャート + +```mermaid +graph TD + A[開始] --> B{条件判定} + B -->|Yes| C[処理A] + B -->|No| D[処理B] + C --> E[終了] + D --> E +``` + +### シーケンス図 + +```mermaid +sequenceDiagram + User->>API: リクエスト + API->>DB: クエリ + DB-->>API: 結果 + API-->>User: レスポンス +``` + +### クラス図 + +```mermaid +classDiagram + class User { + +int id + +string name + +login() + +logout() + } + class Order { + +int id + +float total + } + User "1" --> "*" Order +``` + +### ER図 + +```mermaid +erDiagram + USER ||--o{ ORDER : places + ORDER ||--|{ LINE_ITEM : contains + PRODUCT ||--o{ LINE_ITEM : "ordered in" +``` + +## plantUML 記法 + +### コンポーネント図 + +```plantuml +@startuml +package "Frontend" { + [React App] +} +package "Backend" { + [API Server] + [Database] +} +[React App] --> [API Server] +[API Server] --> [Database] +@enduml +``` + +### アクティビティ図 + +```plantuml +@startuml +start +:ユーザー入力; +if (有効?) then (yes) + :処理実行; +else (no) + :エラー表示; +endif +stop +@enduml +``` + +## ASCII 許可例(ツリーのみ) + +ディレクトリ構造はASCIIで表現可能: + +``` +project/ +├── src/ +│ ├── components/ +│ └── utils/ +├── tests/ +└── docs/ +``` + +## よくある間違い + +### 避けるべき: ASCII ARTで図を描く + +``` + ┌─────────┐ + │ User │ + └────┬────┘ + │ + ┌────▼────┐ + │ API │ + └─────────┘ +``` + +上記のような図は **mermaid** で描いてください: + +```mermaid +graph TD + User --> API +``` + +### 避けるべき: 順序prefixなしで分割 + +``` +docs/ +├── introduction.md ← NG: prefixがない +├── setup.md +└── usage.md +``` + +正しい方法: + +``` +docs/ +├── 01-introduction.md ← OK +├── 02-setup.md +└── 03-usage.md +``` + +## ベストプラクティス + +| DO | DON'T | +|----|-------| +| mermaid/plantUMLで図を描く | ASCII ARTで図を描く | +| 300行以内に収める | 1000行超の巨大ファイル | +| 順序prefixで分割 | prefixなしで分割 | +| 2桁パディング(01-, 02-) | 1桁(1-, 2-) | diff --git a/plugins/ndf/skills-claude/markdown-writing/SKILL.md b/plugins/ndf/skills-claude/markdown-writing/SKILL.md new file mode 100644 index 00000000..56b35839 --- /dev/null +++ b/plugins/ndf/skills-claude/markdown-writing/SKILL.md @@ -0,0 +1,58 @@ +--- +name: markdown-writing +description: "Write Markdown docs, diagrams, and split files." +when_to_use: "Markdown 文書 / 図表を作成 / 編集するとき。Triggers: 'Markdown作成', 'ドキュメント作成', '文書作成', '図を描く', 'mermaid', 'create document', 'write docs'" +allowed-tools: + - Read + - Write + - Edit +--- + +# Markdown Writing Skill + +## 重要ルール + +### 1. 図表作成ルール + +**mermaid または plantUML を使用**(ASCII ART禁止、ツリー除く) + +```mermaid +graph TD + A[開始] --> B{条件判定} + B -->|Yes| C[処理A] + B -->|No| D[処理B] +``` + +### 2. 文書の長さと分割ルール + +| ページ数 | 対応 | +|---------|-----| +| ~300行 | そのまま | +| 301~600行 | 2ファイルに分割 | +| 600行以上 | セクションごとに分割 | + +**分割時のファイル名**: 順序prefix(01-, 02-, ...)+ ケバブケース + +``` +docs/feature-guide/ +├── 01-introduction.md +├── 02-installation.md +└── 03-usage.md +``` + +## チェックリスト + +- [ ] 図表はmermaid/plantUML使用(ツリー除く) +- [ ] ファイル長は300行以内(超える場合は分割) +- [ ] 分割時は順序prefix使用(01-, 02-, ...) + +## 詳細ガイド + +| ファイル | 内容 | +|---------|------| +| `01-diagram-guide.md` | mermaid/plantUML記法、よくある間違い | + +## 関連リソース + +- [Mermaid公式ドキュメント](https://mermaid.js.org/) +- [PlantUML公式ドキュメント](https://plantuml.com/) diff --git a/plugins/ndf/skills-claude/merged/SKILL.md b/plugins/ndf/skills-claude/merged/SKILL.md new file mode 100644 index 00000000..06af6f2a --- /dev/null +++ b/plugins/ndf/skills-claude/merged/SKILL.md @@ -0,0 +1,29 @@ +--- +name: merged +description: "Clean up after a PR is merged." +argument-hint: "[PR番号]" +disable-model-invocation: true +allowed-tools: + - Bash + - Read +--- + +# マージ後クリーンアップコマンド + +PRマージ後のクリーンアップを実行。 + +## 手順 + +0. **事前確認**: github mcpで引数の(引数が無ければ自身が作成した最新の)PRがmainにmergeされていることを確認。mergeされていなければ終了 +1. **事前確認**: `git status`→変更あればstash +2. **main更新**: `git checkout main`→`git pull` +3. **worktreeクリーンアップ**: `git worktree list` で当該PR番号に対応する worktree (`pr`) を探し、あれば `git worktree remove ` で削除(worktree 内の `.cross_review/` も一緒に消える) +4. **ブランチ削除**: `git branch -d ` → stash復元 + +**注意**: 冪等性保証・エラー時中断・削除済み無視 + +## 作業完了報告(必須) + +- 実行サマリー(PRタイトル、マージコミット、削除したブランチ、現在のブランチ) +- mainブランチの状態 +- PR URL diff --git a/plugins/ndf/skills-claude/ndf-policies/SKILL.md b/plugins/ndf/skills-claude/ndf-policies/SKILL.md new file mode 100644 index 00000000..eb25c338 --- /dev/null +++ b/plugins/ndf/skills-claude/ndf-policies/SKILL.md @@ -0,0 +1,10 @@ +--- +name: ndf-policies +description: "Apply core NDF project policies." +user-invocable: false +--- + +# NDFポリシー + +このスキルはNDFプラグインの基本ポリシーを定義します。 +descriptionフィールドが常時コンテキストに注入されるため、本文の参照は不要です。 diff --git a/plugins/ndf/skills-claude/pr-tests/SKILL.md b/plugins/ndf/skills-claude/pr-tests/SKILL.md new file mode 100644 index 00000000..39f13de3 --- /dev/null +++ b/plugins/ndf/skills-claude/pr-tests/SKILL.md @@ -0,0 +1,31 @@ +--- +name: pr-tests +description: "Run PR test plans and comment results." +argument-hint: "[PR番号]" +disable-model-invocation: true +allowed-tools: + - Bash + - Read + - Glob + - Grep +--- + +# PR Test Plan実行 + +`/ndf:pr`で作成されたPRのTest Plan(チェックリスト形式)を読み取り、各テスト項目を自動実行する。 + +**制約**: テスト実行と結果報告のみ。コード修正・git操作・ファイル編集は行わない。 + +## 引数 + +- PR番号(オプション): 省略時は現在ブランチから自動検出 + +## 手順 + +1. **PR情報取得**: PR本文からTest Planセクションの`- [ ]`項目をパース +2. **テスト実行計画**: テスト種類の判定、実行順序の決定、自動/手動の分類 +3. **テスト実行**: 各項目を順次実行し成功/失敗を記録 +4. **結果反映**: + - 成功: PR本文の`- [ ]`を`- [x]`に更新 + - 失敗: PRにコメント追加(問題点・対策案・エラー詳細) +5. **最終報告**: テスト結果サマリーをPRにコメント(総テスト数、成功/失敗/スキップ数、成功率) diff --git a/plugins/ndf/skills-claude/pr/SKILL.md b/plugins/ndf/skills-claude/pr/SKILL.md new file mode 100644 index 00000000..22000e4c --- /dev/null +++ b/plugins/ndf/skills-claude/pr/SKILL.md @@ -0,0 +1,161 @@ +--- +name: pr +description: "Commit, push, and create or update PRs." +argument-hint: "[--draft] [base-branch] or [commit-message]" +disable-model-invocation: true +allowed-tools: + - Bash + - Read + - Glob + - Grep +--- + +# PR作成 + +このプロジェクトのコードをcommit, pushし、GitHubでPull Requestを作成する。既にPRがあればPR説明を最新の変更内容に更新する。 + +**制約**: デフォルトブランチ(main, masterなど)で直接コミット禁止 + +## 使用方法 + +``` +/ndf:pr # main へ通常PR作成 +/ndf:pr --draft # main へドラフトPR作成 +/ndf:pr "新機能の追加" # コミットメッセージ指定 +/ndf:pr --draft "wip: 作業中" # ドラフトPR + メッセージ指定 +/ndf:pr qa/staging # base非main → cherry-pick-prへ誘導 +``` + +## 引数の解釈 + +- `--draft` が含まれていればドラフトPR +- 既知のベースブランチ名(`main`, `master`, `qa/*`, `release/*`, `staging/*` 等)が末尾にあればベース指定 +- それ以外の文字列はコミットメッセージとして扱う +- デフォルトは `main` ベース、非ドラフト + +## 手順 + +### 0. PR確認 + +- `git branch --show-current` で現在ブランチを確認 +- `gh pr list --head ` で既存PR確認 +- 既にPRが存在しOPEN状態なら: + - `git add` → `git commit`(日本語メッセージ)→ `git push` + - **既存PR説明を更新** する(「PR説明の更新」節を参照) + - 終了報告 +- PRがない、またはmerge/close済みなら次へ + +### 1. ブランチ確認・切り替え + +- デフォルトブランチの場合: 新featureブランチを作成して切り替え +- デフォルトブランチ以外: `git stash` → `git pull origin `(コンフリクト時は停止しユーザに報告)→ `git stash pop` + +### 2. ベースブランチ判定 + +- 引数の末尾が `main`/`master` 以外のベースブランチ名(`qa/staging`, `release/v2` 等)の場合: + - **警告を出して `/ndf:cherry-pick-pr ` に誘導する** + - 理由: base非mainのPRに直接pushすると `feature → main` のPRに環境固有コードが混入する(詳細は `/ndf:branch-fix-strategy`) + - ユーザーが明示的に継続を指示した場合のみ進める + +### 3. 変更コミット + +- `git status` → `git add` → `git commit`(日本語メッセージ) +- 引数で指定されたコミットメッセージがあればそれを使用、なければ差分から生成 +- 上位階層を含むすべての変更をcommit + +### 4. プッシュ + +```bash +git push -u origin +``` + +### 5. PR作成 + +- `.github/pull_request_template.md` が存在すれば適用 +- `--draft` 指定ならドラフトPR作成 +- タイトル・説明は日本語、body は `## Summary` + `## Test plan` +- 機密情報(トークン、パスワード、APIキー等)を含めない +- body 末尾に `` を入れる +- **body は必ずHEREDOC形式で渡す**(`\n` リテラル混入防止): + +```bash +gh pr create --title "タイトル" $DRAFT_FLAG --body "$(cat <<'EOF' +## Summary +- 変更内容 + +## Test plan +- [ ] テスト項目 + + +EOF +)" +``` + +`DRAFT_FLAG` は `--draft` 指定時のみ `--draft`、それ以外は空。 + +## PR説明の更新(既存PRがある場合) + +既存PRがある場合、以下の手順でPR説明を更新する: + +1. **変更内容の分析**: + - `git log origin/..HEAD` でブランチ全体のコミット履歴 + - `git diff origin/..HEAD --stat` で変更ファイル一覧 + - 必要に応じて変更ファイルの詳細を取得 +2. **既存PR説明の確認**: + - `gh pr view --json body` で現在のPR説明を取得 + - 既存の関連リンク(Issue参照、設計ドキュメント等)は保持する +3. **PR説明の生成**: + - `.github/pull_request_template.md` のテンプレート構造に従う + - ブランチの**全コミット**の変更内容を反映する(最新コミットだけでなく全体) + - 「Summary」「Test plan」「やらないこと」等を適切に記述 +4. **更新の実行**: + ```bash + gh pr edit --body "" + ``` + +## 命名規則 + +- ブランチ: 英語(github flow) +- コミット・PR: 日本語 +- コミットメッセージ prefix 例: + - `feat:` 新機能 + - `fix:` バグ修正 + - `refactor:` リファクタリング + - `docs:` ドキュメント + - `test:` テスト + - `chore:` その他 + +## 検証ブランチ(qa/*等)へのPR作成 + +**重要: featureブランチから直接検証ブランチへPRを作成してはいけません。** + +### アンチパターン(禁止) + +``` +feature/xxx ──PR──→ qa/staging ← ❌ qa/staging をmergeするとmainが汚染される +``` + +### 正しい手順 + +`/ndf:cherry-pick-pr ` を使う(自動化済み)。詳細な理由と手順は: +- `/ndf:cherry-pick-pr` — 自動化コマンド +- `/ndf:branch-fix-strategy` — 原則と手順 + +## 作業完了報告(必須) + +PR作成/更新完了後、以下を報告: + +- 基本情報(PRタイトル、ベース/ソースブランチ、PR番号、ドラフト有無) +- 変更サマリー(コミット数、変更ファイル数、変更行数、主な変更内容) +- コミット履歴 +- PR本文の概要(Summary、Test plan) +- PR URL + +## 関連 + +- `/ndf:cherry-pick-pr` — 環境ブランチへのcherry-pick PR +- `/ndf:deploy` — 環境ブランチへのデプロイPR(ブランチ全体) +- `/ndf:pr-tests` — Test Plan 自動実行 +- `/ndf:review` — PR単位レビュー +- `/ndf:sync-main` — 現ブランチに main を取り込み +- `/ndf:branch-fix-strategy` — ブランチ戦略の原則 diff --git a/plugins/ndf/skills-claude/problem-solving/SKILL.md b/plugins/ndf/skills-claude/problem-solving/SKILL.md new file mode 100644 index 00000000..1b3c1108 --- /dev/null +++ b/plugins/ndf/skills-claude/problem-solving/SKILL.md @@ -0,0 +1,162 @@ +--- +name: problem-solving +description: "Solve bugs, incidents, and data inconsistencies at root cause." +when_to_use: "データ不整合 / バグ / 障害対応時に自動参照。「つじつま合わせ」を避けて上流で直す判断が必要なとき。Triggers: 'バグ修正', 'データ不整合', '障害対応', '根本原因', 'root cause analysis', 'data inconsistency', 'incident', '上流で直す', 'patch vs fix'" +--- + +# 問題解決ガイドライン + +データ不整合、バグ、障害対応における問題解決の原則と手順。 + +## 1. 根本原因を探る(つじつま合わせをしない) + +### 原則: 上流で直す + +問題はデータフローの**最も上流**で修正する。下流でのパッチ(migrationによるデータ修正、SQL直接更新、出力時の辻褄合わせ)は最終手段。 + +``` +❌ 悪いパターン + DBに異常データがある → migrationで論理削除 → バッチ再実行 + +✅ 良いパターン + DBに異常データがある → なぜ入ったか調査 → 取り込みロジックにバリデーション追加 + → 異常データを論理削除 → バッチ再実行 +``` + +### 判断フロー + +``` +1. 症状を確認(どのデータ・どの機能が、どう間違っているか) +2. データフロー/呼び出しチェーンを遡る(結果 → 計算 → 素材 → 取り込み → 外部ソース) +3. 最初に異常が発生した地点を特定 +4. その地点のコードを修正 +5. 下流にも防御的チェックを追加(多層防御) +6. 修正後にデータ修復(パイプライン再実行) +``` + +### 典型的な見逃しパターン + +| 症状 | 表層の「原因」 | 真の根本原因 | +|------|-------------|-------------| +| 料金が異常値 | 計算ロジックのバグ | 上流の取り込み時に異常値が混入、バリデーション欠如 | +| レコードの2WD/4WD逆転 | 割当ロジックの不具合 | ORM(Eloquent等)のリレーション型不一致(VARCHAR↔INT)でEager Loadマッチングずれ | +| 一部ユーザーで通知が届かない | 通知送信ロジックの問題 | 論理削除フラグの扱いが `delete()` と `forceDelete()` で異なる | + +## 2. ハルシネーション防止チェック + +### 原則: 自分の推論を疑い、必ず裏取りする + +コードリーディングだけで判断せず、以下を必ず実行する。 + +### チェックリスト + +| チェック項目 | 方法 | +|------------|------| +| カラム/フィールドが存在するか | `SHOW COLUMNS` / スキーマ定義ファイル確認(コード読みだけで判断しない) | +| データが存在するか | `SELECT COUNT(*) FROM table WHERE ...` / サンプル取得 | +| 型が一致するか | DB定義(INT/VARCHAR等)とコード側(`$casts`, dataclass 等)の両方を確認 | +| 外部キー/制約が存在するか | マイグレーション履歴を追跡(追加→削除→再追加の変遷を確認) | +| 論理削除ポリシーは何か | `SoftDeletes` / `deleted_at` の有無を確認(`delete()` と `forceDelete()` の挙動が異なる) | +| 環境差異がないか | dev/staging/prod で同じクエリを実行して比較 | + +### やってはいけないこと + +- コードを読んだだけで「このカラムは存在しない」と断定する +- 1つのテーブル/ファイルだけ見て「データに問題はない」と結論づける +- マイグレーションの最終状態だけ見てFK制約の有無を判断する +- 論理削除の有無を確認せず `delete()` を使う + +### 型不一致の検出パターン + +ORMリレーションで以下の組み合わせは危険: + +| ローカルキー型 | 外部キー型 | リスク | +|--------------|----------|-------| +| VARCHAR | INT | Eager Load マッチングでずれる可能性 | +| INT | VARCHAR | 同上 | +| string | integer | strict comparison で不一致 | + +**対策**: 型キャストで揃えるか、リレーション定義時に明示的に型変換する。 + +## 3. データとコードの整合性検証 + +### 原則: 仮説を立てたら、データとコードの両面から検証する + +``` +仮説: 「処理Aが項目Xを逆に割り当てている」 + → コード確認: 処理AのJOIN/代入ロジックを読む + → データ確認: 上流テーブルの値と処理A結果の値を並べて比較 + → 結論: 上流データは正常、処理A結果が逆転 → 処理Aの問題 +``` + +### 検証手順テンプレート + +```sql +-- Step 1: 元データ(上流)を確認 +SELECT * FROM source_table WHERE conditions ORDER BY updated_at DESC; + +-- Step 2: 中間データを確認 +SELECT * FROM intermediate_table WHERE conditions; + +-- Step 3: 最終データ(下流)を確認 +SELECT * FROM result_table WHERE conditions; + +-- Step 4: 上流と下流を突合 +-- 値が一致するか、変換ロジックが正しいか確認 +``` + +## 4. 多層防御 + +### 1つの修正だけに頼らず、複数レイヤーで防御する + +``` +Layer 1: 取り込み時バリデーション(異常値を入れない) +Layer 2: 型整合性(正しくマッチングする) +Layer 3: 処理時の防御条件(異常値があっても除外する) +Layer 4: 出力時検証(結果の妥当性チェック) +``` + +単一レイヤーだけだと、将来別の経路で同じ問題が再発する可能性が残る。 + +## 5. 修正の進め方 + +### 修正順序 + +1. **コードの修正**を先に行う(根本原因の解消) +2. **デプロイ**する +3. **データの修復**は修正済みコードで再実行する(migration や SQL 直接修正ではなく、パイプライン再実行が望ましい) +4. **検証**で修正を確認する + +### コミット・PR戦略 + +- 根本原因の修正とデータ修復は**別コミット**にする(Revertしやすい) +- 重複コードは発見次第リファクタリングする +- 検証環境向けPRは `cherry-pick-pr` 方式で作成し、mainブランチを汚染しない(詳細は `branch-fix-strategy` スキル参照) + +## 6. 調査レポートの書き方 + +### 必須項目 + +1. **症状**: 何がどう間違っているか(定量的に) +2. **根本原因**: コードレベルでどこが問題か(ファイル名:行番号) +3. **エビデンス**: DB クエリ結果 / ログ / コマンド出力で裏付ける +4. **修正方針**: どのフェーズで何を直すか +5. **検証手順**: 修正後にどう確認するか + +### エビデンスの書き方 + +```markdown +**エビデンス(staging DB)**: +| key | value | updated_at | 状態 | +|---|---|---|---| +| A100 | 103,081 | 2026-04-01 10:49 | 異常(最新) | +| A100 | 44,390 | 2026-03-11 13:42 | 正常 | +``` + +SQLクエリ結果をそのまま貼り、「コードを読んだ推測」と「DBで確認した事実」を明確に区別する。 + +## 関連スキル + +- `/ndf:investigation-rules` — 調査レポート作成時のエビデンス主義 +- `/ndf:branch-fix-strategy` — 複数ブランチへの修正適用戦略 +- `/ndf:logging-guidelines` — ログ設計(原因特定を容易にする) diff --git a/plugins/ndf/skills-claude/python-execution/01-uv-setup.md b/plugins/ndf/skills-claude/python-execution/01-uv-setup.md new file mode 100644 index 00000000..aafd4f1c --- /dev/null +++ b/plugins/ndf/skills-claude/python-execution/01-uv-setup.md @@ -0,0 +1,85 @@ +# uv詳細セットアップガイド + +> **Note**: 基本的な`uv sync`と`uv run python`はSKILL.mdを参照。このファイルは初回セットアップや詳細設定が必要な場合のみ参照。 + +## uvインストール + +```bash +# Linux/macOS +curl -LsSf https://astral.sh/uv/install.sh | sh + +# pip経由(代替) +pip install uv + +# 確認 +uv --version +``` + +## 依存関係管理 + +```bash +# uv.lockがある場合(推奨) +uv sync + +# uv.lockがない場合 +uv lock && uv sync + +# 開発用依存関係も含める +uv sync --dev + +# 特定のextraを含める +uv sync --extra test +``` + +## Pythonバージョン管理 + +```bash +# 特定バージョンをインストール +uv python install 3.12 +uv python install 3.11 + +# プロジェクトで使用するバージョンを固定 +uv python pin 3.12 + +# インストール済みバージョン一覧 +uv python list +``` + +## 実行オプション + +```bash +# スクリプト実行 +uv run python script.py + +# モジュール実行 +uv run python -m pytest +uv run python -m mypy . + +# 引数付き +uv run python script.py --arg value + +# インタラクティブシェル +uv run python +``` + +## プロジェクト初期化(新規作成時) + +```bash +# 新規プロジェクト作成 +uv init my-project +cd my-project + +# 依存関係追加 +uv add requests +uv add --dev pytest + +# ロックファイル生成 +uv lock +``` + +## uv環境の利点 + +- **高速**: Rustで実装、pip比10-100倍速 +- **再現性**: uv.lockで完全な依存関係固定 +- **Pythonバージョン管理**: pyenvなしでバージョン切り替え +- **グローバル環境を汚染しない**: プロジェクト単位で隔離 diff --git a/plugins/ndf/skills-claude/python-execution/02-troubleshooting.md b/plugins/ndf/skills-claude/python-execution/02-troubleshooting.md new file mode 100644 index 00000000..3475b7ec --- /dev/null +++ b/plugins/ndf/skills-claude/python-execution/02-troubleshooting.md @@ -0,0 +1,112 @@ +# Python実行 トラブルシューティング + +## よくある問題と解決策 + +### Q: `uv: command not found` + +**原因**: uvがインストールされていない + +**解決策**: +```bash +curl -LsSf https://astral.sh/uv/install.sh | sh +# シェルを再起動するか、パスを通す +source ~/.bashrc # または ~/.zshrc +``` + +### Q: `ModuleNotFoundError` + +**原因**: 依存関係がインストールされていない + +**解決策**: +```bash +# uv環境の場合 +uv sync + +# venv環境の場合 +.venv/bin/pip install -r requirements.txt + +# pyproject.tomlがある場合 +.venv/bin/pip install -e . +``` + +### Q: `python: command not found` + +**原因**: Pythonがインストールされていない、またはパスが通っていない + +**解決策**: +```bash +# python3を試す +python3 --version + +# uvでPythonをインストール +uv python install 3.12 +``` + +### Q: 異なるPythonバージョンが必要 + +**解決策(uv環境)**: +```bash +# 特定バージョンをインストール +uv python install 3.11 + +# プロジェクトで使用するバージョンを固定 +uv python pin 3.11 + +# そのバージョンで実行 +uv run python script.py +``` + +### Q: `pyproject.toml`はあるが`uv.lock`がない + +**解決策**: +```bash +# ロックファイルを生成 +uv lock + +# 依存関係をインストール +uv sync +``` + +### Q: 仮想環境が壊れている + +**解決策**: +```bash +# 仮想環境を削除して再作成 +rm -rf .venv + +# uv環境の場合 +uv sync + +# 手動で作成する場合 +python3 -m venv .venv +.venv/bin/pip install -r requirements.txt +``` + +### Q: パーミッションエラー + +**解決策**: +```bash +# 仮想環境を使用(推奨) +uv sync +uv run python script.py + +# どうしてもグローバルにインストールする場合(非推奨) +pip install --user package_name +``` + +### Q: SSL証明書エラー + +**解決策**: +```bash +# macOSの場合 +/Applications/Python\ 3.x/Install\ Certificates.command + +# または環境変数で一時的に無効化(非推奨) +export PYTHONHTTPSVERIFY=0 +``` + +## 関連リソース + +- [uv公式ドキュメント](https://docs.astral.sh/uv/) +- [Python venv](https://docs.python.org/3/library/venv.html) +- [pyproject.toml仕様](https://packaging.python.org/en/latest/specifications/pyproject-toml/) diff --git a/plugins/ndf/skills-claude/python-execution/SKILL.md b/plugins/ndf/skills-claude/python-execution/SKILL.md new file mode 100644 index 00000000..a07705aa --- /dev/null +++ b/plugins/ndf/skills-claude/python-execution/SKILL.md @@ -0,0 +1,86 @@ +--- +name: python-execution +description: "Detect and run the right Python environment." +when_to_use: "Python スクリプトを実行 / セットアップするとき。Triggers: 'python', 'uv', 'スクリプト', 'python環境'" +allowed-tools: + - Read + - Bash + - Glob +--- + +# Python Execution Skill + +## 概要 + +Pythonコードを実行する前に、プロジェクトの実行環境を調査し、適切な方法で実行するためのガイドラインです。 + +## Step 1: 環境検出 + +```bash +ls -la pyproject.toml uv.lock .venv/ venv/ requirements.txt 2>/dev/null +``` + +## Step 2: 実行コマンド選択 + +| 検出ファイル | 実行方法 | 優先度 | +|-------------|---------|-------| +| `pyproject.toml` | `uv run python` | 最高 | +| `.venv/` | `.venv/bin/python` | 中 | +| `venv/` | `venv/bin/python` | 中 | +| 何もなし | `python3` | 最低 | + +## Step 3: 実行 + +### uv環境(pyproject.tomlあり) + +```bash +# 依存関係インストール(初回のみ) +uv sync + +# 実行 +uv run python script.py +uv run python -m module_name +``` + +**uvがない場合のインストール**: +```bash +curl -LsSf https://astral.sh/uv/install.sh | sh +source ~/.bashrc # パスを反映 +``` + +### venv環境(.venv/あり) + +```bash +# 依存関係インストール(初回のみ) +.venv/bin/pip install -r requirements.txt + +# 実行 +.venv/bin/python script.py +``` + +### システムPython + +```bash +python3 script.py +``` + +## ベストプラクティス + +| DO | DON'T | +|----|-------| +| 実行前に環境を調査 | 環境を確認せずに実行 | +| README.md/CLAUDE.mdの指示を優先 | グローバル環境に依存関係をインストール | +| pyproject.tomlがあればuv使用 | source activateに依存 | +| 仮想環境のPythonをパス指定で実行 | python2を使用 | + +## 詳細ガイド(必要時のみ参照) + +| ファイル | 内容 | 参照タイミング | +|---------|------|--------------| +| `01-uv-setup.md` | uv詳細セットアップ、Pythonバージョン管理 | 初回セットアップ時 | +| `02-troubleshooting.md` | エラー解決策 | 問題発生時 | + +## 関連Skill + +- **corder-code-templates**: Pythonコードテンプレート +- **corder-test-generation**: Pythonテスト生成 diff --git a/plugins/ndf/skills-claude/resolve-pr-comments/SKILL.md b/plugins/ndf/skills-claude/resolve-pr-comments/SKILL.md new file mode 100644 index 00000000..433a72d6 --- /dev/null +++ b/plugins/ndf/skills-claude/resolve-pr-comments/SKILL.md @@ -0,0 +1,146 @@ +--- +name: resolve-pr-comments +description: "Reply to and resolve fixed PR comments." +argument-hint: "[PR番号]" +disable-model-invocation: true +allowed-tools: + - Bash + - Read +--- + +# PRコメントResolveコマンド + +対応済みのPRコメント全てに返信し、スレッドを resolved にする。`/ndf:fix` で修正完了後に呼び出す**クロージング専用**コマンド。 + +## 使用方法 + +``` +/ndf:resolve-pr-comments # 現在のブランチのPRを対象 +/ndf:resolve-pr-comments 9352 # PR番号を指定 +``` + +## `/ndf:fix` との使い分け + +| 観点 | fix | resolve-pr-comments | +|---|---|---| +| 動作 | コード修正+commit+push | 返信+スレッドresolve | +| 前提 | レビュー後、修正が必要 | 修正済み、クロージングのみ | +| 推奨順序 | 先に実行 | fix後の最後に実行 | + +## 処理フロー + +### 1. PR情報の取得 + +```bash +PR_NUMBER="${ARGUMENTS:-$(gh pr view --json number --jq .number)}" +``` + +### 2. PRコメント取得 + +GitHub API でレビューコメントを取得: + +```bash +gh api "repos/:owner/:repo/pulls/$PR_NUMBER/comments" +``` + +### 3. 対応状況の確認 + +各コメントについて、対応済みかどうかを確認する: +- コードの変更履歴(`git log`, `git diff`)と照合 +- 指摘された問題が修正されているか確認 +- PR body の「やらないこと」セクションで別PR対応と明記されているか確認 + +### 4. コメントへの返信 + +対応済みのコメントに対して、内容に応じた返信を投稿する: + +#### 修正対応した場合 +``` +対応しました。 + +{修正内容の簡潔な説明} +``` + +#### 別PRで対応予定の場合 +``` +別PRで対応予定です。 + +PR説明の「やらないこと」に記載の通り、{理由}のため別PRで対応します。 +``` + +#### 対応不要と判断した場合 +``` +確認しました。 + +{対応不要と判断した理由} +``` + +### 5. gh CLI コマンド + +#### レビューコメントに返信(スレッド内) + +```bash +gh api "repos/:owner/:repo/pulls/$PR_NUMBER/comments" \ + -f body="返信メッセージ" \ + -f in_reply_to= +``` + +#### スレッドをResolve(GraphQL) + +まず Thread Node ID を取得: + +```bash +gh api "repos/:owner/:repo/pulls/comments/" --jq '.node_id' +``` + +その上でResolve: + +```bash +gh api graphql -f query=' + mutation { + resolveReviewThread(input: {threadId: ""}) { + thread { isResolved } + } + } +' +``` + +### 6. 実行フロー + +各コメントに対して以下を順次実行: + +1. コメントの内容と対応状況を確認 +2. 適切な返信メッセージを生成 +3. 返信を投稿 +4. スレッドをresolve +5. 結果を報告 + +### 7. 出力フォーマット + +```markdown +## PR #XXXX コメント対応結果 + +### 処理結果 +| # | コメント | 返信内容 | Resolve | +|---|---------|---------|---------| +| 1 | {指摘要約} | 対応しました | ✅ | +| 2 | {指摘要約} | 別PRで対応予定 | ✅ | + +### サマリー +- 処理済み: X件 +- Resolved: X件 +- エラー: X件 +``` + +## 重要ルール + +- **確認してから実行**: 各コメントの対応状況を必ず確認してから返信 +- **コード修正はしない**: 修正は `/ndf:fix` の責務。このコマンドはクロージングのみ +- **適切な返信**: 対応内容に応じた適切な返信メッセージを使用 +- **エラーハンドリング**: API エラー発生時は報告して継続 +- **ユーザー確認**: 判断に迷う場合はユーザーに確認を求める + +## 関連 + +- `/ndf:review-pr-comments` — コメント分類・優先度判定 (READ-ONLY) +- `/ndf:fix` — コメント対応の修正を実施 diff --git a/plugins/ndf/skills-claude/review-branch/SKILL.md b/plugins/ndf/skills-claude/review-branch/SKILL.md new file mode 100644 index 00000000..951e5ea1 --- /dev/null +++ b/plugins/ndf/skills-claude/review-branch/SKILL.md @@ -0,0 +1,129 @@ +--- +name: review-branch +description: "Review the current branch before opening a PR." +when_to_use: "PR作成前にローカルブランチの実装をセルフレビューしたいとき。Triggers: 'ブランチをレビュー', 'PR前にレビュー', 'セルフレビュー', 'review my branch', 'review before PR', 'self review', 'pre-PR review'" +argument-hint: "[focus-area] (例: security, performance, tests)" +allowed-tools: + - Bash + - Read + - Glob + - Grep +--- + +# ブランチ実装レビューコマンド + +現在のブランチで実装された変更を**PR作成前に**コードレビューする。mainブランチとの差分を分析し、コード品質・セキュリティ・パフォーマンスの観点でフィードバックを返す。 + +## `/ndf:review` との使い分け + +| 観点 | review-branch | review | +|---|---|---| +| 対象 | ローカルブランチの差分(PR前) | GitHub上の既存PR | +| 判定 | フィードバックを返す | Approve / Request Changes を判定 | +| 用途 | PR作成前のセルフレビュー | PR作成後のレビュー | + +## 使用方法 + +``` +/ndf:review-branch # 全般レビュー +/ndf:review-branch security # セキュリティに焦点 +/ndf:review-branch performance # パフォーマンスに焦点 +/ndf:review-branch tests # テスト網羅性に焦点 +/ndf:review-branch "ビジネスロジック" # 任意のフォーカス +``` + +## レビュー手順 + +### 1. 変更の把握 + +```bash +git diff main --name-only # 変更ファイル一覧 +git diff main --stat # 差分の統計 +git log main..HEAD --oneline # コミット履歴 +``` + +### 2. 変更内容の分析 + +各変更ファイルに対して以下を確認: + +- **追加・変更されたロジック**: 意図が明確か、正しく実装されているか +- **テストカバレッジ**: 適切なテストが追加されているか +- **コーディング規約**: プロジェクトの規約に準拠しているか + +### 3. 品質チェック観点 + +#### コード品質 +- 命名規則の一貫性 +- 関数/メソッドの責務(単一責任原則) +- DRY原則(重複コードの排除) +- 可読性・保守性 +- 過剰な抽象化がないか(YAGNI) + +#### セキュリティ +- SQLインジェクション対策 +- XSS対策 +- CSRF対策 +- 入力値バリデーション +- 認証・認可の適切性 +- 機密情報(トークン、キー、PII)の取り扱い + +#### パフォーマンス +- N+1 クエリの有無 +- 不要なデータベースアクセス +- メモリ使用量 +- インデックスの活用 + +#### エラーハンドリング +- 例外が適切に捕捉されているか +- ログ出力の妥当性(詳細は `/ndf:logging-guidelines`) +- リトライ/タイムアウトの設計 + +### 4. レビュー結果の報告 + +```markdown +## レビュー結果 + +### 概要 +- 変更ファイル数: X +- 追加行数: +XXX +- 削除行数: -XXX + +### Good(良い点) +- ... + +### Suggestions(改善提案) +- `path/to/file.ext:123` — 提案内容 + +### Issues(要修正) +- `path/to/file.ext:456` — 問題点と修正方針 +``` + +## 使用例 + +```bash +# 全般的なレビュー +/ndf:review-branch + +# セキュリティ重視(認証系変更など) +/ndf:review-branch security + +# N+1クエリ等のパフォーマンス問題に焦点 +/ndf:review-branch performance + +# テストの網羅性を確認 +/ndf:review-branch tests +``` + +## 注意事項 + +- 大量の変更がある場合、重要な変更から優先的にレビューする +- 自動品質チェック(linter, formatter, type checker)は事前実行済みを前提とする +- レビュー結果は提案であり、最終判断は開発者が行う +- **コード修正は行わない**(分析とフィードバックのみ。修正は `/ndf:fix` で別途実行) + +## 関連 + +- `/ndf:review` — PR単位レビュー (Approve/Request Changes判定) +- `/ndf:review-pr-comments` — 既存PRコメントの分類 +- `/ndf:fix` — PRレビューコメントの修正対応 +- `/ndf:logging-guidelines` — ログ設計 diff --git a/plugins/ndf/skills-claude/review-pr-comments/SKILL.md b/plugins/ndf/skills-claude/review-pr-comments/SKILL.md new file mode 100644 index 00000000..1b51139d --- /dev/null +++ b/plugins/ndf/skills-claude/review-pr-comments/SKILL.md @@ -0,0 +1,110 @@ +--- +name: review-pr-comments +description: "Classify existing PR comments before fixing." +when_to_use: "既存PRのレビューコメントを分類・優先度判定したいとき (修正前)。Triggers: 'PRコメントを確認', 'PRコメントを分類', 'コメント対応の優先度', 'PR comments review', 'classify PR comments', 'PRレビュー結果を見て'" +argument-hint: "[PR番号]" +allowed-tools: + - Bash + - Read + - Glob + - Grep +--- + +# PRコメント分析コマンド (READ-ONLY) + +GitHub PRのレビューコメントを全て確認し、対応可否を判定する。**修正は一切行わない。分析・判定のみ**。 + +## 使用方法 + +``` +/ndf:review-pr-comments # 現在のブランチのPRを対象 +/ndf:review-pr-comments 9352 # PR番号を指定 +``` + +## `/ndf:fix` との使い分け + +| 観点 | review-pr-comments | fix | +|---|---|---| +| 動作 | 分類・優先度判定のみ | 実際にコード修正 | +| 出力 | 分類テーブル+推奨アクション | 修正差分+commit | +| 推奨順序 | 最初に実行 | review-pr-commentsの結果を見て実行 | + +「まず全体像を把握 → 優先度を決めてから修正」という流れに使う。 + +## 処理フロー + +### 1. PR情報の取得 + +引数でPR番号が指定されていればそれを使用、なければ現在のブランチから取得。 + +```bash +CURRENT_BRANCH=$(git branch --show-current) +PR_NUMBER="${ARGUMENTS:-$(gh pr view --json number --jq .number)}" +``` + +### 2. PRコメント取得 (3 ソース) + +fix skill の共有スクリプトで インラインコメント / レビュー body / PR レベルコメントを一括取得: + +```bash +FETCH_SCRIPT="${PLUGIN_ROOT:-${CLAUDE_PLUGIN_ROOT}}/skills/fix/scripts/fetch-pr-comments.sh" +"$FETCH_SCRIPT" "$(gh repo view --json nameWithOwner -q .nameWithOwner)" "$PR_NUMBER" +``` + +補助情報 (reviewDecision 等): + +```bash +gh pr view "$PR_NUMBER" --json reviewDecision +``` + +GitHub MCP を使う場合は `mcp__github__get_pull_request_comments` を利用。 + +### 3. コメント分析・分類 + +各コメントを以下のカテゴリに分類する: + +| カテゴリ | 説明 | 対応判断 | +|---------|------|---------| +| 🔴 重大 | セキュリティ、データ整合性、クラッシュの可能性 | **対応必須** | +| 🟡 改善推奨 | コード品質、保守性、ベストプラクティス | **対応推奨** | +| 🟢 軽微 | タイポ、フォーマット、命名規則 | **対応すべき** | +| ⚪ 参考 | 提案、質問、情報共有 | **対応任意** | +| 🔵 別PR対応 | 別PRで対応予定と明記されている内容 | **対応不要** | + +### 4. 出力フォーマット + +```markdown +## PR #XXXX コメントレビュー結果 + +### サマリー +- 総コメント数: X件 +- 対応必須: X件 +- 対応推奨: X件 +- 対応すべき: X件 +- 対応任意/不要: X件 + +### 詳細 + +| # | ファイル | 行 | 指摘内容 | 分類 | 対応判断 | +|---|---------|----|---------|----|---------| +| 1 | path/to/file.ext | 123 | 指摘の要約 | 🔴 重大 | **対応必須** | +| 2 | ... | ... | ... | ... | ... | + +### 推奨アクション +1. まず対応すべき項目(重大+軽微) +2. 次に対応推奨項目 +3. 別PRで対応(コメントで返信推奨) +``` + +## 重要ルール + +- **READ-ONLY**: コードの修正は一切行わない +- **PR説明文を確認**: 「やらないこと」「別PR対応」セクションに記載されている内容は「🔵 別PR対応」として分類 +- **コンテキスト理解**: コメントが指摘している問題の本質を理解して分類 +- **判断根拠**: なぜその分類になったかの理由を簡潔に説明 + +## 関連 + +- `/ndf:fix` — 分類結果を踏まえてコード修正を実施 +- `/ndf:resolve-pr-comments` — 修正完了後の返信+Resolve +- `/ndf:review` — PRを新規にレビューする (Approve/Request Changes判定) diff --git a/plugins/ndf/skills-claude/review/SKILL.md b/plugins/ndf/skills-claude/review/SKILL.md new file mode 100644 index 00000000..cfb920ba --- /dev/null +++ b/plugins/ndf/skills-claude/review/SKILL.md @@ -0,0 +1,337 @@ +--- +name: review +description: "Review PRs and post approve or changes verdicts." +argument-hint: "[PR番号] [AIエージェント(codex|gemini)]" +disable-model-invocation: true +allowed-tools: + - Bash + - Read + - Glob + - Grep +--- + +# PRレビューコマンド + +直前PR、または引数で指定されたPRを専門家としてレビュー。 + +## 引数 + +- 第一引数 `[PR番号]`: レビュー対象のPR番号(省略時は直前のPR) +- 第二引数 `[AIエージェント]`: レビュー実行者(任意) + - 省略時: Claude(自身)でレビュー + - `codex`: Codex CLI に委譲 + - `gemini`: Gemini CLI に委譲 + +## 実行 + +- 問題点・改善点あり → 「Request Changes」 +- 指摘なし → 「Approve」 +- **レビュー結果は必ず GitHub PR 上に投稿する**(後述「レビュー結果の投稿」参照) + - 指摘は可能な限り **コード行に紐付くインラインコメント** として書く + - ファイル横断・設計レベルの所見のみ review body(総評)に書く + +## 観点 + +言語慣用性(Idiomatic)・可読性・コード品質・保守性・セキュリティ・テストカバレッジ +- 上から順に優先して指摘 + +### 具体的なチェックポイント + +- **その言語らしい記述方式**: イディオム・標準ライブラリ・言語機能の活用 +- **メモリ効率・演算性能を意識したコード** + - キャッシュ利用 + - Python: numpy 利用、内包表記、ジェネレータ + - PHP: switch 文の map(連想配列)化 + - 不要なループ・コピーの排除 +- **関数・メソッド・ファイル行数の適正化** + - 目安: 関数/メソッド 50 行、ファイル 300 行 + - ただしプロジェクトの慣例に従う +- **重複・冗長コードの排除** + - PR 範囲にこだわらず積極的にまとめるよう指摘 +- **柔軟性を損なう定数化の排除** + - 数字をそのまま定数にするような硬直化を避ける + - 定数よりも DB の master テーブル、または json/yaml による外部化を検討 + +## レビュー結果の投稿 + +レビュー結果は **GitHub の PR レビュー機能** を使って必ず PR 上に書き込む。 +個別指摘は **コード行に紐付くインラインコメント** が原則。総評(review body)にだけ書くのは避ける。 + +### 指摘の振り分け + +| 指摘の種類 | 投稿先 | +|---|---| +| 特定ファイル・特定行への指摘 | **インラインコメント** (`comments[].path` + `line`) | +| 複数ファイルにまたがる設計指摘 | 代表箇所にインラインコメント + review body に補足 | +| 設計レベル・PR全体の所見 | review body(総評) | +| ファイル単位の指摘(行を絞れない) | そのファイルの代表行にインラインコメント | + +### 投稿フロー(推奨: 1 リクエストで一括投稿) + +`gh api` の Reviews API を使い、**総評 + 複数のインラインコメント + 判定(event)を 1 回で送信** する。 + +```bash +PR= +OWNER_REPO=$(gh repo view --json nameWithOwner -q .nameWithOwner) +SHA=$(gh pr view "$PR" --json headRefOid -q .headRefOid) + +# 1. インラインコメントを JSON 配列で組み立て +# (path / line / side / body の 4 つが必須。複数行レンジは start_line を併用) +# +# ▼ 推奨: jq -n でシェル変数を安全に流し込む(特殊文字混入時の JSON 破損を防ぐ) +SUMMARY=$'## 総評\n\n... 全体所見をここに ...' +jq -n \ + --arg sha "$SHA" \ + --arg event "REQUEST_CHANGES" \ + --arg body "$SUMMARY" \ + '{ + commit_id: $sha, + event: $event, + body: $body, + comments: [ + {path: "src/foo.py", line: 42, side: "RIGHT", + body: "[major / 可読性] この関数は 70 行ある。〇〇 と △△ に分割を推奨。"}, + {path: "src/bar.py", start_line: 10, line: 25, side: "RIGHT", + body: "[minor / 性能] このループは内包表記化できる。"} + ] + }' > /tmp/review-payload.json + +# 2. Reviews API に POST +gh api -X POST "repos/$OWNER_REPO/pulls/$PR/reviews" --input /tmp/review-payload.json +``` + +> 💡 **JSON 組み立てに heredoc (`< JSON が壊れる(あるいはクオート未エスケープで JSON injection になる)。`jq -n --arg` 経由なら値が自動で +> JSON エスケープされるため安全。クオート付き heredoc (`<<'JSON'`) は逆に `$SHA` が展開されず使えない。 + +**`event` の値**: +- `APPROVE` — 指摘なし +- `REQUEST_CHANGES` — 修正必須の指摘あり +- `COMMENT` — 任意の指摘のみ(マージブロックしない) + +### インラインコメント本文の書式 + +各 `comments[].body` の先頭に **`[重要度 / カテゴリ]`** を付けて視認性を上げる: + +``` +[critical / セキュリティ] SQL がエスケープなしで連結されている。プレースホルダ必須。 +[major / 可読性] 70 行関数。〇〇 と △△ に分割を推奨。 +[minor / 言語慣用性] Python なら内包表記で 1 行化可能。 +[nit / スタイル] スペースが揃っていない。 +``` + +重要度の目安: +- `critical` — セキュリティ・データ破損・本番障害につながる +- `major` — 保守性 / 性能 / 仕様逸脱の重要問題 +- `minor` — 改善推奨だがブロッカーではない +- `nit` — 好み・スタイル + +### 既存コメントがある場合の重複防止 + +同じ箇所への二重指摘を避けるため、投稿前に既存コメントを確認する: + +```bash +# 既存のレビューコメント一覧 +gh api "repos/$OWNER_REPO/pulls/$PR/comments" --paginate \ + | jq -r '.[] | "\(.path):\(.line) \(.body | split("\n")[0])"' +``` + +すでに同種の指摘があれば、その指摘は省くか、reply(既存コメントへの返信)にする。 + +### 補助コマンド + +```bash +# review body 単体(インラインなし)で投稿したい場合 +gh pr review "$PR" --request-changes --body "..." +gh pr review "$PR" --approve --body "..." + +# 会話タブへの普通のコメント(行に紐付かない) +gh pr comment "$PR" --body "..." + +# 1 件だけインラインコメントを追加(既存 review に含めない) +gh api -X POST "repos/$OWNER_REPO/pulls/$PR/comments" \ + -F commit_id="$SHA" \ + -F path="src/foo.py" \ + -F line=42 -F side=RIGHT \ + -F body="..." +``` + +## 外部AIへの委譲手順 + +第二引数が指定された場合、上記「観点」「具体的なチェックポイント」「レビュー結果の投稿」の内容を **レビュー指示プロンプト** として組み立て、指定された CLI に渡す。 + +### 共通: プロンプト組み立て + +1. `gh pr view --json title,body,baseRefName,headRefName,url,headRefOid` で PR メタ情報を取得 +2. `gh pr diff ` で差分を取得(または変更ファイル一覧 + 必要箇所を `gh pr view --json files` 経由で抽出) +3. 上記「観点」「具体的なチェックポイント」「レビュー結果の投稿」セクションをそのままプロンプトに転記 +4. PR タイトル・URL・差分を **対象情報** として明記 +5. **出力は GitHub Reviews API のペイロード形式(JSON)で出させる**(後述「外部AIに必須化する出力形式」参照) + +### 外部AIに必須化する出力形式と直接投稿 + +**外部AIは Reviews API ペイロードを組み立てた後、自分自身で `gh api` を呼んで PR に投稿する**。 +(旧版では生成した JSON をメインに返してメインが投稿していたが、メイン context 消費と往復回数が無駄なので削除) + +メインに返すのは「投稿が成功したか」「最終 verdict (event)」「review URL」「件数」の小さな結果サマリのみ。 + +#### プロンプトに必ず含める指示(テンプレート) + +```markdown +## 出力形式と投稿手順(必須) + +レビュー結果は以下の手順で **あなた自身が PR に投稿** してください。 +メイン側に返すのは投稿結果サマリだけです。 + +### 1. ペイロード組み立て + +以下の JSON を `/tmp/-review-pr<番号>-payload.json` に書き出す +(codex なら `apply_patch`、gemini なら `write_file` を使用): + +\`\`\`json +{ + "commit_id": "", + "event": "REQUEST_CHANGES" | "APPROVE" | "COMMENT", + "body": "## 総評\n\n...(設計レベル・PR全体所見のみ)...", + "comments": [ + { + "path": "src/foo.py", + "line": 42, + "side": "RIGHT", + "body": "[major / 可読性] ..." + } + ] +} +\`\`\` + +ルール: +- 個別指摘は必ず `comments[]` のインラインコメントにすること(行を絞れない場合はファイル代表行) +- `body` (総評) には設計・横断的な所見のみ書く。個別指摘の繰り返しは禁止 +- 各 `comments[].body` の先頭に `[重要度 / カテゴリ]` を付ける(critical/major/minor/nit) +- `path` は **PR差分に登場するファイルのみ**(事前に `gh pr diff --name-only` で取得した一覧から選ぶ) +- `line` は **差分に含まれる行**(追加行・コンテキスト行)に限る。`side=RIGHT` がデフォルト +- `commit_id` は `gh pr view --json headRefOid -q .headRefOid` の値を使う + +### 2. 投稿 + +\`\`\`bash +OWNER_REPO=$(gh repo view --json nameWithOwner -q .nameWithOwner) +gh api -X POST "repos/$OWNER_REPO/pulls//reviews" \ + --input /tmp/-review-pr<番号>-payload.json \ + > /tmp/-review-pr<番号>-response.json +\`\`\` + +### 3. 結果サマリの書き出し(メインが読む) + +`/tmp/-review-pr<番号>-result.json` に投稿結果を書き出す: + +\`\`\`json +{ + "status": "posted" | "failed", + "event": "REQUEST_CHANGES" | "APPROVE" | "COMMENT", + "posted_as": "REQUEST_CHANGES" | "APPROVE" | "COMMENT", + "review_url": "https://github.com/.../pull/#pullrequestreview-...", + "comments_count": 5, + "by_severity": {"critical": 0, "major": 2, "minor": 2, "nit": 1}, + "payload_path": "/tmp/-review-pr<番号>-payload.json", + "error": null +} +\`\`\` + +投稿失敗時は `status: "failed"`、`error` にエラーメッセージ、`payload_path` で payload は残す +(メイン側のフォールバック投稿で使う)。 + +**`event` と `posted_as` の使い分け**: + +- `event` — **AI 本来の判定 (intent)**。ループ収束判定(`/ndf:cross-review`)はこれを見る +- `posted_as` — **GitHub に実際投稿した event**。`event` と同じ値がデフォルト + +GitHub は **自分の PR には `REQUEST_CHANGES` で投稿できない**(`HTTP 422: Can not request changes on your own pull request`)。自分 PR レビューの場合は以下のダウングレードを行う: + +- `event = "REQUEST_CHANGES"` のままにしておく(intent 保持) +- ペイロードの `event` だけ `"COMMENT"` にして投稿 +- `posted_as = "COMMENT"` を結果サマリに記録 + +これにより、後段のループ判定で「本当は REQ なので継続が必要」と判断できる。判定にあたっては事前に `gh api user --jq .login` と `gh pr view --json author --jq .author.login` を比較すること。 + +### 4. 重要度の運用ガイド(auto-fix 判定に直結) + +| 重要度 | 定義 | 後段の扱い | +|---|---|---| +| critical | セキュリティ・データ破損・本番障害につながる | **必ず自動修正** | +| major | 保守性・性能・仕様逸脱の重要問題 | **必ず自動修正** | +| minor | 改善推奨だがブロッカーではない | **自動修正対象**(明らかな改善のみ。判断要なら nit に格下げ) | +| nit | 好み・スタイル | **修正しない、最後にユーザ判断にまとめる** | + +過剰な nit 量産は避ける。critical/major で対応すべき真の問題に集中すること。 +``` + +### `codex` 指定時 + +呼び出し手順の詳細は `/ndf:codex` skill(`plugins/ndf/skills/codex/SKILL.md`)に従う。要点: + +- プロンプトを `/tmp/codex-review-pr<番号>-prompt.md` に書き出し +- 出力先ファイルを `/tmp/codex-output-review-pr<番号>.md` として **プロンプト内で `apply_patch` 書き出しを必須化** +- `codex exec --dangerously-bypass-approvals-and-sandbox --config reasoning.effort=medium -C "$PWD" < prompt > stdout 2> err &` でバックグラウンド起動 +- `grep -q '^tokens used$' err` で完了検知 +- 「ファイル → stdout → stderr」三段フォールバックで成果物を回収 + +> ⚠️ **`--dangerously-bypass-approvals-and-sandbox` のセキュリティ注意**: このフラグは codex の bwrap サンドボックスを完全に無効化し、 +> 任意のシェル実行・任意のファイル編集を無確認で許可する。**必ず Docker / devcontainer / VM / CI ランナー等の外部隔離環境内** でのみ使用すること。 +> ホスト直接実行や本番リポジトリでは使わない。詳細な背景・代替策(`unprivileged_userns_clone` 有効化など)は `/ndf:codex` skill の +> 「サンドボックス制約」節を参照。 + +### `gemini` 指定時 + +呼び出し手順の詳細は `/ndf:gemini` skill(`plugins/ndf/skills/gemini/SKILL.md`)に従う。要点: + +- プロンプトを `/tmp/gemini-review-pr<番号>-prompt.md` に書き出し +- **AI 直接投稿フローでは `--yolo` 必須**(`gh api -X POST` がシェル実行のため、`plan` / `auto_edit` だとブロックされる) +- プロンプト側で **「リポジトリ内ファイルを編集してはならない。`gh api` で投稿するだけ」** を強く明示することで `--yolo` のリスクを抑える +- `gemini --yolo --output-format text -p "$(cat prompt.md)" > stdout 2> err &` でバックグラウンド起動 +- `kill -0 $PID` ポーリングで完了検知(Codex と異なり sentinel 不要 / プロセス exit を見る) +- 成果物は stdout サマリ + `/tmp/gemini-review-pr<番号>-result.json` で回収 + +> ⚠️ **`--yolo` の制約は依然有効**: `/ndf:gemini` skill のセキュリティ警告通り、必ず外部隔離環境内でのみ実行する。プロンプトで「リポジトリ編集禁止」を明示することは必須だが、それは sandbox の代替にはならない。 + +### メイン側の検証とフォールバック + +メインエージェントの責務は **結果サマリ読み込みと検証のみ**: + +```bash +AGENT=codex # or gemini +RESULT=/tmp/$AGENT-review-pr$PR-result.json + +if [ ! -s "$RESULT" ]; then + echo "❌ $AGENT: 結果サマリ未生成。完了検知 or プロンプト指示に問題あり" >&2 + exit 1 +fi + +STATUS=$(jq -r '.status' "$RESULT") +EVENT=$(jq -r '.event // empty' "$RESULT") + +if [ "$STATUS" = "failed" ]; then + echo "⚠️ $AGENT: 投稿失敗。payload からメインがフォールバック投稿します" >&2 + PAYLOAD=$(jq -r '.payload_path' "$RESULT") + OWNER_REPO=$(gh repo view --json nameWithOwner -q .nameWithOwner) + SHA=$(gh pr view "$PR" --json headRefOid -q .headRefOid) + jq --arg sha "$SHA" '.commit_id = $sha' "$PAYLOAD" > /tmp/review-fallback.json + gh api -X POST "repos/$OWNER_REPO/pulls/$PR/reviews" --input /tmp/review-fallback.json +fi + +echo "$AGENT: event=$EVENT url=$(jq -r .review_url $RESULT)" +``` + +**Claude 自身による追加判定は行わず**、外部AIの判定(`event`)と指摘内容をそのまま採用する。 + +## 作業完了報告(必須) + +レビュー結果は **PR 上に投稿済み** であることが前提。ユーザーへの報告は以下に絞る: + +- 利用エージェント(claude / codex / gemini のいずれか) +- 投稿結果(review URL、event = APPROVE / REQUEST_CHANGES / COMMENT) +- 件数サマリ(インラインコメント数、重要度別内訳) +- 総評(review body)の要約 +- PR URL + +詳細な指摘内容は PR 上のインラインコメントに残っているため、ユーザー宛報告では繰り返さない。 diff --git a/plugins/ndf/skills-claude/statusline/SKILL.md b/plugins/ndf/skills-claude/statusline/SKILL.md new file mode 100644 index 00000000..52d5288f --- /dev/null +++ b/plugins/ndf/skills-claude/statusline/SKILL.md @@ -0,0 +1,49 @@ +--- +name: statusline +description: "Switch, restore, or inspect the NDF statusline." +when_to_use: "statuslineを切り替え/復元/確認したいとき。Triggers: 'statusline', 'ステータスライン', 'statusline 切り替え', 'statusline 戻す'" +disable-model-invocation: true +allowed-tools: + - Bash +--- + +# Statusline 切り替えコマンド + +NDF 標準 statusline (コンテナ名/ホスト名 + project_dir + コンテキスト使用率) と +既存のカスタム statusline を切り替える。 + +## 表示内容 + +``` +<コンテナ名|ホスト名> [<モデル名>: 12.3k / 200k tokens (6%)] +``` + +- コンテナ環境 (`/.dockerenv` あり) ではコンテナ名、それ以外ではホスト名を表示 +- `CONTAINER_NAME` 環境変数があればそちらを優先 +- 角括弧内のラベルは利用中モデルの表示名 (例: `Opus 4.8`)。取得できない場合は `ctx` にフォールバック + +## 使用方法 + +引数に応じて以下のコマンドを実行する: + +```bash +# 状態確認 (引数なし or status) +bash ${CLAUDE_PLUGIN_ROOT}/scripts/statusline-switch.sh status + +# NDF 標準 statusline に切り替え (既存設定は自動バックアップ) +bash ${CLAUDE_PLUGIN_ROOT}/scripts/statusline-switch.sh set + +# 元の設定に復元 (バックアップが無ければ statusLine 設定を削除) +bash ${CLAUDE_PLUGIN_ROOT}/scripts/statusline-switch.sh restore +``` + +実行後、スクリプトの出力をそのままユーザーに報告する。 +statusline の変更は次回セッション開始時 (または statusline 再描画時) に反映される。 + +## 自動デフォルト設定 (SessionStart hook) + +プラグインインストール後の初回セッション開始時に `statusline-switch.sh ensure` が実行され、 +**statusLine が未設定の場合のみ** NDF 標準 statusline が設定される。 +既に statusline が設定されている場合はそちらが優先され、何も変更しない。 +NDF 標準 statusline の利用中は、プラグイン更新時にスクリプト +(`~/.claude/ndf-statusline.sh`) の内容が自動で追従する。 diff --git a/plugins/ndf/skills-claude/statusline/tests/__init__.py b/plugins/ndf/skills-claude/statusline/tests/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/plugins/ndf/skills-claude/statusline/tests/test_statusline_switch.py b/plugins/ndf/skills-claude/statusline/tests/test_statusline_switch.py new file mode 100644 index 00000000..c875a371 --- /dev/null +++ b/plugins/ndf/skills-claude/statusline/tests/test_statusline_switch.py @@ -0,0 +1,150 @@ +"""statusline-switch.sh `ensure` のバージョンアップ追従ロジックを検証する。 + +NDF が過去に配置した statusline コピー (マーカー付き / レガシー +statusline-command.sh) を settings.json が指している場合に、正規パス +(~/.claude/ndf-statusline.sh) 参照へ自動移行することを確認する。 +ユーザー独自の statusline は決して上書きしないこと (誤検出ガード) も検証する。 + +既存 cross-review テストの規約に倣い、隔離 HOME 上で bash スクリプトを +subprocess 実行して settings.json の最終状態を観測する。 +""" +from __future__ import annotations + +import json +import os +import shutil +import subprocess +from pathlib import Path + +import pytest + +# bash / jq が無ければモジュールごと skip +for _cmd in ("bash", "jq"): + if shutil.which(_cmd) is None: + pytest.skip(f"{_cmd} not available", allow_module_level=True) + +# plugins/ndf/skills/statusline/tests/ -> plugins/ndf/scripts/statusline-switch.sh +SWITCH = Path(__file__).resolve().parents[3] / "scripts" / "statusline-switch.sh" +NDF_COMMAND = "bash ~/.claude/ndf-statusline.sh" + +# NDF statusline コピーとみなされる最小内容 (レガシー判定用: ctx ラベル + コンテナ名取得) +LEGACY_COPY = ( + "#!/bin/bash\n" + "container_name=$(hostname)\n" + 'printf "[ctx: 1k / 2k tokens (5%%)]"\n' +) +# マーカー付きコピー (将来の全コピーが該当) +MARKED_COPY = ( + "#!/bin/bash\n" + "# ndf-statusline: managed (do not edit; auto-updated by ndf:statusline)\n" + 'echo "hi"\n' +) +# NDF と無関係なユーザー独自 statusline +CUSTOM = '#!/bin/bash\necho "my custom bar"\n' + + +def _run_ensure(home: Path) -> subprocess.CompletedProcess: + """隔離 HOME で `statusline-switch.sh ensure` を実行する。""" + env = os.environ.copy() + env["HOME"] = str(home) + return subprocess.run( + ["bash", str(SWITCH), "ensure"], + capture_output=True, + text=True, + env=env, + ) + + +def _settings(home: Path) -> dict: + return json.loads((home / ".claude" / "settings.json").read_text()) + + +def _write_settings(home: Path, command: str) -> None: + (home / ".claude" / "settings.json").write_text( + json.dumps({"statusLine": {"type": "command", "command": command}}) + ) + + +def _claude(home: Path) -> Path: + d = home / ".claude" + d.mkdir(parents=True, exist_ok=True) + return d + + +def test_legacy_copy_is_migrated(tmp_path: Path) -> None: + """マーカー無しの既知レガシー statusline-command.sh は正規パスへ移行される。""" + claude = _claude(tmp_path) + (claude / "statusline-command.sh").write_text(LEGACY_COPY) + _write_settings(tmp_path, "bash ~/.claude/statusline-command.sh") + + result = _run_ensure(tmp_path) + + assert result.returncode == 0, result.stderr + assert _settings(tmp_path)["statusLine"]["command"] == NDF_COMMAND + # 既存設定がバックアップされていること + assert (claude / ".ndf-statusline-backup.json").is_file() + + +def test_marked_copy_is_migrated(tmp_path: Path) -> None: + """マーカー付きコピー (任意のファイル名) は正規パスへ移行される。""" + claude = _claude(tmp_path) + (claude / "my-status.sh").write_text(MARKED_COPY) + _write_settings(tmp_path, "bash ~/.claude/my-status.sh") + + result = _run_ensure(tmp_path) + + assert result.returncode == 0, result.stderr + assert _settings(tmp_path)["statusLine"]["command"] == NDF_COMMAND + + +def test_official_ndf_path_unchanged(tmp_path: Path) -> None: + """既に正規パスを指している場合は何もしない (deploy_script で本体追従済み)。""" + _claude(tmp_path) + _write_settings(tmp_path, NDF_COMMAND) + + result = _run_ensure(tmp_path) + + assert result.returncode == 0, result.stderr + assert _settings(tmp_path)["statusLine"]["command"] == NDF_COMMAND + # 正規パスの場合はバックアップを作らない + assert not (tmp_path / ".claude" / ".ndf-statusline-backup.json").exists() + + +def test_user_custom_is_respected(tmp_path: Path) -> None: + """ユーザー独自 statusline (マーカー無し・別名) は尊重し上書きしない。""" + claude = _claude(tmp_path) + (claude / "mybar.sh").write_text(CUSTOM) + _write_settings(tmp_path, "bash ~/.claude/mybar.sh") + + result = _run_ensure(tmp_path) + + assert result.returncode == 0, result.stderr + assert _settings(tmp_path)["statusLine"]["command"] == "bash ~/.claude/mybar.sh" + assert not (claude / ".ndf-statusline-backup.json").exists() + + +def test_same_name_but_non_ndf_content_is_guarded(tmp_path: Path) -> None: + """statusline-command.sh でも NDF 特徴を含まなければ移行しない (誤検出ガード)。""" + claude = _claude(tmp_path) + (claude / "statusline-command.sh").write_text(CUSTOM) + _write_settings(tmp_path, "bash ~/.claude/statusline-command.sh") + + result = _run_ensure(tmp_path) + + assert result.returncode == 0, result.stderr + assert ( + _settings(tmp_path)["statusLine"]["command"] + == "bash ~/.claude/statusline-command.sh" + ) + assert not (claude / ".ndf-statusline-backup.json").exists() + + +def test_unset_statusline_gets_ndf_default(tmp_path: Path) -> None: + """statusLine 未設定なら NDF 標準を新規設定する。""" + claude = _claude(tmp_path) + (claude / "settings.json").write_text("{}") + + result = _run_ensure(tmp_path) + + assert result.returncode == 0, result.stderr + assert _settings(tmp_path)["statusLine"]["command"] == NDF_COMMAND diff --git a/plugins/ndf/skills-claude/sync-main/SKILL.md b/plugins/ndf/skills-claude/sync-main/SKILL.md new file mode 100644 index 00000000..87aa2230 --- /dev/null +++ b/plugins/ndf/skills-claude/sync-main/SKILL.md @@ -0,0 +1,48 @@ +--- +name: sync-main +description: "Sync the current branch with main or master." +disable-model-invocation: true +allowed-tools: + - Bash + - Read +--- + +# main取り込みコマンド + +最新のデフォルトブランチ(main/master)を現在のブランチにマージする。 + +## 処理フロー + +1. **ブランチ確認** + - `git branch --show-current` で現在ブランチ確認 + - デフォルトブランチ(main/master)自身の場合は `git pull` のみ実行して終了 + +2. **作業ツリー確認** + - `git status` で未コミット変更を確認 + - 未コミット変更があれば `git stash` で退避 + +3. **最新取得** + - `git fetch origin ` でリモート最新を取得 + +4. **マージ実行** + - `git merge origin/ --no-edit` でマージ + - コンフリクト発生時: + - `git diff --name-only --diff-filter=U` でコンフリクトファイル一覧を表示 + - ユーザーに報告し、**自動解決はしない** + - ユーザー確認後に作業継続 + +5. **後処理** + - stash退避していた場合は `git stash pop` で復元 + - コンフリクトがなければ `git push` でリモートに反映 + - 完了報告(マージ済みコミット数、変更ファイル数) + +## 制約 + +- デフォルトブランチ自身での実行は `git pull` に自動フォールバック +- コンフリクトは自動解決しない(ユーザーが解決) +- 作業ツリーが汚れている場合は必ず stash で退避してから実行 + +## 関連 + +- `/ndf:branch-fix-strategy` — 複数ブランチへの修正適用戦略 +- `/ndf:cherry-pick-pr` — 環境ブランチへのcherry-pick PR作成 diff --git a/plugins/ndf/skills-codex/branch-fix-strategy/SKILL.md b/plugins/ndf/skills-codex/branch-fix-strategy/SKILL.md new file mode 100644 index 00000000..a4714a34 --- /dev/null +++ b/plugins/ndf/skills-codex/branch-fix-strategy/SKILL.md @@ -0,0 +1,87 @@ +--- +name: branch-fix-strategy +description: "Plan multi-branch fixes and cherry-picks." +when_to_use: "同じ修正を複数ブランチ (qa/staging/release等) に適用する必要があるとき。Triggers: 'cherry-pick', '環境ブランチに修正適用', 'qaに反映', 'stagingに反映', 'release branchへ', 'multi-branch fix', 'apply to qa/staging'" +--- + +# ブランチ修正適用戦略 + +## 適用タイミング + +- featureブランチの修正を `qa/*`, `staging/*`, `release/*` 等の環境ブランチにも適用する必要がある場合 +- 同じ修正を複数ブランチに並行適用する場面全般 + +## 核心ルール + +### 1. 修正は feature ブランチに先に commit → cherry-pick で環境ブランチへ + +``` +✅ feature に commit → cherry-pick して短命ブランチ → 環境ブランチへ PR +❌ 短命ブランチに先に commit → feature に手作業で再実装(二重作業・不整合リスク) +``` + +### 2. 環境ブランチを feature ブランチに merge しない(main 汚染禁止) + +``` +❌ feature/xxx ← merge qa/staging(conflict 解消目的でも禁止) +``` + +環境ブランチを featureブランチにmergeすると、後で `feature → main` のPRに環境固有コードが混入する。 + +### 3. origin/main を必ず取り込む + +短命ブランチを push する前に必ず `git merge origin/main` する。CI で最新 main 必須の Workflow があるため。 + +### 4. マージ済みブランチに push しない + +環境ブランチ向けの短命ブランチに push する前に `gh pr list --head ` で PR 状態を確認する。マージ済みなら新ブランチ + 新 PR を作成する(サフィックス `-v2`, `-v3` を付ける)。 + +## 実行手順 + +`/ndf:cherry-pick-pr ` で自動化されている。手動で行う場合のみ以下を参照。 + +```bash +# 1. feature ブランチで修正を commit +git checkout feature/xxx +git add && git commit -m "fix: 修正内容" +git log --oneline -1 # commit hash を記録 + +# 2. 短命ブランチを作成 +git fetch origin qa/staging +git checkout -b feature/xxx-for-staging origin/qa/staging + +# 3. origin/main を取り込む(必須) +git fetch origin main +git merge origin/main --no-edit + +# 4. cherry-pick(-x で元 commit hash を参照に残す) +git cherry-pick -x + +# 5. push して PR 作成 +git push -u origin feature/xxx-for-staging +gh pr create --base qa/staging --title "fix: 修正内容(staging検証用)" + +# 6. 元のブランチに戻る +git checkout feature/xxx +``` + +## なぜこの順序が重要か + +| 観点 | 正しい順序 | 誤った順序 | +|------|-----------|-----------| +| 単一ソース | feature ブランチが唯一の正 | 二箇所で実装 | +| 一貫性 | cherry-pick で完全一致 | 手書き差分でズレる | +| 追跡性 | `-x` で元 commit が明記 | 関連 commit 不明確 | + +## revert 操作の注意 + +revertの連鎖(revert → reapply → revert...)ではなく、**最終的なあるべき状態を直接コミット**するのが望ましい。履歴上の意図が明確になり、後の cherry-pick も簡単になる。 + +## 関連コマンド・スキル + +| リソース | 用途 | +|---------|------| +| `/ndf:cherry-pick-pr` | cherry-pick + 短命ブランチ + origin/main 取り込み + PR 作成を自動化 | +| `/ndf:pr` | 通常のPR作成。非 main ベースは `cherry-pick-pr` に誘導される | +| `/ndf:sync-main` | 現在のブランチに最新 main を取り込む | +| `/ndf:deploy` | 環境ブランチへのデプロイPR作成(ブランチ全体をmerge main経由で適用) | diff --git a/plugins/ndf/skills-codex/cherry-pick-pr/SKILL.md b/plugins/ndf/skills-codex/cherry-pick-pr/SKILL.md new file mode 100644 index 00000000..b5dc1341 --- /dev/null +++ b/plugins/ndf/skills-codex/cherry-pick-pr/SKILL.md @@ -0,0 +1,120 @@ +--- +name: cherry-pick-pr +description: "Create cherry-pick PRs for environment branches." +argument-hint: " (例: qa/staging, release/v2)" +disable-model-invocation: true +allowed-tools: + - Bash + - Read + - Grep +--- + +# cherry-pick PR 作成コマンド + +featureブランチから指定ベースブランチへ、短命ブランチ経由で cherry-pick PR を作成する。`feature → main` の PR にベースブランチ固有コードが混入するのを防ぐ。 + +## 使用方法 + +``` +/ndf:cherry-pick-pr qa/staging +/ndf:cherry-pick-pr release/v2 +``` + +## なぜ必要か + +featureブランチに環境ブランチ(`qa/staging`等)を merge して conflict を解消すると、`feature → main` の PR に環境ブランチ固有のコードが混入する(main汚染)。短命ブランチ + cherry-pick で、必要なコミットだけを対象ブランチに届ける。 + +詳細な原則は `/ndf:branch-fix-strategy` スキル参照。 + +## 処理フロー + +### 1. 引数・現状確認 +- 引数からベースブランチ名を取得(必須。未指定なら確認) +- `git branch --show-current` で現在ブランチを取得 + +### 2. 既存PRのマージ済みチェック(必須) + +同じベースブランチ向けの短命ブランチに既存PRがないか確認する。 + +```bash +# 同名パターンのブランチでマージ済みPRがないか確認 +gh pr list --head "-for-" --state merged \ + --json number,mergedAt --jq '.[]' +``` + +マージ済みPRが見つかった場合、**同じブランチ名は使えない**。サフィックスを付ける(例: `-v2`, `-v3`)。 + +### 3. コミット一覧の確認 + +```bash +git log --oneline main..HEAD +``` + +ユーザーに cherry-pick 対象コミットを確認(全コミット or 選択)。 + +### 4. 短命ブランチ作成 + +```bash +git fetch origin +git checkout -b -for- origin/ +``` + +- ``: ベースブランチのスラッシュ以降(例: `qa/staging` → `staging`) +- 例: `feature/add-auth-for-staging` + +### 5. origin/main を取り込む(必須) + +```bash +git fetch origin main +git merge origin/main --no-edit +``` + +CIで最新main必須のWorkflowがあるため、取り込み忘れるとconflictやCIエラーになる。 + +### 6. cherry-pick 実行 + +```bash +git cherry-pick -x ... +``` + +`-x` オプションで元のcommit hashが参照として残り、追跡性が向上する。 + +conflict が発生した場合: +- `git diff --name-only --diff-filter=U` でconflictファイル一覧 +- 解消を試み、ユーザーに確認後 `git cherry-pick --continue` + +### 7. push して PR 作成 + +```bash +git push -u origin +gh pr create --base --title "<タイトル>" --body "$(cat <<'EOF' +## Summary +- feature/xxx からcherry-pickした<環境名>向けPR +- 元コミット: + +## Test plan +- [ ] <環境名>で動作確認 + + +EOF +)" +``` + +### 8. 元ブランチに戻る + +```bash +git checkout +``` + +## 注意事項 + +- 短命ブランチは PR マージ後に削除してよい +- `feature → main` の PR には影響しない +- ベースブランチを feature ブランチに merge するのは **禁止**(main汚染の原因) +- `-x` オプションで元commit参照を残す(追跡性) + +## 関連 + +- `/ndf:branch-fix-strategy` — なぜこの手順が必要かの原則 +- `/ndf:pr` — 通常のPR作成(base=main) +- `/ndf:deploy` — ブランチ全体を環境へデプロイ(cherry-pickとは別用途) diff --git a/plugins/ndf/skills-codex/clean/SKILL.md b/plugins/ndf/skills-codex/clean/SKILL.md new file mode 100644 index 00000000..2f75e54e --- /dev/null +++ b/plugins/ndf/skills-codex/clean/SKILL.md @@ -0,0 +1,20 @@ +--- +name: clean +description: "Delete local and remote merged branches." +disable-model-invocation: true +allowed-tools: + - Bash +--- + +# ブランチクリーンアップコマンド + +mainマージ済みブランチをローカル/リモート削除。 + +## 手順 + +1. `git branch --merged main`確認 +2. main・現在ブランチ除外 +3. `git branch -d ` +4. `git push origin --delete ` + +**注意**: 削除前確認・main除外・現在ブランチ除外 diff --git a/plugins/ndf/skills-codex/deploy/SKILL.md b/plugins/ndf/skills-codex/deploy/SKILL.md new file mode 100644 index 00000000..769919d7 --- /dev/null +++ b/plugins/ndf/skills-codex/deploy/SKILL.md @@ -0,0 +1,114 @@ +--- +name: deploy +description: "Create deploy PRs from feature to environment branches." +argument-hint: " (例: qa/staging, release/v2)" +disable-model-invocation: true +allowed-tools: + - Bash + - Read +--- + +# 環境デプロイPR作成コマンド + +現在のfeatureブランチを指定した環境ブランチへデプロイするためのPRを作成する。`{feature}_to_{env}` という命名のdeployブランチを作成し、最新 origin/main を取り込んでから環境ブランチへPRを出す。 + +## 使用方法 + +``` +/ndf:deploy qa/staging +/ndf:deploy release/v2 +``` + +## cherry-pick-pr との使い分け + +| 観点 | cherry-pick-pr | deploy | +|---|---|---| +| 適用範囲 | featureブランチの**一部コミット**を選択 | featureブランチ**全体**を適用 | +| ブランチ戦略 | 環境ブランチから短命ブランチ派生 | featureブランチから deploy ブランチ派生 | +| main取り込み | 必須 | 必須 | +| 用途 | 特定修正のみ検証環境に届けたい | feature機能全体を環境で検証したい | + +## 処理フロー + +### 1. バリデーション + +```bash +CURRENT_BRANCH=$(git branch --show-current) +[[ "$CURRENT_BRANCH" == "main" || "$CURRENT_BRANCH" == "master" ]] && \ + echo "❌ Error: デフォルトブランチからデプロイできません" && exit 1 +``` + +### 2. deployブランチ名の導出 + +```bash +FEATURE_BRANCH=$(git branch --show-current) +# 環境名を抽出: "qa/staging" → "staging", "release/v2" → "v2" +ENV_SUFFIX=$(echo "$ARGUMENTS" | sed 's|.*/||') +DEPLOY_BRANCH="${FEATURE_BRANCH}_to_${ENV_SUFFIX}" +``` + +### 3. 既存PRチェック + +```bash +EXISTING_PR=$(gh pr list --head "$DEPLOY_BRANCH" --base "$ARGUMENTS" \ + --json number,url --jq '.[0].url // empty') +if [[ -n "$EXISTING_PR" ]]; then + echo "✅ PR already exists: $EXISTING_PR" + exit 0 +fi +``` + +既存PRがあれば更新は「deployブランチにpushする」だけで済むため、再作成しない。 + +### 4. deployブランチ作成 + main取り込み + +```bash +git fetch origin main +git checkout -b "$DEPLOY_BRANCH" +git merge origin/main --no-edit || { + echo "❌ main とのmerge conflict。手動解決が必要です" + git merge --abort + git checkout "$FEATURE_BRANCH" + git branch -D "$DEPLOY_BRANCH" + exit 1 +} +``` + +### 5. push + PR作成 + +```bash +git push -u origin "$DEPLOY_BRANCH" +gh pr create --base "$ARGUMENTS" --head "$DEPLOY_BRANCH" \ + --title "$DEPLOY_BRANCH → $ARGUMENTS" \ + --body "$(cat <<'EOF' +## Summary +- 環境デプロイ用PR +- 元ブランチ: $FEATURE_BRANCH +- main取り込み済み + +## Test plan +- [ ] $ARGUMENTS 環境で動作確認 + + +EOF +)" +``` + +### 6. 元ブランチに復帰 + +```bash +git checkout "$FEATURE_BRANCH" +``` + +## 注意事項 + +- デフォルトブランチからの実行は禁止 +- main取り込みで conflict が出た場合、deployブランチを削除して戻る(featureブランチ側を先に同期すべき) +- deployブランチは PR マージ後に削除してよい +- 環境ブランチへの再デプロイは「同じ deployブランチに push」でPRが更新される + +## 関連 + +- `/ndf:cherry-pick-pr` — 一部コミットだけを環境に届ける場合 +- `/ndf:branch-fix-strategy` — ブランチ運用戦略の原則 +- `/ndf:sync-main` — featureブランチに main を取り込む diff --git a/plugins/ndf/skills-codex/docker-container-access/01-environment-detection.md b/plugins/ndf/skills-codex/docker-container-access/01-environment-detection.md new file mode 100644 index 00000000..51941bcc --- /dev/null +++ b/plugins/ndf/skills-codex/docker-container-access/01-environment-detection.md @@ -0,0 +1,84 @@ +# 環境判定ガイド + +## Step 1: 自身の環境を確認 + +```bash +# 自分がコンテナ内で動作しているか確認 +cat /proc/1/cgroup 2>/dev/null | grep -q docker && echo "コンテナ内" || echo "ホスト環境" + +# または +[ -f /.dockerenv ] && echo "コンテナ内" || echo "ホスト環境" +``` + +## Step 2: Docker環境の種類を判定 + +自身がコンテナ内の場合、以下のいずれかの環境です: + +| 環境 | 説明 | 判定方法 | +|-----|------|---------| +| **DinD** (Docker in Docker) | コンテナ内に独立したDockerデーモン | `docker info`でDocker rootが`/var/lib/docker` | +| **DooD** (Docker outside of Docker) | ホストのDockerソケットを共有 | `/var/run/docker.sock`がマウントされている | + +```bash +# DooD判定: docker.sockがマウントされているか +ls -la /var/run/docker.sock 2>/dev/null && echo "DooD環境の可能性" || echo "DinDまたはホスト環境" + +# Docker rootディレクトリの確認 +docker info 2>/dev/null | grep "Docker Root Dir" +``` + +## DinD環境でのアクセス + +DinD環境では、**localhost**で他のコンテナにアクセスできます。 + +### 特徴 +- コンテナ内に独立したDockerデーモンが動作 +- ネットワークは通常のDocker環境と同じ +- `localhost:ポート`でアクセス可能 + +### アクセス例 + +```bash +# Webサーバーへのアクセス +curl http://localhost:8080 + +# データベースへの接続 +mysql -h localhost -P 3306 -u user -p + +# Playwright MCPでのアクセス +# URL: http://localhost:3000 +``` + +## 環境判定スクリプト + +```bash +#!/bin/bash +# Docker環境判定スクリプト + +echo "=== Docker環境判定 ===" + +# 自分がコンテナ内かチェック +if [ -f /.dockerenv ] || grep -q docker /proc/1/cgroup 2>/dev/null; then + echo "実行環境: Dockerコンテナ内" + + # DinD/DooD判定 + if [ -S /var/run/docker.sock ]; then + echo "Docker形式: DooD (Docker outside of Docker)" + echo "" + echo "→ 他のコンテナへのアクセスにはコンテナ名を使用してください" + echo "→ bind mountはホストのパスを参照するため注意が必要です" + else + echo "Docker形式: DinD (Docker in Docker)" + echo "" + echo "→ localhostで他のコンテナにアクセス可能です" + fi +else + echo "実行環境: ホストマシン" + echo "" + echo "→ 通常のDocker操作が可能です" +fi + +echo "" +echo "=== 利用可能なコンテナ ===" +docker ps --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}" 2>/dev/null || echo "Dockerが利用できません" +``` diff --git a/plugins/ndf/skills-codex/docker-container-access/02-dood-access.md b/plugins/ndf/skills-codex/docker-container-access/02-dood-access.md new file mode 100644 index 00000000..d19fc967 --- /dev/null +++ b/plugins/ndf/skills-codex/docker-container-access/02-dood-access.md @@ -0,0 +1,134 @@ +# DooD環境でのアクセスガイド + +## 特徴 + +- ホストのDockerデーモンを共有 +- localhostはホストマシンを指す(他のコンテナではない) +- コンテナ間通信はDockerネットワーク経由 + +## アクセス方法 + +### 1. コンテナ名でアクセス(同一ネットワーク内) + +```bash +# コンテナ名を確認 +docker ps --format "table {{.Names}}\t{{.Ports}}" + +# コンテナ名でアクセス +curl http://my-web-container:8080 + +# docker-composeの場合、サービス名でアクセス +curl http://web:8080 +``` + +### 2. Dockerネットワーク経由 + +```bash +# ネットワーク一覧を確認 +docker network ls + +# 特定ネットワークのコンテナを確認 +docker network inspect bridge --format '{{range .Containers}}{{.Name}} {{.IPv4Address}}{{"\n"}}{{end}}' + +# IPアドレスでアクセス +curl http://172.17.0.2:8080 +``` + +### 3. 同一ネットワークへの参加 + +```bash +# 自分のコンテナを対象コンテナと同じネットワークに接続 +docker network connect my-network $(hostname) + +# その後、コンテナ名でアクセス可能 +curl http://target-container:8080 +``` + +## curlでのアクセス例 + +```bash +# NG: localhostは使えない +curl http://localhost:8080 # → Connection refused + +# OK: コンテナ名を使用 +curl http://my-app-container:8080 + +# OK: docker-composeのサービス名 +curl http://api:3000 + +# OK: コンテナのIPアドレス +CONTAINER_IP=$(docker inspect -f '{{range.NetworkSettings.Networks}}{{.IPAddress}}{{end}}' my-container) +curl http://${CONTAINER_IP}:8080 +``` + +## Playwright MCP / Chrome DevTools MCP + +```bash +# DooD環境では、コンテナ名またはIPを使用 +# URL: http://web-container:3000 (コンテナ名) +# URL: http://172.17.0.3:3000 (IP) +``` + +--- + +## bind mountの注意点 + +### 問題 + +DooD環境では、`docker run -v`や`docker-compose`のbind mountは**ホストマシンのパス**を参照します。開発コンテナ内のパスではありません。 + +```yaml +# NG: DooD環境では期待通りに動作しない +volumes: + - ./local-dir:/app/data # ホストの./local-dirを参照してしまう +``` + +### 解決策 + +#### 1. Dockerfileでコピー(推奨) + +```dockerfile +FROM node:18 +WORKDIR /app +COPY . . +RUN npm install +CMD ["npm", "start"] +``` + +#### 2. 名前付きボリュームを使用 + +```bash +# ボリュームを作成 +docker volume create my-data + +# ファイルをボリュームにコピー +docker run --rm -v my-data:/data -v $(pwd):/src alpine cp -r /src/. /data/ + +# ボリュームをマウントしてコンテナ起動 +docker run -v my-data:/app/data my-image +``` + +#### 3. docker cpを使用 + +```bash +# コンテナにファイルをコピー +docker cp ./local-file.txt my-container:/app/ + +# コンテナからファイルを取得 +docker cp my-container:/app/output.txt ./ +``` + +### docker-compose.yml での対応 + +```yaml +# DooD環境対応版 +version: '3.8' +services: + app: + build: . # Dockerfileでファイルをコピー + volumes: + - app-data:/app/data # 名前付きボリューム使用 + +volumes: + app-data: +``` diff --git a/plugins/ndf/skills-codex/docker-container-access/03-troubleshooting.md b/plugins/ndf/skills-codex/docker-container-access/03-troubleshooting.md new file mode 100644 index 00000000..0acac32c --- /dev/null +++ b/plugins/ndf/skills-codex/docker-container-access/03-troubleshooting.md @@ -0,0 +1,63 @@ +# トラブルシューティング + +## Q: `curl: (7) Failed to connect to localhost port 8080` + +**原因**: DooD環境でlocalhostを使用している + +**解決策**: +```bash +# コンテナ名またはIPを使用 +docker ps # コンテナ名を確認 +curl http://container-name:8080 +``` + +## Q: bind mountしたファイルが見えない + +**原因**: DooD環境ではホストのパスを参照している + +**解決策**: +```bash +# docker cpでコピー +docker cp ./file.txt container:/app/ + +# または名前付きボリュームを使用 +``` + +## Q: コンテナ間で通信できない + +**原因**: 異なるDockerネットワークに所属している + +**解決策**: +```bash +# 同じネットワークに接続 +docker network connect my-network container-a +docker network connect my-network container-b +``` + +## Q: docker.sockへのアクセス権限がない + +**解決策**: +```bash +# docker グループに追加(要再ログイン) +sudo usermod -aG docker $USER + +# または一時的に権限付与 +sudo chmod 666 /var/run/docker.sock +``` + +--- + +# ベストプラクティス + +## DO(推奨) + +- **コンテナアクセス前に環境を判定する** +- **DooD環境ではコンテナ名/サービス名を使用する** +- **ファイル共有はDockerfileのCOPYまたは名前付きボリュームを使用** +- **docker-composeではサービス名でアクセス** + +## DON'T(非推奨) + +- **環境を確認せずにlocalhostを使用する** +- **DooD環境でbind mountに依存する** +- **IPアドレスをハードコードする(変わる可能性がある)** diff --git a/plugins/ndf/skills-codex/docker-container-access/SKILL.md b/plugins/ndf/skills-codex/docker-container-access/SKILL.md new file mode 100644 index 00000000..eadd1ffe --- /dev/null +++ b/plugins/ndf/skills-codex/docker-container-access/SKILL.md @@ -0,0 +1,76 @@ +--- +name: docker-container-access +description: "Diagnose Docker container access and localhost routing." +when_to_use: "Docker / コンテナへのアクセス・localhost 接続不可・DinD/DooD 環境判定が必要なとき。Triggers: 'docker access', 'container connect', 'localhost not working', 'DinD', 'DooD', 'Docker接続', 'コンテナアクセス', 'curl container'" +allowed-tools: + - Read + - Bash + - Glob +--- + +# Docker Container Access Skill + +## 概要 + +ローカル開発環境がDocker開発コンテナ上で動作している場合、他のDockerコンテナへのアクセス方法が通常と異なります。このスキルでは、環境を判定し、適切なアクセス方法を選択するためのガイドラインを提供します。 + +## クイックリファレンス + +``` +環境判定 → アクセス方法 +──────────────────────────────── +ホスト環境 → localhost:port +DinD環境 → localhost:port +DooD環境 → container-name:port または IP:port + +ファイル共有(DooD環境) +──────────────────────────────── +Dockerfile COPY → 推奨(ビルド時にコピー) +名前付きボリューム → 推奨(永続化が必要な場合) +docker cp → OK(一時的なコピー) +bind mount → NG(ホストのパスを参照) +``` + +## 環境判定(最初に実行) + +```bash +# 自分がコンテナ内か確認 +[ -f /.dockerenv ] && echo "コンテナ内" || echo "ホスト環境" + +# DooD判定 +ls -la /var/run/docker.sock 2>/dev/null && echo "DooD環境" || echo "DinDまたはホスト" +``` + +| 環境 | 説明 | コンテナへのアクセス | +|-----|------|-------------------| +| **ホスト** | 通常のDocker環境 | `localhost:port` | +| **DinD** | コンテナ内に独立したDockerデーモン | `localhost:port` | +| **DooD** | ホストのDockerソケットを共有 | `container-name:port` | + +## 詳細ガイド + +詳細は以下のファイルを参照してください: + +| ファイル | 内容 | +|---------|------| +| `01-environment-detection.md` | 環境判定の詳細、判定スクリプト | +| `02-dood-access.md` | DooD環境でのアクセス方法、bind mount注意点 | +| `03-troubleshooting.md` | トラブルシューティング、ベストプラクティス | + +## よくある問題(簡易版) + +| 症状 | 原因 | 解決策 | +|-----|------|--------| +| `localhost`で接続できない | DooD環境 | コンテナ名を使用 | +| bind mountしたファイルが見えない | DooD環境 | `docker cp`または名前付きボリューム | +| コンテナ間で通信できない | 別ネットワーク | 同じネットワークに接続 | + +## 関連Skill + +- **python-execution**: Python実行環境の判定 +- **corder-code-templates**: Dockerfileテンプレート + +## 関連リソース + +- [Docker Networking](https://docs.docker.com/network/) +- [Docker in Docker](https://hub.docker.com/_/docker) diff --git a/plugins/ndf/skills-codex/fix/SKILL.md b/plugins/ndf/skills-codex/fix/SKILL.md new file mode 100644 index 00000000..92471ddd --- /dev/null +++ b/plugins/ndf/skills-codex/fix/SKILL.md @@ -0,0 +1,303 @@ +--- +name: fix +description: "Fix actionable PR review comments." +when_to_use: "PRレビューコメント (codex/gemini/人間) の指摘を実際にコード修正で対応したいとき。review-pr-comments で分類した後の修正フェーズに使う。Triggers: 'PRコメント対応', 'PRレビュー修正', 'PR fix', 'review feedback fix', 'コメントに対応して修正'" +argument-hint: "[PR番号] [--defer-nit] [--severity-min critical|major|minor]" +allowed-tools: + - Bash + - Read + - Edit + - Write + - Glob + - Grep +--- + +# PR修正コマンド + +直前PR、または引数で指定されたPRのreview comment確認・修正対応実行。 + +## 起動モード + +このスキルは **メインセッション直接実行** と **サブエージェント (`general-purpose`) 起動** の両方に対応する。 +長丁場のクロスレビューループ(`/ndf:cross-review`)からは **必ずサブエージェント経由で起動** されることを想定: + +```python +# メインからの起動例(cross-review が内部でこれを行う) +Agent( + subagent_type="general-purpose", + description="Fix PR review comments (sub-agent)", + prompt=""" +/ndf:fix --defer-nit を実行してください。 + +PR: +リポジトリ: +重要度ポリシー: critical/major/minor は修正、nit は deferred として残す +完了後の戻り値: 件数サマリ + 修正コミット SHA + 残 nit リスト +""" +) +``` + +サブエージェント側ではこの SKILL.md を読み込んで、自己完結で +**修正 → コミット → push → reply → Resolve Conversation** まで実行する。 +メインへの戻り値は最小限のサマリのみ。 + +## 引数 + +| 引数 | 意味 | 既定 | +|---|---|---| +| `[PR番号]` | 対象 PR | 直前 PR | +| `--defer-nit` | nit 指摘は修正せず deferred としてリスト出力 | OFF | +| `--severity-min LEVEL` | 指定重要度未満は無視(`critical` / `major` / `minor`) | `minor` (= minor 以上を修正) | + +## 重要度ベースの自動修正ポリシー + +`[重要度 / カテゴリ]` プレフィックス(`/ndf:review` 出力規約)で分類。 +**ただし重要度ラベルを鵜呑みにしない** — 各指摘ごとにコード/仕様を独自に調査し、 +本来の重要度を判定し直してから下表の動作を適用する(bot のラベリングは参考値に過ぎない)。 + +| 重要度 | 動作 | ユーザ問い合わせ | +|---|---|---| +| `critical` | **必ず自動修正** | なし | +| `major` | **必ず自動修正** | なし | +| `minor` / `nit` (パフォーマンス・可読性・重複コード排除) | **このPRで修正対応**。特にトータル行数が減る方向の修正は積極的に実施 | なし | +| `minor` / `nit` (上記カテゴリ、修正範囲が +30 行を超えそう) | ユーザ問い合わせ | あり | +| `minor` (その他) | 自動修正(明らかな改善のみ)。判断が割れるなら `nit` として deferred 扱い | なし | +| `nit` (その他) | `--defer-nit` 指定時は **修正せず deferred リスト** に追加。最後にまとめてユーザ問い合わせ | あり(最後に1回) | + +**重要度の独自判定**: +- AI agent (CodeRabbit / Copilot 等) が `nit` と付けていても、実体がパフォーマンス改善や重複排除なら **minor/nit カテゴリ修正対象** として扱う +- 逆に AI agent が `critical` と付けていても、実害がないスタイル指摘なら `nit` 相当に格下げして deferred 化してよい +- 重要度はカテゴリ(performance/readability/duplication/security/style/etc)と合わせて、コード本体を読んだ上で判定する + +**指摘の正否判断**: +- ロジック・仕様逸脱・セキュリティ: コード/仕様を確認してから修正可否判断 +- bot 指摘で **明らかに誤読** している場合(例: 意図的な変数展開を「クオート不足」と指摘する等): 修正しない、reply で理由説明 +- 仕様判断が必要な指摘(API 変更、互換性破壊など): ユーザ問い合わせ対象(critical でもエスカレーション) + +**自動判断できない場合の取り扱い** (context 節約のため安易に user に投げない): +- 仕様文書(docs/, README)を読んで判断する +- 既存テストを読んで挙動を確認する +- 関連する他コードの慣例を確認する +- それでも不明なら deferred リストに「要ユーザ判断」として記録、最後にまとめて問い合わせ + +## 手順 + +1. review comment取得 + 重要度を**独自に再判定**(AI agent のラベルは参考値) +2. **CIエラー確認**(`gh pr checks ` で **現時点の** 失敗ジョブを検出) + - **完了待ちはしない**。実行中(PENDING/IN_PROGRESS)のチェックは無視して次ステップへ進む + - 直近で失敗(FAILURE)状態のジョブのみを修正対象に取り込む +3. 修正対象を確定: + - `critical` / `major` → 全件修正対象 + - `minor` / `nit` (パフォーマンス・可読性・重複排除) → 修正対象。+30行超なら **deferred + ユーザ問い合わせ** + - `minor` (その他) → 修正対象(明らかでないものは `deferred[]` へ) + - `nit` (その他、`--defer-nit` 時) → `deferred[]` のみ、修正しない + - CIエラー → 全件修正対象(PRテスト範囲外の **flaky テストも見つけ次第修正**) +4. 問題点修正 + - **コード行数が減る方向の修正は積極的に実施**(重複排除、不要分岐除去 等) +5. **コミット前の再確認**(修正作業中に状況が変わっている可能性への対応) + - **review comment再取得**: 作業中に新しいコメントが追加されていないか確認 + - **CI状態再確認**: 現時点の状態だけ確認(完了待ちはしない)。新しい失敗が出ていれば対象に取り込む + - 新しい指摘/失敗があれば手順3に戻る +6. コミット・プッシュ +7. PRにSummaryコメントを追加(対応した件数 + deferred 件数を明記) +8. 対応したインラインコメントに個別に返信 +9. **deferred スレッドには `[deferred / nit]` のラベル付き返信** を投稿(resolve はしない) +10. reviewerに再レビューを依頼 +11. 対応完了したインラインコメントを「Resolve Conversation」にする(`resolveReviewThread` mutation) + - resolve した thread_id / comment_id / path / line を `resolved_threads[]` に記録 + - `deferred` / `rejected` の thread は Resolve しない(次ラウンドで再評価するため) +12. **戻り値ファイルを書き出す**: `/tmp/fix-pr<番号>-result.json` (後述「戻り値フォーマット」参照) + - `ci_failed_checks` には `gh pr checks --json name,state` から `state=FAILURE` の name を抽出して列挙 + - push 直後の CI 再実行結果は**待たない**ため、戻り値の `ci_status` は push 時点での既知失敗のみを反映する + +- 4〜6はgit、1〜2/5と7以降はgithub mcpまたはghを利用 + +**flakyテストの扱い**: PR の変更範囲外で発生している flaky テストも、見つけ次第このPRで修正する。 +flaky を放置するとリポジトリ全体のコード品質が下がり、後続 PR の CI 信頼性も損なわれるため。 + +## CIエラーチェック + +### 失敗ジョブの検出 + +```bash +# PRの全チェック状態を確認(FAIL/PASS/PENDING) +gh pr checks + +# JSON形式で詳細取得 +gh pr checks --json name,state,link,completedAt + +# 失敗ジョブのみ抽出 +gh pr checks --json name,state | \ + python3 -c "import json,sys; [print(c['name']) for c in json.load(sys.stdin) if c['state']=='FAILURE']" + +# 実行中ジョブのみ抽出(状態スナップショット用。完了は待たない) +gh pr checks --json name,state | \ + python3 -c "import json,sys; [print(c['name']) for c in json.load(sys.stdin) if c['state'] in ('PENDING','IN_PROGRESS','QUEUED')]" +``` + +### CI完了待ちはしない + +このスキルでは **CI 完了待ちは行わない**(`gh pr checks --watch` 等は使わない)。 +- 各チェックポイントでは「現時点で FAILURE のジョブ」のみを取り込んで修正する +- push 後の CI 再実行結果も待たない(待機中に context を消費しないため) +- ただし `gh pr checks --json name,state` での **状態スナップショット取得は実施** + し、戻り値の `ci_status` / `ci_failed_checks` に反映する + +### 失敗ログの取得 + +```bash +# ワークフロー実行ID取得 +RUN_ID=$(gh run list --branch --limit 1 --json databaseId --jq '.[0].databaseId // empty') +[ -z "$RUN_ID" ] && { echo "No CI run found for this branch"; exit 0; } + +# 失敗ステップのログだけ表示(効率的) +gh run view $RUN_ID --log-failed + +# 特定ジョブのログ +gh run view $RUN_ID --job --log +``` + +### CIエラーの分類と対応方針 + +| エラー種別 | 対応方針 | +|---|---| +| **lint/format** | 自動修正ツール実行(`ruff`, `prettier`, `eslint --fix` 等)→ コミット | +| **型チェック** | 型定義・アノテーションを修正。無視コメントは原則禁止(根本対応) | +| **テスト失敗** | 失敗テストを読み、実装/テストどちらが正しいか判断してから修正。テスト側の問題なら仕様確認 | +| **ビルドエラー** | 依存関係・構文・設定ファイルを確認 | +| **依存脆弱性** | 可能ならバージョン更新、無理なら除外ルール追加(理由明記) | +| **タイムアウト/flaky** | retry設定、テスト分割、リトライ追加。**PR範囲外の flaky も見つけ次第修正**(放置でリポジトリ全体の品質劣化を招くため) | +| **インフラ一時障害** | 再実行で解消することがあるため `gh run rerun $RUN_ID` を先に試す | + +### review指摘との統合 + +review指摘とCIエラーは**同じPRで一緒に修正**する: +- 同じファイル・機能に関する指摘とCIエラーは1コミットにまとめる +- 独立しているなら別コミットに分離(git log で追いやすい) + +## ghコマンド例 + +### PR コメント一括取得 (3 ソース) + +```bash +# インラインコメント / レビュー body / PR レベルコメントを一括取得 +FETCH_SCRIPT="${PLUGIN_ROOT:-${CLAUDE_PLUGIN_ROOT}}/skills/fix/scripts/fetch-pr-comments.sh" +"$FETCH_SCRIPT" +``` + +### コメントへの返信 + +```bash +# PRのレビューコメント一覧を取得 (インラインコメントのみ) +gh api repos/{owner}/{repo}/pulls/{pr_number}/comments + +# 特定のコメントに返信(in_reply_to にコメントIDを指定) +gh api repos/{owner}/{repo}/pulls/{pr_number}/comments \ + -f body="修正しました。" \ + -F in_reply_to={comment_id} +``` + +### Resolve Conversation + +```bash +# GraphQL APIでスレッドをresolveする +gh api graphql -f query=' + mutation { + resolveReviewThread(input: {threadId: "{thread_node_id}"}) { + thread { isResolved } + } + } +' +``` + +### thread_node_idの取得方法 + +```bash +# PRのレビュースレッド一覧を取得(node_id含む) +gh api graphql -f query=' + query { + repository(owner: "{owner}", name: "{repo}") { + pullRequest(number: {pr_number}) { + reviewThreads(first: 100) { + nodes { + id + isResolved + comments(first: 1) { + nodes { body } + } + } + } + } + } + } +' +``` + +**方針**: +- 品質・可読性・セキュリティ向上、既存機能影響なし +- 指摘がすべて正しいとは限らない。修正前に仕様を調査し、実施の可否を判断すること +- 未対応の場合はその理由をコメントに書き込む + +## 戻り値フォーマット(必須) + +サブエージェント呼び出し時の context 節約のため、**実行結果は `/tmp/fix-pr<番号>-result.json` に書き出す**: + +```json +{ + "pr": 67, + "fix_commit": "abc1234", + "ci_status": "SUCCESS" | "FAILURE" | "PENDING" | "NONE", + "ci_failed_checks": [], + "ci_note": null, + "fixed_count": 5, + "by_severity": {"critical": 1, "major": 2, "minor": 2, "nit": 0}, + "resolved_threads": [ + { + "thread_id": "PRRT_...", + "comment_id": 3222849090, + "path": "src/foo.py", + "line": 42 + } + ], + "deferred": [ + { + "comment_id": 3222849090, + "thread_id": "PRRT_...", + "path": "src/foo.py", + "line": 42, + "severity": "nit", + "category": "style", + "summary": "末尾セミコロンの有無", + "reason_for_deferral": "好みの範囲。プロジェクト規約と齟齬なし" + } + ], + "rejected": [ + { + "comment_id": 3222849090, + "summary": "heredoc を <<'JSON' にせよ", + "reason_for_rejection": "$SHA を意図的に展開する必要があり、クオート化すると逆に壊れる" + } + ], + "summary_comment_url": "https://github.com/.../pull/67#issuecomment-..." +} +``` + +**フィールド説明**: + +- `ci_failed_checks` — `ci_status = FAILURE` のとき、失敗した check 名の配列。`/ndf:cross-review` 側で code-related (`pint/larastan/test/build/lint/type`) と meta-only (`check_pr_requirements/assignees/reviewers/labels`) を分類し、メタチェックのみ失敗ならループ継続する +- `ci_note` — code-related ではない CI 失敗の補足。例: `"メタチェックのみ失敗: check_pr_requirements — Assignees 未設定"` +- `resolved_threads` — 手順 11 で `resolveReviewThread` mutation を実行したスレッド一覧。`deferred` / `rejected` の thread は **Resolve しない**(再評価のため) + +サブエージェントとして起動された場合は、この JSON をメインに返すサマリの基礎とする。 + +## 作業完了報告(必須) + +メイン or PR への報告内容(戻り値ファイルから抽出): +- 対応した指摘の件数(重要度別: critical/major/minor/nit) +- **deferred 件数**(主に nit、最後にユーザ問い合わせ予定) +- **rejected 件数**(bot 指摘が不適切で修正しなかった件、各々理由付き) +- **対応したCIエラーの一覧**(ジョブ名、エラー内容、修正方法) +- **対応した flaky テストの一覧**(PR範囲外も含む) +- 修正コミット SHA / 修正ファイル一覧 +- 戻り値ファイルパス: `/tmp/fix-pr<番号>-result.json` +- **PR URL を最後に必ず記載**(例: `https://github.com///pull/<番号>`) diff --git a/plugins/ndf/skills-codex/fix/scripts/fetch-pr-comments.sh b/plugins/ndf/skills-codex/fix/scripts/fetch-pr-comments.sh new file mode 100755 index 00000000..aa7f97fe --- /dev/null +++ b/plugins/ndf/skills-codex/fix/scripts/fetch-pr-comments.sh @@ -0,0 +1,47 @@ +#!/usr/bin/env bash +# Usage: fetch-pr-comments.sh +# 3 ソース (インラインコメント / レビュー body / PR レベルコメント) を一括取得し、 +# タグ付き行単位で stdout に出力する。 +# 全ソース取得失敗時は非 0 で終了する(0件取得と取得失敗を区別)。 +set -uo pipefail + +if [[ $# -lt 2 ]] || [[ -z "${1:-}" ]] || [[ -z "${2:-}" ]]; then + echo "ERROR: 引数が不足しています。Usage: $0 " >&2 + exit 1 +fi + +REPO="$1" +PR="$2" + +FAIL_COUNT=0 + +# 1. インラインコメント (diff の特定行に紐づく) +# 本文全体を保持する。改行は \n エスケープして 1 行に収める。 +# gh api --jq は内部で jq -r 相当だが、環境差を吸収するため明示的に jq -r へパイプする。 +if ! gh api "repos/${REPO}/pulls/${PR}/comments" --paginate \ + | jq -r '.[] | "\(.path // "?"):\(.line // .original_line // "?") [\(.user.login)] \(.body // "" | gsub("\n"; "\\n") | gsub("```"; "` ` `"))"'; then + echo "WARNING: インラインコメントの取得に失敗しました (repos/${REPO}/pulls/${PR}/comments)" >&2 + (( FAIL_COUNT += 1 )) || true +fi + +# 2. レビュー body (CHANGES_REQUESTED / COMMENTED 等の総評) +# 本文全体を保持する。改行は \n エスケープして 1 行に収める。 +if ! gh api "repos/${REPO}/pulls/${PR}/reviews" --paginate \ + | jq -r '.[] | select(.body != null and .body != "") | "[REVIEW-BODY] [\(.user.login)] state=\(.state) \(.body | gsub("\n"; "\\n") | gsub("```"; "` ` `"))"'; then + echo "WARNING: レビュー body の取得に失敗しました (repos/${REPO}/pulls/${PR}/reviews)" >&2 + (( FAIL_COUNT += 1 )) || true +fi + +# 3. PR レベルコメント (Conversation タブの通常コメント) +# 本文全体を保持する。改行は \n エスケープして 1 行に収める。 +if ! gh api "repos/${REPO}/issues/${PR}/comments" --paginate \ + | jq -r '.[] | "[PR-COMMENT] [\(.user.login)] \(.body // "" | gsub("\n"; "\\n") | gsub("```"; "` ` `"))"'; then + echo "WARNING: PR レベルコメントの取得に失敗しました (repos/${REPO}/issues/${PR}/comments)" >&2 + (( FAIL_COUNT += 1 )) || true +fi + +# 全ソース失敗時のみ非 0 で終了(認証切れ等の検出) +if (( FAIL_COUNT >= 3 )); then + echo "ERROR: 全 3 ソースの取得に失敗しました" >&2 + exit 1 +fi diff --git a/plugins/ndf/skills-codex/git-gh-operations/01-common-errors.md b/plugins/ndf/skills-codex/git-gh-operations/01-common-errors.md new file mode 100644 index 00000000..a7afa445 --- /dev/null +++ b/plugins/ndf/skills-codex/git-gh-operations/01-common-errors.md @@ -0,0 +1,145 @@ +# Git / gh 共通エラー事例集 + +## 1. git add pathspec エラー + +### 事象 +``` +fatal: pathspec 'lambda-batch/CarImageProcessingPipeline/src/foo.py' did not match any files +``` + +### 原因 +CWD が `/work/repo/lambda-batch/CarImageProcessingPipeline/` なのに、 +リポジトリルートからの相対パスで `git add` した。 + +`git status` はリポジトリルートからの相対パスで表示するが、 +`git add` は CWD からの相対パスで解決する。 + +### 予防策 +```bash +# Step 1: CWD確認 +pwd +# => /work/repo/lambda-batch/CarImageProcessingPipeline/ + +# Step 2: git status の出力を確認 +git status +# modified: lambda-batch/CarImageProcessingPipeline/src/foo.py +# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +# これはリポジトリルートからの相対パス + +# Step 3: CWD からの相対パスに変換 +git add src/foo.py +# または +git add . # CWD以下のすべての変更 +``` + +## 2. gh api 404 エラー + +### 事象 +``` +gh api repos/owner/repo/pulls/comments/123/replies -f body='message' +# => 404 Not Found +``` + +### 原因 +POST メソッドが必要な API エンドポイントに GET でアクセスした。 +`gh api` はデフォルトで GET を使用する。 + +### 修正 +```bash +gh api -X POST repos/owner/repo/pulls/comments/123/replies -f body='message' +``` + +## 3. GitHub 自己 Approve エラー + +### 事象 +``` +Could not approve for pull request review. Can not approve your own pull request +``` + +### 原因 +GitHub はセキュリティ上、自分で作成した PR を APPROVE できない。 + +### 対策 +```bash +# pending review を削除してから COMMENT として再送信 +# method: "delete_pending" → method: "create" + event: "COMMENT" +``` + +## 4. AWS CLI [$LATEST] パースエラー + +### 事象 +``` +Unknown options: , , , +``` + +### 原因 +CloudWatch ログストリーム名に含まれる `[$LATEST]` が +`--query` JMESPath パーサーや shell の glob として解釈される。 + +### 対策 +```bash +# シングルクォートで囲んでも --query との組み合わせで問題が出る +# --output json + python パースが最も安全 +aws logs get-log-events \ + --log-group-name "/aws/lambda/func-name" \ + --log-stream-name '2026/02/18/[$LATEST]abc123' \ + --output json | python3 -c " +import sys, json +data = json.loads(sys.stdin.read()) +for e in data['events']: + print(e['message'].strip()) +" +``` + +## 5. git commit メッセージの特殊文字 + +### 事象 +コミットメッセージに日本語や改行が含まれるとエスケープ問題が発生。 + +### 対策 +常に HEREDOC 形式を使用: +```bash +git commit -m "$(cat <<'EOF' +日本語メッセージ + +詳細説明 + +Co-Authored-By: Claude Opus 4.6 +EOF +)" +``` + +注意: `<<'EOF'` (シングルクォート付き)で変数展開を抑制する。 + +## 6. gh pr checks が exit code 1 で止まる + +### 事象 +``` +gh pr checks 11765 2>&1 +# => チェック結果は表示されるが、1つでもfailがあると exit code 1 で終了 +# => Claude Code が「コマンド失敗」と判定して処理を中断 +``` + +### 原因 +`gh pr checks` は CI チェックに失敗があると非0の exit code を返す仕様。 +Claude Code の Bash ツールはコマンドの exit code が 0 以外だとエラーとして扱う。 + +### 対策 +常に `|| true` を付けて exit code を 0 にする: +```bash +# チェック一覧を取得(failがあっても止まらない) +gh pr checks 11765 2>&1 || true + +# --watch で完了待ちする場合も同様 +gh pr checks 11765 --watch 2>&1 || true + +# 失敗のみフィルタする場合 +gh pr checks 11765 2>&1 | grep -i fail || true +``` + +### 補足 +同様の問題が発生する gh コマンド: +- `gh run view RUN_ID --log-failed` (失敗ログ取得時) +- `gh pr diff` (差分が大きい場合にパイプ破損) + +いずれも `2>&1 || true` を付けることで安全に実行できる。 diff --git a/plugins/ndf/skills-codex/git-gh-operations/SKILL.md b/plugins/ndf/skills-codex/git-gh-operations/SKILL.md new file mode 100644 index 00000000..68b8a7a0 --- /dev/null +++ b/plugins/ndf/skills-codex/git-gh-operations/SKILL.md @@ -0,0 +1,228 @@ +--- +name: git-gh-operations +description: "Resolve git and GitHub CLI operation errors." +when_to_use: "git / gh コマンドでエラーが出た or 操作方法に迷うとき。Triggers: 'git add', 'git commit', 'git push', 'gh pr', 'gh api', 'GitHub操作', 'gitエラー', 'fatal:', 'pathspec'" +allowed-tools: + - Bash + - Read +--- + +# Git / gh 操作スキル + +## 最重要ルール: CWD とパスの整合性 + +git コマンドはすべて **CWD からの相対パス** で解決される。 +操作前に必ず `pwd` で CWD を確認すること。 + +### パターン1: CWDがサブディレクトリの場合 + +``` +# CWD: /work/repo/lambda-batch/MyProject/ +# リポジトリルート: /work/repo/ + +# NG: リポジトリルートからのパスを指定 +git add lambda-batch/MyProject/src/foo.py +# => fatal: pathspec did not match any files + +# OK: CWDからの相対パスを指定 +git add src/foo.py + +# OK: 絶対パスを指定 +git add /work/repo/lambda-batch/MyProject/src/foo.py +``` + +### パターン2: 安全な方法 + +```bash +# 方法A: git -C でリポジトリルートを指定 +git -C /work/repo add lambda-batch/MyProject/src/foo.py + +# 方法B: CWD を変更せずに絶対パスを使用 +git add "$(git rev-parse --show-toplevel)/lambda-batch/MyProject/src/foo.py" + +# 方法C(推奨): CWDからの相対パスを使用 +# まず pwd で確認してからパスを組み立てる +``` + +## git 操作チェックリスト + +### git add の前に + +1. `pwd` で CWD を確認 +2. `git status` で変更ファイルのパスを確認(表示されるパスはリポジトリルートからの相対パス) +3. `git status` の出力パスと CWD の関係を計算してから `git add` する + +### git commit の前に + +1. `git diff --cached` でステージング内容を確認 +2. HEREDOC形式でメッセージを渡す(改行・特殊文字の問題回避) + +```bash +git commit -m "$(cat <<'EOF' +コミットメッセージ + +Co-Authored-By: Claude Opus 4.6 +EOF +)" +``` + +## gh CLI / GitHub API の注意点 + +### パラメータ: `-f` vs `-F` + +```bash +# -f: 文字列パラメータ +gh api repos/OWNER/REPO/pulls/PR/comments -f body="テキスト" + +# -F: 非文字列パラメータ(数値、boolean、null、ファイル) +gh api repos/OWNER/REPO/pulls/PR/comments -F in_reply_to=2826074026 + +# 混在OK +gh api repos/OWNER/REPO/pulls/PR/comments -f body="返信テキスト" -F in_reply_to=2826074026 +``` + +### PRレビューコメントの取得 + +```bash +# コメント一覧を取得(id, path, body の先頭を表示) +gh api repos/OWNER/REPO/pulls/PR/comments \ + --jq '.[] | {id: .id, path: .path, body: (.body | split("\n")[0][:80])}' +``` + +### PRレビューコメントへの返信 + +```bash +# NG: /replies エンドポイントは存在しない(404になる) +gh api repos/OWNER/REPO/pulls/comments/{id}/replies -f body='...' +# => 404 Not Found + +# NG: -X POST を付けても同じ(エンドポイント自体が存在しない) +gh api -X POST repos/OWNER/REPO/pulls/comments/{id}/replies -f body='...' +# => 404 Not Found + +# OK: in_reply_to パラメータを使って新規コメントとして投稿 +gh api repos/OWNER/REPO/pulls/PR/comments \ + -f body="返信テキスト" \ + -F in_reply_to=COMMENT_ID +``` + +### レビュースレッドの Resolve(GraphQL) + +```bash +# 1. 未解決スレッドのID一覧を取得 +gh api graphql -f query=' +query { + repository(owner: "OWNER", name: "REPO") { + pullRequest(number: PR) { + reviewThreads(first: 50) { + nodes { + id + isResolved + comments(first: 1) { + nodes { path body } + } + } + } + } + } +}' --jq '.data.repository.pullRequest.reviewThreads.nodes[] | select(.isResolved == false) | {id, path: .comments.nodes[0].path}' + +# 2. スレッドを Resolve +gh api graphql -f query=' +mutation { + resolveReviewThread(input: {threadId: "PRRT_xxx"}) { + thread { isResolved } + } +}' +``` + +### PR の CI チェック結果 + +`gh pr checks` は1つでもfailがあると **exit code 1** で終了する。 +Claude Codeではコマンド失敗と判定されて処理が止まるため、必ず `|| true` を付ける。 + +```bash +# NG: failがあるとexit code 1で止まる +gh pr checks PR --repo OWNER/REPO + +# OK: exit codeを常に0にして出力を取得 +gh pr checks PR --repo OWNER/REPO 2>&1 || true + +# OK: 失敗のみフィルタ +gh pr checks PR --repo OWNER/REPO 2>&1 | grep -i fail || true +``` + +#### 重要: CIの完了を待ってはいけない + +- `--watch` や完了までのポーリングは **禁止**。現在のステータスを一度スナップショットするだけでよい。 +- チェックが `in_progress` / `queued` / `pending` の場合は **完了を待たず次のステップへ進む**。 +- 対応対象は **コード修正で直せるfailのみ**。以下のような「ステータス確認系」チェックは無視する: + - `check_pr_requirements` 等、PR要件・メタ情報のみ検証するもの + - Lint/テストに非依存なラベル/タイトル/説明チェック + - 外部サービス起因で自己修復するトランジェントなfail(再実行で直るもの) +- 対応する: ビルド失敗・テスト失敗・型エラー・lint違反など、**リポジトリ内コードの修正で解消可能なもの**。 + +```bash +# 失敗ジョブのログ(エラー行のみ抽出) +gh run view RUN_ID --repo OWNER/REPO --log-failed 2>&1 \ + | grep -E '(FAIL|Error|Tests:)' | head -20 || true +``` + +### 自分のPRは Approve できない + +``` +# GitHub の制約: 自分で作成した PR に APPROVE レビューは不可 +# => "Can not approve your own pull request" +# 対策: event を "COMMENT" に変更して送信 +``` + +### PR作成時の body は HEREDOC + +```bash +# NG: \n がリテラルで混入する可能性 +gh pr create --title "タイトル" --body "行1\n行2" + +# OK: HEREDOC形式 +gh pr create --title "タイトル" --body "$(cat <<'EOF' +## Summary +- 変更内容 + +## Test plan +- [ ] テスト項目 +EOF +)" +``` + +## AWS CLI の注意点 + +### CloudWatch ログストリーム名の [$LATEST] + +```bash +# NG: --query で [$LATEST] を含む文字列がパースエラー +aws logs get-log-events --query 'events[*].message' --output text + +# OK: --output json にして python でパース +aws logs get-log-events --output json | python3 -c " +import sys,json +data = json.loads(sys.stdin.read()) +for e in data['events']: + print(e['message'].strip()) +" +``` + +## エラー事例集 + +| エラーメッセージ | 原因 | 対策 | +|----------------|------|------| +| `fatal: pathspec '...' did not match any files` | CWD とパスの不一致 | `pwd` 確認後、CWD相対パスで指定 | +| `404 Not Found` (gh api replies) | `/comments/{id}/replies` は存在しない | `in_reply_to` パラメータで投稿 | +| `422 Unprocessable` (gh api) | `-f` で数値を渡した | 数値は `-F` を使う | +| `Can not approve your own pull request` | 自己 Approve 不可 | `COMMENT` イベントに変更 | +| `gh pr checks` が exit code 1 | 1つでもfailがあると非0終了 | `gh pr checks ... 2>&1 \|\| true` | +| `Unknown options: , , ,` (aws cli) | `[$LATEST]` のシェルエスケープ | `--output json` + python パース | + +## 詳細ガイド + +| ファイル | 内容 | 参照タイミング | +|---------|------|--------------| +| `01-common-errors.md` | 詳細なエラー事例と再現手順 | エラー発生時 | diff --git a/plugins/ndf/skills-codex/implementation-plan/SKILL.md b/plugins/ndf/skills-codex/implementation-plan/SKILL.md new file mode 100644 index 00000000..0e0a1307 --- /dev/null +++ b/plugins/ndf/skills-codex/implementation-plan/SKILL.md @@ -0,0 +1,98 @@ +--- +name: implementation-plan +description: "Create or update implementation plan files." +when_to_use: "実装開始時 / PR作成時に実装プランの作成・更新が必要なとき。複数ファイル変更・新機能追加・DBマイグレーションを含む変更で自動参照。Triggers: '実装プラン', '実装を開始', 'PR作成', 'implementation plan', 'plan first', '設計書を作成', 'issues/に追加'" +--- + +# 実装プランガイド + +## 基本方針 + +実装の開始時およびPR作成時に、`issues/` 配下に実装プランファイルが存在するか確認し、なければ作成する。プランを残すことで後任エンジニアや将来の自分が変更意図を追跡できる。 + +## 実装プランが必要なケース + +以下のいずれかに該当する場合は作成する: + +- 複数ファイルにまたがる変更 +- 新規機能の追加 +- 既存ロジックの大幅な変更 +- DBマイグレーションを伴う変更 +- 複数のタスクに分解できる作業 + +## 実装プランが不要なケース + +以下のような軽微な変更では不要: + +- typo修正、文言変更 +- 設定値の変更のみ +- 1ファイルで完結する軽微な修正 +- フォーマッター適用のみ +- ドキュメントのみの更新 + +判断に迷う場合はユーザーに確認する。 + +## ファイル配置・命名 + +- パス: `issues/` +- ファイル名に日本語は含めないこと(Git/CI/検索ツール互換性のため) +- タスクIDがある場合: `issues/TASK-1234_concise-description.md` +- タスクIDがない場合: `issues/{feature-name}.md` + +## PR作成時のプランファイル生成 + +PR作成時に `issues/` にプランファイルが存在しない場合、以下の情報源からプランファイルを生成する: + +1. **会話履歴** - それまでのやりとりから要件・背景・方針を抽出 +2. **git log** - コミット履歴からタスクの流れと変更概要を把握 +3. **git diff** - 実際の変更内容から修正対象ファイルと変更内容を特定 + +これらを組み合わせて、下記フォーマットに沿ったプランファイルを作成してからPRを作成する。 + +## プランのフォーマット + +```markdown +# {タスクID}: {機能名/修正内容} + +## 関連リンク +(Issue/チケット/設計ドキュメントがあれば記載) + +## 概要 +- 何を実装・修正するのか + +## 問題・背景 +- なぜこの変更が必要なのか(該当する場合) + +## 修正対象 +- 変更対象のファイルパス一覧 + +## タスク分解 + +### Task 1: {タスク名} +- **対象ファイル:** 変更対象のファイルパス +- **変更内容:** 具体的な変更内容 + +### Task 2: {タスク名} +- **対象ファイル:** 変更対象のファイルパス +- **変更内容:** 具体的な変更内容 + +## 影響範囲 +- 変更による影響を受ける機能やファイル + +## テスト計画 +- [ ] {実装した機能が正しく動作することの確認} +- [ ] {既存機能にリグレッションがないことの確認} +``` + +## ワークフロー + +1. 実装の依頼を受けたら、まずプランが必要か判断する +2. 必要な場合は `issues/` にプランファイルを作成してから実装を開始する +3. PR作成時にプランファイルが存在しない場合、必要であれば会話履歴・git log・git diffからプランファイルを生成してからPRを作成する + +## プランと PR Body の関係 + +- プランファイル = 「なぜ」「どう分解するか」を残す永続的な記録 +- PR body = 「何をやったか」「どうテストするか」のレビュー用サマリ + +同じ内容をコピーせず、PR bodyでは「詳細は `issues/xxx.md` 参照」と誘導してもよい。 diff --git a/plugins/ndf/skills-codex/investigation-rules/SKILL.md b/plugins/ndf/skills-codex/investigation-rules/SKILL.md new file mode 100644 index 00000000..a4757a83 --- /dev/null +++ b/plugins/ndf/skills-codex/investigation-rules/SKILL.md @@ -0,0 +1,105 @@ +--- +name: investigation-rules +description: "Write evidence-backed investigation and debug reports." +when_to_use: "調査・デバッグ・不具合レポートを作成するとき。「ない」「該当なし」等の否定的結論を出すときは必ず参照。Triggers: '調査', 'デバッグ', '不具合レポート', '原因調査', 'investigation', 'root cause', 'カラムがない', '該当コードがない', 'データがない'" +--- + +# 調査レポート作成ルール + +不具合調査・データ調査・仕様調査でレポートを作成する際のルール。コード読解だけに頼らず、必ず実行結果・出力・実データで裏取りする。 + +## 否定的結論にはエビデンス必須 + +「カラムがない」「データがない」「関数が呼ばれていない」「該当コードがない」等の **否定的な結論** を書く場合、**必ず実行結果をエビデンスとして添付すること**。 + +### なぜこのルールが必要か + +AIは「もっともらしいが間違った推論」をしがちで、コード読解だけで「ない」と断定して誤判断を招きやすい。事例として、外部テーブルの一部カラムだけを見て「該当カラムなし」と結論づけたが、実際には別名のカラムにデータが存在していた、という判断ミスが典型。 + +### 具体的な裏取り方法 + +| 主張の種類 | 必須エビデンス | +|-----------|--------------| +| DB: カラムが存在しない | `SHOW COLUMNS FROM table_name` / `DESCRIBE` の結果 | +| DB: データが存在しない | `SELECT COUNT(*) FROM table WHERE ...` の結果 | +| DB: テーブルが存在しない | `SHOW TABLES LIKE '%keyword%'` の結果 | +| コード: 関数/シンボルが存在しない | `grep -rn 'name' .` / LSP検索 / Serena `find_symbol` の結果 | +| コード: 呼び出し箇所がない | `find_referencing_symbols` / `grep` の結果 | +| 設定: 値が存在しない | 設定ファイルのdiff / `env` / `config` コマンド出力 | +| ログ: エラーが出ていない | `grep` / 検索ツールのクエリと結果期間 | + +### レポートへの記載例 + +```markdown +### 残課題 + +| 課題 | 概要 | エビデンス | 優先度 | +|------|------|-----------|--------| +| 外部API の retry 未実装 | Xクライアントで retry ハンドリングが無い | `grep -rn "retry\|Retry" src/client/x/` → 0件 | 中 | +| status=deleted の件数 | 論理削除レコードが残存 | `SELECT COUNT(*) FROM ... WHERE status='deleted'` → 2,341件 | 低 | +``` + +### やってはいけないこと + +- コードを読んだだけで「このカラムは存在しない」と断定する +- 1つのテーブル/ファイルだけ見て「データに問題はない」と結論づける +- 外部テーブルの一部のカラムだけ見て「他にはない」と判断する(全カラムを確認する) +- エビデンスなしで残課題の優先度を「低」にする(誤判断の典型) + +## 外部データ調査の原則 + +外部API/外部テーブル/サードパーティデータソースを調査する際は、**全体構造を必ず確認する**。 + +```sql +-- まず全体像を把握する +SHOW COLUMNS FROM external_source_table; + +-- 次に対象カラムのデータ分布を確認する +SELECT column_name, COUNT(*) FROM table GROUP BY column_name; +``` + +外部データは外部システム由来でカラム名・値域が予測しづらいため、コードから逆引きするだけでは見落とす。 + +## ハルシネーション防止チェックリスト + +推論で埋めず、必ず以下を実行して裏取りする: + +| チェック項目 | 方法 | +|------------|------| +| カラム/フィールドが存在するか | `SHOW COLUMNS` / スキーマ定義ファイルを開く | +| データが存在するか | `SELECT COUNT(*) WHERE ...` / サンプルレコード取得 | +| 型が一致するか | DB定義とアプリコード両方を確認(Eloquent `$casts`、dataclass型等) | +| FK/制約が存在するか | マイグレーション履歴を追跡(追加→削除→再追加の変遷を確認) | +| 論理削除ポリシーは何か | `SoftDeletes` / `deleted_at` の有無を確認 | +| 環境差異がないか | dev/staging/prod で同じクエリを実行して比較 | + +## 調査結果の書き方テンプレート + +```markdown +## 症状 +何がどう間違っているか(定量的に、エビデンス付きで) + +## 調査経緯 +1. 仮説1: xxx → クエリ/コマンドで確認 → 否定/肯定 +2. 仮説2: yyy → ... + +## 根本原因 +コードレベルでどこが問題か(ファイル名:行番号で特定) + +## エビデンス +``` +SQL/コマンド実行結果をそのまま貼る +``` + +## 修正方針 +どのフェーズで何を直すか(多層防御の観点) + +## 検証手順 +修正後にどう確認するか(回帰テスト含む) +``` + +SQLクエリ結果・コマンド出力をそのまま貼り、「コードを読んだ推測」と「実行して確認した事実」を明確に区別する。 + +## 関連スキル + +- `/ndf:problem-solving` — 根本原因分析と多層防御の原則 diff --git a/plugins/ndf/skills-codex/issue-plan-strategy/SKILL.md b/plugins/ndf/skills-codex/issue-plan-strategy/SKILL.md new file mode 100644 index 00000000..4275a379 --- /dev/null +++ b/plugins/ndf/skills-codex/issue-plan-strategy/SKILL.md @@ -0,0 +1,335 @@ +--- +name: issue-plan-strategy +description: "Turn issues into plans and implementation workflows." +when_to_use: "issue → plan 作成 / 既存 plan の実装 (実行) を依頼されたとき。複数 PR に分割される設計や、release branch + 個別 PR + worktree 運用が必要なときに参照する。Triggers: 'issueのplanを作って', 'PLANxxの設計', '設計書を起こして', 'このplanを実装して', 'PLANxxを実装', 'planを実行', 'release branch 作って実装開始', 'multi-PR で進めて'" +argument-hint: "[issue-path-or-url] (例: issues/i16.md, https://github.com/org/repo/issues/123)" +allowed-tools: + - Bash + - Read + - Write + - Edit + - Glob + - Grep +--- + +# issue → plan → multi-PR ワークフロー + +1 つの issue から plan を作る際、推奨される PR が複数に分かれることは日常的に発生する。本 skill はその際の **release ブランチ + 個別 PR ブランチ + Draft PR 先行作成 + git worktree 並行開発 + レビュー運用** の標準フローを規定する。 + +本 skill は **plan の作成フェーズと plan の実行(実装)フェーズの両方** をカバーする。同じワークフローが「設計を起こす段階」と「設計に従って実装する段階」を貫通することで、作成者と実装者(あるいは将来の自分)が同じ手順を共有できる。 + +## 発動条件 + +| トリガ | 例 | 入る Step | +|---|---|---| +| スラッシュコマンド (引数あり) | `/ndf:issue-plan-strategy issues/foo.md`、`/ndf:issue-plan-strategy https://github.com/org/repo/issues/123` | Step 0 から | +| スラッシュコマンド (引数なし) | `/ndf:issue-plan-strategy` (現在ブランチで作業中の issue/plan を解析) | Step 0 から | +| 自動発動 (作成系) | 「この issue の plan を作って」「設計書を起こして」「PLAN42 の設計を起こして」 | Step 1〜2 | +| 自動発動 (実行系) | 「この plan を実装して」「PLAN42 を実行して」「multi-PR で進めて」「release branch を切って実装開始」 | Step 0 → 既存 plan を読み → Step 3 以降 | + +引数で渡された issue / plan は **ファイルパス / URL / 番号** いずれでも受け付ける: + +- ファイルパス (`issues/PLANxx_*.md`): 直接 Read +- GitHub Issue URL / `#番号`: `gh issue view --json title,body,labels` で取得 +- それ以外の文字列: そのまま issue 本文として扱う + +## Step 0: 作成フェーズか実行フェーズか判定 + +最初に **既に plan ファイルが存在するか** で判定する。skill 内で `Glob` を使うのが第一選択 (例: `Glob('issues/*PLAN42*')`)。shell で確認する場合は: + +```bash +# issues/ 配下に該当 plan があるか (PLAN42 / feature-name 部分は実値に置換) +find issues/ -maxdepth 1 -iname '*PLAN42*' -o -iname '*feature-name*' +``` + +| 状況 | 進むフェーズ | +|---|---| +| plan ファイルがない / issue しかない | **作成フェーズ** (Step 1〜2 へ) | +| plan ファイルがあり、release branch がない | **実行フェーズ・初期化** (Step 3 へ) | +| release branch も Draft PR も既にある | **実行フェーズ・継続** (Step 5 以降。worktree / 並行開発 / レビュー / merge を進める) | + +実行フェーズで入った場合、既存 plan の **「PR 分割計画」セクション**を必ず Read してから Step 3 以降の自動化判断に使う。 + +## 全体フロー + +``` + ┌─ 作成フェーズ ──────────────────────────────────────┐ +issue 取得 ─┤ │ + │ plan 作成 (必要なら plan モード) ─ 単一PR? ─ YES ─▶ implementation-plan + /ndf:pr で完了 + │ │ + │ NO + └──────────────────────────────────────────┼──────────┘ + ▼ + ┌─ 実行フェーズ ──────────────────────────────────────┐ +既存 plan ─▶│ Step 3: release branch 作成 + Draft release PR │ + │ Step 4: 個別 PR ブランチ作成 + 各 Draft PR (release base) + │ Step 5: git worktree で並行開発 (依存関係を考慮) │ + │ Step 6: 個別 PR ごとに /ndf:review or /ndf:cross-review + │ → /ndf:fix → merge into release │ + │ Step 7: release ブランチで結合テスト相当のレビュー │ + │ Step 8: release PR body 最終化 → Ready & merge │ + └─────────────────────────────────────────────────────┘ +``` + +QA / staging 等の検証環境向けには、個別 PR or release PR 単位で `/ndf:cherry-pick-pr` を別途実行する (Step 9)。 + +実行フェーズに途中から入った場合は、対応する Step の途中再開で構わない。各 Step の冒頭で **既に存在するブランチ / PR / worktree を `git branch -a` / `gh pr list` / `git worktree list` で確認**してから作業に入る。 + +## Step 1: issue 取得と plan 作成 (作成フェーズ専用) + +> 実行フェーズで入った場合はこの Step をスキップし、既存 plan を Read して Step 3 へ進む。 + +1. 引数を解釈して issue 本文を取得する +2. `issues/` 配下に plan ファイルが既に存在するか `Glob` で確認する +3. なければ `/ndf:implementation-plan` の **プランフォーマット**に従って plan ファイルを作成する + - ファイル名は英数 (例: `issues/PLAN42_multi-pr-refactor.md`) + - 内容に「複数 PR に分割する根拠」「PR 単位と依存関係」を必ず含める +4. 設計判断が重い場合は **Claude Code の plan モード** (ExitPlanMode を用いる読み取り専用フェーズ) に切り替えて十分検討してから実装へ進む + +plan の構造は `/ndf:implementation-plan` を参照。本 skill では multi-PR を前提に **以下のセクションを追加**する: + +```markdown +## PR 分割計画 + +| PR # | branch 名 | 概要 | 依存 | 並行可否 | +|---|---|---|---|---| +| 1 | feature/PLAN42-schema | スキーマ追加 | なし | ○ | +| 2 | feature/PLAN42-api | API 実装 | PR1 | × (PR1 merge 後) | +| 3 | feature/PLAN42-ui | UI 実装 | PR1 | ○ (mock で開始可) | + +release branch: `release/PLAN42` +base branch: `main` +``` + +## Step 2: 単一 PR で足りるか判定 + +plan を書いた結果が以下のいずれかなら **release ブランチを作らず**、`/ndf:implementation-plan` + `/ndf:pr` の通常フローに切り替える: + +- 変更ファイルが 1〜2 個で結合度が低い +- 1 PR で安全に review 可能 (差分 ~500 行以内が目安) +- 依存関係のある複数タスクが存在しない + +複数 PR が妥当な場合 (スキーマ + API + UI、機能追加 + マイグレーション、複数モジュール横断 等) のみ Step 3 に進む。 + +## Step 3: release ブランチ + Draft PR 先行作成 (実行フェーズの開始点) + +> 実行フェーズで自動発動した場合の最初の自動化対象。既に `release/` ブランチや Draft PR が存在する場合は作成をスキップし、Step 4 へ進む。 + +### release ブランチ作成 + +```bash +git fetch origin +git checkout -b release/ origin/ +git push -u origin release/ +``` + +### レビュアー視点の原則 (release PR body の大前提) + +個別 PR はセルフレビュー (`/ndf:cross-review` 等) で merge される。**人間のレビュアーが見るのは release PR だけ**であり、個別 PR の存在をレビュアーに意識させてはならない。したがって: + +- release PR の body は **self-contained 必須**: 「何のために」(背景・解決したい課題) と「何を」(release ブランチ全体としての変更内容) を、**個別 PR を一切参照せずに**理解できる粒度で書く +- 個別 PR リンクの列挙を body の本文にしない。開発中の進捗管理に使う場合は `
` 折りたたみ内の補足情報に格下げする +- `/ndf:cross-review` の light rotation と同じ原則を適用する: 現状の差分・実装を反映し、内部用語 (PLAN-ID 運用、round、rotated 等) をレビュアー向け本文に漏らさない + +### release → default の Draft PR を先行作成 + +```bash +gh pr create \ + --base \ + --head release/ \ + --draft \ + --title "release: <概要>" \ + --body "$(cat <<'EOF' +## Summary +- (背景) なぜこの変更が必要か / 解決したい課題 +- (変更内容) release ブランチ全体として何をするか +- plan: issues/_xxx.md + +## Test plan (結合観点のみ) +- [ ] 個別 PR では検出できない結合テスト項目 + +
+開発用: 個別 PR 進捗 (レビュー対象外) + +- [ ] # PR1: ... +- [ ] # PR2: ... +- [ ] # PR3: ... + +
+ + +EOF +)" +``` + +Draft 作成時点では実装が進んでいないため body は plan ベースの暫定でよいが、Ready for review 前に **実装の最終形を反映した body へ最終化**する (Step 8 参照)。 + +release PR を **先に作る理由**: PR 番号が確定し、個別 PR の説明から参照できるため。 + +## Step 4: 個別 PR ブランチ + Draft PR 先行作成 + +> 既存ブランチは `git branch -a | grep "feature/-"` で確認し、未作成のものだけ作る。Draft PR の存在は `gh pr list --base release/ --state all` で確認。 + +各 PR について **同じパターンで先に Draft PR まで作る**: + +```bash +# release ブランチを base に個別ブランチを切る +git fetch origin release/ +git checkout -b feature/- origin/release/ + +# 空コミットで push して Draft PR を作る (base=release と HEAD が同一だと +# gh pr create が "No commits between ..." で失敗するため、差分ゼロのまま PR +# 作成のトリガにする目的で `--allow-empty` を使う) +git commit --allow-empty -m "chore: - Draft PR 作成" +git push -u origin feature/- + +gh pr create \ + --base release/ \ + --head feature/- \ + --draft \ + --title "feat: - <概要>" \ + --body "$(cat <<'EOF' +## Summary +- plan: issues/_xxx.md +- release PR: # +- 担当範囲: + +## Test plan +- [ ] ... + + +EOF +)" +``` + +完了後 release PR の本文を `gh pr edit` で更新し、`
` 内の開発用チェックリストに個別 PR 番号を埋める (body 本文には書かない)。 + +## Step 5: git worktree で並行開発 + +並行可能 (依存なし or mock で先行可) な PR は **git worktree** で同時に開く: + +```bash +# repo ルート (default branch のまま) で +git worktree add ../--schema feature/-schema +git worktree add ../--ui feature/-ui + +# それぞれの worktree で別ターミナル / 別エージェントを起動 +``` + +ガイドライン: + +- **依存のある PR は順次着手**する (PR1 merge → PR2 開始) +- 並行 PR 間で同じファイルを触る場合は事前にレビュー観点で分担を明確化する +- 終わった worktree は `git worktree remove ` で片付ける +- Claude Code から並行開発を指示する場合、Agent tool の `isolation: "worktree"` も検討する + +## Step 6: 個別 PR のレビュー + +**レビューは原則個別 PR 単位**で行う: + +| 用途 | コマンド | +|---|---| +| PR 作成前のセルフレビュー | `/ndf:review-branch` | +| GitHub 上の単体レビュー | `/ndf:review ` | +| codex + gemini 両方の収束ループ | `/ndf:cross-review ` | +| 指摘の修正 | `/ndf:fix ` | + +個別 PR が APPROVE → Draft 解除 → release ブランチへ merge (squash 推奨)。 + +## Step 7: release ブランチのレビュー (結合テスト相当のみ) + +release ブランチへの merge が一通り進んだ段階で: + +- **個別 PR で見た観点を再レビューしない** +- **結合テスト相当**の観点のみレビューする: + - PR 間の API / 型 / スキーマ整合 + - 設定値の重複・矛盾 + - migration の順序依存 + - E2E シナリオ (`/ndf:playwright-scenario-test` の活用) +- ここで個別 PR 範囲のバグが見つかった場合は、**release PR にコメントせず**、該当の個別 PR (既に merge 済みなら新しい修正 PR を release 配下に作成) 側に指摘を書き込み、修正ループを回す +- release PR には integration 観点の指摘のみ残す + +## Step 8: release PR body の最終化と release → default の merge + +### body の最終化 (Ready for review の前に必須) + +個別 PR が全て merge されたら、**Draft 解除の前に** release PR の body を実装の最終形を反映した self-contained な内容へ更新する: + +```bash +# release ブランチ全体の差分を確認して body を書き直す +git fetch origin +git diff origin/...origin/release/ --stat +gh pr edit --title "..." --body "..." +``` + +最終化のチェック観点 (Step 3 のレビュアー視点の原則を満たすこと): + +- [ ] 「何のために」「何を」が個別 PR や plan ファイルを辿らずに理解できる +- [ ] 実装中の方針変更・スコープ増減が body に反映されている +- [ ] 個別 PR への参照が本文に残っていない (`
` 内の開発用情報は残してよい) +- [ ] 内部用語 (round、rotated 等) が漏れていない + +### Draft 解除と merge + +release PR が APPROVE されたら: + +```bash +# Draft 解除 +gh pr ready +# merge: 個別 PR が既に squash 済みで release ブランチに並んでいるため、 +# main 側でも個別 PR 単位の commit を追跡できる `--merge` (merge commit 保持) +# が既定として推奨。プロジェクト規約で線形履歴必須なら `--rebase`、 +# それ以外で commit 数を 1 本にしたい場合のみ `--squash`。 +gh pr merge --merge --delete-branch +``` + +merge 後は plan ファイル末尾に「完了サマリ」(マージ済み PR 番号 / 検証結果) を追記してクローズ化する。 + +## Step 9: 検証環境 (qa/staging 等) への適用 + +QA / staging 検証は **個別 PR 単位** or **release ブランチ単位** のどちらでも OK。 +`/ndf:cherry-pick-pr` は Claude Code 内の slash command なので、shell ではなく +Claude Code セッション上で実行する点に注意。 + +個別 PR 単位で qa に反映する場合: + +```text +# (Claude Code 内で実行する slash command) +/ndf:cherry-pick-pr qa/staging +``` + +release ブランチごと qa に反映する場合 (まとまった検証が必要な場合): + +```bash +# 1. shell で release ブランチに切り替え +git checkout release/ +``` + +```text +# 2. (Claude Code 内で実行する slash command) +/ndf:cherry-pick-pr qa/staging +``` + +詳細は `/ndf:cherry-pick-pr` と `/ndf:branch-fix-strategy` を参照。`feature → main` 系 PR を汚染しないため、検証ブランチ向けは必ず短命ブランチ経由で扱う。 + +## アンチパターン + +| ❌ やってはいけないこと | 理由 | +|---|---| +| release ブランチを作らず巨大な 1 PR で出す | レビュー困難・revert 困難・並行開発不可 | +| 個別 PR の base を default にする | release で統合する意味が失われ、partial merge が default を汚染する | +| 個別 PR Draft 作成を実装後に回す | PR 番号が未確定でクロス参照や CI 待機の段取りが組めない | +| release PR で個別 PR 範囲の指摘を解決しようとする | 該当 PR が既に閉じている場合、コミット意図がずれる | +| release PR の body を個別 PR リンクの列挙だけにする | レビュアーは release PR 単体で変更を把握できず、個別 PR や plan を辿ることになる。body は self-contained 必須 (Step 3 / Step 8) | +| body 最終化せずに Ready for review にする | Draft 作成時の plan ベースの暫定 body のままだと実装の最終形と乖離する | +| 検証ブランチを feature/release に merge する | `feature → main` PR への汚染 (詳細: `/ndf:branch-fix-strategy`) | + +## 関連 skill + +- `/ndf:implementation-plan` — plan ファイルのフォーマット (本 skill が依存) +- `/ndf:branch-fix-strategy` — ブランチ汚染を避ける原則 +- `/ndf:pr` — 通常の PR 作成 / 更新 +- `/ndf:cherry-pick-pr` — 検証ブランチへの cherry-pick PR +- `/ndf:review` / `/ndf:review-branch` / `/ndf:cross-review` — レビュー +- `/ndf:fix` / `/ndf:resolve-pr-comments` — コメント対応 +- `/ndf:playwright-scenario-test` — release ブランチでの E2E 結合テスト diff --git a/plugins/ndf/skills-codex/logging-guidelines/SKILL.md b/plugins/ndf/skills-codex/logging-guidelines/SKILL.md new file mode 100644 index 00000000..007b9691 --- /dev/null +++ b/plugins/ndf/skills-codex/logging-guidelines/SKILL.md @@ -0,0 +1,112 @@ +--- +name: logging-guidelines +description: "Design safe and useful application logging." +when_to_use: "コードにログを追加・修正・整理するとき。Triggers: 'ログ追加', 'log追加', 'logger', 'logging', 'ログレベル', 'log level', 'デバッグログ', 'エラーログ', 'logger.info', 'logger.error', 'print文をログに'" +--- + +# ログ運用ガイドライン + +コードにログを追加・修正する際は、以下のルールに従うこと。言語/フレームワークに依存しない原則として記述している。 + +## ログレベルの選択基準 + +| レベル | 用途 | 本番出力(推奨) | +|--------|------|---------------| +| `error` | 例外発生、処理失敗 | o | +| `warning` | データ不備でスキップ、処理継続可能な異常 | o | +| `info` | バッチ開始/完了、重要なビジネスイベント | 環境による(本番off推奨) | +| `debug` | 開発向けデバッグ情報 | x | + +**推奨**: 本番は `LOG_LEVEL=warning` 以上。info/debug は開発・ステージングのみで出力する。 + +## 使用を避けるログレベル + +以下は用途が曖昧または過剰なため、明示的な運用規則がない限り使わない: + +- `notice` — error/warning/info と区別が曖昧 +- `critical`, `alert`, `emergency` — 通常のアプリには過剰。運用規則として「PagerDuty起動基準」などが定義されていない限り使わない + +## ループ内ログのルール + +### 原則: ループ内では info/warning を出力しない + +ループ内で1件ずつログを出力すると、大量データ処理時にログが爆発する。ループ後にサマリーとしてまとめて出力すること。 + +### サマリーログ化パターン(擬似コード) + +``` +# NG: ループ内で1件ずつ出力 +for item in items: + log.info("処理完了", id=item.id) + +# OK: ループ後にまとめて出力 +processed_count = 0 +for item in items: + # 処理... + processed_count += 1 +log.info("バッチ処理完了", processed_count=processed_count) +``` + +### エラー蓄積パターン + +ループ内で例外が発生し処理を継続する場合は、エラー情報を蓄積してループ後にまとめて報告する。先頭N件のみ含めることで、ログサイズ爆発を防ぐ。 + +``` +errors = [] +for item in items: + try: + process(item) + except Exception as e: + errors.append({"id": item.id, "error": str(e)}) + +if errors: + log.error( + "処理で一部失敗", + total_count=len(items), + failed_count=len(errors), + sample_errors=errors[:10], # 先頭10件のみ + ) +``` + +### ループ内 debug も必要最小限 + +ループ内での debug 出力は、他に代替手段がなく調査に不可欠な場合のみ許容。デフォルトは「ループ外で件数サマリ」を基本とする。 + +## 例外処理のルール + +1. **例外は最上位でログ出力** — エントリポイント(コマンド/コントローラー/ジョブ)で catch してログ出力 +2. **再スロー時はログ不要** — 上位で出力されるため二重出力を避ける +3. **例外を握りつぶさない** — catch後に何も報告せず続行するのは禁止 +4. **広めの例外型で捕捉** — 言語の最上位例外型(Python `Exception`、PHP `Throwable`、Java `Throwable` 等)でトップレベル catch する + +## 必須ルール + +1. **コンテキスト情報を含める** — 調査に必要なID等を構造化ログとして渡す +2. **機密情報を含めない** — パスワード、トークン、クレジットカード番号、個人特定情報は禁止 +3. **メッセージは明確に** — 何が起きたか分かる言葉で記述(プロジェクトの言語ポリシーに従う) +4. **ロガー呼び出しを統一** — プロジェクトで統一ファサード/クライアントを使う(例: Laravel は `Log::`, Python は `logging.getLogger(__name__)`) +5. **グローバル/暗黙の名前空間を使わない** — 明示的にimport/useする + +## ログとメトリクスの使い分け + +- **ログ**: 個別のイベント、エラー、コンテキスト情報(構造化ログ) +- **メトリクス**: 件数、レイテンシ、成功/失敗率の集計(Prometheus/DataDog等) +- **トレース**: リクエスト横断の実行フロー(OpenTelemetry等) + +ループ件数カウントなどは、ログではなくメトリクスに寄せるのが望ましい場合が多い。 + +## アンチパターン一覧 + +| アンチパターン | 問題 | +|--------------|------| +| `log.info("")` / 空メッセージ | 意図が伝わらない | +| `log.error(e)` のみ | スタックトレース/contextが欠ける | +| 機密情報をそのままログに入れる | 情報漏洩リスク | +| ループ内で毎回 info 出力 | ログ爆発 | +| try/except で握りつぶし、何も報告しない | 障害の気配を消す | +| 複数行の ASCII ART をログに含める | grep/集計が困難 | + +## 関連スキル + +- `/ndf:problem-solving` — ログから根本原因を特定する手順 +- `/ndf:investigation-rules` — ログをエビデンスとして扱う際の注意点 diff --git a/plugins/ndf/skills-codex/markdown-writing/01-diagram-guide.md b/plugins/ndf/skills-codex/markdown-writing/01-diagram-guide.md new file mode 100644 index 00000000..db40f52b --- /dev/null +++ b/plugins/ndf/skills-codex/markdown-writing/01-diagram-guide.md @@ -0,0 +1,144 @@ +# 図表作成ガイド + +## mermaid 記法 + +### フローチャート + +```mermaid +graph TD + A[開始] --> B{条件判定} + B -->|Yes| C[処理A] + B -->|No| D[処理B] + C --> E[終了] + D --> E +``` + +### シーケンス図 + +```mermaid +sequenceDiagram + User->>API: リクエスト + API->>DB: クエリ + DB-->>API: 結果 + API-->>User: レスポンス +``` + +### クラス図 + +```mermaid +classDiagram + class User { + +int id + +string name + +login() + +logout() + } + class Order { + +int id + +float total + } + User "1" --> "*" Order +``` + +### ER図 + +```mermaid +erDiagram + USER ||--o{ ORDER : places + ORDER ||--|{ LINE_ITEM : contains + PRODUCT ||--o{ LINE_ITEM : "ordered in" +``` + +## plantUML 記法 + +### コンポーネント図 + +```plantuml +@startuml +package "Frontend" { + [React App] +} +package "Backend" { + [API Server] + [Database] +} +[React App] --> [API Server] +[API Server] --> [Database] +@enduml +``` + +### アクティビティ図 + +```plantuml +@startuml +start +:ユーザー入力; +if (有効?) then (yes) + :処理実行; +else (no) + :エラー表示; +endif +stop +@enduml +``` + +## ASCII 許可例(ツリーのみ) + +ディレクトリ構造はASCIIで表現可能: + +``` +project/ +├── src/ +│ ├── components/ +│ └── utils/ +├── tests/ +└── docs/ +``` + +## よくある間違い + +### 避けるべき: ASCII ARTで図を描く + +``` + ┌─────────┐ + │ User │ + └────┬────┘ + │ + ┌────▼────┐ + │ API │ + └─────────┘ +``` + +上記のような図は **mermaid** で描いてください: + +```mermaid +graph TD + User --> API +``` + +### 避けるべき: 順序prefixなしで分割 + +``` +docs/ +├── introduction.md ← NG: prefixがない +├── setup.md +└── usage.md +``` + +正しい方法: + +``` +docs/ +├── 01-introduction.md ← OK +├── 02-setup.md +└── 03-usage.md +``` + +## ベストプラクティス + +| DO | DON'T | +|----|-------| +| mermaid/plantUMLで図を描く | ASCII ARTで図を描く | +| 300行以内に収める | 1000行超の巨大ファイル | +| 順序prefixで分割 | prefixなしで分割 | +| 2桁パディング(01-, 02-) | 1桁(1-, 2-) | diff --git a/plugins/ndf/skills-codex/markdown-writing/SKILL.md b/plugins/ndf/skills-codex/markdown-writing/SKILL.md new file mode 100644 index 00000000..56b35839 --- /dev/null +++ b/plugins/ndf/skills-codex/markdown-writing/SKILL.md @@ -0,0 +1,58 @@ +--- +name: markdown-writing +description: "Write Markdown docs, diagrams, and split files." +when_to_use: "Markdown 文書 / 図表を作成 / 編集するとき。Triggers: 'Markdown作成', 'ドキュメント作成', '文書作成', '図を描く', 'mermaid', 'create document', 'write docs'" +allowed-tools: + - Read + - Write + - Edit +--- + +# Markdown Writing Skill + +## 重要ルール + +### 1. 図表作成ルール + +**mermaid または plantUML を使用**(ASCII ART禁止、ツリー除く) + +```mermaid +graph TD + A[開始] --> B{条件判定} + B -->|Yes| C[処理A] + B -->|No| D[処理B] +``` + +### 2. 文書の長さと分割ルール + +| ページ数 | 対応 | +|---------|-----| +| ~300行 | そのまま | +| 301~600行 | 2ファイルに分割 | +| 600行以上 | セクションごとに分割 | + +**分割時のファイル名**: 順序prefix(01-, 02-, ...)+ ケバブケース + +``` +docs/feature-guide/ +├── 01-introduction.md +├── 02-installation.md +└── 03-usage.md +``` + +## チェックリスト + +- [ ] 図表はmermaid/plantUML使用(ツリー除く) +- [ ] ファイル長は300行以内(超える場合は分割) +- [ ] 分割時は順序prefix使用(01-, 02-, ...) + +## 詳細ガイド + +| ファイル | 内容 | +|---------|------| +| `01-diagram-guide.md` | mermaid/plantUML記法、よくある間違い | + +## 関連リソース + +- [Mermaid公式ドキュメント](https://mermaid.js.org/) +- [PlantUML公式ドキュメント](https://plantuml.com/) diff --git a/plugins/ndf/skills-codex/merged/SKILL.md b/plugins/ndf/skills-codex/merged/SKILL.md new file mode 100644 index 00000000..06af6f2a --- /dev/null +++ b/plugins/ndf/skills-codex/merged/SKILL.md @@ -0,0 +1,29 @@ +--- +name: merged +description: "Clean up after a PR is merged." +argument-hint: "[PR番号]" +disable-model-invocation: true +allowed-tools: + - Bash + - Read +--- + +# マージ後クリーンアップコマンド + +PRマージ後のクリーンアップを実行。 + +## 手順 + +0. **事前確認**: github mcpで引数の(引数が無ければ自身が作成した最新の)PRがmainにmergeされていることを確認。mergeされていなければ終了 +1. **事前確認**: `git status`→変更あればstash +2. **main更新**: `git checkout main`→`git pull` +3. **worktreeクリーンアップ**: `git worktree list` で当該PR番号に対応する worktree (`pr`) を探し、あれば `git worktree remove ` で削除(worktree 内の `.cross_review/` も一緒に消える) +4. **ブランチ削除**: `git branch -d ` → stash復元 + +**注意**: 冪等性保証・エラー時中断・削除済み無視 + +## 作業完了報告(必須) + +- 実行サマリー(PRタイトル、マージコミット、削除したブランチ、現在のブランチ) +- mainブランチの状態 +- PR URL diff --git a/plugins/ndf/skills-codex/ndf-policies/SKILL.md b/plugins/ndf/skills-codex/ndf-policies/SKILL.md new file mode 100644 index 00000000..eb25c338 --- /dev/null +++ b/plugins/ndf/skills-codex/ndf-policies/SKILL.md @@ -0,0 +1,10 @@ +--- +name: ndf-policies +description: "Apply core NDF project policies." +user-invocable: false +--- + +# NDFポリシー + +このスキルはNDFプラグインの基本ポリシーを定義します。 +descriptionフィールドが常時コンテキストに注入されるため、本文の参照は不要です。 diff --git a/plugins/ndf/skills-codex/playwright-execution/SKILL.md b/plugins/ndf/skills-codex/playwright-execution/SKILL.md new file mode 100644 index 00000000..f99970cd --- /dev/null +++ b/plugins/ndf/skills-codex/playwright-execution/SKILL.md @@ -0,0 +1,101 @@ +--- +name: playwright-execution +description: "Run Playwright E2E tests with evidence and metrics." +when_to_use: "E2E テストの実行 / エビデンス収集 / 動画エビデンス / accessibility チェック / Core Web Vitals 計測が必要なとき。テストスクリプト作成済みであることが前提。Triggers: 'E2E テスト実行', 'テスト実行', '動画エビデンス', 'エビデンス収集', 'テスト証跡', 'a11y テスト', 'accessibility テスト', 'axe-core', 'WCAG', 'Core Web Vitals', 'Web Vitals', 'LCP', 'CLS', 'body_check', 'overlay', '字幕', 'カーソル'" +allowed-tools: + - Read + - Bash(uv *) + - Bash(pytest *) + - Bash(npx *) + - Bash(playwright *) + - Bash(python *) +--- + +# Playwright Execution (テスト実行 + エビデンス収集) + +テストスクリプト作成済みの状態で E2E テストを実行し、エビデンスを収集する。 + +## 前提条件 + +- テストスクリプトが `tests/` に作成済みであること (`/ndf:playwright-script-creation` で作成) +- `scenario.config.yaml` が設定済みであること + +## 大原則 + +**エビデンス動画はデフォルト ON**。全テストで常に動画を取得する。 +明示的にスキップする場合のみ `--pwk-no-video` を指定する。 + +## 実行コマンド + +```bash +./scenario-test/run.sh # 全テスト (動画 ON) +./scenario-test/run.sh -k test_admin # フィルタ +./scenario-test/run.sh --pwk-overlay # 字幕 + カーソル付き動画 +./scenario-test/run.sh --pwk-no-video # 動画のみ OFF +./scenario-test/run.sh --pwk-no-evidence # 全エビデンス OFF (HAR/trace/動画) +``` + +## エビデンス種別 + +| 種別 | デフォルト | OFF フラグ | 説明 | +|---|---|---|---| +| video | **ON** | `--pwk-no-video` | 全テストの動画を取得 | +| trace | ON (retain-on-failure) | `--pwk-no-evidence` | Playwright Trace (DOM + 操作ログ) | +| HAR | ON (minimal) | `--pwk-har-mode none` | ネットワーク通信ログ | +| screenshot | ON (only-on-failure) | `--pwk-no-evidence` | 失敗時スクリーンショット | + +## overlay (赤丸カーソル + 字幕) + +`--pwk-overlay` フラグで全テストの動画にオーバーレイが適用される。 + +API 詳細・使用例は `playwright_kit/overlay.py` を参照。主要関数: `set_caption()`, `flash_click()`, `hide_cursor()`。 + +## 品質計測 + +### accessibility (axe-core) + +`@pytest.mark.page_role` marker が付いたテストで auto_roles にマッチする場合に自動実行。 +設定は `scenario.config.yaml` の `accessibility:` セクションで制御。→ 設定例は `templates/scenario.config.yaml` を参照。 + +### Core Web Vitals + +`@pytest.mark.page_role` marker + auto_roles マッチで LCP/CLS/TTFB/longest_task を自動計測。 +設定は `scenario.config.yaml` の `web_vitals:` セクションで制御。→ 設定例は `templates/scenario.config.yaml` を参照。 + +### body_check (PHP/SSR エラー検出) + +`page.on("response")` で全 HTML レスポンスを監視し、`Fatal error` 等を検出。デフォルト有効。 +`@pytest.mark.no_body_check` で個別 opt-out 可能。→ 設定例は `templates/scenario.config.yaml` の `body_check:` セクションを参照。 + +## 成果物 + +``` +reports// +├── report.md # テスト結果サマリ +├── / +│ ├── video.mp4 # テスト動画 (デフォルト ON) +│ ├── trace.zip # Playwright Trace +│ ├── request.har # ネットワーク通信ログ +│ ├── body_check.jsonl # body_check 違反詳細 +│ └── screenshot-*.png # スクリーンショット +``` + +## CLI options + +| option | 役割 | +|---|---| +| `--pwk-config ` | `scenario.config.yaml` のパス | +| `--pwk-out-dir ` | 成果物出力先 (default: `reports//`) | +| `--pwk-no-video` | 動画収集を OFF (デフォルトは ON) | +| `--pwk-no-evidence` | HAR / trace / video の収集を全て OFF | +| `--pwk-har-mode {minimal,full,none}` | HAR 録画モード (default: minimal) | +| `--pwk-overlay` | overlay (赤丸カーソル + 字幕) を ON | + +## 関連 Skill + +- `/ndf:playwright-script-creation` — テストスクリプト作成 (実行の前段) +- `/ndf:playwright-report` — Markdown レポート生成 +- `/ndf:playwright-kit-ops` — スクリプト実行 (init_project / スキャン) +- `/ndf:playwright-browser-connect` — ブラウザ接続構成 (local / CDP remote) +- `/ndf:playwright-evidence-drive` — エビデンス Google Drive 保管 +- `/ndf:playwright-scenario-test` — 全機能統括 diff --git a/plugins/ndf/skills-codex/playwright-report/SKILL.md b/plugins/ndf/skills-codex/playwright-report/SKILL.md new file mode 100644 index 00000000..2f8897a7 --- /dev/null +++ b/plugins/ndf/skills-codex/playwright-report/SKILL.md @@ -0,0 +1,55 @@ +--- +name: playwright-report +description: "Generate Playwright test result reports." +when_to_use: "テストレポートの生成 / テスト結果の共有が必要なとき。Triggers: 'テストレポート', 'report.md', 'テスト結果', 'テスト報告書', 'レポート生成', 'テスト結果まとめ'" +allowed-tools: + - Read + - Bash(uv *) + - Bash(pytest *) + - Bash(python *) +--- + +# Playwright Report (レポート生成) + +テスト実行後に **Markdown レポート** を自動生成する。 + +## 自動生成 + +`pytest_terminal_summary` hook で `reports//report.md` が自動生成される。特別な設定は不要。 + +```bash +./scenario-test/run.sh +# → reports//report.md が生成される +``` + +## レポート内容 + +| セクション | 内容 | +|---|---| +| サマリ表 | nodeid, role, page_role, 結果, 実行時間, エラー数 | +| 失敗詳細 | FAIL/ERROR のテストごとの詳細情報 | +| body_check 違反 | PHP/SSR エラー検出の詳細 (URL, パターン, スニペット) | +| エビデンスリンク | video, trace, HAR, screenshot へのパス | + +## レポート設定 + +`scenario.config.yaml` の `report` セクション: + +```yaml +report: + title: "シナリオ E2E テスト 実施報告書" + test_plan_link: "./test-plan.md" + phase_labels: {} +``` + +## Google Drive での共有 + +レポート + エビデンスを Drive にアップロードしてチーム共有する場合は +`/ndf:playwright-evidence-drive` を参照。 + +## 関連 Skill + +- `/ndf:playwright-execution` — テスト実行 + エビデンス収集 +- `/ndf:playwright-evidence-drive` — エビデンス Google Drive 保管・共有 +- `/ndf:playwright-kit-ops` — エビデンスアップロードツール (スクリプト群) +- `/ndf:playwright-scenario-test` — 全機能を統括したフルワークフロー diff --git a/plugins/ndf/skills-codex/playwright-script-creation/SKILL.md b/plugins/ndf/skills-codex/playwright-script-creation/SKILL.md new file mode 100644 index 00000000..a42c0a8f --- /dev/null +++ b/plugins/ndf/skills-codex/playwright-script-creation/SKILL.md @@ -0,0 +1,108 @@ +--- +name: playwright-script-creation +description: "Create reproducible Playwright E2E test scripts." +when_to_use: "E2E テストスクリプトの作成 / テストコードの実装 / テストテンプレートからのスクリプト生成が必要なとき。Triggers: 'テストスクリプト作成', 'テストコード作成', 'テスト実装', 'テストを書く', 'シナリオ作成', 'codegen', 'テンプレートからテスト', 'playwright codegen'" +allowed-tools: + - Read + - Edit + - Write + - Bash(uv *) + - Bash(playwright *) + - Bash(python *) +--- + +# Playwright Script Creation (テストスクリプト作成) + +再現可能なテストスクリプトを作成し、レビューを経てからテスト実行に進む。 + +## 大原則 + +**テストスクリプトを実装してからテストを実施する。** +スクリプトが完成・レビューを経るまで `/ndf:playwright-execution` に進まない。 + +## 前提条件 + +- テスト計画が完了していること (`/ndf:playwright-test-planning` で計画済み) +- `init_project.sh` でプロジェクトが初期化済みであること (`/ndf:playwright-kit-ops`) + +## ワークフロー + +``` +[A] テスト計画の確認 (チェックリスト / page role / テスト技法) + │ +[B] テンプレート選択 + │ tests/ 配下の test_*.py.template を起点にする + ▼ +[C] テストコード実装 + │ playwright codegen で操作を記録 → テスト関数に組み込む + │ または手動で expect() ベースの assertion を書く + ▼ +[D] 再現可能性レビュー (下記チェックリスト) + │ +[E] テスト実行へ → /ndf:playwright-execution +``` + +## テンプレート一覧 + +`init_project.sh` で以下のテンプレートが `tests/` に配置済み: + +| テンプレート | page role | 内容 | +|---|---|---| +| `test_auth.py` | auth | ログイン / ログアウトフロー | +| `test_list.py` | list | 一覧ページネーション / ソート | +| `test_form.py` | form | 入力 → 送信 → 結果検証 | +| `test_dashboard.py` | dashboard | KPI / リンク遷移 | + +## テストコードの書き方 + +### テンプレートを起点にする + +各 page role のテンプレートが `templates/test_*.py.template` に用意されている。 +`init_project.sh` 実行時に `tests/` へコピーされるので、プロジェクト固有の URL やセレクタを書き換えて使う。 + +→ コード例: `templates/test_form.py.template`, `templates/test_auth.py.template` 等を参照 + +### playwright codegen での操作記録 + +`uv run playwright codegen ` で操作を記録し、生成コードをテスト関数にコピーする。 +コピー後に `@pytest.mark.page_role()`, `@pytest.mark.role()`, `expect()` assertion, `pwk_config.base_url` を追加する。 + +### overlay 付きテスト + +overlay API (`set_caption`, `flash_click`) の使用例は `playwright_kit/overlay.py` を参照。 + +## fixture / marker 一覧 + +fixture / marker の完全な一覧は `playwright_kit/pytest_plugin.py` の `_PWK_MARKERS` 定義と `playwright_kit/fixtures/` 配下の各モジュールを参照。 + +主な fixture: `pwk_config`, `pwk_role_`, `pwk_evidence`, `pwk_accessibility_scan()`, `pwk_web_vitals_measure()` +主な marker: `@pytest.mark.page_role()`, `@pytest.mark.role()`, `@pytest.mark.phase()`, `@pytest.mark.priority()`, `@pytest.mark.no_body_check` + +## 再現可能性レビューチェックリスト + +スクリプト完成後、以下を全項目確認してからテスト実行に進む: + +- [ ] **再現可能性**: 同じ環境で同じ結果が得られるか (ランダム値・タイムスタンプに依存していないか) +- [ ] **テストデータ独立性**: 外部の状態に依存せず、テスト単体で成立するか +- [ ] **marker 付与**: `@pytest.mark.page_role()` が全テスト関数に付与されているか +- [ ] **role marker**: 認証が必要なテストに `@pytest.mark.role()` + `pwk_role_` fixture があるか +- [ ] **assertion 網羅性**: 正常系 + 少なくとも 1 つの異常系 (バリデーション等) が含まれるか +- [ ] **URL 構築**: ハードコードされた URL ではなく `pwk_config.base_url` を使用しているか +- [ ] **wait 戦略**: `wait_until="domcontentloaded"` 等の明示的な待機指定があるか +- [ ] **ndf plugin 非依存**: `scenario-test/` ディレクトリ単体で実行可能か + +## ndf plugin 非依存 + +`init_project.sh` で埋め込まれた `scenario-test/` は: +- `playwright_kit/` パッケージ本体を含む +- `pyproject.toml` で pytest11 entry-point を定義 +- `run.sh` でワンコマンド実行可能 + +→ ndf plugin 未インストール環境でも `./scenario-test/run.sh` で動作する。 + +## 関連 Skill + +- `/ndf:playwright-test-planning` — テスト計画 (前段) +- `/ndf:playwright-execution` — テスト実行 + エビデンス収集 (後段) +- `/ndf:playwright-kit-ops` — init_project / codegen 等のツール群 +- `/ndf:playwright-scenario-test` — 全機能統括 diff --git a/plugins/ndf/skills-codex/playwright-test-planning/SKILL.md b/plugins/ndf/skills-codex/playwright-test-planning/SKILL.md new file mode 100644 index 00000000..a0810adc --- /dev/null +++ b/plugins/ndf/skills-codex/playwright-test-planning/SKILL.md @@ -0,0 +1,97 @@ +--- +name: playwright-test-planning +description: "Plan E2E tests and classify page roles." +when_to_use: "E2E テストの計画立案 / page role 分類 / テスト技法の選定 / チェックリスト活用が必要なとき。Triggers: 'テスト計画', 'テスト計画立案', 'page role', 'HTSM', 'ISTQB', 'FEW HICCUPPS', 'チェックリスト', 'テスト技法', 'テスト設計'" +allowed-tools: + - Read + - Bash(python *) +--- + +# E2E テスト計画 (理論ベース) + +HTSM / ISTQB / FEW HICCUPPS に基づいて E2E テストシナリオを計画する。 + +## 計画ワークフロー + +``` +[A] 対象 URL を渡される + │ +[B] page role を判定 → scripts/classify_page_role.py --url + ▼ +[C] 該当チェックリストを開く → docs/checklists/checklist-{role}.md + │ 全項目を「適用」or「不適用 (理由付き)」で判定 + ▼ +[D] 必須テスト技法を確定 → docs/03-test-techniques.md § 11 + ▼ +[E] pytest テストを書く → templates/test_.py.template を起点に + ▼ +[F] スクリプト作成へ → /ndf:playwright-script-creation + テスト計画が確定したら、テストスクリプトの作成に進む。 + テスト計画が完了するまでスクリプト作成には進まない。 +``` + +## page role 一覧 + +| role | 説明 | 例 | +|---|---|---| +| lp | ランディングページ | トップ、LP | +| list | 一覧ページ | 商品一覧、記事一覧 | +| item | 詳細ページ | 商品詳細、記事詳細 | +| edit | 編集ページ | プロフィール編集 | +| form | 申込・入力フォーム | 会員登録、問い合わせ | +| search | 検索ページ | サイト内検索 | +| dashboard | ダッシュボード | 管理画面トップ | +| auth | 認証ページ | ログイン、パスワードリセット | +| cart-checkout | カート・決済 | ショッピングカート | +| modal-wizard | モーダル・ウィザード | ステップ型入力 | + +## チェックリスト + +`playwright-test-planning/docs/checklists/` 配下に role 別チェックリストがある: + +``` +docs/checklists/ +├── checklist-common.md # 全 role 共通項目 +├── checklist-lp.md +├── checklist-list.md +├── checklist-item.md +├── checklist-edit.md +├── checklist-form.md +├── checklist-search.md +├── checklist-dashboard.md +├── checklist-auth.md +├── checklist-cart-checkout.md +└── checklist-modal-wizard.md +``` + +## 方法論ドキュメント + +`playwright-test-planning/docs/` 配下: + +| ファイル | 内容 | +|---|---| +| `01-methodology.md` | HTSM / FEW HICCUPPS / ISO 29119-3 の概要 | +| `02-page-roles.md` | page role 分類の詳細定義 | +| `03-test-techniques.md` | テスト技法 (EP/BVA/Decision Table/Pairwise) + role 必須マッピング | +| `04-playwright-mapping.md` | Playwright API → role / 観点 マッピング | +| `05-bug-report.md` | 不具合報告書の仕様 (ISO 29119-3 + FEW HICCUPPS oracle) | + +## 補助スクリプト + +スクリプトの実行は `/ndf:playwright-kit-ops` skill を参照。主なコマンド: + +```bash +# page role を自動推定 (playwright-kit-ops/scripts/ 配下) +python scripts/classify_page_role.py --url + +# Playwright codegen で操作を記録 → テストコードに変換 +python scripts/record_scenario.py +``` + +> 上記は `playwright-kit-ops/` ディレクトリ内での実行を想定。詳細は `/ndf:playwright-kit-ops` を参照。 + +## 関連 Skill + +- `/ndf:playwright-script-creation` — テストスクリプト作成 (次のフェーズ) +- `/ndf:playwright-execution` — テスト実行 + エビデンス収集 +- `/ndf:playwright-scenario-test` — 全機能を統括したフルワークフロー diff --git a/plugins/ndf/skills-codex/playwright-test-planning/docs/01-methodology.md b/plugins/ndf/skills-codex/playwright-test-planning/docs/01-methodology.md new file mode 100644 index 00000000..9c6e0df9 --- /dev/null +++ b/plugins/ndf/skills-codex/playwright-test-planning/docs/01-methodology.md @@ -0,0 +1,148 @@ +# 01. テスト方法論総論 + +本 Skill は「Playwright + curl で実行する E2E テスト」を、経験則ではなく**業界標準の理論**に基づいて設計する。 +本書はその理論的な土台を、実用に落とし込む形で要約したもの。 + +## 1. 目的の二項定義 + +テストの目的は次の 2 つに分解できる (ISTQB / Beizer)。 + +1. **不具合の発見**: 仕様 / 期待挙動から外れる症状を能動的に探す +2. **修正担当者への情報提供**: 発見した症状を**再現可能で偏りのない記述**で伝える + +この 2 つは独立したスキルセットを必要とする。本 Skill は両方を「設計時にどの観点をテストするか」と「実行時に何を証拠として残すか」の 2 段で機械化する。 + +## 2. テスト戦略のフレームワーク (HTSM) + +James Bach の **Heuristic Test Strategy Model** (v6.3) は、テスト戦略を 4 つの構成要素に分解する。 + +``` + Quality Criteria (CRUSCSPCID: どの品質特性をテストするか) + │ + Mission ─── Strategy ─── Test Techniques (どう調査するか) + │ + Project Environment (リソース・制約・チーム・予算・スケジュール) + │ + Product Elements (SFDIPOT: 何をテストするか) +``` + +### 2.1 Product Elements (SFDIPOT) + +「製品の何を見るか」のチェックリスト。 + +| 因子 | 内容 | Web E2E での例 | +|---|---|---| +| **S**tructure | 構造的部品 | URL ツリー / route 設計 / DOM 構造 / コンポーネント階層 | +| **F**unction | 機能 | CRUD / 検索 / 認証 / 決済 / 通知 | +| **D**ata | データ | 入力 / 出力 / 永続化 / 流入元 / 文字種・境界 | +| **I**nterfaces | 接合面 | API / WebSocket / 3rd party / iframe / postMessage | +| **P**latform | プラットフォーム | OS / ブラウザ / device / viewport / 言語 | +| **O**perations | 運用 | 利用シナリオ / ペルソナ / ロール | +| **T**ime | 時間 | 日付 / TZ / 同時実行 / sequence / 期限 | + +### 2.2 Quality Criteria (CRUSCSPCID) + +「どんな品質か」のチェックリスト。本 Skill は **Capability** (機能満足) と **Reliability** (再現性) を主軸に、Web 文脈で重要な **Usability** (a11y 含)、**Security**、**Performance** を併走させる。 + +| 略 | 軸 | 主担当チェック | +|---|---|---| +| C | Capability | 機能要件を満たすか | +| R | Reliability | 同じ操作で同じ結果か。エラー時に回復するか | +| U | Usability | 操作可能性 (a11y / キーボード操作 / 国際化) | +| S | Scalability | 大量データ / 高負荷下の挙動 | +| C | Charisma | 感情的訴求 / ブランド整合 (人間判定主体) | +| S | Security | OWASP Top 10 / CSRF / IDOR / 認証 | +| P | Performance | LCP / INP / CLS / API 応答時間 | +| C | Compatibility | クロスブラウザ / OS / デバイス | +| I | Installability | (SaaS では設定/退会フローに相当) | +| D | Development | テスト容易性 / ログ充実 | + +## 3. テスト技法 (ISTQB CTFL 4.2) + +詳細は `03-test-techniques.md` 参照。本書では「どの page role でどの技法を必須にするか」だけ示す。 + +| page role | 必須技法 | 推奨追加 | +|---|---|---| +| LP | Claims Testing, Domain Testing (viewport) | accessibility / web_vitals | +| list | Equivalence Partitioning, BVA, Pairwise (フィルタ次元 ≥3) | State Transition | +| item | Domain Testing (id partition), Risk Testing (IDOR) | Claims | +| edit | BVA, Equivalence Partitioning, Decision Table | State Transition (dirty/saving/error) | +| form | **Decision Table 必須**, Classification Tree, State Transition | Pairwise | +| search | Domain Testing, Claims Testing | Pairwise (ファセット) | +| dashboard | Domain Testing (期間), Claims Testing | State Transition | +| auth | Decision Table (認証分岐), Risk Testing | | +| cart/checkout | Decision Table, BVA (金額境界), State Transition | | +| modal/wizard | State Transition (open/close/focus), ARIA APG conformance | | + +## 4. Oracle: FEW HICCUPPS (Bach / Bolton) + +「これは不具合か?」を 11 軸で判定する。**全 bug report に該当軸を必ず記録**することで、AI / 人間の判定揺らぎを抑える。 + +| 略 | 軸 | 例 | +|---|---|---| +| **F** | Familiarity (既知パターン) | 過去 bug DB に同型がある | +| **E** | Explainability (説明可能性) | 価格と総額の差を説明できない | +| **W** | World (世界の事実) | 月が 13 月、県が 47 以外 | +| **H** | History (過去版との一貫性) | 前 release ではできた操作 | +| **I** | Image (ブランド/外観) | デザインガイド逸脱 | +| **C** | Comparable products | 競合と比べ明らかに弱い | +| **C** | Claims (仕様/広告) | spec が「3秒以内」と主張 | +| **U** | User expectations | 一般的ユーザが「こう動く」と思う | +| **P** | Product (内部一貫性) | 詳細とリストで値が違う | +| **P** | Purpose (目的整合) | EC なのに購入できない | +| **S** | Statutes/Standards (法令/標準) | WCAG / GDPR / PCI 違反 | + +## 5. Hendrickson Test Heuristics Cheat Sheet + +20 個の guideword で「テストアイデアを生成する」発想支援。実行のたびに「Boundaries / Goldilocks / CRUD / Position / Selection / **Count (0/1/Many)** / Multi-user / Flood / Sequences / Sorting / **Interruptions** / Constraints / Input Method / Configurations / Starvation / Dependencies / Touch Points / Variable Analysis / **State** / Map Making」をチェック。 + +太字の **Count**, **Interruptions**, **State** は Web E2E で見落としやすく、checklists/ で繰り返し参照する。 + +## 6. テスト計画立案フロー (本 Skill の標準手順) + +``` +[1] 対象 URL のスクショまたは構造解析 + │ Playwright: page.accessibility.snapshot() or page.evaluate(getRoleSummary) + ▼ +[2] page role を判定 → docs/02-page-roles.md の識別ヒューリスティック + │ playwright-kit-ops/scripts/classify_page_role.py が補助 (DOM の role 集計) + ▼ +[3] 該当 checklist を開く → docs/checklists/checklist-{role}.md + │ 全項目を「適用」または「不適用 (理由付き)」と判定 + ▼ +[4] 各項目に適用するテスト技法を選ぶ → docs/03-test-techniques.md + │ 例: 編集フィールドなら BVA で min-1/min/min+1/max-1/max/max+1 + ▼ +[5] pytest テストを書く → templates/test_{role}.py.template + │ playwright codegen で操作録画 → そのまま test 関数に貼ってもよい + │ @pytest.mark.page_role(...) を付けると accessibility / web_vitals が autouse で走る + ▼ +[6] 実行 → uv run pytest --pwk-config=./scenario.config.yaml -n 4 + │ trace.zip / video / screenshot / HAR / console / accessibility / web_vitals を自動収集 + │ reports//report.md が pytest_terminal_summary で生成 + ▼ +[7] FAIL → docs/05-bug-report.md の構造で報告 (FEW HICCUPPS 軸付与) +``` + +## 7. 「経験」と「理論」の境界 + +本 Skill では次の方針で経験則を切り出している。 + +| 種類 | 配置 | 理由 | +|---|---|---| +| 業界標準 (ISO / WCAG / OWASP / ISTQB) | docs/ 配下 (このディレクトリ) | 出典がある。揺らぎが小さい | +| ヒューリスティクス (HTSM / FEW HICCUPPS / Hendrickson) | docs/ 配下 | 「思考の道具」として再利用 | +| 個別プロジェクトの慣習 (PHP / Rails / 等) | scenario.config.yaml の `tolerated_console_errors` / `tolerated_page_errors` 正規表現 | 個別カスタマイズ | +| 動画/HUD の細かい数値 (字幕高さ・カーソル色) | playwright_kit/overlay.py のコード内定数 | 表示 UX の調整。理論の対象外 | + +「経験」を docs に書くのではなく、**理論を docs に書き、慣習は config に逃がす** のが本 Skill の規律。 + +## 参考文献 + +- James Bach, "Heuristic Test Strategy Model" v6.3, https://www.developsense.com/resource/htsm.pdf +- Michael Bolton, "FEW HICCUPPS", https://developsense.com/blog/2012/07/few-hiccupps +- Elisabeth Hendrickson et al., "Test Heuristics Cheat Sheet", https://www.ministryoftesting.com/articles/test-heuristics-cheat-sheet +- ISTQB Foundation Level Syllabus 4.2 (Black-box Test Techniques), https://astqb.org/4-2-black-box-test-techniques/ +- ISO/IEC/IEEE 29119-3:2021 — Test documentation +- W3C, "WCAG 2.2", https://w3c.github.io/wcag/requirements/22/ +- OWASP, "Top 10:2025", https://owasp.org/Top10/2025/0x00_2025-Introduction/ diff --git a/plugins/ndf/skills-codex/playwright-test-planning/docs/02-page-roles.md b/plugins/ndf/skills-codex/playwright-test-planning/docs/02-page-roles.md new file mode 100644 index 00000000..f3ccc627 --- /dev/null +++ b/plugins/ndf/skills-codex/playwright-test-planning/docs/02-page-roles.md @@ -0,0 +1,207 @@ +# 02. Page Role 分類 + +ページを役割で分類する。**URL パターンや SEO 構造ではなく、ユーザの目的とテスト観点で分類** する。 +1 ページが複数 role を兼ねる場合は両方の checklist を適用する (例: 一覧 + 検索)。 + +各 role には次の 4 セクションを定義する: +- **識別ヒューリスティック**: そのページが当該 role かを判定する特徴 +- **代表 URL パターン**: よく見るパス +- **必須 checklist**: `docs/checklists/checklist-{role}.md` への参照 +- **代表的 oracle**: FEW HICCUPPS のうち主に使う軸 + +## 全 role 一覧 + +| role | 短い説明 | 識別の主シグナル | +|---|---|---| +| `lp` | Landing Page (外部到達) | nav 中心 + CTA 多 + 機能 < 5 | +| `list` | 一覧 | 同一構造の繰り返し要素 + ページャ | +| `item` | 詳細 | URL に id / 単一エンティティ | +| `edit` | 編集 | プリフィル + save/cancel | +| `form` | 申込フォーム (複数ステップ) | progress indicator + 確認画面 | +| `search` | 検索 | search box + 結果 list + ファセット | +| `dashboard` | ダッシュボード | KPI カード + 複数チャート + 期間フィルタ | +| `auth` | 認証 | login form / logout / 2FA | +| `cart` | カート | 商品行 + 数量変更 + 合計 | +| `checkout` | チェックアウト | 配送/支払い段階 + 確認 | +| `modal` | モーダル | `role="dialog"` + 背景 overlay | +| `wizard` | ウィザード | step インジ + 戻る/次へ | +| `error` | エラーページ | 4xx/5xx + 復帰導線 | +| `settings` | 設定 / プロフィール | 個人設定の保存フォーム群 | + +## 各 role 詳細 + +### `lp` — Landing Page (外部到達ページ) +**識別**: ドメインルート (`/`) または `/lp/*` `/campaign/*`。 +ナビ + ヒーロー + 複数の説明セクション + CTA。SEO meta tag が充実。 +ページ深度 1。機能リンク (form 等) は 1〜3 個に集中。 + +**代表 URL**: `/`, `/lp/2026-spring`, `/about`, `/pricing`, `/features`. + +**必須 checklist**: [`checklists/checklist-lp.md`](checklists/checklist-lp.md) + +**代表的 oracle**: Claims (主張), Image (ブランド), Statutes (a11y / GDPR バナー). + +--- + +### `list` — 一覧ページ +**識別**: 同一構造の要素 (table / card / feed) が繰り返し描画される。 +ページャ or 無限スクロール。ソート/フィルタ UI。各行に詳細リンク。 + +**代表 URL**: `/items`, `/users`, `/orders`, `/posts`, `/products`. + +**必須 checklist**: [`checklists/checklist-list.md`](checklists/checklist-list.md) + +**代表的 oracle**: Product (内部一貫性 — 件数と表示の一致), Statutes (テーブル a11y), Claims (フィルタ仕様). + +--- + +### `item` — 詳細ページ +**識別**: URL に `/{resource}/{id}`。breadcrumbs。編集 / 削除 / 戻るリンク。 + +**代表 URL**: `/items/123`, `/users/u_abc`, `/orders/o_xyz`. + +**必須 checklist**: [`checklists/checklist-item.md`](checklists/checklist-item.md) + +**代表的 oracle**: Product (一覧との値一致), Statutes (IDOR / 認可), History (過去版で動いた操作). + +--- + +### `edit` — 編集ページ +**識別**: 既存値プリフィル + Save / Cancel ボタン。dirty 検知 (`beforeunload`)。CSRF token。 + +**代表 URL**: `/items/123/edit`, `/items?Cmd=Edit&ItemID=123`. + +**必須 checklist**: [`checklists/checklist-edit.md`](checklists/checklist-edit.md) + +**代表的 oracle**: Claims (validation 仕様), Product (保存後の値整合), Statutes (CSRF / a11y errors). + +--- + +### `form` — 申込フォーム (複数ステップ) +**識別**: 進捗インジ (Step 1/N) + 戻る/次へ + 確認画面 + 送信 + 完了画面。 +入力分岐がある (国別 / 法人個人 / オプション)。**コードを読みながら Decision Table を作る対象**。 + +**代表 URL**: `/contact`, `/signup`, `/apply`, `/subscribe`. + +**必須 checklist**: [`checklists/checklist-form.md`](checklists/checklist-form.md) + +**代表的 oracle**: Claims (分岐ロジック仕様), Product (確認画面と送信値の一致), User (ステップ間ナビゲーション期待). + +--- + +### `search` — 検索ページ +**識別**: search box + 結果 list + ファセット + 件数表示 + ハイライト + サジェスト. + +**代表 URL**: `/search`, `/?q=...`, `/find`. + +**必須 checklist**: [`checklists/checklist-search.md`](checklists/checklist-search.md) + +**代表的 oracle**: Claims (relevance 順位), Product (件数と表示の整合), Statutes (XSS / SQL inj sanitize). + +--- + +### `dashboard` — ダッシュボード +**識別**: KPI カード + 複数チャート + 期間/dimension フィルタ + drill-down. + +**代表 URL**: `/dashboard`, `/analytics`, `/reports`, `/admin`. + +**必須 checklist**: [`checklists/checklist-dashboard.md`](checklists/checklist-dashboard.md) + +**代表的 oracle**: Product (合計と内訳の一致), Claims (リアルタイム表記), Statutes (色覚多様性 / a11y). + +--- + +### `auth` — 認証 +**識別**: email/username + password。SSO ボタン / Remember me / Forgot password / 2FA. + +**代表 URL**: `/login`, `/signin`, `/register`, `/forgot-password`, `/auth/callback`. + +**必須 checklist**: [`checklists/checklist-auth.md`](checklists/checklist-auth.md) + +**代表的 oracle**: Statutes (OWASP ASVS / NIST 800-63B), Claims (パスワードポリシー), History (セッション再発行). + +--- + +### `cart` / `checkout` — カート / 決済 +**識別**: 商品行 + 数量 + 合計 + 配送 + 支払い + 確認 + 完了. + +**代表 URL**: `/cart`, `/checkout`, `/checkout/payment`, `/order/confirm`. + +**必須 checklist**: [`checklists/checklist-cart-checkout.md`](checklists/checklist-cart-checkout.md) + +**代表的 oracle**: Claims (税/送料計算), Product (価格再計算と表示の整合), Statutes (PCI DSS), History (在庫変動). + +--- + +### `modal` / `wizard` — モーダル / ウィザード +**識別**: `role="dialog"` + `aria-modal="true"` + overlay + close. wizard は内部に step. + +**代表**: 削除確認 dialog, onboarding wizard, 設定 modal. + +**必須 checklist**: [`checklists/checklist-modal-wizard.md`](checklists/checklist-modal-wizard.md) + +**代表的 oracle**: Statutes (W3C ARIA APG dialog pattern), User (Esc キーで閉じる期待), Product (wizard 状態保持). + +--- + +### `error` — エラーページ +**識別**: HTTP 4xx/5xx 応答。"Page not found" / "Server error" / "Maintenance". + +**代表 URL**: 404 / 500 / 503 / 429 / 401 / 403. + +**必須 checklist**: 一覧未整備 — checklists/checklist-common.md の「エラーハンドリング」節参照 + +**代表的 oracle**: Claims (status code 仕様), Product (実 status と画面の一致), Statutes (PII 露出禁止). + +--- + +### `settings` — 設定 / プロフィール +**識別**: 個人 / 組織設定の保存フォーム群。アバター。退会導線。 + +**代表 URL**: `/settings/profile`, `/settings/notifications`, `/account`. + +**必須 checklist**: 「edit」を流用 + checklists/checklist-common.md のセキュリティ節 (再認証要求). + +**代表的 oracle**: Claims (即時反映表記), Statutes (OWASP ASVS V8 Data Protection), History (退会後のデータ扱い). + +## 識別の自動化 + +`playwright-kit-ops/scripts/classify_page_role.py` は次のヒューリスティックで role を推定する: + +``` +入力: target_url, [既ログイン storage_state] +処理: + 1. page.goto(url) + 2. accessibility tree を抽出 (page.accessibility.snapshot()) + 3. role 集計: + - article >= 2 + listitem >= 2 → list 候補 + - role=heading lvl=1 + role=link >= 5 + role=button (CTA) → lp 候補 + - role=textbox + role=button name="Sign in"|"Login" → auth 候補 + - role=dialog → modal + - role=textbox >= 3 + 進捗 (`step` text or aria-label) → form + - role=table or role=grid → list (table 系) + - getByLabel("Email") + getByLabel("Password") → auth + 4. URL pattern (id 含むなど) で補強 +出力: 推定 role + 信頼度 + 代替候補 +``` + +これにより、AI が「経験で role を決める」のではなく、a11y tree という客観的事実から決まる。 + +## 兼ね role の扱い + +1 ページが複数 role を兼ねる場合 (例: 検索結果 = list + search): + +```python +@pytest.mark.page_role("search", "list") +def test_search_result(page, pwk_role_user): + ... +``` + +このとき各 role の checklist 全項目を走査する。重複項目は片方で OK。 + +## 参考文献 + +- James Bach, "Heuristic Test Strategy Model" v6.3 (Operations / Users) +- Nielsen Norman Group, "Page Types and Templates" +- W3C, "ARIA in HTML", https://www.w3.org/TR/html-aria/ +- W3C WAI-ARIA APG, https://www.w3.org/WAI/ARIA/apg/patterns/ diff --git a/plugins/ndf/skills-codex/playwright-test-planning/docs/03-test-techniques.md b/plugins/ndf/skills-codex/playwright-test-planning/docs/03-test-techniques.md new file mode 100644 index 00000000..4b8cd21b --- /dev/null +++ b/plugins/ndf/skills-codex/playwright-test-planning/docs/03-test-techniques.md @@ -0,0 +1,284 @@ +# 03. テスト技法ライブラリ + +ISTQB CTFL 4.2 のブラックボックス技法を中心に、Web E2E で実用される技法を整理する。 +各技法に **(1) 定義 (2) 適用例 (3) 適用すべき page role (4) 限界** を記す。 + +テストケース YAML には **使用した技法名を必ず記録** すること: + +```yaml +- name: パスワード境界テスト + technique: BVA + oracle: Claims # FEW HICCUPPS のどの軸 + inputs: [7, 8, 64, 65] + expect_behavior: ... +``` + +## 1. Equivalence Partitioning (EP) — 同値分割 + +### 定義 (ISTQB CTFL 4.2.1) +入力ドメインを「同じ処理が期待される」分割に分け、各分割から代表値 1 つでテストする。 +不具合は「分割を取り違えた処理」に起因することが多いという前提。 + +### 適用例 +- 年齢: `<0` / `0–17` / `18–64` / `65–120` / `>120` → 5 分割 → 各 1 テスト +- 入力欄の文字種: `空` / `半角英数` / `全角` / `絵文字` / `制御文字` / `BiDi` + +### 適用 role +全 role。特に `edit`, `form`, `search`. + +### 限界 +- 分割の境界は別途 BVA で補完が必要 +- 順序の無いカテゴリ (色 / 言語) は EP のみ + +--- + +## 2. Boundary Value Analysis (BVA) — 境界値分析 + +### 定義 (ISTQB CTFL 4.2.1) +順序のある分割の境界値そのもの、境界 ± 1 をテストする。 +「不具合は境界に集まる」という経験的事実を踏まえる。 + +### 適用例 +- パスワード長 (仕様 8〜64): `7 / 8 / 9 / 63 / 64 / 65` +- ページ番号 (1 始まり): `0 / 1 / 2 / last-1 / last / last+1 / -1 / 'abc'` +- 金額 (0 円許容?): `-1 / 0 / 1 / max-1 / max / max+1` + +### 適用 role +`edit`, `form`, `list` (ページネーション), `cart` (金額境界), `search` (件数 0/1/many). + +### 限界 +- 順序の無いカテゴリには無効 +- 境界仕様が曖昧な場合は **どこを境界としたか** を bug report に明記 + +--- + +## 3. Decision Table — 判定表 + +### 定義 (ISTQB CTFL 4.2.2) +入力条件と期待結果の組合せを表で網羅する。 + +``` +| 国 | 会員ランク | クーポン | 期待送料 | +|----|----------|---------|---------| +| JP | Free | なし | 500 円 | +| JP | Free | あり | 0 円 | +| JP | Pro | なし | 0 円 | +| US | Free | なし | 1500 円 | +| US | Pro | なし | 0 円 | +``` + +ルール ≤ 6 個の条件で網羅。> 6 個なら Classification Tree + Pairwise で削減。 + +### 適用例 +- 認証: (auth_present, csrf_token, captcha) × 期待 status code +- 配送料計算: (国, 会員, クーポン, 重量) × 配送料 + +### 適用 role +**`form`, `auth`, `cart`/`checkout` で必須**。 +Edit / Search でも入力分岐があれば適用。 + +### 限界 +- 条件 6 個で `2^6 = 64` 行になり管理不能 → 上位概念で集約 (Classification Tree) +- 条件の独立性が前提 (相互作用は別テスト) + +--- + +## 4. State Transition Testing — 状態遷移 + +### 定義 (ISTQB CTFL 4.2.2) +状態と遷移を表/図で定義し、有効遷移と無効遷移を網羅。 +0-switch (1 遷移) / 1-switch (2 連続遷移) でカバレッジを階層化。 + +### 適用例 +注文の状態遷移: + +``` +[draft] ─submit→ [submitted] ─pay→ [paid] ─ship→ [shipped] ─deliver→ [delivered] + │ │ + └──cancel────────────────────[cancelled] +``` + +無効遷移: `delivered → cancel`, `submitted → ship`, etc. + +### 適用 role +`cart`/`checkout` (cart→checkout→paid→fulfilled), `auth` (logged_out→logging_in→logged_in→locked), `form` (step1→step2→...→complete), `edit` (clean→dirty→saving→saved/error). + +### 限界 +- 状態爆発時 (>20 状態) に階層化が必要 +- 並行状態 (multi-tab) は別モデル + +--- + +## 5. Use Case Testing — ユースケース + +### 定義 (ISTQB CTFL 4.2.2) +アクター × ゴールから主流れと例外流れを抽出してシナリオ化。 + +### 適用例 +「ユーザが商品を返品する」: +- 主流れ: 注文一覧 → 該当注文 → 返品申請 → 理由選択 → 返品ラベル DL → 完了 +- 例外: 期限超過 / 配送中 / 既返品済み / 一部返品 + +### 適用 role +全 role の **シナリオ束ね** に有効。本 Skill では「1 testcase = 1 use case scenario」。 + +### 限界 +- UI 詳細はカバーしない (BVA / EP で補強) + +--- + +## 6. Pairwise / All-Pairs Testing + +### 定義 (ISTQB CTFL 4.2.3) +多次元組合せを「全 2 因子組合せ」に絞る。 +**不具合の 70%以上が 2 因子相互作用**という経験則 (Kuhn et al. 2004) に基づく。 + +### 適用例 +OS (3) × Browser (4) × 言語 (5) × 端末タイプ (3) = 全 180 通り → All-Pairs で ~20 通り. +ツール: PICT (Microsoft), allpairs.py (Python). + +### 適用 role +`form` (国 × 配送 × 支払い × 法人/個人), `dashboard` (期間 × dimension × フィルタ), `search` (ファセット組合せ), `list` (ソート × フィルタ × ページ). + +### 限界 +- 3 因子以上の交互作用は見逃す +- ツール依存 (手作業では困難) + +--- + +## 7. Classification Tree Method (CTM) + +### 定義 (Grimm/Grochtmann 1993) +入力因子と値クラスを階層的なツリーに整理し、葉ノードを Pairwise で組合せ生成。 + +### 適用例 +``` +申込フォーム +├── 顧客種別: [個人, 法人] +├── 国: [JP, US, EU, 他] +├── 支払い: [カード, 銀振, PayPal] +└── 配送: [標準, 速達, 店舗受取] +``` +→ 葉 4 因子の All-Pairs で ~20 ケース生成。 + +### 適用 role +`form` (複数ステップ), `cart`/`checkout` (オプション組合せ). + +--- + +## 8. Domain Testing (HTSM) + +### 定義 (Kaner / Bach) +入力/出力データを系統的に分割し、典型値・境界値・無効値を選ぶ。 +EP/BVA を Web の文字列・日付・URL・ファイル等に拡張した実用版。 + +### 標準分割セット +| データ型 | 分割 | +|---|---| +| 整数 | min-1, min, min+1, 0, 1, -1, mid, max-1, max, max+1, NaN, ∞ | +| 文字列 | 空, 1 文字, 短, 平均, 長, max, max+1, 半角, 全角, 絵文字, BiDi, 制御文字, ヌル文字 | +| 日付 | 過去 / 現在 / 未来 / 閏年 2/29 / DST 切替 / 年末年始 / TZ 境界 / RFC 3339 違反 | +| URL | http/https/file/ftp / 異なるドメイン / クエリ / フラグメント / IDN / IPv6 / open redirect | +| ファイル | 0 byte / 拡張子のみ / 拡張子偽装 / 大ファイル / Unicode 名 / 同名重複 | + +### 適用 role +`edit`, `form`, `search`, `list`, `cart` の数値/金額. + +--- + +## 9. その他 HTSM / 経験的技法 + +### Stress Testing +過負荷・低リソース・大量データで応答を観察。 +Playwright での近似: `route` で全リクエストに 300ms delay を注入、`context.set_offline(True)` で回線切断、データ生成スクリプトで 10000 件投入。 + +### Flow Testing +リセットせず連続操作。副作用を引き出す。 +例: カートに追加 50 連発 → 二重登録 / 在庫不整合. + +### Scenario Testing (HTSM) +「重要人物が重要な事をする物語」を実行。 +本 Skill の pytest テスト関数 1 件 = 1 シナリオ. + +### Claims Testing (HTSM) +仕様 / 広告 / SLA の主張を逐一検証。 +例:「3秒以内に表示」「99.9% uptime」「Drag & Drop に対応」. + +### Risk Testing (HTSM) +想定欠陥を仮説立てし、それを暴く試験を設計。 +例: 「他人の注文を IDOR で見れるはずだ」→ 別ユーザの id で URL を踏む. + +### User Testing (HTSM) +ペルソナごとの利用シナリオを実行。スクリーンリーダー利用者 / 高齢者 / 非ネイティブ言語話者. + +### Automatic Checking +機械的に oracle で照合できる部分を網羅 (axe-core / visual diff / API レスポンス検査). + +--- + +## 10. Hendrickson Test Heuristics (20 guideword) + +| guideword | 説明 | +|---|---| +| Boundaries | 境界値 (BVA) | +| Goldilocks | 短すぎ・長すぎ・適切 | +| CRUD | Create / Read / Update / Delete を全網羅 | +| Position | 並び順の最初/最後/中間 | +| Selection | 選択 0/1/全/不正 | +| **Count** | 0 件 / 1 件 / 多数 | +| Multi-user | 同時編集 / 競合 | +| Flood | 連打 / 大量データ | +| Sequences | 順序を入替えて副作用を引き出す | +| Sorting | 昇順 / 降順 / null 含む / i18n 並び | +| **Interruptions** | ネットワーク切断 / タブ閉じる / セッション切れ | +| Constraints | 必須 / 一意 / 関係 / FK | +| Input Method | キーボード / マウス / タッチ / 音声 / コピペ | +| Configurations | OS / ブラウザ / viewport | +| Starvation | 低メモリ / 低帯域 / バッテリー低下 | +| Dependencies | 上位/下位データ / 第三者 API | +| Touch Points | 通知 / メール / SMS への副作用 | +| Variable Analysis | 変数の生死範囲 / scope | +| **State** | 状態遷移とその境界 | +| Map Making | テスト対象の地図を描く (探索) | + +太字は Web E2E で見落としやすい必須項目。 + +## 11. 「揺らぎ排除」のための技法選択ルール + +AI / 人間が「思いつき」でテストを書かないように、**page role × データ型 → 必須技法** を以下に固定する。 + +``` +入力: page_role, data_type +出力: 必須技法のリスト + +(role, data) → techniques +───────────────────────────────────────── +(*, 数値) → BVA + EP +(*, 文字列) → BVA (長さ) + Domain (文字種) +(*, 日付) → Domain (日付セット) +(*, URL/path) → Domain (URL 種別) + Risk (open redirect) +(*, ファイル) → Domain (ファイル種別) +(form, *) → Decision Table 必須 +(checkout, 金額) → BVA + Decision Table (税/送料/クーポン) +(list, *) → EP (Count: 0/1/Many) +(search, クエリ) → Domain (clean/inj) + Claims (relevance) +(auth, 認証情報) → Decision Table + Risk (列挙/ロック) +(*, 状態を持つ操作) → State Transition +(*, 多次元組合せ) → Pairwise (All-Pairs) +(*, 仕様で主張あり) → Claims Testing +(*, IDOR/CSRF/XSS リスク) → Risk Testing +``` + +このマッピングは利用者が pytest テストを書く際の指針として使う。 +``@pytest.mark.parametrize`` で各境界値 / 各 row を test 関数として展開し、 +4 軸以上は事前に Pairwise で削減してから ``parametrize`` する運用を推奨する。 + +## 参考文献 + +- ISTQB CTFL Syllabus 4.2, "Black-box Test Techniques" +- Glenford Myers, "The Art of Software Testing" 3rd ed. +- Cem Kaner, "Domain Testing Workbook" +- Grimm/Grochtmann (1993), "Classification Trees for Partition Testing" +- Kuhn et al. (2004), "Software Fault Interactions and Implications for Software Testing", IEEE TSE +- Hendrickson/Lyndsay/Emery, "Test Heuristics Cheat Sheet", https://www.ministryoftesting.com/articles/test-heuristics-cheat-sheet +- James Bach, HTSM v6.3 diff --git a/plugins/ndf/skills-codex/playwright-test-planning/docs/04-playwright-mapping.md b/plugins/ndf/skills-codex/playwright-test-planning/docs/04-playwright-mapping.md new file mode 100644 index 00000000..24abddcb --- /dev/null +++ b/plugins/ndf/skills-codex/playwright-test-planning/docs/04-playwright-mapping.md @@ -0,0 +1,249 @@ +# 04. Playwright API → page role / 観点 マッピング + +「経験で API を選ぶ」のではなく、**page role × 観点 → 使う Playwright API** を一意に固定するための表。 +本 Skill のロケーター戦略・assertion 戦略・debug ツール選択は本書に従う。 + +## 1. ロケーター優先順位 (公式推奨) + +ユーザの操作意図を反映する a11y セマンティクスを最優先。 +**この順序を守ることがスキル全体の根幹。** CSS/XPath は禁忌。 + +| 優先度 | API (Python) | 用途 | コメント | +|---|---|---|---| +| 1 | `page.get_by_role(role, name=)` | 主要操作要素 (button/link/heading/textbox/listitem/dialog/tab/row/cell ...) | a11y role + accessible name | +| 2 | `page.get_by_label(text)` | フォーム要素 (`