Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
015d499
docs(ci): Claudeレビューを他レビュー統合型に変える設計を追加
mhaya Sep 1, 2026
fe8ce54
docs(ci): Claudeレビュー統合の実装計画を追加
mhaya Sep 1, 2026
616b31a
test(ci): Claudeレビュー統合のテスト基盤とPR#1905のfixtureを追加
mhaya Sep 1, 2026
d6da496
docs(ci): 実装計画のfixture期待値を実データに合わせる
mhaya Sep 1, 2026
6bd6b61
feat(ci): PRの既存レビューをGraphQLで収集するスクリプトを追加
mhaya Sep 1, 2026
c8f12c3
fix(ci): レビュー出力のテストと pagination limit 検出を追加
mhaya Sep 1, 2026
d1e57fb
docs(ci): 設計のGraphQLクエリをlast:100に修正
mhaya Sep 1, 2026
5661ce7
feat(ci): 既存レビューを外部データ枠に入れた入力とプロンプトを追加
mhaya Sep 1, 2026
45cb6e0
fix(ci): 外部レビュー本文からの囲み偽造をnonceと記号無害化で防ぐ
mhaya Sep 1, 2026
32c6f18
feat(ci): Claude出力の和集合と検証を行う集約スクリプトを追加
mhaya Sep 1, 2026
664cd57
fix(ci): 集約スクリプトのパス内重複排除と行番号検証を実装
mhaya Sep 1, 2026
38bf278
fix(ci): 行番号正規化による鍵衝突を解決
mhaya Sep 1, 2026
6a1d362
feat(ci): 裁定結果を集約コメントのMarkdownに描画する処理を追加
mhaya Sep 1, 2026
4edd6c9
fix(ci): render.py の Markdown 注入を防ぐ
mhaya Sep 1, 2026
f0047c9
fix(ci): _cell() のバックスラッシュ回帰と改行によるブロック注入を修正
mhaya Sep 1, 2026
84dab8a
docs(ci): 設計に出力側のMarkdown注入対策を追記
mhaya Sep 1, 2026
ce4b2ba
feat(ci): 確度の高い修正案をinline suggestionとして投稿する処理を追加
mhaya Sep 1, 2026
bcd705c
fix(ci): claude-fix マーカーの偽造対策と kind ガードの回帰テストを追加
mhaya Sep 1, 2026
6d92563
fix(ci): claude-fixマーカーをreplacement経由で偽造できる穴を塞ぐ
mhaya Sep 1, 2026
6a1b177
feat(ci): Claudeレビューを他レビュー統合型に変更
mhaya Sep 1, 2026
d82ad47
fix(ci): レビュー配線のレビュー指摘3件を修正
mhaya Sep 1, 2026
3f16c97
refactor(claude-review): _esc/_cell/_fence を mdsafe.py に集約
mhaya Sep 1, 2026
d7b1bcc
fix(claude-review): 行頭の構造記号を無害化する(所見1/2)
mhaya Sep 1, 2026
073f5d5
fix(claude-review): 壊れたパスを passes の分母に数えない(所見3)
mhaya Sep 1, 2026
63a511e
fix(claude-review): inline suggestion が無いとき「あり(inline)」と言わない(所見4)
mhaya Sep 1, 2026
494b144
fix(claude-review): pull_request_review系トリガに投稿者ガードを追加(所見7)
mhaya Sep 1, 2026
51117b0
fix(claude-review): SELF 判定が [bot] 表記のログインを見逃す穴を塞ぐ(所見8)
mhaya Sep 1, 2026
e28d939
fix(claude-review): clean_adj も空の title を弾く(所見11)
mhaya Sep 1, 2026
304dc3e
fix(claude-review): @ メンションを無害化する(所見12)
mhaya Sep 1, 2026
99ef35f
docs(claude-review): 計画・設計書の陳腐化した記述を修正(所見5/6)
mhaya Sep 1, 2026
b0fcd48
add operations.md
mhaya Sep 1, 2026
31396e8
fix(claude-review): PR #1907 のレビュー指摘に対応する
mhaya Sep 1, 2026
ccf9367
chore(claude-review): api-inventory 側のワークフロー複製を消す
mhaya Sep 1, 2026
11516e5
fix
mhaya Sep 2, 2026
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
449 changes: 225 additions & 224 deletions .github/workflows/claude-pr-review.yml

