# 指示書Q — `prisma/schema.prisma` を最新DDL（0909）に追従させ、再シードする

| 項目 | 内容 |
|---|---|
| 実行環境 | ★**Cursor 内の Claude が実装します**★（`.claude/commands/d-watch.md` の役割分担表を参照） |
| 実行状態 | ★**実行済み**★（D-096。段階0〜7すべて完了。`origin/develop` へ push 済み） |
| 実行順 | ★**指示書P（第2歩・D-Sec）の前提**★。★指示書P は段階1 で止まっている★。本指示書を終えてから指示書P を段階1 から再開する。★同時に走っている未実行の指示書は 指示書I（`lib/auth/`）／指示書J（`lib/settings/`）★ だが、★`docs/decisions.md` / `docs/handoff.md` は共通で触る★ため ★**同時に走らせないこと**★ |
| 取得する決定番号 | ★**着手直前に `grep -n "^### D-0" docs/decisions.md \| tail -3` で最終番号を実測すること**★。★作成時点の最終は `D-095`（`docs/decisions.md:3978`）なので `D-096` の見込み★。★D-068 / D-089 で二重採番が実際に起きている。必ず自分で確認★ |
| 前提 | ★**D-094**★（`docs/decisions.md:3822`。最新DDL の照合結果。★率13列＋面積10列＝計23列の型変更★） / ★**D-095**★（`:3978`。`dwatch_local` を最新DDL から作り直した。★全テーブル0行★） / **D-056**（`:353`。`schema.prisma` を手で書き換えない） / **D-059**（`:392`。実DDL を正とし `db pull` の生成結果を採用する） / **D-086**（`:2814`。第1歩の実行記録。★Edge Runtime バンドル破壊の地雷★） / **D-050**（`:308`。通ってからコミット） |
| 手順の骨格 | ★**`docs/handoff/指示書E_スキーマを実DDLに一致.md`（211行）**★。★特に手順3（`db pull` が出力しないものを手で戻す。`:92-136`）と手順4（Laravel 基盤10テーブルを削除しない。`:139-156`）を全文読むこと★ |
| 段階数 | ★**8段階**★（段階0〜段階7） |
| 作成 | 2026-09-09（`docs/handoff.md` の最新は **追記25**（`docs/handoff.md:2061`）） |

> 実行後はこの表と、文書末尾の「実行状態」表を更新してください。

---

## ★★冒頭に読むべきこと — 本指示書の作成中に `db pull` が実行された★★

★本指示書の作成調査中（2026-09-09 19:10）に、作業ツリーの `prisma/schema.prisma` が
**すでに `db pull` で上書きされていました**★（実測: mtime `2026-09-09 19:10:39`、モデル数 39、
★**コメント 0行**★）。★**つまり段階2 の「控えを取る」は手遅れです。ただし失われていません。**★

| 事実 | 根拠 |
|---|---|
| ★`db pull` 前の `schema.prisma` は **HEAD にコミット済み**★ | `git log -1 -- prisma/schema.prisma` → ★`d20be80`★（D-050。指示書E の実行コミット） |
| ★したがって **101行のコメントは `git show HEAD:prisma/schema.prisma` から完全に復元できる**★ | 実測: HEAD 版のコメント行数 ★101★ / 作業ツリー版 ★0★ |

★**帰結: 段階2 は「控えを取る」ではなく「HEAD から移植し直す」に読み替えてください。**★
★`git checkout` / `git restore` で戻してはいけません★（`db pull` の成果である型変更まで消えます）。

---

## 背景

- ★2026-09-09 に最新DDL `clean_watch_20260909.sql` を受領した（D-094）★。
  ★率カラムが `tinyint unsigned` → `double(4,1)`、面積が `decimal` → `double` に変わった。計23列★
- ★同日、`dwatch_local` をその DDL から作り直した（D-095）★。
  ★39テーブル / FK48本 / typo ゼロ / 受領DDLと列レベルで完全一致 / **全テーブル0行**★
- ★`prisma/schema.prisma`（HEAD 版）は 2026-09-03 に 09-02版から `db pull` した生成物で、型が古い★
- ★指示書P（第2歩・D-Sec）が段階1 で止まっている★。★本指示書はその再開の前提★

