20 コマンド
ワークスペース共通 18
プロジェクト固有 2
置き場所: .claude/commands/
セッション運用
4
新規セッション開始時の軽量セットアップ(毎セッション用)。ドキュメント読み込み・日次スタンプ確認・プロジェクト選択のみを実行します。
プロジェクト選択後は resume-project ワークフロー(`.agents/workflows/resume-project.md`)に委譲します。
> **フル版との関係**: 当日初回・「おはよう」では `/spj-full`(監査・リポジトリ最新化・deploy drift・ダッシュボード・日報マージ)を使う。
> `/spj` はそれ以降の毎セッション用の**軽量起動**。当日まだフル版を実行していない場合は STEP 2 で `/spj-full` を案内する(自動実行はしない)。
## 手順
> **NETYP_ROOT** は各 bash ブロック冒頭で自動解決します(workspace-config.json → `~/NetyProd` フォールバック)。
> 以下のパスで `${NETYP_ROOT}` が登場する場合は解決後の値で読み替えてください。
### STEP 1: グローバルルール読み込み
以下のファイルを読む:
- `${NETYP_ROOT}/00.aimd/HANDOFF.md`
- `${NETYP_ROOT}/agent_rules.md`
> `00_SESSION_CHECKLIST.md` は **非 Claude Code エージェント (Antigravity / Codex) 向けの手順書**で、Claude Code は `/spj` 自身が同等処理を実行するため Read 不要。
> `CLAUDE.md` は cwd で自動ロードされるため明示的に読む必要はない。
### STEP 2: 日次スタンプ確認
当日にフル版(`/spj-full`)が実行済みかを 1 回だけ確認する。**監査本体は実行しない**(判定のみ)。
```bash
NETYP_ROOT=$(node -e "const os=require('os');try{const c=require(os.homedir()+'/NetyProd/.agents/config/workspace-config.json');console.log(c.workspace.root)}catch(e){console.log(os.homedir()+'/NetyProd')}")
node "${NETYP_ROOT}/.agents/scripts/audit-workspace.js" --daily-check
```
- **Exit 1(NEEDED)**: 今日まだフル版が未実行 → 次の 1 行をユーザーに案内する(**自動実行はしない**):
> 今日はまだフル版未実行です。『おはよう』または /spj-full を推奨
- **Exit 0(DONE)**: 今日すでにフル版実行済み → サイレントで続行
### STEP 3: 作業プロジェクトをユーザーに確認
NetyProd 直下の Git リポジトリを「稼働」と「休眠」の2段に分けて提示する。
**休眠判定の第一基準は HANDOFF.md の休眠宣言**(`ステータス: 休眠`)。commit 日基準だけだと、休眠宣言そのものや棚卸しコミットで時計がリセットされ判定が壊れるため(2026-07-03 の実例)。宣言がない repo は 90 日 commit なしで休眠扱い(フォールバック)。
**git fetch はしない**(ローカル読みのみ・軽量)。
```bash
NETYP_ROOT=$(node -e "const os=require('os');try{const c=require(os.homedir()+'/NetyProd/.agents/config/workspace-config.json');console.log(c.workspace.root)}catch(e){console.log(os.homedir()+'/NetyProd')}")
dormant_list=()
for dir in "$NETYP_ROOT"/*/; do
if [ -d "${dir}.git" ]; then
repo="${dir%/}"
name=$(basename "$repo")
# 第一基準: HANDOFF の休眠宣言
if grep -q "ステータス: 休眠" "$repo/HANDOFF.md" 2>/dev/null; then
dormant_list+=("$name")
continue
fi
last2w=$(git -C "$repo" log --since="2 weeks ago" --oneline 2>/dev/null | head -1)
last90d=$(git -C "$repo" log --since="90 days ago" --oneline 2>/dev/null | head -1)
if [ -n "$last2w" ]; then
echo "$name | ${last2w}"
elif [ -z "$last90d" ]; then
dormant_list+=("$name")
fi
fi
done
if [ "${#dormant_list[@]}" -gt 0 ]; then
echo "休眠: $(IFS=,; echo "${dormant_list[*]}") (${#dormant_list[@]}個 — 再開時は名前を指定)"
fi
```
「以下のリポジトリで最近変更がありました。どのプロジェクトの作業をしますか?」と稼働一覧を提示し、休眠行があればその下に1行だけ添える(個別展開しない)。
### STEP 4: resume-project に委譲
ユーザーがプロジェクトを選択したら、`.agents/workflows/resume-project.md` のフロー(STEP 1以降)を実行する。
## 引数
引数なし
当日初回のフルセットアップ。「おはよう」でも起動。監査・リポジトリ最新化・deploy drift・ダッシュボード・日報マージをすべて実行します。
プロジェクト選択後は resume-project ワークフロー(`.agents/workflows/resume-project.md`)に委譲します。
> **簡易版との関係**: 毎セッションの軽量起動は `/spj`(簡易版)を使う。`/spj-full` は当日初回・「おはよう」で全 STEP を実行する重量版。
## 手順
> **NETYP_ROOT** は各 bash ブロック冒頭で自動解決します(workspace-config.json → `~/NetyProd` フォールバック)。
> 以下のパスで `${NETYP_ROOT}` が登場する場合は解決後の値で読み替えてください。
### STEP 0: bypass 使用状況を記録 (Issue [#67](https://github.com/netyu2iv-ops/00aimd/issues/67))
`SPJ_SKIP_*` env vars の使用状況を JSONL に append し、連用検出に備える。
```bash
NETYP_ROOT=$(node -e "const os=require('os');try{const c=require(os.homedir()+'/NetyProd/.agents/config/workspace-config.json');console.log(c.workspace.root)}catch(e){console.log(os.homedir()+'/NetyProd')}")
node "${NETYP_ROOT}/.agents/scripts/bypass-tracker.js" record
node "${NETYP_ROOT}/.agents/scripts/bypass-tracker.js" check
```
- `record`: 現在の `SPJ_SKIP_*` env vars をログに記録 (bypass 使用時のみ stdout に表示)
- `check`: 直近 3 回連続で同じ bypass が使われていれば警告メッセージを表示。**警告が出た場合は `/spj-full` 報告に含める**こと
- 警告がなければサイレントで続行
### STEP 0.6: 運用ログの日次ローテーション (軍師検収 2026-07-03 勧告6 / Issue #101)
`.agents/config/*.jsonl` はローテーションなしで無限成長するため、日次で上限超過分を
`<name>.archive.jsonl` に退避する。
```bash
NETYP_ROOT=$(node -e "const os=require('os');try{const c=require(os.homedir()+'/NetyProd/.agents/config/workspace-config.json');console.log(c.workspace.root)}catch(e){console.log(os.homedir()+'/NetyProd')}")
node "${NETYP_ROOT}/.agents/scripts/rotate-jsonl.js" --file="${NETYP_ROOT}/.agents/config/bash-executed.jsonl" --max-lines=10000
node "${NETYP_ROOT}/.agents/scripts/rotate-jsonl.js" --file="${NETYP_ROOT}/.agents/config/audit-log.jsonl" --max-lines=2000
node "${NETYP_ROOT}/.agents/scripts/rotate-jsonl.js" --file="${NETYP_ROOT}/.agents/config/spj-bypass-log.jsonl" --max-lines=2000
node "${NETYP_ROOT}/.agents/scripts/rotate-jsonl.js" --file="${NETYP_ROOT}/.agents/config/gate-log.jsonl" --max-lines=5000
```
- ファイルが上限以下、または未生成なら no-op(エラーではない)
- ローテーションが発生したら「〇〇件を archive へ退避」の 1 行を報告に含める(大量退避時のみ触れれば十分)
`.claude/agents/ROSTER.md`(guild-master 用ロスターキャッシュ / 軍師検収 2026-07-03 勧告5)も同タイミングで日次再生成する(エージェント定義の変更頻度は月数回のため 1 日 1 回で十分):
```bash
NETYP_ROOT=$(node -e "const os=require('os');try{const c=require(os.homedir()+'/NetyProd/.agents/config/workspace-config.json');console.log(c.workspace.root)}catch(e){console.log(os.homedir()+'/NetyProd')}")
node "${NETYP_ROOT}/.agents/scripts/gen-agent-roster.js"
```
### 緊急時 bypass (Issue [#64](https://github.com/netyu2iv-ops/00aimd/issues/64))
特定 STEP が hang する / 急ぎで作業を始めたい場合は、以下の環境変数で skip 可能。実行前に主エージェントが**必ずチェック**すること:
| 環境変数 | スキップ対象 | 用途 |
|---|---|---|
| `SPJ_SKIP_LAYER3=1` | STEP 2.5c (Layer 3 LLM 監査) | LLM agent の応答が遅い / token を節約したい |
| `SPJ_SKIP_AUDIT=1` | STEP 2.5 全体 (daily-check / Layer 1+2 / Layer 3 / バグログ) | 監査基盤が壊れている際の回避路 |
| `SPJ_SKIP_NOTION=1` | resume-project STEP 0.5 (worklog マージ) | Notion API 障害時 |
| `SPJ_SKIP_FETCH=1` | STEP 3 git fetch (リモート差分確認) | オフライン作業 / 急ぎ |
| `SPJ_SKIP_DASHBOARD=1` | STEP 3.6 (使用量ダッシュボード再生成) | ダッシュボード更新が不要なとき |
| `SPJ_MINIMAL=1` | 上記すべてを skip + STEP 1 と STEP 4 のみ実行 | 完全最小起動 |
各 STEP の冒頭で対応する env var をチェックし、true の場合は「⏭ SKIPPED (bypass)」と 1 行報告して次の STEP へ。
> **注意**: bypass はあくまで緊急回避。常用すると整合性検証が機能しなくなる。連用時は warning を表示すること (例: 同じ bypass を 3 回連続で使ったら次回 `/spj-full` で「最近 N 回 SKIPPED されました」とリマインド)。
```bash
# 主エージェントが各 STEP 冒頭で実行する判定例
if [ "$SPJ_MINIMAL" = "1" ] || [ "$SPJ_SKIP_AUDIT" = "1" ]; then
echo "⏭ STEP 2.5 SKIPPED (bypass: SPJ_SKIP_AUDIT or SPJ_MINIMAL)"
# STEP 2.5 全体を skip
fi
```
### STEP 1: グローバルルール読み込み
以下のファイルを読む:
- `${NETYP_ROOT}/00.aimd/HANDOFF.md`
- `${NETYP_ROOT}/agent_rules.md`
> `00_SESSION_CHECKLIST.md` は **非 Claude Code エージェント (Antigravity / Codex) 向けの手順書**で、Claude Code は `/spj-full` 自身が同等処理を実行するため Read 不要 (Issue [#61](https://github.com/netyu2iv-ops/00aimd/issues/61))。
> `CLAUDE.md` は cwd で自動ロードされるため明示的に読む必要はない。
### STEP 2: 環境確認(Docker / MCP)
#### 2a: Docker Desktop 確認
```bash
docker ps 2>&1 | head -3
```
- 起動していない場合: 「Docker Desktop を起動後、**Claude Code を再起動**してから /spj-full を実行してください」とユーザーに伝える
- ⚠️ Docker を起動しただけでは MCP は使えない。**MCP は Claude Code 起動時にのみ接続される**
#### 2b: MCP 接続確認
ToolSearch を使って以下を確認する:
- `list_issues` または `github` を検索 → `github-mcp-server` がロードされているか
- `notion` を検索 → `notion-mcp-server` がロードされているか
結果をユーザーに報告する:
| MCP サーバー | 状態 |
|---|---|
| `github-mcp-server` | ✓ 利用可能 / ⚠️ 未ロード |
| `notion-mcp-server` | ✓ 利用可能 / ⚠️ 未ロード |
**⚠️ MCP が未ロードの場合:**
- ユーザーに「Claude Code を再起動してから /spj-full を実行してください」と案内する
- 作業を続ける場合はフォールバックを使用:
- GitHub: `curl` + PAT(`~/.claude/settings.json` の `GITHUB_PERSONAL_ACCESS_TOKEN`)
- Notion: `notion-worklog.js` スクリプト直接実行、またはNotion操作を次回セッションに持ち越す
### STEP 2.5: ワークスペース監査
#### 2.5a: 今日フル監査が実行済みかを確認
```bash
NETYP_ROOT=$(node -e "const os=require('os');try{const c=require(os.homedir()+'/NetyProd/.agents/config/workspace-config.json');console.log(c.workspace.root)}catch(e){console.log(os.homedir()+'/NetyProd')}")
node "${NETYP_ROOT}/.agents/scripts/audit-workspace.js" --daily-check
```
- **Exit 0(DONE)**: 今日すでにフル監査済み → 「本日フル実行済み」と警告し、監査は Layer 1 のみに縮退してスキップ(フル版を当日 2 回目に呼んだケース)
```bash
NETYP_ROOT=$(node -e "const os=require('os');try{const c=require(os.homedir()+'/NetyProd/.agents/config/workspace-config.json');console.log(c.workspace.root)}catch(e){console.log(os.homedir()+'/NetyProd')}")
node "${NETYP_ROOT}/.agents/scripts/audit-workspace.js" --trigger=spj_subsequent --layer=1
```
- **Exit 1(NEEDED)**: 今日まだフル監査未実施 → 以下の 2.5b〜2.5c を実行する
#### 2.5b: Layer 1+2 自動チェック(NEEDED の場合のみ)
```bash
NETYP_ROOT=$(node -e "const os=require('os');try{const c=require(os.homedir()+'/NetyProd/.agents/config/workspace-config.json');console.log(c.workspace.root)}catch(e){console.log(os.homedir()+'/NetyProd')}")
node "${NETYP_ROOT}/.agents/scripts/audit-workspace.js" --trigger=spj_daily_first --layer=2
```
結果に応じて:
- `✗ ERROR` がある場合: ユーザーに内容を報告し、修正してから続行するか確認する
- `⚠ WARN` がある場合: ユーザーに一覧を報告する(続行は妨げない)
- `✓ PASS` のみ: サイレントで続行
#### 2.5c: Layer 3 意味チェック(NEEDED かつ Layer 1+2 がエラーなしの場合)
以下のファイルペアを読み、**意味的な矛盾・重複・陳腐化**がないかをチェックする:
| チェックペア | 観点 |
|---|---|
| `CONFIRMATION_RULES.md` ↔ `permission-checker.js` BLOCKED/ALLOWED | ルールの意味が一致しているか。片方にあって片方にない定義がないか |
| `agent_rules.md` ↔ `CLAUDE.md` | 役割境界 (Scope 宣言) が保たれているか・越境記述がないか |
| `spj.md` ↔ `spj-full.md` ↔ `resume-project.md` ↔ `save-project.md` | 手順の重複・相互矛盾がないか |
| `start-project.md` ↔ `project-template/` | テンプレートが最新ルールを反映しているか |
問題を発見した場合(**Issue [#63](https://github.com/netyu2iv-ops/00aimd/issues/63) で WARN-only に変更 / 2026-05-10**):
- **`/spj-full` 経由の Layer 3 は WARN-only**: AUTO-FIX も silent commit も**禁止**
- 検出した問題は `⚠ WARN` として一覧化してユーザーに提示する
- **AUTO-FIX が必要な場合**: ユーザーが明示的に `/audit-workspace --apply-l3` を実行(または個別ファイルを手動修正)
- 問題なければサイレントで続行
#### 2.6: バグログ昇格チェック(A + B トリガ)
毎回実行する軽量チェック。`00.aimd/engineering-lessons.md` の review-metadata と各プロジェクトの `docs/bug-log.md` 件数を比較し、レビュー候補を通知する。
```bash
NETYP_ROOT=$(node -e "const os=require('os');try{const c=require(os.homedir()+'/NetyProd/.agents/config/workspace-config.json');console.log(c.workspace.root)}catch(e){console.log(os.homedir()+'/NetyProd')}")
# メタデータ取得
META_FILE="${NETYP_ROOT}/00.aimd/engineering-lessons.md"
LAST_REVIEW=$(grep 'last-review:' "$META_FILE" 2>/dev/null | sed 's/.*last-review:[[:space:]]*//' | tr -d '[:space:]' | head -1)
LAST_COUNT=$(grep 'last-bug-log-entry-count:' "$META_FILE" 2>/dev/null | sed 's/.*last-bug-log-entry-count:[[:space:]]*//' | tr -d '[:space:]' | head -1)
TH_ENTRIES=$(grep 'threshold-new-entries:' "$META_FILE" 2>/dev/null | sed 's/.*threshold-new-entries:[[:space:]]*//' | tr -d '[:space:]' | head -1)
TH_DAYS=$(grep 'threshold-days:' "$META_FILE" 2>/dev/null | sed 's/.*threshold-days:[[:space:]]*//' | tr -d '[:space:]' | head -1)
TH_ENTRIES=${TH_ENTRIES:-3}
TH_DAYS=${TH_DAYS:-7}
# 現在の bug-log エントリ合計(全プロジェクト横断、"## [YYYY-" 形式のエントリ見出しをカウント)
CURRENT_COUNT=$(grep -hE '^## \[[0-9]{4}-' "$NETYP_ROOT"/*/docs/bug-log.md 2>/dev/null | wc -l | tr -d ' ')
# 新規エントリ数・経過日数
NEW_ENTRIES=$((CURRENT_COUNT - ${LAST_COUNT:-0}))
if [ -n "$LAST_REVIEW" ]; then
DAYS_SINCE=$(( ( $(date +%s) - $(date -d "$LAST_REVIEW" +%s 2>/dev/null || echo 0) ) / 86400 ))
else
DAYS_SINCE=999
fi
# 報告
echo "[lessons-review] current=$CURRENT_COUNT last=$LAST_COUNT new=$NEW_ENTRIES days=$DAYS_SINCE"
if [ "$NEW_ENTRIES" -ge "$TH_ENTRIES" ]; then
echo "⚠ 知見レビュー候補: 前回レビュー以降 ${NEW_ENTRIES} 件の新規バグログ(閾値 ${TH_ENTRIES})"
fi
if [ "$DAYS_SINCE" -ge "$TH_DAYS" ]; then
echo "📋 週次レビュー推奨: 前回レビューから ${DAYS_SINCE} 日経過(閾値 ${TH_DAYS})"
fi
```
**判定**:
- `NEW_ENTRIES >= threshold-new-entries` (既定 3) → **A トリガ**: 「知見レビュー候補」として報告
- `DAYS_SINCE >= threshold-days` (既定 7) → **B トリガ**: 「週次レビュー推奨」として報告
- どちらも未達 → サイレントで続行
**ユーザーへの提示**:
- A または B が発火した場合、上記メッセージを `/spj-full` の報告に含め、「`/promote-lessons` で実行できます」と案内する
- 自動実行はしない(作業中のユーザーを遮らない)
#### 2.7: メモリ統合の 30 日リマインド(Issue [#101](https://github.com/netyu2iv-ops/00aimd/issues/101))
auto memory の重複統合・stale 削除を促す軽量チェック。スタンプファイルの最終実行日から 30 日超過なら通知する(A/B トリガと同じ通知のみ方式・自動実行はしない)。
```bash
NETYP_ROOT=$(node -e "const os=require('os');try{const c=require(os.homedir()+'/NetyProd/.agents/config/workspace-config.json');console.log(c.workspace.root)}catch(e){console.log(os.homedir()+'/NetyProd')}")
STAMP_FILE="${NETYP_ROOT}/.agents/config/last-memory-consolidate.txt"
TH_MEM_DAYS=30
LAST_MEM=$(head -1 "$STAMP_FILE" 2>/dev/null | tr -d '[:space:]')
if [ -n "$LAST_MEM" ]; then
MEM_DAYS=$(( ( $(date +%s) - $(date -d "$LAST_MEM" +%s 2>/dev/null || echo 0) ) / 86400 ))
else
MEM_DAYS=999
fi
echo "[memory-consolidate] last=${LAST_MEM:-(未実施)} days=$MEM_DAYS"
if [ "$MEM_DAYS" -ge "$TH_MEM_DAYS" ]; then
if [ -n "$LAST_MEM" ]; then
echo "🧹 メモリ統合を推奨: 前回から ${MEM_DAYS} 日経過(閾値 ${TH_MEM_DAYS})。\`/consolidate-memory\` で実行できます。実行後は ${STAMP_FILE} を当日日付で更新してください"
else
echo "🧹 メモリ統合を推奨: 未実施(スタンプなし)。\`/consolidate-memory\` で実行できます。実行後は ${STAMP_FILE} を当日日付で更新してください"
fi
fi
```
**判定**:
- `MEM_DAYS >= 30`(または未実施)→ 「メモリ統合を推奨」を `/spj-full` 報告に含め、「`/consolidate-memory` で実行できます」と案内する
- 30 日以内 → サイレントで続行
**ユーザーへの提示**:
- 通知のみ(自動実行はしない)。実行するかはユーザー判断。実行後はスタンプファイルを当日日付で更新すること
### STEP 3: ワークスペース内の Git リポジトリを確認・最新化
NetyProd 直下にある全 Git リポジトリを動的に発見し、活動状況とリモートとの差分を確認する。
> **bypass**: `SPJ_SKIP_FETCH=1` または `SPJ_MINIMAL=1` が設定されていれば、本 STEP は skip して `⏭ STEP 3 SKIPPED (bypass)` と報告する。
>
> **並列化** (Issue [#65](https://github.com/netyu2iv-ops/00aimd/issues/65) — 2026-05-10): `git fetch` は **背景並列実行**、ローカル状態取得 (log / behind / ahead) は順次実行。12 repo の wall-clock を ~10s → ~2s に短縮。
```bash
NETYP_ROOT=$(node -e "const os=require('os');try{const c=require(os.homedir()+'/NetyProd/.agents/config/workspace-config.json');console.log(c.workspace.root)}catch(e){console.log(os.homedir()+'/NetyProd')}")
# Phase 1: 並列 fetch (各 repo を background で起動 → wait で全完了を待つ)
fetch_pids=()
for dir in "$NETYP_ROOT"/*/; do
if [ -d "${dir}.git" ]; then
git -C "${dir%/}" fetch --quiet 2>/tmp/spj-fetch-$(basename "${dir%/}").log &
fetch_pids+=($!)
fi
done
# 全 fetch の完了を待つ (個別エラーは /tmp/spj-fetch-*.log に記録済み)
wait "${fetch_pids[@]}" 2>/dev/null
# Phase 2: ローカル状態を順次取得 (fetch 済みなので高速)
for dir in "$NETYP_ROOT"/*/; do
if [ -d "${dir}.git" ]; then
repo="${dir%/}"
name=$(basename "$repo")
count=$(git -C "$repo" log --since="2 weeks ago" --oneline 2>/dev/null | wc -l)
last=$(git -C "$repo" log --since="2 weeks ago" --oneline 2>/dev/null | head -1)
branch=$(git -C "$repo" branch --show-current 2>/dev/null)
behind=$(git -C "$repo" rev-list HEAD..origin/$branch --count 2>/dev/null || echo "0")
ahead=$(git -C "$repo" rev-list origin/$branch..HEAD --count 2>/dev/null || echo "0")
echo "$name | commits(2w)=${count} | behind=${behind} | ahead=${ahead} | ${last}"
fi
done
```
> **fetch エラーの取得方法**: 個別 repo の fetch がエラーを返した場合、`/tmp/spj-fetch-<repo名>.log` を参照。例えば `cat /tmp/spj-fetch-PJ_RSO.log`。
#### リモートより古いリポジトリの自動更新
上記で `behind > 0` のリポジトリについて、以下の処理を行う:
```bash
# behind > 0 の各リポジトリに対して実行
repo="<対象リポジトリのパス>"
uncommitted=$(git -C "$repo" status --porcelain 2>/dev/null | wc -l)
if [ "$uncommitted" -eq 0 ]; then
# ローカル変更なし → 安全に pull
git -C "$repo" pull
else
# ローカル変更あり → pull を試みて競合確認
git -C "$repo" stash
result=$(git -C "$repo" pull 2>&1)
if echo "$result" | grep -q "CONFLICT\|conflict"; then
# 競合発生 → abort して元に戻し、ユーザーに報告
git -C "$repo" merge --abort 2>/dev/null || git -C "$repo" rebase --abort 2>/dev/null
git -C "$repo" stash pop
echo "⚠️ CONFLICT: $repo - 競合が発生したため保留しました"
else
git -C "$repo" stash pop
echo "✓ Updated: $repo"
fi
fi
```
**ユーザーへの報告**:
- 自動更新できたリポジトリ: `✓ Updated: <repo名>`
- 競合のため保留したリポジトリ: `⚠️ 競合保留: <repo名>(ファイル一覧と対処案を提示)`
- すでに最新のリポジトリ: スキップ(報告不要)
### STEP 3.5: Deploy drift 検出 (R237 deploy 漏れ対策)
各 deployable プロジェクトで、ローカル commit と本番 deploy 状態の差分を検出する。
```bash
NETYP_ROOT=$(node -e "const os=require('os');try{const c=require(os.homedir()+'/NetyProd/.agents/config/workspace-config.json');console.log(c.workspace.root)}catch(e){console.log(os.homedir()+'/NetyProd')}")
# PJ_RSO: PC_BUILD_ID 比較
PROJ="${NETYP_ROOT}/PJ_RSO"
if [ -f "${PROJ}/index.html" ] && [ -f "${PROJ}/firebase.json" ]; then
LOCAL_BID=$(grep "const PC_BUILD_ID" "${PROJ}/index.html" | grep -oE 'pc-r[0-9]+' | head -1)
PROD_BID=$(curl -s --max-time 8 "https://pj-rso.web.app/index.html" 2>/dev/null | grep "const PC_BUILD_ID" | grep -oE 'pc-r[0-9]+' | head -1)
if [ -n "$LOCAL_BID" ] && [ -n "$PROD_BID" ] && [ "$LOCAL_BID" != "$PROD_BID" ]; then
echo "🚨 PJ_RSO deploy drift: local=${LOCAL_BID} / prod=${PROD_BID}"
echo " → cd ${PROJ} && firebase deploy --only hosting"
elif [ -n "$LOCAL_BID" ] && [ "$LOCAL_BID" = "$PROD_BID" ]; then
echo "✓ PJ_RSO deploy in-sync (${LOCAL_BID})"
fi
fi
```
**ユーザーへの提示**:
- drift 検出時: 「⚠ Deploy drift」を `/spj-full` 報告に含め、deploy コマンドを案内する
- in-sync 時: サイレント or 1 行 ✓ 報告
- 自動 deploy はしない (作業中のユーザーを遮らない / deploy は明示的アクション)
### STEP 3.6: 使用量ダッシュボード再生成 (Claude/Codex トークン集計)
その日最初の `/spj-full` でのみ、ローカルログから使用量ダッシュボードを再生成する。生成はローカル処理のため自動実行し、続けて**オンラインに反映 (deploy) するかをユーザーに確認(ヒアリング)し、承認時のみ実行する**(自動 deploy はしない / 反映先は Cloudflare Access 保護の `agent-usage-dashboard.pages.dev`)。
> **bypass**: `SPJ_SKIP_DASHBOARD=1` または `SPJ_MINIMAL=1` が設定されていれば skip し `⏭ STEP 3.6 SKIPPED (bypass)` と報告する。
> ツール詳細・更新手順は `00.aimd/tools/agent-usage-dashboard/DEPLOY.md` 参照。`wrangler` の OAuth 認証が有効なら deploy は主エージェントの環境から実行できる。認証エラー(非対話で credentials 無し)の場合のみ、対話ターミナルでの実行をユーザーに案内する。
```bash
NETYP_ROOT=$(node -e "const os=require('os');try{const c=require(os.homedir()+'/NetyProd/.agents/config/workspace-config.json');console.log(c.workspace.root)}catch(e){console.log(os.homedir()+'/NetyProd')}")
DASH_DIR="${NETYP_ROOT}/00.aimd/tools/agent-usage-dashboard"
GEN_SCRIPT="${NETYP_ROOT}/00.aimd/tools/scripts/agent-usage-dashboard.js"
STAMP="${DASH_DIR}/publish/.last-spj-gen"
TODAY=$(TZ=Asia/Tokyo date +%Y-%m-%d)
if [ "$SPJ_SKIP_DASHBOARD" = "1" ] || [ "$SPJ_MINIMAL" = "1" ]; then
echo "⏭ STEP 3.6 SKIPPED (bypass)"
elif [ ! -f "$GEN_SCRIPT" ]; then
echo "⏭ STEP 3.6 SKIPPED (generator 未検出)"
elif [ "$(cat "$STAMP" 2>/dev/null | tr -d '[:space:]')" = "$TODAY" ]; then
echo "✓ dashboard 本日再生成済み ($TODAY)"
elif mkdir -p "${DASH_DIR}/publish" && node "$GEN_SCRIPT" --out="${DASH_DIR}/publish/index.html" && cp "${DASH_DIR}/publish/index.html" "${DASH_DIR}/index.html"; then
echo "$TODAY" > "$STAMP"
echo "✓ dashboard 再生成 (publish/index.html 更新)"
echo " → 次にユーザーへ deploy 可否を確認: npx wrangler pages deploy \"${DASH_DIR}/publish\" --project-name agent-usage-dashboard --commit-dirty=true"
else
echo "⚠ dashboard 再生成に失敗 (出力を確認)"
fi
```
**ユーザーへの提示(deploy ヒアリング)**:
- 再生成成功時: 「使用量ダッシュボードを再生成しました。オンラインに反映 (deploy) しますか?」とユーザーに確認する。
- **はい** → 主エージェントが deploy を実行: `npx wrangler pages deploy "${DASH_DIR}/publish" --project-name agent-usage-dashboard --commit-dirty=true`。成功したら本番 URL を 1 行報告。認証エラー時は「対話ターミナルで上記コマンドを実行してください」と案内。
- **いいえ** → deploy せず、コマンドだけ案内して次へ。
- 本日再生成済み(既に当日分を反映済みなら deploy ヒアリングは不要)/ skip / generator 未検出時: 1 行 ✓ or ⏭ 報告のみ。
### STEP 4: 作業プロジェクトをユーザーに確認
「以下のリポジトリで最近変更がありました。どのプロジェクトの作業をしますか?」と一覧を提示してユーザーに選択を促す。
### STEP 5: resume-project に委譲
ユーザーがプロジェクトを選択したら、`.agents/workflows/resume-project.md` のフロー(STEP 1以降)を実行する。
## 引数
引数なし
現在の作業プロジェクトをセーブします(`.agents/workflows/save-project.md` に定義されたワークフローを実行)。
## 手順
`.agents/workflows/save-project.md` に定義された以下のステップを順に実行してください:
1. **HANDOFF.md の最新化**
- 完了済み機能・WIP・既知バグ・Next Steps を更新
- 最終更新日を今日($CURRENT_DATE)に更新
2. **Notion へワークログを追記**
- 該当プロジェクトの Notion ページに今日の作業サマリーを追記
- `notion-mcp-server` の `append_block_children` を使用
- MCP が利用できない場合は HANDOFF.md に「Notion 同期未完了」と記録
3. **関連 GitHub Issue の更新**
- 完了した Issue はクローズ(コメント追加後)
- 未完了の Issue には進捗と引き継ぎ事項をコメント
4. **ワークスペース全体のコミット確認とプッシュ**
- NetyProd 直下の全 Git リポジトリをスキャンし、未コミット変更を確認
- 未コミット・未プッシュのリポジトリを順にコミット・プッシュ
- 新規作成プロジェクトも含む動的スキャン(ハードコード不要)
```bash
NETYP_ROOT="C:/Users/yuto/NetyProd"
for dir in "$NETYP_ROOT"/*/; do
[ -d "${dir}.git" ] && echo "$(basename ${dir%/}): $(git -C ${dir%/} status --short | wc -l) changes"
done
```
5. **日報を AIワークログ DB に保存**
- 本日の全作業サマリーを Notion「AIワークログ」データベースに保存
```bash
node "C:/Users/yuto/NetyProd/.agents/scripts/notion-worklog.js" \
--date="$(date +%Y-%m-%d)" \
--projects="<作業リポジトリ>" \
--summary="<本日の作業サマリー>" \
--commits="<repo:N形式>"
```
6. **ワークフロー定義を変更した場合のみ**: Notion 同期(`agent_rules.md §7` 参照)
## 引数
引数なし(現在の作業プロジェクトが対象)
NetyProd 配下の全プロジェクトを一括コミット・プッシュし、Notion ワークログに統合1件として保存します。
## 手順
`.agents/workflows/save-all.md` に定義されたステップを順に実行してください。
1. **settings.json バリデーション**
2. **全リポジトリスキャン** — 未コミット・未プッシュの一覧を提示
3. **一括コミット・プッシュ** — 変更内容から自動でコミットメッセージを生成(確認不要)
4. **HANDOFF.md 最終更新日を更新**(変更ありリポジトリのみ)
5. **Notion ワークログに統合1件保存**
## /save-project との違い
- `/save-project` → 現在の作業プロジェクトのみ・HANDOFF.md を詳細更新
- `/save-all` → 全プロジェクト対象・最終更新日のみ更新・ワークログを統合1件で記録
## 引数
なし
Git・コミット
1
今回のセッションで自分が触ったファイルだけを、pathspec スコープで安全にコミットします(共有 index の巻き込み事故を構造的に防ぐ / Issue #102・L-037)。
## なぜこのコマンドが要るか
NetyProd では複数の Claude Code セッション(主セッション + spawn_task / チップ由来)が**同じプロジェクトディレクトリの単一 repo(共有 index)**を触る。`git commit`(pathspec なし)は index 全体を commit するため、**別セッションが staged 済みのファイルを巻き込んで push する事故**が起きる(PJ_RSO bug-log #068 / wmap #004 / engineering-lessons L-037)。
`/save-project` はこの規律を STEP 4 で焼き込み済みだが、**セッション途中のアドホックな 1 コミット**には安全な経路が無かった。本コマンドがその経路。
## 手順
引数($ARGUMENTS)があればコミットメッセージのヒントとして使う。無ければ diff から要約する。
### STEP 1: 自分の変更を確認
```bash
cd <対象リポジトリ>
git status --short # 1 文字目が大文字 M/A/D = 別セッションが staged 済みの合図(L-037)
git diff --stat
```
- 出力から **今回のセッションで自分が触ったファイルだけ** を対象パスに選ぶ。
- 身に覚えのないファイル(`M `/`A `/`D ` で始まる pre-staged 行)は**対象に含めない**。
### STEP 2: 明示パス add → pathspec commit → (必要なら)push
add から commit までを 1 回の Bash 呼び出しで `&&` 連結し、別セッションの割り込み窓を最小化する。
```bash
cd <対象リポジトリ> && \
git add <path1> <path2> ... && \
git commit -m "<メッセージ>
Co-Authored-By: Claude <noreply@anthropic.com>" -- <path1> <path2> ...
```
- **add は明示パスのみ**。`-A` / `--all` / `-u` / 単独 `.` は使わない(`ask_bulk_git_add` で確認ダイアログが入る)。
- **commit は必ず pathspec 付き**(`-- <path...>`)。これは `--only` 意味論で、**index に他セッションの staged が混ざっていても指定パスだけが commit される**。共有 index 経由の巻き込みを構造的に防ぐ。
- push はユーザーが求めた場合、または通常のセーブフローの一部としてのみ。単発コミットだけが目的なら push しない。
### STEP 3: 混入チェック
```bash
git log -1 --stat
```
- commit message に書いていないファイルが `--stat` に含まれていないか 1 行で確認する。
- 想定外ファイルがあれば別セッションの巻き込み。`git reset --soft HEAD~1` で戻して対象パスを絞り直す。
## 注意
- `.gitignore` で除外すべきファイル(認証情報・ビルド成果物)が対象パスに紛れていないか STEP 1 で確認する。
- 複数リポジトリを跨ぐ場合はリポジトリごとに STEP 1-3 を繰り返す。ワークスペース全体の一括セーブは `/save-project`(現行 PJ)/ `/save-all`(全 PJ)を使う。
- 詳細背景の SSOT は `00.aimd/17_WORKTREE_PLAYBOOK.md §10` と `.agents/workflows/save-project.md` STEP 4。
品質・レビュー
4
実装完了後の品質ゲートパイプラインを実行します。
**Validator / Implementer 分離原則** に従い、各 subagent は実装の試行錯誤コンテキストを引き継がず、
spec と diff だけを根拠に独立判定します。
## 設計原則(重要)
> "Don't ask the same agent to write code and verify it. The validator is a separate agent
> with a separate prompt, separate context, and explicit permission to fail the work."
> — toniantunovic / dev.to (2026)
各 subagent には以下を **必ず明記** すること:
- あなたは実装者ではない。実装者の意図・苦労話は無視する
- 根拠は `git diff` と `.claude/specs/in-progress/*.md` のみ
- ユーザー報告ケースが verify に含まれていなければ FAIL
- spec を更新せずに振る舞いが変わっていたら FAIL(SSOT 違反)
## パイプライン
### STEP 0: Active Spec の特定
```bash
ls C:/Users/yuto/NetyProd/.claude/specs/in-progress/*.md 2>/dev/null
git diff --name-only
git diff --cached --name-only
```
変更ファイルが in-progress spec の管理対象に含まれるか判定。
含まれる場合、その spec を STEP 1〜3 すべての subagent に渡す。
### STEP 1: Verifier(テスト・ビルド検証)
`verifier` サブエージェントを起動。プロンプト末尾に必ず以下を含める:
```
あなたは実装者ではない。コミット前の独立検証者として:
- テストスイートが PASS するか
- TypeScript 型エラーがないか
- ビルドが成功するか
- 構文エラーがないか
を確認せよ。
加えて、active spec ([spec パス]) の §verify テンプレに記載された
ユーザー報告ケース全件を確認したエビデンスが diff またはコミットメッセージに
含まれているか検査せよ。代表ケースだけの verify は FAIL とすること。
```
**FAIL の場合**: 修正してから再度 `/post-impl` を実行。PASS になるまでコミットしない。
### STEP 2: Spec Conformance Check(新設)
active spec が存在する場合のみ実行。`general-purpose` サブエージェントで spec 準拠性を独立判定:
```
あなたは独立した spec 準拠性チェッカー。実装者ではない。
入力:
- active spec: .claude/specs/in-progress/[spec名].md
- diff: git diff (unstaged + staged)
判定:
1. spec の「不変条件 / 契約」に違反する変更がないか
2. spec の「地雷リスト」に該当する変更がないか
3. 振る舞いを変えているのに spec が更新されていないか(SSOT 違反)
4. spec の verify テンプレに新ケース追加が必要な変更ではないか
CRITICAL / HIGH / MEDIUM / LOW で報告。
CRITICAL = SSOT 破壊・地雷リスト違反 → コミット不可
HIGH = 不変条件違反 → コミット前に要修正
```
### STEP 3: Code Reviewer(セキュリティ・設計レビュー)
`code-reviewer` サブエージェントを起動。プロンプトに以下を追加:
```bash
git diff --name-only
git diff --cached --name-only
```
```
あなたは独立した security / design レビュー担当。
CLAUDE.md §Boundaries の 🚫 Never do リストへの抵触を最優先で検査せよ:
- innerHTML / outerHTML / document.write に user-controlled 値
- eval / new Function / setTimeout(string)
- secrets ハードコード
- href への未検証値
- style.cssText への埋め込み
等。
```
**CRITICAL / HIGH が出た場合**: 修正してから再実行。
**MEDIUM 以下のみ**: コミット可能(HANDOFF.md の Known Issues に記録推奨)。
### STEP 4: コミット準備確認
3 エージェントが PASS / APPROVED になったら以下を報告:
```
## /post-impl 結果
| チェック | 結果 |
|---|---|
| Verifier (test/build) | ✅ PASS |
| Spec Conformance | ✅ PASS (or N/A if no active spec) |
| Code Reviewer (security/design) | ✅ APPROVED |
コミット可能です。
変更ファイル: [一覧]
推奨コミットメッセージ: [自動生成]
```
## 引数
引数なし(カレントディレクトリの変更を対象とする)。
in-progress spec が複数ヒットしたら全 spec を STEP 1-2 に渡す。
ワークスペース全体の定期監査をオンデマンドで実行します(Layer 1+2+3 フル監査)。
Issue #42 で定義した 3層チェックをすべて実行します。
> **AUTO-FIX policy (Issue [#63](https://github.com/netyu2iv-ops/00aimd/issues/63) — 2026-05-10)**: 既定は **WARN-only**。AUTO-FIX を実行するには引数 `--fix` (Layer 1+2) または `--apply-l3` (Layer 3) を明示すること。silent commit は禁止。
## 手順
### STEP 1: Layer 1+2 自動チェック (WARN-only)
```bash
node "C:/Users/yuto/NetyProd/.agents/scripts/audit-workspace.js" \
--trigger=manual --layer=2 --verbose
```
結果を表示する。ERROR があればユーザーに報告して修正を促す。WARN は一覧化して提示。
### STEP 2: Layer 1+2 AUTO-FIX (引数 `--fix` が指定された場合のみ)
ユーザーが `/audit-workspace --fix` を実行した場合のみ:
```bash
node "C:/Users/yuto/NetyProd/.agents/scripts/audit-workspace.js" \
--trigger=manual --layer=2 --fix
```
修正内容とコミットハッシュをユーザーに報告する。`--fix` 未指定時は **このステップをスキップ**。
### STEP 3: Layer 3 意味チェック (LLM・WARN-only)
`workspace-auditor` サブエージェントを **WARN-only モード** で起動し、以下のファイルペアを意味チェックする:
| チェック | 対象 |
|---|---|
| C-1 | CONFIRMATION_RULES.md ↔ permission-checker.js |
| C-2 | agent_rules.md ↔ CLAUDE.md (役割境界 verification) |
| C-3 | spj.md ↔ resume-project.md ↔ save-project.md |
| C-4 | start-project.md ↔ project-template/ |
`/audit-workspace --apply-l3` で起動された場合は、prompt に `AUTO_FIX_ALLOWED=true` を含めて agent に伝える (それ以外の場合は WARN-only)。
### STEP 4: 結果サマリーの表示
```
## /audit-workspace 結果(YYYY-MM-DD HH:MM)
| Layer | チェック数 | PASS | WARN | ERROR | AUTO-FIX |
|---|---|---|---|---|---|
| L1 構造 | N | N | N | N | N |
| L2 整合性 | N | N | N | N | N |
| L3 意味 | N | N | N | N | N |
### 要対応 WARN
- [一覧]
### 実施した AUTO-FIX
- [一覧]
```
WARN がある場合は Issue 起票するか HANDOFF.md Known Issues に追記するかをユーザーに確認する。
## 引数
- `--fix`: Layer 1+2 の AUTO-FIX を実行する (省略時は WARN-only)
- `--apply-l3`: Layer 3 LLM agent に AUTO-FIX を許可する (省略時は WARN-only)
- 引数なし: 全 Layer を WARN-only で実行 (推奨・安全)
例:
- `/audit-workspace` — 全部チェックして WARN を一覧表示 (silent commit なし)
- `/audit-workspace --fix` — Layer 1+2 のみ AUTO-FIX を許可 (e.g. 閉済 Issue 除去)
- `/audit-workspace --apply-l3` — Layer 3 LLM の AUTO-FIX も許可
- `/audit-workspace --fix --apply-l3` — フル AUTO-FIX
バグログからワークスペース横断の知見を昇格させるレビューを実行します。
「知見レビュー」「`/promote-lessons`」のいずれでも起動します。
## 目的
各プロジェクトの `docs/bug-log.md` に蓄積されたバグエントリのうち、他プロジェクトでも再利用可能な汎用原則を `00.aimd/engineering-lessons.md` に昇格させる。
## 手順
### STEP 1: 対象エントリの収集
```bash
NETYP_ROOT=$(node -e "const os=require('os');try{const c=require(os.homedir()+'/NetyProd/.agents/config/workspace-config.json');console.log(c.workspace.root)}catch(e){console.log(os.homedir()+'/NetyProd')}")
META_FILE="${NETYP_ROOT}/00.aimd/engineering-lessons.md"
LAST_REVIEW=$(grep 'last-review:' "$META_FILE" 2>/dev/null | sed 's/.*last-review:[[:space:]]*//' | tr -d '[:space:]' | head -1)
LAST_COUNT=$(grep 'last-bug-log-entry-count:' "$META_FILE" 2>/dev/null | sed 's/.*last-bug-log-entry-count:[[:space:]]*//' | tr -d '[:space:]' | head -1)
echo "前回レビュー日: $LAST_REVIEW"
echo "前回レビュー時エントリ数: $LAST_COUNT"
# 全プロジェクトの bug-log を列挙
for f in "$NETYP_ROOT"/*/docs/bug-log.md; do
[ -f "$f" ] || continue
echo "--- $f ---"
grep -hE '^## \[[0-9]{4}-' "$f" | head -20
done
```
### STEP 2: 各プロジェクトの bug-log.md を読む
`$NETYP_ROOT/*/docs/bug-log.md` をすべて Read で開き、前回レビュー以降に追加されたエントリに注目する(日付で判定、もしくは全件見直す場合は「今回追加の区別なく」レビューしてもよい)。
### STEP 3: 昇格判定
各エントリについて、以下を順に評価する:
1. **他プロジェクトでも起こり得るか?** ← プロジェクト固有の仕様に深く依存していれば NO
2. **既に `engineering-lessons.md` に同等のルールがあるか?** ← あれば `重複` 判定
3. **具体プロジェクト名・ファイル名を剥がしても原則として意味を成すか?** ← しなければ NO
4. **判断基準・チェック項目として言語化できるか?** ← 単なる修正手順ならまだ抽象度が足りない
**昇格する**: 上記すべて YES → `engineering-lessons.md` に新規 `L-NNN` エントリとして追加
**昇格しない**: いずれか NO → スキップ(元の bug-log に留める)
### STEP 4: 昇格作業
昇格対象ごとに:
1. `engineering-lessons.md` に `L-NNN` エントリを追加
- 「分野」「由来」「診断の順序/原則/チェックリスト」の形式で書く
- プロジェクト名・ファイル名を除去し、**原則とチェックリスト** に絞る
- 由来には元の bug-log エントリ番号を明記(`由来: PJ_RSO bug-log #005`)
2. 元の bug-log エントリ末尾に昇格リンクを追記
- `→ 昇格先: [engineering-lessons.md L-NNN](../../00.aimd/engineering-lessons.md#l-nnn)`
### STEP 5: メタデータ更新
`engineering-lessons.md` 冒頭の HTML コメントを更新:
```markdown
<!--
review-metadata (edit on every promotion-review execution)
last-review: YYYY-MM-DD ← 本日の日付
last-bug-log-entry-count: N ← 全 bug-log のエントリ合計数(再計測)
threshold-new-entries: 3
threshold-days: 7
-->
```
再計測コマンド:
```bash
grep -hE '^## \[[0-9]{4}-' "$NETYP_ROOT"/*/docs/bug-log.md 2>/dev/null | wc -l
```
### STEP 6: レビュー結果の報告
ユーザーに以下を報告:
- 昇格させたエントリ: `L-NNN` タイトル(理由も簡潔に)
- 昇格見送りエントリ: タイトルと理由(プロジェクト固有すぎ / 既存ルールで包摂など)
- 更新したメタデータ: 新しい `last-review` / `last-bug-log-entry-count`
## ガードレール
- **ユーザー確認なしで `engineering-lessons.md` を破壊的に編集しない**: 昇格候補を提示 → ユーザーが OK したら追加
- 昇格対象が 0 件でもメタデータ(`last-review` 日付)は更新する(次の通知がリセットされる)
- 既存の L-NNN エントリの書き換えは行わない(追加のみ)。重複があったらユーザーに報告
コンサル資料水準のドキュメントを、ライター(doc-writer/ストーリーテラー)・レビュワー(doc-reviewer/校閲官)・デザイナー(doc-designer)の3体構成で作成します。
「ドキュメント作成して」「資料をまとめて」等の自然文でも起動しますが、**重いループを伴うため `/write-doc <topic>` の明示起動を推奨**します(軽い要約・1〜2文の説明にはこのコマンドを使わない)。
## 目的
論理構成(ピラミッド原則)・MECE・平易さ・章構成/ページネーション(doc-reviewer)と、配色・タイポグラフィ・レイアウトの視覚仕上げ(doc-designer)を、doc-writer の執筆との往復で担保する。往復カウンタは doc-reviewer と doc-designer で共有し、上限(最大2往復)を設けて無限ループを防止する。
## 引数
| 引数 | 動作 |
|---|---|
| なし | 「トピックを教えてください」と確認して終了 |
| `<topic>` | トピックを受けて STEP 1 から開始 |
## 実行手順
### STEP 1: 要件確認
以下が不明瞭なら `AskUserQuestion` で確認する:
- 想定読者(専門知識ゼロの意思決定者か、同僚エンジニアか等)
- 想定ページ数・深さ
- 一次情報のファイルパス(ある場合)
### STEP 2: doc-writer 起動(ROUND 1)
`Agent` ツールで `subagent_type="doc-writer"` を起動し、`[TOPIC]/[AUDIENCE]/[DEPTH]/[SOURCES]/[ROUND]=1` を渡す。初稿HTMLの絶対パスを受け取る。
### STEP 3: doc-reviewer 起動(論理構成・MECE)
`Agent` ツールで `subagent_type="doc-reviewer"` を起動し、`[DRAFT_PATH]/[TOPIC]/[AUDIENCE]/[ROUND]` を渡す。
判定に応じて分岐:
- **REVISE** → STEP 2 に戻り、doc-writer に `[ROUND]+1` と `[REVISE_NOTES]`(doc-reviewerの指摘そのまま)を渡して改訂させる
- **ESCALATE** → 未解決点一覧をユーザーに提示し、次のアクション(採用/追加指示/再設計)を選んでもらう。ここでこのコマンドの処理は一旦終了
- **PASS** → STEP 3.5 へ
### STEP 3.5: doc-designer 起動(視覚仕上げ)
`Agent` ツールで `subagent_type="doc-designer"` を起動し、`[DRAFT_PATH]/[TOPIC]/[ROUND]` を渡す。**`[ROUND]` は doc-reviewer と同一のカウンタを共有する**(独立カウンタにしない — 全体で最大2往復、3回目のROUNDはdoc-reviewer/doc-designerどちらが対象でも無条件ESCALATEになる設計)。
判定に応じて分岐:
- **REVISE** → STEP 2 に戻り、doc-writer に `[ROUND]+1` と `[REVISE_NOTES]`(doc-designerの指摘)を渡して改訂させる。内容が変わるため、次ROUNDは STEP 3(doc-reviewer)から再度通す
- **ESCALATE** → 未解決の視覚課題一覧をユーザーに提示し、次のアクションを選んでもらう。処理を一旦終了
- **PASS** → STEP 4 へ
### STEP 4: fact-auditor(数値・図表を含む場合のみ)
資料に数値主張・統計・比較グラフが含まれる場合、`Agent` ツールで `subagent_type="fact-auditor"` を起動し、資料内の数値主張を裏取りする。BLOCK が出た場合は doc-writer に修正させ、STEP 3 から再度回す(この往復はカウンタに含めない — 事実誤りの修正は無限ループリスクが質的に異なるため)。
### STEP 5: secretary で提示文言判定
資料を提示する報告文(「資料を作成しました」等)を `secretary` に通し、APPROVED / REVISED の判定を得てから送信する(CLAUDE.md §secretary必須相談シーンに準拠)。
### STEP 6: 表示確認
`preview_start` または `Artifact` ツールで実際にレンダリングし、ユーザーに提示する。PPTX形式が必要な場合は、ここで HTML成果物を渡した上で `anthropic-skills:pptx` スキルに変換を委譲する(doc-designerはPPTX生成そのものを行わない)。
## 他モードとの関係
| モード | 起動契機 | 動作 |
|---|---|---|
| 明示コマンド(本コマンド、推奨) | `/write-doc <topic>` | フル3体ループ(doc-writer→doc-reviewer→doc-designer)を実行 |
| 暗黙起動 | 「ドキュメント作成して」等の自然文 | 同じフローだが、軽い要約依頼と誤認しないよう起動前に一度「コンサル資料水準の資料作成でよいか」を確認する |
詳細はエージェント定義 `.claude/agents/doc-writer.md` / `.claude/agents/doc-reviewer.md` / `.claude/agents/doc-designer.md` を参照。
計測・同期
3
---
description: 計測ダッシュボード集約 — /stats <audit|secretary|permissions> で監査履歴・secretary判定・パーミッション分析を表示
---
# /stats
NetyProd ワークスペースの計測系ダッシュボードを 1 コマンドに集約する。引数でドメインを切り替える。
## 引数
- 引数なし: 3 ドメインの案内のみ表示(実行はしない)
- `/stats audit`: ワークスペース監査ログ (`audit-log.jsonl`) の集計
- `/stats secretary`: secretary 呼び出しの GA4 ログ集計
- `/stats permissions`: パーミッション判断(GA4 レポート)の分析
各ドメインは追加オプションをそのまま透過する(例: `/stats audit --detail`)。
---
## 引数なしの場合の案内
```
/stats は 3 ドメインを持ちます:
/stats audit — ワークスペース監査 (audit-log.jsonl) の集計。Layer 別実行回数・WARN/ERROR 推移
/stats secretary — secretary 呼び出し (GA4) の判定分布・コスト概算
/stats permissions — パーミッション判断 (GA4) の分析・CONFIRMATION_RULES.md 更新案
例: /stats audit --detail / /stats secretary --period=30d
```
---
## `/stats audit` — ワークスペース監査ログ集計
`audit-log.jsonl` から監査履歴を集計してダッシュボードを表示する。Layer 3 LLM agent の ROI 判断材料として使用する(Issue [#66](https://github.com/netyu2iv-ops/00aimd/issues/66) — 効果測定)。
**使用スクリプト**: `.agents/scripts/audit-stats.js`
(`.agents/scripts/codex-audit-stats.js` は別スクリプトで PJ_RSO の Codex pre-user-review サイクル専用の集計。`audit-log.jsonl` ではなく PJ_RSO 配下の `runs/<run_id>/status.json` を集計対象とする、役割の異なるツール。ワークスペース監査の集計には使わない)
### STEP 1: 全期間サマリ表示
```bash
node "C:/Users/yuto/NetyProd/.agents/scripts/audit-stats.js"
```
表示項目:
- 対象期間 / 総実行回数
- 起動経路別 (`spj_subsequent` / `spj_daily_first` / `manual` / `weekly_friday`)
- Layer 別実行回数 + 平均 latency (L1 / L2 / L3)
- 累計 PASS / INFO / WARN / ERROR / AUTO-FIX
- 月次トレンド (WARN / ERROR / AUTO-FIX 推移)
- ROI シグナル (Layer 3 AUTO-FIX 率)
### STEP 2: 詳細を見たい場合
```bash
node "C:/Users/yuto/NetyProd/.agents/scripts/audit-stats.js" --detail
```
追加表示:
- ファイル別 WARN 件数 (top 10)
- 反復 WARN メッセージ (top 5・noise 候補)
- 直近 ERROR / AUTO-FIX (各 5 件)
### STEP 3: 期間を絞りたい場合
```bash
node "C:/Users/yuto/NetyProd/.agents/scripts/audit-stats.js" --since=2026-04-01 --detail
```
### STEP 4: 機械可読出力 (他スクリプトに渡す場合)
```bash
node "C:/Users/yuto/NetyProd/.agents/scripts/audit-stats.js" --format=json
```
### 想定する判断シーン
**A. Layer 3 ROI 判断 (3 ヶ月運用後)** — `--detail` で Layer 3 実行回数が 10 回以上かつ AUTO-FIX 件数が 0 / 反復 WARN がほぼ同一 → Layer 3 効果限定的 → 週次運用への降格を検討。多様な WARN を継続的に検出 → 継続運用。
**B. WARN が多発しているファイルの特定** — `--detail` の「ファイル別 WARN 件数 (top 10)」で同一ファイルが 10 件以上の WARN → 設計問題の可能性 → spec 化 or リファクタ検討。
**C. 反復 WARN (noise 候補) の特定** — 同じメッセージが 3 回以上 → 監査ルール側の改善余地。
### 関連
- 仕様: `00.aimd/06_WORKSPACE_AUDIT.md`
- 元監査: `claude-code-strategy-consultant /spj 監査` (2026-05-10) P2-1
- ログ: `.agents/config/audit-log.jsonl`
---
## `/stats secretary` — secretary 呼び出しの GA4 ログ集計
NetyProd ワークスペースで運用中の `secretary` エージェントの呼び出し統計を集計し、B 案継続 / A 案移行 (廃止) の判断材料を提示する。
### 引数
`--period=<期間>` (任意): `1d` / `7d` / `30d`(既定: `30d`)
### STEP 1: GA4 Data API で secretary_invocation イベントを取得
```bash
NETYP_ROOT=$(node -e "const os=require('os');try{const c=require(os.homedir()+'/NetyProd/.agents/config/workspace-config.json');console.log(c.workspace.root)}catch(e){console.log(os.homedir()+'/NetyProd')}")
PERIOD="${1:-30d}"
node "${NETYP_ROOT}/.agents/scripts/ga4-report.js" \
--event=secretary_invocation \
--period="${PERIOD}" \
--dimensions="judgment,intent,project" \
--output=json > /tmp/secretary-stats.json 2>/dev/null || \
echo '{"error":"ga4-report.js does not yet support --event filter — fallback to transcript scan"}' > /tmp/secretary-stats.json
```
### STEP 2: 集計(GA4 が利用できない場合の代替: 会話履歴 scan)
GA4 取得が失敗した場合、ccd_session_mgmt で transcript を scan して粗い推定を取る:
```
mcp__ccd_session_mgmt__search_session_transcripts({
query: "secretary",
limit: 50,
include_archived: false
})
```
各 hit から「APPROVED / REVISED / SUPPRESS」のいずれかが含まれているかを数える。
### STEP 3: 集計レポート
以下の形式で出力:
```
## /stats secretary — period: <期間>
[呼び出し総数]: N
[判定分布]
- APPROVED: a (a/N %)
- REVISED: r (r/N %)
- SUPPRESS: s (s/N %)
[INTENT 分布]
- ASK_USER: ...
- REPORT: ...
- NOTIFY: ...
- REQUEST_PERMISSION: ...
[プロジェクト分布]
- pj_rso: ...
- 00.aimd: ...
- ...
[コスト推定]
- per-invocation: ~2,500 input tok + ~500 output tok
- 期間合計: N × 2,500 input tok = X tok
- 期間合計: N × 500 output tok = Y tok
- USD 換算: input X × $15/M + output Y × $75/M = $Z
[誤判定候補(手動確認用)]
- SUPPRESS のうち、user が事後に「これは聞いてほしかった」と発言した形跡があるもの → 該当ターン番号を列挙
- REVISED のうち、原文が問題なかったのに書き換えられたもの → 該当ターン番号を列挙
※ 機械判定ではなく目視確認のため、候補を抽出するに留める
[判断材料]
- 月額コスト試算: <$Z × 30 / 期間日数>
- B 案継続の場合の月額: $50 想定値との乖離 → <小さい / 大きい>
- A 案移行を推奨するか: <Yes / No / 継続観察>
```
### STEP 4: 候補 user に提示
レポートを user に提示し、「このまま B 案継続」「A 案へ移行」「さらに改修」のどれを選ぶか確認する。
### 速報レビュー(Day 1 / Day 7 / Day 30)
scheduled task で自動起動される 3 回の速報レビュー(過去実行済・履歴として残置):
- `secretary-review-day1` (2026-05-10): 初日の挙動が爆発していないか
- `secretary-review-day7` (2026-05-16): 1 週間運用で判定分布が安定しているか
- `secretary-review-day30` (2026-06-08): 1 ヶ月運用後の継続判断
各レビューは本コマンド(`/stats secretary --period=<該当期間>`)を実行し、結果を user に通知する。
---
## `/stats permissions` — パーミッション判断の分析
GA4 のパーミッションデータを取得・分析し、`CONFIRMATION_RULES.md` の更新案を提案する。
### 引数
- 引数なし: 過去30日分を分析
- `--days=N`: 過去N日分を分析
### 手順
1. GA4 レポートを取得する:
```bash
node "C:/Users/yuto/NetyProd/.agents/scripts/ga4-report.js" --days=30 --no-html
```
2. 出力データを分析し、以下の観点でパターンを読み取る:
- `decision = user_approved` が多いコマンド → SafeToAutoRun 昇格候補
- `decision = user_denied` が多いコマンド → BlockedOnUser 強化候補
- `agent_type` 別の傾向差異
- `project` 別の確認負荷の偏り
3. 分析結果を以下の形式でユーザーに提示する:
**SafeToAutoRun 昇格候補**(過去30日でuser_approvedのみ・5回以上)
| コマンド | rule_matched | 承認回数 |
|---|---|---|
| ... | ... | ... |
**気になるパターン**
- (特記事項があれば)
4. ユーザーが承認した場合、`CONFIRMATION_RULES.md` に該当ルールを追記する。
---
## 統合履歴
旧 `/audit-stats` `/secretary-stats` `/analyze-permissions` は 2026-07-03 に本コマンドへ統合(使用実績: 全期間 1/5/3 回)。
GA4 から最新のパーミッション分析データを取得し、Notion ダッシュボードを更新します。
## 手順
1. 以下のコマンドを実行する:
```
node "C:/Users/yuto/NetyProd/.agents/scripts/notion-report.js" $ARGUMENTS
```
2. 実行結果を確認し、各レポートの挿入件数をユーザーに報告する。
3. データが0件の場合は「GA4 にまだデータが蓄積されていません。数日後に再実行してください。」と伝える。
4. 成功した場合は Notion DB の URL を案内する:
https://www.notion.so/331186b7a41981028fb4e97d8dc14251
## 引数
- 引数なし: 過去30日分を取得
- `--days=N`: 過去N日分を取得(例: `/update-ga4 --days=7`)
# /update-confirmation-rules-notion
CONFIRMATION_RULES.md の内容を Notion ページ(CONFIRMATION_RULES 詳細ルール定義)に同期します。
CONFIRMATION_RULES.md を更新した際は必ずこのコマンドを実行して Notion を最新状態に保ちます。
## 手順
### STEP 1: 現状確認
まず CONFIRMATION_RULES.md の最新内容を確認する:
```bash
cat C:/Users/yuto/NetyProd/00.aimd/CONFIRMATION_RULES.md
```
### STEP 2: Notion 同期スクリプトを実行
```bash
node C:/Users/yuto/NetyProd/.agents/scripts/update-confirmation-rules-notion.js
```
### STEP 3: 結果確認
スクリプトの出力を確認し、エラーがなければ完了を報告する。
エラーが発生した場合は内容を分析し、スクリプトのデバッグを行う。
### STEP 4: 完了報告
以下の情報をユーザーに報告する:
- 同期した Notion ページの URL
- 更新されたブロック数
- CONFIRMATION_RULES.md の最新変更内容サマリー
## 引数
引数なし(--dry-run オプションを付けてテスト実行も可能)
```bash
node C:/Users/yuto/NetyProd/.agents/scripts/update-confirmation-rules-notion.js --dry-run
```
## 備考
- Notion ページ ID: `331186b7-a419-810b-a74c-eecb99c7deeb`
- Notion ページ URL: https://www.notion.so/331186b7a419810ba74ceecb99c7deeb
- スクリプト: `C:/Users/yuto/NetyProd/.agents/scripts/update-confirmation-rules-notion.js`
- 同期元: `C:/Users/yuto/NetyProd/00.aimd/CONFIRMATION_RULES.md`
## このコマンドを実行すべきタイミング
CONFIRMATION_RULES.md に以下の変更を加えた後:
- SafeToAutoRun セクションへのルール追加・変更
- BlockedOnUser セクションへのルール追加・変更
- 変更履歴への追記
- permission-checker.js の BLOCKED/ALLOWED ルール変更を CONFIRMATION_RULES.md に反映した後
エージェント・自律継続
3
---
description: ギルドマスター(編成の司令塔)に依頼を投げ、必要エージェントの編成表を返す
---
ギルドマスター(編成の司令塔)に依頼を投げ、必要エージェントの編成表を返します。
「ギルマス」「ギルドマスター」「`/gm`」のいずれでも起動します。
## 目的
依頼内容から「今回どのエージェントを・必須で / 推奨で・どのタイミングで・並列で呼ぶべきか」「逆に呼ばなくてよいものは何か」を、**guild-master** サブエージェントが編成表として返す。
エージェントが 15 体規模に増え、CLAUDE.md の必須相談シーン表も肥大した中で、主エージェントが毎回「今回の編成」を再構成する負荷を下げる。
## 引数
| 引数 | 動作 |
|---|---|
| なし | 「依頼内容を添えてください(例: `/gm PJ_RSO の印刷レイアウトを直したい`)」と案内して終了 |
| `<依頼内容>` | 依頼を guild-master に渡し、編成表を取得して提示 |
## 実行手順
### STEP 0: 引数チェック
`$ARGUMENTS` が空なら、以下を案内して終了する(サブエージェントは起動しない):
> 依頼内容を添えてください(例: `/gm PJ_RSO の印刷レイアウトを直したい`)。
> ギルマスが「必須ゲート / 推奨相談先 / 並列可否 / 呼ばなくてよいもの」の編成表を返します。
### STEP 1: guild-master 起動
`Agent` ツールで `subagent_type="guild-master"` を起動し、`$ARGUMENTS`(依頼内容)を渡す。エージェントは自身の system prompt に従い:
1. `.claude/agents/*.md` を Glob で全列挙し、各 frontmatter(役割・別名・起動タイミング・並列可否)を Read
2. `CLAUDE.md` の必須相談シーン表・§Verification を Read
3. 依頼が触れるプロジェクト固有ルール(必要時)を反映
4. 依頼を分類し、各エージェントを 必須 / 推奨 / 対象外 に振り分け、citation 付きの編成表を返す
### STEP 2: 結果提示
エージェントの編成表(必須ゲート / 推奨相談先 / 実行順序 / 呼ばなくてよいもの / 根拠 citation)をユーザーに提示する。
## 位置づけ
- ギルマスは**毎タスクの強制経由点ではない**。呼ぶのは (1) 複数エージェントが絡む非自明タスクの冒頭 (2) 編成に迷ったとき (3) 新エージェント追加後の見直し。
- 単純な 1〜2 ファイルの変更では起動不要(ギルマス自身が「不要」と返す設計)。
詳細はエージェント定義 `.claude/agents/guild-master.md` を参照。
keep-going モードを ON にします。指定タスクを**完了まで自律継続**させ、途中で停止しようとしても Stop hook が継続を促します(Sonnet 5 等の早期停止対策)。
## 実行
引数 `$ARGUMENTS` を完了させたいタスクとして keep-going 状態を作成します。
```bash
node "C:/Users/yuto/NetyProd/.agents/scripts/keep-going-guard.js" --on $ARGUMENTS
```
## 動作と安全弁
- **デフォルト OFF**。このコマンドで明示起動した時だけ Stop hook が発火します。
- **完了の合図**: タスクが完全に終わったら、最終メッセージに `<<KEEP_GOING_COMPLETE>>` と明記すると停止します。
- **中断**: `/keep-going-off` でいつでも解除できます。
- **暴走防止(3重)**:
1. 連続自動継続は **5 回**まで(超えたら自動解除)
2. 起動から **2 時間**で自動解除
3. 直前に discipline-keeper=BLOCK / secretary=SUPPRESS があれば発火せず解除(「立ち止まる」ゲートが優先)
- 行き詰まった・同一ファイル3回目 fix・設計を見直すべき場面では**無理に続けず停止して報告**すること(keep-going は品質ゲートを上書きしない)。
## 起動後の振る舞い
keep-going ON の間は、各ターンで「まだ完了条件を満たしていないか」を自己確認し、未達なら次の一手に進むこと。完了条件を満たしたら `<<KEEP_GOING_COMPLETE>>` を添えて締める。
keep-going モードを解除します(Stop hook による自動継続を止め、通常の停止に戻します)。
## 実行
```bash
node "C:/Users/yuto/NetyProd/.agents/scripts/keep-going-guard.js" --off
```
解除後は通常どおり、ターン終了で停止します。現在の状態を確認したい場合は `--status` を使えます:
```bash
node "C:/Users/yuto/NetyProd/.agents/scripts/keep-going-guard.js" --status
```
知見・成果物の管理
3
---
description: 週次 — auto memory / bug-log / 直近フィードバックを横断レビューし、15_USER_PROFILE.md を更新する
---
# /review-user-profile
`00.aimd/15_USER_PROFILE.md`(オーナー像)を最新状態に保つための週次メンテナンスコマンド。手動実行と scheduled task からの自動実行の両方をサポート。
## 引数
引数なし。
## 手順
### STEP 1: 現状の 15_USER_PROFILE.md を Read
```
C:/Users/yuto/NetyProd/00.aimd/15_USER_PROFILE.md
```
特に「最終更新日」と §10 参照元一覧を把握する。
### STEP 2: 直近 7 日間の auto memory 変化を抽出
```bash
MEMORY_DIR="C:/Users/yuto/.claude/projects/C--Users-yuto-NetyProd/memory"
# 7 日以内に作成・更新された memory ファイル
find "$MEMORY_DIR" -name "*.md" -mtime -7 -type f 2>/dev/null
```
各ファイルを Read し、以下を抽出:
- 新たに記録された feedback 系(`feedback_*.md`)
- user 系プロファイル(`user_*.md`)の追加・変更
- project 系で「進行中」になったもの
### STEP 3: 直近 7 日間の bug-log 横断確認
```bash
NETYP_ROOT=$(node -e "const os=require('os');try{const c=require(os.homedir()+'/NetyProd/.agents/config/workspace-config.json');console.log(c.workspace.root)}catch(e){console.log(os.homedir()+'/NetyProd')}")
for f in "$NETYP_ROOT"/*/docs/bug-log.md; do
[ -f "$f" ] || continue
echo "=== $f ==="
# 過去 7 日に追加されたエントリ見出しを抽出(ファイル mtime が 7 日以内のもの)
if [ "$(find "$f" -mtime -7 -printf "%p\n" 2>/dev/null)" ]; then
head -200 "$f" | grep -E '^## \[[0-9]{4}-' | head -10
fi
done
```
bug-log で繰り返し現れたパターン(同じファイル名・同じ症状種別)を抽出し、ユーザーの「好み」と関連がないか判定する。
### STEP 4: engineering-lessons.md の差分確認
```bash
NETYP_ROOT=$(node -e "...")
git -C "$NETYP_ROOT/00.aimd" log --since="7 days ago" --oneline -- engineering-lessons.md
```
新規昇格 lesson があれば、ユーザーの判断パターン推察に使う。
### STEP 5: 候補抽出 — 15_USER_PROFILE.md に反映すべき変更
以下のいずれかに該当するものを候補とする:
| 候補種別 | 例 |
|---|---|
| **新規 feedback memory** で 15_USER_PROFILE.md に未記載 | 新たな出力スタイル指示 / 新たな技術選好 |
| **既存記載の更新** | 採用ツールが変わった / 運用ルールが変わった |
| **Lethal Trifecta の新パターン** | 過去になかった失敗類型が記録された |
| **古くなった記載** | 引用先 memory が削除されている / 言及プロジェクトが終了した |
### STEP 6: 編集案の提示
候補が 1 件以上ある場合、以下のフォーマットで edit plan を作る:
```
[REVIEW SUMMARY] - YYYY-MM-DD
新規候補: N 件 / 更新候補: M 件 / 削除候補: K 件
[CHANGES]
1. 追加: §X.Y に「<新ルール要約>」(出典: feedback_xxx.md)
2. 更新: §A.B の「<旧>」→ 「<新>」(出典: <理由>)
3. 削除: §C.D の「<項目>」(理由: feedback_xxx.md は最新で否定された)
```
候補ゼロなら以下を出力して終了:
```
[REVIEW SUMMARY] - YYYY-MM-DD
変更なし。15_USER_PROFILE.md は最新状態。
```
### STEP 7: 適用
`mtime -7` 抽出で **新たな矛盾を発見した場合のみ** 自動で edit を適用する。
それ以外(軽微な追加 / 言い換え)はユーザーに edit plan を提示し承認を待つ。
自動適用する条件:
- auto memory に新規 feedback ファイルが存在し、内容が 15_USER_PROFILE.md と矛盾しない(純粋追加)
- 削除対象の memory が物理的に存在しない(dead reference)
これ以外(既存記載の書き換え・優先度変更)は edit plan を提示してユーザー判断を待つ。
### STEP 8: 適用後
15_USER_PROFILE.md の「最終更新日」と §10 を更新し、netyroot リポジトリで commit:
```bash
NETYP_ROOT=$(node -e "...")
cd "$NETYP_ROOT/00.aimd"
git add 15_USER_PROFILE.md
git commit -m "profile: 週次レビューで <要約>"
git push
```
### STEP 9: 完了報告
実行が scheduled task からの場合: ログだけ残す(user 通知しない)。
手動実行の場合: STEP 6 のサマリを表示。
## 自動実行(scheduled task 経由)
scheduled-tasks に登録済み:
- taskId: `weekly-user-profile-review`
- cron: `0 22 * * 0`(毎週日曜 22:00 ローカル時間)
- prompt: 本コマンドを実行
登録解除や cron 変更は `mcp__scheduled-tasks__update_scheduled_task` を使用。
プロジェクトのプロトタイプ全体を棚卸しし、現行最新版を確定して `docs/PROTOTYPE_INDEX.md` を再生成する。
「プロトタイプ整理」「proto カタログ更新」「`/proto-index`」のいずれでも起動します。
## 目的
プロジェクト内に増えがちなプロトタイプ HTML / デザイン案を **prototype-librarian** エージェントが
棚卸しし、機能領域ごとの **現行最新版** を一義的に確定。仕様・デザイン要約と系譜を
`docs/PROTOTYPE_INDEX.md`(SSOT カタログ)として記録・更新する。
「どれが最新版か分からない」「同じ機能の proto が乱立」状態を構造的に解消する。
## 引数
| 引数 | 動作 |
|---|---|
| なし | 現在の作業プロジェクトを対象に棚卸し(プロジェクト不明なら確認) |
| `<project>` | 指定プロジェクト(例: `PJ_RSO` / `YAWEB` / `PEDAL`)を対象 |
| `all` | 初期スコープ 3 プロジェクト(PJ_RSO / YAWEB / PEDAL)を順に処理 |
> 初期対象は proto 多用の **PJ_RSO / YAWEB / PEDAL** 先行。他プロジェクトは引数明示で対応。
---
## 実行手順
### STEP 1: 対象プロジェクト確定
引数または現在の作業プロジェクトから対象 `<P>` を決める。曖昧なら確認する。
### STEP 2: prototype-librarian 起動
`Agent` ツールで `subagent_type="prototype-librarian"` を起動し、対象 `<P>` を渡す。
エージェントは system prompt の手順に従い:
1. `<P>/HANDOFF.md` / 既存 `docs/PROTOTYPE_INDEX.md` / `design/README.md` 等の SSOT を Read
2. proto 実体を Glob で全列挙(`dist/` `public/` `build/` は複製として除外集計)
3. `git log` で各 proto の最終更新・系譜を確認
4. 機能領域ごとに現行最新版を確定(citation 必須)
5. `docs/PROTOTYPE_INDEX.md` を**全体再生成**(非破壊・確認不要)
6. proto HTML の `<head>` に `<!-- proto-status: ... -->` マーカー注入(非破壊・確認不要)
7. 破壊的整理(rename/move/delete/重複削除)は `[PROPOSAL]` として提示(未実行)
### STEP 3: 結果報告
エージェントの出力(現行最新版サマリ / 検出問題 / 整理提案)をユーザーに提示する。
`[PROPOSAL]` がある場合は「承認すれば checkpoint 付きで実行します」と添える。
### STEP 4: 提案の実行(ユーザー承認時のみ)
ユーザーが整理提案を承認した場合のみ:
1. 「checkpoint します」と宣言(agent_rules.md §12)
2. rename / move / delete を実行
3. `/proto-index <P>` を再実行してカタログを再同期
---
## 他モードとの関係
| モード | 起動契機 | 動作 |
|---|---|---|
| 手動(本コマンド) | `/proto-index <P>` | カタログ全再生成 + 提案 |
| 提示前ゲート | proto を user に見せる前(CLAUDE.md 必須相談) | PROCEED / WARN / BLOCK 判定 |
| /spj 自動 | セッション開始時 | drift 検知 → WARN 通知のみ(自動再生成しない) |
| save 時自動 | proto HTML を含む save-project | カタログ自動再生成 |
詳細はエージェント定義 `.claude/agents/prototype-librarian.md` および
system prompt `.agents/prompts/prototype-librarian-system-prompt.md` を参照。
ユーザー操作フローを rrweb で構造化録画し、Claude が解釈する。
「ユーザーフロー録画」「`/userflow`」のいずれでも起動します。
## 目的
スクリーンショット数枚では伝わりにくい多段階の UI 操作・バグ再現手順を、**rrweb (DOM mutation + イベント) の JSON ログ** として記録し、Claude が「どの要素を・いつ・どの順で操作したか」を構造的に読めるようにする。
動画より圧倒的に軽量(30 秒で 200〜500 KB)かつ Claude が要素レベルで理解できる。
## サブコマンド
引数で動作が変わる:
| 引数 | 動作 |
|---|---|
| なし | できることと使い方の概要を表示 |
| `setup` | 初回セットアップ手順(ブックマークレット導入) |
| `analyze <path>` | 録画 JSON を解析してタイムライン出力 |
---
## /userflow(引数なし)
以下を表示する:
```
/userflow — ユーザー操作フロー録画ワークフロー
できること:
- rrweb でブラウザ操作を構造化録画(クリック・入力・遷移・スクロール)
- JSON を解析して人間可読タイムラインに変換
- Claude が要素レベルで操作意図を理解できる
サブコマンド:
/userflow setup — 初回のみ: ブックマークレット導入
/userflow analyze <path> — 録画ファイルを解析
参照:
.agents/templates/rrweb-bookmarklets.md ← ブックマークレット本体
.agents/scripts/rrweb-analyze.js ← 解析スクリプト
```
ユーザーがどれを実行したいか確認してから次に進む。
---
## /userflow setup
初回セットアップ。以下を順に案内:
### STEP 1: ブックマークレット 2 つを Chrome に登録
`.agents/templates/rrweb-bookmarklets.md` を Read で開き、ユーザーに「録画開始」「停止+保存」の 2 つの URL を提示する。
ユーザーは Chrome のブックマークバーで:
1. 右クリック → 「ページを追加」
2. 名前: `▶ Record Flow`、URL: 提示された `javascript:...` 行を貼り付け
3. 同様に `⏹ Save Flow` を追加
### STEP 2: テスト録画
ユーザーに以下を依頼:
1. 任意のページを開く(例: `https://example.com`)
2. `▶ Record Flow` をクリック → DevTools Console に `🔴 rrweb recording started` が出るのを確認
3. リンクをいくつかクリック・スクロール
4. `⏹ Save Flow` をクリック → `userflow-<timestamp>.json` がダウンロードされるのを確認
### STEP 3: 解析テスト
ダウンロードされた JSON のパスを聞き、`/userflow analyze <path>` を実行して動作確認。
### CSP でブロックされた場合
`.agents/templates/rrweb-bookmarklets.md` の「CSP でブロックされた場合」セクションに沿って Tampermonkey 案を案内する。
---
## /userflow analyze <path>
引数で渡された JSON を解析する:
```bash
node "C:/Users/yuto/NetyProd/.agents/scripts/rrweb-analyze.js" "<path>"
```
オプション:
- `--max=N` — タイムライン最大表示行数(デフォルト 200)
- `--raw` — 全イベントを raw JSON で出力(巨大になるので必要時のみ)
### 解析後の Claude の動き
タイムラインを読み、以下を報告する:
1. **フロー概要**: 何をしようとした操作か(要素・テキストから推定)
2. **重要なイベント**: ページ遷移・主要なクリック・入力
3. **ユーザーが詰まった可能性のある箇所**: 同じ要素を複数回クリック・長い滞在時間・スクロール往復
4. ユーザーの依頼(バグ調査・UX レビュー等)に応じた具体的な所見
タイムラインだけで判断できないとき(要素の見た目やレイアウトが必要なとき)は、ユーザーに該当時点のスクショを追加で求める。
---
## 提案トリガ(Claude が能動的に勧めるとき)
以下を検出したら「`/userflow` で録画を渡してもらえると要素レベルで追えます」と提案する:
| 兆候 | 例 |
|---|---|
| 連続スクショで多段階フロー説明 | 3 枚以上のスクショ + 「この後ここを押して…」 |
| バグの再現手順説明 | 「再現手順は…」「こうやると…」「順番に…」 |
| UX レビュー依頼 | 「このフロー使いにくい?」「迷子になる?」 |
| 操作経路の食い違い | ユーザーの説明と実装が合わない |
提案文例:
> このフローは `/userflow` で録画してもらうと、クリック対象や入力タイミングが Claude 側で要素レベルで読めます。初回セットアップなら `/userflow setup`、すでに録画済みなら `/userflow analyze <path>` で解析します。
提案は **1 セッションに 1 回まで**。ユーザーが断ったら再度勧めない。
---
## ガードレール
- ブックマークレットは `maskAllInputs: true` で input 値を自動マスクするが、`contenteditable` や非 input 要素のテキストはマスクされない。**機密情報を含む画面では録画前にユーザーに警告**する
- 録画 JSON は機密になりうる(DOM 構造・URL パラメータ等)。コミットしない方針を案内する
- ファイルサイズが 5 MB を超える録画は長すぎる可能性が高い → フローを区切って再録画を提案
PJ_RSO 固有
2
10〜30 round に 1 回、UI 修正の総括 alignment 報告を生成する
(alignment-audit-spec.md §4 Stage 3)。
## 用途
サイクル末 (例: R232 完了時) に全 scope を一括 audit + screenshot を取り、
1 ページの markdown report に集約。discipline-keeper / ユーザーが citation
源として参照する。
## 手順
### STEP 1: Round/サイクル番号の特定
- `git log --oneline -20` から最新コミットの "Rxxx" 表記を抽出
- ユーザーに「サイクル番号 Rxxx で正しいですか?」と確認 (skip 可)
### STEP 2: 全 scope audit (Preview MCP / Playwright MCP)
`/post-impl` STEP 1.5 と同じ手順で以下を実行:
#### 2-A: Horizontal Overflow Audit (mobile)
viewport 393×852 (iPhone 15) で `tools/scripts/horizontal-overflow-audit.js`
を `preview_eval`。`overflow_px > 0` なら fail として記録。
cycle 単位の追跡では viewport を変えて 393 / 375 / 600 の 3 段階で測ると
break point の特定が早い。
#### 2-B: Alignment Audit (PC)
viewport 1440×900 で 4 scope:
- `.measure-panel`
- `.floating-tool`
- `.score-row`
- `#structPalette`
加えて、可能なら以下 state も audit (Issue #81 対応):
- measure-panel rhythm/setting タブ active
- structure mode active
- viewport 600px / 375px
### STEP 3: Screenshot
各 state ごとに `browser_take_screenshot` で full page 撮影。
`docs/visual-baseline/YYYY-MM-DD/cycle-Rxxx-{state}.png` 形式で保存。
### STEP 4: Report 生成
`docs/visual-baseline/YYYY-MM-DD/alignment-cycle-report-Rxxx.md` を作成:
```markdown
# Alignment Cycle Report — Rxxx
**Date**: YYYY-MM-DD
**Cycle**: Rxxx (前 cycle: Ryyy)
**Audit baseline**: alignment-audit-spec.md vN
## Summary
### Horizontal Overflow (mobile viewports)
| Viewport | overflow_px | Result |
|---|---|---|
| 393×852 (iPhone 15) | 0 | ✅ PASS |
| 375×812 (iPhone SE) | 0 | ✅ PASS |
| 600×800 (boundary) | 0 | ✅ PASS |
### Alignment (PC viewport 1440×900)
| State | Scopes audited | Pass | Fail |
|---|---|---|---|
| default render | 4 | 4 | 0 |
| rhythm tab active | 1 | 1 | 0 |
| ... | | | |
## Multimodal Vision Check (主エージェント)
- 歯並び問題: なし / あり (詳細: ...)
## Fail 詳細
(fail 0 件なら省略)
## Discipline-keeper Citation
(WARN/BLOCK あれば追加要件と対応を記載)
## Artifacts
- alignment-audit-Rxxx-default.json
- alignment-audit-Rxxx-rhythm.json
- cycle-Rxxx-default.png
- ...
## 次サイクルへの引き継ぎ
- 解消 fail: ...
- 残 fail: ...
- spec 改訂事項: ...
```
### STEP 5: ユーザーに送付
report の主要部分 (Summary + 未解消 fail) をチャットに転記。
discipline-keeper 経由で citation すべき項目があれば flag する。
## 不変条件
- 全 state の audit 結果を report に含める (代表 state だけは禁止 — bug-log #015 同型)
- before/after screenshot を **必ず** 保存 (spec §4 Stage 2 不変条件)
- discipline-keeper WARN/BLOCK は無視せず、追加要件を report に反映
## 引数
引数なし (round 番号は git log から自動推定)。
PJ_RSO 専用の実装後品質ゲートパイプライン。
NetyProd workspace の `/post-impl` (Validator/Implementer 分離) を継承し、
**UI 変更を含む commit に対して alignment-audit ステップを追加**する。
## 設計原則
workspace `/post-impl` (`~/NetyProd/.claude/commands/post-impl.md`) の
STEP 0〜4 をそのまま実行した上で、PJ_RSO 固有の **STEP 1.5** を挿入する。
UI 変更を含まない commit (script のみ・doc のみ等) では STEP 1.5 はスキップ。
## パイプライン
### STEP 0: Active Spec の特定
workspace `/post-impl` STEP 0 と同じ。`PJ_RSO/.claude/specs/in-progress/` を含めること。
### STEP 1: Verifier (テスト・ビルド検証)
workspace `/post-impl` STEP 1 と同じ。
### STEP 1.5: Visual & Layout Audits (PJ_RSO 専用・条件付き)
#### 起動条件
`git diff --name-only` および `git diff --cached --name-only` の結果に
**以下のいずれか**が含まれる場合のみ実行:
- `index.html` (CSS / DOM 構造変更)
- `js/v2-render.js` (描画ロジック)
- `js/v2-vexflow.js` (VexFlow マウント)
- `js/score-app-bar.js` / `js/score-meta-strip.js` / `js/score-header.js` (Modern Editorial 三層)
- `design/score/*.html` / `design/panel/*.html` (proto SSOT)
- `.agents/scripts/alignment-audit-inline.js` / `tools/scripts/horizontal-overflow-audit.js` (audit script 自身)
含まれない場合: 「UI 変更なし、audit スキップ」と報告して STEP 2 へ。
#### Tool 選択
以下のいずれかを使う (検出順):
1. **Claude_Preview MCP** (推奨・iteration 中の局所修正向け) — `preview_start` で
`pj-rso-local` を起動 → `preview_resize` で viewport 設定 → `preview_eval` で
audit script を実行。**ローカル変更を見れる**ので commit 直前 verify に最適。
2. **MCP_DOCKER Playwright** (本番回帰確認向け) — `browser_navigate` で本番 URL を
開く。デプロイ後の最終 smoke test で使う。**未デプロイの変更は見えない**ことに注意。
両方 unavailable なら「audit は Preview/Playwright MCP 必須。手動実行を依頼」と
報告して STEP 2 へ。
#### 1.5-A: Horizontal Overflow Audit (mobile, R267 起点)
**目的**: `[data-tip]::after` tooltip など pseudo-element 由来の `body.scrollWidth`
拡張を検出。これを許すと iPhone 等で意図しない水平スワイプが発生する (R267 事例)。
**手順**:
1. viewport を **393×852 (iPhone 15)** に設定
```
preview_resize { width: 393, height: 852 }
```
2. ページをリロード (cb クエリ推奨):
```
preview_eval: window.location.href = 'http://localhost:3000/?cb=' + Date.now();
```
3. measure-card 描画完了を待ってから `tools/scripts/horizontal-overflow-audit.js` の
全文を `preview_eval` に投げる。
4. 戻り値を読む:
- `ok: true` → PASS、次のステップへ
- `ok: false` → 報告された `chain` (body から narrow down した culprit chain) を
ユーザーに提示、修正に戻る (commit せず)。`pseudo_hint` があれば
`data-tip ::after` 起因と推定。
**fail 例** (R267 で検出されたパターン):
```json
{ "ok": false, "overflow_px": 91,
"chain": [
{ "tag": "DIV", "cls": "page", "delta": 91 },
{ "tag": "MAIN", "cls": "workspace", "delta": 91 },
{ "tag": "HEADER", "id": "scoreAppBar", "delta": 91 },
{ "tag": "BUTTON", "id": "appBarMenuBtn", "delta": 70 }
],
"pseudo_hint": { "data_tip": "メニュー (Save / 曲情報...)", "after_width": "220.5px" }
}
```
#### 1.5-B: Alignment Audit (sibling variance / baseline)
**目的**: 兄弟要素の高さ・幅・baseline の整列ズレ検出。
**State coverage** (Issue #81 反映):
| Phase | viewport | state | 必須/Optional |
|---|---|---|---|
| A.1 | PC 1440 | chord tab (default) | 必須 |
| A.2 | PC 1440 | rhythm tab active | 必須 |
| A.3 | PC 1440 | setting tab active | 必須 |
| B | PC 1440 | structure mode active | Optional (構成モード変更 commit のみ) |
| C.1 | mobile 375 | chord tab | 必須 (mobile UX commit のみ) |
| C.2 | mobile 375 | rhythm tab | 必須 (mobile UX commit のみ) |
| C.3 | mobile 375 | setting tab | 必須 (mobile UX commit のみ) |
| D | PC 1440 | library mode (table/grid) | Optional (library 変更 commit のみ) |
**手順**:
1. viewport を target に設定
```
preview_resize { width: 1440, height: 900 } // または 375x812 for mobile
```
2. ページを `?vb=1&cb=...` でリロード (vb-design class が body に付く必要あり)
3. (Preview MCP) `preview_eval` で `.agents/scripts/alignment-audit-inline.js` の
`auditAlignment` / `prepareForAudit` 関数を inject。
(Playwright MCP) `browser_navigate` + `browser_evaluate` で同関数 inject。
4. measure-card click で panel open → 必要なら data-panel-tab="..." で tab 切替
5. 以下 4 scope を順次実行:
- `.measure-panel`
- `.floating-tool`
- `.score-row`
- `#structPalette`
6. 結果が `passed: true` (or `failsCount: 0`) であること確認
**過去 baseline**:
- 2026-05-08 R269 で Phase A (PC 3 tabs) + Phase C (mobile 3 tabs) 全 PASS
→ `docs/visual-baseline/2026-05-08/audit-R269-state-coverage.json`
#### 1.5-C: 結果保存
`docs/visual-baseline/YYYY-MM-DD/audit-{round}.json` に保存:
```json
{
"round": "Rxxx",
"date": "YYYY-MM-DD",
"horizontal_overflow": { "viewport": "393x852", "ok": true, "overflow_px": 0 },
"alignment": {
"viewport": "1440x900",
"results": { ".measure-panel": {...}, ... },
"summary": { "passed_scopes": 4, "failed_scopes": 0 }
}
}
```
#### 1.5-C-bis: Silent-Failure Detection (handler 発火 → 副作用観測)
**目的**: click handler / event handler が「コードは落ちないが期待動作が起きない」silent
failure 状態でないか検出 (R259 起点・Issue #93)。「handler が存在する」≠「click が効果を持つ」。
**起動条件**:
新規 click handler / event handler を含む変更 (上記 1.5 の起動条件に追加で、
`addEventListener` / `onclick` / button 要素追加 / setMode 系の経路追加が含まれる場合)。
**手順**:
1. preview を起動した状態で `tools/scripts/silent-failure-detector.js` を `preview_eval`。
2. 入力として `window.__sfdTargets` を直前にセット。例:
```js
window.__sfdTargets = [
{ selector: '.measure-card', label: 'panel open', expect: { drawer: 'chord' } },
{ selector: '.slot-rhythm-btn', label: 'rhythm CTA', expect: { drawer: 'rhythm' } },
{ selector: '.slot-chord-btn', label: 'chord slot', expect: { drawer: 'chord' } },
{ selector: '#propsBtn', label: 'props tab', expect: { drawer: 'props' } },
];
```
3. 戻り値の `summary.silentFailures` が空であること、`results[i].expectMet === 'PASS'` を全件確認。
**観測チャンネル** (PJ_RSO-tuned):
- drawer 表示状態 (`#chordDrawer` / `#rhythmDrawer` / `#propsDrawer` の computed `display`)
- panel state (`[data-mode]` / `[data-active-tab]` / class)
- body class (mode toggles の伝播)
- active class 数 (`is-active` / `is-panel-active` / `is-open` / `is-selected`)
- 全 element 数の delta (DOM 追加/削除)
- toast text (`#appToast` / `.toast`)
- `pj_rso_*` localStorage keys
- click 時の `console.error` / `console.warn` (silent failure と並行で warn が出ることがある)
**「主動線 + 近道導線」coverage** (Issue #93 part C):
新規 CTA や近道導線 (例: 空 slot から直接タブ切替できるボタン) を追加した場合、
**既存主動線 (panel-tabs) と独立に** detector を回す。R259 の根本原因は CTA が
dormant 経路を主動線に格上げしてバグ顕在化したこと。
**fail 例** (R259 を pre-fix 状態で検出した場合):
```json
{
"label": "rhythm CTA",
"hadEffect": true,
"expectMet": "FAIL (drawer_rhythm=none)",
"diff": { "panel_data_mode": { "before": "", "after": "rhythm" } }
}
```
`hadEffect: true` でも `expectMet: FAIL` なら期待外の経路で silent failure。
#### 1.5-D: 判定
- **三 audit (overflow + alignment + silent-failure) すべて PASS** + multimodal vision
check 主エージェント実施 → STEP 2 へ
- **いずれかで fail** → 修正に戻る (commit せず)。fail 内容を spec §3 計測項目別に分類
#### Multimodal Vision Check (alignment-audit-spec.md §4 Stage 2)
audit 0 件 ≠ 完了。`browser_take_screenshot` で full page を撮影し、
主エージェントが目視で「歯並び YES/NO」を判定。before/after の screenshot を
`docs/visual-baseline/YYYY-MM-DD/` に保存。
#### Discipline-keeper Citation
UI commit 直前なので **必ず** `discipline-keeper` subagent に並列で
commit gate 判定を依頼すること (CLAUDE.md §discipline-keeper 必須相談シーン)。
WARN/BLOCK が返れば、追加要件を反映してから commit。
### STEP 2: Spec Conformance Check
workspace `/post-impl` STEP 2 と同じ。
`alignment-audit-spec.md` が active なら必ず読み込ませる。
### STEP 3: Code Reviewer
workspace `/post-impl` STEP 3 と同じ。
### STEP 4: コミット準備確認
workspace `/post-impl` STEP 4 + audit 行を追加:
```
## /post-impl 結果 (PJ_RSO)
| チェック | 結果 |
|---|---|
| Verifier (test/build) | ✅ PASS |
| Horizontal Overflow Audit (mobile 393, UI changes only) | ✅ PASS (overflow=0) or N/A |
| Alignment Audit (PC 1440, UI changes only) | ✅ PASS (4/4 scope) or N/A |
| Silent-Failure Detection (new handlers only) | ✅ PASS (silentFailures=0) or N/A |
| Spec Conformance | ✅ PASS |
| Code Reviewer (security/design) | ✅ APPROVED |
| Discipline-keeper (UI commit gate) | ✅ PROCEED |
コミット可能です。
変更ファイル: [一覧]
推奨コミットメッセージ: [自動生成]
verify 行追加例:
`verify: horizontal-overflow OK + alignment-audit OK + silent-failure (4 handler all PASS, drawer expectations met)`
artifact 行追加例: `artifact: docs/visual-baseline/YYYY-MM-DD/audit-{round}.json`
```
## 不変条件 (alignment-audit-spec.md §7 継承)
- audit fail が残る状態で commit しない
- audit 0 件 ≠ 完了 (multimodal vision check が必要)
- UI commit は discipline-keeper citation 必須
## 引数
引数なし (workspace `/post-impl` と同じ)。
補足 — 行数はコマンド定義ファイルの規模の目安です(ロジック本体は .agents/scripts/ 側にあり、コマンド定義はそれを呼ぶだけのものが多い)。説明文は各定義ファイルの先頭記述をそのまま読み出しているため、定義を更新して再生成すれば内容が追従します。