Large diffs are not rendered by default.

303 changes: 303 additions & 0 deletions docs/OPERATIONS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,303 @@
# WEKO3 運用ルール

> **素案 / DRAFT** — チームレビュー前。
> 2026-09-01 に §9 の未決 5 件を決定し、本文に反映済み(決定の記録は §9)。

## 0. この文書の位置づけ

| 文書 | 書いてあること |
|---|---|
| `AGENTS.md` | コード規約・環境・テストの流儀 |
| **本書** | **日々守るべき運用ルール**(誰が・いつ・何をするか) |
| `tools/api-inventory/ci/README.md` | API 台帳 CI の設置手順・トラブルシュート |
| `tools/api-inventory/scripts/README.md` | 台帳そのものの作り方(Phase 1-9) |
| `tools/claude-review/README.md` | Claude PR レビューのスクリプト構成と実行順 |

本書は**手順書ではなくルール**。手順は上の各 README を見る。
迷ったときに「どうすべきか」を決める根拠がここにある。

対象は `RCOSDP/weko` の開発・レビュー・リリースに関わる全員。

---

## 1. 大前提: このリポジトリは public

`RCOSDP/weko` は public。**Actions のログ・artifact・PR コメントも誰でも読める。**
このリポジトリの運用ルールのほぼ全部が、ここから導かれている。

| 置いてよい場所 | 内容 |
|---|---|
| `RCOSDP/weko`(public) | コード、ツール、CI の定義。**データは 1 件も置かない** |
| `RCOSDP/weko-secret`(private) | API 台帳 TSV、`api_snapshot.json`、`reconcile_*`、調査記録 |

### 禁止事項

- **台帳・ベースライン・調査記録を public リポジトリに commit しない。**
台帳は「どの経路を・どう叩けば・何が取れるか」と実証結果を持つ。攻撃手順書に近い。
- **CI に明細を出させない。** 件数だけを出す(`--summary-only`)。URI・endpoint 名は出さない。
- **`fixtures.json` を commit しない。** OAuth アクセストークンと平文パスワードを含む。

`tools/api-inventory/.gitignore` が `*.tsv` などを無視しているが、
**これは保険であって設計ではない。データを公開領域に置かないことが設計。**
`git status` に `tools/api-inventory/` 配下の `*.tsv` や `api_snapshot.json` が現れたら、
置き場所を間違えている。

---

## 2. ブランチとタグの対応規則

台帳とベースラインは **WEKO3 のブランチごとに内容が違う**。
`develop_v2.0.4` のコードを `main` の台帳と突き合わせれば、
ブランチ間の経路差がそのまま差分として出る。件数が常に非ゼロになれば、誰も読まなくなる。

### 規則 2-1: private 側には weko と同名のブランチを作る

```text
RCOSDP/weko fix/issue62569 ──PR──> develop_v2.0.4
│ 同名で対応させる
RCOSDP/weko-secret fix/issue62569 ──PR──> develop_v2.0.4
```

台帳を触らない変更なら private 側にブランチを作らなくてよい(base 解決に落ちる)。

CI は **PR の head → base → 既定ブランチ**の順に private 側の同名ブランチを探す。
head を先に見るのは、公開側のコード PR と private 側の台帳 PR を**並行してレビューでき、
マージ順に依存させない**ため。

### 規則 2-2: 新しいリリースラインを切ったら、private 側にも同名ブランチを作る

