担当: Claude Code(サブエージェントで実装し、監督がレビューする)。範囲は API まで(画面は次の指示書)。 決定の記録は D-184(案は本書 §9。docs/decisions.md には別セッションの未コミット差分があるため、その commit 後に追記する)。
/errors)でエラー内容をセレクトリストから選べるようにする。 選択肢はスプレッドシート「PUDUエラー一覧_20261016」の「PUDUエラー 決定稿」シート(131行。A列 = ID、C列 = エラー分類(main ja)、G列 = エラー詳細(日))。 「その他」を選んだときは備考欄に手入力。セレクトリストはエラー分類で絞れる。error_lists(管理側UIなし): id bigint unsigned pk AI / error_category_main_en varchar(100) / error_category_main_ja varchar(200) / error_category_sub_en varchar(100) / error_category_sub_ja varchar(200) / error_detail_en text / error_detail_ja text / inactive tinyint unsigned 既定0 / created_at / updated_at / deleted_at(すべて timestamp)。★Pudu の error_type の列は無い★robot_error_reports.error_list_id bigint unsigned(定義書は必須○・既定値なし・FK なし・索引なし)error_lists は先方で作成済み。★こちら(DFA)が ID で選んで登録し、名前は ID で DB から引く★(先方が自動で入れる列ではない)SHOW GRANTS で確認する★(未確認)NOT_STARTED)の行にも出す★(制御盤 D-S_CONTROL_FAILURE・セキュリティ SECURITY_ON の行には出さない — 監督の提案「ロボットのエラーの行だけ」に清掃開始失敗を足した決定と読む)/★その他は備考必須★d-watch-api.yaml の★関係する全経路★(/errors・/errors/{error_id}/status・新設・スキーマ)を直すnpx tsc --noEmit・npm run lint・npx vitest run の件数を報告(基準: 139 files / 3284 tests)prisma db push / migrate / db pull を実行しない★(.env.local はステージングを指している。スキーマ変更は TeamWorks の領域。CLAUDE.md §7)。npx prisma generate は DB に触らないので可git add -A 禁止★。★docs/decisions.md・docs/handoff/指示書AY_*・docs/handoff/設計_制御盤ログの取り出し_* は別セッションの未コミット差分 — 触らない★t() に通さない・変換しない(D-077 と同じ。日英は DB の列を出し分ける)/prechecks/{id}/status と D-Sec(同じ PATCH を使う lib/ds-alerts/edit.ts)から error_list_id を書ける経路を作らないd-watch-api.yaml を先に直す)GET /error-lists(tags: masters)inactive = 0 かつ deleted_at IS NULL の行だけ★。並びは ★id の昇順★meta は /groups と同じ書き方(total = 件数、page = 1、per_page = 件数)。クエリパラメータなし{ items: ErrorListItem[], meta }ErrorListItem: id(integer) / error_category_main_en / error_category_main_ja / error_category_sub_en / error_category_sub_ja / error_detail_en / error_detail_ja(すべて string。DB の値のまま)/ note_required(boolean。この選択肢を選ぶと備考が必須。lib/config の ERROR_LIST_NOTE_REQUIRED_IDS)ErrorReportItem に3項目を追加(required に入れる)error_list_id: integer, nullable。DB の値のまま。null = 未選択error_list: ErrorListItem, nullable。error_list_id の名前解決。★無効化・削除済みの行でも解決する★(施設名と同じく名前解決は絞らない)。 error_list_id が null、または error_lists に無い id なら null(画面は前者を「未選択」、後者を「不明(id)」と出す)error_list_selectable: boolean。この行でエラー内容を選べるか。error_type が ERROR_LIST_UNSELECTABLE_ERROR_TYPES(D-S_CONTROL_FAILURE・SECURITY_ON。完全一致)なら false、それ以外は true。★画面は error_type を見ずにこれだけを見る★(CLAUDE.md §9.6)PATCH /errors/{error_id}/status の本文に error_list_id を追加details は既存の書式。フィールドは error_list_id / note):
error_list_selectable が false → 422error_lists に無い、または inactive ≠ 0、または deleted_at が非 NULL → 422error_list_id が ERROR_LIST_NOTE_REQUIRED_IDS に入り、★適用後★の備考が空(null または空白だけ)なら 422(その他を選んで備考を書かない/既にその他の行で備考を消す、の両方)。 ★状態だけを変える要求には掛けない★・★選べない行(error_list_selectable が false)には掛けない★ (レビュー指摘で監督が判断 2026-10-27: /prechecks は error_list_id を見ずに備考を消せるので、「その他・備考なし」の行はアプリ自身が作れる。 そこで状態だけの保存まで 422 にすると、触っていない備考が理由で止まり、アラート画面と食い違う)isEmptyPatch)に error_list_id を含めるErrorReportItem(新3項目を含む)robot_error_reports の5列(status / comment / responded_at / resolved_at / error_list_id)★。error_list_id は★この経路だけ★。 control_error_histories は従来どおり(今回触らない)lib/config/index.ts)ERROR_LIST_NOTE_REQUIRED_IDS: readonly number[] = [131](決定稿の「OTHER ERROR / その他(該当なし)」。ID は基本固定・追加変更ありうる — ユーザー回答④)ERROR_LIST_UNSELECTABLE_ERROR_TYPES: readonly string[] = ["D-S_CONTROL_FAILURE", "SECURITY_ON"](ユーザー判断 2026-10-27。NOT_STARTED は選べる)prisma/schema.prisma(★db pull できないための手書き★)ErrorList モデル(@@map("error_lists"))を定義書どおりに足す。id BigInt @id @default(autoincrement()) @db.UnsignedBigInt、 inactive Int @default(0) @db.UnsignedTinyInt、created_at DateTime @db.Timestamp(0)、updated_at / deleted_at は DateTime?。リレーションは張らない(FK が無い)RobotErrorReport に error_list_id BigInt? @db.UnsignedBigInt(定義書は必須だがユーザー回答③「初期は空欄」で NULL 可にする)npx prisma generate を実行@updatedAt を付けない★(既存の注意どおり)lib/fixtures/error-lists.ts: 決定稿 131行(元データ: 監督が抽出した JSON。パスは依頼文に書く)。すべて inactive: 0・deleted_at: null。★error_type 列はテーブルに無いので入れない★(コメントに出典だけ書く)lib/fixtures/error-reports.ts: 既存行のいくつかに error_list_id を入れる — 有効な id/その他(131)+備考あり/error_lists に無い id(例 9999)/null(大半)。 NOT_STARTED の行と D-S_CONTROL_FAILURE・SECURITY_ON の行が fixtures にあることを確かめる(無ければ足す)docs/fixtures.md に追記GET /error-lists 用: db.errorLists()(fixtures / Prisma)。Prisma は where: { inactive: 0, deleted_at: null }, orderBy: { id: "asc" }robot-error-select.ts の選択列に error_list_id を足すerror_list_id(非 null)を集めて errorList.findMany({ where: { id: { in } } }) を★絞らずに★1回引き、写像で解決(N+1 にしない)error-report-mapping.ts で3項目を組み立てる。error_list_selectable の判定は純粋関数1つ(lib/config の定数を読む)/errors 専用のパーサ・計画(lib/errors/status-update.ts を新設。parsePrecheckStatusUpdateBody / planPrecheckStatusUpdate を内部で使い、error_list_id を足す)。 ★lib/prechecks/status-update.ts の挙動は変えない★(/prechecks は error_list_id を捨てるまま)ErrorStatusPatch = PrecheckStatusPatch & { error_list_id?: number }、ErrorStatusUpdateRequest(lib/types)robot-error-write.ts: 既存の robotErrorColumnsFromPatch(4列)は★そのまま★(事前チェックが使う)。/errors 用に robotErrorColumnsFromErrorPatch を足し、 error_list_id だけを追加で許す(BigInt に変換)。「4列以外を含めば例外」の歯止めは5列版にも入れるlib/db/index.ts の updateErrorReportColumns(interface と fixtures 版・Prisma 版の3か所)を ErrorStatusPatch にfixture-error-report-overrides.ts は error_list_id も写す(★写し忘れると fixtures で 200 なのに反映されない★)lib/logger/events.ts の DbWriteColumn・auditBase)に error_list_id の old/newlib/db/__tests__/robot-error-write-sql.test.ts を5列に。★事前チェック・D-Sec の経路では error_list_id を書けない★ことを固定するテストを足す| 段階 | 内容 | 担当ファイル |
|---|---|---|
| 1 契約 | §3 の YAML、§4 の設定、lib/types の型、§5-1 の schema と generate、§5-2 の error-lists.ts |
d-watch-api.yaml / lib/config/index.ts / lib/types/index.ts / prisma/schema.prisma / lib/generated/ / lib/fixtures/error-lists.ts |
| 2a 読み取り | §5-2 の error-reports fixtures、§5-3、app/api/error-lists/route.ts+テスト、GET /errors のテスト更新 |
lib/fixtures/error-reports.ts / lib/db/robot-error-select.ts / lib/db/error-report-mapping.ts / 新 lib/db/error-list-source.ts / lib/db/index.ts(★読み取り関数だけ★)/ app/api/error-lists/ / app/api/errors/__tests__/ / docs/fixtures.md |
| 2b 書き込み | §5-4 | 新 lib/errors/ / app/api/errors/[error_id]/status/ / lib/db/robot-error-write.ts / lib/db/fixture-error-report-overrides.ts / lib/logger/events.ts / lib/db/index.ts(★updateErrorReportColumns の3か所だけ★)/ 関連テスト |
| 3 レビュー | 監督が差分を読み、別のエージェントに独立レビューさせる | — |
| 4 資料 | docs/code-map.md、CLAUDE.md §3・§7(書ける列をテーブルごとに書き分ける)、本書の完了記録 |
監督 |
2a と 2b は並行。lib/db/index.ts は担当の関数以外を触らない(Edit が「変更された」で失敗したら読み直して再適用)。
npm run build 成功GET /error-lists(131件)・GET /errors(新3項目)・PATCH(有効 id/その他+備考なし→422/選べない行→422/無効 id→422/同じ id で状態だけ→200)を実際に叩いて確かめるSHOW GRANTS で error_list_id の UPDATE 権限を確認(ユーザー回答②)information_schema で error_lists と error_list_id(型・NULL 可否)を確認 → db pull → 手書きとの差分確認error_lists の行数・中身が決定稿 131行と一致するか(特に 131 = その他)dwatch_local)には error_lists も error_list_id も無かった★。実DBモードでは GET /errors・PATCH /errors・D-Sec の保存・GET /error-lists が 500 になり、 シード(select の無い robotErrorReport.create)も落ちる。→ ★2026-10-27 にローカルにだけ表と列を足す手順を scripts/local-db/ に用意した★(ユーザー指示「ローカル環境でテストするのでダミーのDB作成」)error_lists の id)を登録できるようにする。保存先は robot_error_reports.error_list_id(★アプリが書く5列目。この表のこの経路だけ★)D-S_CONTROL_FAILURE・SECURITY_ON 以外(清掃開始失敗は選べる)。その他(id 131)は備考必須。未選択は NULL。解除は作らないprisma/schema.prisma の ErrorList と error_list_id は定義書ベースの手書き(D-056 の例外。接続回復後に db pull で置き換え)