## この指示書の目的

★`prisma/schema.prisma` を最新DDL に追従させ、再シードして、指示書P を再開できる状態に戻すこと★。

---

## 段階0: 前提の確認（読むだけ・コミットなし）

読むもの:

- ★`docs/decisions.md` の **D-094**（`:3822`）★ — ★何の型がどう変わったか★
- ★**D-095**（`:3978`）★ — ★`dwatch_local` を作り直した経緯。特に「6. Cursor に引き継ぐこと」（`:4023`付近）★
- **D-056**（`:353`） / **D-059**（`:392`） — ★生成物を正とする / 実DDL を正とする★
- ★`docs/handoff/指示書E_スキーマを実DDLに一致.md` の **手順3**（`:92-136`）と **手順4**（`:139-156`）★

確認するもの:

- ★作業ツリーに Cursor の未コミット分がある★（実測: `lib/format/date.ts` / `scripts/seed-local-db.ts` の
  変更、`lib/db/ds-status.ts` / `lib/db/__tests__/ds-status.test.ts` /
  `lib/format/__tests__/date.test.ts` の未追跡）。
  ★**これらは失われていません。消さないこと・戻さないこと**★（指示書P の成果物）
- ★`dwatch_local` は作り直し済みで空★（D-095）。★このDBに `db push` / `migrate` をしないこと★
- ★`prisma db pull` の接続先は `prisma7.config.ts` が `DATABASE_URL` から読む★
  （★実測: `prisma7.config.ts:17-19` の `datasource: { url: process.env["DATABASE_URL"] }`。
  `DATABASE_URL` は `.env.local:7`。`prisma7.config.ts:8` で `.env.local` を明示的に読んでいる★）。
  ★接続先が `dwatch_local` であることを目視で確認してから `db pull` すること★

### この段階の完了条件

上記をすべて読み、★作業ツリーの未コミット分の一覧を自分の目で確認した★こと。コミットは無し。

---

## 段階1: ★一時スクリプトを削除する★

- ★`scripts/_tmp-check-columns.ts` と `scripts/_tmp-fix-typo-columns.ts` を削除する★
- ★理由★: ★役目を終えた（typo は `dwatch_local` の陳腐化が原因で、作り直しにより解消。D-095 項2）★。
  ★特に後者は ALTER を実行するので、残すと事故のもとになる★
- ★どちらも未追跡ファイルなので `git rm` ではなく単純削除でよい★

> ★**注記（実測 2026-09-09 19:11）**★: ★`scripts/` の中身は `seed-local-db.ts` **1本だけ**で、
> 一時スクリプト2本は**すでに存在しません**★。★その場合この段階はスキップし、
> 「着手時点で既に削除済みだった」と実行状態表に記録してください★。

### この段階の完了条件

`git status` に `_tmp-` が出てこないこと。`ls scripts/` に `_tmp-` が無いこと。

---

## 段階2: ★`db pull` の結果に、HEAD からコメントを移植し直す★

★指示書E の手順1・2（`:69-91`）に従うこと★。ただし ★冒頭の「読むべきこと」のとおり、
`db pull` は**すでに実行済み**★なので、実際にやるのは移植です。

### 2-1. `db pull` が未実行だった場合のみ実行する

```
npx prisma db pull
```

- ★`--force` は付けないこと★（enrich が働かず、PascalCase モデル名と `@@map` が捨てられる。指示書E `:86`）
- ★`--print` で新規ファイルへ出す方式も取らないこと★（同じ理由）
- ★期待: モデル数 39 のまま★（実測: 作業ツリー版 39 / HEAD 版 39）

### 2-2. ★★最大の落とし穴 — コメント101行の移植★★

★`db pull` はコメントを保持しません★。★現行 HEAD の `prisma/schema.prisma` には **101行のコメント**が
あります★（実測）。TeamWorks の回答内容・確認中の項目（A-1 / A-2 / A-3）・
「実DDL確認済み」の注記など、★**再取得できない情報が含まれます**★。

★手順★:

1. ★控えを取り出す★ — `git show HEAD:prisma/schema.prisma > <リポジトリ外の作業パス>/schema.head.prisma`
   （★`docs/` に置かないこと★。成果物と混ざる。指示書E `:75`）