対応ブランチが無くても CI は止まらないが、**出る件数は当てにならない。**
警告付きの PR コメントを「PASS だった」と読まないこと。
FAIL にしていないのは、対応ブランチの無いリリースラインで全 PR が止まるのを避けるため。

実例(2026-09-01): `RCOSDP/weko` の `release_v2.0.4` に合わせて、
`RCOSDP/weko-secret` にも `release_v2.0.4` を作り `main` へ PR した
(weko-secret PR #2)。マージ後に `v2.0.4` タグを打っている。

### 規則 2-3: バージョンタグは両リポジトリで同名にする

WEKO3 に `v2.0.3` を打ったら、private 側にも `v2.0.3` を打つ。
タグメッセージには対象コミットの完全な SHA と、その時点の台帳規模・突き合わせ結果を残す。

タグを打たずに台帳だけ更新すると、**過去のバージョンに対する調査結果を後から参照できない。**
インシデント調査や監査で「その時点でどうだったか」を問われたときに答えられなくなる。

---

## 3. API 台帳の運用

### 3-1. 更新義務

**API を変更した PR では、private 側の `api_snapshot.json` を更新する。**

公開側のコード変更と private 側のベースライン更新は**別の PR になる**。
データを公開領域に置かない代償で、ここだけ手順が 2 つに分かれる。

```bash
# API を変更した作業ブランチで
./install.sh
python3 tools/api-inventory/scripts/snapshot.py \
--out "$WEKO_API_INVENTORY_DIR/api_snapshot.json"
# → private 側で同名ブランチを切って commit / PR
```

**ベースラインは `install.sh` で作った環境から生成する。** 手元の docker 環境で作ると
依存パッケージの版差で W6 が出続け、本当の依存更新に気づけなくなる。

### 3-1a. 台帳更新 PR のレビュー担当

**public 側のコード PR と同じ人がレビューする。** セキュリティ観点の担当を別に立てない。

リソース制約による判断であり、望ましい形ではない。同じ人が両方を見る以上、
**ゲートと 2 本の PR に分かれた構成が唯一の歯止めになる。**
§3-3 の「原則やり直し」を運用で緩めないこと。緩めた時点で歯止めが無くなる。

### 3-2. CI の役割と、レビュアの役割

| | 役割 |
|---|---|
| **CI** | 「ベースラインを更新せずに API を変えること」を防ぐ。それだけ |
| **レビュア** | 変更の妥当性を判断する。**private 側の `git diff` を見る** |

ベースラインを更新すれば差分は 0 になる。
**CI が緑なのは「台帳を更新した」という意味であって、「変更が妥当」という意味ではない。**
どの経路が増えたか・認証がどう変わったかは、private リポジトリの diff にしか出ない。

### 3-3. ゲートが落ちたとき

詳細は `tools/api-inventory/ci/README.md` §4。運用上の要点だけ:

| ゲート | 原則 |
|---|---|
| G1 / G2(認証デコレータの欠落・削除) | 意図的な公開なら**台帳に根拠を書いたうえで**ベースライン更新 |
| G3 / G4(認証のコメントアウト、config が危険側) | **原則やり直し。** 残すならコード中に理由を明記 |
| G8 / G9(未認証で書き込み系に到達、認可の回帰) | **原則やり直し** |
| reconcile B(台帳にあるが実機に無い) | `reconcile_allow.json` に**理由付きで**登録。理由なしの登録は禁止 |

**「とりあえず allow に入れて通す」を防ぐため、`reconcile_allow.json` は理由の文字列が必須。
レビューで理由を読むこと。**

#### 例外の承認者

**G3 / G4 / G8 / G9 の「原則やり直し」に対する例外は、RCOS 公開基盤チームリーダが承認する。**

- 承認は PR 上に記録を残す。口頭・チャットでの承認は無効
- 承認の記録には、なぜ安全と判断したかの根拠を書く
- 承認されたものは台帳側にも根拠を残す(次のバージョンで同じ議論を繰り返さないため)

承認者を定義しない「原則やり直し」は、実務では必ず形骸化する。

WARN(W1〜W6)はゲートを通すが、レビューでは見る。

---

## 4. CI の構成

| ワークフロー | いつ走る | 出すもの | 出さないもの |
|---|---|---|---|
| `api-inventory-drift` | PR / 手動 | 件数のみ、台帳ブランチ名 | URI・endpoint 名・台帳の中身 |
| `claude-pr-review` | PR / レビュー投稿時 / `@claude`(※) | 指摘と修正案 | — |
| `unit-tests` / `ui-tests` | PR | テスト結果 | — |
| `ci-images` | 呼び出し元から | ビルド済みイメージ | — |

※ `claude-pr-review` を**レビュー投稿と `@claude` で起動できるのは、
`author_association` が OWNER / MEMBER / COLLABORATOR の人だけ**
(CodeRabbit のレビューだけは例外として許可。裁定対象がそれ自身のため)。
public リポジトリなので、この条件が無いと無関係のアカウントが
30 分ジョブ・Claude 2 パスを何度でも起動でき、サブスクリプションの
トークンを消費できてしまう。

### 秘密情報

| Secret | 用途 |
|---|---|
| `API_INVENTORY_REPO` | 台帳の取得元 private リポジトリ |
| `API_INVENTORY_SSH_KEY` | weko-secret の **read-only deploy key** |
| `CLAUDE_CODE_AUTH_TOKEN` | Claude サブスクリプションの長期トークン |

- deploy key を使うのは、対象が 1 リポジトリに構造的に限定され、読み取り専用で、
個人アカウントに紐づかないため(PAT より事故時の影響が小さい)。
- **Secret は fork からの PR には渡らない。** `pull_request` イベントは GitHub が
fork PR に Secret を渡さない。`issue_comment` は base 側の文脈で走るため Secret が
使える状態でジョブが始まるが、`claude-pr-review.yml` は最初のステップ
(`Resolve PR`)で head repo を API で確かめ、fork ならそこで打ち切る。
Secret を step の env に置くのはその後(`Check token`)。この順序を崩すと
この節の保証が成り立たなくなるので、ステップを入れ替えないこと。
- 未設定ならジョブは何もせずスキップする。

---

## 5. PR レビューの運用

### 5-1. レビューの層

| 層 | 誰 | 見るもの |
|---|---|---|
| 1 | CodeRabbit | 差分全般 |
| 2 | Claude PR Review | **他レビューを裏取りして裁定**し、誰も挙げていない問題を補う(導入中) |
| 3 | 人間のレビュア | 上 2 つの裁定を判断する。API 台帳の diff を見る |

### 5-2. 自動レビューの扱い

- **無条件に信じない。** CodeRabbit も Claude も誤検知を出す。
- **無条件に無視しない。** 特に認可・破壊的操作・入力検証の指摘は、
誤検知より見逃しのほうが高くつく。
- 反論するときは**スレッドに理由を書く。** 書かずに resolve しない。

#### 自動レビューの指摘はマージのブロック条件ではない。ただし無視もしない

自動レビューの指摘は、必ずしも対応が必要なものばかりではない。
一方で**対応必要性の強い情報**であり、放置してよいものでもない。

**規則: すべての指摘に、何らかの反応を残す。**

| 判断 | 残すもの |
|---|---|
| 直す | 修正コミット |
| 直さない | **理由をスレッドに書いてから** resolve する |
| 判断が付かない | スレッドを開いたまま、判断できない理由を書く |

無反応のまま resolve する、あるいは放置してマージする、のどちらも不可。

### 5-3. スレッドを resolve する前に

**「解決済み」は「修正済み」ではない。**
返信なしで resolve されたスレッドは、直したのか判断を放棄したのか区別がつかない。

- 直したなら resolve してよい
- 直さないと決めたなら、**理由を書いてから** resolve する
- 議論の途中なら resolve しない

### 5-4. マージの条件

- `unit-tests` / `ui-tests` が緑
- `api-inventory-drift` が緑、**かつ**台帳ブランチ名の警告が出ていない
- **すべてのレビュー指摘に反応が残っている**(修正済み、または理由つきで却下済み)。
判断が付かず開いたままのスレッドがあるなら、それを承知でマージするかどうかを
PR 上で明示すること
- API を変えたなら private 側の台帳 PR がレビュー済み
- G3/G4/G8/G9 の例外を使うなら、RCOS 公開基盤チームリーダの承認が PR 上にある

---

## 6. 棚卸しとリリース

### 頻度

**全経路の棚卸しは WEKO バージョンアップ時に行う。** 定期(月次・四半期など)の棚卸しは設けない。
日々の変更は `api-inventory-drift` の CI が拾うため、そこで漏れたものをバージョンアップ時に回収する。

### リリース時の手順(要点)

1. private 側に WEKO3 と同名のブランチを作る
2. 新バージョンで `install.sh` → `snapshot.py` でベースラインを作り直す
3. `reconcile.py` の差分を 0 にする(新規経路を台帳に追加、消えた経路を整理)
4. `changed_rows.py` が出す行を Phase 2-3 で再確認する
5. private 側を commit し、**WEKO3 と同名のタグを打つ**

---

## 7. やってはいけないこと(チェックリスト)

- [ ] 台帳・ベースライン・調査記録を public リポジトリに commit する
- [ ] `fixtures.json` を commit する
- [ ] CI に URI や endpoint 名を出させる
- [ ] `reconcile_allow.json` に理由なしで登録する
- [ ] 台帳ブランチ名の警告が出ている PR を「PASS」と読む
- [ ] API を変えてベースラインを更新しない
- [ ] ベースラインを `install.sh` 以外の環境で作る
- [ ] レビュースレッドを理由を書かずに resolve する
- [ ] 自動レビューの指摘を無反応のまま放置してマージする
- [ ] G3/G4/G8/G9 の例外を、チームリーダの承認記録なしに通す
- [ ] 新しいリリースラインを切って private 側に同名ブランチを作らない
- [ ] タグを打たずに台帳だけ更新する

---

## 8. 用語

| 語 | 意味 |
|---|---|
| **台帳** | `weko3_api_list_full.tsv`(57列) / `weko3_api_list.tsv`(24列)。API の棚卸し結果 |
| **ベースライン** | `api_snapshot.json`。実機の `url_map` から取った経路のスナップショット |
| **private リポジトリ** | `RCOSDP/weko-secret`。台帳とベースラインの置き場所 |
| **ゲート** | CI を FAIL させる条件(G1-G9、reconcile A-E) |
| **プロファイル** | config による blueprint 登録の分岐に対応した測定条件。比較は同一プロファイル同士で行う |

---

## 9. 決定の記録

| 決定日 | 項目 | 決定 |
|---|---|---|
| 2026-09-01 | 台帳更新 PR のレビュー担当 | public 側と同じ人。別担当を立てるリソースが無い(§3-1a) |
| 2026-09-01 | G3/G4/G8/G9 の例外承認者 | RCOS 公開基盤チームリーダ。PR 上に根拠つきで記録(§3-3) |
| 2026-09-01 | 自動レビュー指摘の位置づけ | マージのブロック条件にはしない。ただし対応必要性の強い情報として、全指摘に何らかの反応を残す(§5-2) |
| 2026-09-01 | 棚卸しの頻度 | WEKO バージョンアップ時。定期棚卸しは設けない(§6) |
| 2026-09-01 | 本書の置き場所 | `docs/OPERATIONS.md` |

### 積み残し

- private リポジトリ(`RCOSDP/weko-secret`)側にも本書を置くかどうかは未決。
現状は public 側のみ。
- `claude-pr-review` は導入中。数 PR 運用したうえで、§5-2 の扱いを見直す余地がある。
Loading
Loading