prismaSource.prechecks() を実DB経由にする)| 項目 | 内容 | ||
|---|---|---|---|
| 実行環境 | ★Cursor 内の Claude が実装します★(.claude/commands/d-watch.md の役割分担表を参照) |
||
| 実行状態 | ★★実行済み(2026-09-10)★★ — ★段階0〜段階5 をすべて実施。記録は docs/decisions.md の D-105 / docs/handoff.md の 追記30★ |
||
| 実行順 | ★指示書R(D-099)の続き★。★指示書M / P / R が作った scripts/seed-local-db.ts / lib/db/prisma.ts / lib/db/local-guard.ts / lib/db/use-fixtures.ts / lib/db/ds-status.ts / lib/db/clean-log-mapping.ts / lib/format/date.ts の上に積む作業★です。★prismaSource.facilities() / schedules() / dsDevices() / dsAlerts() / cleanLogs() は1文字も変えません★。★触るコードが重なる未実行の指示書は、着手直前に自分で確認すること★(作成時点では、docs/decisions.md / docs/handoff.md を共通で触る指示書と同時に走らせないこと) |
||
| 取得する決定番号 | ★**着手直前に `grep -nE "^### D-(0\ | 1)[0-9][0-9]" docs/decisions.md \ | tail -3で最終番号を実測すること**★。★作成時点の最終はD-101(docs/decisions.md:4784)なので、最初の空き番号はD-102の見込み★。★★^### D-0だけでは3桁台(D-100 以降)を拾えない★★(D-101 冒頭の注記)。★2026-09-07 にD-068` の二重採番が実際に起きています★ |
| 前提 | ★D-090 項6 / 項7 / 項8★(docs/decisions.md:3382 / :3383 / :3384。★prechecks の未決3件★) / ★D-091 項4★(:3546。precheck が分前を表す予定) / ★D-093 項2★(:3749。precheck は任意の分数。★本指示書の設計根拠★) / ★D-092★(:3599。precheck 行の仕組み) / ★D-098★(:4342。Standby.) / ★D-099★(:4442。指示書R の実行記録) / ★D-101★(:4784。認証 proxy.ts) / D-070 1-2(:1130。error_id を使い string のまま) / D-052(:325。ソート順) / D-054(:336。open の意味) / D-042(:226。書き込み4カラム) / D-050(:308) / D-056(:353) / D-077(:1847。エラー値を変換しない) |
||
| 段階数 | ★6段階★(段階0〜段階5) | ||
| ★着手前確認★ | ★★なし(すべて解決済み)★★ — ★launch_failed の判定は ★B案★(本清掃行に紐づく clean_status_histories の行が無い。cleanLogs() の departed と同じ判定を共有する)で確定★(★記録: docs/decisions.md の D-103(:5222)★)。★B案の帰結として残っていた「エラー行が無い launch_failed 行の各フィールドをどう埋めるか」も D-104 で確定★(★段階3 の「3-3b 出発失敗の行の埋め方」を見ること★)。★★新しい仕様判断は1つも要らない。ユーザーの回答を待たずに段階0 から通しで実行してよい★★ |
||
| 着手前の基準 | ★着手直前に自分で npm test / npx tsc --noEmit / npm run lint を実行し、その実測値を基準にすること★(D-099 の完了値は「34ファイル / 658テスト / tsc 0 / lint 0」だが、★鵜呑みにしない★) |
||
| 作成 | 2026-09-10(作成時点の決定事項最終番号 D-101 / docs/handoff.md の最新は 追記29(docs/handoff.md:2342)) |
実行後はこの表と、文書末尾の「実行状態」表を更新してください。
★この指示書を読んでいるあなたへ★ —
.claude/commands/d-watch.mdの「実装は Cursor 側」は 2つの環境の役割分担です。Cursor の中で動いている Claude は実装担当です。 ★調査や改訂ではなく実装を行ってください。★ ★★うまくいかなければ途中で止めて構いません★★ — ただし ★本指示書は API契約と型を変えます★。 ★段階1 まで進めて止めた場合、USE_FIXTURESを戻すだけでは元に戻りません★。 ★止めるなら段階の切れ目(コミット単位)で止めること★。
prechecks 1本だけなのか★★★本指示書の範囲は prismaSource.prechecks() の1本だけです。★ ★★サマリ系4本(reportKpis / facilityPerformance / errorBreakdown / continuousProblems)には 手を付けません。★★
★D-090 項2(docs/decisions.md:3349 付近の分割表)の当初計画では、第4歩を 「prechecks + サマリ3本」の4本立てにしていました。★サマリ3本を外します★。理由は3つ:
| # | 理由 |
|---|---|
| ★1★ | ★★prechecks は API契約(d-watch-api.yaml)と型(lib/types/index.ts)の変更を伴う★★ — ★他の7メソッドが「既存の契約に合わせて DB から値を作る」作業なのに対し、prechecks だけは「契約そのものが実データを表現できない」ことが分かっている★(D-093 項2)。★性質がまったく違うので同じ指示書に混ぜない★ |
| ★2★ | ★サマリ系は「サマリテーブルを読む+当期(進行中の週/月/年)をその場集計する」という共通構造★(CLAUDE.md §4.7。★進行中の期間はサマリテーブルに存在しない★)。★4本を1本の指示書にまとめたほうが、当期集計の置き場所(D-090 項14 / 項15)を1回で決められる★ |
| ★3★ | ★continuousProblems は cleanLogs の連続日数算出に依存する★(D-090 項2 の分割方針)。★lib/db/clean-log-mapping.ts:112 の computeConsecutiveProblemDays() を流用する話になるので、サマリ系と一緒に扱うのが自然★ |
★→ サマリ系4本は 第5歩(別の指示書)で扱います★。
severity の型を変える必要がある★★| 箇所 | 実測内容 | ||
|---|---|---|---|
★lib/types/index.ts:124★ |
`export type PrecheckSeverity = "precheck_1h" \ | "precheck_30m" \ | "launch_failed";— ★3値固定★(:140のseverity` フィールドで使用) |
★d-watch-api.yaml:1156★ |
★enum: [precheck_1h, precheck_30m, launch_failed]★(PrecheckItem は :1149 から) |
||
★components/features/alerts/AlertsScreen.tsx:20-24★ |
SEVERITY_LABEL が ★:21 precheck_1h: "1h前異常" / :22 precheck_30m: "30分前異常" / :23 launch_failed: "出発失敗"★。★固定ラベル★(:156 で t(SEVERITY_LABEL[item.severity]) として使用) |
★注意★: ★D-093 項2-1 は
lib/types/index.ts:118/d-watch-api.yaml:1072と記録しているが★その後の編集で行がずれている★。★上の実測値が正。行番号は必ず自分で取り直すこと★。
docs/decisions.md:3749。ユーザー回答)★: clean_timetables.precheck は 「0 / 60 / 30」の3値ではなく、★設定値に応じた任意の分数★。★20 なら20分前★precheck = 20 の行が来ても、いまの3値では表現できない★clean_timetables.precheck は tinyint unsigned(0〜255)なので、 値が 1/2 から 60/30/20 に変わっても DB 側の型変更は不要★★(D-094 で確認済み)。 ★★変えるのは当方の API契約と型のほう★★| 項目 | 変更後 | |
|---|---|---|
PrecheckSeverity |
★`"precheck" \ | "launch_failed"` の2値★ |
| ★新フィールド★ | ★`precheck_minutes: number \ | null`★ — ★「何分前か」を数値で持つ★ |
★launch_failed のとき★ |
★precheck_minutes は null★ |
|
| 画面 | ★${n}分前異常 と組み立てる★(固定ラベルをやめる) |
★案B(precheck_20 のような enum を増やす)★ / ★案C(60/30 以外をその他に丸める)★は ★D-093 項2-2 で「採らない」と結論済み★。★蒸し返さないこと★。
lib/i18n.ts はキーが日本語原文の完全一致なので、数値が混ざる文言はそのままキーにできない★lib/i18n.ts:86-87★ が方式Aを ★推奨★ として説明している (t("他{n}件を表示 →").replace("{n}", String(n))。実例は ★:96★)。 ★方式B(前後を分割して連結)は :92-95 で「1文字キーは他画面の文言と衝突しやすい」として非推奨★lib/i18n.ts:158 "第{n}回チェック": "Check #{n}" / :159 "{n}分前": "{n} min before"★。★"{n}分前異常" を足すのが自然★"1h前異常" / "30分前異常" / "出発失敗" は現在 lib/i18n.ts にキーが無い★★ (実測。grep でヒット0件。D-093 項2-3 が指摘済み)。 ★AlertsScreen.tsx:156 が t() を通しているのに対訳が無く、★EN でも日本語のまま出る★★。 ★新しい文言を作るついでに対訳も入れること★"残量"(AlertsScreen.tsx:167)/ "検知"(:171)にもキーが無い★★(実測)。 ★ついでに入れてよい(1行ずつなので巻き込み事故のリスクは小さい)★★以下は解決済みの記録です。★★確認を待つ必要はありません★★(★判定=D-103 / 各フィールドの埋め方=D-104★)。
launch_failed(出発失敗)を DB のどの状態で判定するか★ → ★★B案で確定★★★★ユーザーの問い(2026-09-10。原文)★★:
Sは本清掃の清掃結果を抽出するところと同じではだめですか
★★この指摘が正しい★★。★launch_failed は「出発しなかった」という事象そのもの★であり、 ★指示書R(D-099)が cleanLogs() で既に判定している departed === false と同じ出来事★です。 ★清掃詳細ログ(F-02)とアラート(F-03)が、同じ出来事を別の切り口で見ているだけ★。 ★別ロジックを立てると、片方だけ直したときに数字が食い違う★。
★確定内容★:
launch_failed は ★★「本清掃行(precheck === CLEAN_TIMETABLE_PRECHECK.main)に紐づく clean_status_histories の行が無い」★★で判定する★cleanLogs() の departed と同じ判定を共有すること★★根拠(★2026-09-10 実測。着手時に自分でも開いて確認すること★):
lib/db/index.ts:274-279 のコメント(★原文★):
// ★「出発したか」は DB の値で決める。「予定+猶予30分」を当方で計算しない★ // (D-091 項1 / 指示書R 禁止事項3。LAUNCH_GRACE_MINUTES はここから読まない) // ★本清掃に紐づく clean_status_histories の行が無い=未出発(未実施)★という設計。 // `clean_status`(-1/0/1/2)に「出発しなかった」を表す値が無く、 // 行が作られないことが未実施を意味する、という D-091 項1 後段の読みを採った。 // ★実データでどのカラムが未実施を表すかは要確認★(決定台帳に記載)。
実装は lib/db/index.ts:292 の ★departed: history !== undefined★ (history は :280 の historyByTimetableId.get(key(row.id)))
docs/decisions.md:3382)の「★launch_failed の DB 表現も未定義★」は、 本回答で解決★(★記録は docs/decisions.md の D-103★)選択肢(★当初の提示をそのまま残す。採用案に ✅★):
| 案 | 判定方法 | 帰結 | 採否 |
|---|---|---|---|
| A | ★robot_error_reports.clean_timetable_id が本清掃行(precheck = 本清掃コード)を指すエラー = launch_failed★。★precheck 行を指すものは severity: "precheck" + precheck_minutes = その行の precheck 値★ |
★1つのクエリで両方を出し分けられ、severity の判定規則が「紐づく clean_timetables 行の precheck 値だけ」で閉じる★。★resolution_status / responded_at / resolved_at / note(=書き込み許可4カラム。D-042)を launch_failed にも持たせられる★。★ただしシードに本清掃行のエラーを足す必要がある(段階1)★ |
★不採用★ — ★「エラー行があること」を出発失敗の条件にすると、cleanLogs() の departed と別の定義になる★。★同じ出来事に2つの判定ができ、片方だけ直したときに /detail-log と /alerts で数字が食い違う★ |
| ★B ✅★ | ★本清掃行に clean_status_histories が無い(=未出発。D-099 の departed 判定)ことを launch_failed とする★ |
★cleanLogs() の departed=false と定義が完全に一致する★。★しかしエラー行が存在しないので、robot_status / detected_at / resolution_status / responded_at / resolved_at / note の置き場が無い★ |
★★採用★★ — ★同じ出来事は同じ判定で出す★。★下記「残る課題」で4カラムの扱いを決めること★ |
| C | ★第4歩では launch_failed を出さない(precheck 行由来の severity: "precheck" のみ返す)★ |
★実装は最小。TeamWorks の回答を待てる★。★ただし /alerts から「出発失敗」が消え、fixtures との突き合わせ(段階4)で常に差が出る★ |
★不採用★ — ★待つ必要が無かった★。★判定は既にコードの中にあり、TeamWorks の回答を待つ論点ではない★ |
★★実装上の注意 — 判定を2箇所に書かないこと★★:
lib/db/clean-log-mapping.ts に切り出されていない★ — ★lib/db/index.ts:292 にインラインで書かれている★ (★同ファイルの export は formatModelName / robotStatusFromErrors / isProblemCompletion / computeConsecutiveProblemDays の4つのみ。2026-09-10 実測★)lib/db/clean-log-mapping.ts に 純粋関数として出し、cleanLogs() と prechecks() の両方から呼ぶこと★。 ★cleanLogs() の挙動は1ビットも変えない(禁止事項の「既存5メソッドは1文字も変えない」は、 この切り出しに伴う呼び出し置換のみ例外とし、段階5 で記録すること)★★B案の帰結(★D-104 で確定済み。段階3 で「決める」必要はもう無い★)★:
launch_failed に対応する robot_error_reports の行が存在しない★ため、 ★resolution_status / responded_at / resolved_at / note(D-042 の書き込み許可4カラム)の 置き場が無い★resolution_status は unresolved 固定 / note / responded_at / resolved_at は null★。★詳細と根拠は段階3 の 「3-3b 出発失敗の行の埋め方」を見ること★。★precheck 由来の行だけが4カラムの実体を持つ、という形になる★★★すべて解決済みなので、そのまま段階1 に入ってよい★★。 ★決定は docs/decisions.md の D-103(判定)と D-104(埋め方)に記録済み★。
PrecheckItem の各フィールドの取得元と、未決3件の扱い★★PrecheckItem は lib/types/index.ts:138-155★。
| フィールド | 取得元 | 状態・扱い |
|---|---|---|
★id★ |
★robot_error_reports.id / error_id(★どちらも varchar(50)★。prisma/schema.prisma:303-304)★ |
★D-090 項7(docs/decisions.md:3383): 型が number(lib/types/index.ts:139)と食い違う★。★D-070 1-2(:1130)で「error_id を使い string のまま」と方針は確定済み、★実装が未着手★★ → ★★段階1 で string にする★★ |
★severity★ |
clean_timetables.precheck |
★D-090 項6: 未決。★上記の型変更(2値化 + precheck_minutes)で解決する★ |
★precheck_minutes(新設)★ |
clean_timetables.precheck の値そのもの |
★launch_failed のときは null★ |
serial_number |
robot_error_reports.serial_number |
★varchar(20)。NOT NULL★ |
facility_id / facility_name |
robot_error_reports.facility_id → ★facility リレーションを include★ |
★facility_id は FK があるのでリレーションで辿れる(prisma/schema.prisma:329)★。★BigInt → Number()★ |
scheduled_at |
★clean_timetables.start_at(本清掃行)★ |
★toJstIso()(lib/format/date.ts)を使う★(指示書P で導入済み)。★precheck 行の start_at ではなく親の本清掃行の値★(parent_id で引く) |
★robot_status★ |
★robot_error_reports.error_type の生値★ |
★D-077 / D-098。日本語に変換しない★。★エラーが無ければ ROBOT_STATUS_STANDBY(lib/config/index.ts:72 = "Standby.")★。★lib/db/clean-log-mapping.ts:54 の robotStatusFromErrors() がこの規則を既に実装している → 流用すること★ |
★detected_at★ |
★robot_error_reports.errored_at(prisma/schema.prisma:324。★nullable★)または created_at(:327。★NOT NULL / default now()★)★ |
★★どちらを使うか未決。決めて記録すること★★。★推奨: errored_at ?? created_at(errored_at を優先し、null のときだけ created_at に落とす)★。★理由: errored_at が「エラーが起きた時刻」で意味的に正しいが nullable なので、NOT NULL の created_at を保険にする★ |
resolution_status |
robot_error_reports.status(:322。★Int @default(0) @db.UnsignedTinyInt★) |
★0 = unresolved / 1 = in_progress / 2 = resolved★。★lib/db/ds-status.ts の resolutionStatusFromControlErrorStatus() と同じ値域なので、同じ作法で純粋関数に切り出すこと★ |
responded_at / resolved_at |
同名カラム(:325 / :326。★どちらも nullable★) |
★書き込み許可4カラム(D-042。docs/decisions.md:226)★。★本作業は読むだけ★ |
note |
robot_error_reports.comment(:323。★nullable★) |
同上 |
★battery_level★ |
★★取得元が無い★★ | ★D-090 項8(docs/decisions.md:3384): robots.battery は現在値のみで履歴が無い★。★★null を返すことを推奨★★(「事前チェック時点の残量」は DB から取れないため、当方で現在値を代入すると別時点の値を過去のアラートに貼ることになる)。★決めて記録すること★ |
★d-watch-api.yaml:1149-1176 の PrecheckItem には★:
facility_id が無い★(lib/types/index.ts:142 にはある)battery_level が無い★(lib/types/index.ts:154 にはある。AlertsScreen.tsx:165-169 が表示している)★★段階1 でこの2つも足すこと★★(★CLAUDE.md §6-1「API契約を変えたくなったら先に YAML を直す」★)。
id を string にすると影響が出る箇所(★洗い出し済み。自分で grep し直すこと★)★★| # | 箇所 | 内容 |
|---|---|---|
| 1 | ★lib/types/index.ts:139★ |
id: number → ★id: string★ |
| 2 | ★d-watch-api.yaml:1153★ 付近 |
id: { type: integer, example: 1 } → ★{ type: string }★ |
| ★3★ | ★d-watch-api.yaml:442★ |
★/prechecks/{id}/status が共有パラメータ PathId(:997-1001。★type: integer★)を参照している★。★★PathId は他に6箇所(:337 :370 :769 :957 :969)から参照されているので、PathId 自体を変えないこと★★ → ★/prechecks/{id}/status にだけインラインの string パラメータを書く★ |
| ★4★ | ★lib/prechecks/query.ts:132★ |
sortPrechecks() の同値時タイブレークが ★a.id - b.id(数値減算)★。★string では動かない★ → ★a.id < b.id ? -1 : a.id > b.id ? 1 : 0 等に変える★。★D-052(docs/decisions.md:325)の「detected_at 降順 / 同値は id 昇順」という契約は変えないこと★ |
| 5 | ★lib/fixtures/prechecks.ts:21 :36 :52 :69 :84 :101 :116 :131★(8件) |
★id: 1 → id: "1" 等★。★★lib/fixtures/ の改変になるので、指示書R 禁止事項12(CLAUDE.md §9.5)に抵触する — ★型変更に伴う必然の追従なので本指示書では許可する★。★値の意味は変えないこと(1 → "1" のように同じ文字列にする)★★ |
| 6 | ★lib/prechecks/__tests__/query.test.ts★(:14 :143-145 :151-153 :158 :162 :166 :170 :194 :284 :293) |
★id と severity の両方が変わる★。★期待値表を先に直してからテストを走らせること★(CLAUDE.md §9.4) |
| 7 | ★components/features/alerts/AlertsScreen.tsx:149★ |
key={item.id} — ★React の key は string でも動くので変更不要★(確認だけすること) |
| 8 | app/api/prechecks/route.ts |
★id を直接触っていない(:42 で型として使うだけ)ので変更不要の見込み★。★確認すること★ |
★★/prechecks/{id}/status(PATCH)の API ルートはまだ実装されていません★★ (app/api/prechecks/ には route.ts しかない。実測)。★本指示書で作らないこと★。
| # | 落とし穴 |
|---|---|
| ★1★ | ★robot_error_reports.clean_timetable_id(prisma/schema.prisma:312)に FK も KEY も無い★(★しかも BigInt? で nullable★)。★include で clean_timetables を辿れない → 別クエリ+メモリ上の手動 join★(cleanLogs() と同じ。★lib/db/index.ts:205-250 付近の実装をそのまま流用できる★) |
| ★2★ | ★robot_error_reports に deleted_at が無い★(prisma/schema.prisma:299-337 を実測)→ ★論理削除の絞り込みを書かない★。★書くと型エラーになる(=安全側)。無理に回避しないこと★ |
| ★3★ | ★id / error_id は varchar(50)★(:303-304)→ ★Number() は NaN になっても例外を出さない★。★★本作業では Number() を通さない(string のまま返す)のが正解★★ |
| ★4★ | ★BigInt → Number()★ を忘れると JSON.stringify が例外を投げる(NextResponse.json が 500 になる。★tsc は捕まえない★)。★facility_id が該当★ |
| ★5★ | ★RobotErrorReport には @id が無く error_id @unique だけ★(:303-304)→ ★Prisma の findUnique は error_id でしか引けない★ |
| ★6★ | ★clean_timetables.start_at は datetime(TZ情報なし)★。★API は +09:00 付き ISO8601 → toJstIso() を使う★ |
★指示書R(D-099 段階1)で clean_timetables / clean_statuses / clean_status_histories / robot_error_reports はシード済み★(scripts/seed-local-db.ts。★npm run seed:local★)。 ★ただし prechecks の観点では足りないものがあります★:
| # | 不足 | 帰結 | 対応 |
|---|---|---|---|
| ★1★ | ★robot_error_reports の status / comment / responded_at / resolved_at を1件も入れていない★(scripts/seed-local-db.ts:689-705 を実測) |
★status は default 0 なので、★全件が unresolved・note が null★になる★。★/alerts の「対応中 / 解消」が1件も出ない★ |
★段階1 に含めること★。★lib/fixtures/prechecks.ts の8件と同じ分布(未解消3 / 対応中2 / 解消3)になるよう、シードで値を散らすこと★ |
| ★2★ | ★本清掃行に紐づくエラー行が無い★(precheck 行にしか作っていない) | ★★B案(確定)ではこれが正常★★。★launch_failed はエラー行ではなく、本清掃行に clean_status_histories の行が無いことで判定する(cleanLogs() の departed と同じ。D-103)ため、★★エラー行が無いことがそのまま launch_failed の存在を意味する★★(エラー行の有無を条件にする必要が無い) |
★不採用の A案ならここでエラー行の追加が要ったが、B案ではこの不足を埋める作業は不要★。★段階1 に追加のシード作業は無い★ |
| 3 | ★シードのエラー行は lib/fixtures/clean-logs.ts 由来であり、lib/fixtures/prechecks.ts の8件とは別物★ |
★段階4 の USE_FIXTURES 突き合わせで件数が一致しない★ |
★★これは想定内★★。★「同じ8件を再現する」ことは目指さない★。★確認するのは変換規則が正しいこと(severity / precheck_minutes / robot_status / resolution_status の作られ方)★ |
★シードを触る場合の作法★: ★deleteMany の逆順(scripts/seed-local-db.ts:392-395)を崩さない★ / ★2回続けて実行しても結果が同じであること★ / ★実在の住所・電話番号・社名・人名を入れないこと★ (CLAUDE.md §7。★既存のダミー値は :229-231 の ERROR_LEVEL_PLACEHOLDER / ERROR_DETAIL_PLACEHOLDER★)。
| # | ★してはいけないこと★ | 理由 |
|---|---|---|
| ★1★ | ★★サマリ系4本(reportKpis / facilityPerformance / errorBreakdown / continuousProblems)に手を付けること★★ |
★第5歩の範囲★。★共通構造でまとめて書くほうが良いと本書冒頭で結論済み★ |
| ★2★ | ★★エラー種別を日本語に変換すること / 7分類に寄せること★★ | ★D-077(docs/decisions.md:1847)/ D-088 / D-098★。★error_type の値をそのまま robot_status に入れる★ |
| ★3★ | ★★precheck の値(0/1/2、60、30 など)をコードに直書きすること★★ |
★CLAUDE.md §7 / D-091 項4 / D-093 項2★。★lib/config/index.ts:49-54 の CLEAN_TIMETABLE_PRECHECK を使う★。★値が変わったとき1箇所で追従できる形を壊さない★ |
| ★4★ | ★deleted_at が無いテーブルで論理削除の絞り込みを書くこと★ |
★型エラーになる(=安全側)。落とし穴2★ |
| ★5★ | ★clean_timetables.inactive で絞ること★ |
★第1〜3歩と同じ方針(lib/db/index.ts:180)。★仕様が未確定なので絞らない側に倒す★ |
| ★6★ | ★★メインDB(TeamWorks 側)に接続・書き込みすること / dwatch_ddl に書き込むこと★★ |
CLAUDE.md §2 / §7 / D-042。★作業は dwatch_local の中だけ★。★接続先ホスト名は未受領★ |
| ★7★ | ★prisma migrate / db push / db pull を使うこと / prisma/schema.prisma を手で書き換えること★ |
★CLAUDE.md §7 / D-056 / D-059★。★prisma/schema.prisma:301-302 のコメントが D-070 1-2 より古い(「API 契約を変更しない」と書いてある)が、★それでも手で直さない★★ |
| ★8★ | ★prismaSource の既存5メソッド(facilities / schedules / dsDevices / dsAlerts / cleanLogs)を変更すること★ |
★指示書M / P / R の成果物★。★本作業は「その隣に1本足す」だけ★ |
| ★9★ | ★lib/db/prisma.ts / local-guard.ts / use-fixtures.ts / ds-status.ts を変更すること★ |
★完成しており、そのまま効く★。★特に use-fixtures.ts は Edge Runtime バンドル破壊の修正そのもの★(D-086) |
| ★10★ | ★lib/db/ にフィルタ・ページング・ソートを持ち込むこと★ |
★lib/db/index.ts:71-75 の設計方針★。★prechecks には judge も連続日数も無いので、この例外は使えない★ |
| ★11★ | ★書き込み許可4カラム以外に書き込むこと / 本作業で DB に書き込むこと★ | ★D-042★。★本作業は読むだけ(シードを除く)★ |
| ★12★ | ★テストを DB 依存にすること★ | ★遅く・不安定になり、DB が空の環境で落ちる★。★テストは fixtures と純粋関数だけ★ |
| ★13★ | ★git add -A を使うこと★ |
CLAUDE.md §7。★必ずファイルパスを明示★ |
| ★14★ | ★.env.local をコミットすること / DB の認証情報を文書やコードに書くこと★ |
CLAUDE.md §9.3。★確認後は USE_FIXTURES=true に戻す★ |
| ★15★ | ★npm run dev を Bash で起動すること★ |
★Browser pane の preview_start を使う★(段階4) |
★段階0(前提の確認。★読むだけ・コミットなし★)→ 段階1(API契約と型 + 必要ならシードの補完) → 段階2(fixtures と画面)→ 段階3(prismaSource.prechecks())→ 段階4(動作確認。★コミットなし★) → 段階5(記録と push)★。★★段階1・2・3・5 でそれぞれ1コミット★★。
★段階ごとに npx tsc --noEmit / npm run lint / npm test を実行し、通ってからコミットすること★ (D-050。docs/decisions.md:308)。
| # | 対象 | 見る点 |
|---|---|---|
| 1 | ★D-090 項6 / 項7 / 項8★(docs/decisions.md:3382-3384) |
★未決3件の原文★ |
| 2 | ★D-093 項2★(:3749。特に ★2-2 の案A(:3774)★ と ★2-3 の注意(:3782)★) |
★本指示書の設計根拠★ |
| 3 | ★D-091 項4★(:3546)/ ★D-070 1-2★(:1130)/ ★D-098★(:4342) |
★precheck が分前を表す予定★ / ★error_id を string のまま★ / ★Standby.★ |
| 4 | ★★prismaSource.cleanLogs()(lib/db/index.ts:186-320)★★ |
★これが雛形★。★手動 join(:205-250 付近)/ 遅延 import / Number() / toJstIso() / docstring の書き方をそのまま流用する★ |
| 5 | ★lib/db/clean-log-mapping.ts(全141行)★ |
★robotStatusFromErrors()(:54)は prechecks でもそのまま使える★。★RobotErrorLike(:32)も同じ★ |
| 6 | ★lib/db/ds-status.ts★ |
★resolutionStatusFromControlErrorStatus() の作法(0/1/2 → 3値)を robot_error_reports.status に流用する★ |
| 7 | ★scripts/seed-local-db.ts(全784行。特に :646-712)★ |
★precheck 行とエラー行の作り方★。★「調査済みの事実」5 の不足2件を自分で確認すること★ |
| 8 | ★lib/i18n.ts:80-97 / :155-160★ |
★方式A の説明と既存の実例★ |
.env.local の DATABASE_URL が dwatch_local を指していることを確認する★。 ★値そのものを画面・ログ・文書に出さないこと★(CLAUDE.md §9.3).env.local に ALLOW_DIRECT_ACCESS=true があることを確認する★(★作成時点では設定済み★。 D-101 項2。★無いと proxy.ts が全ルートを止めるので段階4 で詰まる★)npm test のファイル数・テスト数 / tsc / lint)を自分で実測して控えた★launch_failed の DB 表現 = B案。D-103)。新たに回答を得る必要はない★★★実装より先に契約を直す★(CLAUDE.md §6-1)。
d-watch-api.yaml:1156 の enum を ★[precheck, launch_failed]★ に変更し、description も直す★precheck_minutes を追加★({ type: integer, nullable: true }。 ★description に「何分前のチェックか。launch_failed のときは null」と書く★):1152 付近の id を { type: string, example: "RER-1001-1" } に変更★facility_id と battery_level を追加★(「調査済みの事実」2):442 の PathId 参照を、/prechecks/{id}/status 専用のインライン string パラメータに置き換える★ (★★components/parameters/PathId 自体は変えない★★。他6箇所が参照している)lib/types/index.ts:124 PrecheckSeverity を "precheck" | "launch_failed" に★:139 id: number → id: string★(D-090 項7 / D-070 1-2。★決定済みなのでここで実装する★)PrecheckItem に precheck_minutes: number | null を追加★(★コメントで「launch_failed は null」 「値は clean_timetables.precheck の生値」を明記★)id を string にした影響の追従★★「調査済みの事実」3 の表の #4・#6 を直す★(lib/prechecks/query.ts:132 のタイブレークと、 lib/prechecks/__tests__/query.test.ts)。★#5(fixtures)は段階2 でまとめて直してよい★。
robot_error_reports に status / comment / responded_at / resolved_at を入れる★ (★分布は fixtures の8件に倣う。値は決め打ちでよいが、規則をコメントに書くこと★)launch_failed はエラー行を使わず「本清掃行に clean_status_histories が無いこと」 (departed。D-103)で判定するため、ここでのエラー行追加はしない★npx tsc --noEmit エラー0 / npm run lint 0 / npm test 全パス★d-watch-api.yaml と lib/types/index.ts の内容が一致していること★(★enum / nullable / 型★)components/parameters/PathId に差分が無いこと★lib/fixtures/prechecks.tsid を string に★ / ★severity: "precheck_1h" → severity: "precheck", precheck_minutes: 60★ / ★"precheck_30m" → severity: "precheck", precheck_minutes: 30★ / ★"launch_failed" → precheck_minutes: null★PRECHECK_MINUTES_BEFORE(lib/config/index.ts:34)から取ること★(禁止事項3)precheck_minutes: 20(設定値以外の任意の分数)の行★。 ★D-093 項2 の「20 なら20分前」を画面と型が本当に表現できるかの検証になる★。 ★★これが本指示書で fixtures を触る主目的なので、忘れないこと★★components/features/alerts/AlertsScreen.tsx:20-24 の SEVERITY_LABEL を分数から組み立てる形に変える★:
launch_failed → t("出発失敗")★precheck → t("{n}分前異常").replace("{n}", String(item.precheck_minutes))★precheck_minutes が null の precheck(起きないはずの組み合わせ)をどう出すか決めること★★ (★推奨: t("事前チェック異常") にフォールバックし、黙って空文字を出さない★):26-28 の severityColor() は launch_failed かどうかで分岐しているだけなのでそのまま動く★ (確認だけすること)★lib/i18n.ts に追加する(★方式A。:86-87 / :158-159 の前例に倣う★)★:
| キー | EN | 備考 |
|---|---|---|
★"{n}分前異常"★ |
★"{n} min before: error" 等★ |
★方式A。:159 の "{n}分前" の隣に置くと読みやすい★ |
★"出発失敗"★ |
"Launch failed" |
★★現在キーが無い(EN でも日本語のまま出ている)★★ |
★"事前チェック異常"★ |
"Pre-check error" |
★2-2 のフォールバックを作る場合★ |
★"残量" / "検知"★ |
"Battery" / "Detected" |
★同じ画面でキーが無いもの(AlertsScreen.tsx:167 / :171)★ |
★★"1h前異常" / "30分前異常" はキーごと消える★★(★組み立て式に変わるため★)。 ★キーが無かったので削除対象も無い(実測)★。
robot_status を生値に寄せるか★★lib/fixtures/prechecks.ts の robot_status は現在 ★日本語6値★★ ("ハンドルアップ" / "オフライン" / "充電中" / "セキュリティ有効" / "緊急停止")。
docs/decisions.md:3084)で error_type を英語識別子に寄せたのと 同じ扱いにするのが一貫する★★。★DB 経由では error_type の生値がそのまま入るため★lib/theme-status.ts の色分けがグレーになる★(★日本語6文字列の完全一致で引くため。 lib/config/index.ts:197 の ROBOT_STATUS_TONES)。★これは D-077 の想定挙動★Standby. にし、 ★ROBOT_STATUS_TONES には足さなかった★★(D-099 項2-2。lib/config/index.ts:185-187 のコメント)robot_status に差が出るのは想定内として記録する★npx tsc --noEmit エラー0 / npm run lint 0 / npm test 全パスUSE_FIXTURES=true のまま /alerts が表示され、★「60分前異常」「30分前異常」「20分前異常」 「出発失敗」がすべて正しく出ること★★0/1/2 や 60 / 30 が AlertsScreen.tsx / lib/fixtures/ に直書きされていないこと★★prismaSource.prechecks() を実装する★lib/db/index.ts:321-323 の notImplemented("prechecks") を実装に置き換える★。 ★cleanLogs()(:186-320)と同じ形にすること★(遅延 import → クエリ → 手動 join → map)。
robot_error_reports を findMany(★facility は FK があるので include してよい★)★clean_timetables を findMany(★clean_timetable_id に FK が無いので include で辿れない★)★clean_timetables.id をキーに Map を作る★clean_timetables 行 → precheck の値 で severity / precheck_minutes を決める★scheduled_at は親の本清掃行の start_at★ — ★precheck 行なら parent_id で親を引く / 本清掃行なら自分自身★clean_timetable_id が null のエラー行★(prisma/schema.prisma:312 は nullable)★の扱いを 決めて記録すること★(★推奨: prechecks の対象外として除外する。 「清掃タイムテーブルに紐づかないエラー」は事前チェックのアラートではないため★)★★この方針(なぜ include が使えないのか)をコードコメントに残すこと★★ — ★D-094 で TeamWorks に FK 追加を再依頼中なので、FK が付いたら include に書き換えられる★。 ★根拠(prisma/schema.prisma:312 に FK も KEY も無い)を書くこと★。
severity の組み立て★★★precheck = 0(本清掃)の行に紐づくエラーは launch_failed に相当するか?★★ — ★B案で確定(D-103)★。★D-090 項6 が「launch_failed の DB 表現は未定義」としていたが、これで解決済み★。
紐づく clean_timetables 行 |
severity |
precheck_minutes |
|---|---|---|
★precheck === CLEAN_TIMETABLE_PRECHECK.main(本清掃)★ |
★A案なら launch_failed★ |
★null★ |
| ★それ以外(事前チェック行)★ | ★"precheck"★ |
★★precheck の値をそのまま★★ …ただし ★現行DDLは 1 / 2 のコード値★(D-091 項4 の切替前)なので、★CLEAN_TIMETABLE_PRECHECK.rounds と PRECHECK_MINUTES_BEFORE の対応表で分数に直す★(lib/config/index.ts:49-54 のコメントがこの対応を明記している)。★★切替後は「そのまま使う」に変わる — その分岐を1箇所の純粋関数に閉じ込め、コメントで明示すること★★ |
0/1/2 や 60/30 を直書きしないこと★★(禁止事項3)★上の 3-3 の表は「A案なら launch_failed」という条件付きで書かれているが、 ★★採ったのは B案 なので、その分岐には入らない★★★ — ★launch_failed はエラー行から作らない(本清掃行に紐づく clean_status_histories が 無いことから作る。D-103)★。★したがって「本清掃行を指すエラー行」を launch_failed に 読み替えてはいけない★。
★★出発失敗の行には robot_error_reports の行が存在しない★★ため、エラー行から取るはずの フィールドが空になる。★埋め方はすべて既存の前例に揃える。新しい判断は要らない★:
| フィールド | 確定内容 | なぜそうするか | 前例 |
|---|---|---|---|
★id★ |
★本清掃行の clean_timetables.id★(★BigInt なので Number() を通す★) |
★1回の清掃を一意に指す最小の単位★。★エラー行が無いので error_id は使えないが、出発失敗は「その本清掃が出発しなかった」という事象なので、本清掃行の id で一意に決まる★ |
★D-099 項4(docs/decisions.md:4559)★ — ★CleanLogItem.id にまったく同じ値を採っている★(★原文: 「id(D-090 項3 の解決): 本清掃行(precheck = 0)の clean_timetables.id。1回の清掃を一意に指す最小の単位。事前チェック行は parent_id でこれを指すので、1件の CleanLogItem に対応する id が必ず1つに決まる」★)。★実装は lib/db/index.ts:283 の id: Number(row.id)(row は本清掃行)★ |
★robot_status★ |
★Standby.★ |
★エラー行が0件のときの値★。★自分で文字列を書かず、既存の純粋関数に空配列を渡すだけでよい★ | ★D-098★。★robotStatusFromErrors()(lib/db/clean-log-mapping.ts:54)が errors.length === 0 のとき ROBOT_STATUS_STANDBY(lib/config/index.ts:72 = "Standby.")を返す★。★cleanLogs() も lib/db/index.ts:271 で同じ関数を呼んでいる★ |
★resolution_status★ |
★unresolved 固定★ |
★「まだ誰も対応していない」の意味★。★PrecheckStatus は unresolved / in_progress / resolved の3値(lib/types/index.ts:125。YAML は d-watch-api.yaml:1165)なので、状態を持てない行は先頭の値に倒すしかない★ |
★precheck 由来の行が robot_error_reports.status の default 0(= unresolved)から作られるのと同じ値★ |
★note / responded_at / resolved_at★ |
★すべて null★ |
★エラー行が無いので備考も日時も存在しない★。★null は「値が無い」という事実そのもの★ |
★型定義がいずれも nullable(lib/types/index.ts:149 / :151 / :152)★ |
★★「その他」「不明」のような語を使わないこと★★ — ★D-089 項3(docs/decisions.md:3249-3251)で 同じ判断をしている★: ★「『その他』は D-067(破棄済み)の『未知の値をその他に寄せる』方針と 紛らわしい」★。★やり方(1箇所の定数に固定値を置く)は同じでよいが、★語だけは避ける★★。
★★id を D-099 と同じにする利点★★:
error_id(string)、launch_failed の行は本清掃行の id(数値の文字列化)になる★。 ★PrecheckItem.id は段階1 で string にするので型は揃う★。★★衝突しないことを確認し、 必要なら混ざらないことが分かる形にするかを判断して段階5 に記録すること★★★★申し送り(第4歩のスコープ外。将来の課題)★★
robot_error_reports の行が無いため、★★将来「対応状況の更新機能」を 作るときに書き込み先が無い★★★PATCH /prechecks/{id}/status は API契約にあるだけで未実装★ (app/api/prechecks/ には route.ts しかない。★実測して確認すること★)。 ★画面も表示だけで、components/features/alerts/AlertsScreen.tsx の onClick は フィルタ切替の3つ(:117 / :124 / :131。すべて setStatusFilter)だけ★。★D-Sec 側も同様★★将来の選択肢は2つ★:
| 案 | 内容 | 前例 | |---|---|---| | ★1★ | ★DFA 独自ストアに持つ★ | ★D-076(docs/decisions.md:1762)の D-Sec デバイス備考★ — ★lib/settings/ds-device-notes.ts が json-store.ts を薄く包み、GET のときに DB 由来の値へ上書きしている(app/api/ds-devices/route.ts)★ | | ★2★ | ★TeamWorks に「出発失敗のときもエラー行を作る」ことを依頼する★ | ★D-042 の書き込み許可4カラムがそのまま使えるようになる★ |
★★本指示書ではどちらも実装しない★★。★段階5 で申し送りとして記録するだけでよい★
robot_status★: ★robotStatusFromErrors()(lib/db/clean-log-mapping.ts:54)を流用★。 ★1件のエラー行を扱うので配列に包んで渡すだけでよい★detected_at★: ★決めた規則(推奨 errored_at ?? created_at)で toJstIso() を通す★resolution_status★: ★status(0/1/2)→ 3値。★純粋関数に切り出す★(ds-status.ts と同じ作法)★battery_level★: ★null★(D-090 項8。★理由をコメントに残すこと★)id★: ★error_id を使う★(D-070 1-2)。★Number() を通さない★facility_id★: ★Number()★(BigInt。落とし穴4)lib/db/precheck-mapping.ts を新設するか、lib/db/clean-log-mapping.ts に足すか★を 判断して記録すること(★推奨: 新設。cleanLogs 側のテストと混ざらない★)severity / precheck_minutes の組み立て(precheck コード → 2値+分数)★ / ★resolution_status の変換★ / ★detected_at の選択★CLAUDE.md §9.4)。★境界値: 本清掃コード / rounds の各値 / 未知の precheck 値(例 20)/ status の 0・1・2・想定外値 / errored_at が null★npx tsc --noEmit エラー0 / npm run lint 0 / npm test 全パスprismaSource の既存5メソッドに差分が無いこと★(禁止事項8)app/api/prechecks/route.ts に差分が無いこと★(★データ層の差し替えだけで動くことが正しさの証明★)severity の組み立て規則・battery_level を null にした理由が コメントに残っていること★.env.local の USE_FIXTURES を false にする★ (★lib/db/use-fixtures.ts は文字列 "false" のみを見る。FALSE や 0 では切り替わらない★)npm run dev を Bash で起動しないこと。Browser pane の preview_start を使う★ (.claude/launch.json に d-watch(npm run dev / port 3000)がある)docs/decisions.md:4784)で proxy.ts が入り、 ★全ルートが保護されている★★
.env.local に ALLOW_DIRECT_ACCESS=true が必要★ (★作成時点では設定済み。自分で確認すること★)/login でトークンを入れる必要があるかを実際に確かめること★★ (app/login/page.tsx / app/api/auth/login が存在する)。 ★必要なら .env.local の AUTH_TOKEN を使う(★値を文書やログに出さないこと★)★preview_start に url を渡して開き直す★。 ★指示書R(D-099 段階3)では Browser pane が使えず curl で代替した★。 ★同じ状況なら curl でよいが、★その旨と「目視できなかった項目」を必ず記録すること★★USE_FIXTURES の true / false で /api/prechecks を突き合わせる★★| # | 項目 |
|---|---|
| 1 | ★severity が "precheck" / "launch_failed" の2値だけであること★(★旧3値が1件も出ないこと★) |
| 2 | ★precheck_minutes が 数値で入り、launch_failed では null であること★ |
| 3 | ★id が 文字列であること★(★"RER-..." 形式。NaN や null が混ざっていないこと★) |
| 4 | ★scheduled_at / detected_at / responded_at / resolved_at が ★+09:00 付き★ であること★ |
| 5 | ★robot_status に英語識別子(例 Handrail Lifted)または Standby. が出ること★。★★日本語(「ハンドルアップ」等)が出たら変換してしまっています★★ |
| 6 | ★resolution_status が unresolved / in_progress / resolved に散っていること★(★全件 unresolved なら段階1-4 のシード補完が効いていない★) |
| 7 | ★battery_level が全件 null であること★(D-090 項8) |
| 8 | ★ソート順が detected_at 降順・同値は id 昇順であること★(D-052) |
/alerts 画面★| # | 項目 |
|---|---|
| 1 | ★/alerts が実DB経由で表示されること(HTTP 200)★ |
| 2 | ★★「◯分前異常」が正しく出ること★★(★precheck_minutes の値がそのままラベルに出る★) |
| 3 | ★「出発失敗」が出ること★(★B案確定。不採用の C案を選んでいた場合のみ出ないのが正しかった★) |
| 4 | ★色分け(severityColor)が launch_failed だけ赤(c.ng)になること★ |
| 5 | ★robot_status のバッジがグレーになること★(★生値は日本語6値に一致しない。想定挙動★) |
| 6 | ★サマリカード(未解消 / 解消 / 全件)の数が items と整合すること★(D-054) |
| 7 | ★EN 表示で対訳が効いていること★ |
| 画面 | 期待 |
|---|---|
★/detail-log / /dashboard / /facilities / /schedules / /ds-logs / /ds-alerts★ |
★200。回帰していないこと★(★特に /detail-log 253件 / /dashboard が 9 / 9。D-099★) |
/reports |
★500★(第5歩) |
[db] xxx のPrisma実装はまだありません。… であること★(lib/db/index.ts:155-159)USE_FIXTURES=true への復帰★read_console_messages でブラウザ側のエラー0件★(★使えなければ「確認できなかった」と記録★)preview_logs でサーバ側のエラーを確認★(★A Node.js module is loaded が出ていないこと★).env.local を USE_FIXTURES=true に戻し、dev サーバを再起動する★★/alerts で fixtures の8件+境界値1件が 正しいラベルで出ること★)。★これを確認して初めて「壊していない」と言えます★USE_FIXTURES=true に戻して全画面が従来どおり動くことを確認した★★docs/decisions.md に追記★着手直前に grep -nE "^### D-(0|1)[0-9][0-9]" docs/decisions.md | tail -3 で最終番号を実測すること★ (★^### D-0 だけでは3桁台を拾えない。^### D-1 も併せて grep すること★。 作成時点の最終は D-101)。
★記録すること★:
severity の新しい設計★★ — ★2値化 + precheck_minutes を採った理由(D-093 項2-2 の案A)★ / ★precheck コード → 分数の対応をどこに閉じ込めたか★ / ★D-091 項4 の切替後にどう変わるか★PrecheckItem.id を string にしたこと★★(D-090 項7 / D-070 1-2 の実装完了)と、 ★影響が出た箇所の一覧★(★特に PathId を変えずインライン化した判断★)detected_at に errored_at / created_at のどちらを使ったか★★と理由battery_level を null にした判断★★(D-090 項8 の解決)と、 ★「事前チェック時点の残量」を取るには何が必要か★(★TeamWorks への照会候補として残す★)launch_failed の DB 表現をどう決めたか★★(★B案で確定。D-103。D-090 項6 の解決★)"出発失敗" 等がこれまで対訳無しだった事実も記録★)robot_status を生値に寄せたか)★と理由status / comment / 4カラム / 本清掃行のエラー行)precheck が 0/1/2 → 0/60/30 に切り替わる時期と 新旧混在の有無(D-091 項4)★ / ★PRECHECK_MINUTES_BEFORE と DB の precheck のどちらが正か (D-093 項3 の未決2)★ / ★precheck に入りうる値の範囲(D-093 項3 の第7回候補)★ / ★error_type の実値(D-090 項18)★npm test のファイル数・テスト数 / tsc / lint。★着手前の基準値との差★)docs/handoff.md に追記★最新は 追記29(docs/handoff.md:2342)★。次は ★追記30★ の見込み。★着手直前に自分で確認すること★。
git add は必ずファイルパスを明示。git add -A は禁止★(禁止事項13).env.local をコミットしないこと★(禁止事項14)。★USE_FIXTURES=true に戻したことを確認してから★git push origin develop(★main へは push しない★)docs/decisions.md に決定番号を追記した(★上記12項目すべて記録★)/ docs/handoff.md に追記した / ★origin/develop へ push 済み★ / ★文書末尾の「実行状態」表を更新した★| 対象 | いつ |
|---|---|
★reportKpis / facilityPerformance / errorBreakdown / continuousProblems★ |
★第5歩★(★サマリテーブル+当期その場集計の共通構造でまとめて★) |
★dsAlerts の security_off 側★ |
★D-091 項3 の内部調整の結果待ち★ |
★PATCH /prechecks/{id}/status の API ルート実装★ |
★別の指示書★(★契約は直すが実装しない★) |
★点検記録2本(inspections / inspectionDetail)★ |
★最後★(D-072 項7) |
★robot_status への formatRawLabel() 適用(D-089 項7 の申し送り)★ |
★別の指示書★ |
launch_failed の DB 表現)は D-103 でB案に解決済み。新たな回答を待たずに段階0 から通しで実行した★npx tsc --noEmit エラー0 / npm run lint 0 / npm test 全パスd-watch-api.yaml の enum が [precheck, launch_failed] になり、precheck_minutes / facility_id / battery_level が定義され、id が string になっていること★★components/parameters/PathId に差分が無いこと★★(他6箇所への巻き込みを避けた)USE_FIXTURES=false で /alerts が 200 で表示され、「◯分前異常」が正しく出ること★precheck_minutes: 20 の fixtures 行が「20分前異常」と表示されること★★(★任意の分数に対応できた証明★)robot_status に英語識別子または Standby. が出ること(生値方針の帰結)★id が文字列で返り、ソート(D-052)が壊れていないこと★USE_FIXTURES=true に戻して全画面が従来どおり動くこと★prisma/schema.prisma / app/api/prechecks/route.ts / prismaSource の既存5メソッド / lib/db/prisma.ts / local-guard.ts / use-fixtures.ts / ds-status.ts / ★サマリ系4本(notImplemented のまま)★ に差分が無いこと★docs/decisions.md / docs/handoff.md の更新 / ★origin/develop へ push 済み★ / 文書末尾の「実行状態」表を更新した| 段階 | 状態 | コミット |
|---|---|---|
| ★着手前の確認★ | ★★なし(すべて解決済み。2026-09-10)★★ — ★判定 = B案★(launch_failed = ★本清掃行に紐づく clean_status_histories の行が無い★。cleanLogs() の departed と同じ判定を共有する)。★記録: docs/decisions.md の D-103(:5222)★ / ★出発失敗の行の埋め方(id / robot_status / resolution_status / note / responded_at / resolved_at)= D-104★。★★新しい仕様判断は1つも要らない★★ |
— |
| 段階0 前提の確認 | ★実施済み★ | コミットなし |
| 段階1 API契約と型 | ★実施済み★ | ★0af0722★ |
| 段階2 fixtures と画面 | ★実施済み★ | ★8cdd299★ |
段階3 prismaSource.prechecks() |
★実施済み★ | ★cbfffc9★ |
| 段階4 動作確認 | ★実施済み(★Browser pane が使えず curl で代替。目視できなかった項目は D-105 項12 に記録★)★ | コミットなし |
| 段階5 記録と push | ★実施済み★ | ★D-105 / 追記30 のコミット★ |
実行日: ★2026-09-10★ / 取得した決定番号: ★D-105★(★着手直前に grep -nE "^### D-(0\|1)[0-9][0-9]" docs/decisions.md \| tail -3 で最終番号 D-104 を実測してから採番。ずれは無かった★) 実測値(着手前 / 完了後): ★41ファイル / 778テスト / tsc 0 / lint 0★ → ★43ファイル / 801テスト / tsc 0 / lint 0★ ★決めたこと★: launch_failed の DB 表現 = ★B案で確定済み(D-103)★ / 出発失敗の行の埋め方 = ★D-104 で確定済み★(id = 本清掃行の clean_timetables.id / robot_status = Standby. / resolution_status = unresolved / note・responded_at・resolved_at = null)/ detected_at のカラム = ★errored_at ?? created_at★(出発失敗の行は ★scheduled_at と同値★。fixtures の前例に揃えた) / battery_level の扱い = ★常に null★(D-090 項8 の解決) / 段階2-4(robot_status を生値に寄せたか) = ★★寄せない(日本語のまま)★★ — ★lib/fixtures/clean-logs.ts が日本語のままで、シードがその値を error_type にそのまま入れているため、片方だけ英語にすると逆に食い違う★ / 変換ロジックの置き場所 = ★lib/db/precheck-mapping.ts を新設★ / clean_timetable_id が null のエラー行 = ★対象外★ / 本清掃行を指すエラー行 = ★対象外(launch_failed に読み替えない)★ 詳細: docs/decisions.md の該当番号を参照