2. ★控えと作業ツリーを diff しながら、コメントだけを作業ツリー側へ移植する★
3. ★★移植後に行数を数えて確認する★★ —
   `grep -c "^\s*//" prisma/schema.prisma` が ★**101 から大きく減っていないこと**★
   （増えるのは構わない。段階2-4 で冒頭コメントを更新するため）

> ★移植して**はいけない**もの★: ★型・`@db.*` 属性・`@default` — これらは `db pull` の生成結果が正★（D-056）。
> ★移植するのはコメント（`//` 行）だけ★。

### 2-3. ★`@updatedAt` と `@default(now())` を DDL で確かめて戻す★

★`@updatedAt` は Prisma 固有の属性なので `db pull` は出力しません★（指示書E 手順3-1、`:96-121`）。
★enrich が既存分を引き継ぐことはありますが、**全部は引き継ぎません**★。

★実測（2026-09-09）★: ★HEAD 版の `@updatedAt` は **24箇所**、`db pull` 後の作業ツリーは **20箇所**★。

★受領DDL を自分で grep して判断すること。推測で付けないこと★:

```
awk '/^CREATE TABLE/{t=$3} /ON UPDATE current_timestamp/{print t, $1}' \
  "C:\Users\daich\Downloads\clean_watch_20260909.sql" | sort -u
```

★実測結果: `ON UPDATE current_timestamp` を持つのは **20テーブル / 21列**★
（`clean_link_schedules` / `clean_schedules` / `clean_statuses` / `clean_task_reports` /
`clean_timetables` / `control_reports` / `controls` / `customer_contacts` / `customer_summaries` /
`customers` / `devices` / `facilities` / `facility_summaries` / `groups` / `link_schedules` /
`robot_error_reports` / `robot_task_versions` / `robots` / `sections` の `updated_at`、および
★`security_statuses` は `updated_at` と `reported_at` の**2列**★）。

★突き合わせた結果（実測。**着手時に必ず取り直すこと**。作業ツリーは Cursor が編集中で動いている）★:

| 対象 | 判断 |
|---|---|
| ★`CleanTaskReport.updated_at`★ | ★DDL に `ON UPDATE` あり／作業ツリーに `@updatedAt` **なし** → **付け直す**★ |
| `FacilityContact.updated_at` | ★DDL に `ON UPDATE` **なし** → 付けない★（HEAD 版には付いていたが、DDL が正） |
| `SectionRobotStatus.updated_at` | ★DDL に `ON UPDATE` **なし** → 付けない★（同上） |

★`@default(now())` も同様に、DDL の `DEFAULT current_timestamp()` の有無と突き合わせること★。
★判断した結果はその場にコメントで残す★（指示書E `:112-117`。次に `db pull` した人が同じ grep を
やり直さずに済むように）:

```prisma
// 実DDL確認済み(0909): updated_at に ON UPDATE CURRENT_TIMESTAMP が無いため @updatedAt は付けない
```

### 2-4. ★冒頭コメントを更新する★

★指示書E 手順3-3（`:129-137`）の項目を、今回の値に書き換えること★:

- ★元DDL: `clean_watch_20260909.sql`★ / ★受領日: 2026-09-09★ / ★`db pull` 実施日: 2026-09-09★
- ★投入先のローカルDB名: **`dwatch_local`**★ — ★**今回は `dwatch_ddl` ではありません**★
- ★D-094（23列の型変更）と D-095（`dwatch_local` の作り直し）への参照★
- ★`datasource db` ブロックの「Prisma 7 では接続URLを書けない」コメント（HEAD 版 `:8-9`）も
  `db pull` で消えている。これも戻すこと★
- 既存の記述（D-056 / D-059 / 命名の経緯 / 確認中3件）は ★そのまま残す★

### 2-5. ★Laravel 基盤10テーブルを削除しないこと★

`users` / `sessions` / `jobs` / `migrations` / `cache` / `cache_locks` / `failed_jobs` /
`job_batches` / `password_reset_tokens` / `personal_access_tokens`

★削除すると `db pull` のたびに再追加され、本当の変更が差分ノイズに埋もれます★（指示書E `:139-154`）。
★末尾にまとめ、区切りコメントで「参照しない」と明記する★。
★`clean_link_schedules` も同様に削除せず、モデル直上に不使用の旨を書く★（D-058）。

