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

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions .claude/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"hooks": {
"PreToolUse": [
{
"matcher": "Bash",
"hooks": [
{
"type": "command",
"command": "bash \"$CLAUDE_PROJECT_DIR/scripts/hooks/irreversible-ops-guard.sh\"",
"timeout": 15,
"statusMessage": "Checking for irreversible operations..."
}
]
}
]
}
}
20 changes: 20 additions & 0 deletions .claude/skills/accessibility-checker/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,26 @@ Review each component/story, focusing on applicability and evidence collection.

Apply minimal, safe code changes per component, then re-check affected items.

> **🛑 Fix は既定の動作ではない(このスキルで最優先のルール)**
>
> このスキルの既定の成果物は **レポート生成("Generate Report" / `workflow.md` の "3. Review")まで**。
> コードの書き換え(`workflow.md` の "4. Fixes")は以下を満たしたときだけ行う。
>
> ※ ステップ番号は SKILL.md の Quick Workflow(1〜4)と `workflow.md`(1〜7)で振り方が異なる。
> 停止位置は番号ではなく**名前**で判断すること。
>
> - ユーザーが「直して」「修正して」と**明示的に依頼した**場合に限る。
> 「a11y チェックして」「レビューして」という依頼は**修正の承認ではない**
> - 修正に入る前に、**Fail / Needs review の一覧を提示し、どれを直すかユーザーに選んでもらう**。
Comment thread
coderabbitai[bot] marked this conversation as resolved.
> 「見つかったので全部直しておきました」をやらない
> - 一度に触るのは**選ばれた対象のスコープ内だけ**。レビュー中に視界に入った別コンポーネントや
> 別ファイルの問題は、直さずレポートの「フォローアップ候補」に積む
> - Fail の指摘が正しくても、修正が公開 API の変更(props の削除・リネーム・挙動変更)を伴う場合は
> 実装せず提案に留める(`Deprecate Risky APIs Progressively` の方針を参照)
>
> English: Reporting is the default deliverable. Only modify code when the user explicitly asks for
> fixes, and only within the scope they approved — never fix everything you found on your own initiative.

---

## Workflow
Expand Down
6 changes: 6 additions & 0 deletions .claude/skills/accessibility-checker/references/workflow.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,12 @@ For each checklist item, record how it was verified:

## 4. Fixes (Minimal Changes + Non-Breaking Improvements)

> 🛑 **This step only runs when the user explicitly asked for fixes and approved the scope.**
> See "3. Fix" under *Intended Usage* in `SKILL.md`. If they only asked for a review,
> stop after **"3. Review (Recording Evidence)"** above — report the proposed fixes
> instead of applying them. (Step numbers differ between `SKILL.md`'s Quick Workflow
> and this file, so always identify the stopping point by name, not by number.)

- Prioritize fixes that don't break compatibility
- For "accident-prone APIs," prefer **gradual deprecation** over removal (see `PROJECT_POLICY.md` for details)

Expand Down
59 changes: 51 additions & 8 deletions .claude/skills/release-sparkle-design/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,17 @@ user-invocable: true

## AI アシスタントへの指示

> **🛑 不可逆操作の扱い(このスキルで最優先のルール)**
>
> 🛑 が付いた項目(PR マージ / タグ push / GitHub Release 作成 / npm publish)は、
> **ユーザーが名指しで指示したときだけ**実行する。「リリースして」という最初の依頼は、
> マージ・publish までの事前承認ではない。**リストに並んでいることは実行してよい理由にならない。**
> 🛑 の手前まで進んだら停止し、状況(PR 番号 / CI 状態 / 次のコマンド)を報告して指示を待つ。
>
> これらは `scripts/hooks/irreversible-ops-guard.sh`(PreToolUse hook)が実際にブロックする。
> ブロックされたら、ユーザーの指示を得たうえで `SPARKLE_CONFIRM=1` を先頭に付けて再実行する。
> **hook が無い環境(Claude Code 以外のエージェント)でも、上のルールは同じように適用する。**
Comment on lines +39 to +41

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔒 Security & Privacy | 🟠 Major | 🏗️ Heavy lift

