From 5adf2825d95e473671904ddba8175f95817dad59 Mon Sep 17 00:00:00 2001 From: "takemi.ohama" Date: Sat, 8 Aug 2026 02:53:03 +0000 Subject: [PATCH 1/7] =?UTF-8?q?chore:=20feature/inventory-frontmatter=20?= =?UTF-8?q?=E3=81=AE=20Draft=20PR=20=E4=BD=9C=E6=88=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From ecc3b4935ca16915078149ecc222bde9fcfb21c4 Mon Sep 17 00:00:00 2001 From: "takemi.ohama" Date: Sat, 8 Aug 2026 04:16:29 +0000 Subject: [PATCH 2/7] =?UTF-8?q?Feat:=20Skill=20frontmatter=20=E3=81=AE?= =?UTF-8?q?=E8=A6=8F=E7=B4=84=E6=A4=9C=E6=9F=BB=E3=82=B9=E3=82=AF=E3=83=AA?= =?UTF-8?q?=E3=83=97=E3=83=88=E3=82=92=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit scripts/check-skill-frontmatter.py を新規作成した。検査は 3 種類に分かれる。 - individual: 仕様準拠 (name / description / compatibility)、安全性 (< >)、 可搬性 (発動条件の有無 / 二重引用符 / 先頭のトリガ語)、運用 (長さ / 行数 / 発動制御の組み合わせ / 未知の項目名) - aggregate: Codex の初期一覧予算と frontmatter 総量 - cross: Skill 間のトリガ語重複 判定が本質的に近似になる項目 (description 先頭のトリガ語、when_to_use の追加 トリガ、argument-hint の有無) は警告にとどめ、--strict で失敗させる。 現状の 33 Skill に対して 30 件のエラーを検出する。これらは本 PR の frontmatter 一括見直しで解消する。 --- scripts/check-skill-frontmatter.py | 361 +++++++++++++++++++++++++++++ 1 file changed, 361 insertions(+) create mode 100644 scripts/check-skill-frontmatter.py diff --git a/scripts/check-skill-frontmatter.py b/scripts/check-skill-frontmatter.py new file mode 100644 index 00000000..47232acd --- /dev/null +++ b/scripts/check-skill-frontmatter.py @@ -0,0 +1,361 @@ +#!/usr/bin/env python3 +"""Skill の frontmatter が執筆規約に適合しているかを検査する。 + +規約の本文は plugins/ndf-shared/skills/README.md にある。本スクリプトはそのうち +機械的に判定できる項目だけを検査し、継続的インテグレーションで実行する。 + +検査は 3 種類に分かれる。 + +- **individual** — Skill 単位。仕様準拠・安全性・可搬性・運用 +- **aggregate** — 全 Skill の合計。Codex の初期一覧予算と frontmatter 総量 +- **cross** — Skill 間。トリガ語の重複 + +判定が本質的に近似になる項目(description 先頭のトリガ語、when_to_use の追加トリガ)は +警告にとどめ、`--strict` を付けたときだけ失敗させる。 + +使い方: + + python3 scripts/check-skill-frontmatter.py + python3 scripts/check-skill-frontmatter.py --skills-dir plugins/ndf-shared/skills + python3 scripts/check-skill-frontmatter.py --strict + python3 scripts/check-skill-frontmatter.py --report # 実測値の一覧だけ出す +""" +from __future__ import annotations + +import argparse +import pathlib +import re +import sys + +# --- 規約の上限値 ----------------------------------------------------------- +# 出典は plugins/ndf-shared/skills/README.md「上限値」。 +NAME_MAX = 64 # Agent Skills 仕様 +DESCRIPTION_SPEC_MAX = 1024 # Agent Skills 仕様 +DESCRIPTION_OPS_MAX = 300 # 運用目標 +DESC_LEAD_CHARS = 160 # この範囲に用途またはトリガ語を置く(Codex の短縮対策) +COMPATIBILITY_MAX = 500 # Agent Skills 仕様 +DESC_PLUS_WTU_MAX = 1536 # Claude Code の一覧切り詰め +SKILL_MD_MAX_LINES = 500 # 仕様の推奨 / コンパクション対策 +CODEX_LISTING_MAX = 8000 # Codex の初期一覧予算(コンテキスト長不明時) +FRONTMATTER_TOTAL_MAX = 12000 # 全 Skill の frontmatter 合計。棚卸完了時の実測を基準に設定 + +# --- 許可する frontmatter の項目 ------------------------------------------- +# Agent Skills 仕様の 6 項目 + Claude Code 独自項目。 +# 未知の項目はハイフン誤り(when-to-use など)を弾くために失敗させる。 +SPEC_KEYS = {"name", "description", "license", "compatibility", "metadata", "allowed-tools"} +CLAUDE_KEYS = { + "when_to_use", "argument-hint", "arguments", "disable-model-invocation", + "user-invocable", "paths", "effort", "context", "background", "agent", "model", +} +ALLOWED_KEYS = SPEC_KEYS | CLAUDE_KEYS + +NAME_RE = re.compile(r"^[a-z0-9]+(?:-[a-z0-9]+)*$") +FRONT_MATTER_RE = re.compile(r"\A---\s*\n(.*?)\n---\s*\n", re.DOTALL) +KEY_RE = re.compile(r"^([A-Za-z][A-Za-z0-9_-]*):\s*(.*)$") +QUOTED_RE = re.compile(r"['\"]([^'\"]+)['\"]") +TRIGGER_LABEL_RE = re.compile( + r"(?:Triggers?|明示トリガ|トリガー?)\s*[::]\s*(.+)", re.IGNORECASE | re.DOTALL +) +# 「いつ使うか」を示す語。description にこれが無いと Codex / Kiro で発動判定できない。 +USE_WHEN_RE = re.compile(r"Use\s+when|use\s+when|使う|使い|とき|時に|ときに") +SENTENCE_SPLIT_RE = re.compile(r"(?<=[.。])\s*") + + +class Finding: + __slots__ = ("skill", "level", "code", "message") + + def __init__(self, skill: str, level: str, code: str, message: str) -> None: + self.skill = skill + self.level = level + self.code = code + self.message = message + + def __str__(self) -> str: + mark = "ERROR" if self.level == "error" else "WARN " + return f"{mark} [{self.code}] {self.skill}: {self.message}" + + +def parse_front_matter(text: str) -> tuple[dict[str, str], str] | tuple[None, str]: + """frontmatter を {key: 生の値} と生ブロックの組で返す。 + + 値は引用符を外さずそのまま保持する。二重引用符の有無を検査するため。 + リスト値(allowed-tools 等)は改行区切りの文字列にまとめる。 + """ + m = FRONT_MATTER_RE.match(text) + if not m: + return None, "" + block = m.group(1) + out: dict[str, str] = {} + key: str | None = None + buf: list[str] = [] + for line in block.splitlines(): + km = KEY_RE.match(line) + if km: + if key is not None: + out[key] = "\n".join(buf).strip() + key = km.group(1) + buf = [km.group(2)] + elif key is not None: + buf.append(line.strip()) + if key is not None: + out[key] = "\n".join(buf).strip() + return out, block + + +def unquote(value: str) -> str: + v = value.strip() + if len(v) >= 2 and v[0] == v[-1] and v[0] in "\"'": + return v[1:-1] + return v + + +def extract_triggers(*fields: str) -> list[str]: + """`Triggers:` / `明示トリガ:` 以降に列挙された引用符付きの語を集める。""" + triggers: list[str] = [] + for field in fields: + if not field: + continue + m = TRIGGER_LABEL_RE.search(field) + if not m: + continue + triggers.extend(q.strip() for q in QUOTED_RE.findall(m.group(1))) + seen: set[str] = set() + out: list[str] = [] + for t in triggers: + k = t.lower() + if k and k not in seen: + seen.add(k) + out.append(t) + return out + + +def load_skills(skills_dir: pathlib.Path) -> list[dict]: + skills: list[dict] = [] + for d in sorted(skills_dir.iterdir()): + f = d / "SKILL.md" + if not d.is_dir() or not f.exists(): + continue + text = f.read_text(encoding="utf-8", errors="replace") + fm, block = parse_front_matter(text) + skills.append({ + "dir": d.name, + "path": f, + "fm": fm, + "block": block, + "lines": len(text.splitlines()), + }) + return skills + + +def check_skill(s: dict) -> list[Finding]: + name_hint = s["dir"] + fm = s["fm"] + if fm is None: + return [Finding(name_hint, "error", "spec/frontmatter", "frontmatter がない")] + + out: list[Finding] = [] + add = lambda level, code, msg: out.append(Finding(name_hint, level, code, msg)) + + raw_desc = fm.get("description", "") + desc = unquote(raw_desc) + raw_wtu = fm.get("when_to_use", "") + wtu = unquote(raw_wtu) + name = unquote(fm.get("name", "")) + + # --- 仕様準拠 --- + if not name: + add("error", "spec/name", "name がない") + else: + if name != s["dir"]: + add("error", "spec/name", f"name '{name}' が親ディレクトリ名 '{s['dir']}' と一致しない") + if len(name) > NAME_MAX: + add("error", "spec/name", f"name が {len(name)} 文字(上限 {NAME_MAX})") + if not NAME_RE.match(name): + add("error", "spec/name", + f"name '{name}' は小文字英数とハイフンのみ・先頭末尾ハイフン不可・連続ハイフン不可") + + if not desc: + add("error", "spec/description", "description がない、または空") + elif len(desc) > DESCRIPTION_SPEC_MAX: + add("error", "spec/description", f"description が {len(desc)} 文字(仕様上限 {DESCRIPTION_SPEC_MAX})") + + compat = unquote(fm.get("compatibility", "")) + if len(compat) > COMPATIBILITY_MAX: + add("error", "spec/compatibility", f"compatibility が {len(compat)} 文字(上限 {COMPATIBILITY_MAX})") + + # --- 安全性 --- + # Agent Skills 仕様がシステムプロンプトへの注入リスクとして警告している。 + if "<" in s["block"] or ">" in s["block"]: + bad = [k for k, v in fm.items() if "<" in v or ">" in v] + add("error", "safety/angle-bracket", + f"frontmatter に < または > が含まれる({', '.join(bad) or '不明'})") + + # --- 可搬性 --- + # Codex と Kiro は when_to_use を読まないため、発動条件は description に要る。 + if desc and not USE_WHEN_RE.search(desc): + add("error", "portability/use-when", + "description に発動条件を示す語(Use when / 使う / とき)がない") + if raw_desc and not raw_desc.startswith('"'): + add("error", "portability/quote", + "description が二重引用符で囲まれていない(Kiro が未引用のコロンで検出に失敗する)") + if desc: + # Codex は初期一覧が予算を超えると description を先頭から残して短縮する。 + # 「いつ使うか」が後半にしかないと、短縮後は暗黙起動の判定に届かない。 + # 厳密な判定はできないため、先頭 DESC_LEAD_CHARS 文字の中に用途を示す語か + # 宣言トリガ語のどちらかが現れることを目安にする。 + lead = desc[:DESC_LEAD_CHARS] + triggers = extract_triggers(desc, wtu) + has_trigger = any(t.lower() in lead.lower() for t in triggers) + if not has_trigger and not USE_WHEN_RE.search(lead): + add("warn", "portability/lead", + f"description の先頭 {DESC_LEAD_CHARS} 文字に用途もトリガ語も現れない" + "(Codex は予算超過時に description を先頭から残して短縮する)") + + # --- 運用 --- + if len(desc) > DESCRIPTION_OPS_MAX: + add("error", "ops/description-length", + f"description が {len(desc)} 文字(運用上限 {DESCRIPTION_OPS_MAX})") + if len(desc) + len(wtu) > DESC_PLUS_WTU_MAX: + add("error", "ops/desc-plus-wtu", + f"description + when_to_use が {len(desc) + len(wtu)} 文字(上限 {DESC_PLUS_WTU_MAX})") + if s["lines"] > SKILL_MD_MAX_LINES: + add("error", "ops/skill-lines", f"SKILL.md が {s['lines']} 行(上限 {SKILL_MD_MAX_LINES})") + + if wtu: + # when_to_use は「Claude Code 向けの追加トリガ」がある場合だけ付ける。 + # description のトリガ語を並べ替えただけのものは、その根拠を持たない。 + d_trigs = {t.lower() for t in extract_triggers(desc)} + w_trigs = {t.lower() for t in extract_triggers(wtu)} + if w_trigs and not (w_trigs - d_trigs): + add("warn", "ops/wtu-no-extra", + "when_to_use のトリガ語が description と同一で、追加トリガがない") + + dmi = unquote(fm.get("disable-model-invocation", "")).lower() == "true" + uinv = unquote(fm.get("user-invocable", "")).lower() == "false" + if dmi and uinv: + add("error", "ops/uninvocable", + "disable-model-invocation: true と user-invocable: false の同時指定は誰も起動できない") + if dmi and not fm.get("argument-hint"): + add("warn", "ops/argument-hint", + "disable-model-invocation があるのに argument-hint がない(明示起動時の引数が伝わらない)") + + ctx = unquote(fm.get("context", "")) + for k in ("agent", "background"): + if k in fm and ctx != "fork": + add("error", "ops/context-fork", f"{k} は context: fork のときだけ指定できる") + + unknown = sorted(set(fm) - ALLOWED_KEYS) + if unknown: + add("error", "ops/unknown-key", f"未知の項目名: {', '.join(unknown)}") + + return out + + +def check_aggregate(skills: list[dict], skills_dir: pathlib.Path) -> tuple[list[Finding], dict]: + """Codex の初期一覧予算と frontmatter 総量を検査する。 + + Codex は起動時に name / description / ファイルパスを一覧として読み込み、 + この一覧に総量予算を設けている(超過すると description を短縮し、なお超えると + Skill を一覧から省略して警告を出す)。 + """ + listing = 0 + fm_total = 0 + for s in skills: + fm = s["fm"] or {} + name = unquote(fm.get("name", s["dir"])) + desc = unquote(fm.get("description", "")) + rel = f"{skills_dir.name}/{s['dir']}/SKILL.md" + listing += len(name) + len(desc) + len(rel) + fm_total += len(s["block"]) + + out: list[Finding] = [] + if listing > CODEX_LISTING_MAX: + out.append(Finding("(全体)", "error", "ops/codex-listing", + f"Codex の初期一覧に載る合計が {listing} 文字(上限 {CODEX_LISTING_MAX})")) + if fm_total > FRONTMATTER_TOTAL_MAX: + out.append(Finding("(全体)", "error", "ops/frontmatter-total", + f"全 Skill の frontmatter 合計が {fm_total} 文字(上限 {FRONTMATTER_TOTAL_MAX})")) + return out, {"codex_listing": listing, "frontmatter_total": fm_total} + + +def check_trigger_collisions(skills: list[dict]) -> list[Finding]: + """同じトリガ語を複数の Skill が宣言していないかを検査する。 + + 重複すると同じ依頼で複数の Skill が起動を競い、どちらが選ばれるかが + 依頼文の細部に左右される。 + """ + owners: dict[str, list[str]] = {} + for s in skills: + fm = s["fm"] or {} + trigs = extract_triggers(unquote(fm.get("description", "")), + unquote(fm.get("when_to_use", ""))) + for t in trigs: + owners.setdefault(t.lower(), []).append(s["dir"]) + out: list[Finding] = [] + for trig, names in sorted(owners.items()): + uniq = sorted(set(names)) + if len(uniq) > 1: + out.append(Finding(", ".join(uniq), "error", "ops/trigger-collision", + f"トリガ語 '{trig}' が複数の Skill で重複している")) + return out + + +def main() -> int: + ap = argparse.ArgumentParser(description=__doc__, + formatter_class=argparse.RawDescriptionHelpFormatter) + ap.add_argument("--skills-dir", default="plugins/ndf-shared/skills", + help="検査対象の Skill ディレクトリ(default: %(default)s)") + ap.add_argument("--strict", action="store_true", + help="警告も失敗として扱う") + ap.add_argument("--report", action="store_true", + help="判定せず実測値の一覧だけ出力する") + args = ap.parse_args() + + skills_dir = pathlib.Path(args.skills_dir) + if not skills_dir.is_dir(): + print(f"[check-skill-frontmatter] ディレクトリがない: {skills_dir}", file=sys.stderr) + return 2 + + skills = load_skills(skills_dir) + if not skills: + print(f"[check-skill-frontmatter] SKILL.md が見つからない: {skills_dir}", file=sys.stderr) + return 2 + + findings: list[Finding] = [] + for s in skills: + findings.extend(check_skill(s)) + agg, metrics = check_aggregate(skills, skills_dir) + findings.extend(agg) + findings.extend(check_trigger_collisions(skills)) + + if args.report: + print(f"{'skill':34} {'lines':>5} {'desc':>5} {'wtu':>5} flags") + for s in sorted(skills, key=lambda x: x["dir"]): + fm = s["fm"] or {} + flags = [k for k in ("disable-model-invocation", "user-invocable", "paths", + "effort", "context", "arguments", "license") + if k in fm] + print(f"{s['dir']:34} {s['lines']:>5} " + f"{len(unquote(fm.get('description', ''))):>5} " + f"{len(unquote(fm.get('when_to_use', ''))):>5} {','.join(flags)}") + print(f"\nSkill 数: {len(skills)}") + print(f"Codex 初期一覧の合計: {metrics['codex_listing']} 文字 (上限 {CODEX_LISTING_MAX})") + print(f"frontmatter 合計: {metrics['frontmatter_total']} 文字 (上限 {FRONTMATTER_TOTAL_MAX})") + return 0 + + errors = [f for f in findings if f.level == "error"] + warns = [f for f in findings if f.level == "warn"] + for f in sorted(findings, key=lambda x: (x.level != "error", x.skill, x.code)): + print(str(f), file=sys.stderr if f.level == "error" else sys.stdout) + + print(f"\nSkill {len(skills)} 個を検査 — エラー {len(errors)} 件 / 警告 {len(warns)} 件") + print(f"Codex 初期一覧の合計: {metrics['codex_listing']} / {CODEX_LISTING_MAX} 文字") + print(f"frontmatter 合計: {metrics['frontmatter_total']} / {FRONTMATTER_TOTAL_MAX} 文字") + + if errors or (args.strict and warns): + return 1 + return 0 + + +if __name__ == "__main__": + sys.exit(main()) From f73158dd515c7891eb3617d4adca71149aa574c4 Mon Sep 17 00:00:00 2001 From: "takemi.ohama" Date: Sat, 8 Aug 2026 04:42:23 +0000 Subject: [PATCH 3/7] =?UTF-8?q?Feat:=20=E6=A4=9C=E6=9F=BB=E3=82=B9?= =?UTF-8?q?=E3=82=AF=E3=83=AA=E3=83=97=E3=83=88=E3=82=92=E8=A6=8F=E7=B4=84?= =?UTF-8?q?=E3=81=AE=E6=9C=80=E7=B5=82=E5=BD=A2=E3=81=B8=E5=90=88=E3=82=8F?= =?UTF-8?q?=E3=81=9B=E3=82=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 初期一覧の予算を配布先ごとに manifest から計算する。Claude Code は 1 項目 250 文字で切り詰めてから積む仕様を反映した - Codex / Kiro は disable-model-invocation と user-invocable を解釈しないため、 明示指示専用と常時注入の Skill は description 自体に意図を書き残す必要がある。 これを portability/explicit-only と portability/inject-only として検査する - description 先頭のトリガ語判定を「最初の 1 文」から「先頭 160 文字」に緩めた --- scripts/check-skill-frontmatter.py | 65 ++++++++++++++++++++++++------ 1 file changed, 52 insertions(+), 13 deletions(-) diff --git a/scripts/check-skill-frontmatter.py b/scripts/check-skill-frontmatter.py index 47232acd..2636d0b7 100644 --- a/scripts/check-skill-frontmatter.py +++ b/scripts/check-skill-frontmatter.py @@ -7,7 +7,7 @@ 検査は 3 種類に分かれる。 - **individual** — Skill 単位。仕様準拠・安全性・可搬性・運用 -- **aggregate** — 全 Skill の合計。Codex の初期一覧予算と frontmatter 総量 +- **aggregate** — 配布先ごとの初期一覧予算(Claude Code / Codex)と frontmatter 総量 - **cross** — Skill 間。トリガ語の重複 判定が本質的に近似になる項目(description 先頭のトリガ語、when_to_use の追加トリガ)は @@ -37,6 +37,8 @@ DESC_PLUS_WTU_MAX = 1536 # Claude Code の一覧切り詰め SKILL_MD_MAX_LINES = 500 # 仕様の推奨 / コンパクション対策 CODEX_LISTING_MAX = 8000 # Codex の初期一覧予算(コンテキスト長不明時) +CLAUDE_LISTING_MAX = 8000 # Claude Code の初期一覧予算(コンテキスト長不明時) +CLAUDE_ITEM_TRUNCATE = 250 # Claude Code は 1 項目をこの長さで切り詰める FRONTMATTER_TOTAL_MAX = 12000 # 全 Skill の frontmatter 合計。棚卸完了時の実測を基準に設定 # --- 許可する frontmatter の項目 ------------------------------------------- @@ -230,6 +232,19 @@ def check_skill(s: dict) -> list[Finding]: add("warn", "ops/wtu-no-extra", "when_to_use のトリガ語が description と同一で、追加トリガがない") + # Codex と Kiro には disable-model-invocation / user-invocable がなく description は + # 常に読まれる。発動制御の意図を description 自体へ書き残す必要がある。 + if unquote(fm.get("disable-model-invocation", "")).lower() == "true": + if not re.search(r"明示|explicit|Explicit", desc): + add("error", "portability/explicit-only", + "明示指示専用の Skill は description に「利用者が明示的に指示したときのみ実行する」" + "旨を書く(Codex / Kiro は disable-model-invocation を解釈しない)") + if unquote(fm.get("user-invocable", "")).lower() == "false": + if not re.search(r"知識として|参照する|実行しない|reference only|do not execute", desc): + add("error", "portability/inject-only", + "常時注入のみの Skill は description に「知識として参照する。手順として実行しない」" + "旨を書く(Codex / Kiro は user-invocable を解釈しない)") + dmi = unquote(fm.get("disable-model-invocation", "")).lower() == "true" uinv = unquote(fm.get("user-invocable", "")).lower() == "false" if dmi and uinv: @@ -251,31 +266,52 @@ def check_skill(s: dict) -> list[Finding]: return out +def load_manifests(skills_dir: pathlib.Path) -> dict[str, set[str]]: + """manifests/-skills.txt を読み、配布先ごとの Skill 名集合を返す。""" + man_dir = skills_dir.parent / "manifests" + out: dict[str, set[str]] = {} + for runtime in ("claude", "codex", "kiro"): + f = man_dir / f"{runtime}-skills.txt" + if f.exists(): + out[runtime] = {line.strip() for line in f.read_text().split() if line.strip()} + return out + + def check_aggregate(skills: list[dict], skills_dir: pathlib.Path) -> tuple[list[Finding], dict]: - """Codex の初期一覧予算と frontmatter 総量を検査する。 + """初期一覧の予算と frontmatter 総量を検査する。 - Codex は起動時に name / description / ファイルパスを一覧として読み込み、 - この一覧に総量予算を設けている(超過すると description を短縮し、なお超えると - Skill を一覧から省略して警告を出す)。 + Claude Code と Codex は起動時に name / description / ファイルパスを一覧として + 読み込み、この一覧に総量予算を設けている(超過すると description を短縮し、 + なお超えると Skill を一覧から省略して警告を出す)。予算は配布先ごとに効くため、 + manifest に載っている Skill だけを数える。 """ - listing = 0 + manifests = load_manifests(skills_dir) + listings: dict[str, int] = {r: 0 for r in manifests} fm_total = 0 for s in skills: fm = s["fm"] or {} name = unquote(fm.get("name", s["dir"])) desc = unquote(fm.get("description", "")) rel = f"{skills_dir.name}/{s['dir']}/SKILL.md" - listing += len(name) + len(desc) + len(rel) fm_total += len(s["block"]) + for runtime, members in manifests.items(): + if s["dir"] not in members: + continue + # Claude Code は 1 項目を 250 文字で切り詰めてから積む。 + d = desc[:CLAUDE_ITEM_TRUNCATE] if runtime == "claude" else desc + listings[runtime] += len(name) + len(d) + len(rel) out: list[Finding] = [] - if listing > CODEX_LISTING_MAX: - out.append(Finding("(全体)", "error", "ops/codex-listing", - f"Codex の初期一覧に載る合計が {listing} 文字(上限 {CODEX_LISTING_MAX})")) + limits = {"claude": CLAUDE_LISTING_MAX, "codex": CODEX_LISTING_MAX, "kiro": None} + for runtime, total in sorted(listings.items()): + limit = limits.get(runtime) + if limit is not None and total > limit: + out.append(Finding("(全体)", "error", f"ops/{runtime}-listing", + f"{runtime} の初期一覧に載る合計が {total} 文字(上限 {limit})")) if fm_total > FRONTMATTER_TOTAL_MAX: out.append(Finding("(全体)", "error", "ops/frontmatter-total", f"全 Skill の frontmatter 合計が {fm_total} 文字(上限 {FRONTMATTER_TOTAL_MAX})")) - return out, {"codex_listing": listing, "frontmatter_total": fm_total} + return out, {"listings": listings, "frontmatter_total": fm_total} def check_trigger_collisions(skills: list[dict]) -> list[Finding]: @@ -339,7 +375,8 @@ def main() -> int: f"{len(unquote(fm.get('description', ''))):>5} " f"{len(unquote(fm.get('when_to_use', ''))):>5} {','.join(flags)}") print(f"\nSkill 数: {len(skills)}") - print(f"Codex 初期一覧の合計: {metrics['codex_listing']} 文字 (上限 {CODEX_LISTING_MAX})") + for runtime, total in sorted(metrics["listings"].items()): + print(f"{runtime} の初期一覧の合計: {total} 文字") print(f"frontmatter 合計: {metrics['frontmatter_total']} 文字 (上限 {FRONTMATTER_TOTAL_MAX})") return 0 @@ -349,7 +386,9 @@ def main() -> int: print(str(f), file=sys.stderr if f.level == "error" else sys.stdout) print(f"\nSkill {len(skills)} 個を検査 — エラー {len(errors)} 件 / 警告 {len(warns)} 件") - print(f"Codex 初期一覧の合計: {metrics['codex_listing']} / {CODEX_LISTING_MAX} 文字") + for runtime, total in sorted(metrics["listings"].items()): + limit = {"claude": CLAUDE_LISTING_MAX, "codex": CODEX_LISTING_MAX}.get(runtime) + print(f"{runtime} の初期一覧の合計: {total}" + (f" / {limit} 文字" if limit else " 文字")) print(f"frontmatter 合計: {metrics['frontmatter_total']} / {FRONTMATTER_TOTAL_MAX} 文字") if errors or (args.strict and warns): From 5b668a632c0bca0603a2d47b207442aaad95e4d1 Mon Sep 17 00:00:00 2001 From: "takemi.ohama" Date: Sat, 8 Aug 2026 05:13:53 +0000 Subject: [PATCH 4/7] =?UTF-8?q?Feat:=20=E5=85=A8=20Skill=20=E3=81=AE=20fro?= =?UTF-8?q?ntmatter=20=E3=82=92=E8=A6=8F=E7=B4=84=E3=81=B8=E6=8F=83?= =?UTF-8?q?=E3=81=88=E6=A4=9C=E6=9F=BB=E3=82=92=20CI=20=E3=81=B8=E7=B5=84?= =?UTF-8?q?=E3=81=BF=E8=BE=BC=E3=82=80=20(0-7)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `plugins/ndf-shared/skills/README.md` の frontmatter 規約に対し、全 29 Skill を `scripts/check-skill-frontmatter.py` がエラー 0 件 / 警告 0 件で通る状態へ揃えた。 - 発動制御: `merged` / `pr` / `review` / `pr-tests` から `disable-model-invocation` を外した。いずれも日常的に自然文で依頼されるため。`deploy` / `cherry-pick-pr` / `statusline` は書き込みを伴うため明示指示専用を維持し、Codex / Kiro が同キーを 解釈しないことを踏まえて `description` に明示指示専用である旨を書いた - `description`: 全 Skill を「何をするか + Use when + Triggers」の形へ書き直し、 用途とトリガ語を先頭 160 文字へ置いた。`when_to_use` は Claude Code 限定配布の `official-skills-autoloader` だけに残した。3 ランタイムへ配る Skill のトリガ語を `when_to_use` へ置くと Codex / Kiro で発動判定に効かないため - トリガ語: `investigation-rules` の `調査` などの広すぎる語を具体化し、 `playwright-evidence` と `playwright-kit-ops` の `upload_evidence` 重複を解消した - `paths` を `ml-model-structure`(`analysis/**`)へ、`effort: high` を `review` へ付与 - `deploy` / `cherry-pick-pr` の `argument-hint` から `<` `>` を除去した - 配布されていなかった `qa-security-scan` を 3 ランタイムへ、 `official-skills-autoloader` を Claude Code へ配布対象として追加した。台帳の 発動改善判定は配布されていない状態では効かないため - `FRONTMATTER_TOTAL_MAX` を実測 12,145 文字に約 7% の余裕を足した 13,000 で確定した - `.github/workflows/runtime-plugin-validate.yml` へ検査ジョブを追加した 検査スクリプトの変更(理由つき): - `ops/argument-hint` を警告から失敗へ変更した。近似判定ではなく機械的に判定でき、 計画(Task 0-7 の検査項目表)でも失敗条件として挙げられているため - manifest の読み取りで行末の `#` 以降をコメントとして落とすようにした。 `scripts/build-runtime-plugins.sh` の解釈と揃っておらず、コメント付き manifest では 配布先の判定が実際のビルド結果とずれるため Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_01AGejnYyYFuSkQjBhW2KQNy --- .github/workflows/runtime-plugin-validate.yml | 9 + docs/specifications/ndf-skill-inventory.md | 46 +++ .../ndf-claude/skills/cherry-pick-pr/SKILL.md | 4 +- .../ndf-claude/skills/cross-review/SKILL.md | 3 +- plugins/ndf-claude/skills/deploy/SKILL.md | 4 +- .../skills/docker-container-access/SKILL.md | 3 +- .../ndf-claude/skills/external-ai/SKILL.md | 3 +- plugins/ndf-claude/skills/fix/SKILL.md | 3 +- .../skills/implementation-plan/SKILL.md | 3 +- .../skills/investigation-rules/SKILL.md | 3 +- .../skills/issue-plan-strategy/SKILL.md | 3 +- .../skills/logging-guidelines/SKILL.md | 2 +- .../skills/markdown-writing/SKILL.md | 3 +- plugins/ndf-claude/skills/merged/SKILL.md | 3 +- .../ndf-claude/skills/ndf-policies/SKILL.md | 2 +- .../official-skills-autoloader/SKILL.md | 128 ++++++++ .../ndf-claude/skills/plan-to-spec/SKILL.md | 2 +- .../skills/playwright-authoring/SKILL.md | 3 +- plugins/ndf-claude/skills/pr-tests/SKILL.md | 3 +- plugins/ndf-claude/skills/pr/SKILL.md | 3 +- .../skills/problem-solving/SKILL.md | 3 +- .../qa-security-scan/01-owasp-checklist.md | 298 ++++++++++++++++++ .../qa-security-scan/02-auth-checklist.md | 127 ++++++++ .../qa-security-scan/03-report-template.md | 144 +++++++++ .../skills/qa-security-scan/SKILL.md | 55 ++++ plugins/ndf-claude/skills/review/SKILL.md | 5 +- plugins/ndf-claude/skills/statusline/SKILL.md | 4 +- .../ndf-codex/skills/cherry-pick-pr/SKILL.md | 4 +- .../ndf-codex/skills/cross-review/SKILL.md | 3 +- plugins/ndf-codex/skills/deploy/SKILL.md | 4 +- .../skills/docker-container-access/SKILL.md | 3 +- plugins/ndf-codex/skills/external-ai/SKILL.md | 3 +- plugins/ndf-codex/skills/fix/SKILL.md | 3 +- .../skills/implementation-plan/SKILL.md | 3 +- .../skills/investigation-rules/SKILL.md | 3 +- .../skills/issue-plan-strategy/SKILL.md | 3 +- .../skills/logging-guidelines/SKILL.md | 2 +- .../skills/markdown-writing/SKILL.md | 3 +- plugins/ndf-codex/skills/merged/SKILL.md | 3 +- .../ndf-codex/skills/ndf-policies/SKILL.md | 2 +- .../ndf-codex/skills/plan-to-spec/SKILL.md | 2 +- .../skills/playwright-authoring/SKILL.md | 3 +- .../skills/playwright-evidence/SKILL.md | 3 +- .../skills/playwright-kit-ops/SKILL.md | 3 +- .../skills/playwright-planning/SKILL.md | 3 +- plugins/ndf-codex/skills/pr-tests/SKILL.md | 3 +- plugins/ndf-codex/skills/pr/SKILL.md | 3 +- .../ndf-codex/skills/problem-solving/SKILL.md | 3 +- .../qa-security-scan/01-owasp-checklist.md | 298 ++++++++++++++++++ .../qa-security-scan/02-auth-checklist.md | 127 ++++++++ .../qa-security-scan/03-report-template.md | 144 +++++++++ .../skills/qa-security-scan/SKILL.md | 55 ++++ plugins/ndf-codex/skills/review/SKILL.md | 5 +- .../ndf-kiro/skills/cherry-pick-pr/SKILL.md | 4 +- plugins/ndf-kiro/skills/cross-review/SKILL.md | 3 +- plugins/ndf-kiro/skills/deploy/SKILL.md | 4 +- .../skills/docker-container-access/SKILL.md | 3 +- plugins/ndf-kiro/skills/external-ai/SKILL.md | 3 +- plugins/ndf-kiro/skills/fix/SKILL.md | 3 +- .../skills/implementation-plan/SKILL.md | 3 +- .../skills/investigation-rules/SKILL.md | 3 +- .../skills/issue-plan-strategy/SKILL.md | 3 +- .../skills/logging-guidelines/SKILL.md | 2 +- .../ndf-kiro/skills/markdown-writing/SKILL.md | 3 +- plugins/ndf-kiro/skills/merged/SKILL.md | 3 +- plugins/ndf-kiro/skills/ndf-policies/SKILL.md | 2 +- plugins/ndf-kiro/skills/plan-to-spec/SKILL.md | 2 +- .../skills/playwright-authoring/SKILL.md | 3 +- plugins/ndf-kiro/skills/pr-tests/SKILL.md | 3 +- plugins/ndf-kiro/skills/pr/SKILL.md | 3 +- .../ndf-kiro/skills/problem-solving/SKILL.md | 3 +- .../qa-security-scan/01-owasp-checklist.md | 298 ++++++++++++++++++ .../qa-security-scan/02-auth-checklist.md | 127 ++++++++ .../qa-security-scan/03-report-template.md | 144 +++++++++ .../ndf-kiro/skills/qa-security-scan/SKILL.md | 55 ++++ plugins/ndf-kiro/skills/review/SKILL.md | 5 +- plugins/ndf-kiro/skills/statusline/SKILL.md | 4 +- .../ndf-shared/manifests/claude-skills.txt | 2 + plugins/ndf-shared/manifests/codex-skills.txt | 1 + plugins/ndf-shared/manifests/kiro-skills.txt | 1 + plugins/ndf-shared/skills/README.md | 17 +- .../ndf-shared/skills/cherry-pick-pr/SKILL.md | 4 +- .../ndf-shared/skills/cross-review/SKILL.md | 3 +- plugins/ndf-shared/skills/deploy/SKILL.md | 4 +- .../skills/docker-container-access/SKILL.md | 3 +- .../ndf-shared/skills/external-ai/SKILL.md | 3 +- plugins/ndf-shared/skills/fix/SKILL.md | 3 +- .../ndf-shared/skills/google-auth/SKILL.md | 3 +- .../ndf-shared/skills/google-drive/SKILL.md | 3 +- .../skills/implementation-plan/SKILL.md | 3 +- .../skills/investigation-rules/SKILL.md | 3 +- .../skills/issue-plan-strategy/SKILL.md | 3 +- .../skills/logging-guidelines/SKILL.md | 2 +- .../skills/markdown-writing/SKILL.md | 3 +- plugins/ndf-shared/skills/merged/SKILL.md | 3 +- .../skills/ml-model-structure/SKILL.md | 5 +- .../ndf-shared/skills/ndf-policies/SKILL.md | 2 +- .../official-skills-autoloader/SKILL.md | 5 +- .../ndf-shared/skills/plan-to-spec/SKILL.md | 2 +- .../skills/playwright-authoring/SKILL.md | 3 +- .../skills/playwright-evidence/SKILL.md | 3 +- .../skills/playwright-kit-ops/SKILL.md | 3 +- .../skills/playwright-planning/SKILL.md | 3 +- plugins/ndf-shared/skills/pr-tests/SKILL.md | 3 +- plugins/ndf-shared/skills/pr/SKILL.md | 3 +- .../skills/problem-solving/SKILL.md | 3 +- .../skills/qa-security-scan/SKILL.md | 4 +- plugins/ndf-shared/skills/review/SKILL.md | 5 +- .../ndf-shared/skills/skill-stats/SKILL.md | 3 +- plugins/ndf-shared/skills/statusline/SKILL.md | 4 +- scripts/check-skill-frontmatter.py | 26 +- 111 files changed, 2203 insertions(+), 184 deletions(-) create mode 100644 plugins/ndf-claude/skills/official-skills-autoloader/SKILL.md create mode 100644 plugins/ndf-claude/skills/qa-security-scan/01-owasp-checklist.md create mode 100644 plugins/ndf-claude/skills/qa-security-scan/02-auth-checklist.md create mode 100644 plugins/ndf-claude/skills/qa-security-scan/03-report-template.md create mode 100644 plugins/ndf-claude/skills/qa-security-scan/SKILL.md create mode 100644 plugins/ndf-codex/skills/qa-security-scan/01-owasp-checklist.md create mode 100644 plugins/ndf-codex/skills/qa-security-scan/02-auth-checklist.md create mode 100644 plugins/ndf-codex/skills/qa-security-scan/03-report-template.md create mode 100644 plugins/ndf-codex/skills/qa-security-scan/SKILL.md create mode 100644 plugins/ndf-kiro/skills/qa-security-scan/01-owasp-checklist.md create mode 100644 plugins/ndf-kiro/skills/qa-security-scan/02-auth-checklist.md create mode 100644 plugins/ndf-kiro/skills/qa-security-scan/03-report-template.md create mode 100644 plugins/ndf-kiro/skills/qa-security-scan/SKILL.md diff --git a/.github/workflows/runtime-plugin-validate.yml b/.github/workflows/runtime-plugin-validate.yml index 2b6a2cda..ebc8b986 100644 --- a/.github/workflows/runtime-plugin-validate.yml +++ b/.github/workflows/runtime-plugin-validate.yml @@ -44,6 +44,15 @@ jobs: python-version: "3.x" - run: bash scripts/build-runtime-plugins.sh --check + skill-frontmatter-check: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-python@v5 + with: + python-version: "3.x" + - run: python3 scripts/check-skill-frontmatter.py + runtime-plugin-validate: runs-on: ubuntu-latest steps: diff --git a/docs/specifications/ndf-skill-inventory.md b/docs/specifications/ndf-skill-inventory.md index 4cc4bb02..0c1939e8 100644 --- a/docs/specifications/ndf-skill-inventory.md +++ b/docs/specifications/ndf-skill-inventory.md @@ -163,6 +163,52 @@ merged, ndf-policies, pr, pr-tests, resolve-pr-comments, review, sync-main `deploy` へのトリガ語宣言と `qa-security-scan` のトリガ語見直しののち再測定することを、 frontmatter 見直し後の確認項目とする。 +## frontmatter 見直しの結果 + +[棚卸の計画](../../issues/ndf-development-skills/07-tasks.md) の Task 0-7 で全 29 Skill の +frontmatter を [規約](../../plugins/ndf-shared/skills/README.md) へ揃えた。台帳の表は測定日 +時点の値であり、以下の変更は表へ反映していない。 + +### 発動制御 + +| Skill | 変更 | 理由 | +| --- | --- | --- | +| `merged` / `pr` / `review` / `pr-tests` | `disable-model-invocation` を削除 | 日常的に自然文で依頼されるため。明示指示専用のままではエージェントが Skill を使わず独自手順で実行する | +| `deploy` / `cherry-pick-pr` / `statusline` | 明示指示専用を維持 | 環境ブランチへの書き込みと設定ファイルの書き換えを伴う。`description` に「利用者が明示的に指示したときのみ実行する」と明記し、Codex / Kiro でも意図が伝わるようにした | +| `ndf-policies` | `user-invocable: false` を維持 | `description` に「知識として参照するだけで、手順として実行しない」と明記した | + +### 配布先 + +| Skill | 台帳の配布 | 変更後 | 理由 | +| --- | --- | --- | --- | +| `qa-security-scan` | — | CXK | 発動改善の判定はどこにも配布されていない状態では効かない。ランタイム非依存の判断基準であり 3 種すべてへ配る | +| `official-skills-autoloader` | — | C | 同上。ただし取得先が `~/.claude/skills/` のため Claude Code 限定 | + +### トリガ語 + +- 広すぎるトリガを具体化した。`investigation-rules` の `調査` → `調査レポートを書く`、 + `implementation-plan` の `PR作成` を削除して `pr` へ寄せる、`markdown-writing` の + `仕様書` → `仕様書を書く`、`problem-solving` の `バグ修正` → `バグの根本原因` +- `playwright-evidence` と `playwright-kit-ops` で重複していた `upload_evidence` を解消した。 + スクリプトを持つ `playwright-kit-ops` 側に `upload_evidence.py` として残し、 + `playwright-evidence` は `エビデンスをDriveへ保管` に置き換えた +- `deploy` と `cherry-pick-pr` はトリガ語を宣言していなかったため新たに宣言した。 + 次回の `/ndf:skill-stats` で両者の機会を測定できる + +### 実測値 + +| 項目 | 見直し前 | 見直し後 | 上限 | +| --- | ---: | ---: | ---: | +| 検査エラー | 33 | 0 | 0 | +| 検査警告 | 16 | 0 | — | +| `description` 最大 | 401 | 288 | 300 | +| Claude Code 初期一覧 | 3,133 | 6,029 | 8,000 | +| Codex 初期一覧 | 3,933 | 6,466 | 8,000 | +| frontmatter 合計 | 12,724 | 12,145 | 13,000 | + +初期一覧の合計が増えているのは、`when_to_use` に置いていたトリガ語を `description` へ移し、 +Codex と Kiro でも発動判定に効くようにしたためである。 + ## 参照 - 棚卸の計画: [issues/ndf-development-skills/02-skill-inventory.md](../../issues/ndf-development-skills/02-skill-inventory.md) diff --git a/plugins/ndf-claude/skills/cherry-pick-pr/SKILL.md b/plugins/ndf-claude/skills/cherry-pick-pr/SKILL.md index 1de3823b..4228d90d 100644 --- a/plugins/ndf-claude/skills/cherry-pick-pr/SKILL.md +++ b/plugins/ndf-claude/skills/cherry-pick-pr/SKILL.md @@ -1,7 +1,7 @@ --- name: cherry-pick-pr -description: "Create cherry-pick PRs for environment branches and apply the same fix across multiple branches." -argument-hint: " (例: qa/staging, release/v2)" +description: "Cherry-pick a merged fix onto environment branches (qa/staging, release) as a new PR. 破壊的操作のため、利用者が /ndf:cherry-pick-pr を明示的に指示したときのみ実行する。Triggers: 'cherry-pick', 'qaにも同じ修正を適用', 'stagingにも反映', 'release branchへ適用', 'multi-branch fix'" +argument-hint: "ベースブランチ名 (例: qa/staging, release/v2)" disable-model-invocation: true allowed-tools: - Bash diff --git a/plugins/ndf-claude/skills/cross-review/SKILL.md b/plugins/ndf-claude/skills/cross-review/SKILL.md index 2472f576..31357abd 100644 --- a/plugins/ndf-claude/skills/cross-review/SKILL.md +++ b/plugins/ndf-claude/skills/cross-review/SKILL.md @@ -1,7 +1,6 @@ --- name: cross-review -description: "Run iterative Codex and Gemini PR reviews." -when_to_use: "PR を codex + gemini 両方でレビューし、両者 APPROVE まで自動収束させたいときに限定して使う。明示トリガ: 'cross-review', 'クロスレビュー', '両AIレビュー', '収束レビュー', 'codex と gemini でレビュー'。通常の単発 PR レビュー依頼 (第二意見が 1 回欲しい等) は本 skill を選ばず /ndf:review を使う。重い収束ループ (codex+gemini を複数ラウンド起動) のため、単発レビューと責務を明確に分ける。" +description: "Review a PR with both Codex and Gemini, looping fixes until both APPROVE. Use when a converging two-AI review is wanted; for a one-shot second opinion use /ndf:review. Triggers: 'cross-review', 'クロスレビュー', '両AIレビュー', '収束レビュー', 'codex と gemini でレビュー'" argument-hint: "[PR番号] [--max-rounds N] [--rotate-after K] [--rotate-mode light|squash] [--only codex|gemini] [--focus TEXT] [--extra-instructions-file PATH]" allowed-tools: - Bash diff --git a/plugins/ndf-claude/skills/deploy/SKILL.md b/plugins/ndf-claude/skills/deploy/SKILL.md index 8bca071b..c4baa425 100644 --- a/plugins/ndf-claude/skills/deploy/SKILL.md +++ b/plugins/ndf-claude/skills/deploy/SKILL.md @@ -1,7 +1,7 @@ --- name: deploy -description: "Create a deploy PR from the current feature branch to an environment branch such as qa/staging or release/v2. 破壊的操作のため、利用者が /ndf:deploy を明示的に指示したときのみ実行する(環境ブランチへデプロイ / qaに上げる / stagingに反映 / リリースブランチへPR)。deployブランチを作成し origin/main を取り込んでからPRを出す。" -argument-hint: " (例: qa/staging, release/v2)" +description: "Create a deploy PR from the current feature branch to an environment branch such as qa/staging or release/v2. 破壊的操作のため、利用者が /ndf:deploy を明示的に指示したときのみ実行する。Triggers: '環境ブランチへデプロイ', 'qaに上げる', 'stagingへデプロイ', 'リリースブランチへPR'" +argument-hint: "環境ブランチ名 (例: qa/staging, release/v2)" disable-model-invocation: true allowed-tools: - Bash diff --git a/plugins/ndf-claude/skills/docker-container-access/SKILL.md b/plugins/ndf-claude/skills/docker-container-access/SKILL.md index 444a993f..bd464ca9 100644 --- a/plugins/ndf-claude/skills/docker-container-access/SKILL.md +++ b/plugins/ndf-claude/skills/docker-container-access/SKILL.md @@ -1,7 +1,6 @@ --- 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'" +description: "Diagnose Docker container access and localhost routing failures. Use when a container is unreachable, localhost does not connect, or DinD/DooD has to be identified. Triggers: 'localhost not working', 'コンテナに接続できない', 'DinD', 'DooD', 'curl container'" allowed-tools: - Read - Bash diff --git a/plugins/ndf-claude/skills/external-ai/SKILL.md b/plugins/ndf-claude/skills/external-ai/SKILL.md index 9684e739..9a959755 100644 --- a/plugins/ndf-claude/skills/external-ai/SKILL.md +++ b/plugins/ndf-claude/skills/external-ai/SKILL.md @@ -1,7 +1,6 @@ --- name: external-ai -description: "Delegate coding, review, or research to an external AI CLI (Codex / Gemini). Use for 'codexで調査', 'geminiレビュー', '第二意見レビュー', 'external AI review', 'codex exec', 'gemini exec'." -when_to_use: "外部 AI へコード生成 / レビュー / 調査を委譲したいとき。追加トリガ: '外部AIに投げて', 'クロスチェックして', 'もう一つのAIに見てもらう', 'CLI で codex を回す'" +description: "Delegate coding, review, or research to an external AI CLI (Codex or Gemini). Use when a second opinion or an offloaded investigation is wanted. Triggers: 'codexで調査', 'geminiレビュー', '第二意見レビュー', 'codex exec', 'gemini exec', '外部AIに投げて'" --- # 外部 AI 委譲スキル (Codex / Gemini) diff --git a/plugins/ndf-claude/skills/fix/SKILL.md b/plugins/ndf-claude/skills/fix/SKILL.md index e6c85ee3..6ea24b41 100644 --- a/plugins/ndf-claude/skills/fix/SKILL.md +++ b/plugins/ndf-claude/skills/fix/SKILL.md @@ -1,7 +1,6 @@ --- name: fix -description: "Classify PR review comments, fix the actionable ones, then reply and resolve each thread. Use when responding to PR review feedback from codex, gemini, bots, or humans." -when_to_use: "PR レビューコメントへの対応全般。分類だけしたいときは --classify-only。Triggers: 'PRコメント対応', 'PRレビュー修正', 'PRコメントを確認', 'PRコメントを分類', 'コメント対応の優先度', 'PR fix', 'classify PR comments', 'コメントに対応して修正', 'Resolveして'" +description: "Classify PR review comments, fix the actionable ones, then reply and resolve each thread. Use when responding to review feedback from codex, gemini, bots, or humans on a PR. Triggers: 'PRコメント対応', 'PRレビュー修正', 'PRコメントを分類', 'コメントに対応して修正', 'Resolveして'" argument-hint: "[PR番号] [--classify-only] [--defer-nit] [--severity-min critical|major|minor]" allowed-tools: - Bash diff --git a/plugins/ndf-claude/skills/implementation-plan/SKILL.md b/plugins/ndf-claude/skills/implementation-plan/SKILL.md index 0e0a1307..2d961ee1 100644 --- a/plugins/ndf-claude/skills/implementation-plan/SKILL.md +++ b/plugins/ndf-claude/skills/implementation-plan/SKILL.md @@ -1,7 +1,6 @@ --- name: implementation-plan -description: "Create or update implementation plan files." -when_to_use: "実装開始時 / PR作成時に実装プランの作成・更新が必要なとき。複数ファイル変更・新機能追加・DBマイグレーションを含む変更で自動参照。Triggers: '実装プラン', '実装を開始', 'PR作成', 'implementation plan', 'plan first', '設計書を作成', 'issues/に追加'" +description: "Create or update an implementation plan file under issues/ before coding starts. Use when a change spans multiple files, adds a feature, or includes a DB migration. Triggers: '実装プラン', '実装を開始', 'implementation plan', '設計書を作成', 'issues/に追加'" --- # 実装プランガイド diff --git a/plugins/ndf-claude/skills/investigation-rules/SKILL.md b/plugins/ndf-claude/skills/investigation-rules/SKILL.md index a4757a83..1a20b2d0 100644 --- a/plugins/ndf-claude/skills/investigation-rules/SKILL.md +++ b/plugins/ndf-claude/skills/investigation-rules/SKILL.md @@ -1,7 +1,6 @@ --- name: investigation-rules -description: "Write evidence-backed investigation and debug reports." -when_to_use: "調査・デバッグ・不具合レポートを作成するとき。「ない」「該当なし」等の否定的結論を出すときは必ず参照。Triggers: '調査', 'デバッグ', '不具合レポート', '原因調査', 'investigation', 'root cause', 'カラムがない', '該当コードがない', 'データがない'" +description: "Write evidence-backed investigation and debug reports, and never state a negative finding without showing the search behind it. Use when writing an investigation or bug report. Triggers: '調査レポートを書く', '不具合レポート', '原因調査', 'カラムがない', '該当コードがない'" --- # 調査レポート作成ルール diff --git a/plugins/ndf-claude/skills/issue-plan-strategy/SKILL.md b/plugins/ndf-claude/skills/issue-plan-strategy/SKILL.md index 7f96f04a..26e07fdf 100644 --- a/plugins/ndf-claude/skills/issue-plan-strategy/SKILL.md +++ b/plugins/ndf-claude/skills/issue-plan-strategy/SKILL.md @@ -1,7 +1,6 @@ --- 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 で進めて'" +description: "Turn an issue into a plan, then drive the plan through a release branch, per-PR worktrees, and multi-PR execution. Use when asked to design a plan from an issue or to execute an existing plan. Triggers: 'issueのplanを作って', 'このplanを実装して', 'planを実行', 'release branch 作って実装開始', 'multi-PR で進めて'" argument-hint: "[issue-path-or-url] (例: issues/i16.md, https://github.com/org/repo/issues/123)" allowed-tools: - Bash diff --git a/plugins/ndf-claude/skills/logging-guidelines/SKILL.md b/plugins/ndf-claude/skills/logging-guidelines/SKILL.md index 3ad64b34..56e24879 100644 --- a/plugins/ndf-claude/skills/logging-guidelines/SKILL.md +++ b/plugins/ndf-claude/skills/logging-guidelines/SKILL.md @@ -1,6 +1,6 @@ --- name: logging-guidelines -description: "Choose log levels and write safe, useful application logs when adding or reworking logging in code(ログ追加 / logger / ログレベル / デバッグログ / エラーログ / print文をログに). Use when editing source code that emits logs, to pick the level and keep secrets and personal data out of the output." +description: "Choose log levels and keep secrets and personal data out of application logs. Use when adding, reworking, or reviewing logging in source code. Triggers: 'ログ追加', 'ログレベルを決める', 'ログ設計', 'print文をログに', 'ログに個人情報'" paths: - "**/*.py" - "**/*.ts" diff --git a/plugins/ndf-claude/skills/markdown-writing/SKILL.md b/plugins/ndf-claude/skills/markdown-writing/SKILL.md index 4b4d9488..736b47ce 100644 --- a/plugins/ndf-claude/skills/markdown-writing/SKILL.md +++ b/plugins/ndf-claude/skills/markdown-writing/SKILL.md @@ -1,7 +1,6 @@ --- name: markdown-writing -description: "Write Markdown docs, PR bodies, and reports that read well to a third party." -when_to_use: "Markdown 文書 / 仕様書 / 設計書 / PR 本文 / 調査レポート / 図表を作成・編集するとき。Triggers: 'Markdown作成', 'ドキュメント作成', '文書作成', '仕様書', '設計書', 'PR本文', 'PR説明', '調査レポート', '図を描く', 'mermaid', 'create document', 'write docs', 'write PR description'" +description: "Write Markdown docs, specs, PR bodies, and reports that read well to a third party, including tables and mermaid diagrams. Use when authoring or editing a Markdown document. Triggers: 'ドキュメント作成', 'PR本文', 'PR説明', '仕様書を書く', 'mermaid', 'write docs'" allowed-tools: - Read - Write diff --git a/plugins/ndf-claude/skills/merged/SKILL.md b/plugins/ndf-claude/skills/merged/SKILL.md index 78891b9e..0eeb1939 100644 --- a/plugins/ndf-claude/skills/merged/SKILL.md +++ b/plugins/ndf-claude/skills/merged/SKILL.md @@ -1,8 +1,7 @@ --- name: merged -description: "Clean up after a PR is merged: update main, remove the worktree, and delete merged branches." +description: "Clean up after a PR is merged: update main, remove the worktree, and delete the merged branch. Use when a PR has just been merged or leftover branches and worktrees need clearing. Triggers: 'マージ後の後片付け', 'ブランチを整理', 'worktreeを削除', 'merged cleanup'" argument-hint: "[PR番号]" -disable-model-invocation: true allowed-tools: - Bash - Read diff --git a/plugins/ndf-claude/skills/ndf-policies/SKILL.md b/plugins/ndf-claude/skills/ndf-policies/SKILL.md index ab8becf5..f1a22887 100644 --- a/plugins/ndf-claude/skills/ndf-policies/SKILL.md +++ b/plugins/ndf-claude/skills/ndf-policies/SKILL.md @@ -1,6 +1,6 @@ --- name: ndf-policies -description: "Apply core NDF project policies, including the branch strategy for applying the same fix to environment branches (qa/staging/release) without contaminating feature branches." +description: "Core NDF project policies. 知識として参照するだけで、手順として実行しない。判断に迷ったときの基準として使う: ブランチ戦略、環境ブランチ (qa/staging/release) へ同じ修正を適用する原則、feature ブランチを汚さない運用、PR 運用ルール。" user-invocable: false --- diff --git a/plugins/ndf-claude/skills/official-skills-autoloader/SKILL.md b/plugins/ndf-claude/skills/official-skills-autoloader/SKILL.md new file mode 100644 index 00000000..3c260a60 --- /dev/null +++ b/plugins/ndf-claude/skills/official-skills-autoloader/SKILL.md @@ -0,0 +1,128 @@ +--- +name: official-skills-autoloader +description: "Install an Anthropic official Skill on demand (docx / pptx / xlsx / pdf / frontend-design / webapp-testing / mcp-builder) and run it. Use when a request needs Office or PDF output that no local Skill covers. Triggers: 'Word作成', 'Excel出力', 'スライド生成', 'PDF作成'" +when_to_use: "Claude Code 専用。~/.claude/skills/ へ公式 Skill を取得して読み込む。追加トリガ: '.docx', '.pptx', '.xlsx', '.pdf', 'MCPサーバーを作りたい', 'フロントエンド設計'" +allowed-tools: + - Bash + - Read +--- + +# 公式Skill自動ローダー + +ユーザーの要求から必要なAnthropic公式Skillを特定し、未インストールなら自動でインストール→読込して作業を進めます。利用者は**インストール作業を意識する必要がありません**。 + +## 対応マッピング + +| ユーザー要求の例 | 使用するSkill | +|---|---| +| Word / .docx / 文書 / レポート | `docx` | +| PowerPoint / .pptx / スライド / プレゼン | `pptx` | +| Excel / .xlsx / スプレッドシート / 表計算 | `xlsx` | +| PDF 生成 / フォーム / .pdf 作成 | `pdf` | +| フロントエンド設計 / UI設計 | `frontend-design` | +| Playwright / E2Eテスト / Webアプリテスト | `webapp-testing` | +| HTML/Reactアプリ生成 / Artifacts | `web-artifacts-builder` | +| 新規Skill作成 | `skill-creator` | +| Claude API / SDK開発 | `claude-api` | +| MCPサーバー作成 | `mcp-builder` | + +## 対応ランタイム + +**Claude Code 専用**。インストール先の `~/.claude/skills/` を読むのは Claude Code だけで、Codex は `.agents/skills/`、Kiro CLI は `.kiro/skills/` を読む。両ランタイムでは公式 Skill の自動読込は行われないため、配布するとしても Claude Code の manifest に限る。 + +配布先は `plugins/ndf-shared/manifests/claude-skills.txt` のみとする。Codex / Kiro の manifest には載せない。 + +## 動作手順 + +### ステップ1: 対象Skillを特定 + +ユーザーの発話から上記マッピングで対象Skill名を1つ決定。曖昧な場合はユーザーに確認。 + +### ステップ2: インストール状態を確認 + +以下のBashコマンドで確認: + +```bash +SKILL_NAME="<対象名>" +if [ -d "$HOME/.claude/skills/$SKILL_NAME" ] || [ -L "$HOME/.claude/skills/$SKILL_NAME" ]; then + echo "INSTALLED" +else + echo "MISSING" +fi +``` + +### ステップ3: 未インストールなら自動インストール + +```bash +SKILL_NAME="<対象名>" +CACHE_DIR="${XDG_CACHE_HOME:-$HOME/.cache}/anthropic-skills" +USER_SKILLS="$HOME/.claude/skills" + +# 初回のみ公式リポジトリをclone +if [ ! -d "$CACHE_DIR/.git" ]; then + echo "公式Skillリポジトリを取得中..." + mkdir -p "$(dirname "$CACHE_DIR")" + git clone --depth 1 https://github.com/anthropics/skills.git "$CACHE_DIR" +fi + +# 対象Skillの存在確認 +if [ ! -d "$CACHE_DIR/skills/$SKILL_NAME" ]; then + echo "ERROR: $SKILL_NAME は公式リポジトリに存在しません" + exit 1 +fi + +# シンボリックリンク作成 +mkdir -p "$USER_SKILLS" +ln -sfn "$CACHE_DIR/skills/$SKILL_NAME" "$USER_SKILLS/$SKILL_NAME" +echo "Installed: $USER_SKILLS/$SKILL_NAME" +``` + +ユーザーには「公式Skill `` を準備しています...」と一言伝える。 + +### ステップ4: SKILL.mdを読み込んで実行 + +``` +Read(file_path="$HOME/.claude/skills//SKILL.md") +``` + +読み込んだSKILL.mdの内容を**現在のコンテキストで実行**する。そのSkillが指定する `scripts/` ディレクトリや `reference/` ファイルも必要に応じて読込。 + +## 注意事項 + +### ライセンス + +- Apache-2.0(mcp-builder, frontend-design, webapp-testing, claude-api 等): 再配布可 +- プロプライエタリ(docx, pptx, xlsx, pdf): **個人環境での利用のみ**。リポジトリに含めない、社内共有しない + +このautoloaderが行うのは**利用者のローカル環境へのインストールのみ**で、再配布には該当しません。 + +### パス規約 + +- cache: `~/.cache/anthropic-skills/` (XDG準拠) +- リンク先: `~/.claude/skills//` (ユーザー領域) +- プロジェクト単位で配置したい場合は `plugins/ndf-shared/scripts/install-official-skills.sh --scope project ` を直接実行 + +### 再読込 + +同一セッション内では Read したSKILL.mdの内容で作業を完結させます。次回セッション以降はClaude Codeが自動でそのSkillを認識するため、このautoloaderは介入しません。 + +### 手動管理したい場合 + +- 一覧表示: `bash plugins/ndf-shared/scripts/install-official-skills.sh --list` +- 更新: `bash plugins/ndf-shared/scripts/install-official-skills.sh --update` +- 明示的なインストール: `bash plugins/ndf-shared/scripts/install-official-skills.sh ` + +## エラーハンドリング + +| 症状 | 対応 | +|---|---| +| git clone失敗 | ネットワーク・認証を確認。プロキシ環境では HTTP_PROXY 設定を確認 | +| 対象Skillが公式にない | --list で最新の公式一覧を確認、マッピングを更新 | +| 権限エラー | `~/.claude/skills/` の書込権限を確認 | +| 既に別物がある | ユーザーに確認してから上書き | + +## 対象外 + +- 自作Skillの生成(これは `skill-creator` に委譲) +- プロプライエタリSkillのCIへの組込(ライセンス違反) +- NDFプラグイン自体のスキル管理 diff --git a/plugins/ndf-claude/skills/plan-to-spec/SKILL.md b/plugins/ndf-claude/skills/plan-to-spec/SKILL.md index eaea6f98..0fdd5ec3 100644 --- a/plugins/ndf-claude/skills/plan-to-spec/SKILL.md +++ b/plugins/ndf-claude/skills/plan-to-spec/SKILL.md @@ -1,6 +1,6 @@ --- name: plan-to-spec -description: "Finalize an implemented plan into a permanent specification document. Use after implementation is complete and an issues/ plan, PLAN file, design note, or implementation plan should become the final as-is specification under docs/ or another authoritative specification location. Triggers: 'planを仕様書にして', '確定仕様書に移動', '実装完了後にplanを整理', 'planをdocsへ移動', '仕様書としてリライト', 'plan-to-spec', 'finalize plan spec'." +description: "Rewrite a finished implementation plan into a permanent specification under docs/. Use when implementation is complete and an issues/ plan should become the as-is specification. Triggers: 'planを仕様書にして', '確定仕様書に移動', 'planをdocsへ移動', 'plan-to-spec'" allowed-tools: - Bash - Read diff --git a/plugins/ndf-claude/skills/playwright-authoring/SKILL.md b/plugins/ndf-claude/skills/playwright-authoring/SKILL.md index 3742e685..e196c902 100644 --- a/plugins/ndf-claude/skills/playwright-authoring/SKILL.md +++ b/plugins/ndf-claude/skills/playwright-authoring/SKILL.md @@ -1,7 +1,6 @@ --- name: playwright-authoring -description: "Create reproducible Playwright test scripts and run them with evidence, or check a page over browser MCP. Use when writing E2E test code, running E2E tests, doing a browser smoke check, or connecting to a remote Chrome over CDP (テストスクリプト作成 / テスト実行 / ブラウザ動作確認 / CDP 接続)." -when_to_use: "テストコード実装 / エビデンス動画・trace 収集 / accessibility・Core Web Vitals 計測 / ブラウザ接続先の変更が必要なとき。Triggers: 'playwright codegen', 'pwk_evidence', 'axe-core', 'WCAG', 'LCP', 'CLS', 'body_check', 'overlay', 'connectOverCDP', 'host.docker.internal', 'remote debugging'" +description: "Write Playwright E2E test scripts and run them with video / trace evidence, or check a page over browser MCP. Use when writing or running E2E tests, doing a browser smoke check, or connecting to Chrome over CDP. Triggers: 'playwright codegen', 'axe-core', 'connectOverCDP', 'ブラウザ動作確認'" argument-hint: "[url]" allowed-tools: - Read diff --git a/plugins/ndf-claude/skills/pr-tests/SKILL.md b/plugins/ndf-claude/skills/pr-tests/SKILL.md index 39f13de3..836146d2 100644 --- a/plugins/ndf-claude/skills/pr-tests/SKILL.md +++ b/plugins/ndf-claude/skills/pr-tests/SKILL.md @@ -1,8 +1,7 @@ --- name: pr-tests -description: "Run PR test plans and comment results." +description: "Run the test plan written in a PR body and post the results back as a PR comment. Use when a PR test plan has to be executed and reported. Triggers: 'PRのテストを実行', 'テストプランを実行', 'テスト結果をPRにコメント'" argument-hint: "[PR番号]" -disable-model-invocation: true allowed-tools: - Bash - Read diff --git a/plugins/ndf-claude/skills/pr/SKILL.md b/plugins/ndf-claude/skills/pr/SKILL.md index 3bfe6b16..dfe4ae48 100644 --- a/plugins/ndf-claude/skills/pr/SKILL.md +++ b/plugins/ndf-claude/skills/pr/SKILL.md @@ -1,8 +1,7 @@ --- name: pr -description: "Commit, push, and create or update PRs." +description: "Commit, push, and create or update a pull request for the current branch. Use when asked to commit and open a PR, update an existing PR, or push work for review. Triggers: 'PRを作って', 'PR作成', 'コミットしてプッシュ', 'PRを更新', 'draft PR'" argument-hint: "[--draft] [base-branch] or [commit-message]" -disable-model-invocation: true allowed-tools: - Bash - Read diff --git a/plugins/ndf-claude/skills/problem-solving/SKILL.md b/plugins/ndf-claude/skills/problem-solving/SKILL.md index 94133205..56b0dfbb 100644 --- a/plugins/ndf-claude/skills/problem-solving/SKILL.md +++ b/plugins/ndf-claude/skills/problem-solving/SKILL.md @@ -1,7 +1,6 @@ --- 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'" +description: "Solve bugs, incidents, and data inconsistencies at the root cause instead of patching downstream. Use when a bug, outage, or data inconsistency needs a fix decision. Triggers: 'バグの根本原因', 'データ不整合', '障害対応', 'root cause analysis', '上流で直す', 'patch vs fix'" --- # 問題解決ガイドライン diff --git a/plugins/ndf-claude/skills/qa-security-scan/01-owasp-checklist.md b/plugins/ndf-claude/skills/qa-security-scan/01-owasp-checklist.md new file mode 100644 index 00000000..797015b2 --- /dev/null +++ b/plugins/ndf-claude/skills/qa-security-scan/01-owasp-checklist.md @@ -0,0 +1,298 @@ +# OWASP Top 10 詳細チェックリスト + +## 1. インジェクション + +**脆弱性の説明**: +信頼できないデータがコマンドやクエリの一部として送信され、攻撃者が意図しないコマンドを実行したり、適切な認可なしにデータにアクセスしたりできる。 + +**チェック項目**: + +- [ ] **SQLインジェクション対策** + ```javascript + // ❌ Bad: 文字列連結 + const query = `SELECT * FROM users WHERE id = ${userId}`; + + // ✅ Good: パラメータ化クエリ + const query = 'SELECT * FROM users WHERE id = ?'; + db.query(query, [userId]); + ``` + +- [ ] **コマンドインジェクション対策** + ```javascript + // ❌ Bad: ユーザー入力を直接使用 + exec(`ping ${userInput}`); + + // ✅ Good: ホワイトリスト検証 + エスケープ + if (!/^[a-zA-Z0-9.-]+$/.test(userInput)) { + throw new Error('Invalid input'); + } + ``` + +- [ ] **LDAPインジェクション対策** + - 特殊文字のエスケープ + - パラメータ化クエリの使用 + +- [ ] **NoSQLインジェクション対策** + ```javascript + // ❌ Bad: オブジェクトを直接使用 + User.find({ username: req.body.username }); + + // ✅ Good: 型検証 + const username = String(req.body.username); + User.find({ username }); + ``` + +**修正方法**: +1. パラメータ化クエリ/プリペアドステートメント使用 +2. ORMの使用(Sequelize、TypeORM等) +3. 入力値の厳格な検証(ホワイトリスト) +4. エスケープ処理 + +## 2. 認証の不備 + +**チェック項目**: + +- [ ] **パスワードの安全なハッシュ化** + ```javascript + // ❌ Bad: 平文保存、MD5/SHA1 + const hash = md5(password); + + // ✅ Good: bcrypt/Argon2 + const bcrypt = require('bcrypt'); + const hash = await bcrypt.hash(password, 10); + ``` + +- [ ] **セッション管理** + - セッションIDの再生成(ログイン後) + - セキュアなCookie設定(HttpOnly, Secure, SameSite) + - セッションタイムアウトの設定 + +- [ ] **多要素認証(MFA)** + - 重要な操作でMFA要求 + - TOTPまたはSMS認証 + +- [ ] **ブルートフォース攻撃対策** + - レート制限(rate limiting) + - アカウントロックアウト + - CAPTCHA + +- [ ] **パスワードポリシー** + - 最小8文字以上 + - 大文字、小文字、数字、記号の組み合わせ + - 過去のパスワードの再利用禁止 + +**修正方法**: +1. bcrypt/Argon2でパスワードをハッシュ化 +2. JWTトークンまたはセキュアなセッション管理 +3. express-rate-limitでレート制限 +4. パスワードポリシーの強制 + +## 3. 機密データの露出 + +**チェック項目**: + +- [ ] **通信の暗号化** + - HTTPS/TLS 1.2以上の使用 + - HTTP Strict Transport Security (HSTS) ヘッダー + +- [ ] **保存時の暗号化** + ```javascript + // ✅ Good: AES-256で暗号化 + const crypto = require('crypto'); + const algorithm = 'aes-256-cbc'; + const key = crypto.randomBytes(32); + const iv = crypto.randomBytes(16); + + function encrypt(text) { + const cipher = crypto.createCipheriv(algorithm, key, iv); + let encrypted = cipher.update(text, 'utf8', 'hex'); + encrypted += cipher.final('hex'); + return encrypted; + } + ``` + +- [ ] **機密情報のログ出力禁止** + ```javascript + // ❌ Bad + console.log('User password:', password); + logger.info('Credit card:', creditCard); + + // ✅ Good + logger.info('User authenticated', { userId: user.id }); + ``` + +- [ ] **APIキー・シークレットの管理** + - 環境変数で管理 + - .envファイルは.gitignoreに追加 + - AWS Secrets Manager / HashiCorp Vault 等の使用 + +**修正方法**: +1. すべての通信をHTTPS化 +2. 機密データの暗号化(AES-256) +3. 環境変数で機密情報を管理 +4. ログに機密情報を出力しない + +## 4. XXE(XML External Entity) + +**チェック項目**: + +- [ ] **XML パーサーの安全な設定** + ```javascript + // ✅ Good: DTD処理を無効化 + const { XMLParser } = require('fast-xml-parser'); + const parser = new XMLParser({ + ignoreAttributes: false, + processEntities: false // DTD処理を無効化 + }); + ``` + +- [ ] **外部エンティティの禁止** +- [ ] **DTD処理の無効化** + +**修正方法**: +1. XML パーサーでDTD処理を無効化 +2. 外部エンティティの参照を禁止 +3. 可能であればJSONを使用 + +## 5. アクセス制御の不備 + +**チェック項目**: + +- [ ] **認可チェックの実装** + ```javascript + // ✅ Good: ミドルウェアで認可チェック + function requireAdmin(req, res, next) { + if (req.user.role !== 'admin') { + return res.status(403).json({ error: 'Forbidden' }); + } + next(); + } + + app.delete('/api/users/:id', authMiddleware, requireAdmin, deleteUser); + ``` + +- [ ] **ロールベースアクセス制御(RBAC)** + - ユーザーごとにロール設定 + - リソースごとに必要なロールを定義 + +- [ ] **オブジェクトレベルの認可** + ```javascript + // ❌ Bad: IDだけで削除 + app.delete('/api/posts/:id', async (req, res) => { + await Post.destroy({ where: { id: req.params.id } }); + }); + + // ✅ Good: 所有者チェック + app.delete('/api/posts/:id', authMiddleware, async (req, res) => { + const post = await Post.findByPk(req.params.id); + if (post.userId !== req.user.id) { + return res.status(403).json({ error: 'Forbidden' }); + } + await post.destroy(); + }); + ``` + +- [ ] **IDORの防止**(Insecure Direct Object Reference) + +**修正方法**: +1. すべてのAPIエンドポイントで認可チェック +2. ロールベースアクセス制御の実装 +3. オブジェクトの所有者確認 + +## 6. セキュリティ設定ミス + +**チェック項目**: + +- [ ] **デフォルトパスワードの変更** +- [ ] **不要なサービスの無効化** +- [ ] **セキュリティヘッダーの設定** + ```javascript + // ✅ Good: helmet.js でセキュリティヘッダー設定 + const helmet = require('helmet'); + app.use(helmet()); + app.use(helmet.contentSecurityPolicy({ + directives: { + defaultSrc: ["'self'"], + scriptSrc: ["'self'", "'unsafe-inline'"], + styleSrc: ["'self'", "'unsafe-inline'"] + } + })); + ``` + +- [ ] **エラーメッセージの適切化** + ```javascript + // ❌ Bad: 詳細なエラーを公開 + res.status(500).json({ error: error.stack }); + + // ✅ Good: 一般的なエラーメッセージ + res.status(500).json({ error: 'Internal server error' }); + // 詳細はログに記録 + logger.error('Error details:', error); + ``` + +- [ ] **CORSの適切な設定** + ```javascript + // ✅ Good: 特定のオリジンのみ許可 + const cors = require('cors'); + app.use(cors({ + origin: 'https://example.com', + credentials: true + })); + ``` + +**修正方法**: +1. helmet.js でセキュリティヘッダー設定 +2. 環境別の設定(開発/本番) +3. エラーメッセージは一般的に、詳細はログに + +## 7. XSS(クロスサイトスクリプティング) + +**チェック項目**: + +- [ ] **HTMLエスケープ** + ```javascript + // ❌ Bad: 直接HTMLに挿入 + document.getElementById('output').innerHTML = userInput; + + // ✅ Good: エスケープして挿入 + document.getElementById('output').textContent = userInput; + + // または DOMPurify を使用 + import DOMPurify from 'dompurify'; + const clean = DOMPurify.sanitize(userInput); + ``` + +- [ ] **Content-Security-Policy (CSP) 設定** +- [ ] **HTTPOnlyクッキー** + ```javascript + // ✅ Good: HTTPOnly, Secure, SameSite + res.cookie('token', token, { + httpOnly: true, + secure: true, + sameSite: 'strict' + }); + ``` + +- [ ] **DOMベースXSS対策** + - `eval()`, `innerHTML`, `document.write()` を避ける + +**修正方法**: +1. すべての出力をエスケープ +2. Content-Security-Policy ヘッダー設定 +3. DOMPurifyなどのサニタイゼーションライブラリ使用 + +## 8-10. その他の脆弱性 + +**8. 安全でないデシリアライゼーション** +- [ ] 信頼できないデータのデシリアライズ禁止 +- [ ] 署名・検証の実装 + +**9. 既知の脆弱性があるコンポーネント** +- [ ] 依存ライブラリの最新化 +- [ ] `npm audit` / `pip-audit` の実行 +- [ ] Dependabot / Renovate の利用 + +**10. ログとモニタリングの不足** +- [ ] セキュリティイベントのログ +- [ ] 異常検知の仕組み +- [ ] 定期的なログレビュー diff --git a/plugins/ndf-claude/skills/qa-security-scan/02-auth-checklist.md b/plugins/ndf-claude/skills/qa-security-scan/02-auth-checklist.md new file mode 100644 index 00000000..0ff70595 --- /dev/null +++ b/plugins/ndf-claude/skills/qa-security-scan/02-auth-checklist.md @@ -0,0 +1,127 @@ +# 認証・認可チェックリスト + +## 認証テスト + +### ログイン機能 + +- [ ] **正しい認証情報でログイン成功** +- [ ] **誤った認証情報でログイン失敗** +- [ ] **パスワード忘れ機能** + - リセットリンクの有効期限 + - リセット後の古いリンク無効化 + +### セッション管理 + +- [ ] **ログアウト後にセッション無効化** +- [ ] **セッションタイムアウト** + - アイドルタイムアウト(15-30分推奨) + - 絶対タイムアウト(8-24時間推奨) +- [ ] **同時ログインの制限** + - 必要に応じて制限を実装 + - 新規ログイン時に既存セッションを無効化 + +### トークン管理(JWT) + +- [ ] **トークン有効期限** + - アクセストークン: 15分-1時間 + - リフレッシュトークン: 7-30日 +- [ ] **トークンリフレッシュ** + - リフレッシュトークンのローテーション +- [ ] **署名検証** + - 強力な秘密鍵の使用 + - アルゴリズムの明示的指定 + +```javascript +// ✅ Good: JWT検証 +const jwt = require('jsonwebtoken'); + +function verifyToken(token) { + return jwt.verify(token, process.env.JWT_SECRET, { + algorithms: ['HS256'], // アルゴリズムを明示 + issuer: 'your-app', + audience: 'your-users' + }); +} +``` + +## 認可テスト + +### ロールベースアクセス制御 + +- [ ] **管理者のみアクセス可能なリソース** + - /admin/* へのアクセス制限 + - 管理機能の認可チェック +- [ ] **一般ユーザーの権限制限** + - 他ユーザーのデータへのアクセス禁止 + - 機能制限の適用 + +### リソース所有者チェック + +- [ ] **自分のリソースのみ編集・削除可能** + +```javascript +// ✅ Good: 所有者チェック +async function updateResource(req, res) { + const resource = await Resource.findByPk(req.params.id); + + if (!resource) { + return res.status(404).json({ error: 'Not found' }); + } + + // 所有者または管理者のみ許可 + if (resource.userId !== req.user.id && req.user.role !== 'admin') { + return res.status(403).json({ error: 'Forbidden' }); + } + + await resource.update(req.body); + res.json(resource); +} +``` + +## テストケース例 + +### 認証バイパステスト + +``` +1. 認証なしで保護されたエンドポイントにアクセス + → 401 Unauthorized が返ること + +2. 無効なトークンでアクセス + → 401 Unauthorized が返ること + +3. 期限切れトークンでアクセス + → 401 Unauthorized が返ること + +4. 改ざんされたトークンでアクセス + → 401 Unauthorized が返ること +``` + +### 権限昇格テスト + +``` +1. 一般ユーザーで管理者APIにアクセス + → 403 Forbidden が返ること + +2. ユーザーAでユーザーBのリソースを編集 + → 403 Forbidden が返ること + +3. URLのIDを変更して他ユーザーのデータにアクセス + → 403 Forbidden が返ること +``` + +## 実装チェックリスト + +### 必須実装 + +- [ ] パスワードはbcrypt/Argon2でハッシュ化 +- [ ] セッション/トークンにはセキュアなCookie設定 +- [ ] すべてのAPIエンドポイントに認証ミドルウェア +- [ ] 認可チェックは各リソースアクセス時に実行 +- [ ] レート制限を実装 + +### 推奨実装 + +- [ ] 多要素認証(MFA) +- [ ] パスワード強度チェック +- [ ] ログイン試行回数制限 +- [ ] セキュリティログの記録 diff --git a/plugins/ndf-claude/skills/qa-security-scan/03-report-template.md b/plugins/ndf-claude/skills/qa-security-scan/03-report-template.md new file mode 100644 index 00000000..6ad9f7ec --- /dev/null +++ b/plugins/ndf-claude/skills/qa-security-scan/03-report-template.md @@ -0,0 +1,144 @@ +# セキュリティレポートテンプレート + +## 使用方法 + +このテンプレートをコピーして、セキュリティスキャン結果を報告してください。 + +--- + +# セキュリティスキャンレポート - [アプリケーション名] + +## エグゼクティブサマリー + +- **スキャン日**: YYYY-MM-DD +- **スキャン範囲**: [対象範囲の説明] +- **重大な脆弱性**: X件 +- **警告**: Y件 +- **情報**: Z件 + +## 重大な脆弱性 (Critical/High) + +### 1. [脆弱性名] + +- **場所**: [ファイルパス/エンドポイント] +- **リスクレベル**: 高 +- **説明**: [脆弱性の詳細説明] +- **影響**: [悪用された場合の影響] +- **修正方法**: + ```javascript + // 修正前 + [問題のあるコード] + + // 修正後 + [修正されたコード] + ``` +- **優先度**: 最高(即座に修正) + +### 2. [脆弱性名] + +[同様のフォーマットで記載] + +## 警告 (Medium) + +### 3. [脆弱性名] + +- **場所**: [ファイルパス/エンドポイント] +- **リスクレベル**: 中 +- **説明**: [脆弱性の詳細説明] +- **修正方法**: [修正方法の説明] + +## 情報 (Low/Info) + +### 4. [項目名] + +- **場所**: [ファイルパス/エンドポイント] +- **説明**: [詳細説明] +- **推奨事項**: [推奨される対応] + +## 推奨事項 + +1. **即座に修正**: 重大な脆弱性X件 +2. **1週間以内に修正**: 警告Y件 +3. **セキュリティヘッダー追加**: helmet.js 使用 +4. **依存ライブラリの更新**: npm audit で検出された脆弱性 +5. **定期的なセキュリティスキャン**: 月1回の実施 + +## 次のステップ + +1. [ ] 重大な脆弱性の修正 +2. [ ] 修正後の再スキャン +3. [ ] ペネトレーションテストの実施 +4. [ ] セキュリティ監視の強化 + +--- + +## レポート作成のポイント + +### リスクレベルの判断基準 + +| レベル | 基準 | +|--------|------| +| Critical | リモートコード実行、認証バイパス、データ全体へのアクセス | +| High | SQLインジェクション、XSS(保存型)、権限昇格 | +| Medium | XSS(反射型)、CSRF、情報漏洩(限定的) | +| Low | セキュリティヘッダー不足、詳細なエラーメッセージ | +| Info | ベストプラクティスからの逸脱 | + +### 修正優先度 + +1. **即座に**: Critical/High(本番環境に影響) +2. **1週間以内**: Medium(悪用の可能性あり) +3. **次回リリース**: Low/Info(改善推奨) + +## Codex CLI 連携 + +詳細な独立レビューが必要な場合は `corder` エージェントに委譲するか、`/ndf:external-ai` skill の手順で `codex exec` を直接起動する。例: + +```bash +# === 1. プロンプト書き出し(最終出力先を明示し apply_patch で書かせる) === +FINAL=/tmp/codex-output-sec-scan.md + +cat > /tmp/sec-scan-prompt.md < /tmp/sec-scan-stdout.md \ + 2> /tmp/sec-scan-err.log & + +# === 3. 完了確認(^tokens used$ sentinel を待つ。`ps -p` は zombie を生存と誤判定する) === +until grep -q '^tokens used$' /tmp/sec-scan-err.log 2>/dev/null; do + sleep 30 +done + +# === 4. 成果物を回収(ファイル → stdout → stderr の三段フォールバック) === +if [ -s "$FINAL" ]; then + cp "$FINAL" ./sec-scan-result.md +elif [ -s /tmp/sec-scan-stdout.md ]; then + cp /tmp/sec-scan-stdout.md ./sec-scan-result.md + echo "WARN: stdout からフォールバック回収(ファイル書き出しなし)" >&2 +else + echo "ERROR: Codex の最終出力を回収できませんでした。stderr 末尾を確認:" >&2 + tail -200 /tmp/sec-scan-err.log +fi +``` + +詳細は `/ndf:external-ai` skill と `references/cli-codex.md` を参照。 diff --git a/plugins/ndf-claude/skills/qa-security-scan/SKILL.md b/plugins/ndf-claude/skills/qa-security-scan/SKILL.md new file mode 100644 index 00000000..b741edaa --- /dev/null +++ b/plugins/ndf-claude/skills/qa-security-scan/SKILL.md @@ -0,0 +1,55 @@ +--- +name: qa-security-scan +description: "Run an OWASP Top 10 security review of code, authentication, authorization, and data protection. Use when asked for a security review of a change or a vulnerability check. Triggers: 'セキュリティレビュー', 'セキュリティスキャン', '脆弱性チェック', 'OWASP', '認証認可の確認', 'SQLインジェクション'" +--- + +# QA Security Scan Skill + +## 概要 + +セキュリティスキャンと脆弱性評価を実施する際に使用します。OWASP Top 10に基づいた包括的なチェックリストと、認証・認可・データ保護の検証手順を提供します。 + +## クイックリファレンス + +### OWASP Top 10 概要 + +| # | 脆弱性 | 主な対策 | +|---|--------|----------| +| 1 | インジェクション | パラメータ化クエリ、ORM使用 | +| 2 | 認証の不備 | bcrypt/Argon2、MFA、レート制限 | +| 3 | 機密データ露出 | HTTPS、暗号化、環境変数管理 | +| 4 | XXE | DTD処理無効化、JSON使用 | +| 5 | アクセス制御不備 | RBAC、所有者チェック | +| 6 | 設定ミス | helmet.js、適切なCORS | +| 7 | XSS | エスケープ、CSP、DOMPurify | +| 8 | デシリアライゼーション | 署名検証、信頼できるデータのみ | +| 9 | 既知の脆弱性 | npm audit、Dependabot | +| 10 | ログ不足 | セキュリティイベント記録 | + +### 基本的な使い方 + +1. 対象コードを特定 +2. 該当するチェックリストを適用 +3. 脆弱性を発見したらレポート作成 +4. 修正方法を提案 + +## ベストプラクティス + +| DO | DON'T | +|----|-------| +| 定期的なスキャン(月1回以上) | スキャンのみで満足 | +| CI/CDパイプラインに統合 | 警告を無視 | +| 重大度順に対応(高→低) | 本番環境で初スキャン | +| 修正後に再スキャン | 自動化ツールに全依存 | + +## 詳細ガイド + +| ファイル | 内容 | +|---------|------| +| `01-owasp-checklist.md` | OWASP Top 10 詳細チェックリストとコード例 | +| `02-auth-checklist.md` | 認証・認可テスト手順 | +| `03-report-template.md` | セキュリティレポートテンプレート | + +## 関連Skill + +- **corder-code-templates**: セキュアなコードテンプレート diff --git a/plugins/ndf-claude/skills/review/SKILL.md b/plugins/ndf-claude/skills/review/SKILL.md index 2afd42e2..fefe037d 100644 --- a/plugins/ndf-claude/skills/review/SKILL.md +++ b/plugins/ndf-claude/skills/review/SKILL.md @@ -1,9 +1,8 @@ --- name: review -description: "Review a PR diff, or the current branch diff with --branch, and post an approve or request-changes verdict." -when_to_use: "PR をレビューするとき、および PR 作成前にローカルブランチをセルフレビューするとき (--branch)。Triggers: 'レビューして', 'PRレビュー', 'マージ前チェック', 'ブランチをレビュー', 'セルフレビュー', 'PR前にレビュー', 'review my branch', 'self review', 'pre-PR review'" +description: "Review a PR diff, or the current branch diff with --branch, and post an approve or request-changes verdict. Use when asked to review a PR, check a diff before merge, or self-review a branch. Triggers: 'レビューして', 'PRレビュー', 'マージ前チェック', 'ブランチをレビュー', 'セルフレビュー'" argument-hint: "[PR番号 | --branch] [AIエージェント(codex|gemini)] [--focus AREA]" -disable-model-invocation: true +effort: high allowed-tools: - Bash - Read diff --git a/plugins/ndf-claude/skills/statusline/SKILL.md b/plugins/ndf-claude/skills/statusline/SKILL.md index ab17e4a0..22357fe7 100644 --- a/plugins/ndf-claude/skills/statusline/SKILL.md +++ b/plugins/ndf-claude/skills/statusline/SKILL.md @@ -1,7 +1,7 @@ --- name: statusline -description: "Switch, restore, or inspect the NDF statusline." -when_to_use: "statuslineを切り替え/復元/確認したいとき。Triggers: 'statusline', 'ステータスライン', 'statusline 切り替え', 'statusline 戻す'" +description: "Switch, restore, or inspect the NDF statusline in the Claude Code settings file. 設定ファイルを書き換えるため、利用者が /ndf:statusline を明示的に指示したときのみ実行する。Triggers: 'statusline 切り替え', 'statusline 戻す', 'ステータスライン'" +argument-hint: "status | set | restore" disable-model-invocation: true allowed-tools: - Bash diff --git a/plugins/ndf-codex/skills/cherry-pick-pr/SKILL.md b/plugins/ndf-codex/skills/cherry-pick-pr/SKILL.md index 1de3823b..4228d90d 100644 --- a/plugins/ndf-codex/skills/cherry-pick-pr/SKILL.md +++ b/plugins/ndf-codex/skills/cherry-pick-pr/SKILL.md @@ -1,7 +1,7 @@ --- name: cherry-pick-pr -description: "Create cherry-pick PRs for environment branches and apply the same fix across multiple branches." -argument-hint: " (例: qa/staging, release/v2)" +description: "Cherry-pick a merged fix onto environment branches (qa/staging, release) as a new PR. 破壊的操作のため、利用者が /ndf:cherry-pick-pr を明示的に指示したときのみ実行する。Triggers: 'cherry-pick', 'qaにも同じ修正を適用', 'stagingにも反映', 'release branchへ適用', 'multi-branch fix'" +argument-hint: "ベースブランチ名 (例: qa/staging, release/v2)" disable-model-invocation: true allowed-tools: - Bash diff --git a/plugins/ndf-codex/skills/cross-review/SKILL.md b/plugins/ndf-codex/skills/cross-review/SKILL.md index a04d98e6..340015e3 100644 --- a/plugins/ndf-codex/skills/cross-review/SKILL.md +++ b/plugins/ndf-codex/skills/cross-review/SKILL.md @@ -1,7 +1,6 @@ --- name: cross-review -description: "Run iterative Codex and Gemini PR reviews." -when_to_use: "PR を codex + gemini 両方でレビューし、両者 APPROVE まで自動収束させたいときに限定して使う。明示トリガ: 'cross-review', 'クロスレビュー', '両AIレビュー', '収束レビュー', 'codex と gemini でレビュー'。通常の単発 PR レビュー依頼 (第二意見が 1 回欲しい等) は本 skill を選ばず /ndf:review を使う。重い収束ループ (codex+gemini を複数ラウンド起動) のため、単発レビューと責務を明確に分ける。" +description: "Review a PR with both Codex and Gemini, looping fixes until both APPROVE. Use when a converging two-AI review is wanted; for a one-shot second opinion use /ndf:review. Triggers: 'cross-review', 'クロスレビュー', '両AIレビュー', '収束レビュー', 'codex と gemini でレビュー'" argument-hint: "[PR番号] [--max-rounds N] [--rotate-after K] [--rotate-mode light|squash] [--only codex|gemini] [--focus TEXT] [--extra-instructions-file PATH]" allowed-tools: - Bash diff --git a/plugins/ndf-codex/skills/deploy/SKILL.md b/plugins/ndf-codex/skills/deploy/SKILL.md index 8bca071b..c4baa425 100644 --- a/plugins/ndf-codex/skills/deploy/SKILL.md +++ b/plugins/ndf-codex/skills/deploy/SKILL.md @@ -1,7 +1,7 @@ --- name: deploy -description: "Create a deploy PR from the current feature branch to an environment branch such as qa/staging or release/v2. 破壊的操作のため、利用者が /ndf:deploy を明示的に指示したときのみ実行する(環境ブランチへデプロイ / qaに上げる / stagingに反映 / リリースブランチへPR)。deployブランチを作成し origin/main を取り込んでからPRを出す。" -argument-hint: " (例: qa/staging, release/v2)" +description: "Create a deploy PR from the current feature branch to an environment branch such as qa/staging or release/v2. 破壊的操作のため、利用者が /ndf:deploy を明示的に指示したときのみ実行する。Triggers: '環境ブランチへデプロイ', 'qaに上げる', 'stagingへデプロイ', 'リリースブランチへPR'" +argument-hint: "環境ブランチ名 (例: qa/staging, release/v2)" disable-model-invocation: true allowed-tools: - Bash diff --git a/plugins/ndf-codex/skills/docker-container-access/SKILL.md b/plugins/ndf-codex/skills/docker-container-access/SKILL.md index 444a993f..bd464ca9 100644 --- a/plugins/ndf-codex/skills/docker-container-access/SKILL.md +++ b/plugins/ndf-codex/skills/docker-container-access/SKILL.md @@ -1,7 +1,6 @@ --- 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'" +description: "Diagnose Docker container access and localhost routing failures. Use when a container is unreachable, localhost does not connect, or DinD/DooD has to be identified. Triggers: 'localhost not working', 'コンテナに接続できない', 'DinD', 'DooD', 'curl container'" allowed-tools: - Read - Bash diff --git a/plugins/ndf-codex/skills/external-ai/SKILL.md b/plugins/ndf-codex/skills/external-ai/SKILL.md index 9684e739..9a959755 100644 --- a/plugins/ndf-codex/skills/external-ai/SKILL.md +++ b/plugins/ndf-codex/skills/external-ai/SKILL.md @@ -1,7 +1,6 @@ --- name: external-ai -description: "Delegate coding, review, or research to an external AI CLI (Codex / Gemini). Use for 'codexで調査', 'geminiレビュー', '第二意見レビュー', 'external AI review', 'codex exec', 'gemini exec'." -when_to_use: "外部 AI へコード生成 / レビュー / 調査を委譲したいとき。追加トリガ: '外部AIに投げて', 'クロスチェックして', 'もう一つのAIに見てもらう', 'CLI で codex を回す'" +description: "Delegate coding, review, or research to an external AI CLI (Codex or Gemini). Use when a second opinion or an offloaded investigation is wanted. Triggers: 'codexで調査', 'geminiレビュー', '第二意見レビュー', 'codex exec', 'gemini exec', '外部AIに投げて'" --- # 外部 AI 委譲スキル (Codex / Gemini) diff --git a/plugins/ndf-codex/skills/fix/SKILL.md b/plugins/ndf-codex/skills/fix/SKILL.md index 32f4c515..99aea9f6 100644 --- a/plugins/ndf-codex/skills/fix/SKILL.md +++ b/plugins/ndf-codex/skills/fix/SKILL.md @@ -1,7 +1,6 @@ --- name: fix -description: "Classify PR review comments, fix the actionable ones, then reply and resolve each thread. Use when responding to PR review feedback from codex, gemini, bots, or humans." -when_to_use: "PR レビューコメントへの対応全般。分類だけしたいときは --classify-only。Triggers: 'PRコメント対応', 'PRレビュー修正', 'PRコメントを確認', 'PRコメントを分類', 'コメント対応の優先度', 'PR fix', 'classify PR comments', 'コメントに対応して修正', 'Resolveして'" +description: "Classify PR review comments, fix the actionable ones, then reply and resolve each thread. Use when responding to review feedback from codex, gemini, bots, or humans on a PR. Triggers: 'PRコメント対応', 'PRレビュー修正', 'PRコメントを分類', 'コメントに対応して修正', 'Resolveして'" argument-hint: "[PR番号] [--classify-only] [--defer-nit] [--severity-min critical|major|minor]" allowed-tools: - Bash diff --git a/plugins/ndf-codex/skills/implementation-plan/SKILL.md b/plugins/ndf-codex/skills/implementation-plan/SKILL.md index 0e0a1307..2d961ee1 100644 --- a/plugins/ndf-codex/skills/implementation-plan/SKILL.md +++ b/plugins/ndf-codex/skills/implementation-plan/SKILL.md @@ -1,7 +1,6 @@ --- name: implementation-plan -description: "Create or update implementation plan files." -when_to_use: "実装開始時 / PR作成時に実装プランの作成・更新が必要なとき。複数ファイル変更・新機能追加・DBマイグレーションを含む変更で自動参照。Triggers: '実装プラン', '実装を開始', 'PR作成', 'implementation plan', 'plan first', '設計書を作成', 'issues/に追加'" +description: "Create or update an implementation plan file under issues/ before coding starts. Use when a change spans multiple files, adds a feature, or includes a DB migration. Triggers: '実装プラン', '実装を開始', 'implementation plan', '設計書を作成', 'issues/に追加'" --- # 実装プランガイド diff --git a/plugins/ndf-codex/skills/investigation-rules/SKILL.md b/plugins/ndf-codex/skills/investigation-rules/SKILL.md index a4757a83..1a20b2d0 100644 --- a/plugins/ndf-codex/skills/investigation-rules/SKILL.md +++ b/plugins/ndf-codex/skills/investigation-rules/SKILL.md @@ -1,7 +1,6 @@ --- name: investigation-rules -description: "Write evidence-backed investigation and debug reports." -when_to_use: "調査・デバッグ・不具合レポートを作成するとき。「ない」「該当なし」等の否定的結論を出すときは必ず参照。Triggers: '調査', 'デバッグ', '不具合レポート', '原因調査', 'investigation', 'root cause', 'カラムがない', '該当コードがない', 'データがない'" +description: "Write evidence-backed investigation and debug reports, and never state a negative finding without showing the search behind it. Use when writing an investigation or bug report. Triggers: '調査レポートを書く', '不具合レポート', '原因調査', 'カラムがない', '該当コードがない'" --- # 調査レポート作成ルール diff --git a/plugins/ndf-codex/skills/issue-plan-strategy/SKILL.md b/plugins/ndf-codex/skills/issue-plan-strategy/SKILL.md index 7f96f04a..26e07fdf 100644 --- a/plugins/ndf-codex/skills/issue-plan-strategy/SKILL.md +++ b/plugins/ndf-codex/skills/issue-plan-strategy/SKILL.md @@ -1,7 +1,6 @@ --- 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 で進めて'" +description: "Turn an issue into a plan, then drive the plan through a release branch, per-PR worktrees, and multi-PR execution. Use when asked to design a plan from an issue or to execute an existing plan. Triggers: 'issueのplanを作って', 'このplanを実装して', 'planを実行', 'release branch 作って実装開始', 'multi-PR で進めて'" argument-hint: "[issue-path-or-url] (例: issues/i16.md, https://github.com/org/repo/issues/123)" allowed-tools: - Bash diff --git a/plugins/ndf-codex/skills/logging-guidelines/SKILL.md b/plugins/ndf-codex/skills/logging-guidelines/SKILL.md index 3ad64b34..56e24879 100644 --- a/plugins/ndf-codex/skills/logging-guidelines/SKILL.md +++ b/plugins/ndf-codex/skills/logging-guidelines/SKILL.md @@ -1,6 +1,6 @@ --- name: logging-guidelines -description: "Choose log levels and write safe, useful application logs when adding or reworking logging in code(ログ追加 / logger / ログレベル / デバッグログ / エラーログ / print文をログに). Use when editing source code that emits logs, to pick the level and keep secrets and personal data out of the output." +description: "Choose log levels and keep secrets and personal data out of application logs. Use when adding, reworking, or reviewing logging in source code. Triggers: 'ログ追加', 'ログレベルを決める', 'ログ設計', 'print文をログに', 'ログに個人情報'" paths: - "**/*.py" - "**/*.ts" diff --git a/plugins/ndf-codex/skills/markdown-writing/SKILL.md b/plugins/ndf-codex/skills/markdown-writing/SKILL.md index 4b4d9488..736b47ce 100644 --- a/plugins/ndf-codex/skills/markdown-writing/SKILL.md +++ b/plugins/ndf-codex/skills/markdown-writing/SKILL.md @@ -1,7 +1,6 @@ --- name: markdown-writing -description: "Write Markdown docs, PR bodies, and reports that read well to a third party." -when_to_use: "Markdown 文書 / 仕様書 / 設計書 / PR 本文 / 調査レポート / 図表を作成・編集するとき。Triggers: 'Markdown作成', 'ドキュメント作成', '文書作成', '仕様書', '設計書', 'PR本文', 'PR説明', '調査レポート', '図を描く', 'mermaid', 'create document', 'write docs', 'write PR description'" +description: "Write Markdown docs, specs, PR bodies, and reports that read well to a third party, including tables and mermaid diagrams. Use when authoring or editing a Markdown document. Triggers: 'ドキュメント作成', 'PR本文', 'PR説明', '仕様書を書く', 'mermaid', 'write docs'" allowed-tools: - Read - Write diff --git a/plugins/ndf-codex/skills/merged/SKILL.md b/plugins/ndf-codex/skills/merged/SKILL.md index 78891b9e..0eeb1939 100644 --- a/plugins/ndf-codex/skills/merged/SKILL.md +++ b/plugins/ndf-codex/skills/merged/SKILL.md @@ -1,8 +1,7 @@ --- name: merged -description: "Clean up after a PR is merged: update main, remove the worktree, and delete merged branches." +description: "Clean up after a PR is merged: update main, remove the worktree, and delete the merged branch. Use when a PR has just been merged or leftover branches and worktrees need clearing. Triggers: 'マージ後の後片付け', 'ブランチを整理', 'worktreeを削除', 'merged cleanup'" argument-hint: "[PR番号]" -disable-model-invocation: true allowed-tools: - Bash - Read diff --git a/plugins/ndf-codex/skills/ndf-policies/SKILL.md b/plugins/ndf-codex/skills/ndf-policies/SKILL.md index ab8becf5..f1a22887 100644 --- a/plugins/ndf-codex/skills/ndf-policies/SKILL.md +++ b/plugins/ndf-codex/skills/ndf-policies/SKILL.md @@ -1,6 +1,6 @@ --- name: ndf-policies -description: "Apply core NDF project policies, including the branch strategy for applying the same fix to environment branches (qa/staging/release) without contaminating feature branches." +description: "Core NDF project policies. 知識として参照するだけで、手順として実行しない。判断に迷ったときの基準として使う: ブランチ戦略、環境ブランチ (qa/staging/release) へ同じ修正を適用する原則、feature ブランチを汚さない運用、PR 運用ルール。" user-invocable: false --- diff --git a/plugins/ndf-codex/skills/plan-to-spec/SKILL.md b/plugins/ndf-codex/skills/plan-to-spec/SKILL.md index eaea6f98..0fdd5ec3 100644 --- a/plugins/ndf-codex/skills/plan-to-spec/SKILL.md +++ b/plugins/ndf-codex/skills/plan-to-spec/SKILL.md @@ -1,6 +1,6 @@ --- name: plan-to-spec -description: "Finalize an implemented plan into a permanent specification document. Use after implementation is complete and an issues/ plan, PLAN file, design note, or implementation plan should become the final as-is specification under docs/ or another authoritative specification location. Triggers: 'planを仕様書にして', '確定仕様書に移動', '実装完了後にplanを整理', 'planをdocsへ移動', '仕様書としてリライト', 'plan-to-spec', 'finalize plan spec'." +description: "Rewrite a finished implementation plan into a permanent specification under docs/. Use when implementation is complete and an issues/ plan should become the as-is specification. Triggers: 'planを仕様書にして', '確定仕様書に移動', 'planをdocsへ移動', 'plan-to-spec'" allowed-tools: - Bash - Read diff --git a/plugins/ndf-codex/skills/playwright-authoring/SKILL.md b/plugins/ndf-codex/skills/playwright-authoring/SKILL.md index 3742e685..e196c902 100644 --- a/plugins/ndf-codex/skills/playwright-authoring/SKILL.md +++ b/plugins/ndf-codex/skills/playwright-authoring/SKILL.md @@ -1,7 +1,6 @@ --- name: playwright-authoring -description: "Create reproducible Playwright test scripts and run them with evidence, or check a page over browser MCP. Use when writing E2E test code, running E2E tests, doing a browser smoke check, or connecting to a remote Chrome over CDP (テストスクリプト作成 / テスト実行 / ブラウザ動作確認 / CDP 接続)." -when_to_use: "テストコード実装 / エビデンス動画・trace 収集 / accessibility・Core Web Vitals 計測 / ブラウザ接続先の変更が必要なとき。Triggers: 'playwright codegen', 'pwk_evidence', 'axe-core', 'WCAG', 'LCP', 'CLS', 'body_check', 'overlay', 'connectOverCDP', 'host.docker.internal', 'remote debugging'" +description: "Write Playwright E2E test scripts and run them with video / trace evidence, or check a page over browser MCP. Use when writing or running E2E tests, doing a browser smoke check, or connecting to Chrome over CDP. Triggers: 'playwright codegen', 'axe-core', 'connectOverCDP', 'ブラウザ動作確認'" argument-hint: "[url]" allowed-tools: - Read diff --git a/plugins/ndf-codex/skills/playwright-evidence/SKILL.md b/plugins/ndf-codex/skills/playwright-evidence/SKILL.md index f66d8edc..cfb6f200 100644 --- a/plugins/ndf-codex/skills/playwright-evidence/SKILL.md +++ b/plugins/ndf-codex/skills/playwright-evidence/SKILL.md @@ -1,7 +1,6 @@ --- name: playwright-evidence -description: "Generate the Playwright test report and store its evidence on Google Drive. Use when generating report.md, sharing E2E test results, or uploading video / trace / HAR evidence to Drive (テストレポート / テスト結果共有 / テスト報告書 / エビデンス保管 / Drive アップロード)." -when_to_use: "レポート生成 / エビデンスのチーム配布 / Drive リンクを埋め込んだ Google Docs 作成が必要なとき。Triggers: 'report.md', 'pwk-drive-folder', 'upload_evidence', 'gdrive_upload_dir', 'trace viewer', 'report を Docs に'" +description: "Generate the Playwright test report and store its evidence on Google Drive. Use when producing report.md, sharing E2E results, or archiving video / trace / HAR evidence. Triggers: 'report.md', 'テスト報告書', 'エビデンスをDriveへ保管', 'trace viewer'" allowed-tools: - Read - Bash(python *) diff --git a/plugins/ndf-codex/skills/playwright-kit-ops/SKILL.md b/plugins/ndf-codex/skills/playwright-kit-ops/SKILL.md index 39cbeb03..ab1a7c0f 100644 --- a/plugins/ndf-codex/skills/playwright-kit-ops/SKILL.md +++ b/plugins/ndf-codex/skills/playwright-kit-ops/SKILL.md @@ -1,7 +1,6 @@ --- name: playwright-kit-ops -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 実行'" +description: "Run the playwright_kit scripts: project init, page-role classification, one-off a11y / CWV scans, and Drive upload helpers. Use when a playwright_kit script has to be run directly. Triggers: 'init_project.sh', 'classify_page_role.py', 'run_a11y_scan.py', 'upload_evidence.py'" allowed-tools: - Read - Bash(python *) diff --git a/plugins/ndf-codex/skills/playwright-planning/SKILL.md b/plugins/ndf-codex/skills/playwright-planning/SKILL.md index 73039aa0..88862956 100644 --- a/plugins/ndf-codex/skills/playwright-planning/SKILL.md +++ b/plugins/ndf-codex/skills/playwright-planning/SKILL.md @@ -1,7 +1,6 @@ --- name: playwright-planning -description: "Plan Playwright E2E tests by judging page role and choosing checklists and test techniques. Use when starting E2E scenario testing, designing test cases, or laying out the whole E2E workflow (テスト計画 / テスト設計 / page role / チェックリスト / シナリオテスト)." -when_to_use: "E2E テスト計画の立案 / page role 分類 / テスト技法の選定 / pytest-playwright ワークフロー全体像の把握が必要なとき。Triggers: 'HTSM', 'ISTQB', 'FEW HICCUPPS', 'ISO 29119', 'テスト観点', 'テスト計画書', 'フル E2E'" +description: "Plan Playwright E2E tests: judge the page role, then pick checklists and test techniques. Use when starting E2E scenario testing or designing test cases. Triggers: 'テスト計画書', 'テスト観点', 'page role 分類', 'HTSM', 'ISTQB', 'FEW HICCUPPS'" allowed-tools: - Read - Bash(python *) diff --git a/plugins/ndf-codex/skills/pr-tests/SKILL.md b/plugins/ndf-codex/skills/pr-tests/SKILL.md index 39f13de3..836146d2 100644 --- a/plugins/ndf-codex/skills/pr-tests/SKILL.md +++ b/plugins/ndf-codex/skills/pr-tests/SKILL.md @@ -1,8 +1,7 @@ --- name: pr-tests -description: "Run PR test plans and comment results." +description: "Run the test plan written in a PR body and post the results back as a PR comment. Use when a PR test plan has to be executed and reported. Triggers: 'PRのテストを実行', 'テストプランを実行', 'テスト結果をPRにコメント'" argument-hint: "[PR番号]" -disable-model-invocation: true allowed-tools: - Bash - Read diff --git a/plugins/ndf-codex/skills/pr/SKILL.md b/plugins/ndf-codex/skills/pr/SKILL.md index 3bfe6b16..dfe4ae48 100644 --- a/plugins/ndf-codex/skills/pr/SKILL.md +++ b/plugins/ndf-codex/skills/pr/SKILL.md @@ -1,8 +1,7 @@ --- name: pr -description: "Commit, push, and create or update PRs." +description: "Commit, push, and create or update a pull request for the current branch. Use when asked to commit and open a PR, update an existing PR, or push work for review. Triggers: 'PRを作って', 'PR作成', 'コミットしてプッシュ', 'PRを更新', 'draft PR'" argument-hint: "[--draft] [base-branch] or [commit-message]" -disable-model-invocation: true allowed-tools: - Bash - Read diff --git a/plugins/ndf-codex/skills/problem-solving/SKILL.md b/plugins/ndf-codex/skills/problem-solving/SKILL.md index 94133205..56b0dfbb 100644 --- a/plugins/ndf-codex/skills/problem-solving/SKILL.md +++ b/plugins/ndf-codex/skills/problem-solving/SKILL.md @@ -1,7 +1,6 @@ --- 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'" +description: "Solve bugs, incidents, and data inconsistencies at the root cause instead of patching downstream. Use when a bug, outage, or data inconsistency needs a fix decision. Triggers: 'バグの根本原因', 'データ不整合', '障害対応', 'root cause analysis', '上流で直す', 'patch vs fix'" --- # 問題解決ガイドライン diff --git a/plugins/ndf-codex/skills/qa-security-scan/01-owasp-checklist.md b/plugins/ndf-codex/skills/qa-security-scan/01-owasp-checklist.md new file mode 100644 index 00000000..797015b2 --- /dev/null +++ b/plugins/ndf-codex/skills/qa-security-scan/01-owasp-checklist.md @@ -0,0 +1,298 @@ +# OWASP Top 10 詳細チェックリスト + +## 1. インジェクション + +**脆弱性の説明**: +信頼できないデータがコマンドやクエリの一部として送信され、攻撃者が意図しないコマンドを実行したり、適切な認可なしにデータにアクセスしたりできる。 + +**チェック項目**: + +- [ ] **SQLインジェクション対策** + ```javascript + // ❌ Bad: 文字列連結 + const query = `SELECT * FROM users WHERE id = ${userId}`; + + // ✅ Good: パラメータ化クエリ + const query = 'SELECT * FROM users WHERE id = ?'; + db.query(query, [userId]); + ``` + +- [ ] **コマンドインジェクション対策** + ```javascript + // ❌ Bad: ユーザー入力を直接使用 + exec(`ping ${userInput}`); + + // ✅ Good: ホワイトリスト検証 + エスケープ + if (!/^[a-zA-Z0-9.-]+$/.test(userInput)) { + throw new Error('Invalid input'); + } + ``` + +- [ ] **LDAPインジェクション対策** + - 特殊文字のエスケープ + - パラメータ化クエリの使用 + +- [ ] **NoSQLインジェクション対策** + ```javascript + // ❌ Bad: オブジェクトを直接使用 + User.find({ username: req.body.username }); + + // ✅ Good: 型検証 + const username = String(req.body.username); + User.find({ username }); + ``` + +**修正方法**: +1. パラメータ化クエリ/プリペアドステートメント使用 +2. ORMの使用(Sequelize、TypeORM等) +3. 入力値の厳格な検証(ホワイトリスト) +4. エスケープ処理 + +## 2. 認証の不備 + +**チェック項目**: + +- [ ] **パスワードの安全なハッシュ化** + ```javascript + // ❌ Bad: 平文保存、MD5/SHA1 + const hash = md5(password); + + // ✅ Good: bcrypt/Argon2 + const bcrypt = require('bcrypt'); + const hash = await bcrypt.hash(password, 10); + ``` + +- [ ] **セッション管理** + - セッションIDの再生成(ログイン後) + - セキュアなCookie設定(HttpOnly, Secure, SameSite) + - セッションタイムアウトの設定 + +- [ ] **多要素認証(MFA)** + - 重要な操作でMFA要求 + - TOTPまたはSMS認証 + +- [ ] **ブルートフォース攻撃対策** + - レート制限(rate limiting) + - アカウントロックアウト + - CAPTCHA + +- [ ] **パスワードポリシー** + - 最小8文字以上 + - 大文字、小文字、数字、記号の組み合わせ + - 過去のパスワードの再利用禁止 + +**修正方法**: +1. bcrypt/Argon2でパスワードをハッシュ化 +2. JWTトークンまたはセキュアなセッション管理 +3. express-rate-limitでレート制限 +4. パスワードポリシーの強制 + +## 3. 機密データの露出 + +**チェック項目**: + +- [ ] **通信の暗号化** + - HTTPS/TLS 1.2以上の使用 + - HTTP Strict Transport Security (HSTS) ヘッダー + +- [ ] **保存時の暗号化** + ```javascript + // ✅ Good: AES-256で暗号化 + const crypto = require('crypto'); + const algorithm = 'aes-256-cbc'; + const key = crypto.randomBytes(32); + const iv = crypto.randomBytes(16); + + function encrypt(text) { + const cipher = crypto.createCipheriv(algorithm, key, iv); + let encrypted = cipher.update(text, 'utf8', 'hex'); + encrypted += cipher.final('hex'); + return encrypted; + } + ``` + +- [ ] **機密情報のログ出力禁止** + ```javascript + // ❌ Bad + console.log('User password:', password); + logger.info('Credit card:', creditCard); + + // ✅ Good + logger.info('User authenticated', { userId: user.id }); + ``` + +- [ ] **APIキー・シークレットの管理** + - 環境変数で管理 + - .envファイルは.gitignoreに追加 + - AWS Secrets Manager / HashiCorp Vault 等の使用 + +**修正方法**: +1. すべての通信をHTTPS化 +2. 機密データの暗号化(AES-256) +3. 環境変数で機密情報を管理 +4. ログに機密情報を出力しない + +## 4. XXE(XML External Entity) + +**チェック項目**: + +- [ ] **XML パーサーの安全な設定** + ```javascript + // ✅ Good: DTD処理を無効化 + const { XMLParser } = require('fast-xml-parser'); + const parser = new XMLParser({ + ignoreAttributes: false, + processEntities: false // DTD処理を無効化 + }); + ``` + +- [ ] **外部エンティティの禁止** +- [ ] **DTD処理の無効化** + +**修正方法**: +1. XML パーサーでDTD処理を無効化 +2. 外部エンティティの参照を禁止 +3. 可能であればJSONを使用 + +## 5. アクセス制御の不備 + +**チェック項目**: + +- [ ] **認可チェックの実装** + ```javascript + // ✅ Good: ミドルウェアで認可チェック + function requireAdmin(req, res, next) { + if (req.user.role !== 'admin') { + return res.status(403).json({ error: 'Forbidden' }); + } + next(); + } + + app.delete('/api/users/:id', authMiddleware, requireAdmin, deleteUser); + ``` + +- [ ] **ロールベースアクセス制御(RBAC)** + - ユーザーごとにロール設定 + - リソースごとに必要なロールを定義 + +- [ ] **オブジェクトレベルの認可** + ```javascript + // ❌ Bad: IDだけで削除 + app.delete('/api/posts/:id', async (req, res) => { + await Post.destroy({ where: { id: req.params.id } }); + }); + + // ✅ Good: 所有者チェック + app.delete('/api/posts/:id', authMiddleware, async (req, res) => { + const post = await Post.findByPk(req.params.id); + if (post.userId !== req.user.id) { + return res.status(403).json({ error: 'Forbidden' }); + } + await post.destroy(); + }); + ``` + +- [ ] **IDORの防止**(Insecure Direct Object Reference) + +**修正方法**: +1. すべてのAPIエンドポイントで認可チェック +2. ロールベースアクセス制御の実装 +3. オブジェクトの所有者確認 + +## 6. セキュリティ設定ミス + +**チェック項目**: + +- [ ] **デフォルトパスワードの変更** +- [ ] **不要なサービスの無効化** +- [ ] **セキュリティヘッダーの設定** + ```javascript + // ✅ Good: helmet.js でセキュリティヘッダー設定 + const helmet = require('helmet'); + app.use(helmet()); + app.use(helmet.contentSecurityPolicy({ + directives: { + defaultSrc: ["'self'"], + scriptSrc: ["'self'", "'unsafe-inline'"], + styleSrc: ["'self'", "'unsafe-inline'"] + } + })); + ``` + +- [ ] **エラーメッセージの適切化** + ```javascript + // ❌ Bad: 詳細なエラーを公開 + res.status(500).json({ error: error.stack }); + + // ✅ Good: 一般的なエラーメッセージ + res.status(500).json({ error: 'Internal server error' }); + // 詳細はログに記録 + logger.error('Error details:', error); + ``` + +- [ ] **CORSの適切な設定** + ```javascript + // ✅ Good: 特定のオリジンのみ許可 + const cors = require('cors'); + app.use(cors({ + origin: 'https://example.com', + credentials: true + })); + ``` + +**修正方法**: +1. helmet.js でセキュリティヘッダー設定 +2. 環境別の設定(開発/本番) +3. エラーメッセージは一般的に、詳細はログに + +## 7. XSS(クロスサイトスクリプティング) + +**チェック項目**: + +- [ ] **HTMLエスケープ** + ```javascript + // ❌ Bad: 直接HTMLに挿入 + document.getElementById('output').innerHTML = userInput; + + // ✅ Good: エスケープして挿入 + document.getElementById('output').textContent = userInput; + + // または DOMPurify を使用 + import DOMPurify from 'dompurify'; + const clean = DOMPurify.sanitize(userInput); + ``` + +- [ ] **Content-Security-Policy (CSP) 設定** +- [ ] **HTTPOnlyクッキー** + ```javascript + // ✅ Good: HTTPOnly, Secure, SameSite + res.cookie('token', token, { + httpOnly: true, + secure: true, + sameSite: 'strict' + }); + ``` + +- [ ] **DOMベースXSS対策** + - `eval()`, `innerHTML`, `document.write()` を避ける + +**修正方法**: +1. すべての出力をエスケープ +2. Content-Security-Policy ヘッダー設定 +3. DOMPurifyなどのサニタイゼーションライブラリ使用 + +## 8-10. その他の脆弱性 + +**8. 安全でないデシリアライゼーション** +- [ ] 信頼できないデータのデシリアライズ禁止 +- [ ] 署名・検証の実装 + +**9. 既知の脆弱性があるコンポーネント** +- [ ] 依存ライブラリの最新化 +- [ ] `npm audit` / `pip-audit` の実行 +- [ ] Dependabot / Renovate の利用 + +**10. ログとモニタリングの不足** +- [ ] セキュリティイベントのログ +- [ ] 異常検知の仕組み +- [ ] 定期的なログレビュー diff --git a/plugins/ndf-codex/skills/qa-security-scan/02-auth-checklist.md b/plugins/ndf-codex/skills/qa-security-scan/02-auth-checklist.md new file mode 100644 index 00000000..0ff70595 --- /dev/null +++ b/plugins/ndf-codex/skills/qa-security-scan/02-auth-checklist.md @@ -0,0 +1,127 @@ +# 認証・認可チェックリスト + +## 認証テスト + +### ログイン機能 + +- [ ] **正しい認証情報でログイン成功** +- [ ] **誤った認証情報でログイン失敗** +- [ ] **パスワード忘れ機能** + - リセットリンクの有効期限 + - リセット後の古いリンク無効化 + +### セッション管理 + +- [ ] **ログアウト後にセッション無効化** +- [ ] **セッションタイムアウト** + - アイドルタイムアウト(15-30分推奨) + - 絶対タイムアウト(8-24時間推奨) +- [ ] **同時ログインの制限** + - 必要に応じて制限を実装 + - 新規ログイン時に既存セッションを無効化 + +### トークン管理(JWT) + +- [ ] **トークン有効期限** + - アクセストークン: 15分-1時間 + - リフレッシュトークン: 7-30日 +- [ ] **トークンリフレッシュ** + - リフレッシュトークンのローテーション +- [ ] **署名検証** + - 強力な秘密鍵の使用 + - アルゴリズムの明示的指定 + +```javascript +// ✅ Good: JWT検証 +const jwt = require('jsonwebtoken'); + +function verifyToken(token) { + return jwt.verify(token, process.env.JWT_SECRET, { + algorithms: ['HS256'], // アルゴリズムを明示 + issuer: 'your-app', + audience: 'your-users' + }); +} +``` + +## 認可テスト + +### ロールベースアクセス制御 + +- [ ] **管理者のみアクセス可能なリソース** + - /admin/* へのアクセス制限 + - 管理機能の認可チェック +- [ ] **一般ユーザーの権限制限** + - 他ユーザーのデータへのアクセス禁止 + - 機能制限の適用 + +### リソース所有者チェック + +- [ ] **自分のリソースのみ編集・削除可能** + +```javascript +// ✅ Good: 所有者チェック +async function updateResource(req, res) { + const resource = await Resource.findByPk(req.params.id); + + if (!resource) { + return res.status(404).json({ error: 'Not found' }); + } + + // 所有者または管理者のみ許可 + if (resource.userId !== req.user.id && req.user.role !== 'admin') { + return res.status(403).json({ error: 'Forbidden' }); + } + + await resource.update(req.body); + res.json(resource); +} +``` + +## テストケース例 + +### 認証バイパステスト + +``` +1. 認証なしで保護されたエンドポイントにアクセス + → 401 Unauthorized が返ること + +2. 無効なトークンでアクセス + → 401 Unauthorized が返ること + +3. 期限切れトークンでアクセス + → 401 Unauthorized が返ること + +4. 改ざんされたトークンでアクセス + → 401 Unauthorized が返ること +``` + +### 権限昇格テスト + +``` +1. 一般ユーザーで管理者APIにアクセス + → 403 Forbidden が返ること + +2. ユーザーAでユーザーBのリソースを編集 + → 403 Forbidden が返ること + +3. URLのIDを変更して他ユーザーのデータにアクセス + → 403 Forbidden が返ること +``` + +## 実装チェックリスト + +### 必須実装 + +- [ ] パスワードはbcrypt/Argon2でハッシュ化 +- [ ] セッション/トークンにはセキュアなCookie設定 +- [ ] すべてのAPIエンドポイントに認証ミドルウェア +- [ ] 認可チェックは各リソースアクセス時に実行 +- [ ] レート制限を実装 + +### 推奨実装 + +- [ ] 多要素認証(MFA) +- [ ] パスワード強度チェック +- [ ] ログイン試行回数制限 +- [ ] セキュリティログの記録 diff --git a/plugins/ndf-codex/skills/qa-security-scan/03-report-template.md b/plugins/ndf-codex/skills/qa-security-scan/03-report-template.md new file mode 100644 index 00000000..6ad9f7ec --- /dev/null +++ b/plugins/ndf-codex/skills/qa-security-scan/03-report-template.md @@ -0,0 +1,144 @@ +# セキュリティレポートテンプレート + +## 使用方法 + +このテンプレートをコピーして、セキュリティスキャン結果を報告してください。 + +--- + +# セキュリティスキャンレポート - [アプリケーション名] + +## エグゼクティブサマリー + +- **スキャン日**: YYYY-MM-DD +- **スキャン範囲**: [対象範囲の説明] +- **重大な脆弱性**: X件 +- **警告**: Y件 +- **情報**: Z件 + +## 重大な脆弱性 (Critical/High) + +### 1. [脆弱性名] + +- **場所**: [ファイルパス/エンドポイント] +- **リスクレベル**: 高 +- **説明**: [脆弱性の詳細説明] +- **影響**: [悪用された場合の影響] +- **修正方法**: + ```javascript + // 修正前 + [問題のあるコード] + + // 修正後 + [修正されたコード] + ``` +- **優先度**: 最高(即座に修正) + +### 2. [脆弱性名] + +[同様のフォーマットで記載] + +## 警告 (Medium) + +### 3. [脆弱性名] + +- **場所**: [ファイルパス/エンドポイント] +- **リスクレベル**: 中 +- **説明**: [脆弱性の詳細説明] +- **修正方法**: [修正方法の説明] + +## 情報 (Low/Info) + +### 4. [項目名] + +- **場所**: [ファイルパス/エンドポイント] +- **説明**: [詳細説明] +- **推奨事項**: [推奨される対応] + +## 推奨事項 + +1. **即座に修正**: 重大な脆弱性X件 +2. **1週間以内に修正**: 警告Y件 +3. **セキュリティヘッダー追加**: helmet.js 使用 +4. **依存ライブラリの更新**: npm audit で検出された脆弱性 +5. **定期的なセキュリティスキャン**: 月1回の実施 + +## 次のステップ + +1. [ ] 重大な脆弱性の修正 +2. [ ] 修正後の再スキャン +3. [ ] ペネトレーションテストの実施 +4. [ ] セキュリティ監視の強化 + +--- + +## レポート作成のポイント + +### リスクレベルの判断基準 + +| レベル | 基準 | +|--------|------| +| Critical | リモートコード実行、認証バイパス、データ全体へのアクセス | +| High | SQLインジェクション、XSS(保存型)、権限昇格 | +| Medium | XSS(反射型)、CSRF、情報漏洩(限定的) | +| Low | セキュリティヘッダー不足、詳細なエラーメッセージ | +| Info | ベストプラクティスからの逸脱 | + +### 修正優先度 + +1. **即座に**: Critical/High(本番環境に影響) +2. **1週間以内**: Medium(悪用の可能性あり) +3. **次回リリース**: Low/Info(改善推奨) + +## Codex CLI 連携 + +詳細な独立レビューが必要な場合は `corder` エージェントに委譲するか、`/ndf:external-ai` skill の手順で `codex exec` を直接起動する。例: + +```bash +# === 1. プロンプト書き出し(最終出力先を明示し apply_patch で書かせる) === +FINAL=/tmp/codex-output-sec-scan.md + +cat > /tmp/sec-scan-prompt.md < /tmp/sec-scan-stdout.md \ + 2> /tmp/sec-scan-err.log & + +# === 3. 完了確認(^tokens used$ sentinel を待つ。`ps -p` は zombie を生存と誤判定する) === +until grep -q '^tokens used$' /tmp/sec-scan-err.log 2>/dev/null; do + sleep 30 +done + +# === 4. 成果物を回収(ファイル → stdout → stderr の三段フォールバック) === +if [ -s "$FINAL" ]; then + cp "$FINAL" ./sec-scan-result.md +elif [ -s /tmp/sec-scan-stdout.md ]; then + cp /tmp/sec-scan-stdout.md ./sec-scan-result.md + echo "WARN: stdout からフォールバック回収(ファイル書き出しなし)" >&2 +else + echo "ERROR: Codex の最終出力を回収できませんでした。stderr 末尾を確認:" >&2 + tail -200 /tmp/sec-scan-err.log +fi +``` + +詳細は `/ndf:external-ai` skill と `references/cli-codex.md` を参照。 diff --git a/plugins/ndf-codex/skills/qa-security-scan/SKILL.md b/plugins/ndf-codex/skills/qa-security-scan/SKILL.md new file mode 100644 index 00000000..b741edaa --- /dev/null +++ b/plugins/ndf-codex/skills/qa-security-scan/SKILL.md @@ -0,0 +1,55 @@ +--- +name: qa-security-scan +description: "Run an OWASP Top 10 security review of code, authentication, authorization, and data protection. Use when asked for a security review of a change or a vulnerability check. Triggers: 'セキュリティレビュー', 'セキュリティスキャン', '脆弱性チェック', 'OWASP', '認証認可の確認', 'SQLインジェクション'" +--- + +# QA Security Scan Skill + +## 概要 + +セキュリティスキャンと脆弱性評価を実施する際に使用します。OWASP Top 10に基づいた包括的なチェックリストと、認証・認可・データ保護の検証手順を提供します。 + +## クイックリファレンス + +### OWASP Top 10 概要 + +| # | 脆弱性 | 主な対策 | +|---|--------|----------| +| 1 | インジェクション | パラメータ化クエリ、ORM使用 | +| 2 | 認証の不備 | bcrypt/Argon2、MFA、レート制限 | +| 3 | 機密データ露出 | HTTPS、暗号化、環境変数管理 | +| 4 | XXE | DTD処理無効化、JSON使用 | +| 5 | アクセス制御不備 | RBAC、所有者チェック | +| 6 | 設定ミス | helmet.js、適切なCORS | +| 7 | XSS | エスケープ、CSP、DOMPurify | +| 8 | デシリアライゼーション | 署名検証、信頼できるデータのみ | +| 9 | 既知の脆弱性 | npm audit、Dependabot | +| 10 | ログ不足 | セキュリティイベント記録 | + +### 基本的な使い方 + +1. 対象コードを特定 +2. 該当するチェックリストを適用 +3. 脆弱性を発見したらレポート作成 +4. 修正方法を提案 + +## ベストプラクティス + +| DO | DON'T | +|----|-------| +| 定期的なスキャン(月1回以上) | スキャンのみで満足 | +| CI/CDパイプラインに統合 | 警告を無視 | +| 重大度順に対応(高→低) | 本番環境で初スキャン | +| 修正後に再スキャン | 自動化ツールに全依存 | + +## 詳細ガイド + +| ファイル | 内容 | +|---------|------| +| `01-owasp-checklist.md` | OWASP Top 10 詳細チェックリストとコード例 | +| `02-auth-checklist.md` | 認証・認可テスト手順 | +| `03-report-template.md` | セキュリティレポートテンプレート | + +## 関連Skill + +- **corder-code-templates**: セキュアなコードテンプレート diff --git a/plugins/ndf-codex/skills/review/SKILL.md b/plugins/ndf-codex/skills/review/SKILL.md index 2afd42e2..fefe037d 100644 --- a/plugins/ndf-codex/skills/review/SKILL.md +++ b/plugins/ndf-codex/skills/review/SKILL.md @@ -1,9 +1,8 @@ --- name: review -description: "Review a PR diff, or the current branch diff with --branch, and post an approve or request-changes verdict." -when_to_use: "PR をレビューするとき、および PR 作成前にローカルブランチをセルフレビューするとき (--branch)。Triggers: 'レビューして', 'PRレビュー', 'マージ前チェック', 'ブランチをレビュー', 'セルフレビュー', 'PR前にレビュー', 'review my branch', 'self review', 'pre-PR review'" +description: "Review a PR diff, or the current branch diff with --branch, and post an approve or request-changes verdict. Use when asked to review a PR, check a diff before merge, or self-review a branch. Triggers: 'レビューして', 'PRレビュー', 'マージ前チェック', 'ブランチをレビュー', 'セルフレビュー'" argument-hint: "[PR番号 | --branch] [AIエージェント(codex|gemini)] [--focus AREA]" -disable-model-invocation: true +effort: high allowed-tools: - Bash - Read diff --git a/plugins/ndf-kiro/skills/cherry-pick-pr/SKILL.md b/plugins/ndf-kiro/skills/cherry-pick-pr/SKILL.md index 1de3823b..4228d90d 100644 --- a/plugins/ndf-kiro/skills/cherry-pick-pr/SKILL.md +++ b/plugins/ndf-kiro/skills/cherry-pick-pr/SKILL.md @@ -1,7 +1,7 @@ --- name: cherry-pick-pr -description: "Create cherry-pick PRs for environment branches and apply the same fix across multiple branches." -argument-hint: " (例: qa/staging, release/v2)" +description: "Cherry-pick a merged fix onto environment branches (qa/staging, release) as a new PR. 破壊的操作のため、利用者が /ndf:cherry-pick-pr を明示的に指示したときのみ実行する。Triggers: 'cherry-pick', 'qaにも同じ修正を適用', 'stagingにも反映', 'release branchへ適用', 'multi-branch fix'" +argument-hint: "ベースブランチ名 (例: qa/staging, release/v2)" disable-model-invocation: true allowed-tools: - Bash diff --git a/plugins/ndf-kiro/skills/cross-review/SKILL.md b/plugins/ndf-kiro/skills/cross-review/SKILL.md index 676c381e..a23cb3d1 100644 --- a/plugins/ndf-kiro/skills/cross-review/SKILL.md +++ b/plugins/ndf-kiro/skills/cross-review/SKILL.md @@ -1,7 +1,6 @@ --- name: cross-review -description: "Run iterative Codex and Gemini PR reviews." -when_to_use: "PR を codex + gemini 両方でレビューし、両者 APPROVE まで自動収束させたいときに限定して使う。明示トリガ: 'cross-review', 'クロスレビュー', '両AIレビュー', '収束レビュー', 'codex と gemini でレビュー'。通常の単発 PR レビュー依頼 (第二意見が 1 回欲しい等) は本 skill を選ばず /ndf:review を使う。重い収束ループ (codex+gemini を複数ラウンド起動) のため、単発レビューと責務を明確に分ける。" +description: "Review a PR with both Codex and Gemini, looping fixes until both APPROVE. Use when a converging two-AI review is wanted; for a one-shot second opinion use /ndf:review. Triggers: 'cross-review', 'クロスレビュー', '両AIレビュー', '収束レビュー', 'codex と gemini でレビュー'" argument-hint: "[PR番号] [--max-rounds N] [--rotate-after K] [--rotate-mode light|squash] [--only codex|gemini] [--focus TEXT] [--extra-instructions-file PATH]" allowed-tools: - Bash diff --git a/plugins/ndf-kiro/skills/deploy/SKILL.md b/plugins/ndf-kiro/skills/deploy/SKILL.md index 8bca071b..c4baa425 100644 --- a/plugins/ndf-kiro/skills/deploy/SKILL.md +++ b/plugins/ndf-kiro/skills/deploy/SKILL.md @@ -1,7 +1,7 @@ --- name: deploy -description: "Create a deploy PR from the current feature branch to an environment branch such as qa/staging or release/v2. 破壊的操作のため、利用者が /ndf:deploy を明示的に指示したときのみ実行する(環境ブランチへデプロイ / qaに上げる / stagingに反映 / リリースブランチへPR)。deployブランチを作成し origin/main を取り込んでからPRを出す。" -argument-hint: " (例: qa/staging, release/v2)" +description: "Create a deploy PR from the current feature branch to an environment branch such as qa/staging or release/v2. 破壊的操作のため、利用者が /ndf:deploy を明示的に指示したときのみ実行する。Triggers: '環境ブランチへデプロイ', 'qaに上げる', 'stagingへデプロイ', 'リリースブランチへPR'" +argument-hint: "環境ブランチ名 (例: qa/staging, release/v2)" disable-model-invocation: true allowed-tools: - Bash diff --git a/plugins/ndf-kiro/skills/docker-container-access/SKILL.md b/plugins/ndf-kiro/skills/docker-container-access/SKILL.md index 444a993f..bd464ca9 100644 --- a/plugins/ndf-kiro/skills/docker-container-access/SKILL.md +++ b/plugins/ndf-kiro/skills/docker-container-access/SKILL.md @@ -1,7 +1,6 @@ --- 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'" +description: "Diagnose Docker container access and localhost routing failures. Use when a container is unreachable, localhost does not connect, or DinD/DooD has to be identified. Triggers: 'localhost not working', 'コンテナに接続できない', 'DinD', 'DooD', 'curl container'" allowed-tools: - Read - Bash diff --git a/plugins/ndf-kiro/skills/external-ai/SKILL.md b/plugins/ndf-kiro/skills/external-ai/SKILL.md index 9684e739..9a959755 100644 --- a/plugins/ndf-kiro/skills/external-ai/SKILL.md +++ b/plugins/ndf-kiro/skills/external-ai/SKILL.md @@ -1,7 +1,6 @@ --- name: external-ai -description: "Delegate coding, review, or research to an external AI CLI (Codex / Gemini). Use for 'codexで調査', 'geminiレビュー', '第二意見レビュー', 'external AI review', 'codex exec', 'gemini exec'." -when_to_use: "外部 AI へコード生成 / レビュー / 調査を委譲したいとき。追加トリガ: '外部AIに投げて', 'クロスチェックして', 'もう一つのAIに見てもらう', 'CLI で codex を回す'" +description: "Delegate coding, review, or research to an external AI CLI (Codex or Gemini). Use when a second opinion or an offloaded investigation is wanted. Triggers: 'codexで調査', 'geminiレビュー', '第二意見レビュー', 'codex exec', 'gemini exec', '外部AIに投げて'" --- # 外部 AI 委譲スキル (Codex / Gemini) diff --git a/plugins/ndf-kiro/skills/fix/SKILL.md b/plugins/ndf-kiro/skills/fix/SKILL.md index 74e038b9..e2314e62 100644 --- a/plugins/ndf-kiro/skills/fix/SKILL.md +++ b/plugins/ndf-kiro/skills/fix/SKILL.md @@ -1,7 +1,6 @@ --- name: fix -description: "Classify PR review comments, fix the actionable ones, then reply and resolve each thread. Use when responding to PR review feedback from codex, gemini, bots, or humans." -when_to_use: "PR レビューコメントへの対応全般。分類だけしたいときは --classify-only。Triggers: 'PRコメント対応', 'PRレビュー修正', 'PRコメントを確認', 'PRコメントを分類', 'コメント対応の優先度', 'PR fix', 'classify PR comments', 'コメントに対応して修正', 'Resolveして'" +description: "Classify PR review comments, fix the actionable ones, then reply and resolve each thread. Use when responding to review feedback from codex, gemini, bots, or humans on a PR. Triggers: 'PRコメント対応', 'PRレビュー修正', 'PRコメントを分類', 'コメントに対応して修正', 'Resolveして'" argument-hint: "[PR番号] [--classify-only] [--defer-nit] [--severity-min critical|major|minor]" allowed-tools: - Bash diff --git a/plugins/ndf-kiro/skills/implementation-plan/SKILL.md b/plugins/ndf-kiro/skills/implementation-plan/SKILL.md index 0e0a1307..2d961ee1 100644 --- a/plugins/ndf-kiro/skills/implementation-plan/SKILL.md +++ b/plugins/ndf-kiro/skills/implementation-plan/SKILL.md @@ -1,7 +1,6 @@ --- name: implementation-plan -description: "Create or update implementation plan files." -when_to_use: "実装開始時 / PR作成時に実装プランの作成・更新が必要なとき。複数ファイル変更・新機能追加・DBマイグレーションを含む変更で自動参照。Triggers: '実装プラン', '実装を開始', 'PR作成', 'implementation plan', 'plan first', '設計書を作成', 'issues/に追加'" +description: "Create or update an implementation plan file under issues/ before coding starts. Use when a change spans multiple files, adds a feature, or includes a DB migration. Triggers: '実装プラン', '実装を開始', 'implementation plan', '設計書を作成', 'issues/に追加'" --- # 実装プランガイド diff --git a/plugins/ndf-kiro/skills/investigation-rules/SKILL.md b/plugins/ndf-kiro/skills/investigation-rules/SKILL.md index a4757a83..1a20b2d0 100644 --- a/plugins/ndf-kiro/skills/investigation-rules/SKILL.md +++ b/plugins/ndf-kiro/skills/investigation-rules/SKILL.md @@ -1,7 +1,6 @@ --- name: investigation-rules -description: "Write evidence-backed investigation and debug reports." -when_to_use: "調査・デバッグ・不具合レポートを作成するとき。「ない」「該当なし」等の否定的結論を出すときは必ず参照。Triggers: '調査', 'デバッグ', '不具合レポート', '原因調査', 'investigation', 'root cause', 'カラムがない', '該当コードがない', 'データがない'" +description: "Write evidence-backed investigation and debug reports, and never state a negative finding without showing the search behind it. Use when writing an investigation or bug report. Triggers: '調査レポートを書く', '不具合レポート', '原因調査', 'カラムがない', '該当コードがない'" --- # 調査レポート作成ルール diff --git a/plugins/ndf-kiro/skills/issue-plan-strategy/SKILL.md b/plugins/ndf-kiro/skills/issue-plan-strategy/SKILL.md index 7f96f04a..26e07fdf 100644 --- a/plugins/ndf-kiro/skills/issue-plan-strategy/SKILL.md +++ b/plugins/ndf-kiro/skills/issue-plan-strategy/SKILL.md @@ -1,7 +1,6 @@ --- 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 で進めて'" +description: "Turn an issue into a plan, then drive the plan through a release branch, per-PR worktrees, and multi-PR execution. Use when asked to design a plan from an issue or to execute an existing plan. Triggers: 'issueのplanを作って', 'このplanを実装して', 'planを実行', 'release branch 作って実装開始', 'multi-PR で進めて'" argument-hint: "[issue-path-or-url] (例: issues/i16.md, https://github.com/org/repo/issues/123)" allowed-tools: - Bash diff --git a/plugins/ndf-kiro/skills/logging-guidelines/SKILL.md b/plugins/ndf-kiro/skills/logging-guidelines/SKILL.md index 3ad64b34..56e24879 100644 --- a/plugins/ndf-kiro/skills/logging-guidelines/SKILL.md +++ b/plugins/ndf-kiro/skills/logging-guidelines/SKILL.md @@ -1,6 +1,6 @@ --- name: logging-guidelines -description: "Choose log levels and write safe, useful application logs when adding or reworking logging in code(ログ追加 / logger / ログレベル / デバッグログ / エラーログ / print文をログに). Use when editing source code that emits logs, to pick the level and keep secrets and personal data out of the output." +description: "Choose log levels and keep secrets and personal data out of application logs. Use when adding, reworking, or reviewing logging in source code. Triggers: 'ログ追加', 'ログレベルを決める', 'ログ設計', 'print文をログに', 'ログに個人情報'" paths: - "**/*.py" - "**/*.ts" diff --git a/plugins/ndf-kiro/skills/markdown-writing/SKILL.md b/plugins/ndf-kiro/skills/markdown-writing/SKILL.md index 4b4d9488..736b47ce 100644 --- a/plugins/ndf-kiro/skills/markdown-writing/SKILL.md +++ b/plugins/ndf-kiro/skills/markdown-writing/SKILL.md @@ -1,7 +1,6 @@ --- name: markdown-writing -description: "Write Markdown docs, PR bodies, and reports that read well to a third party." -when_to_use: "Markdown 文書 / 仕様書 / 設計書 / PR 本文 / 調査レポート / 図表を作成・編集するとき。Triggers: 'Markdown作成', 'ドキュメント作成', '文書作成', '仕様書', '設計書', 'PR本文', 'PR説明', '調査レポート', '図を描く', 'mermaid', 'create document', 'write docs', 'write PR description'" +description: "Write Markdown docs, specs, PR bodies, and reports that read well to a third party, including tables and mermaid diagrams. Use when authoring or editing a Markdown document. Triggers: 'ドキュメント作成', 'PR本文', 'PR説明', '仕様書を書く', 'mermaid', 'write docs'" allowed-tools: - Read - Write diff --git a/plugins/ndf-kiro/skills/merged/SKILL.md b/plugins/ndf-kiro/skills/merged/SKILL.md index 78891b9e..0eeb1939 100644 --- a/plugins/ndf-kiro/skills/merged/SKILL.md +++ b/plugins/ndf-kiro/skills/merged/SKILL.md @@ -1,8 +1,7 @@ --- name: merged -description: "Clean up after a PR is merged: update main, remove the worktree, and delete merged branches." +description: "Clean up after a PR is merged: update main, remove the worktree, and delete the merged branch. Use when a PR has just been merged or leftover branches and worktrees need clearing. Triggers: 'マージ後の後片付け', 'ブランチを整理', 'worktreeを削除', 'merged cleanup'" argument-hint: "[PR番号]" -disable-model-invocation: true allowed-tools: - Bash - Read diff --git a/plugins/ndf-kiro/skills/ndf-policies/SKILL.md b/plugins/ndf-kiro/skills/ndf-policies/SKILL.md index ab8becf5..f1a22887 100644 --- a/plugins/ndf-kiro/skills/ndf-policies/SKILL.md +++ b/plugins/ndf-kiro/skills/ndf-policies/SKILL.md @@ -1,6 +1,6 @@ --- name: ndf-policies -description: "Apply core NDF project policies, including the branch strategy for applying the same fix to environment branches (qa/staging/release) without contaminating feature branches." +description: "Core NDF project policies. 知識として参照するだけで、手順として実行しない。判断に迷ったときの基準として使う: ブランチ戦略、環境ブランチ (qa/staging/release) へ同じ修正を適用する原則、feature ブランチを汚さない運用、PR 運用ルール。" user-invocable: false --- diff --git a/plugins/ndf-kiro/skills/plan-to-spec/SKILL.md b/plugins/ndf-kiro/skills/plan-to-spec/SKILL.md index eaea6f98..0fdd5ec3 100644 --- a/plugins/ndf-kiro/skills/plan-to-spec/SKILL.md +++ b/plugins/ndf-kiro/skills/plan-to-spec/SKILL.md @@ -1,6 +1,6 @@ --- name: plan-to-spec -description: "Finalize an implemented plan into a permanent specification document. Use after implementation is complete and an issues/ plan, PLAN file, design note, or implementation plan should become the final as-is specification under docs/ or another authoritative specification location. Triggers: 'planを仕様書にして', '確定仕様書に移動', '実装完了後にplanを整理', 'planをdocsへ移動', '仕様書としてリライト', 'plan-to-spec', 'finalize plan spec'." +description: "Rewrite a finished implementation plan into a permanent specification under docs/. Use when implementation is complete and an issues/ plan should become the as-is specification. Triggers: 'planを仕様書にして', '確定仕様書に移動', 'planをdocsへ移動', 'plan-to-spec'" allowed-tools: - Bash - Read diff --git a/plugins/ndf-kiro/skills/playwright-authoring/SKILL.md b/plugins/ndf-kiro/skills/playwright-authoring/SKILL.md index 3742e685..e196c902 100644 --- a/plugins/ndf-kiro/skills/playwright-authoring/SKILL.md +++ b/plugins/ndf-kiro/skills/playwright-authoring/SKILL.md @@ -1,7 +1,6 @@ --- name: playwright-authoring -description: "Create reproducible Playwright test scripts and run them with evidence, or check a page over browser MCP. Use when writing E2E test code, running E2E tests, doing a browser smoke check, or connecting to a remote Chrome over CDP (テストスクリプト作成 / テスト実行 / ブラウザ動作確認 / CDP 接続)." -when_to_use: "テストコード実装 / エビデンス動画・trace 収集 / accessibility・Core Web Vitals 計測 / ブラウザ接続先の変更が必要なとき。Triggers: 'playwright codegen', 'pwk_evidence', 'axe-core', 'WCAG', 'LCP', 'CLS', 'body_check', 'overlay', 'connectOverCDP', 'host.docker.internal', 'remote debugging'" +description: "Write Playwright E2E test scripts and run them with video / trace evidence, or check a page over browser MCP. Use when writing or running E2E tests, doing a browser smoke check, or connecting to Chrome over CDP. Triggers: 'playwright codegen', 'axe-core', 'connectOverCDP', 'ブラウザ動作確認'" argument-hint: "[url]" allowed-tools: - Read diff --git a/plugins/ndf-kiro/skills/pr-tests/SKILL.md b/plugins/ndf-kiro/skills/pr-tests/SKILL.md index 39f13de3..836146d2 100644 --- a/plugins/ndf-kiro/skills/pr-tests/SKILL.md +++ b/plugins/ndf-kiro/skills/pr-tests/SKILL.md @@ -1,8 +1,7 @@ --- name: pr-tests -description: "Run PR test plans and comment results." +description: "Run the test plan written in a PR body and post the results back as a PR comment. Use when a PR test plan has to be executed and reported. Triggers: 'PRのテストを実行', 'テストプランを実行', 'テスト結果をPRにコメント'" argument-hint: "[PR番号]" -disable-model-invocation: true allowed-tools: - Bash - Read diff --git a/plugins/ndf-kiro/skills/pr/SKILL.md b/plugins/ndf-kiro/skills/pr/SKILL.md index 3bfe6b16..dfe4ae48 100644 --- a/plugins/ndf-kiro/skills/pr/SKILL.md +++ b/plugins/ndf-kiro/skills/pr/SKILL.md @@ -1,8 +1,7 @@ --- name: pr -description: "Commit, push, and create or update PRs." +description: "Commit, push, and create or update a pull request for the current branch. Use when asked to commit and open a PR, update an existing PR, or push work for review. Triggers: 'PRを作って', 'PR作成', 'コミットしてプッシュ', 'PRを更新', 'draft PR'" argument-hint: "[--draft] [base-branch] or [commit-message]" -disable-model-invocation: true allowed-tools: - Bash - Read diff --git a/plugins/ndf-kiro/skills/problem-solving/SKILL.md b/plugins/ndf-kiro/skills/problem-solving/SKILL.md index 94133205..56b0dfbb 100644 --- a/plugins/ndf-kiro/skills/problem-solving/SKILL.md +++ b/plugins/ndf-kiro/skills/problem-solving/SKILL.md @@ -1,7 +1,6 @@ --- 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'" +description: "Solve bugs, incidents, and data inconsistencies at the root cause instead of patching downstream. Use when a bug, outage, or data inconsistency needs a fix decision. Triggers: 'バグの根本原因', 'データ不整合', '障害対応', 'root cause analysis', '上流で直す', 'patch vs fix'" --- # 問題解決ガイドライン diff --git a/plugins/ndf-kiro/skills/qa-security-scan/01-owasp-checklist.md b/plugins/ndf-kiro/skills/qa-security-scan/01-owasp-checklist.md new file mode 100644 index 00000000..797015b2 --- /dev/null +++ b/plugins/ndf-kiro/skills/qa-security-scan/01-owasp-checklist.md @@ -0,0 +1,298 @@ +# OWASP Top 10 詳細チェックリスト + +## 1. インジェクション + +**脆弱性の説明**: +信頼できないデータがコマンドやクエリの一部として送信され、攻撃者が意図しないコマンドを実行したり、適切な認可なしにデータにアクセスしたりできる。 + +**チェック項目**: + +- [ ] **SQLインジェクション対策** + ```javascript + // ❌ Bad: 文字列連結 + const query = `SELECT * FROM users WHERE id = ${userId}`; + + // ✅ Good: パラメータ化クエリ + const query = 'SELECT * FROM users WHERE id = ?'; + db.query(query, [userId]); + ``` + +- [ ] **コマンドインジェクション対策** + ```javascript + // ❌ Bad: ユーザー入力を直接使用 + exec(`ping ${userInput}`); + + // ✅ Good: ホワイトリスト検証 + エスケープ + if (!/^[a-zA-Z0-9.-]+$/.test(userInput)) { + throw new Error('Invalid input'); + } + ``` + +- [ ] **LDAPインジェクション対策** + - 特殊文字のエスケープ + - パラメータ化クエリの使用 + +- [ ] **NoSQLインジェクション対策** + ```javascript + // ❌ Bad: オブジェクトを直接使用 + User.find({ username: req.body.username }); + + // ✅ Good: 型検証 + const username = String(req.body.username); + User.find({ username }); + ``` + +**修正方法**: +1. パラメータ化クエリ/プリペアドステートメント使用 +2. ORMの使用(Sequelize、TypeORM等) +3. 入力値の厳格な検証(ホワイトリスト) +4. エスケープ処理 + +## 2. 認証の不備 + +**チェック項目**: + +- [ ] **パスワードの安全なハッシュ化** + ```javascript + // ❌ Bad: 平文保存、MD5/SHA1 + const hash = md5(password); + + // ✅ Good: bcrypt/Argon2 + const bcrypt = require('bcrypt'); + const hash = await bcrypt.hash(password, 10); + ``` + +- [ ] **セッション管理** + - セッションIDの再生成(ログイン後) + - セキュアなCookie設定(HttpOnly, Secure, SameSite) + - セッションタイムアウトの設定 + +- [ ] **多要素認証(MFA)** + - 重要な操作でMFA要求 + - TOTPまたはSMS認証 + +- [ ] **ブルートフォース攻撃対策** + - レート制限(rate limiting) + - アカウントロックアウト + - CAPTCHA + +- [ ] **パスワードポリシー** + - 最小8文字以上 + - 大文字、小文字、数字、記号の組み合わせ + - 過去のパスワードの再利用禁止 + +**修正方法**: +1. bcrypt/Argon2でパスワードをハッシュ化 +2. JWTトークンまたはセキュアなセッション管理 +3. express-rate-limitでレート制限 +4. パスワードポリシーの強制 + +## 3. 機密データの露出 + +**チェック項目**: + +- [ ] **通信の暗号化** + - HTTPS/TLS 1.2以上の使用 + - HTTP Strict Transport Security (HSTS) ヘッダー + +- [ ] **保存時の暗号化** + ```javascript + // ✅ Good: AES-256で暗号化 + const crypto = require('crypto'); + const algorithm = 'aes-256-cbc'; + const key = crypto.randomBytes(32); + const iv = crypto.randomBytes(16); + + function encrypt(text) { + const cipher = crypto.createCipheriv(algorithm, key, iv); + let encrypted = cipher.update(text, 'utf8', 'hex'); + encrypted += cipher.final('hex'); + return encrypted; + } + ``` + +- [ ] **機密情報のログ出力禁止** + ```javascript + // ❌ Bad + console.log('User password:', password); + logger.info('Credit card:', creditCard); + + // ✅ Good + logger.info('User authenticated', { userId: user.id }); + ``` + +- [ ] **APIキー・シークレットの管理** + - 環境変数で管理 + - .envファイルは.gitignoreに追加 + - AWS Secrets Manager / HashiCorp Vault 等の使用 + +**修正方法**: +1. すべての通信をHTTPS化 +2. 機密データの暗号化(AES-256) +3. 環境変数で機密情報を管理 +4. ログに機密情報を出力しない + +## 4. XXE(XML External Entity) + +**チェック項目**: + +- [ ] **XML パーサーの安全な設定** + ```javascript + // ✅ Good: DTD処理を無効化 + const { XMLParser } = require('fast-xml-parser'); + const parser = new XMLParser({ + ignoreAttributes: false, + processEntities: false // DTD処理を無効化 + }); + ``` + +- [ ] **外部エンティティの禁止** +- [ ] **DTD処理の無効化** + +**修正方法**: +1. XML パーサーでDTD処理を無効化 +2. 外部エンティティの参照を禁止 +3. 可能であればJSONを使用 + +## 5. アクセス制御の不備 + +**チェック項目**: + +- [ ] **認可チェックの実装** + ```javascript + // ✅ Good: ミドルウェアで認可チェック + function requireAdmin(req, res, next) { + if (req.user.role !== 'admin') { + return res.status(403).json({ error: 'Forbidden' }); + } + next(); + } + + app.delete('/api/users/:id', authMiddleware, requireAdmin, deleteUser); + ``` + +- [ ] **ロールベースアクセス制御(RBAC)** + - ユーザーごとにロール設定 + - リソースごとに必要なロールを定義 + +- [ ] **オブジェクトレベルの認可** + ```javascript + // ❌ Bad: IDだけで削除 + app.delete('/api/posts/:id', async (req, res) => { + await Post.destroy({ where: { id: req.params.id } }); + }); + + // ✅ Good: 所有者チェック + app.delete('/api/posts/:id', authMiddleware, async (req, res) => { + const post = await Post.findByPk(req.params.id); + if (post.userId !== req.user.id) { + return res.status(403).json({ error: 'Forbidden' }); + } + await post.destroy(); + }); + ``` + +- [ ] **IDORの防止**(Insecure Direct Object Reference) + +**修正方法**: +1. すべてのAPIエンドポイントで認可チェック +2. ロールベースアクセス制御の実装 +3. オブジェクトの所有者確認 + +## 6. セキュリティ設定ミス + +**チェック項目**: + +- [ ] **デフォルトパスワードの変更** +- [ ] **不要なサービスの無効化** +- [ ] **セキュリティヘッダーの設定** + ```javascript + // ✅ Good: helmet.js でセキュリティヘッダー設定 + const helmet = require('helmet'); + app.use(helmet()); + app.use(helmet.contentSecurityPolicy({ + directives: { + defaultSrc: ["'self'"], + scriptSrc: ["'self'", "'unsafe-inline'"], + styleSrc: ["'self'", "'unsafe-inline'"] + } + })); + ``` + +- [ ] **エラーメッセージの適切化** + ```javascript + // ❌ Bad: 詳細なエラーを公開 + res.status(500).json({ error: error.stack }); + + // ✅ Good: 一般的なエラーメッセージ + res.status(500).json({ error: 'Internal server error' }); + // 詳細はログに記録 + logger.error('Error details:', error); + ``` + +- [ ] **CORSの適切な設定** + ```javascript + // ✅ Good: 特定のオリジンのみ許可 + const cors = require('cors'); + app.use(cors({ + origin: 'https://example.com', + credentials: true + })); + ``` + +**修正方法**: +1. helmet.js でセキュリティヘッダー設定 +2. 環境別の設定(開発/本番) +3. エラーメッセージは一般的に、詳細はログに + +## 7. XSS(クロスサイトスクリプティング) + +**チェック項目**: + +- [ ] **HTMLエスケープ** + ```javascript + // ❌ Bad: 直接HTMLに挿入 + document.getElementById('output').innerHTML = userInput; + + // ✅ Good: エスケープして挿入 + document.getElementById('output').textContent = userInput; + + // または DOMPurify を使用 + import DOMPurify from 'dompurify'; + const clean = DOMPurify.sanitize(userInput); + ``` + +- [ ] **Content-Security-Policy (CSP) 設定** +- [ ] **HTTPOnlyクッキー** + ```javascript + // ✅ Good: HTTPOnly, Secure, SameSite + res.cookie('token', token, { + httpOnly: true, + secure: true, + sameSite: 'strict' + }); + ``` + +- [ ] **DOMベースXSS対策** + - `eval()`, `innerHTML`, `document.write()` を避ける + +**修正方法**: +1. すべての出力をエスケープ +2. Content-Security-Policy ヘッダー設定 +3. DOMPurifyなどのサニタイゼーションライブラリ使用 + +## 8-10. その他の脆弱性 + +**8. 安全でないデシリアライゼーション** +- [ ] 信頼できないデータのデシリアライズ禁止 +- [ ] 署名・検証の実装 + +**9. 既知の脆弱性があるコンポーネント** +- [ ] 依存ライブラリの最新化 +- [ ] `npm audit` / `pip-audit` の実行 +- [ ] Dependabot / Renovate の利用 + +**10. ログとモニタリングの不足** +- [ ] セキュリティイベントのログ +- [ ] 異常検知の仕組み +- [ ] 定期的なログレビュー diff --git a/plugins/ndf-kiro/skills/qa-security-scan/02-auth-checklist.md b/plugins/ndf-kiro/skills/qa-security-scan/02-auth-checklist.md new file mode 100644 index 00000000..0ff70595 --- /dev/null +++ b/plugins/ndf-kiro/skills/qa-security-scan/02-auth-checklist.md @@ -0,0 +1,127 @@ +# 認証・認可チェックリスト + +## 認証テスト + +### ログイン機能 + +- [ ] **正しい認証情報でログイン成功** +- [ ] **誤った認証情報でログイン失敗** +- [ ] **パスワード忘れ機能** + - リセットリンクの有効期限 + - リセット後の古いリンク無効化 + +### セッション管理 + +- [ ] **ログアウト後にセッション無効化** +- [ ] **セッションタイムアウト** + - アイドルタイムアウト(15-30分推奨) + - 絶対タイムアウト(8-24時間推奨) +- [ ] **同時ログインの制限** + - 必要に応じて制限を実装 + - 新規ログイン時に既存セッションを無効化 + +### トークン管理(JWT) + +- [ ] **トークン有効期限** + - アクセストークン: 15分-1時間 + - リフレッシュトークン: 7-30日 +- [ ] **トークンリフレッシュ** + - リフレッシュトークンのローテーション +- [ ] **署名検証** + - 強力な秘密鍵の使用 + - アルゴリズムの明示的指定 + +```javascript +// ✅ Good: JWT検証 +const jwt = require('jsonwebtoken'); + +function verifyToken(token) { + return jwt.verify(token, process.env.JWT_SECRET, { + algorithms: ['HS256'], // アルゴリズムを明示 + issuer: 'your-app', + audience: 'your-users' + }); +} +``` + +## 認可テスト + +### ロールベースアクセス制御 + +- [ ] **管理者のみアクセス可能なリソース** + - /admin/* へのアクセス制限 + - 管理機能の認可チェック +- [ ] **一般ユーザーの権限制限** + - 他ユーザーのデータへのアクセス禁止 + - 機能制限の適用 + +### リソース所有者チェック + +- [ ] **自分のリソースのみ編集・削除可能** + +```javascript +// ✅ Good: 所有者チェック +async function updateResource(req, res) { + const resource = await Resource.findByPk(req.params.id); + + if (!resource) { + return res.status(404).json({ error: 'Not found' }); + } + + // 所有者または管理者のみ許可 + if (resource.userId !== req.user.id && req.user.role !== 'admin') { + return res.status(403).json({ error: 'Forbidden' }); + } + + await resource.update(req.body); + res.json(resource); +} +``` + +## テストケース例 + +### 認証バイパステスト + +``` +1. 認証なしで保護されたエンドポイントにアクセス + → 401 Unauthorized が返ること + +2. 無効なトークンでアクセス + → 401 Unauthorized が返ること + +3. 期限切れトークンでアクセス + → 401 Unauthorized が返ること + +4. 改ざんされたトークンでアクセス + → 401 Unauthorized が返ること +``` + +### 権限昇格テスト + +``` +1. 一般ユーザーで管理者APIにアクセス + → 403 Forbidden が返ること + +2. ユーザーAでユーザーBのリソースを編集 + → 403 Forbidden が返ること + +3. URLのIDを変更して他ユーザーのデータにアクセス + → 403 Forbidden が返ること +``` + +## 実装チェックリスト + +### 必須実装 + +- [ ] パスワードはbcrypt/Argon2でハッシュ化 +- [ ] セッション/トークンにはセキュアなCookie設定 +- [ ] すべてのAPIエンドポイントに認証ミドルウェア +- [ ] 認可チェックは各リソースアクセス時に実行 +- [ ] レート制限を実装 + +### 推奨実装 + +- [ ] 多要素認証(MFA) +- [ ] パスワード強度チェック +- [ ] ログイン試行回数制限 +- [ ] セキュリティログの記録 diff --git a/plugins/ndf-kiro/skills/qa-security-scan/03-report-template.md b/plugins/ndf-kiro/skills/qa-security-scan/03-report-template.md new file mode 100644 index 00000000..6ad9f7ec --- /dev/null +++ b/plugins/ndf-kiro/skills/qa-security-scan/03-report-template.md @@ -0,0 +1,144 @@ +# セキュリティレポートテンプレート + +## 使用方法 + +このテンプレートをコピーして、セキュリティスキャン結果を報告してください。 + +--- + +# セキュリティスキャンレポート - [アプリケーション名] + +## エグゼクティブサマリー + +- **スキャン日**: YYYY-MM-DD +- **スキャン範囲**: [対象範囲の説明] +- **重大な脆弱性**: X件 +- **警告**: Y件 +- **情報**: Z件 + +## 重大な脆弱性 (Critical/High) + +### 1. [脆弱性名] + +- **場所**: [ファイルパス/エンドポイント] +- **リスクレベル**: 高 +- **説明**: [脆弱性の詳細説明] +- **影響**: [悪用された場合の影響] +- **修正方法**: + ```javascript + // 修正前 + [問題のあるコード] + + // 修正後 + [修正されたコード] + ``` +- **優先度**: 最高(即座に修正) + +### 2. [脆弱性名] + +[同様のフォーマットで記載] + +## 警告 (Medium) + +### 3. [脆弱性名] + +- **場所**: [ファイルパス/エンドポイント] +- **リスクレベル**: 中 +- **説明**: [脆弱性の詳細説明] +- **修正方法**: [修正方法の説明] + +## 情報 (Low/Info) + +### 4. [項目名] + +- **場所**: [ファイルパス/エンドポイント] +- **説明**: [詳細説明] +- **推奨事項**: [推奨される対応] + +## 推奨事項 + +1. **即座に修正**: 重大な脆弱性X件 +2. **1週間以内に修正**: 警告Y件 +3. **セキュリティヘッダー追加**: helmet.js 使用 +4. **依存ライブラリの更新**: npm audit で検出された脆弱性 +5. **定期的なセキュリティスキャン**: 月1回の実施 + +## 次のステップ + +1. [ ] 重大な脆弱性の修正 +2. [ ] 修正後の再スキャン +3. [ ] ペネトレーションテストの実施 +4. [ ] セキュリティ監視の強化 + +--- + +## レポート作成のポイント + +### リスクレベルの判断基準 + +| レベル | 基準 | +|--------|------| +| Critical | リモートコード実行、認証バイパス、データ全体へのアクセス | +| High | SQLインジェクション、XSS(保存型)、権限昇格 | +| Medium | XSS(反射型)、CSRF、情報漏洩(限定的) | +| Low | セキュリティヘッダー不足、詳細なエラーメッセージ | +| Info | ベストプラクティスからの逸脱 | + +### 修正優先度 + +1. **即座に**: Critical/High(本番環境に影響) +2. **1週間以内**: Medium(悪用の可能性あり) +3. **次回リリース**: Low/Info(改善推奨) + +## Codex CLI 連携 + +詳細な独立レビューが必要な場合は `corder` エージェントに委譲するか、`/ndf:external-ai` skill の手順で `codex exec` を直接起動する。例: + +```bash +# === 1. プロンプト書き出し(最終出力先を明示し apply_patch で書かせる) === +FINAL=/tmp/codex-output-sec-scan.md + +cat > /tmp/sec-scan-prompt.md < /tmp/sec-scan-stdout.md \ + 2> /tmp/sec-scan-err.log & + +# === 3. 完了確認(^tokens used$ sentinel を待つ。`ps -p` は zombie を生存と誤判定する) === +until grep -q '^tokens used$' /tmp/sec-scan-err.log 2>/dev/null; do + sleep 30 +done + +# === 4. 成果物を回収(ファイル → stdout → stderr の三段フォールバック) === +if [ -s "$FINAL" ]; then + cp "$FINAL" ./sec-scan-result.md +elif [ -s /tmp/sec-scan-stdout.md ]; then + cp /tmp/sec-scan-stdout.md ./sec-scan-result.md + echo "WARN: stdout からフォールバック回収(ファイル書き出しなし)" >&2 +else + echo "ERROR: Codex の最終出力を回収できませんでした。stderr 末尾を確認:" >&2 + tail -200 /tmp/sec-scan-err.log +fi +``` + +詳細は `/ndf:external-ai` skill と `references/cli-codex.md` を参照。 diff --git a/plugins/ndf-kiro/skills/qa-security-scan/SKILL.md b/plugins/ndf-kiro/skills/qa-security-scan/SKILL.md new file mode 100644 index 00000000..b741edaa --- /dev/null +++ b/plugins/ndf-kiro/skills/qa-security-scan/SKILL.md @@ -0,0 +1,55 @@ +--- +name: qa-security-scan +description: "Run an OWASP Top 10 security review of code, authentication, authorization, and data protection. Use when asked for a security review of a change or a vulnerability check. Triggers: 'セキュリティレビュー', 'セキュリティスキャン', '脆弱性チェック', 'OWASP', '認証認可の確認', 'SQLインジェクション'" +--- + +# QA Security Scan Skill + +## 概要 + +セキュリティスキャンと脆弱性評価を実施する際に使用します。OWASP Top 10に基づいた包括的なチェックリストと、認証・認可・データ保護の検証手順を提供します。 + +## クイックリファレンス + +### OWASP Top 10 概要 + +| # | 脆弱性 | 主な対策 | +|---|--------|----------| +| 1 | インジェクション | パラメータ化クエリ、ORM使用 | +| 2 | 認証の不備 | bcrypt/Argon2、MFA、レート制限 | +| 3 | 機密データ露出 | HTTPS、暗号化、環境変数管理 | +| 4 | XXE | DTD処理無効化、JSON使用 | +| 5 | アクセス制御不備 | RBAC、所有者チェック | +| 6 | 設定ミス | helmet.js、適切なCORS | +| 7 | XSS | エスケープ、CSP、DOMPurify | +| 8 | デシリアライゼーション | 署名検証、信頼できるデータのみ | +| 9 | 既知の脆弱性 | npm audit、Dependabot | +| 10 | ログ不足 | セキュリティイベント記録 | + +### 基本的な使い方 + +1. 対象コードを特定 +2. 該当するチェックリストを適用 +3. 脆弱性を発見したらレポート作成 +4. 修正方法を提案 + +## ベストプラクティス + +| DO | DON'T | +|----|-------| +| 定期的なスキャン(月1回以上) | スキャンのみで満足 | +| CI/CDパイプラインに統合 | 警告を無視 | +| 重大度順に対応(高→低) | 本番環境で初スキャン | +| 修正後に再スキャン | 自動化ツールに全依存 | + +## 詳細ガイド + +| ファイル | 内容 | +|---------|------| +| `01-owasp-checklist.md` | OWASP Top 10 詳細チェックリストとコード例 | +| `02-auth-checklist.md` | 認証・認可テスト手順 | +| `03-report-template.md` | セキュリティレポートテンプレート | + +## 関連Skill + +- **corder-code-templates**: セキュアなコードテンプレート diff --git a/plugins/ndf-kiro/skills/review/SKILL.md b/plugins/ndf-kiro/skills/review/SKILL.md index 2afd42e2..fefe037d 100644 --- a/plugins/ndf-kiro/skills/review/SKILL.md +++ b/plugins/ndf-kiro/skills/review/SKILL.md @@ -1,9 +1,8 @@ --- name: review -description: "Review a PR diff, or the current branch diff with --branch, and post an approve or request-changes verdict." -when_to_use: "PR をレビューするとき、および PR 作成前にローカルブランチをセルフレビューするとき (--branch)。Triggers: 'レビューして', 'PRレビュー', 'マージ前チェック', 'ブランチをレビュー', 'セルフレビュー', 'PR前にレビュー', 'review my branch', 'self review', 'pre-PR review'" +description: "Review a PR diff, or the current branch diff with --branch, and post an approve or request-changes verdict. Use when asked to review a PR, check a diff before merge, or self-review a branch. Triggers: 'レビューして', 'PRレビュー', 'マージ前チェック', 'ブランチをレビュー', 'セルフレビュー'" argument-hint: "[PR番号 | --branch] [AIエージェント(codex|gemini)] [--focus AREA]" -disable-model-invocation: true +effort: high allowed-tools: - Bash - Read diff --git a/plugins/ndf-kiro/skills/statusline/SKILL.md b/plugins/ndf-kiro/skills/statusline/SKILL.md index c9e5ef55..644a850e 100644 --- a/plugins/ndf-kiro/skills/statusline/SKILL.md +++ b/plugins/ndf-kiro/skills/statusline/SKILL.md @@ -1,7 +1,7 @@ --- name: statusline -description: "Switch, restore, or inspect the NDF statusline." -when_to_use: "statuslineを切り替え/復元/確認したいとき。Triggers: 'statusline', 'ステータスライン', 'statusline 切り替え', 'statusline 戻す'" +description: "Switch, restore, or inspect the NDF statusline in the Claude Code settings file. 設定ファイルを書き換えるため、利用者が /ndf:statusline を明示的に指示したときのみ実行する。Triggers: 'statusline 切り替え', 'statusline 戻す', 'ステータスライン'" +argument-hint: "status | set | restore" disable-model-invocation: true allowed-tools: - Bash diff --git a/plugins/ndf-shared/manifests/claude-skills.txt b/plugins/ndf-shared/manifests/claude-skills.txt index a94a7a37..e1dcb869 100644 --- a/plugins/ndf-shared/manifests/claude-skills.txt +++ b/plugins/ndf-shared/manifests/claude-skills.txt @@ -18,3 +18,5 @@ external-ai statusline issue-plan-strategy plan-to-spec +qa-security-scan +official-skills-autoloader diff --git a/plugins/ndf-shared/manifests/codex-skills.txt b/plugins/ndf-shared/manifests/codex-skills.txt index 46047cd8..b82bfe19 100644 --- a/plugins/ndf-shared/manifests/codex-skills.txt +++ b/plugins/ndf-shared/manifests/codex-skills.txt @@ -19,4 +19,5 @@ playwright-planning pr pr-tests problem-solving +qa-security-scan review diff --git a/plugins/ndf-shared/manifests/kiro-skills.txt b/plugins/ndf-shared/manifests/kiro-skills.txt index a94a7a37..5d6bb198 100644 --- a/plugins/ndf-shared/manifests/kiro-skills.txt +++ b/plugins/ndf-shared/manifests/kiro-skills.txt @@ -18,3 +18,4 @@ external-ai statusline issue-plan-strategy plan-to-spec +qa-security-scan diff --git a/plugins/ndf-shared/skills/README.md b/plugins/ndf-shared/skills/README.md index 50c36bae..8a30b618 100644 --- a/plugins/ndf-shared/skills/README.md +++ b/plugins/ndf-shared/skills/README.md @@ -4,11 +4,17 @@ 編集元である。ここでは frontmatter の書き方を規約として定める。本文の書き方は各 `SKILL.md` に委ね、規約は発動と配布に関わる部分だけを扱う。 -frontmatter の機械検査は未実装である。現在の継続的インテグレーションは -`scripts/build-runtime-plugins.sh --check` / `scripts/validate-runtime-plugins.sh` / -`scripts/check-markdown-links.py` を実行しており、本規約はそれまで人手で確認する。検査スクリプト -`scripts/check-skill-frontmatter.py` の追加は -[棚卸の計画](../../../issues/ndf-development-skills/07-tasks.md) の Task 0-7 で行う。 +本規約のうち機械的に判定できる項目は `scripts/check-skill-frontmatter.py` が検査し、 +継続的インテグレーションで実行する(`scripts/build-runtime-plugins.sh --check` / +`scripts/validate-runtime-plugins.sh` / `scripts/check-markdown-links.py` と同じワークフロー)。 + +```bash +python3 scripts/check-skill-frontmatter.py # 検査 +python3 scripts/check-skill-frontmatter.py --report # 実測値の一覧 +``` + +判定が本質的に近似になる項目(`description` 先頭のトリガ語、`when_to_use` の追加トリガ)は +警告にとどまり、`--strict` を付けたときだけ失敗する。 利用実績と維持・統合・削除の判定は [docs/specifications/ndf-skill-inventory.md](../../../docs/specifications/ndf-skill-inventory.md) @@ -121,6 +127,7 @@ when_to_use: "Claude Code 向けの追加トリガのみ。description で足り | `SKILL.md` 本文 | 5,000 トークン | 仕様の推奨 | | Claude Code の初期 Skill 一覧の合計 | コンテキストウィンドウの 1%。不明な場合は 8,000 文字。1 項目あたり 250 文字で切り詰め | Claude Code 公式ドキュメント | | Codex の初期 Skill 一覧の合計 | コンテキストウィンドウの 2%。不明な場合は 8,000 文字 | Codex 公式ドキュメント | +| 全 Skill の frontmatter 合計 | 13,000 文字 | リポジトリ固有の運用値。Task 0-7 完了時点の実測 12,145 文字(Skill 29 個)に約 7% の余裕を足した値。`scripts/check-skill-frontmatter.py` の `FRONTMATTER_TOTAL_MAX` | 運用目標の 300 文字は仕様上限より厳しい。全 Skill 分の `description` が常時注入されるため、 仕様上限は 1 個で使い切ってよい量ではない。 diff --git a/plugins/ndf-shared/skills/cherry-pick-pr/SKILL.md b/plugins/ndf-shared/skills/cherry-pick-pr/SKILL.md index 1de3823b..4228d90d 100644 --- a/plugins/ndf-shared/skills/cherry-pick-pr/SKILL.md +++ b/plugins/ndf-shared/skills/cherry-pick-pr/SKILL.md @@ -1,7 +1,7 @@ --- name: cherry-pick-pr -description: "Create cherry-pick PRs for environment branches and apply the same fix across multiple branches." -argument-hint: " (例: qa/staging, release/v2)" +description: "Cherry-pick a merged fix onto environment branches (qa/staging, release) as a new PR. 破壊的操作のため、利用者が /ndf:cherry-pick-pr を明示的に指示したときのみ実行する。Triggers: 'cherry-pick', 'qaにも同じ修正を適用', 'stagingにも反映', 'release branchへ適用', 'multi-branch fix'" +argument-hint: "ベースブランチ名 (例: qa/staging, release/v2)" disable-model-invocation: true allowed-tools: - Bash diff --git a/plugins/ndf-shared/skills/cross-review/SKILL.md b/plugins/ndf-shared/skills/cross-review/SKILL.md index 2472f576..31357abd 100644 --- a/plugins/ndf-shared/skills/cross-review/SKILL.md +++ b/plugins/ndf-shared/skills/cross-review/SKILL.md @@ -1,7 +1,6 @@ --- name: cross-review -description: "Run iterative Codex and Gemini PR reviews." -when_to_use: "PR を codex + gemini 両方でレビューし、両者 APPROVE まで自動収束させたいときに限定して使う。明示トリガ: 'cross-review', 'クロスレビュー', '両AIレビュー', '収束レビュー', 'codex と gemini でレビュー'。通常の単発 PR レビュー依頼 (第二意見が 1 回欲しい等) は本 skill を選ばず /ndf:review を使う。重い収束ループ (codex+gemini を複数ラウンド起動) のため、単発レビューと責務を明確に分ける。" +description: "Review a PR with both Codex and Gemini, looping fixes until both APPROVE. Use when a converging two-AI review is wanted; for a one-shot second opinion use /ndf:review. Triggers: 'cross-review', 'クロスレビュー', '両AIレビュー', '収束レビュー', 'codex と gemini でレビュー'" argument-hint: "[PR番号] [--max-rounds N] [--rotate-after K] [--rotate-mode light|squash] [--only codex|gemini] [--focus TEXT] [--extra-instructions-file PATH]" allowed-tools: - Bash diff --git a/plugins/ndf-shared/skills/deploy/SKILL.md b/plugins/ndf-shared/skills/deploy/SKILL.md index 8bca071b..c4baa425 100644 --- a/plugins/ndf-shared/skills/deploy/SKILL.md +++ b/plugins/ndf-shared/skills/deploy/SKILL.md @@ -1,7 +1,7 @@ --- name: deploy -description: "Create a deploy PR from the current feature branch to an environment branch such as qa/staging or release/v2. 破壊的操作のため、利用者が /ndf:deploy を明示的に指示したときのみ実行する(環境ブランチへデプロイ / qaに上げる / stagingに反映 / リリースブランチへPR)。deployブランチを作成し origin/main を取り込んでからPRを出す。" -argument-hint: " (例: qa/staging, release/v2)" +description: "Create a deploy PR from the current feature branch to an environment branch such as qa/staging or release/v2. 破壊的操作のため、利用者が /ndf:deploy を明示的に指示したときのみ実行する。Triggers: '環境ブランチへデプロイ', 'qaに上げる', 'stagingへデプロイ', 'リリースブランチへPR'" +argument-hint: "環境ブランチ名 (例: qa/staging, release/v2)" disable-model-invocation: true allowed-tools: - Bash diff --git a/plugins/ndf-shared/skills/docker-container-access/SKILL.md b/plugins/ndf-shared/skills/docker-container-access/SKILL.md index 444a993f..bd464ca9 100644 --- a/plugins/ndf-shared/skills/docker-container-access/SKILL.md +++ b/plugins/ndf-shared/skills/docker-container-access/SKILL.md @@ -1,7 +1,6 @@ --- 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'" +description: "Diagnose Docker container access and localhost routing failures. Use when a container is unreachable, localhost does not connect, or DinD/DooD has to be identified. Triggers: 'localhost not working', 'コンテナに接続できない', 'DinD', 'DooD', 'curl container'" allowed-tools: - Read - Bash diff --git a/plugins/ndf-shared/skills/external-ai/SKILL.md b/plugins/ndf-shared/skills/external-ai/SKILL.md index 9684e739..9a959755 100644 --- a/plugins/ndf-shared/skills/external-ai/SKILL.md +++ b/plugins/ndf-shared/skills/external-ai/SKILL.md @@ -1,7 +1,6 @@ --- name: external-ai -description: "Delegate coding, review, or research to an external AI CLI (Codex / Gemini). Use for 'codexで調査', 'geminiレビュー', '第二意見レビュー', 'external AI review', 'codex exec', 'gemini exec'." -when_to_use: "外部 AI へコード生成 / レビュー / 調査を委譲したいとき。追加トリガ: '外部AIに投げて', 'クロスチェックして', 'もう一つのAIに見てもらう', 'CLI で codex を回す'" +description: "Delegate coding, review, or research to an external AI CLI (Codex or Gemini). Use when a second opinion or an offloaded investigation is wanted. Triggers: 'codexで調査', 'geminiレビュー', '第二意見レビュー', 'codex exec', 'gemini exec', '外部AIに投げて'" --- # 外部 AI 委譲スキル (Codex / Gemini) diff --git a/plugins/ndf-shared/skills/fix/SKILL.md b/plugins/ndf-shared/skills/fix/SKILL.md index e6c85ee3..6ea24b41 100644 --- a/plugins/ndf-shared/skills/fix/SKILL.md +++ b/plugins/ndf-shared/skills/fix/SKILL.md @@ -1,7 +1,6 @@ --- name: fix -description: "Classify PR review comments, fix the actionable ones, then reply and resolve each thread. Use when responding to PR review feedback from codex, gemini, bots, or humans." -when_to_use: "PR レビューコメントへの対応全般。分類だけしたいときは --classify-only。Triggers: 'PRコメント対応', 'PRレビュー修正', 'PRコメントを確認', 'PRコメントを分類', 'コメント対応の優先度', 'PR fix', 'classify PR comments', 'コメントに対応して修正', 'Resolveして'" +description: "Classify PR review comments, fix the actionable ones, then reply and resolve each thread. Use when responding to review feedback from codex, gemini, bots, or humans on a PR. Triggers: 'PRコメント対応', 'PRレビュー修正', 'PRコメントを分類', 'コメントに対応して修正', 'Resolveして'" argument-hint: "[PR番号] [--classify-only] [--defer-nit] [--severity-min critical|major|minor]" allowed-tools: - Bash diff --git a/plugins/ndf-shared/skills/google-auth/SKILL.md b/plugins/ndf-shared/skills/google-auth/SKILL.md index 006019db..305b278a 100644 --- a/plugins/ndf-shared/skills/google-auth/SKILL.md +++ b/plugins/ndf-shared/skills/google-auth/SKILL.md @@ -1,7 +1,6 @@ --- name: google-auth -description: "Set up OAuth for Google APIs." -when_to_use: "Google API の OAuth2 認証が必要なときに自動参照。Triggers: 'Google認証', 'OAuth', 'google_token', 'spreadsheets', 'Google API', 'client_secret'" +description: "Set up OAuth2 credentials for Google APIs (Drive, Docs, Sheets). Use when a script needs Google API access and the token is missing or expired. Triggers: 'Google認証', 'client_secret', 'google_token', 'OAuth2 認証'" allowed-tools: - Read - Bash(python *) diff --git a/plugins/ndf-shared/skills/google-drive/SKILL.md b/plugins/ndf-shared/skills/google-drive/SKILL.md index 48f287d3..cd7d8dc7 100644 --- a/plugins/ndf-shared/skills/google-drive/SKILL.md +++ b/plugins/ndf-shared/skills/google-drive/SKILL.md @@ -1,7 +1,6 @@ --- name: google-drive -description: "Export, download, upload, and share Google Drive files." -when_to_use: "Google Drive / Docs のファイル操作が必要なとき。Triggers: 'Google Drive', 'Google Docs', 'drive.file', 'ファイルエクスポート', 'ダウンロード', 'アップロード', '公開共有リンク'" +description: "Export, download, upload, and share Google Drive and Docs files. Use when a file has to be fetched from or published to Drive, or a share link is needed. Triggers: 'Google Drive', 'Google Docs', 'Driveにファイルをアップロード', '公開共有リンク'" allowed-tools: - Read - Bash(python *) diff --git a/plugins/ndf-shared/skills/implementation-plan/SKILL.md b/plugins/ndf-shared/skills/implementation-plan/SKILL.md index 0e0a1307..2d961ee1 100644 --- a/plugins/ndf-shared/skills/implementation-plan/SKILL.md +++ b/plugins/ndf-shared/skills/implementation-plan/SKILL.md @@ -1,7 +1,6 @@ --- name: implementation-plan -description: "Create or update implementation plan files." -when_to_use: "実装開始時 / PR作成時に実装プランの作成・更新が必要なとき。複数ファイル変更・新機能追加・DBマイグレーションを含む変更で自動参照。Triggers: '実装プラン', '実装を開始', 'PR作成', 'implementation plan', 'plan first', '設計書を作成', 'issues/に追加'" +description: "Create or update an implementation plan file under issues/ before coding starts. Use when a change spans multiple files, adds a feature, or includes a DB migration. Triggers: '実装プラン', '実装を開始', 'implementation plan', '設計書を作成', 'issues/に追加'" --- # 実装プランガイド diff --git a/plugins/ndf-shared/skills/investigation-rules/SKILL.md b/plugins/ndf-shared/skills/investigation-rules/SKILL.md index a4757a83..1a20b2d0 100644 --- a/plugins/ndf-shared/skills/investigation-rules/SKILL.md +++ b/plugins/ndf-shared/skills/investigation-rules/SKILL.md @@ -1,7 +1,6 @@ --- name: investigation-rules -description: "Write evidence-backed investigation and debug reports." -when_to_use: "調査・デバッグ・不具合レポートを作成するとき。「ない」「該当なし」等の否定的結論を出すときは必ず参照。Triggers: '調査', 'デバッグ', '不具合レポート', '原因調査', 'investigation', 'root cause', 'カラムがない', '該当コードがない', 'データがない'" +description: "Write evidence-backed investigation and debug reports, and never state a negative finding without showing the search behind it. Use when writing an investigation or bug report. Triggers: '調査レポートを書く', '不具合レポート', '原因調査', 'カラムがない', '該当コードがない'" --- # 調査レポート作成ルール diff --git a/plugins/ndf-shared/skills/issue-plan-strategy/SKILL.md b/plugins/ndf-shared/skills/issue-plan-strategy/SKILL.md index 7f96f04a..26e07fdf 100644 --- a/plugins/ndf-shared/skills/issue-plan-strategy/SKILL.md +++ b/plugins/ndf-shared/skills/issue-plan-strategy/SKILL.md @@ -1,7 +1,6 @@ --- 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 で進めて'" +description: "Turn an issue into a plan, then drive the plan through a release branch, per-PR worktrees, and multi-PR execution. Use when asked to design a plan from an issue or to execute an existing plan. Triggers: 'issueのplanを作って', 'このplanを実装して', 'planを実行', 'release branch 作って実装開始', 'multi-PR で進めて'" argument-hint: "[issue-path-or-url] (例: issues/i16.md, https://github.com/org/repo/issues/123)" allowed-tools: - Bash diff --git a/plugins/ndf-shared/skills/logging-guidelines/SKILL.md b/plugins/ndf-shared/skills/logging-guidelines/SKILL.md index 3ad64b34..56e24879 100644 --- a/plugins/ndf-shared/skills/logging-guidelines/SKILL.md +++ b/plugins/ndf-shared/skills/logging-guidelines/SKILL.md @@ -1,6 +1,6 @@ --- name: logging-guidelines -description: "Choose log levels and write safe, useful application logs when adding or reworking logging in code(ログ追加 / logger / ログレベル / デバッグログ / エラーログ / print文をログに). Use when editing source code that emits logs, to pick the level and keep secrets and personal data out of the output." +description: "Choose log levels and keep secrets and personal data out of application logs. Use when adding, reworking, or reviewing logging in source code. Triggers: 'ログ追加', 'ログレベルを決める', 'ログ設計', 'print文をログに', 'ログに個人情報'" paths: - "**/*.py" - "**/*.ts" diff --git a/plugins/ndf-shared/skills/markdown-writing/SKILL.md b/plugins/ndf-shared/skills/markdown-writing/SKILL.md index 4b4d9488..736b47ce 100644 --- a/plugins/ndf-shared/skills/markdown-writing/SKILL.md +++ b/plugins/ndf-shared/skills/markdown-writing/SKILL.md @@ -1,7 +1,6 @@ --- name: markdown-writing -description: "Write Markdown docs, PR bodies, and reports that read well to a third party." -when_to_use: "Markdown 文書 / 仕様書 / 設計書 / PR 本文 / 調査レポート / 図表を作成・編集するとき。Triggers: 'Markdown作成', 'ドキュメント作成', '文書作成', '仕様書', '設計書', 'PR本文', 'PR説明', '調査レポート', '図を描く', 'mermaid', 'create document', 'write docs', 'write PR description'" +description: "Write Markdown docs, specs, PR bodies, and reports that read well to a third party, including tables and mermaid diagrams. Use when authoring or editing a Markdown document. Triggers: 'ドキュメント作成', 'PR本文', 'PR説明', '仕様書を書く', 'mermaid', 'write docs'" allowed-tools: - Read - Write diff --git a/plugins/ndf-shared/skills/merged/SKILL.md b/plugins/ndf-shared/skills/merged/SKILL.md index 78891b9e..0eeb1939 100644 --- a/plugins/ndf-shared/skills/merged/SKILL.md +++ b/plugins/ndf-shared/skills/merged/SKILL.md @@ -1,8 +1,7 @@ --- name: merged -description: "Clean up after a PR is merged: update main, remove the worktree, and delete merged branches." +description: "Clean up after a PR is merged: update main, remove the worktree, and delete the merged branch. Use when a PR has just been merged or leftover branches and worktrees need clearing. Triggers: 'マージ後の後片付け', 'ブランチを整理', 'worktreeを削除', 'merged cleanup'" argument-hint: "[PR番号]" -disable-model-invocation: true allowed-tools: - Bash - Read diff --git a/plugins/ndf-shared/skills/ml-model-structure/SKILL.md b/plugins/ndf-shared/skills/ml-model-structure/SKILL.md index d0138589..465f892b 100644 --- a/plugins/ndf-shared/skills/ml-model-structure/SKILL.md +++ b/plugins/ndf-shared/skills/ml-model-structure/SKILL.md @@ -1,7 +1,8 @@ --- name: ml-model-structure -description: "Structure ML training, inference, and versioned models." -when_to_use: "機械学習モデルの新規構築・再学習・推論API/コンテナ開発・モデルのバージョン管理/並行運用を行うとき。analysis/ 配下に学習スクリプトや推論コードを配置する設計判断が必要なとき。Triggers: 'モデル構築', 'モデル再学習', 'モデルのバージョン管理', '推論コンテナ', '推論API', 'SageMaker', 'feature SSoT', 'train/serve skew', 'analysis ディレクトリ', 'champion challenger', '並行運用'" +description: "Lay out ML training and inference code as self-contained versioned directories with a per-version feature SSoT. Use when building, retraining, or versioning a model. Triggers: 'モデル構築', 'モデル再学習', 'モデルのバージョン管理', '推論API', 'train/serve skew', 'champion challenger'" +paths: + - "analysis/**" allowed-tools: - Read - Write diff --git a/plugins/ndf-shared/skills/ndf-policies/SKILL.md b/plugins/ndf-shared/skills/ndf-policies/SKILL.md index ab8becf5..f1a22887 100644 --- a/plugins/ndf-shared/skills/ndf-policies/SKILL.md +++ b/plugins/ndf-shared/skills/ndf-policies/SKILL.md @@ -1,6 +1,6 @@ --- name: ndf-policies -description: "Apply core NDF project policies, including the branch strategy for applying the same fix to environment branches (qa/staging/release) without contaminating feature branches." +description: "Core NDF project policies. 知識として参照するだけで、手順として実行しない。判断に迷ったときの基準として使う: ブランチ戦略、環境ブランチ (qa/staging/release) へ同じ修正を適用する原則、feature ブランチを汚さない運用、PR 運用ルール。" user-invocable: false --- diff --git a/plugins/ndf-shared/skills/official-skills-autoloader/SKILL.md b/plugins/ndf-shared/skills/official-skills-autoloader/SKILL.md index 46e3dace..3c260a60 100644 --- a/plugins/ndf-shared/skills/official-skills-autoloader/SKILL.md +++ b/plugins/ndf-shared/skills/official-skills-autoloader/SKILL.md @@ -1,6 +1,7 @@ --- name: official-skills-autoloader -description: "Install an Anthropic official Skill on demand and run it. Use when the request needs Word/Excel/PowerPoint/PDF creation or editing, frontend design, webapp testing, or MCP server scaffolding(Word作成 / Excel出力 / スライド生成 / PDF作成 / .docx / .pptx / .xlsx / .pdf / MCPサーバーを作りたい). Claude Code 専用。" +description: "Install an Anthropic official Skill on demand (docx / pptx / xlsx / pdf / frontend-design / webapp-testing / mcp-builder) and run it. Use when a request needs Office or PDF output that no local Skill covers. Triggers: 'Word作成', 'Excel出力', 'スライド生成', 'PDF作成'" +when_to_use: "Claude Code 専用。~/.claude/skills/ へ公式 Skill を取得して読み込む。追加トリガ: '.docx', '.pptx', '.xlsx', '.pdf', 'MCPサーバーを作りたい', 'フロントエンド設計'" allowed-tools: - Bash - Read @@ -29,7 +30,7 @@ allowed-tools: **Claude Code 専用**。インストール先の `~/.claude/skills/` を読むのは Claude Code だけで、Codex は `.agents/skills/`、Kiro CLI は `.kiro/skills/` を読む。両ランタイムでは公式 Skill の自動読込は行われないため、配布するとしても Claude Code の manifest に限る。 -なお現在この Skill はどの manifest にも載っておらず、配布物へ含まれていない。`description` を直しても配布されるまで発動はしない。 +配布先は `plugins/ndf-shared/manifests/claude-skills.txt` のみとする。Codex / Kiro の manifest には載せない。 ## 動作手順 diff --git a/plugins/ndf-shared/skills/plan-to-spec/SKILL.md b/plugins/ndf-shared/skills/plan-to-spec/SKILL.md index eaea6f98..0fdd5ec3 100644 --- a/plugins/ndf-shared/skills/plan-to-spec/SKILL.md +++ b/plugins/ndf-shared/skills/plan-to-spec/SKILL.md @@ -1,6 +1,6 @@ --- name: plan-to-spec -description: "Finalize an implemented plan into a permanent specification document. Use after implementation is complete and an issues/ plan, PLAN file, design note, or implementation plan should become the final as-is specification under docs/ or another authoritative specification location. Triggers: 'planを仕様書にして', '確定仕様書に移動', '実装完了後にplanを整理', 'planをdocsへ移動', '仕様書としてリライト', 'plan-to-spec', 'finalize plan spec'." +description: "Rewrite a finished implementation plan into a permanent specification under docs/. Use when implementation is complete and an issues/ plan should become the as-is specification. Triggers: 'planを仕様書にして', '確定仕様書に移動', 'planをdocsへ移動', 'plan-to-spec'" allowed-tools: - Bash - Read diff --git a/plugins/ndf-shared/skills/playwright-authoring/SKILL.md b/plugins/ndf-shared/skills/playwright-authoring/SKILL.md index 3742e685..e196c902 100644 --- a/plugins/ndf-shared/skills/playwright-authoring/SKILL.md +++ b/plugins/ndf-shared/skills/playwright-authoring/SKILL.md @@ -1,7 +1,6 @@ --- name: playwright-authoring -description: "Create reproducible Playwright test scripts and run them with evidence, or check a page over browser MCP. Use when writing E2E test code, running E2E tests, doing a browser smoke check, or connecting to a remote Chrome over CDP (テストスクリプト作成 / テスト実行 / ブラウザ動作確認 / CDP 接続)." -when_to_use: "テストコード実装 / エビデンス動画・trace 収集 / accessibility・Core Web Vitals 計測 / ブラウザ接続先の変更が必要なとき。Triggers: 'playwright codegen', 'pwk_evidence', 'axe-core', 'WCAG', 'LCP', 'CLS', 'body_check', 'overlay', 'connectOverCDP', 'host.docker.internal', 'remote debugging'" +description: "Write Playwright E2E test scripts and run them with video / trace evidence, or check a page over browser MCP. Use when writing or running E2E tests, doing a browser smoke check, or connecting to Chrome over CDP. Triggers: 'playwright codegen', 'axe-core', 'connectOverCDP', 'ブラウザ動作確認'" argument-hint: "[url]" allowed-tools: - Read diff --git a/plugins/ndf-shared/skills/playwright-evidence/SKILL.md b/plugins/ndf-shared/skills/playwright-evidence/SKILL.md index f66d8edc..cfb6f200 100644 --- a/plugins/ndf-shared/skills/playwright-evidence/SKILL.md +++ b/plugins/ndf-shared/skills/playwright-evidence/SKILL.md @@ -1,7 +1,6 @@ --- name: playwright-evidence -description: "Generate the Playwright test report and store its evidence on Google Drive. Use when generating report.md, sharing E2E test results, or uploading video / trace / HAR evidence to Drive (テストレポート / テスト結果共有 / テスト報告書 / エビデンス保管 / Drive アップロード)." -when_to_use: "レポート生成 / エビデンスのチーム配布 / Drive リンクを埋め込んだ Google Docs 作成が必要なとき。Triggers: 'report.md', 'pwk-drive-folder', 'upload_evidence', 'gdrive_upload_dir', 'trace viewer', 'report を Docs に'" +description: "Generate the Playwright test report and store its evidence on Google Drive. Use when producing report.md, sharing E2E results, or archiving video / trace / HAR evidence. Triggers: 'report.md', 'テスト報告書', 'エビデンスをDriveへ保管', 'trace viewer'" allowed-tools: - Read - Bash(python *) diff --git a/plugins/ndf-shared/skills/playwright-kit-ops/SKILL.md b/plugins/ndf-shared/skills/playwright-kit-ops/SKILL.md index 39cbeb03..ab1a7c0f 100644 --- a/plugins/ndf-shared/skills/playwright-kit-ops/SKILL.md +++ b/plugins/ndf-shared/skills/playwright-kit-ops/SKILL.md @@ -1,7 +1,6 @@ --- name: playwright-kit-ops -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 実行'" +description: "Run the playwright_kit scripts: project init, page-role classification, one-off a11y / CWV scans, and Drive upload helpers. Use when a playwright_kit script has to be run directly. Triggers: 'init_project.sh', 'classify_page_role.py', 'run_a11y_scan.py', 'upload_evidence.py'" allowed-tools: - Read - Bash(python *) diff --git a/plugins/ndf-shared/skills/playwright-planning/SKILL.md b/plugins/ndf-shared/skills/playwright-planning/SKILL.md index 73039aa0..88862956 100644 --- a/plugins/ndf-shared/skills/playwright-planning/SKILL.md +++ b/plugins/ndf-shared/skills/playwright-planning/SKILL.md @@ -1,7 +1,6 @@ --- name: playwright-planning -description: "Plan Playwright E2E tests by judging page role and choosing checklists and test techniques. Use when starting E2E scenario testing, designing test cases, or laying out the whole E2E workflow (テスト計画 / テスト設計 / page role / チェックリスト / シナリオテスト)." -when_to_use: "E2E テスト計画の立案 / page role 分類 / テスト技法の選定 / pytest-playwright ワークフロー全体像の把握が必要なとき。Triggers: 'HTSM', 'ISTQB', 'FEW HICCUPPS', 'ISO 29119', 'テスト観点', 'テスト計画書', 'フル E2E'" +description: "Plan Playwright E2E tests: judge the page role, then pick checklists and test techniques. Use when starting E2E scenario testing or designing test cases. Triggers: 'テスト計画書', 'テスト観点', 'page role 分類', 'HTSM', 'ISTQB', 'FEW HICCUPPS'" allowed-tools: - Read - Bash(python *) diff --git a/plugins/ndf-shared/skills/pr-tests/SKILL.md b/plugins/ndf-shared/skills/pr-tests/SKILL.md index 39f13de3..836146d2 100644 --- a/plugins/ndf-shared/skills/pr-tests/SKILL.md +++ b/plugins/ndf-shared/skills/pr-tests/SKILL.md @@ -1,8 +1,7 @@ --- name: pr-tests -description: "Run PR test plans and comment results." +description: "Run the test plan written in a PR body and post the results back as a PR comment. Use when a PR test plan has to be executed and reported. Triggers: 'PRのテストを実行', 'テストプランを実行', 'テスト結果をPRにコメント'" argument-hint: "[PR番号]" -disable-model-invocation: true allowed-tools: - Bash - Read diff --git a/plugins/ndf-shared/skills/pr/SKILL.md b/plugins/ndf-shared/skills/pr/SKILL.md index 3bfe6b16..dfe4ae48 100644 --- a/plugins/ndf-shared/skills/pr/SKILL.md +++ b/plugins/ndf-shared/skills/pr/SKILL.md @@ -1,8 +1,7 @@ --- name: pr -description: "Commit, push, and create or update PRs." +description: "Commit, push, and create or update a pull request for the current branch. Use when asked to commit and open a PR, update an existing PR, or push work for review. Triggers: 'PRを作って', 'PR作成', 'コミットしてプッシュ', 'PRを更新', 'draft PR'" argument-hint: "[--draft] [base-branch] or [commit-message]" -disable-model-invocation: true allowed-tools: - Bash - Read diff --git a/plugins/ndf-shared/skills/problem-solving/SKILL.md b/plugins/ndf-shared/skills/problem-solving/SKILL.md index 94133205..56b0dfbb 100644 --- a/plugins/ndf-shared/skills/problem-solving/SKILL.md +++ b/plugins/ndf-shared/skills/problem-solving/SKILL.md @@ -1,7 +1,6 @@ --- 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'" +description: "Solve bugs, incidents, and data inconsistencies at the root cause instead of patching downstream. Use when a bug, outage, or data inconsistency needs a fix decision. Triggers: 'バグの根本原因', 'データ不整合', '障害対応', 'root cause analysis', '上流で直す', 'patch vs fix'" --- # 問題解決ガイドライン diff --git a/plugins/ndf-shared/skills/qa-security-scan/SKILL.md b/plugins/ndf-shared/skills/qa-security-scan/SKILL.md index 0adfc80f..b741edaa 100644 --- a/plugins/ndf-shared/skills/qa-security-scan/SKILL.md +++ b/plugins/ndf-shared/skills/qa-security-scan/SKILL.md @@ -1,13 +1,13 @@ --- name: qa-security-scan -description: "Run an OWASP Top 10 security review of code, authentication, authorization, and data protection. Use when asked for a security scan, vulnerability assessment, or a security review of a change(セキュリティスキャン / 脆弱性チェック / セキュリティレビュー / OWASP / 認証認可の確認 / SQLインジェクションの確認)." +description: "Run an OWASP Top 10 security review of code, authentication, authorization, and data protection. Use when asked for a security review of a change or a vulnerability check. Triggers: 'セキュリティレビュー', 'セキュリティスキャン', '脆弱性チェック', 'OWASP', '認証認可の確認', 'SQLインジェクション'" --- # QA Security Scan Skill ## 概要 -qaエージェントがセキュリティスキャンと脆弱性評価を実施する際に使用します。OWASP Top 10に基づいた包括的なチェックリストと、認証・認可・データ保護の検証手順を提供します。 +セキュリティスキャンと脆弱性評価を実施する際に使用します。OWASP Top 10に基づいた包括的なチェックリストと、認証・認可・データ保護の検証手順を提供します。 ## クイックリファレンス diff --git a/plugins/ndf-shared/skills/review/SKILL.md b/plugins/ndf-shared/skills/review/SKILL.md index 2afd42e2..fefe037d 100644 --- a/plugins/ndf-shared/skills/review/SKILL.md +++ b/plugins/ndf-shared/skills/review/SKILL.md @@ -1,9 +1,8 @@ --- name: review -description: "Review a PR diff, or the current branch diff with --branch, and post an approve or request-changes verdict." -when_to_use: "PR をレビューするとき、および PR 作成前にローカルブランチをセルフレビューするとき (--branch)。Triggers: 'レビューして', 'PRレビュー', 'マージ前チェック', 'ブランチをレビュー', 'セルフレビュー', 'PR前にレビュー', 'review my branch', 'self review', 'pre-PR review'" +description: "Review a PR diff, or the current branch diff with --branch, and post an approve or request-changes verdict. Use when asked to review a PR, check a diff before merge, or self-review a branch. Triggers: 'レビューして', 'PRレビュー', 'マージ前チェック', 'ブランチをレビュー', 'セルフレビュー'" argument-hint: "[PR番号 | --branch] [AIエージェント(codex|gemini)] [--focus AREA]" -disable-model-invocation: true +effort: high allowed-tools: - Bash - Read diff --git a/plugins/ndf-shared/skills/skill-stats/SKILL.md b/plugins/ndf-shared/skills/skill-stats/SKILL.md index 93a95cb2..796fe68a 100644 --- a/plugins/ndf-shared/skills/skill-stats/SKILL.md +++ b/plugins/ndf-shared/skills/skill-stats/SKILL.md @@ -1,7 +1,6 @@ --- name: skill-stats -description: "Analyze Skill usage from Claude Code transcripts." -when_to_use: "Skill 利用統計 / hit rate を算出したいとき。Triggers: 'skill stats', 'skill統計', 'skill利用分析', 'skill usage', 'skill hit rate'" +description: "Measure Skill usage from Claude Code transcripts: invocation counts, trigger hit rate, and per-Skill breakdown. Use when auditing which Skills actually fire. Triggers: 'skill統計', 'skill利用分析', 'skill hit rate', 'skill-stats'" allowed-tools: - Bash - Read diff --git a/plugins/ndf-shared/skills/statusline/SKILL.md b/plugins/ndf-shared/skills/statusline/SKILL.md index ab17e4a0..22357fe7 100644 --- a/plugins/ndf-shared/skills/statusline/SKILL.md +++ b/plugins/ndf-shared/skills/statusline/SKILL.md @@ -1,7 +1,7 @@ --- name: statusline -description: "Switch, restore, or inspect the NDF statusline." -when_to_use: "statuslineを切り替え/復元/確認したいとき。Triggers: 'statusline', 'ステータスライン', 'statusline 切り替え', 'statusline 戻す'" +description: "Switch, restore, or inspect the NDF statusline in the Claude Code settings file. 設定ファイルを書き換えるため、利用者が /ndf:statusline を明示的に指示したときのみ実行する。Triggers: 'statusline 切り替え', 'statusline 戻す', 'ステータスライン'" +argument-hint: "status | set | restore" disable-model-invocation: true allowed-tools: - Bash diff --git a/scripts/check-skill-frontmatter.py b/scripts/check-skill-frontmatter.py index 2636d0b7..269a00d8 100644 --- a/scripts/check-skill-frontmatter.py +++ b/scripts/check-skill-frontmatter.py @@ -39,7 +39,10 @@ CODEX_LISTING_MAX = 8000 # Codex の初期一覧予算(コンテキスト長不明時) CLAUDE_LISTING_MAX = 8000 # Claude Code の初期一覧予算(コンテキスト長不明時) CLAUDE_ITEM_TRUNCATE = 250 # Claude Code は 1 項目をこの長さで切り詰める -FRONTMATTER_TOTAL_MAX = 12000 # 全 Skill の frontmatter 合計。棚卸完了時の実測を基準に設定 +# 全 Skill の frontmatter 合計。棚卸(Task 0-7)完了時点の実測 12,145 文字(Skill 29 個、 +# 2026-08-08)を基準に、約 7% の余裕を足して 13,000 とした。余裕分は Skill 2〜3 個分の +# frontmatter に相当する。Skill を増やすときは実測しなおしてこの値を更新する。 +FRONTMATTER_TOTAL_MAX = 13000 # --- 許可する frontmatter の項目 ------------------------------------------- # Agent Skills 仕様の 6 項目 + Claude Code 独自項目。 @@ -251,7 +254,9 @@ def check_skill(s: dict) -> list[Finding]: add("error", "ops/uninvocable", "disable-model-invocation: true と user-invocable: false の同時指定は誰も起動できない") if dmi and not fm.get("argument-hint"): - add("warn", "ops/argument-hint", + # 近似判定ではなく機械的に判定できるため、計画(Task 0-7 の検査項目表)どおり + # 失敗条件として扱う。 + add("error", "ops/argument-hint", "disable-model-invocation があるのに argument-hint がない(明示起動時の引数が伝わらない)") ctx = unquote(fm.get("context", "")) @@ -267,13 +272,24 @@ def check_skill(s: dict) -> list[Finding]: def load_manifests(skills_dir: pathlib.Path) -> dict[str, set[str]]: - """manifests/-skills.txt を読み、配布先ごとの Skill 名集合を返す。""" + """manifests/(runtime)-skills.txt を読み、配布先ごとの Skill 名集合を返す。 + + 行末の `#` 以降はコメントとして落とす。scripts/build-runtime-plugins.sh の + manifest 解釈と揃えるため(揃っていないと、コメント付きの manifest で + 配布先の判定が実際のビルド結果とずれる)。 + """ man_dir = skills_dir.parent / "manifests" out: dict[str, set[str]] = {} for runtime in ("claude", "codex", "kiro"): f = man_dir / f"{runtime}-skills.txt" - if f.exists(): - out[runtime] = {line.strip() for line in f.read_text().split() if line.strip()} + if not f.exists(): + continue + members: set[str] = set() + for line in f.read_text(encoding="utf-8").splitlines(): + name = line.split("#", 1)[0].strip() + if name: + members.add(name) + out[runtime] = members return out From e6aabafef939cbfcc231d6afe0453c3a27e4a59d Mon Sep 17 00:00:00 2001 From: "takemi.ohama" Date: Sat, 8 Aug 2026 05:17:02 +0000 Subject: [PATCH 5/7] Merge release/skill-inventory into feature/inventory-frontmatter MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Task 0-8 (PR #74) の Codex 向け agents/openai.yaml 生成処理を取り込んだ。 本 PR が merged / pr / review / pr-tests から disable-model-invocation を 外したため、再ビルドでこの 4 個の openai.yaml が削除され、生成対象は 明示指示専用を維持する cherry-pick-pr と deploy の 2 個になった。 --- plugins/ndf-codex/skills/cherry-pick-pr/agents/openai.yaml | 2 +- plugins/ndf-codex/skills/deploy/agents/openai.yaml | 2 +- plugins/ndf-codex/skills/merged/agents/openai.yaml | 4 ---- plugins/ndf-codex/skills/pr-tests/agents/openai.yaml | 4 ---- plugins/ndf-codex/skills/pr/agents/openai.yaml | 4 ---- plugins/ndf-codex/skills/review/agents/openai.yaml | 4 ---- 6 files changed, 2 insertions(+), 18 deletions(-) delete mode 100644 plugins/ndf-codex/skills/merged/agents/openai.yaml delete mode 100644 plugins/ndf-codex/skills/pr-tests/agents/openai.yaml delete mode 100644 plugins/ndf-codex/skills/pr/agents/openai.yaml delete mode 100644 plugins/ndf-codex/skills/review/agents/openai.yaml diff --git a/plugins/ndf-codex/skills/cherry-pick-pr/agents/openai.yaml b/plugins/ndf-codex/skills/cherry-pick-pr/agents/openai.yaml index 31590300..0af16d06 100644 --- a/plugins/ndf-codex/skills/cherry-pick-pr/agents/openai.yaml +++ b/plugins/ndf-codex/skills/cherry-pick-pr/agents/openai.yaml @@ -1,4 +1,4 @@ policy: allow_implicit_invocation: false interface: - default_prompt: " (例: qa/staging, release/v2)" + default_prompt: "ベースブランチ名 (例: qa/staging, release/v2)" diff --git a/plugins/ndf-codex/skills/deploy/agents/openai.yaml b/plugins/ndf-codex/skills/deploy/agents/openai.yaml index 68c5828d..165e26b9 100644 --- a/plugins/ndf-codex/skills/deploy/agents/openai.yaml +++ b/plugins/ndf-codex/skills/deploy/agents/openai.yaml @@ -1,4 +1,4 @@ policy: allow_implicit_invocation: false interface: - default_prompt: " (例: qa/staging, release/v2)" + default_prompt: "環境ブランチ名 (例: qa/staging, release/v2)" diff --git a/plugins/ndf-codex/skills/merged/agents/openai.yaml b/plugins/ndf-codex/skills/merged/agents/openai.yaml deleted file mode 100644 index 35f2e747..00000000 --- a/plugins/ndf-codex/skills/merged/agents/openai.yaml +++ /dev/null @@ -1,4 +0,0 @@ -policy: - allow_implicit_invocation: false -interface: - default_prompt: "[PR番号]" diff --git a/plugins/ndf-codex/skills/pr-tests/agents/openai.yaml b/plugins/ndf-codex/skills/pr-tests/agents/openai.yaml deleted file mode 100644 index 35f2e747..00000000 --- a/plugins/ndf-codex/skills/pr-tests/agents/openai.yaml +++ /dev/null @@ -1,4 +0,0 @@ -policy: - allow_implicit_invocation: false -interface: - default_prompt: "[PR番号]" diff --git a/plugins/ndf-codex/skills/pr/agents/openai.yaml b/plugins/ndf-codex/skills/pr/agents/openai.yaml deleted file mode 100644 index ce8499a5..00000000 --- a/plugins/ndf-codex/skills/pr/agents/openai.yaml +++ /dev/null @@ -1,4 +0,0 @@ -policy: - allow_implicit_invocation: false -interface: - default_prompt: "[--draft] [base-branch] or [commit-message]" diff --git a/plugins/ndf-codex/skills/review/agents/openai.yaml b/plugins/ndf-codex/skills/review/agents/openai.yaml deleted file mode 100644 index 22e2c991..00000000 --- a/plugins/ndf-codex/skills/review/agents/openai.yaml +++ /dev/null @@ -1,4 +0,0 @@ -policy: - allow_implicit_invocation: false -interface: - default_prompt: "[PR番号 | --branch] [AIエージェント(codex|gemini)] [--focus AREA]" From a1c6b5d2421fa813d0df4ddde7af362c80d8883b Mon Sep 17 00:00:00 2001 From: "takemi.ohama" Date: Sat, 8 Aug 2026 05:27:41 +0000 Subject: [PATCH 6/7] =?UTF-8?q?fix:=20merged=20/=20pr=20=E3=81=AB=E5=AE=9F?= =?UTF-8?q?=E8=A1=8C=E5=89=8D=E7=A2=BA=E8=AA=8D=E3=82=92=E5=BF=85=E9=A0=88?= =?UTF-8?q?=E5=8C=96=E3=81=97=20argument-hint=20=E5=88=A4=E5=AE=9A?= =?UTF-8?q?=E3=82=92=E6=9D=A1=E4=BB=B6=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit cross-review round 1 (codex) の指摘 3 件に対応する。 - merged / pr: disable-model-invocation を戻す代わりに、取り消しの難しい 操作(worktree 削除・ブランチ削除・push・PR 作成)の直前に対象を一覧提示 して利用者の同意を得る手順を SKILL.md と description へ固定した。 Codex / Kiro は disable-model-invocation を解釈しないため、安全性の担保を frontmatter ではなく本文と description に置く - skills/README.md: 「明示指示専用」の対象を「取り消しが難しく、かつ明示起動が 定着している操作」に限定し、自然文で日常的に依頼される破壊的操作は 「自動発動 + 実行前確認」で守るという選択肢と使い分けの基準を明文化した。 Codex の openai.yaml がビルドで自動生成される旨(Task 0-8 完了)も反映 - check-skill-frontmatter.py: argument-hint の要求を「引数を取る Skill」に 条件化した。判定は frontmatter の arguments / 本文の $ARGUMENTS / 本文の 「引数」への言及のいずれか。根拠はスクリプトのコメントに記載 - ndf-skill-inventory.md: 発動制御の変更表に実行前確認の行を追加 検査: エラー 0 / 警告 0、build --check / markdown links / validate すべて通過 Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_01AGejnYyYFuSkQjBhW2KQNy --- docs/specifications/ndf-skill-inventory.md | 1 + plugins/ndf-claude/skills/merged/SKILL.md | 30 +++++++++++++--- plugins/ndf-claude/skills/pr/SKILL.md | 30 ++++++++++++++-- plugins/ndf-codex/skills/merged/SKILL.md | 30 +++++++++++++--- plugins/ndf-codex/skills/pr/SKILL.md | 30 ++++++++++++++-- plugins/ndf-kiro/skills/merged/SKILL.md | 30 +++++++++++++--- plugins/ndf-kiro/skills/pr/SKILL.md | 30 ++++++++++++++-- plugins/ndf-shared/skills/README.md | 40 +++++++++++++++++---- plugins/ndf-shared/skills/merged/SKILL.md | 30 +++++++++++++--- plugins/ndf-shared/skills/pr/SKILL.md | 30 ++++++++++++++-- scripts/check-skill-frontmatter.py | 41 +++++++++++++++++++--- 11 files changed, 283 insertions(+), 39 deletions(-) diff --git a/docs/specifications/ndf-skill-inventory.md b/docs/specifications/ndf-skill-inventory.md index 0c1939e8..c5f2b573 100644 --- a/docs/specifications/ndf-skill-inventory.md +++ b/docs/specifications/ndf-skill-inventory.md @@ -174,6 +174,7 @@ frontmatter を [規約](../../plugins/ndf-shared/skills/README.md) へ揃えた | Skill | 変更 | 理由 | | --- | --- | --- | | `merged` / `pr` / `review` / `pr-tests` | `disable-model-invocation` を削除 | 日常的に自然文で依頼されるため。明示指示専用のままではエージェントが Skill を使わず独自手順で実行する | +| `merged` / `pr` | 実行前確認を必須手順として本文へ固定 | 上記 2 つは取り消しの難しい操作(worktree / ブランチ削除、push と PR 作成)を含む。自動発動を許すかわりに、削除・書き込みの直前に対象を一覧提示して同意を得る手順を `SKILL.md` と `description` に固定した。`disable-model-invocation` を解釈しない Codex / Kiro でも同じ安全性が働く | | `deploy` / `cherry-pick-pr` / `statusline` | 明示指示専用を維持 | 環境ブランチへの書き込みと設定ファイルの書き換えを伴う。`description` に「利用者が明示的に指示したときのみ実行する」と明記し、Codex / Kiro でも意図が伝わるようにした | | `ndf-policies` | `user-invocable: false` を維持 | `description` に「知識として参照するだけで、手順として実行しない」と明記した | diff --git a/plugins/ndf-claude/skills/merged/SKILL.md b/plugins/ndf-claude/skills/merged/SKILL.md index 0eeb1939..21cee4ac 100644 --- a/plugins/ndf-claude/skills/merged/SKILL.md +++ b/plugins/ndf-claude/skills/merged/SKILL.md @@ -1,6 +1,6 @@ --- name: merged -description: "Clean up after a PR is merged: update main, remove the worktree, and delete the merged branch. Use when a PR has just been merged or leftover branches and worktrees need clearing. Triggers: 'マージ後の後片付け', 'ブランチを整理', 'worktreeを削除', 'merged cleanup'" +description: "Clean up after a merged PR: update main, remove the worktree, and delete merged branches. 削除の前に対象を一覧提示して同意を取る。Use when a PR was merged or branches and worktrees need clearing. Triggers: 'マージ後の後片付け', 'ブランチを整理', 'worktreeを削除', 'merged cleanup'" argument-hint: "[PR番号]" allowed-tools: - Bash @@ -23,13 +23,32 @@ PR マージ後の後始末をまとめて実行する。対象 PR のブラン 手順 1(PR のマージ確認)を前提条件にしてはならない。「マージ済みブランチの整理」と 「main の取り込み」はいずれも **単独で実行可能** で、PR のマージ状態に依存しない。 +## 削除前の同意取得(必須) + +worktree 削除・ローカルブランチ削除・リモートブランチ削除はいずれも取り消しが難しい。 +**この 3 種類の操作は、実行の直前に削除対象を一覧で提示して利用者の同意を得る。 +同意が得られていない対象は削除しない。** この Skill は自然文の依頼でも起動するため、 +安全性はこの手順で担保する(frontmatter の発動制御には依存しない)。 + +| 操作 | 提示するもの | +|---|---| +| worktree 削除 | worktree のパスと、未コミット変更の有無(`git -C status --short`) | +| ローカルブランチ削除 | ブランチ名と、main へ未マージのコミットがあるか | +| リモートブランチ削除 | リモート名とブランチ名。共有ブランチに影響するため、他の削除と分けて同意を取る | + +- 「削除してよいか」だけを尋ねるのは確認にならない。**対象そのものを一覧で示す** +- 同意が得られなかった対象はスキップし、作業完了報告にスキップした対象と理由を記載する +- 利用者が対象を明示して削除を依頼した場合(`/ndf:merged 123` で PR 番号を指定した等)は、 + その依頼が対象への同意にあたる。それでも一覧の提示は行い、依頼に含まれない対象 + (マージ済みブランチの一括整理、リモート削除)については改めて同意を取る + ## クリーンアップの手順 1. **マージ確認**: 引数の(引数がなければ自身が作成した最新の)PR が main に merge されていることを github mcp で確認。merge されていなければクリーンアップは実施せず終了 2. **作業ツリー退避**: `git branch --show-current` で**退避元のブランチ名を記録**し、`git status` を確認して変更があれば `git stash` 3. **main 更新**: `git checkout main` → `git pull` -4. **worktree クリーンアップ**: `git worktree list` で当該 PR 番号に対応する worktree (`pr`) を探し、あれば `git worktree remove ` で削除(worktree 内の `.cross_review/` も一緒に消える) -5. **ブランチ削除**: `git branch -d ` +4. **worktree クリーンアップ**: `git worktree list` で当該 PR 番号に対応する worktree (`pr`) を探し、**「削除前の同意取得」に従ってパスと未コミット変更の有無を提示し、同意を得てから** `git worktree remove ` で削除(worktree 内の `.cross_review/` も一緒に消える) +5. **ブランチ削除**: 削除するブランチ名を提示して同意を得てから `git branch -d ` 6. **マージ済みブランチの整理**: 下記の手順で残存ブランチをまとめて削除 7. **復元**: 手順 2 で stash していれば、**退避元のブランチへ戻してから**復元する - 退避元のブランチが残っている場合: `git checkout <退避元のブランチ>` → `git stash pop` @@ -50,8 +69,9 @@ git push origin --delete # 3. リモートにも残っていれば削 ``` - main と現在のブランチは必ず除外する -- 削除対象を提示し、確認を取ってから削除する -- リモート削除は共有ブランチに影響するため、対象を明示してから実行する +- **手順 2 の前に削除対象のローカルブランチを一覧で提示し、同意を得てから削除する** +- **手順 3 のリモート削除は共有ブランチに影響するため、ローカル削除とは分けて対象を提示し、 + 改めて同意を得てから実行する**(「削除前の同意取得」を参照) ## main の取り込み diff --git a/plugins/ndf-claude/skills/pr/SKILL.md b/plugins/ndf-claude/skills/pr/SKILL.md index dfe4ae48..e8e80fcb 100644 --- a/plugins/ndf-claude/skills/pr/SKILL.md +++ b/plugins/ndf-claude/skills/pr/SKILL.md @@ -1,6 +1,6 @@ --- name: pr -description: "Commit, push, and create or update a pull request for the current branch. Use when asked to commit and open a PR, update an existing PR, or push work for review. Triggers: 'PRを作って', 'PR作成', 'コミットしてプッシュ', 'PRを更新', 'draft PR'" +description: "Commit, push, and create or update a pull request. push と PR 作成の前に対象ブランチ・base・変更ファイルを提示して同意を取る。Use when asked to commit and open a PR, update a PR, or push work for review. Triggers: 'PRを作って', 'PR作成', 'コミットしてプッシュ', 'PRを更新', 'draft PR'" argument-hint: "[--draft] [base-branch] or [commit-message]" allowed-tools: - Bash @@ -32,6 +32,28 @@ allowed-tools: - それ以外の文字列はコミットメッセージとして扱う - デフォルトは `main` ベース、非ドラフト +## push / PR 作成前の同意取得(必須) + +push と PR 作成は外部(GitHub)への書き込みで、取り消しには追加の操作が要る。 +この Skill は自然文の依頼でも起動するため、安全性はこの手順で担保する +(frontmatter の発動制御には依存しない)。 + +**手順 4(プッシュ)と手順 5(PR 作成)の直前に、次を提示する。** + +- push 先のブランチ名と、PR のベースブランチ +- コミット対象のファイル一覧(`git status --short`)と変更量(`git diff --stat`) +- 使用するコミットメッセージ +- 既存 PR の有無(新規作成なのか、既存 PR の更新なのか) + +同意の扱い: + +- 利用者の依頼が push と PR 作成まで明示的に含む場合(`/ndf:pr` の明示起動、 + 「コミットしてPRを作って」等)は、その依頼を同意とみなしてよい。提示は行い、 + 結果報告に含める +- それ以外(作業の流れで暗黙に起動した場合)は、提示したうえで**明示的な同意を得てから + push する**。同意が得られなければ commit までで止め、push も PR 作成も行わない +- ベースブランチが `main`/`master` 以外の場合は、手順 2 の誘導を優先する + ## 手順 ### 0. PR確認 @@ -39,7 +61,7 @@ allowed-tools: - `git branch --show-current` で現在ブランチを確認 - `gh pr list --head ` で既存PR確認 - 既にPRが存在しOPEN状態なら: - - `git add` → `git commit`(日本語メッセージ)→ `git push` + - `git add` → `git commit`(日本語メッセージ)→ **「push / PR 作成前の同意取得」に従って提示** → `git push` - **既存PR説明を更新** する(「PR説明の更新」節を参照) - 終了報告 - PRがない、またはmerge/close済みなら次へ @@ -64,12 +86,16 @@ allowed-tools: ### 4. プッシュ +**「push / PR 作成前の同意取得」に従って提示し、同意を確認してから実行する。** + ```bash git push -u origin ``` ### 5. PR作成 +- **作成する PR のタイトル・ベースブランチ・ドラフト有無を提示してから実行する** + (手順 4 で一括して同意を得ている場合は再確認不要) - `.github/pull_request_template.md` が存在すれば適用 - `--draft` 指定ならドラフトPR作成 - タイトル・説明は日本語、body は `## Summary` + `## Test plan` diff --git a/plugins/ndf-codex/skills/merged/SKILL.md b/plugins/ndf-codex/skills/merged/SKILL.md index 0eeb1939..21cee4ac 100644 --- a/plugins/ndf-codex/skills/merged/SKILL.md +++ b/plugins/ndf-codex/skills/merged/SKILL.md @@ -1,6 +1,6 @@ --- name: merged -description: "Clean up after a PR is merged: update main, remove the worktree, and delete the merged branch. Use when a PR has just been merged or leftover branches and worktrees need clearing. Triggers: 'マージ後の後片付け', 'ブランチを整理', 'worktreeを削除', 'merged cleanup'" +description: "Clean up after a merged PR: update main, remove the worktree, and delete merged branches. 削除の前に対象を一覧提示して同意を取る。Use when a PR was merged or branches and worktrees need clearing. Triggers: 'マージ後の後片付け', 'ブランチを整理', 'worktreeを削除', 'merged cleanup'" argument-hint: "[PR番号]" allowed-tools: - Bash @@ -23,13 +23,32 @@ PR マージ後の後始末をまとめて実行する。対象 PR のブラン 手順 1(PR のマージ確認)を前提条件にしてはならない。「マージ済みブランチの整理」と 「main の取り込み」はいずれも **単独で実行可能** で、PR のマージ状態に依存しない。 +## 削除前の同意取得(必須) + +worktree 削除・ローカルブランチ削除・リモートブランチ削除はいずれも取り消しが難しい。 +**この 3 種類の操作は、実行の直前に削除対象を一覧で提示して利用者の同意を得る。 +同意が得られていない対象は削除しない。** この Skill は自然文の依頼でも起動するため、 +安全性はこの手順で担保する(frontmatter の発動制御には依存しない)。 + +| 操作 | 提示するもの | +|---|---| +| worktree 削除 | worktree のパスと、未コミット変更の有無(`git -C status --short`) | +| ローカルブランチ削除 | ブランチ名と、main へ未マージのコミットがあるか | +| リモートブランチ削除 | リモート名とブランチ名。共有ブランチに影響するため、他の削除と分けて同意を取る | + +- 「削除してよいか」だけを尋ねるのは確認にならない。**対象そのものを一覧で示す** +- 同意が得られなかった対象はスキップし、作業完了報告にスキップした対象と理由を記載する +- 利用者が対象を明示して削除を依頼した場合(`/ndf:merged 123` で PR 番号を指定した等)は、 + その依頼が対象への同意にあたる。それでも一覧の提示は行い、依頼に含まれない対象 + (マージ済みブランチの一括整理、リモート削除)については改めて同意を取る + ## クリーンアップの手順 1. **マージ確認**: 引数の(引数がなければ自身が作成した最新の)PR が main に merge されていることを github mcp で確認。merge されていなければクリーンアップは実施せず終了 2. **作業ツリー退避**: `git branch --show-current` で**退避元のブランチ名を記録**し、`git status` を確認して変更があれば `git stash` 3. **main 更新**: `git checkout main` → `git pull` -4. **worktree クリーンアップ**: `git worktree list` で当該 PR 番号に対応する worktree (`pr`) を探し、あれば `git worktree remove ` で削除(worktree 内の `.cross_review/` も一緒に消える) -5. **ブランチ削除**: `git branch -d ` +4. **worktree クリーンアップ**: `git worktree list` で当該 PR 番号に対応する worktree (`pr`) を探し、**「削除前の同意取得」に従ってパスと未コミット変更の有無を提示し、同意を得てから** `git worktree remove ` で削除(worktree 内の `.cross_review/` も一緒に消える) +5. **ブランチ削除**: 削除するブランチ名を提示して同意を得てから `git branch -d ` 6. **マージ済みブランチの整理**: 下記の手順で残存ブランチをまとめて削除 7. **復元**: 手順 2 で stash していれば、**退避元のブランチへ戻してから**復元する - 退避元のブランチが残っている場合: `git checkout <退避元のブランチ>` → `git stash pop` @@ -50,8 +69,9 @@ git push origin --delete # 3. リモートにも残っていれば削 ``` - main と現在のブランチは必ず除外する -- 削除対象を提示し、確認を取ってから削除する -- リモート削除は共有ブランチに影響するため、対象を明示してから実行する +- **手順 2 の前に削除対象のローカルブランチを一覧で提示し、同意を得てから削除する** +- **手順 3 のリモート削除は共有ブランチに影響するため、ローカル削除とは分けて対象を提示し、 + 改めて同意を得てから実行する**(「削除前の同意取得」を参照) ## main の取り込み diff --git a/plugins/ndf-codex/skills/pr/SKILL.md b/plugins/ndf-codex/skills/pr/SKILL.md index dfe4ae48..e8e80fcb 100644 --- a/plugins/ndf-codex/skills/pr/SKILL.md +++ b/plugins/ndf-codex/skills/pr/SKILL.md @@ -1,6 +1,6 @@ --- name: pr -description: "Commit, push, and create or update a pull request for the current branch. Use when asked to commit and open a PR, update an existing PR, or push work for review. Triggers: 'PRを作って', 'PR作成', 'コミットしてプッシュ', 'PRを更新', 'draft PR'" +description: "Commit, push, and create or update a pull request. push と PR 作成の前に対象ブランチ・base・変更ファイルを提示して同意を取る。Use when asked to commit and open a PR, update a PR, or push work for review. Triggers: 'PRを作って', 'PR作成', 'コミットしてプッシュ', 'PRを更新', 'draft PR'" argument-hint: "[--draft] [base-branch] or [commit-message]" allowed-tools: - Bash @@ -32,6 +32,28 @@ allowed-tools: - それ以外の文字列はコミットメッセージとして扱う - デフォルトは `main` ベース、非ドラフト +## push / PR 作成前の同意取得(必須) + +push と PR 作成は外部(GitHub)への書き込みで、取り消しには追加の操作が要る。 +この Skill は自然文の依頼でも起動するため、安全性はこの手順で担保する +(frontmatter の発動制御には依存しない)。 + +**手順 4(プッシュ)と手順 5(PR 作成)の直前に、次を提示する。** + +- push 先のブランチ名と、PR のベースブランチ +- コミット対象のファイル一覧(`git status --short`)と変更量(`git diff --stat`) +- 使用するコミットメッセージ +- 既存 PR の有無(新規作成なのか、既存 PR の更新なのか) + +同意の扱い: + +- 利用者の依頼が push と PR 作成まで明示的に含む場合(`/ndf:pr` の明示起動、 + 「コミットしてPRを作って」等)は、その依頼を同意とみなしてよい。提示は行い、 + 結果報告に含める +- それ以外(作業の流れで暗黙に起動した場合)は、提示したうえで**明示的な同意を得てから + push する**。同意が得られなければ commit までで止め、push も PR 作成も行わない +- ベースブランチが `main`/`master` 以外の場合は、手順 2 の誘導を優先する + ## 手順 ### 0. PR確認 @@ -39,7 +61,7 @@ allowed-tools: - `git branch --show-current` で現在ブランチを確認 - `gh pr list --head ` で既存PR確認 - 既にPRが存在しOPEN状態なら: - - `git add` → `git commit`(日本語メッセージ)→ `git push` + - `git add` → `git commit`(日本語メッセージ)→ **「push / PR 作成前の同意取得」に従って提示** → `git push` - **既存PR説明を更新** する(「PR説明の更新」節を参照) - 終了報告 - PRがない、またはmerge/close済みなら次へ @@ -64,12 +86,16 @@ allowed-tools: ### 4. プッシュ +**「push / PR 作成前の同意取得」に従って提示し、同意を確認してから実行する。** + ```bash git push -u origin ``` ### 5. PR作成 +- **作成する PR のタイトル・ベースブランチ・ドラフト有無を提示してから実行する** + (手順 4 で一括して同意を得ている場合は再確認不要) - `.github/pull_request_template.md` が存在すれば適用 - `--draft` 指定ならドラフトPR作成 - タイトル・説明は日本語、body は `## Summary` + `## Test plan` diff --git a/plugins/ndf-kiro/skills/merged/SKILL.md b/plugins/ndf-kiro/skills/merged/SKILL.md index 0eeb1939..21cee4ac 100644 --- a/plugins/ndf-kiro/skills/merged/SKILL.md +++ b/plugins/ndf-kiro/skills/merged/SKILL.md @@ -1,6 +1,6 @@ --- name: merged -description: "Clean up after a PR is merged: update main, remove the worktree, and delete the merged branch. Use when a PR has just been merged or leftover branches and worktrees need clearing. Triggers: 'マージ後の後片付け', 'ブランチを整理', 'worktreeを削除', 'merged cleanup'" +description: "Clean up after a merged PR: update main, remove the worktree, and delete merged branches. 削除の前に対象を一覧提示して同意を取る。Use when a PR was merged or branches and worktrees need clearing. Triggers: 'マージ後の後片付け', 'ブランチを整理', 'worktreeを削除', 'merged cleanup'" argument-hint: "[PR番号]" allowed-tools: - Bash @@ -23,13 +23,32 @@ PR マージ後の後始末をまとめて実行する。対象 PR のブラン 手順 1(PR のマージ確認)を前提条件にしてはならない。「マージ済みブランチの整理」と 「main の取り込み」はいずれも **単独で実行可能** で、PR のマージ状態に依存しない。 +## 削除前の同意取得(必須) + +worktree 削除・ローカルブランチ削除・リモートブランチ削除はいずれも取り消しが難しい。 +**この 3 種類の操作は、実行の直前に削除対象を一覧で提示して利用者の同意を得る。 +同意が得られていない対象は削除しない。** この Skill は自然文の依頼でも起動するため、 +安全性はこの手順で担保する(frontmatter の発動制御には依存しない)。 + +| 操作 | 提示するもの | +|---|---| +| worktree 削除 | worktree のパスと、未コミット変更の有無(`git -C status --short`) | +| ローカルブランチ削除 | ブランチ名と、main へ未マージのコミットがあるか | +| リモートブランチ削除 | リモート名とブランチ名。共有ブランチに影響するため、他の削除と分けて同意を取る | + +- 「削除してよいか」だけを尋ねるのは確認にならない。**対象そのものを一覧で示す** +- 同意が得られなかった対象はスキップし、作業完了報告にスキップした対象と理由を記載する +- 利用者が対象を明示して削除を依頼した場合(`/ndf:merged 123` で PR 番号を指定した等)は、 + その依頼が対象への同意にあたる。それでも一覧の提示は行い、依頼に含まれない対象 + (マージ済みブランチの一括整理、リモート削除)については改めて同意を取る + ## クリーンアップの手順 1. **マージ確認**: 引数の(引数がなければ自身が作成した最新の)PR が main に merge されていることを github mcp で確認。merge されていなければクリーンアップは実施せず終了 2. **作業ツリー退避**: `git branch --show-current` で**退避元のブランチ名を記録**し、`git status` を確認して変更があれば `git stash` 3. **main 更新**: `git checkout main` → `git pull` -4. **worktree クリーンアップ**: `git worktree list` で当該 PR 番号に対応する worktree (`pr`) を探し、あれば `git worktree remove ` で削除(worktree 内の `.cross_review/` も一緒に消える) -5. **ブランチ削除**: `git branch -d ` +4. **worktree クリーンアップ**: `git worktree list` で当該 PR 番号に対応する worktree (`pr`) を探し、**「削除前の同意取得」に従ってパスと未コミット変更の有無を提示し、同意を得てから** `git worktree remove ` で削除(worktree 内の `.cross_review/` も一緒に消える) +5. **ブランチ削除**: 削除するブランチ名を提示して同意を得てから `git branch -d ` 6. **マージ済みブランチの整理**: 下記の手順で残存ブランチをまとめて削除 7. **復元**: 手順 2 で stash していれば、**退避元のブランチへ戻してから**復元する - 退避元のブランチが残っている場合: `git checkout <退避元のブランチ>` → `git stash pop` @@ -50,8 +69,9 @@ git push origin --delete # 3. リモートにも残っていれば削 ``` - main と現在のブランチは必ず除外する -- 削除対象を提示し、確認を取ってから削除する -- リモート削除は共有ブランチに影響するため、対象を明示してから実行する +- **手順 2 の前に削除対象のローカルブランチを一覧で提示し、同意を得てから削除する** +- **手順 3 のリモート削除は共有ブランチに影響するため、ローカル削除とは分けて対象を提示し、 + 改めて同意を得てから実行する**(「削除前の同意取得」を参照) ## main の取り込み diff --git a/plugins/ndf-kiro/skills/pr/SKILL.md b/plugins/ndf-kiro/skills/pr/SKILL.md index dfe4ae48..e8e80fcb 100644 --- a/plugins/ndf-kiro/skills/pr/SKILL.md +++ b/plugins/ndf-kiro/skills/pr/SKILL.md @@ -1,6 +1,6 @@ --- name: pr -description: "Commit, push, and create or update a pull request for the current branch. Use when asked to commit and open a PR, update an existing PR, or push work for review. Triggers: 'PRを作って', 'PR作成', 'コミットしてプッシュ', 'PRを更新', 'draft PR'" +description: "Commit, push, and create or update a pull request. push と PR 作成の前に対象ブランチ・base・変更ファイルを提示して同意を取る。Use when asked to commit and open a PR, update a PR, or push work for review. Triggers: 'PRを作って', 'PR作成', 'コミットしてプッシュ', 'PRを更新', 'draft PR'" argument-hint: "[--draft] [base-branch] or [commit-message]" allowed-tools: - Bash @@ -32,6 +32,28 @@ allowed-tools: - それ以外の文字列はコミットメッセージとして扱う - デフォルトは `main` ベース、非ドラフト +## push / PR 作成前の同意取得(必須) + +push と PR 作成は外部(GitHub)への書き込みで、取り消しには追加の操作が要る。 +この Skill は自然文の依頼でも起動するため、安全性はこの手順で担保する +(frontmatter の発動制御には依存しない)。 + +**手順 4(プッシュ)と手順 5(PR 作成)の直前に、次を提示する。** + +- push 先のブランチ名と、PR のベースブランチ +- コミット対象のファイル一覧(`git status --short`)と変更量(`git diff --stat`) +- 使用するコミットメッセージ +- 既存 PR の有無(新規作成なのか、既存 PR の更新なのか) + +同意の扱い: + +- 利用者の依頼が push と PR 作成まで明示的に含む場合(`/ndf:pr` の明示起動、 + 「コミットしてPRを作って」等)は、その依頼を同意とみなしてよい。提示は行い、 + 結果報告に含める +- それ以外(作業の流れで暗黙に起動した場合)は、提示したうえで**明示的な同意を得てから + push する**。同意が得られなければ commit までで止め、push も PR 作成も行わない +- ベースブランチが `main`/`master` 以外の場合は、手順 2 の誘導を優先する + ## 手順 ### 0. PR確認 @@ -39,7 +61,7 @@ allowed-tools: - `git branch --show-current` で現在ブランチを確認 - `gh pr list --head ` で既存PR確認 - 既にPRが存在しOPEN状態なら: - - `git add` → `git commit`(日本語メッセージ)→ `git push` + - `git add` → `git commit`(日本語メッセージ)→ **「push / PR 作成前の同意取得」に従って提示** → `git push` - **既存PR説明を更新** する(「PR説明の更新」節を参照) - 終了報告 - PRがない、またはmerge/close済みなら次へ @@ -64,12 +86,16 @@ allowed-tools: ### 4. プッシュ +**「push / PR 作成前の同意取得」に従って提示し、同意を確認してから実行する。** + ```bash git push -u origin ``` ### 5. PR作成 +- **作成する PR のタイトル・ベースブランチ・ドラフト有無を提示してから実行する** + (手順 4 で一括して同意を得ている場合は再確認不要) - `.github/pull_request_template.md` が存在すれば適用 - `--draft` 指定ならドラフトPR作成 - タイトル・説明は日本語、body は `## Summary` + `## Test plan` diff --git a/plugins/ndf-shared/skills/README.md b/plugins/ndf-shared/skills/README.md index 8a30b618..64d9a7a2 100644 --- a/plugins/ndf-shared/skills/README.md +++ b/plugins/ndf-shared/skills/README.md @@ -65,13 +65,13 @@ when_to_use: "Claude Code 向けの追加トリガのみ。description で足り | --- | --- | --- | --- | --- | | 自動発動(既定) | 追加トリガがあれば `when_to_use` を併記 | 既定で暗黙起動可 | 自動ロード | 知識・判断基準・ワークフロー | | パス限定自動発動 | 上記 + `paths` | `paths` 無効 | `paths` 無効 | 特定ディレクトリでのみ意味を持つもの | -| 明示指示専用 | `disable-model-invocation: true`(引数を取るなら + `argument-hint`) | 現状は制御手段なし。`description` に明示指示専用である旨を記載する | 制御手段なし。`description` に「利用者が明示的に指示したときのみ実行する」と記載 | 破壊的操作・外部への書き込み | +| 明示指示専用 | `disable-model-invocation: true`(引数を取るなら + `argument-hint`) | `agents/openai.yaml` の `policy.allow_implicit_invocation: false`。加えて `description` に明示指示専用である旨を記載する | 制御手段なし。`description` に「利用者が明示的に指示したときのみ実行する」と記載 | 取り消しが難しく、かつ明示起動が定着している操作 | | 常時注入のみ | `user-invocable: false` | 相当機能なし | 相当機能なし | `ndf-policies` | -- Codex には `/agents/openai.yaml` の `policy.allow_implicit_invocation: false` という - 相当機能があるが、現在の `plugins/ndf-codex` 配布物はこのファイルを生成していないため利用でき - ない。生成処理の追加は - [棚卸の計画](../../../issues/ndf-development-skills/07-tasks.md) の Task 0-8 で行う +- Codex の相当機能は `/agents/openai.yaml` の `policy.allow_implicit_invocation: false` + である。`scripts/build-runtime-plugins.sh` が `disable-model-invocation: true` の Skill に対して + このファイルを自動生成するため、共通編集元では frontmatter だけを書けばよい + ([棚卸の計画](../../../issues/ndf-development-skills/07-tasks.md) の Task 0-8) - 「常時注入のみ」に相当する機能は Codex と Kiro にない。両ランタイムは `user-invocable: false` を解釈せず、この分類の Skill も通常の Skill として扱う。唯一の対象である `ndf-policies` は 3 ランタイムすべてへ配布している(`plugins/ndf-shared/manifests/`)ため、Codex では暗黙起動 @@ -83,10 +83,36 @@ when_to_use: "Claude Code 向けの追加トリガのみ。description で足り へ載らず、`user-invocable: false` は載る。Codex と Kiro にはこのキーがなく `description` は 常に読まれるため、明示指示専用にする Skill は `description` 自体へ「利用者が明示的に指示した ときのみ実行する」と書き残す -- 明示指示専用にしてよいのは、実行してしまうと取り消しが難しい操作に限る。日常的に自然文で - 依頼される Skill に付けると、エージェントは Skill を使わず独自手順で実行する - `disable-model-invocation: true` と `user-invocable: false` を同時に指定しない。誰も起動 できなくなる +- 「引数を取るなら + `argument-hint`」の引数の有無は `scripts/check-skill-frontmatter.py` が + `SKILL.md` から機械的に判定する。frontmatter の `arguments`、本文の `$ARGUMENTS`、本文の + 「引数」への言及(節見出しでも散文でもよい)のいずれかがあれば引数を取るとみなす。 + 引数を取るのに本文がそれに一切触れていないと判定から漏れるため、引数の説明は本文に書く + +### 取り消しの難しい操作をどちらで守るか + +破壊的操作・外部への書き込みを含む Skill の守り方は 2 つある。**取り消しの難しさだけでは +決まらない。** 明示指示専用は「その Skill が使われなくなる」副作用を持つため、 +**利用者がどう依頼しているかの実測**で選ぶ。 + +| 守り方 | 選ぶ条件 | 実装 | +| --- | --- | --- | +| 明示指示専用 | 取り消しが難しく、**かつ**利用者が `/ndf:` で明示起動する運用が定着している(自然文での依頼がほぼない) | `disable-model-invocation: true` + `description` に明示指示専用と明記(Codex の `openai.yaml` はビルドで自動生成) | +| 自動発動 + 実行前確認 | 取り消しは難しいが、**日常的に自然文で依頼される**。明示指示専用にすると Skill が使われず、エージェントが独自手順で同じ操作を実行してしまう | 暗黙起動を許し、取り消しの難しい手順の**直前に対象の一覧提示と利用者の同意**を必須手順として `SKILL.md` 本文へ固定する。`description` にも確認を取る旨を書く | + +判断材料は +[棚卸台帳](../../../docs/specifications/ndf-skill-inventory.md)の実測起動数と、 +そのうち明示起動が占める割合である。明示起動がほぼ全数なら前者、自然文の依頼が多い、あるいは +Skill を使わず独自手順で実行された形跡があるなら後者を選ぶ。 + +- 後者では安全性の担保を frontmatter ではなく **本文の手順と `description`** に置く。Codex と + Kiro は `disable-model-invocation` を解釈せず、Claude Code でもそれは発動制御であって + 実行前確認ではないため、そもそも frontmatter だけでは守れない +- 実行前確認では、**何を消すか / 何を外部へ書き込むか**を一覧で提示する。対象を示さない + 「実行してよいですか」は同意になっていない +- 現時点の適用: 明示指示専用は `deploy` / `cherry-pick-pr` / `statusline`、 + 自動発動 + 実行前確認は `merged` / `pr` ## トリガ語の規則 diff --git a/plugins/ndf-shared/skills/merged/SKILL.md b/plugins/ndf-shared/skills/merged/SKILL.md index 0eeb1939..21cee4ac 100644 --- a/plugins/ndf-shared/skills/merged/SKILL.md +++ b/plugins/ndf-shared/skills/merged/SKILL.md @@ -1,6 +1,6 @@ --- name: merged -description: "Clean up after a PR is merged: update main, remove the worktree, and delete the merged branch. Use when a PR has just been merged or leftover branches and worktrees need clearing. Triggers: 'マージ後の後片付け', 'ブランチを整理', 'worktreeを削除', 'merged cleanup'" +description: "Clean up after a merged PR: update main, remove the worktree, and delete merged branches. 削除の前に対象を一覧提示して同意を取る。Use when a PR was merged or branches and worktrees need clearing. Triggers: 'マージ後の後片付け', 'ブランチを整理', 'worktreeを削除', 'merged cleanup'" argument-hint: "[PR番号]" allowed-tools: - Bash @@ -23,13 +23,32 @@ PR マージ後の後始末をまとめて実行する。対象 PR のブラン 手順 1(PR のマージ確認)を前提条件にしてはならない。「マージ済みブランチの整理」と 「main の取り込み」はいずれも **単独で実行可能** で、PR のマージ状態に依存しない。 +## 削除前の同意取得(必須) + +worktree 削除・ローカルブランチ削除・リモートブランチ削除はいずれも取り消しが難しい。 +**この 3 種類の操作は、実行の直前に削除対象を一覧で提示して利用者の同意を得る。 +同意が得られていない対象は削除しない。** この Skill は自然文の依頼でも起動するため、 +安全性はこの手順で担保する(frontmatter の発動制御には依存しない)。 + +| 操作 | 提示するもの | +|---|---| +| worktree 削除 | worktree のパスと、未コミット変更の有無(`git -C status --short`) | +| ローカルブランチ削除 | ブランチ名と、main へ未マージのコミットがあるか | +| リモートブランチ削除 | リモート名とブランチ名。共有ブランチに影響するため、他の削除と分けて同意を取る | + +- 「削除してよいか」だけを尋ねるのは確認にならない。**対象そのものを一覧で示す** +- 同意が得られなかった対象はスキップし、作業完了報告にスキップした対象と理由を記載する +- 利用者が対象を明示して削除を依頼した場合(`/ndf:merged 123` で PR 番号を指定した等)は、 + その依頼が対象への同意にあたる。それでも一覧の提示は行い、依頼に含まれない対象 + (マージ済みブランチの一括整理、リモート削除)については改めて同意を取る + ## クリーンアップの手順 1. **マージ確認**: 引数の(引数がなければ自身が作成した最新の)PR が main に merge されていることを github mcp で確認。merge されていなければクリーンアップは実施せず終了 2. **作業ツリー退避**: `git branch --show-current` で**退避元のブランチ名を記録**し、`git status` を確認して変更があれば `git stash` 3. **main 更新**: `git checkout main` → `git pull` -4. **worktree クリーンアップ**: `git worktree list` で当該 PR 番号に対応する worktree (`pr`) を探し、あれば `git worktree remove ` で削除(worktree 内の `.cross_review/` も一緒に消える) -5. **ブランチ削除**: `git branch -d ` +4. **worktree クリーンアップ**: `git worktree list` で当該 PR 番号に対応する worktree (`pr`) を探し、**「削除前の同意取得」に従ってパスと未コミット変更の有無を提示し、同意を得てから** `git worktree remove ` で削除(worktree 内の `.cross_review/` も一緒に消える) +5. **ブランチ削除**: 削除するブランチ名を提示して同意を得てから `git branch -d ` 6. **マージ済みブランチの整理**: 下記の手順で残存ブランチをまとめて削除 7. **復元**: 手順 2 で stash していれば、**退避元のブランチへ戻してから**復元する - 退避元のブランチが残っている場合: `git checkout <退避元のブランチ>` → `git stash pop` @@ -50,8 +69,9 @@ git push origin --delete # 3. リモートにも残っていれば削 ``` - main と現在のブランチは必ず除外する -- 削除対象を提示し、確認を取ってから削除する -- リモート削除は共有ブランチに影響するため、対象を明示してから実行する +- **手順 2 の前に削除対象のローカルブランチを一覧で提示し、同意を得てから削除する** +- **手順 3 のリモート削除は共有ブランチに影響するため、ローカル削除とは分けて対象を提示し、 + 改めて同意を得てから実行する**(「削除前の同意取得」を参照) ## main の取り込み diff --git a/plugins/ndf-shared/skills/pr/SKILL.md b/plugins/ndf-shared/skills/pr/SKILL.md index dfe4ae48..e8e80fcb 100644 --- a/plugins/ndf-shared/skills/pr/SKILL.md +++ b/plugins/ndf-shared/skills/pr/SKILL.md @@ -1,6 +1,6 @@ --- name: pr -description: "Commit, push, and create or update a pull request for the current branch. Use when asked to commit and open a PR, update an existing PR, or push work for review. Triggers: 'PRを作って', 'PR作成', 'コミットしてプッシュ', 'PRを更新', 'draft PR'" +description: "Commit, push, and create or update a pull request. push と PR 作成の前に対象ブランチ・base・変更ファイルを提示して同意を取る。Use when asked to commit and open a PR, update a PR, or push work for review. Triggers: 'PRを作って', 'PR作成', 'コミットしてプッシュ', 'PRを更新', 'draft PR'" argument-hint: "[--draft] [base-branch] or [commit-message]" allowed-tools: - Bash @@ -32,6 +32,28 @@ allowed-tools: - それ以外の文字列はコミットメッセージとして扱う - デフォルトは `main` ベース、非ドラフト +## push / PR 作成前の同意取得(必須) + +push と PR 作成は外部(GitHub)への書き込みで、取り消しには追加の操作が要る。 +この Skill は自然文の依頼でも起動するため、安全性はこの手順で担保する +(frontmatter の発動制御には依存しない)。 + +**手順 4(プッシュ)と手順 5(PR 作成)の直前に、次を提示する。** + +- push 先のブランチ名と、PR のベースブランチ +- コミット対象のファイル一覧(`git status --short`)と変更量(`git diff --stat`) +- 使用するコミットメッセージ +- 既存 PR の有無(新規作成なのか、既存 PR の更新なのか) + +同意の扱い: + +- 利用者の依頼が push と PR 作成まで明示的に含む場合(`/ndf:pr` の明示起動、 + 「コミットしてPRを作って」等)は、その依頼を同意とみなしてよい。提示は行い、 + 結果報告に含める +- それ以外(作業の流れで暗黙に起動した場合)は、提示したうえで**明示的な同意を得てから + push する**。同意が得られなければ commit までで止め、push も PR 作成も行わない +- ベースブランチが `main`/`master` 以外の場合は、手順 2 の誘導を優先する + ## 手順 ### 0. PR確認 @@ -39,7 +61,7 @@ allowed-tools: - `git branch --show-current` で現在ブランチを確認 - `gh pr list --head ` で既存PR確認 - 既にPRが存在しOPEN状態なら: - - `git add` → `git commit`(日本語メッセージ)→ `git push` + - `git add` → `git commit`(日本語メッセージ)→ **「push / PR 作成前の同意取得」に従って提示** → `git push` - **既存PR説明を更新** する(「PR説明の更新」節を参照) - 終了報告 - PRがない、またはmerge/close済みなら次へ @@ -64,12 +86,16 @@ allowed-tools: ### 4. プッシュ +**「push / PR 作成前の同意取得」に従って提示し、同意を確認してから実行する。** + ```bash git push -u origin ``` ### 5. PR作成 +- **作成する PR のタイトル・ベースブランチ・ドラフト有無を提示してから実行する** + (手順 4 で一括して同意を得ている場合は再確認不要) - `.github/pull_request_template.md` が存在すれば適用 - `--draft` 指定ならドラフトPR作成 - タイトル・説明は日本語、body は `## Summary` + `## Test plan` diff --git a/scripts/check-skill-frontmatter.py b/scripts/check-skill-frontmatter.py index 269a00d8..53be338d 100644 --- a/scripts/check-skill-frontmatter.py +++ b/scripts/check-skill-frontmatter.py @@ -65,6 +65,37 @@ USE_WHEN_RE = re.compile(r"Use\s+when|use\s+when|使う|使い|とき|時に|ときに") SENTENCE_SPLIT_RE = re.compile(r"(?<=[.。])\s*") +# --- 「引数を取る Skill か」の判定 ------------------------------------------- +# 規約(README「発動制御の 4 分類」)は明示指示専用の Skill に対して +# 「disable-model-invocation: true(引数を取るなら + argument-hint)」と定めている。 +# 引数を取らない明示指示専用 Skill まで落とさないよう、引数の有無を SKILL.md から +# 機械的に判定する。判定材料は、実際の Skill が引数を表現している次の 3 通り。 +# +# 1. frontmatter の `arguments` … Claude Code の名前付き引数を宣言している +# 2. 本文の `$ARGUMENTS` … 引数をそのまま展開する(deploy / fix / plan-to-spec) +# 3. 本文が引数を説明している … 「## 引数」節(review / pr-tests / cross-review)、 +# 「### 1. 引数・現状確認」(cherry-pick-pr)、 +# 「引数に応じて…」(statusline)など表記は揺れる +# +# 3 は見出しに限定すると statusline のような散文の説明を取りこぼすため、本文中の +# 「引数」への言及も拾う。英語表記は一般語と紛れるので見出しに限定する。 +# 引数を取るのに SKILL.md がそれを一切説明していない Skill は判定から漏れるが、 +# その場合は利用者にも引数が伝わらないため argument-hint 以前の問題として扱う。 +ARGUMENTS_VAR_RE = re.compile(r"\$\{?ARGUMENTS\}?") +ARGUMENTS_HEADING_RE = re.compile(r"^#{1,6}\s.*\b(?:arguments?|options?)\b", re.MULTILINE | re.IGNORECASE) +ARGUMENTS_TEXT_RE = re.compile(r"引数") + + +def takes_arguments(fm: dict[str, str], body: str) -> bool: + """SKILL.md が引数を取ると読めるかを判定する(判定根拠は上のコメント)。""" + if "arguments" in fm: + return True + return bool( + ARGUMENTS_VAR_RE.search(body) + or ARGUMENTS_TEXT_RE.search(body) + or ARGUMENTS_HEADING_RE.search(body) + ) + class Finding: __slots__ = ("skill", "level", "code", "message") @@ -142,11 +173,13 @@ def load_skills(skills_dir: pathlib.Path) -> list[dict]: continue text = f.read_text(encoding="utf-8", errors="replace") fm, block = parse_front_matter(text) + m = FRONT_MATTER_RE.match(text) skills.append({ "dir": d.name, "path": f, "fm": fm, "block": block, + "body": text[m.end():] if m else text, "lines": len(text.splitlines()), }) return skills @@ -253,11 +286,11 @@ def check_skill(s: dict) -> list[Finding]: if dmi and uinv: add("error", "ops/uninvocable", "disable-model-invocation: true と user-invocable: false の同時指定は誰も起動できない") - if dmi and not fm.get("argument-hint"): - # 近似判定ではなく機械的に判定できるため、計画(Task 0-7 の検査項目表)どおり - # 失敗条件として扱う。 + if dmi and takes_arguments(fm, s["body"]) and not fm.get("argument-hint"): + # 規約は「引数を取るなら + argument-hint」。引数を取らない明示指示専用 Skill には + # 要求しない(判定方法は takes_arguments の説明を参照)。 add("error", "ops/argument-hint", - "disable-model-invocation があるのに argument-hint がない(明示起動時の引数が伝わらない)") + "引数を取る明示指示専用 Skill に argument-hint がない(明示起動時の引数が伝わらない)") ctx = unquote(fm.get("context", "")) for k in ("agent", "background"): From 95c8f1c9a01f7b23fc3aacf9bc04f952b28650f1 Mon Sep 17 00:00:00 2001 From: "takemi.ohama" Date: Sat, 8 Aug 2026 05:40:04 +0000 Subject: [PATCH 7/7] =?UTF-8?q?Fix:=20official-skills-autoloader=20?= =?UTF-8?q?=E3=81=AB=E3=82=A4=E3=83=B3=E3=82=B9=E3=83=88=E3=83=BC=E3=83=AB?= =?UTF-8?q?=E5=89=8D=E3=81=AE=E5=90=8C=E6=84=8F=E5=8F=96=E5=BE=97=E3=82=92?= =?UTF-8?q?=E5=BF=85=E9=A0=88=E5=8C=96=E3=81=97=E3=83=91=E3=82=B9=E3=82=92?= =?UTF-8?q?=E9=85=8D=E5=B8=83=E7=89=A9=E5=9F=BA=E6=BA=96=E3=81=B8=E4=BF=AE?= =?UTF-8?q?=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit cross-review round 2 の指摘 3 件に対応。 - official-skills-autoloader に「インストール前の同意取得(必須)」節を新設。 クローン元 URL / クローン先 / symlink を張る先 / 対象 Skill 名の 4 点を一覧提示して 同意を得てからステップ3 を実行することを必須手順として固定。description と when_to_use にも確認を取る旨を追記 - 手動管理コマンドとプロジェクト配置の案内を ${CLAUDE_PLUGIN_ROOT}/scripts/install-official-skills.sh へ置き換え。 playwright-authoring / playwright-kit-ops に残っていた配布物で解決できない plugins/ndf-shared/... の案内も修正 - 規約 (skills/README.md) の「取り消しの難しい操作をどちらで守るか」の適用先を表に整理し、 official-skills-autoloader を「自動発動 + 実行前確認」として追加 - 棚卸台帳の発動制御表に判断理由を追記し、実測値を再計測結果へ更新 (description 最大 296 / Claude 6,036 / Codex 6,473 / frontmatter 12,211) Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_01AGejnYyYFuSkQjBhW2KQNy --- docs/specifications/ndf-skill-inventory.md | 14 +++-- .../official-skills-autoloader/SKILL.md | 63 ++++++++++++++++--- .../skills/playwright-authoring/SKILL.md | 5 +- .../skills/playwright-authoring/SKILL.md | 5 +- .../skills/playwright-kit-ops/SKILL.md | 10 +-- .../playwright_kit/uploaders/__init__.py | 2 +- .../playwright-kit-ops/scripts/_drive_auth.py | 2 +- .../scripts/upload_evidence.py | 2 +- .../templates/runtime-README.md | 9 ++- .../skills/playwright-authoring/SKILL.md | 5 +- plugins/ndf-shared/skills/README.md | 15 ++++- .../official-skills-autoloader/SKILL.md | 63 ++++++++++++++++--- .../skills/playwright-authoring/SKILL.md | 5 +- .../skills/playwright-kit-ops/SKILL.md | 10 +-- .../playwright_kit/uploaders/__init__.py | 2 +- .../playwright-kit-ops/scripts/_drive_auth.py | 2 +- .../scripts/upload_evidence.py | 2 +- .../templates/runtime-README.md | 9 ++- scripts/check-skill-frontmatter.py | 4 +- 19 files changed, 174 insertions(+), 55 deletions(-) diff --git a/docs/specifications/ndf-skill-inventory.md b/docs/specifications/ndf-skill-inventory.md index c5f2b573..dabb7497 100644 --- a/docs/specifications/ndf-skill-inventory.md +++ b/docs/specifications/ndf-skill-inventory.md @@ -177,6 +177,7 @@ frontmatter を [規約](../../plugins/ndf-shared/skills/README.md) へ揃えた | `merged` / `pr` | 実行前確認を必須手順として本文へ固定 | 上記 2 つは取り消しの難しい操作(worktree / ブランチ削除、push と PR 作成)を含む。自動発動を許すかわりに、削除・書き込みの直前に対象を一覧提示して同意を得る手順を `SKILL.md` と `description` に固定した。`disable-model-invocation` を解釈しない Codex / Kiro でも同じ安全性が働く | | `deploy` / `cherry-pick-pr` / `statusline` | 明示指示専用を維持 | 環境ブランチへの書き込みと設定ファイルの書き換えを伴う。`description` に「利用者が明示的に指示したときのみ実行する」と明記し、Codex / Kiro でも意図が伝わるようにした | | `ndf-policies` | `user-invocable: false` を維持 | `description` に「知識として参照するだけで、手順として実行しない」と明記した | +| `official-skills-autoloader` | 自動発動を維持し、実行前確認を必須手順として本文へ固定 | 本 PR で Claude Code の manifest へ追加したことで暗黙起動が可能になり、外部リポジトリの clone と `~/.claude/skills/` への symlink 作成が同意なしに走りうる状態になった。明示指示専用(`disable-model-invocation`)も検討したが、この Skill は起動 0 / 機会 97 で台帳の判定が「発動改善」であり、明示専用は判定と逆行して機会 97 をそのまま取りこぼす。また `~/.claude/skills/` を読むのは Claude Code だけで Codex / Kiro には配布しないが、`disable-model-invocation` は Claude Code でも発動制御であって実行前確認ではないため、これだけでは同意取得を保証できない。したがって `merged` / `pr` と同じ「自動発動 + 実行前確認」を採り、クローン元 URL・クローン先・symlink を張る先・対象 Skill 名の 4 点を一覧提示して同意を得る手順を `SKILL.md` と `description` に固定した | ### 配布先 @@ -202,10 +203,15 @@ frontmatter を [規約](../../plugins/ndf-shared/skills/README.md) へ揃えた | --- | ---: | ---: | ---: | | 検査エラー | 33 | 0 | 0 | | 検査警告 | 16 | 0 | — | -| `description` 最大 | 401 | 288 | 300 | -| Claude Code 初期一覧 | 3,133 | 6,029 | 8,000 | -| Codex 初期一覧 | 3,933 | 6,466 | 8,000 | -| frontmatter 合計 | 12,724 | 12,145 | 13,000 | +| `description` 最大 | 401 | 296 | 300 | +| Claude Code 初期一覧 | 3,133 | 6,036 | 8,000 | +| Codex 初期一覧 | 3,933 | 6,473 | 8,000 | +| frontmatter 合計 | 12,724 | 12,211 | 13,000 | + +見直し後の値は `python3 scripts/check-skill-frontmatter.py --report` の出力(Skill 29 個、 +エラー 0 / 警告 0)である。Claude Code の初期一覧は 1 項目を 250 文字で切り詰めてから積むため、 +`description` を 250 文字より長くしても合計は増えない。Codex の初期一覧は Codex の manifest に +載る Skill だけを数えるため、Claude Code 限定の `official-skills-autoloader` は含まれない。 初期一覧の合計が増えているのは、`when_to_use` に置いていたトリガ語を `description` へ移し、 Codex と Kiro でも発動判定に効くようにしたためである。 diff --git a/plugins/ndf-claude/skills/official-skills-autoloader/SKILL.md b/plugins/ndf-claude/skills/official-skills-autoloader/SKILL.md index 3c260a60..3ae3148c 100644 --- a/plugins/ndf-claude/skills/official-skills-autoloader/SKILL.md +++ b/plugins/ndf-claude/skills/official-skills-autoloader/SKILL.md @@ -1,7 +1,7 @@ --- name: official-skills-autoloader -description: "Install an Anthropic official Skill on demand (docx / pptx / xlsx / pdf / frontend-design / webapp-testing / mcp-builder) and run it. Use when a request needs Office or PDF output that no local Skill covers. Triggers: 'Word作成', 'Excel出力', 'スライド生成', 'PDF作成'" -when_to_use: "Claude Code 専用。~/.claude/skills/ へ公式 Skill を取得して読み込む。追加トリガ: '.docx', '.pptx', '.xlsx', '.pdf', 'MCPサーバーを作りたい', 'フロントエンド設計'" +description: "Install an Anthropic official Skill on demand and run it. Use when a request needs Office or PDF output that no local Skill covers. Triggers: 'Word作成', 'Excel出力', 'スライド生成', 'PDF作成'. 対象は docx / pptx / xlsx / pdf / frontend-design / webapp-testing / mcp-builder。取得元・書き込み先・対象 Skill を提示して同意を得てから実行する。" +when_to_use: "Claude Code 専用。~/.claude/skills/ へ公式 Skill を取得して読み込む。インストールは同意を得てから実行する。追加トリガ: '.docx', '.pptx', '.xlsx', '.pdf', 'MCPサーバーを作りたい', 'フロントエンド設計'" allowed-tools: - Bash - Read @@ -9,7 +9,7 @@ allowed-tools: # 公式Skill自動ローダー -ユーザーの要求から必要なAnthropic公式Skillを特定し、未インストールなら自動でインストール→読込して作業を進めます。利用者は**インストール作業を意識する必要がありません**。 +ユーザーの要求から必要なAnthropic公式Skillを特定し、未インストールなら**同意を得たうえで**インストール→読込して作業を進めます。利用者はインストール手順そのものを調べる必要はありませんが、**外部リポジトリの取得とホームディレクトリへの書き込みは同意なしに行いません**。 ## 対応マッピング @@ -32,6 +32,42 @@ allowed-tools: 配布先は `plugins/ndf-shared/manifests/claude-skills.txt` のみとする。Codex / Kiro の manifest には載せない。 +## インストール前の同意取得(必須) + +この Skill は自然文の依頼でも起動する。インストールは**外部リポジトリの取得**と +**ホームディレクトリ配下への書き込み**を伴い、利用者が明示的に頼んでいない操作になりうる。 +**ステップ3 を実行する前に、以下の 4 点を一覧で提示して利用者の同意を得る。同意が得られなければ +インストールを行わず、その Skill を使わない方法で作業を続けるか、作業を中断する。** + +| 提示する項目 | 値 | +|---|---| +| 対象 Skill 名 | ステップ1 で特定した名前(複数なら全件) | +| クローン元 URL | `https://github.com/anthropics/skills.git`(`--depth 1`) | +| クローン先 | `${XDG_CACHE_HOME:-$HOME/.cache}/anthropic-skills`(実際に展開したパスを表示する) | +| symlink を張る先 | `$HOME/.claude/skills/<対象 Skill 名>` | + +提示例: + +``` +公式 Skill `pptx` が未インストールです。インストールしてよろしいですか。 +- 取得元: https://github.com/anthropics/skills.git (--depth 1) +- 取得先: /home/user/.cache/anthropic-skills +- リンク作成先: /home/user/.claude/skills/pptx +- 対象 Skill: pptx +``` + +規則: + +- 「インストールしてよいですか」だけを尋ねるのは確認にならない。**上記 4 点を必ず示す** +- 利用者が `/ndf:official-skills-autoloader pptx` のように対象を指定して明示起動した場合や、 + 「公式 Skill を入れて」のように依頼自体がインストールを含む場合は、その依頼を同意とみなす。 + それでも取得元・取得先・リンク作成先は提示する +- **暗黙起動(「スライドを作って」等)の場合は、提示のうえ明示的な同意を得てから実行する** +- すでにインストール済み(ステップ2 が `INSTALLED`)ならインストールは発生しないため、 + 同意取得は不要。ステップ4 へ進む +- ライセンスがプロプライエタリな Skill(`docx` / `pptx` / `xlsx` / `pdf`)では、 + 「注意事項 > ライセンス」の制約もあわせて提示する + ## 動作手順 ### ステップ1: 対象Skillを特定 @@ -51,7 +87,10 @@ else fi ``` -### ステップ3: 未インストールなら自動インストール +### ステップ3: 未インストールならインストール + +**「インストール前の同意取得(必須)」を先に実施し、同意を得てからこのコマンドを実行する。** +同意が得られていない状態でこのブロックを実行してはならない。 ```bash SKILL_NAME="<対象名>" @@ -77,7 +116,7 @@ ln -sfn "$CACHE_DIR/skills/$SKILL_NAME" "$USER_SKILLS/$SKILL_NAME" echo "Installed: $USER_SKILLS/$SKILL_NAME" ``` -ユーザーには「公式Skill `` を準備しています...」と一言伝える。 +同意を得たうえで実行し、ユーザーには「公式Skill `` を準備しています...」と一言伝える。 ### ステップ4: SKILL.mdを読み込んで実行 @@ -100,7 +139,7 @@ Read(file_path="$HOME/.claude/skills//SKILL.md") - cache: `~/.cache/anthropic-skills/` (XDG準拠) - リンク先: `~/.claude/skills//` (ユーザー領域) -- プロジェクト単位で配置したい場合は `plugins/ndf-shared/scripts/install-official-skills.sh --scope project ` を直接実行 +- プロジェクト単位で配置したい場合は `bash ${CLAUDE_PLUGIN_ROOT}/scripts/install-official-skills.sh --scope project ` を直接実行 ### 再読込 @@ -108,9 +147,15 @@ Read(file_path="$HOME/.claude/skills//SKILL.md") ### 手動管理したい場合 -- 一覧表示: `bash plugins/ndf-shared/scripts/install-official-skills.sh --list` -- 更新: `bash plugins/ndf-shared/scripts/install-official-skills.sh --update` -- 明示的なインストール: `bash plugins/ndf-shared/scripts/install-official-skills.sh ` +スクリプトはプラグインの配布物に含まれる。`${CLAUDE_PLUGIN_ROOT}` は Claude Code が +インストール済みプラグインのルートに展開する環境変数で、`scripts/` はその直下にある。 + +- 一覧表示: `bash ${CLAUDE_PLUGIN_ROOT}/scripts/install-official-skills.sh --list` +- 更新: `bash ${CLAUDE_PLUGIN_ROOT}/scripts/install-official-skills.sh --update` +- 明示的なインストール: `bash ${CLAUDE_PLUGIN_ROOT}/scripts/install-official-skills.sh ` + +リポジトリを直接 clone して作業している場合は `plugins/ndf-claude/scripts/install-official-skills.sh` +(編集元は `plugins/ndf-shared/scripts/install-official-skills.sh`)を使う。 ## エラーハンドリング diff --git a/plugins/ndf-claude/skills/playwright-authoring/SKILL.md b/plugins/ndf-claude/skills/playwright-authoring/SKILL.md index e196c902..fd67b896 100644 --- a/plugins/ndf-claude/skills/playwright-authoring/SKILL.md +++ b/plugins/ndf-claude/skills/playwright-authoring/SKILL.md @@ -245,5 +245,6 @@ Chrome DevTools MCP の利用可能な方を自動選択する。どちらも使 - `/ndf:review --branch` — 変更差分のコードレビュー - `/ndf:pr-tests` — PR Test Plan の自動実行 -> `playwright-planning` / `playwright-evidence` / `playwright-kit-ops` は Codex 公開セットに同梱される。 -> Claude Code / Kiro CLI では `plugins/ndf-shared/skills/` を直接参照する。 +> `playwright-planning` / `playwright-evidence` / `playwright-kit-ops` は Codex 公開セットにのみ同梱される。 +> Claude Code / Kiro CLI のプラグインには含まれないため、必要な場合はリポジトリ +> [devbasex/ai-plugins](https://github.com/devbasex/ai-plugins) の `plugins/ndf-shared/skills/` を参照する。 diff --git a/plugins/ndf-codex/skills/playwright-authoring/SKILL.md b/plugins/ndf-codex/skills/playwright-authoring/SKILL.md index e196c902..fd67b896 100644 --- a/plugins/ndf-codex/skills/playwright-authoring/SKILL.md +++ b/plugins/ndf-codex/skills/playwright-authoring/SKILL.md @@ -245,5 +245,6 @@ Chrome DevTools MCP の利用可能な方を自動選択する。どちらも使 - `/ndf:review --branch` — 変更差分のコードレビュー - `/ndf:pr-tests` — PR Test Plan の自動実行 -> `playwright-planning` / `playwright-evidence` / `playwright-kit-ops` は Codex 公開セットに同梱される。 -> Claude Code / Kiro CLI では `plugins/ndf-shared/skills/` を直接参照する。 +> `playwright-planning` / `playwright-evidence` / `playwright-kit-ops` は Codex 公開セットにのみ同梱される。 +> Claude Code / Kiro CLI のプラグインには含まれないため、必要な場合はリポジトリ +> [devbasex/ai-plugins](https://github.com/devbasex/ai-plugins) の `plugins/ndf-shared/skills/` を参照する。 diff --git a/plugins/ndf-codex/skills/playwright-kit-ops/SKILL.md b/plugins/ndf-codex/skills/playwright-kit-ops/SKILL.md index ab1a7c0f..595f3cd1 100644 --- a/plugins/ndf-codex/skills/playwright-kit-ops/SKILL.md +++ b/plugins/ndf-codex/skills/playwright-kit-ops/SKILL.md @@ -58,12 +58,14 @@ cd /path/to/your-app ./scenario-test/run.sh --pwk-drive-folder= # Drive 自動アップロード ``` -Drive 連携は optional dependency として扱う。Codex 公開セットには `google-auth` -skill を同梱しないため、Drive 系コマンドや `--pwk-drive-folder` を使う場合は -`GOOGLE_AUTH_SCRIPTS` を `google-auth/scripts` の実パスへ設定する。 +Drive 連携は optional dependency として扱う。`google-auth` skill はどのランタイムの +配布物にも同梱していないため、Drive 系コマンドや `--pwk-drive-folder` を使う場合は +リポジトリ [devbasex/ai-plugins](https://github.com/devbasex/ai-plugins) を clone し、 +`GOOGLE_AUTH_SCRIPTS` をその clone 先の `google-auth/scripts` へ設定する。 ```bash -export GOOGLE_AUTH_SCRIPTS=/path/to/plugins/ndf-shared/skills/google-auth/scripts +# を実パスに置き換える +export GOOGLE_AUTH_SCRIPTS=/plugins/ndf-shared/skills/google-auth/scripts cd scenario-test uv sync --extra drive ``` diff --git a/plugins/ndf-codex/skills/playwright-kit-ops/playwright_kit/uploaders/__init__.py b/plugins/ndf-codex/skills/playwright-kit-ops/playwright_kit/uploaders/__init__.py index 3d8f8e98..d7bdb900 100644 --- a/plugins/ndf-codex/skills/playwright-kit-ops/playwright_kit/uploaders/__init__.py +++ b/plugins/ndf-codex/skills/playwright-kit-ops/playwright_kit/uploaders/__init__.py @@ -45,7 +45,7 @@ def _ensure_google_auth_on_path() -> None: "Google Drive 連携には optional skill `google-auth` が必要です。\n" "Codex 公開セットには同梱していないため、Drive 系コマンドを使う前に " "`GOOGLE_AUTH_SCRIPTS` を google-auth/scripts へ設定してください。\n" - "例: export GOOGLE_AUTH_SCRIPTS=/path/to/plugins/ndf-shared/skills/google-auth/scripts\n" + "例: export GOOGLE_AUTH_SCRIPTS=/plugins/ndf-shared/skills/google-auth/scripts\n" "検索した候補:\n - " f"{searched}" ) diff --git a/plugins/ndf-codex/skills/playwright-kit-ops/scripts/_drive_auth.py b/plugins/ndf-codex/skills/playwright-kit-ops/scripts/_drive_auth.py index ddc873cc..bb40055d 100644 --- a/plugins/ndf-codex/skills/playwright-kit-ops/scripts/_drive_auth.py +++ b/plugins/ndf-codex/skills/playwright-kit-ops/scripts/_drive_auth.py @@ -43,7 +43,7 @@ def _ensure_google_auth_on_path() -> None: "Google Drive 連携には optional skill `google-auth` が必要です。\n" "Codex 公開セットには同梱していないため、Drive 系コマンドを使う前に " "`GOOGLE_AUTH_SCRIPTS` を google-auth/scripts へ設定してください。\n" - "例: export GOOGLE_AUTH_SCRIPTS=/path/to/plugins/ndf-shared/skills/google-auth/scripts\n" + "例: export GOOGLE_AUTH_SCRIPTS=/plugins/ndf-shared/skills/google-auth/scripts\n" "検索した候補:\n - " f"{searched}" ) diff --git a/plugins/ndf-codex/skills/playwright-kit-ops/scripts/upload_evidence.py b/plugins/ndf-codex/skills/playwright-kit-ops/scripts/upload_evidence.py index ebe2abc8..ea249e66 100644 --- a/plugins/ndf-codex/skills/playwright-kit-ops/scripts/upload_evidence.py +++ b/plugins/ndf-codex/skills/playwright-kit-ops/scripts/upload_evidence.py @@ -49,7 +49,7 @@ def _ensure_google_auth_on_path() -> None: "Google Drive 連携には optional skill `google-auth` が必要です。\n" "Codex 公開セットには同梱していないため、Drive 系コマンドを使う前に " "`GOOGLE_AUTH_SCRIPTS` を google-auth/scripts へ設定してください。\n" - "例: export GOOGLE_AUTH_SCRIPTS=/path/to/plugins/ndf-shared/skills/google-auth/scripts\n" + "例: export GOOGLE_AUTH_SCRIPTS=/plugins/ndf-shared/skills/google-auth/scripts\n" "検索した候補:\n - " f"{searched}" ) diff --git a/plugins/ndf-codex/skills/playwright-kit-ops/templates/runtime-README.md b/plugins/ndf-codex/skills/playwright-kit-ops/templates/runtime-README.md index 945db447..8ae433b1 100644 --- a/plugins/ndf-codex/skills/playwright-kit-ops/templates/runtime-README.md +++ b/plugins/ndf-codex/skills/playwright-kit-ops/templates/runtime-README.md @@ -96,12 +96,15 @@ web vitals (LCP/CLS/TTFB) が **autouse で自動実行** されます。 - `--pwk-overlay`: 動画に赤丸カーソル + 字幕を焼き込む - `--pwk-drive-folder `: 終了後に成果物を Google Drive にアップロード -Drive 連携は optional dependency です。`--pwk-drive-folder` や Drive 系スクリプトを -使う場合は、事前に `GOOGLE_AUTH_SCRIPTS` を `google-auth/scripts` の実パスへ設定し、 +Drive 連携は optional dependency です。`google-auth` skill はどのランタイムの配布物にも +同梱していないため、`--pwk-drive-folder` や Drive 系スクリプトを使う場合はリポジトリ +[devbasex/ai-plugins](https://github.com/devbasex/ai-plugins) を clone し、事前に +`GOOGLE_AUTH_SCRIPTS` をその clone 先の `google-auth/scripts` へ設定してから Drive extra を同期してください。 ```bash -export GOOGLE_AUTH_SCRIPTS=/path/to/plugins/ndf-shared/skills/google-auth/scripts +# を clone 先の実パスに置き換える +export GOOGLE_AUTH_SCRIPTS=/plugins/ndf-shared/skills/google-auth/scripts uv sync --extra drive ``` diff --git a/plugins/ndf-kiro/skills/playwright-authoring/SKILL.md b/plugins/ndf-kiro/skills/playwright-authoring/SKILL.md index e196c902..fd67b896 100644 --- a/plugins/ndf-kiro/skills/playwright-authoring/SKILL.md +++ b/plugins/ndf-kiro/skills/playwright-authoring/SKILL.md @@ -245,5 +245,6 @@ Chrome DevTools MCP の利用可能な方を自動選択する。どちらも使 - `/ndf:review --branch` — 変更差分のコードレビュー - `/ndf:pr-tests` — PR Test Plan の自動実行 -> `playwright-planning` / `playwright-evidence` / `playwright-kit-ops` は Codex 公開セットに同梱される。 -> Claude Code / Kiro CLI では `plugins/ndf-shared/skills/` を直接参照する。 +> `playwright-planning` / `playwright-evidence` / `playwright-kit-ops` は Codex 公開セットにのみ同梱される。 +> Claude Code / Kiro CLI のプラグインには含まれないため、必要な場合はリポジトリ +> [devbasex/ai-plugins](https://github.com/devbasex/ai-plugins) の `plugins/ndf-shared/skills/` を参照する。 diff --git a/plugins/ndf-shared/skills/README.md b/plugins/ndf-shared/skills/README.md index 64d9a7a2..e9f5211f 100644 --- a/plugins/ndf-shared/skills/README.md +++ b/plugins/ndf-shared/skills/README.md @@ -111,8 +111,17 @@ Skill を使わず独自手順で実行された形跡があるなら後者を 実行前確認ではないため、そもそも frontmatter だけでは守れない - 実行前確認では、**何を消すか / 何を外部へ書き込むか**を一覧で提示する。対象を示さない 「実行してよいですか」は同意になっていない -- 現時点の適用: 明示指示専用は `deploy` / `cherry-pick-pr` / `statusline`、 - 自動発動 + 実行前確認は `merged` / `pr` + +現時点の適用: + +| Skill | 守り方 | 取り消しの難しい操作 | 判断根拠(棚卸台帳の実測) | +| --- | --- | --- | --- | +| `deploy` | 明示指示専用 | 本番デプロイ | 明示起動の運用が定着 | +| `cherry-pick-pr` | 明示指示専用 | 環境ブランチへの push | 同上 | +| `statusline` | 明示指示専用 | ユーザー設定ファイルの書き換え | 同上 | +| `merged` | 自動発動 + 実行前確認 | worktree / ローカル・リモートブランチ削除 | 起動 248(明示 248 / 自動 0)。統合元の `clean` は起動 0 / 機会 251 | +| `pr` | 自動発動 + 実行前確認 | commit / push / PR 作成 | 起動 173(明示 171 / 自動 2)。自然文の依頼では Skill を通らず独自手順で実行されていた | +| `official-skills-autoloader` | 自動発動 + 実行前確認 | 外部リポジトリの clone と `~/.claude/skills/` への symlink 作成 | 起動 0 / 機会 97。台帳の判定は「発動改善」で、明示指示専用は判定と逆行する | ## トリガ語の規則 @@ -153,7 +162,7 @@ Skill を使わず独自手順で実行された形跡があるなら後者を | `SKILL.md` 本文 | 5,000 トークン | 仕様の推奨 | | Claude Code の初期 Skill 一覧の合計 | コンテキストウィンドウの 1%。不明な場合は 8,000 文字。1 項目あたり 250 文字で切り詰め | Claude Code 公式ドキュメント | | Codex の初期 Skill 一覧の合計 | コンテキストウィンドウの 2%。不明な場合は 8,000 文字 | Codex 公式ドキュメント | -| 全 Skill の frontmatter 合計 | 13,000 文字 | リポジトリ固有の運用値。Task 0-7 完了時点の実測 12,145 文字(Skill 29 個)に約 7% の余裕を足した値。`scripts/check-skill-frontmatter.py` の `FRONTMATTER_TOTAL_MAX` | +| 全 Skill の frontmatter 合計 | 13,000 文字 | リポジトリ固有の運用値。Task 0-7 完了時点の実測 12,211 文字(Skill 29 個)に約 6% の余裕を足した値。`scripts/check-skill-frontmatter.py` の `FRONTMATTER_TOTAL_MAX` | 運用目標の 300 文字は仕様上限より厳しい。全 Skill 分の `description` が常時注入されるため、 仕様上限は 1 個で使い切ってよい量ではない。 diff --git a/plugins/ndf-shared/skills/official-skills-autoloader/SKILL.md b/plugins/ndf-shared/skills/official-skills-autoloader/SKILL.md index 3c260a60..3ae3148c 100644 --- a/plugins/ndf-shared/skills/official-skills-autoloader/SKILL.md +++ b/plugins/ndf-shared/skills/official-skills-autoloader/SKILL.md @@ -1,7 +1,7 @@ --- name: official-skills-autoloader -description: "Install an Anthropic official Skill on demand (docx / pptx / xlsx / pdf / frontend-design / webapp-testing / mcp-builder) and run it. Use when a request needs Office or PDF output that no local Skill covers. Triggers: 'Word作成', 'Excel出力', 'スライド生成', 'PDF作成'" -when_to_use: "Claude Code 専用。~/.claude/skills/ へ公式 Skill を取得して読み込む。追加トリガ: '.docx', '.pptx', '.xlsx', '.pdf', 'MCPサーバーを作りたい', 'フロントエンド設計'" +description: "Install an Anthropic official Skill on demand and run it. Use when a request needs Office or PDF output that no local Skill covers. Triggers: 'Word作成', 'Excel出力', 'スライド生成', 'PDF作成'. 対象は docx / pptx / xlsx / pdf / frontend-design / webapp-testing / mcp-builder。取得元・書き込み先・対象 Skill を提示して同意を得てから実行する。" +when_to_use: "Claude Code 専用。~/.claude/skills/ へ公式 Skill を取得して読み込む。インストールは同意を得てから実行する。追加トリガ: '.docx', '.pptx', '.xlsx', '.pdf', 'MCPサーバーを作りたい', 'フロントエンド設計'" allowed-tools: - Bash - Read @@ -9,7 +9,7 @@ allowed-tools: # 公式Skill自動ローダー -ユーザーの要求から必要なAnthropic公式Skillを特定し、未インストールなら自動でインストール→読込して作業を進めます。利用者は**インストール作業を意識する必要がありません**。 +ユーザーの要求から必要なAnthropic公式Skillを特定し、未インストールなら**同意を得たうえで**インストール→読込して作業を進めます。利用者はインストール手順そのものを調べる必要はありませんが、**外部リポジトリの取得とホームディレクトリへの書き込みは同意なしに行いません**。 ## 対応マッピング @@ -32,6 +32,42 @@ allowed-tools: 配布先は `plugins/ndf-shared/manifests/claude-skills.txt` のみとする。Codex / Kiro の manifest には載せない。 +## インストール前の同意取得(必須) + +この Skill は自然文の依頼でも起動する。インストールは**外部リポジトリの取得**と +**ホームディレクトリ配下への書き込み**を伴い、利用者が明示的に頼んでいない操作になりうる。 +**ステップ3 を実行する前に、以下の 4 点を一覧で提示して利用者の同意を得る。同意が得られなければ +インストールを行わず、その Skill を使わない方法で作業を続けるか、作業を中断する。** + +| 提示する項目 | 値 | +|---|---| +| 対象 Skill 名 | ステップ1 で特定した名前(複数なら全件) | +| クローン元 URL | `https://github.com/anthropics/skills.git`(`--depth 1`) | +| クローン先 | `${XDG_CACHE_HOME:-$HOME/.cache}/anthropic-skills`(実際に展開したパスを表示する) | +| symlink を張る先 | `$HOME/.claude/skills/<対象 Skill 名>` | + +提示例: + +``` +公式 Skill `pptx` が未インストールです。インストールしてよろしいですか。 +- 取得元: https://github.com/anthropics/skills.git (--depth 1) +- 取得先: /home/user/.cache/anthropic-skills +- リンク作成先: /home/user/.claude/skills/pptx +- 対象 Skill: pptx +``` + +規則: + +- 「インストールしてよいですか」だけを尋ねるのは確認にならない。**上記 4 点を必ず示す** +- 利用者が `/ndf:official-skills-autoloader pptx` のように対象を指定して明示起動した場合や、 + 「公式 Skill を入れて」のように依頼自体がインストールを含む場合は、その依頼を同意とみなす。 + それでも取得元・取得先・リンク作成先は提示する +- **暗黙起動(「スライドを作って」等)の場合は、提示のうえ明示的な同意を得てから実行する** +- すでにインストール済み(ステップ2 が `INSTALLED`)ならインストールは発生しないため、 + 同意取得は不要。ステップ4 へ進む +- ライセンスがプロプライエタリな Skill(`docx` / `pptx` / `xlsx` / `pdf`)では、 + 「注意事項 > ライセンス」の制約もあわせて提示する + ## 動作手順 ### ステップ1: 対象Skillを特定 @@ -51,7 +87,10 @@ else fi ``` -### ステップ3: 未インストールなら自動インストール +### ステップ3: 未インストールならインストール + +**「インストール前の同意取得(必須)」を先に実施し、同意を得てからこのコマンドを実行する。** +同意が得られていない状態でこのブロックを実行してはならない。 ```bash SKILL_NAME="<対象名>" @@ -77,7 +116,7 @@ ln -sfn "$CACHE_DIR/skills/$SKILL_NAME" "$USER_SKILLS/$SKILL_NAME" echo "Installed: $USER_SKILLS/$SKILL_NAME" ``` -ユーザーには「公式Skill `` を準備しています...」と一言伝える。 +同意を得たうえで実行し、ユーザーには「公式Skill `` を準備しています...」と一言伝える。 ### ステップ4: SKILL.mdを読み込んで実行 @@ -100,7 +139,7 @@ Read(file_path="$HOME/.claude/skills//SKILL.md") - cache: `~/.cache/anthropic-skills/` (XDG準拠) - リンク先: `~/.claude/skills//` (ユーザー領域) -- プロジェクト単位で配置したい場合は `plugins/ndf-shared/scripts/install-official-skills.sh --scope project ` を直接実行 +- プロジェクト単位で配置したい場合は `bash ${CLAUDE_PLUGIN_ROOT}/scripts/install-official-skills.sh --scope project ` を直接実行 ### 再読込 @@ -108,9 +147,15 @@ Read(file_path="$HOME/.claude/skills//SKILL.md") ### 手動管理したい場合 -- 一覧表示: `bash plugins/ndf-shared/scripts/install-official-skills.sh --list` -- 更新: `bash plugins/ndf-shared/scripts/install-official-skills.sh --update` -- 明示的なインストール: `bash plugins/ndf-shared/scripts/install-official-skills.sh ` +スクリプトはプラグインの配布物に含まれる。`${CLAUDE_PLUGIN_ROOT}` は Claude Code が +インストール済みプラグインのルートに展開する環境変数で、`scripts/` はその直下にある。 + +- 一覧表示: `bash ${CLAUDE_PLUGIN_ROOT}/scripts/install-official-skills.sh --list` +- 更新: `bash ${CLAUDE_PLUGIN_ROOT}/scripts/install-official-skills.sh --update` +- 明示的なインストール: `bash ${CLAUDE_PLUGIN_ROOT}/scripts/install-official-skills.sh ` + +リポジトリを直接 clone して作業している場合は `plugins/ndf-claude/scripts/install-official-skills.sh` +(編集元は `plugins/ndf-shared/scripts/install-official-skills.sh`)を使う。 ## エラーハンドリング diff --git a/plugins/ndf-shared/skills/playwright-authoring/SKILL.md b/plugins/ndf-shared/skills/playwright-authoring/SKILL.md index e196c902..fd67b896 100644 --- a/plugins/ndf-shared/skills/playwright-authoring/SKILL.md +++ b/plugins/ndf-shared/skills/playwright-authoring/SKILL.md @@ -245,5 +245,6 @@ Chrome DevTools MCP の利用可能な方を自動選択する。どちらも使 - `/ndf:review --branch` — 変更差分のコードレビュー - `/ndf:pr-tests` — PR Test Plan の自動実行 -> `playwright-planning` / `playwright-evidence` / `playwright-kit-ops` は Codex 公開セットに同梱される。 -> Claude Code / Kiro CLI では `plugins/ndf-shared/skills/` を直接参照する。 +> `playwright-planning` / `playwright-evidence` / `playwright-kit-ops` は Codex 公開セットにのみ同梱される。 +> Claude Code / Kiro CLI のプラグインには含まれないため、必要な場合はリポジトリ +> [devbasex/ai-plugins](https://github.com/devbasex/ai-plugins) の `plugins/ndf-shared/skills/` を参照する。 diff --git a/plugins/ndf-shared/skills/playwright-kit-ops/SKILL.md b/plugins/ndf-shared/skills/playwright-kit-ops/SKILL.md index ab1a7c0f..595f3cd1 100644 --- a/plugins/ndf-shared/skills/playwright-kit-ops/SKILL.md +++ b/plugins/ndf-shared/skills/playwright-kit-ops/SKILL.md @@ -58,12 +58,14 @@ cd /path/to/your-app ./scenario-test/run.sh --pwk-drive-folder= # Drive 自動アップロード ``` -Drive 連携は optional dependency として扱う。Codex 公開セットには `google-auth` -skill を同梱しないため、Drive 系コマンドや `--pwk-drive-folder` を使う場合は -`GOOGLE_AUTH_SCRIPTS` を `google-auth/scripts` の実パスへ設定する。 +Drive 連携は optional dependency として扱う。`google-auth` skill はどのランタイムの +配布物にも同梱していないため、Drive 系コマンドや `--pwk-drive-folder` を使う場合は +リポジトリ [devbasex/ai-plugins](https://github.com/devbasex/ai-plugins) を clone し、 +`GOOGLE_AUTH_SCRIPTS` をその clone 先の `google-auth/scripts` へ設定する。 ```bash -export GOOGLE_AUTH_SCRIPTS=/path/to/plugins/ndf-shared/skills/google-auth/scripts +# を実パスに置き換える +export GOOGLE_AUTH_SCRIPTS=/plugins/ndf-shared/skills/google-auth/scripts cd scenario-test uv sync --extra drive ``` diff --git a/plugins/ndf-shared/skills/playwright-kit-ops/playwright_kit/uploaders/__init__.py b/plugins/ndf-shared/skills/playwright-kit-ops/playwright_kit/uploaders/__init__.py index 3d8f8e98..d7bdb900 100644 --- a/plugins/ndf-shared/skills/playwright-kit-ops/playwright_kit/uploaders/__init__.py +++ b/plugins/ndf-shared/skills/playwright-kit-ops/playwright_kit/uploaders/__init__.py @@ -45,7 +45,7 @@ def _ensure_google_auth_on_path() -> None: "Google Drive 連携には optional skill `google-auth` が必要です。\n" "Codex 公開セットには同梱していないため、Drive 系コマンドを使う前に " "`GOOGLE_AUTH_SCRIPTS` を google-auth/scripts へ設定してください。\n" - "例: export GOOGLE_AUTH_SCRIPTS=/path/to/plugins/ndf-shared/skills/google-auth/scripts\n" + "例: export GOOGLE_AUTH_SCRIPTS=/plugins/ndf-shared/skills/google-auth/scripts\n" "検索した候補:\n - " f"{searched}" ) diff --git a/plugins/ndf-shared/skills/playwright-kit-ops/scripts/_drive_auth.py b/plugins/ndf-shared/skills/playwright-kit-ops/scripts/_drive_auth.py index ddc873cc..bb40055d 100644 --- a/plugins/ndf-shared/skills/playwright-kit-ops/scripts/_drive_auth.py +++ b/plugins/ndf-shared/skills/playwright-kit-ops/scripts/_drive_auth.py @@ -43,7 +43,7 @@ def _ensure_google_auth_on_path() -> None: "Google Drive 連携には optional skill `google-auth` が必要です。\n" "Codex 公開セットには同梱していないため、Drive 系コマンドを使う前に " "`GOOGLE_AUTH_SCRIPTS` を google-auth/scripts へ設定してください。\n" - "例: export GOOGLE_AUTH_SCRIPTS=/path/to/plugins/ndf-shared/skills/google-auth/scripts\n" + "例: export GOOGLE_AUTH_SCRIPTS=/plugins/ndf-shared/skills/google-auth/scripts\n" "検索した候補:\n - " f"{searched}" ) diff --git a/plugins/ndf-shared/skills/playwright-kit-ops/scripts/upload_evidence.py b/plugins/ndf-shared/skills/playwright-kit-ops/scripts/upload_evidence.py index ebe2abc8..ea249e66 100644 --- a/plugins/ndf-shared/skills/playwright-kit-ops/scripts/upload_evidence.py +++ b/plugins/ndf-shared/skills/playwright-kit-ops/scripts/upload_evidence.py @@ -49,7 +49,7 @@ def _ensure_google_auth_on_path() -> None: "Google Drive 連携には optional skill `google-auth` が必要です。\n" "Codex 公開セットには同梱していないため、Drive 系コマンドを使う前に " "`GOOGLE_AUTH_SCRIPTS` を google-auth/scripts へ設定してください。\n" - "例: export GOOGLE_AUTH_SCRIPTS=/path/to/plugins/ndf-shared/skills/google-auth/scripts\n" + "例: export GOOGLE_AUTH_SCRIPTS=/plugins/ndf-shared/skills/google-auth/scripts\n" "検索した候補:\n - " f"{searched}" ) diff --git a/plugins/ndf-shared/skills/playwright-kit-ops/templates/runtime-README.md b/plugins/ndf-shared/skills/playwright-kit-ops/templates/runtime-README.md index 945db447..8ae433b1 100644 --- a/plugins/ndf-shared/skills/playwright-kit-ops/templates/runtime-README.md +++ b/plugins/ndf-shared/skills/playwright-kit-ops/templates/runtime-README.md @@ -96,12 +96,15 @@ web vitals (LCP/CLS/TTFB) が **autouse で自動実行** されます。 - `--pwk-overlay`: 動画に赤丸カーソル + 字幕を焼き込む - `--pwk-drive-folder `: 終了後に成果物を Google Drive にアップロード -Drive 連携は optional dependency です。`--pwk-drive-folder` や Drive 系スクリプトを -使う場合は、事前に `GOOGLE_AUTH_SCRIPTS` を `google-auth/scripts` の実パスへ設定し、 +Drive 連携は optional dependency です。`google-auth` skill はどのランタイムの配布物にも +同梱していないため、`--pwk-drive-folder` や Drive 系スクリプトを使う場合はリポジトリ +[devbasex/ai-plugins](https://github.com/devbasex/ai-plugins) を clone し、事前に +`GOOGLE_AUTH_SCRIPTS` をその clone 先の `google-auth/scripts` へ設定してから Drive extra を同期してください。 ```bash -export GOOGLE_AUTH_SCRIPTS=/path/to/plugins/ndf-shared/skills/google-auth/scripts +# を clone 先の実パスに置き換える +export GOOGLE_AUTH_SCRIPTS=/plugins/ndf-shared/skills/google-auth/scripts uv sync --extra drive ``` diff --git a/scripts/check-skill-frontmatter.py b/scripts/check-skill-frontmatter.py index 53be338d..a1cd3225 100644 --- a/scripts/check-skill-frontmatter.py +++ b/scripts/check-skill-frontmatter.py @@ -39,8 +39,8 @@ CODEX_LISTING_MAX = 8000 # Codex の初期一覧予算(コンテキスト長不明時) CLAUDE_LISTING_MAX = 8000 # Claude Code の初期一覧予算(コンテキスト長不明時) CLAUDE_ITEM_TRUNCATE = 250 # Claude Code は 1 項目をこの長さで切り詰める -# 全 Skill の frontmatter 合計。棚卸(Task 0-7)完了時点の実測 12,145 文字(Skill 29 個、 -# 2026-08-08)を基準に、約 7% の余裕を足して 13,000 とした。余裕分は Skill 2〜3 個分の +# 全 Skill の frontmatter 合計。棚卸(Task 0-7)完了時点の実測 12,211 文字(Skill 29 個、 +# 2026-08-08)を基準に、約 6% の余裕を足して 13,000 とした。余裕分は Skill 2〜3 個分の # frontmatter に相当する。Skill を増やすときは実測しなおしてこの値を更新する。 FRONTMATTER_TOTAL_MAX = 13000