### この段階の完了条件

1. ★`npx prisma validate` が通る★
2. ★モデル数が 39★（`grep -c "^model " prisma/schema.prisma`）
3. ★コメント行数が 101 から大きく減っていない★
4. ★`@updatedAt` の数と位置が、DDL の `ON UPDATE current_timestamp`（20テーブル/21列）と一致する★
5. Laravel 基盤10テーブルと `clean_link_schedules` が残っている

---

## 段階3: ★生成とビルドの追従★

```
npx prisma generate
npx tsc --noEmit
npm run lint
npm test
```

- ★型変更で落ちる箇所を直す★
- ★予想される変化★: `Decimal` → ★`Float`★、`Int @db.UnsignedTinyInt`（率）→ ★`Float`★
- ★ただし**実際の生成結果を確認すること**★。★`db pull` が `double(4,1)` をどう表現するかは推測しない★
  - ★実測（作業ツリー）★: ★`clean_ratio` / `task_area` / `clean_area` /
    `operation_ratio` / `launch_ratio` / `error_ratio` はすべて ★`Float`（`@db.*` 属性なし）★★。
    ★MySQL コネクタでは `Float` の既定が `Double` なので属性が出力されない★
- ★現時点でアプリコードは面積・率のカラムを参照していない見込み★
  （`prismaSource` は `facilities()` / `schedules()` のみ実装済み。D-086）★なので落ちない可能性もある★
- ★★落ちなかった場合も、それを記録すること★★（「型は変わったがアプリコードは未参照だった」）

### この段階の完了条件

★`npx tsc --noEmit` エラー0 / `npm run lint` 0 / `npm test` 全パス★。
★着手直前に自分で測った基準値からテスト数が減っていないこと★（D-050）。

> ★段階1・段階2・段階3 は**まとめて1コミットにしてもよい**★（★実装者判断★）。
> ★分ける場合も、`npx prisma validate` / `tsc` / `lint` / `test` が通ってからコミットすること★（D-050）。

---

## 段階4: ★再シード★

```
npm run seed:local
```

（★`package.json:12` の `"seed:local": "tsx scripts/seed-local-db.ts"`★）

★シードは冪等に作られている★ので、そのまま流せるはずです。

### ★★確認すること★★

- ★`dwatch_local` が 28 → 39テーブルになったので、シード対象外のテーブルが増えている★。
  ★シードが「知らないテーブル」で落ちないこと★
- ★型が変わった列（`clean_ratio` など）にシードが値を入れているなら、`double` で通ること★
- ★件数★（★`scripts/seed-local-db.ts:441-450` の完了ログで確認できる★）:

| テーブル | 期待件数 |
|---|---|
| `groups` / `customers` | ★1 / 1★ |
| `devices` | ★1★ |
| `facilities` | ★12★ |
| `sections` / `robots` | ★14 / 14★ |
| `clean_schedules` | ★12★ |

★これは D-086 / D-087 時点の実測値です。★着手時に指示書M・指示書P の記録で確認すること★★。
★`clean_schedules` は fixtures 13件中1件が意図的にスキップされる★
（`scripts/seed-local-db.ts:162-173`。★スキップ件数が想定と違うと例外で止まる設計★）。

- ★指示書P の段階1 が追記した D-Sec のシード（`controls` / `control_reports` /
  `control_error_histories`）が未コミットの作業ツリーに入っている★
  （`scripts/seed-local-db.ts:185-227`。★施設12 の `DS-012` はシードから除外。着手前確認A案★）。
  ★これが流れるかも確認すること★。★落ちるなら**指示書P 側の問題として切り分けて報告する**★
  （★本指示書で `scripts/seed-local-db.ts` を直さないこと★）

### この段階の完了条件

シードが例外なく完走し、件数が上表と一致すること。

---

## 段階5: 動作確認

- ★`npm run dev` を Bash で起動しないこと。Browser pane の `preview_start` を使う★
- ★Browser pane が黒画面 / 0×0 になる既知の問題★: ★`preview_start` に `url` を渡して開き直す★

### 5-1. ★`USE_FIXTURES=true`（既定。`.env.local:2`）で回帰が無いこと★