SPARKLE_CONFIRM=1の承認スコープをhook実装と一致させてください。

hookはコマンドセグメント内の指定だけでなく、継承されたプロセス環境のSPARKLE_CONFIRM=1も承認扱いにします。export SPARKLE_CONFIRM=1や複合コマンドで、意図していない不可逆操作まで通過する可能性があります。セグメント単位だけを許可することを文書化し、hookとテストも同じ契約にしてください。

🧰 Tools
🪛 SkillSpector (2.4.4)

[warning] 100: [RP1] null: npx commands without a version suffix (e.g. @1.0.0) create a rug-pull risk if the upstream server is compromised and publishes a malicious update.

Remediation: Pin the version: npx @scope/server@1.2.3

(MCP Rug Pull (RP1))


[error] 154: [PE3] Credential Access: Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Remediation: Remove references to credential paths. Use environment variables or secrets managers. For docs, use placeholder paths (e.g., /path/to/config). Never load .env or token files in production code paths.

(Privilege Escalation (PE3))


[error] 193: [PE3] Credential Access: Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Remediation: Remove references to credential paths. Use environment variables or secrets managers. For docs, use placeholder paths (e.g., /path/to/config). Never load .env or token files in production code paths.

(Privilege Escalation (PE3))

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.claude/skills/release-sparkle-design/SKILL.md around lines 39 - 41, Update
the SPARKLE_CONFIRM=1 guidance in the release skill so approval is limited to
the command segment that explicitly sets it, excluding inherited or exported
environment values and unrelated segments in compound commands. Align
scripts/hooks/irreversible-ops-guard.sh and its tests with this segment-scoped
contract, and document the same behavior for environments without the hook.


### 実行方針

1. **ユーザーにリリース種別を確認**
Expand All @@ -43,6 +54,9 @@ user-invocable: true

3. **以下のチェックリストを順に実行する**

- ただし 🛑 が付いた項目に到達したら、そこで停止してユーザーの明示的な指示を待つ
(上の「不可逆操作の扱い」を参照)。停止せずに走り切ってはならない

---

## リリース手順チェックリスト
Expand All @@ -61,11 +75,15 @@ user-invocable: true
タグ未作成・Release 未作成のバージョンがある場合は **新バージョンを切る前に** 必ず追補する。

- [ ] 該当バージョンのリリースコミット(`🔖 chore: release vX.Y.Z` 等)の SHA を特定: `git log --all --oneline | grep release`
- [ ] そのコミットに対して `git tag vX.Y.Z <SHA>` でタグを作成
- [ ] `git push origin vX.Y.Z` でタグを push
- [ ] `gh release create vX.Y.Z --title "vX.Y.Z" --notes "..."` で Release を作成
- [ ] そのコミットに対して `git tag vX.Y.Z <SHA>` でタグを作成(ローカルタグまでは自走してよい)
- [ ] 🛑 `git push origin vX.Y.Z` でタグを push
- [ ] 🛑 `gh release create vX.Y.Z --title "vX.Y.Z" --notes "..."` で Release を作成
- notes は CHANGELOG.md の該当セクションをコピペするのが確実

> 🛑 **ここで停止する。** 追補対象のバージョンと、打とうとしているタグ / SHA の対応表を提示し、
> ユーザーの承認を得てから push・Release 作成を実行する。タグの push は取り消しが面倒で、
> 誤ったコミットに打つと publish 対象がずれる。

### 新バージョンの準備(リリース PR 作成)

- [ ] `chore/release-X.Y.Z` ブランチを `origin/main` から切る(worktree 推奨)
Expand All @@ -88,31 +106,56 @@ user-invocable: true

### リリース PR レビュー・マージ

> 🛑 **AI はここで必ず停止する。PR 作成までがこのスキルの自走範囲。**
> PR の URL・変更差分の要約・CI の状態を報告して**ユーザーの応答を待つ**。
> **AI によるセルフレビュー(`/code-review` 等)は人間のレビューの代替にならない。**
> publish の前段であるマージは、後戻りが難しい操作の入口なので、必ず人が差分を見る。

