**公開前に、存在しない話への 301 だけ絞り込むことを勧めます。** 条件の範囲と処理順は概ね適切で、提示された差分自体に転送ループはありません。

以下は提示された差分・設定・検証結果に基づくレビューです。実際のビルド成果物や既存の転送設定までは確認していません。

### A1. 転送条件：✅ OK

完全一致と正規表現で、対象を十分限定できています。

| リクエスト | この追加処理での結果 |
|---|---|
| `/manga/ep9` | `/manga/ep09` へ301 |
| `/manga/ep90` | 対象外 |
| `/manga/ep09` | 対象外 |
| `/manga-archive` | 対象外 |
| `/manga/ep9/` | 対象外 |
| `/prototype6/` | `/series6` へ301 |
| `/prototype7`・`/prototype10` | 対象外 |
| `/prototype1/foo` | 対象外 |

`url.pathname` で判定するためクエリは条件に影響せず、`to.search = url.search` で保持されます。転送先は固定の同一オリジン内パスなので、クエリで外部サイトへ転送先を差し替える問題もありません。

`/manga/ep9/` を対象外にするのは、今回の表どおりです。末尾スラッシュ付きも救済したくなった場合だけ、話数の正規表現を `\/?$` に変更してください。

### A2. 転送ループ：✅ OK／実環境の追加転送は要確認

今回の転送先は、すべて `movedTo()` の条件から外れます。**この差分内ではループしません。**

`auto-trailing-slash` は、たとえば `foo.html` なら `/foo`、`foo/index.html` なら `/foo/` を正規形とします。そのため、成果物によっては次の追加転送が起きますが、ループではありません。[Cloudflare公式資料](https://developers.cloudflare.com/workers/static-assets/routing/advanced/html-handling/)

```text
/manga → /manga-archive → /manga-archive/ → 200
```

公開前には、実アセットを使って各転送先の最終応答が200になることを確認してください。正規形がスラッシュ付きなら、最初からそこへ転送すると1回で済みます。別途 `_redirects` や Cloudflare のルールがある場合、その逆向き転送も確認対象です。

### A3. 存在しない話への301：⚠️ 要注意・公開前の修正推奨

該当行は次です。

```js
const m = path.match(/^\/(manga|english-4-koma)\/ep([1-9])$/);
```

これは、ページの存在に関係なく両言語の1〜9話を転送します。

`301 → 404` はプロトコル上のエラーではありません。ただし、**「転送前と結果は同じ」なのは最終的に404になる点だけ**です。通信が1回増え、存在しない住所への恒久転送を記憶させる可能性があります。今回の「行き先がはっきりしているものだけ」という方針にも合いません。

**存在する話の番号だけを許可する修正を推奨します。** 8話分・6話分という件数だけでは連番とは断定できないため、実際の番号を列挙するのが確実です。

```js
if (m && EXISTING_EPISODES[m[1]].has(m[2])) {
  return `/${m[1]}/ep0${m[2]}`;
}
```

`EXISTING_EPISODES` は実在する番号の集合として定義します。毎リクエスト `env.ASSETS.fetch()` で存在確認する必要はなく、静的サイトなら明示リストかビルド時生成で十分です。

### B1. 既存処理への影響：⚠️ 基本は維持、記録とヘッダーに差分あり

- **`/api/`・`/media/`：✅ OK**  
  先に既存の `route()` へ返すため、今回の判定は通りません。
- **`/pixelstomotors/`：✅ OK**  
  旧形式の転送が先に動きます。たとえば `/pixelstomotors/manga` は `/manga` を経由して `/manga-archive` へ進む複数段転送になりますが、既存動作を壊してはいません。
- **静的アセット：✅ OK**  
  対象外のパスは、従来どおり元の `request` を `env.ASSETS.fetch()` に渡します。
- **クローラー記録：⚠️ 意図した観測ができなくなる**  
  元の住所へのアクセスは記録されません。追従先へのアクセスは記録され得ますが、どの旧住所から来たかは分からなくなります。配信上の問題はありませんが、今回の改善効果を測りたいなら、旧パス・転送先・301を記録する価値があります。記録失敗で転送を止めない方針は維持してください。
- **レスポンスヘッダー：⚠️ 確認対象**  
  新しい `Response.redirect()` は `secured()` を通りません。既存の静的レスポンス側でも共通ヘッダーを付けているなら、新しい301にはそのヘッダーが付きません。`secured()` の中身が未提示なので、必要なものがあるか確認してください。

### B2. 301の選択：✅ OK／戻す際は要注意

確認済みの旧住所から対応する現行ページへの移転なので、301で適切です。Googleも恒久転送を、転送先を正規URLとする強いシグナルとして扱います。[Google公式資料](https://developers.google.com/search/docs/crawling-indexing/301-redirects)

ただし301はキャッシュされ得ます。コードを戻しても、ブラウザが旧住所を再取得せず転送を続ける場合があります。検索エンジン側の評価更新にも再クロールが必要です。[HTTP仕様](https://www.rfc-editor.org/rfc/rfc9110.html#section-15.4.2)

戻す可能性が具体的にある住所だけは302を検討できますが、今回の確定した移転をすべて302にする必要はありません。存在しない話を除外してから301を出すのが適切です。

### C1. その他の住所の判断：✅ OK／追加は根拠があるものだけ

`/ai-agent` や `/files/LOG395/{c}` を404のままにする判断は妥当です。対応する内容がない住所を一覧やトップページへ一括転送する必要はありません。

追加候補は `/record/precision-is-not-learning/` です。現コードでは末尾スラッシュ付きは対象外なので、アクセス実績があるか、旧ページの住所として使っていた根拠があれば完全一致表に追加してください。

大文字小文字・二重スラッシュ・任意の番号などへ、推測だけで条件を広げる必要はありません。

### 公開してよいか

**存在しない話への転送を除外し、実アセットで転送先の200を確認できれば、公開してよいと判断します。**

公開前に対応する項目は次のとおりです。

1. **修正推奨：** 話数の転送を、実在する番号に限定する。
2. **確認必須：** 実アセットで末尾スラッシュ処理を含む転送全体を追い、最終200・ループなしを確認する。
3. **運用判断：** 旧住所のアクセス記録を残すか、301にも共通ヘッダーが必要かを決める。

完全一致表と `/prototype1〜6` の正規表現には、提示情報の範囲で公開を妨げる問題はありません。