- ★`/dashboard` が「9 / 10 完了」★（D-090 項の確認項目7 と同じ。`docs/decisions.md:3306`）
- 全画面が従来どおり表示される
- ★`read_console_messages` でエラー0件★

### 5-2. ★`USE_FIXTURES=false` で第1歩の成果が保たれていること★

- ★`/facilities` と `/schedules` が 200 で表示される★
- ★施設12「フレッシュタウン湖畔店」が**ロボット0台・スケジュール0件**で出ること★
- ★他画面が 500 になるのは想定どおり★（未実装のメソッドがある）。
  ★**404 が出たら Edge Runtime バンドル破壊の回帰を疑うこと**★（D-086 段階5）

### この段階の完了条件

上記がすべて確認でき、★`USE_FIXTURES` を `true` に戻した★こと。

---

## 段階6: 記録と push

### 6-1. `docs/decisions.md` に追記

★着手直前に `grep -n "^### D-0" docs/decisions.md | tail -3` で最終番号を実測すること★。
★作成時点の最終は `D-095` なので `D-096` の見込み★。

記録すること:

1. ★`db pull` をやり直した経緯★（D-094 の23列の型変更 / D-095 の `dwatch_local` 作り直し）
2. ★型が実際にどう変わったか★（★生成結果の実測。推測ではなく★）
3. ★アプリコードに影響が出たか出なかったか★（★出なかった場合もその旨を明記★）
4. ★コメントの移植で失われたものがあれば明記★（移植前後の行数も）
5. ★`@updatedAt` / `@default(now())` の判断結果★（DDL grep の結果と、付けた／付けなかった箇所）
6. ★一時スクリプト2本を削除したこと★（★着手時点で既に無かった場合はその旨★）
7. ★再シードの件数（実測）★

### 6-2. `docs/handoff.md` に追記

★最新は追記25（`docs/handoff.md:2061`）★なので ★追記26★ の見込み（★着手時に確認すること★）。

### 6-3. コミットと push

★`git add` は必ずファイルパスを明示。`git add -A` は禁止★（`CLAUDE.md` §7。★過去に事故が起きている★）。

★★このコミットに含めてよいのは次の3つだけです★★:

| 含める | 含めない |
|---|---|
| ★`prisma/schema.prisma`★ | ★`lib/db/ds-status.ts` / `lib/db/__tests__/ds-status.test.ts`★ |
| ★`docs/decisions.md` / `docs/handoff.md`★ | ★`lib/format/date.ts` / `lib/format/__tests__/date.test.ts`★ |
| ★本指示書（実行状態表の更新）★ | ★`scripts/seed-local-db.ts`★ |

★右列は**指示書P の作業分**です。巻き込まないこと★。
★`lib/generated/prisma` は `.gitignore:44` で追跡外なのでコミット対象外★（実測）。

```
git push origin develop
```

### この段階の完了条件

★`origin/develop` へ push 済み★。★`git status` に指示書P の未コミット分が**そのまま残っている**こと★。

---

## ★段階7: 指示書P へ引き継ぐ★

- ★`docs/handoff/指示書P_ローカルDBで動かす第2歩_DSec.md` の冒頭メタ表と末尾の実行状態表に、
  「★スキーマを 0909 DDL に追従させ再シード済み。段階1 を再開できる状態になった★」旨と、
  本指示書で取得した決定番号を記録する★
- ★指示書P の段階1 から再開する★
- ★この段階の完了条件★: 指示書P の実行状態表が更新されていること

---

## ★禁止事項★