- [ ] レビュー受領(CodeRabbit / Codex / 人間レビュアー)
- [ ] 全 CI green を確認(`gh pr checks <PR番号>`)
- [ ] **通常マージ(`--merge`)でマージ**。スカッシュは禁止(コミットが消えるとリリース履歴が辿れない)
- [ ] base branch protection があるため、必要なら admin マージ: `gh pr merge <PR番号> --merge --admin`
- [ ] 🛑 **通常マージ(`--merge`)でマージ**。スカッシュは禁止(コミットが消えるとリリース履歴が辿れない)
- [ ] 🛑 base branch protection があるため、必要なら admin マージ: `gh pr merge <PR番号> --merge --admin`
- `--admin` は保護ブランチのレビュー要件を迂回する。**ユーザーが admin マージを明示的に求めたときだけ**使う。
「protection で弾かれたから `--admin` を付け直す」を AI の判断でやらない

### マージ後: タグ・Release・publish

> 🛑 **マージが済んだからといって、AI の判断で続けて publish まで走らない。**
> 「タグを打って publish して」と明示的に指示されてから着手し、実行前に
> 置き換えた実際の値(`X.Y.Z` / `RELEASE_SHA`)を提示して確認を取る。

- [ ] `git fetch origin main && git checkout main && git pull` で最新化
- [ ] **リリースコミットの SHA を `git log --oneline | grep release | head -1` で必ず特定**
- [ ] **タグはリリースコミットの SHA を明示して打つ**(HEAD に打つと main が進んだ場合に誤タグ → publish 漏れ・誤 publish の温床):
```bash
RELEASE_SHA=$(git log --oneline | grep "release vX.Y.Z" | head -1 | awk '{print $1}')
# 候補が 1 件であることを確認してからタグを打つ(別バージョンを掴むと誤 publish になる)
CANDIDATES=$(git log --format='%H %s' | grep -F "release vX.Y.Z")
echo "$CANDIDATES"
[ "$(echo "$CANDIDATES" | wc -l)" -eq 1 ] || { echo "候補が 1 件ではない。手で SHA を特定すること" >&2; exit 1; }
RELEASE_SHA=$(echo "$CANDIDATES" | awk '{print $1}')
git show --no-patch --oneline "$RELEASE_SHA" # 対象コミットを目視確認する
git tag vX.Y.Z "$RELEASE_SHA"
```
Comment thread
coderabbitai[bot] marked this conversation as resolved.
- [ ] 🛑 タグを push する(打った SHA とコミットメッセージを提示して確認後):
```bash
git push origin vX.Y.Z
```
- [ ] **GitHub Release 作成**:
- [ ] 🛑 **GitHub Release 作成**:
CHANGELOG.md のセクションを `--notes` で直接渡すのが確実:
```bash
awk '/^## \[X\.Y\.Z\]/{flag=1;next} /^## \[/{flag=0} flag' CHANGELOG.md > /tmp/notes.md
# 見出しの誤記や CHANGELOG 未反映だと空になる。空の Release を作らない
[ -s /tmp/notes.md ] || { echo "CHANGELOG から vX.Y.Z のセクションを抽出できなかった" >&2; exit 1; }
cat /tmp/notes.md # 内容を目視確認してから作成する
gh release create vX.Y.Z --title "vX.Y.Z" --notes-file /tmp/notes.md
```
Comment thread
coderabbitai[bot] marked this conversation as resolved.
- [ ] **npm publish** — GitHub Actions ワークフローを実行。**tag ref で実行する**ことで、main が進んでも正しいリリースコミットの内容が publish される:
- [ ] 🛑 **npm publish** — GitHub Actions ワークフローを実行。**tag ref で実行する**ことで、main が進んでも正しいリリースコミットの内容が publish される:
```bash
gh workflow run "Publish to npm" --ref vX.Y.Z
```
- **publish は取り消せない。** npm の unpublish は公開 72 時間以内かつ依存されていない場合のみで、
実質的な回復手段は「新しいパッチバージョンを出す」しかない。実行前に必ずユーザーの明示的な
指示を得る(`--ref` に渡すタグ名も読み上げて確認する)
- workflow が `npm error code E404 'pkg@X.Y.Z' is not in this registry` で失敗する場合は **NPM_TOKEN の期限切れ**(auth 失敗が 404 として返る npm registry 仕様)
- workflow が `npm error code EOTP` で失敗する場合は、**トークン種別が 2FA バイパス対応していない**。次のいずれかで作り直し:
- Classic Token: タイプを **Automation** で発行
Expand Down
15 changes: 15 additions & 0 deletions .cursor/rules/context.mdc
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,21 @@ pnpm test # Component tests
- **Update the lockfile whenever `package.json` changes**: CI runs `pnpm install --frozen-lockfile` and will fail otherwise
- **Use the pinned toolchain**: Node.js 22.14.0 / pnpm 10.12.4 (see `.tool-versions`; newer pnpm majors can rewrite the lockfile)

### Irreversible Operations Are Blocked by a Hook
`scripts/hooks/irreversible-ops-guard.sh` (a PreToolUse hook wired in `.claude/settings.json`) blocks:

- `npm/pnpm/yarn/bun publish` (an enabled `--dry-run` passes), `unpublish`, `deprecate`
- `gh pr merge`, `gh release create/delete`, `gh repo create/delete/archive`, publish workflows
- Release tag pushes, `--tags`, force pushes (including a `+` refspec), and remote ref deletion (`--delete` / `:ref`)

It also looks inside command substitutions (`$(...)`) and `bash -c "..."`, so those are not a way around it.

- These run **only when the user names the operation**. A broad "release it" / "go ahead" is not approval.
- Once instructed, re-run with `SPARKLE_CONFIRM=1` **in front of that command**. Adding that prefix without an instruction defeats the guard.
- An inherited/exported `SPARKLE_CONFIRM=1` is deliberately ignored — approval is per command, not per session.
- Agents without hook support must follow the same rule — the hook is a backstop, not the rule itself.
- Tests: `pnpm test:hooks`

## AI Assistance Guidelines
- Refer to specific instruction files for detailed guidance:
- `docs/ai-instructions/testing.md` for testing
Expand Down
15 changes: 15 additions & 0 deletions .github/instructions/ai-context.instructions.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,21 @@ pnpm test # Component tests
- **Update the lockfile whenever `package.json` changes**: CI runs `pnpm install --frozen-lockfile` and will fail otherwise
- **Use the pinned toolchain**: Node.js 22.14.0 / pnpm 10.12.4 (see `.tool-versions`; newer pnpm majors can rewrite the lockfile)

### Irreversible Operations Are Blocked by a Hook
`scripts/hooks/irreversible-ops-guard.sh` (a PreToolUse hook wired in `.claude/settings.json`) blocks:

- `npm/pnpm/yarn/bun publish` (an enabled `--dry-run` passes), `unpublish`, `deprecate`
- `gh pr merge`, `gh release create/delete`, `gh repo create/delete/archive`, publish workflows
- Release tag pushes, `--tags`, force pushes (including a `+` refspec), and remote ref deletion (`--delete` / `:ref`)

It also looks inside command substitutions (`$(...)`) and `bash -c "..."`, so those are not a way around it.

- These run **only when the user names the operation**. A broad "release it" / "go ahead" is not approval.
- Once instructed, re-run with `SPARKLE_CONFIRM=1` **in front of that command**. Adding that prefix without an instruction defeats the guard.
- An inherited/exported `SPARKLE_CONFIRM=1` is deliberately ignored — approval is per command, not per session.
- Agents without hook support must follow the same rule — the hook is a backstop, not the rule itself.
- Tests: `pnpm test:hooks`