| # | 禁止 | 理由 |
|---|---|---|
| 1 | ★`prisma/schema.prisma` を手で書き換えること★ | D-056。★コメントの移植と `@updatedAt` / `@default(now())` の復元だけが例外★ |
| 2 | ★`git checkout` / `git restore` で `prisma/schema.prisma` を HEAD に戻すこと★ | ★`db pull` の成果（23列の型変更）まで消える★。★控えは `git show HEAD:...` で**読むだけ**★ |
| 3 | ★Laravel 基盤10テーブルを削除すること★ | 指示書E 手順4。★`db pull` のたびに再追加され差分ノイズになる★ |
| 4 | ★`prisma migrate` / `db push` を使うこと★ | ★`dwatch_local` を実DDL の姿から乖離させる★（D-086 項3） |
| 5 | ★`dwatch_ddl` / `dwatch_ddl_0907` / `dwatch_ddl_0909` に触れること★ | ★照合用の参照専用★（D-094 / D-095） |
| 6 | ★TeamWorks 側の本番DBに接続すること★ | `CLAUDE.md` §7 |
| 7 | ★`git add -A` を使うこと★ | ★Cursor の未コミット作業を巻き込む。過去に事故が起きている★ |
| 8 | ★`lib/db/ds-status.ts` / `lib/format/date.ts` / `scripts/seed-local-db.ts` の未コミット分を消す・戻す★ | ★指示書P の成果物★ |
| 9 | ★コメントの移植を省略すること★ | ★101行あり、再取得できない情報を含む★ |
| 10 | ★`npm run dev` を Bash で起動すること★ | ★Browser pane の `preview_start` を使う★ |

## ★着手前確認★ — ★なし★（すべて回答済み）

---

## 完了条件（総括）

1. 一時スクリプト2本が無い
2. ★`npx prisma validate` が通り、モデル数 39、コメント行数が 101 から大きく減っていない★
3. ★`@updatedAt` が DDL の `ON UPDATE current_timestamp`（20テーブル/21列）と一致し、判断根拠がコメントにある★
4. ★冒頭コメントが `clean_watch_20260909.sql` / 2026-09-09 / `dwatch_local` に更新されている★
5. ★`npx tsc --noEmit` 0 / `npm run lint` 0 / `npm test` 全パス（テスト数が減っていない）★
6. ★`npm run seed:local` が完走し、件数が想定どおり★
7. ★`USE_FIXTURES=true` で回帰なし（`/dashboard` が「9 / 10 完了」・コンソールエラー0）★／
   ★`USE_FIXTURES=false` で `/facilities` / `/schedules` が動く（404 が出ない）★／★最後に `true` に戻した★
8. `docs/decisions.md` / `docs/handoff.md` / 指示書P の実行状態表 / 本文書の実行状態表 を更新した
9. ★`origin/develop` へ push 済み。指示書P の未コミット分が残っている★

---

## 実行状態

| 段階 | 状態 | コミット |
|---|---|---|
| ★**着手前の確認**★ | ★**なし**★ | — |
| 段階0 前提の確認 | 完了 | コミットなし |
| 段階1 一時スクリプトの削除 | 完了（着手時点で既に削除済みだった） | コミットなし |
| 段階2 `db pull` とコメントの移植 | 完了 | 本コミット |
| 段階3 生成とビルドの追従 | 完了（型変更でアプリコードは落ちなかった） | 本コミット |
| 段階4 再シード | 完了 | コミットなし（`dwatch_local` へのデータ投入。git管理外） |
| 段階5 動作確認 | 完了（Browser pane 無し。curl で代替） | コミットなし |
| 段階6 記録と push | 完了 | 本コミット |
| 段階7 指示書P へ引き継ぐ | 完了（D-096 §10 に記録） | 本コミット |

**実行日**: 2026-09-09
**取得した決定番号**: D-096（`docs/decisions.md:4102`）
**着手前の実測値**（`npm test` / `tsc` / `lint`）: 33ファイル / 631テスト・0・0
**一時スクリプト2本の有無**: 着手時点で既に削除済み（`scripts/` は `seed-local-db.ts` 1本のみ）
**コメント行数（移植前 / 移植後）**: 101行 → 153行
**`@updatedAt` の増減と根拠**: HEAD版24箇所 → 0909実DDL grep（20テーブル/21列）に合わせて21箇所に。
  `CleanTaskReport.updated_at` に新規で付与（0909で `ON UPDATE current_timestamp()` が追加されたため）。
  詳細は D-096 §3
**型変更でアプリコードが落ちたか**: 落ちなかった（`prismaSource` は型が変わった23列を未参照）
**再シードの件数**: `groups=1 customers=1 devices=1 facilities=12 sections=14 robots=14 clean_schedules=12
  controls=11 control_reports=14 control_error_histories=5`（2回連続で同一。冪等性確認済み）
**詳細**: `docs/decisions.md` D-096 を参照