## AI Assistance Guidelines
- Refer to specific instruction files for detailed guidance:
- `docs/ai-instructions/testing.md` for testing
Expand Down
15 changes: 15 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,21 @@ pnpm test # Component tests
- **Update the lockfile whenever `package.json` changes**: CI runs `pnpm install --frozen-lockfile` and will fail otherwise
- **Use the pinned toolchain**: Node.js 22.14.0 / pnpm 10.12.4 (see `.tool-versions`; newer pnpm majors can rewrite the lockfile)

### Irreversible Operations Are Blocked by a Hook
`scripts/hooks/irreversible-ops-guard.sh` (a PreToolUse hook wired in `.claude/settings.json`) blocks:

- `npm/pnpm/yarn/bun publish` (an enabled `--dry-run` passes), `unpublish`, `deprecate`
- `gh pr merge`, `gh release create/delete`, `gh repo create/delete/archive`, publish workflows
- Release tag pushes, `--tags`, force pushes (including a `+` refspec), and remote ref deletion (`--delete` / `:ref`)

It also looks inside command substitutions (`$(...)`) and `bash -c "..."`, so those are not a way around it.

- These run **only when the user names the operation**. A broad "release it" / "go ahead" is not approval.
- Once instructed, re-run with `SPARKLE_CONFIRM=1` **in front of that command**. Adding that prefix without an instruction defeats the guard.
- An inherited/exported `SPARKLE_CONFIRM=1` is deliberately ignored — approval is per command, not per session.
- Agents without hook support must follow the same rule — the hook is a backstop, not the rule itself.
- Tests: `pnpm test:hooks`

## AI Assistance Guidelines
- Refer to specific instruction files for detailed guidance:
- `docs/ai-instructions/testing.md` for testing
Expand Down
15 changes: 15 additions & 0 deletions docs/ai-instructions/context.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,21 @@ pnpm test # Component tests
- **Update the lockfile whenever `package.json` changes**: CI runs `pnpm install --frozen-lockfile` and will fail otherwise
- **Use the pinned toolchain**: Node.js 22.14.0 / pnpm 10.12.4 (see `.tool-versions`; newer pnpm majors can rewrite the lockfile)

### Irreversible Operations Are Blocked by a Hook
`scripts/hooks/irreversible-ops-guard.sh` (a PreToolUse hook wired in `.claude/settings.json`) blocks:

- `npm/pnpm/yarn/bun publish` (an enabled `--dry-run` passes), `unpublish`, `deprecate`
- `gh pr merge`, `gh release create/delete`, `gh repo create/delete/archive`, publish workflows
- Release tag pushes, `--tags`, force pushes (including a `+` refspec), and remote ref deletion (`--delete` / `:ref`)

It also looks inside command substitutions (`$(...)`) and `bash -c "..."`, so those are not a way around it.

- These run **only when the user names the operation**. A broad "release it" / "go ahead" is not approval.
- Once instructed, re-run with `SPARKLE_CONFIRM=1` **in front of that command**. Adding that prefix without an instruction defeats the guard.
- An inherited/exported `SPARKLE_CONFIRM=1` is deliberately ignored — approval is per command, not per session.
- Agents without hook support must follow the same rule — the hook is a backstop, not the rule itself.
- Tests: `pnpm test:hooks`

Comment thread
coderabbitai[bot] marked this conversation as resolved.
## AI Assistance Guidelines
- Refer to specific instruction files for detailed guidance:
- `docs/ai-instructions/testing.md` for testing
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
"start": "next start",
"lint": "next lint",
"test": "vitest run --project unit",
"test:hooks": "bash scripts/hooks/irreversible-ops-guard.test.sh",
"test:watch": "vitest --project unit",
"test:ai-analyze": "npm test > test-output.log 2>&1 && echo 'Test results saved to test-output.log for AI analysis'",
"test:failures": "npm test > test-output.log 2>&1 && grep -A 5 -B 5 'FAIL\\|✗\\|Error' test-output.log > test-failures.log && echo 'Test failures extracted to test-failures.log'",
Expand Down
Loading
Loading