日付: 2026-10-02 / 担当: Cursor / 前提: D-155(本書の根拠)/ D-151 / 指示書AQ / 指示書AR / CLAUDE.md §4.2・§4.3・§4.7・§6・§7・§9.4
★渡す時期: 指示書AR・指示書AT(4カラム UPDATE)と一緒に渡す★(D-155 項6)。 ★当てる順番: AR を先に終えてから AS★(同じファイルのコメントを両方が直すため。§10 を参照)。
★§2 の未決は監督が決定済み(2026-10-02。D-156)★。
min(clean_area ÷ task_area × 100, 100) を ★小数第1位まで切り捨て★clean_task_reports.clean_ratio 列は完了率に使わない★clean_timetable_id が NULL)を外す★。面積の合計には含める(D-155 項3)。clean_task_reports.status)を数字ではなく表示名で出す★(D-155 項2)。判定には使わない。★暫定の仕様である★(「一旦」)。第11回で TeamWorks から訂正後の clean_ratio の式を受け取ったら見直す。 ★だから「1回ごとの完了率を決める関数」は ★1つだけ★ にし、あとで clean_ratio 列に戻すときに ★その1関数を直せば済む★ 形にする。
| いつ | 何が起きたか |
|---|---|
| 2026-09-30(D-151) | 完了率を「clean_task_reports.clean_ratio 列の単純平均」にした。面積比(Σclean_area ÷ Σtask_area)は廃止 |
| 2026-10-02(第10回 N-3 の回答) | TeamWorks: ★clean_ratio 列は「計算式が間違っている。訂正したら回答する」★。★サマリ(*_summaries.clean_ratio)は「清掃1回ごとに clean_area / task_area * 100(100より大きい値は100、小数点第2位以下切捨て)を計算し、合算して平均」★。★precheck = 0 の予定に紐づく行だけが対象で、clean_timetable_id が NULL の行は対象外★ |
| 2026-10-02(D-155) | ★当期(アプリがその場で集計する分)もサマリと同じ式にする★。式が違うと、★前期比(サマリ)と当期(アプリ)の差が、別の式どうしの差になる★ |
★廃止したものと採用するものを取り違えないこと★(いちばん間違えやすい):
| 中身 | 状態 | |
|---|---|---|
| 面積比(D-151 で廃止) | ★期間の合計どうしを割る★ Σclean_area ÷ Σtask_area |
★廃止のまま★。使わない |
| 面積で重み付けした平均 | task_area を重みにした平均 |
★使わない★ |
| ★1回ごとの面積比の単純平均(本書で採用)★ | ★1回ずつ割って、上限100・小数第1位まで切り捨て★、それを ★清掃1回=1票★ で平均 | ★採用★ |
いまのコードには「面積から再計算しない」「面積比は clean_ratio と相関しない」という説明が多数ある。 ★1回ごとの面積比は、本書で正しい計算になる★ので、★それらの説明は直す必要がある★(段階6)。 ただし「Σ面積 ÷ Σ面積は使わない」「面積で重み付けしない」という説明は ★今後も正しい★ので残す。
clean_area は同じ場所を複数回清掃した面積の総和(第10回 N-4)。ユーザー提供CSV 189行では ★68.3% の行が clean_area > task_area★ で、★これらは全部 100% になる★。★◎が多めに出る★。ユーザーはこれを承知で採用した(D-155 項1)。★上限100を外したり、別の補正を入れたりしないこと★。
task_area = 0 で、レポートの行はある清掃をどう扱うか★本書の式では、task_area = 0 の清掃は「1回ごとの完了率 = null」になる★(D-155 項1。分子にも分母にも入れない)。 ところが ★いまのコードは「完了率が null ⟺ 出発していない(未実施)」を前提にしている★ (lib/db/clean-log-mapping.ts:186-190 の不変条件)。この前提で「未実施」を数えている箇所が3つある:
| 箇所 | いまの数え方 | task_area = 0 の清掃がどうなるか |
|---|---|---|
lib/judge/rescue.ts:153(要レスキュー R-1「未実施3日連続」) |
completion_rate === null を未実施とする |
★出発したのに「未実施」に数えられる★ |
lib/db/report-mapping.ts:647(launchFailedDaysInRun()。連続問題施設の「うち{m}日は出発失敗」) |
同上 | ★出発したのに「出発失敗の日」に数えられる★ |
lib/db/clean-log-mapping.ts:323-325(isProblemCompletion()。連続日数) |
null を「問題あり」とする | 問題日に数えられる(判定は × なので、これは整合する) |
詳細ログの1行は ★departed = true(✓)・清掃結果は表示名・完了率 -・判定 ×★ になる(judgeGrade(null) が × を返すため。lib/judge/grade.ts:30)。アドバイスは R1・R2・B1 のどれも出ない(lib/judge/advice.ts:61-83)。
選択肢:
| 案 | 内容 | 帰結 |
|---|---|---|
| ★A(推奨)★ | ★「未実施」は departed で数える★。ConsecutiveInput(lib/db/clean-log-mapping.ts:328)と RescueRowInput(lib/judge/rescue.ts:68)に departed: boolean を足し、R-1 と launchFailedDaysInRun() は !departed を見る |
意味どおりになる。★判定ロジックの入力が1つ増える★ので、表5 の期待値を先にテストで固定する |
| C(最小) | いまの数え方のまま。不変条件が崩れることだけ docstring に書く | 変更が小さい。★task_area = 0 の清掃が R-1・出発失敗日に誤って数えられる★(頻度は不明。第11回で task_area = 0 の扱いを確認中) |
★本書の段階3-4 は案A で書いてある★。★監督が案C を選んだら、段階3-4 の「案Aのみ」と書いた作業と表5 を飛ばす★。
監督の決定: ★案A★(2026-10-02)。理由: CLAUDE.md §4.7「未実施 = 本清掃に対応するレポート行が無いこと」に合う。★レポート行がある清掃を出発失敗に数えると、現場に誤った連絡(R1・R-1)が飛ぶ★。段階3-4 と表5 はそのまま行うこと。
| # | 論点 | 決定 |
|---|---|---|
| 2 | F-08 で期間指定が無いとき、完了率用の行を保持期間(2年)ぶん取ってくる | ★このまま採る★。ただし ★取った行数と所要時間をログに出す★(judge 系の既存イベントに rate_rows / elapsed_ms を足す)。実データで重ければ別途手当てする |
| 3 | 事前チェックの予定・存在しない予定に紐づく行(表4 F3/F4) | ★面積の合計には含め、完了率と実施回数からは外す(表4 のとおり)★ |
| 7 | F-08 で「面積はあるが実施回数0」の施設が出る | ★画面の注記を1行足す★: 「清掃面積には予定外の清掃を含みます。完了率と実施回数は予定された本清掃だけです」(EN: "Area includes unscheduled runs. Completion rate and run count cover scheduled main runs only."。英訳は暫定) |
| 8 | EN 表示で出発失敗のセルが "Launch failed" になる | ★それでよい★(i18n を通すのが正しい) |
| 6 | 面積が負の値 | 特別扱いしない(本書のとおり) |
| 4 / 5 / 9 | clean_timetable_histories の扱い / CLAUDE.md §4.2 の分母の書き方 / docs/code-map.md |
監督が扱う(第11回・CLAUDE.md・別作業)。★Cursor は触らない★ |
| # | 決定 | 理由 | |
|---|---|---|---|
| D1 | ★1回ごとの完了率は lib/judge/kpi.ts の新しい関数 runCompletionRate() だけが決める★。シグネチャ: `runCompletionRate(report: { clean_area: number; task_area: number }): number \ |
null` | ★暫定の式なので、戻すときに1関数で済むようにする★(CLAUDE.md §4.2)。判定層(lib/judge/)は DB 層を import しないので、引数は構造的な型にする(CleanRatioTally と同じ作法。kpi.ts:46-47) |
| D2 | ★上限 100 と小数の桁数 1 は lib/config/index.ts に定数として置く★(例: RUN_COMPLETION_RATE = { cap: 100, decimals: 1 } as const。出所 = 第10回 N-3 を docstring に書く) |
CLAUDE.md §7(数値の直書き禁止)の趣旨に合わせる。式の部品が1箇所に集まる |
|
| D3 | ★切り捨ての前に浮動小数の誤差を吸収する★。方法は次の1つに決める(§5-1): Math.floor(Math.round(raw * 10 ** (decimals + 5)) / 10 ** 5) / 10 ** decimals(decimals = 1 なら Math.floor(Math.round(raw * 1e6) / 1e5) / 10) |
0.57 / 1 * 100 は 56.99999999999999 になり、そのまま切り捨てると 56.9 になる(表1 R6)。★1e-6 ポイント未満の差は誤差とみなす★ |
|
| D4 | ★task_area === 0 なら null★(分子にも分母にも入れない) |
D-155 項1。★暫定・第11回で確認★。task_area は NOT NULL(prisma/schema.prisma:525)なので null の扱いは要らない |
|
| D5 | ★平均の取り方は変えない★ — meanCleanRatio()(kpi.ts:88-91)をそのまま使う。★平均は丸めない★。★判定は生値、表示だけ displayRate()(Math.round)★ |
CLAUDE.md §4.3。切り捨ては「1回ごとの値」だけ |
|
| D6 | ★clean_ratio 列は完了率に使わない。ただし型・select・fixtures からは消さない★(読まないだけ) |
★戻すときに runCompletionRate() の1関数を直せば済むようにするため★。呼び出し側は ★行(clean_ratio も持っている)をそのまま渡し★、呼び出し側で clean_area / task_area だけに分解しないこと |
|
| D7 | ★内部の名前(meanCleanRatio / CleanRatioTally / cleanRatioSum / cleanRatioCount / clean_ratio_sum / clean_ratio_count)は変えない★。docstring で「1回ごとの完了率の合計・件数」と意味を書き直す |
名前を変えると16ファイル・約200行の機械的な差分が中身の変更に混ざり、レビュー(daichi。D-154)で読めなくなる。★暫定の式なので、戻すときにも名前を戻さずに済む★ | |
| D8 | ★judge.areas ログの分子・分母の項目名は、最終的に overall_completion_rate_sum / overall_completion_rate_count にする★(§10) |
中身は「items[].completion_rate の合計と件数」。式の名前(clean_ratio)を項目名に入れると、式を戻したり変えたりするたびに名前と中身がずれる |
|
| D9 | ★総清掃面積(F-08)の完了率と実施回数は、「clean_timetable_id が NULL でなく、その予定が本清掃(precheck = 0)である行」だけで数える★。★面積の合計は全行(予定外を含む)★ |
D-155 項3。サマリと同じ(N-3)。他の画面は既に本清掃の id で引いているので変更不要(§5-4) | |
| D10 | ★清掃結果の表示名は lib/config/index.ts に表で置き、lib/i18n.ts で英訳する★。★表に無い値は生値の数字のまま★(「その他」に潰さない)。★API の task_status は数字のまま★ |
D-155 項2。CLEAN_ERROR_LABELS(lib/config/index.ts:298-316)と同じ形。英語は仮(ユーザーが後でまとめて見直す) |
|
| D11 | ★CSV の清掃結果は日本語の表示名★ | CSV は見出し(lib/clean-logs/csv.ts:63-79)も「出発/未出発」(:103)も日本語固定で、言語を受け取っていない。それに合わせる |
|
| D12 | ★清掃結果(status)は判定に使わない★ |
D-155 項2。中断・異常終了でも完了率で ◎○△× を出す。CLAUDE.md §4.4 の「中断で返る=失敗」は実データを見て見直す(本書の範囲外) |
★表1・表2 は監督が確定した正である。Cursor は値を変えないこと★(CLAUDE.md §0-2・§6-2・§9.4)。 ★段階1 で、実装より先にこの表をテストにする★。表とテストが食い違ったら、テストを表に合わせる。実装の都合で表を直さない。
runCompletionRate| # | clean_area | task_area | 期待値 | 確かめること |
|---|---|---|---|---|
| R1 | 50 | 100 | 50.0 | 基本 |
| R2 | 100 | 100 | 100.0 | ちょうど100 |
| R3 | 150 | 100 | 100.0 | 上限で100に切る |
| R4 | 89.99 | 100 | 89.9 | 四捨五入ではなく切り捨て |
| R5 | 89.95 | 100 | 89.9 | 切り捨て(四捨五入なら90.0) |
| R6 | 0.57 | 1 | 57.0 | 浮動小数の誤差(56.99999…)で56.9にしない |
| R7 | 0.7 | 1 | 70.0 | 同上 |
| R8 | 0 | 100 | 0.0 | 清掃面積0 |
| R9 | 10 | 0 | null | 対象面積0は分子・分母の外 |
| R10 | 1377.39502 | 1377.39502 | 100.0 | 実データの桁 |
| R11 | 898.892509 | 1377.39502 | 65.2 | 65.26…を切り捨て |
| # | 1回ごとの値 | 平均(生値) | 表示 | 判定 |
|---|---|---|---|---|
| M1 | [100.0, 80.0] | 90.0 | 90% | ◎ |
| M2 | [89.9, 90.0] | 89.95 | 90% | ○(表示は90だが判定は○。§4.3) |
| M3 | [100.0, 40.0] | 70.0 | 70% | ○ |
| M4 | [70.0, 69.9] | 69.95 | 70% | △ |
| M5 | [10.0] | 10.0 | 10% | △ |
| M6 | [9.9] | 9.9 | 10% | × |
| M7 | [null, 50.0] | 50.0 | 50% | △(nullは数えない) |
| M8 | [null] / [] | null | — | 未実施と同じ扱い(×・出発失敗の表示は既存どおり) |
| M9 | [150/100→100.0, 150/100→100.0, 0/100→0.0] | 66.666… | 67% | △ |
テストの書き方の注意:
meanCleanRatio() に Σ と件数を渡して出す★(テストの中で自前の割り算を書かない)。null は Σ にも件数にも入れないdisplayRate()(lib/judge/grade.ts:43-46)の戻り。★M8 の「—」は displayRate(null) の "-"★judgeGrade(平均の生値)。★M8 は judgeGrade(null) = ×★runCompletionRate() を通して1回ごとの値を作ってから★平均する(表1 と表2 をつなぐケース)toBe(M2 の 89.95、M4 の 69.95 は JS でそのまま出る。2026-10-02 に node で確認済み)。M9 だけ toBeCloseTo(200 / 3, 10)formatCleanTaskStatus。出所: 第10回 N-2 の原文。D-155 項2)入力(task_status) |
日本語(画面・CSV) | 英語(画面。★仮★) |
|---|---|---|
null(レポートの行が無い) |
出発失敗 | Launch failed(既存キー lib/i18n.ts:208) |
| 0 | 清掃開始前 | Not started |
| 1 | 清掃中 | Cleaning |
| 2 | 清掃中断 | Interrupted |
| 3 | 清掃キャンセル | Cancelled |
| 4 | 清掃正常終了 | Completed |
| 5 | 清掃異常終了 | Ended abnormally |
| 6(CSV実測にある・意味は未受領) | 6 |
6 |
| 255 | 255 |
255 |
★日本語は N-2 の原文から1文字も変えないこと★(言い換え禁止。lib/config/index.ts:291-295 と同じ約束)。 ★「その他」「不明」に潰さないこと★(D-089 項3 / D-104 項2)。
純粋関数(§段階4 の cleanAreaStatsFromRows())に対するテスト。施設はすべて同じ1施設。
| # | その施設のレポート行 | clean_area 合計 |
task_area 合計 |
executed_count |
completion_rate(aggregateCleanArea() の結果) |
|---|---|---|---|---|---|
| F1 | 予定外(clean_timetable_id NULL)100/100 の1行だけ |
100 | 100 | 0 | null |
| F2 | 本清掃 50/100 + 予定外 100/100 | 150 | 200 | 1 | 50.0 |
| F3 | 事前チェック(precheck ≠ 0)の予定に紐づく 80/100 の1行だけ |
80 | 100 | 0 | null |
| F4 | 予定が見つからない id(dangling)80/100 の1行だけ | 80 | 100 | 0 | null |
| F5 | 本清掃 10/0 の1行だけ(task_area = 0) |
10 | 0 | 1 | null |
| F6 | 本清掃 150/100 + 本清掃 0/100 | 150 | 200 | 2 | 50.0((100.0 + 0.0) ÷ 2) |
| F7 | 本清掃の行の clean_ratio 列が 12.3、面積は 50/100 |
50 | 100 | 1 | ★50.0★(★clean_ratio 列を読んでいないことの確認★) |
| # | 清掃 | departed |
completion_rate |
R-1 の未実施日 | 出発失敗の日(launchFailedDaysInRun) |
連続日数の問題日(isProblemCompletion) |
|---|---|---|---|---|---|---|
| U1 | レポートの行が無い | false | null | 数える | 数える | 問題 |
| U2 | ★行がある・task_area = 0★ |
★true★ | ★null★ | ★数えない★ | ★数えない★ | 問題(判定 × と同じ) |
| U3 | 行がある・50/100 | true | 50.0 | 数えない | 数えない | 問題(△) |
| U4 | 行がある・100/100 | true | 100.0 | 数えない | 数えない | 問題なし |
| U5 | 同じ施設・同じ日に U1 と U4 | — | — | その日を1日数える(OR) | その日を1日数える(OR) | 問題 |
| # | 罠 | どう避けるか | |
|---|---|---|---|
| 5-1 | ★浮動小数の誤差で切り捨てが1段下がる★(0.57/1*100 = 56.999… → 56.9) |
D3 の式を使う。★Math.floor(raw * 10) / 10 と書かない★。★toFixed() は四捨五入なので使わない★。表1 R6・R7 で固定する |
|
| 5-2 | ★平均した値を切り捨てる・丸める★ | 切り捨ては1回ごとの値だけ(D5)。★meanCleanRatio() の戻りに手を加えない★。M2・M4 で固定する |
|
| 5-3 | ★periodOfSummaryRow()(lib/db/report-mapping.ts:99)に触る★ |
★触らない★。年次行が月次に化けて500になる(CLAUDE.md §4.7) |
|
| 5-4 | ★サマリの clean_ratio(*_summaries)まで計算し直す★ |
★サマリはそのまま読む★(kpiFromSummaryRatios()。report-mapping.ts:230-240)。★サマリの clean_ratio は既に本書と同じ式★(N-3)。SummaryRatios.clean_ratio(:221)は変えない |
|
| 5-5 | ★生SQL($queryRaw / $executeRaw)で F-08 を集計する★ |
★禁止★(eslint が止める。CLAUDE.md §3)。上限・切り捨ては Prisma の groupBy で書けないので、★行を取り寄せて JS で計算する★(段階4) |
|
| 5-6 | ★閾値・式の数字を直書きする★ | 90/70/10 は GRADE_THRESHOLDS、上限100と桁数は D2 の定数から読む |
|
| 5-7 | ★判定のルールを変える★ | ★変えるのは「完了率の材料」だけ★。judgeGrade()・L1〜L3・アドバイスの条件は変えない(【未決1】案A の「未実施の数え方」だけは例外。表5) |
|
| 5-8 | ★clean_area / task_area を Decimal として扱う★ |
★Prisma の型は Float(number)★(prisma/schema.prisma:525-526。D-094 で double(12,6) に変わった)。Number() 変換も Decimal の import も要らない |
|
| 5-9 | ★呼び出し側で report.clean_area / report.task_area を書く★ |
★必ず runCompletionRate() を通す★。`grep -rn "clean_area /\ |
clean_area\s*\/" lib appで0件にする(runCompletionRate()` の中だけ) |
| 5-10 | ★clean_timetable_id が NULL の行を F-08 の番人と同じ扱いにし忘れる★ |
番人(countDuplicatedTimetables()。lib/db/clean-area-source.ts:292-305)は ★変えない★。完了率用の取り寄せも ★同じ { not: null } で除く★(NULL は1グループにまとまる。同 :272-283) |
|
| 5-11 | ★include でレポート→予定を引く★ |
★使わない★(clean_timetable_id に FK が無い。IN が膨らむ。clean-area-source.ts:56-62)。予定は ★id を集めて chunkForInClause()(lib/db/chunked.ts)で分けて★別クエリで引く |
|
| 5-12 | ★作業ツリーの CleanLogTable.tsx が「変更あり(M)」に見える★ |
2026-10-02 時点で ★git diff の中身は0行★(改行コードだけの差と思われる)。★着手前に git diff components/features/detail-log/CleanLogTable.tsx を見て、自分の変更以外を混ぜないこと★ |
|
| 5-13 | ★git add -A★ |
★禁止★(CLAUDE.md §7)。ファイルパスを明示する |
★各段階の終わりに npx tsc --noEmit -p . と npm test を通すこと★。 ★段階3 で fixtures を使うテストが落ちたら、段階6 の fixtures の作業を先にやってよい★(順番を入れ替えてよいのは fixtures だけ)。 行番号は 2026-10-02 の develop(ef34043)で確かめたもの。★AR を先に当てるとずれる★ので、記述(関数名・文)で探すこと。
lib/judge/__tests__/run-completion-rate.test.ts★ を作る:
it.each で。期待値は toBe(R9 は toBeNull())[null] と [] の2件に分ける)。§4 の「テストの書き方の注意」に従うlib/format/__tests__/clean-result.test.ts(既存)に足す。英語は translate("en", formatCleanTaskStatus(x)) で確かめるit.todo で行だけ並べておく★(書き忘れ防止)runCompletionRate が無い)のが正しい★。コミットはテストだけで1つrunCompletionRate() を作る(lib/judge/kpi.ts)lib/config/index.ts に D2 の定数を足す(GRADE_THRESHOLDS(:18)の近く)。docstring に出所(第10回 N-3 の原文「100より大きい値は100、小数点第2位以下切捨て」。docs/handoff/TeamWorks回答_第10回_20261002.md:73)と「暫定(D-155)」を書くlib/judge/kpi.ts に runCompletionRate() を足す。中身は D3・D4 の通り:
task_area === 0 → nullraw = clean_area / task_area * 100 → Math.min(raw, cap) → D3 の切り捨てclean_ratio 列に戻すときはこの関数の中身だけを直す★/D3 の誤差吸収の理由(R6)/承知している弱点(§1)/★Σ面積 ÷ Σ面積(廃止)とは別物★lib/judge/kpi.ts の既存の説明を直す:
:4-21 — :9 の式を「Σ 1回ごとの完了率 ÷ 件数(1回ごとの完了率 = runCompletionRate())」に。:12-14 は AR 追補2 で一部消える。残りを「完了率は D-155 で TeamWorks のサマリと同じ式にした(暫定)」に書き直すCleanRatioTally(:39-54)— cleanRatioSum は「★1回ごとの完了率(runCompletionRate() の戻り)の合計★」、cleanRatioCount は「その件数。★未実施と task_area = 0 の清掃は数えない★」(D7。名前は変えない)meanCleanRatio() の docstring(:56-87)— 「clean_task_reports.clean_ratio の単純平均」を「1回ごとの完了率の単純平均」に。:80-83 の「★その2つを割って『完了率』と呼ばないこと★(実測で clean_ratio と相関しない)」は ★いまの仕様と逆★ なので、「Σclean_area ÷ Σtask_area(期間の合計どうし)で割らないこと。1回ごとに割るのは runCompletionRate() の仕事」に直す。:65-72(単純平均にする理由)は残すmeanCleanRatio() の中身(:88-91)は変えない★runCompletionRate() に通す★完了率を出している経路は次の表ですべて★(2026-10-02 に grep -rn "clean_ratio" app lib components scripts の全件を分類して確かめた。分類は §8)。
| # | 経路 | 変えるもの |
|---|---|---|
| 3-1 | 清掃詳細ログの1行・アラート・エリア別完了率の行・連続日数・要レスキュー(すべて completionRateFromReport() 経由) |
lib/db/clean-log-mapping.ts |
| 3-2 | レポートKPI(当期) | lib/db/report-mapping.ts |
| 3-3 | 総清掃面積 F-08 | 段階4 |
| 3-4 | 要レスキュー R-1 と出発失敗の日(【未決1】案A のみ) | lib/db/clean-log-mapping.ts / lib/db/consecutive-source.ts / lib/judge/rescue.ts / lib/db/rescue-mapping.ts / lib/db/report-mapping.ts |
lib/db/clean-log-mapping.tsCleanTaskReportLike(:91-107)に clean_area: number / task_area: number を足す。★clean_ratio は残す★(D6。docstring に「完了率には使っていない。runCompletionRate() を clean_ratio 列に戻すときのために残している」と書く)
:101-102「★clean_area / task_area を足さないこと★」は ★いまの仕様と逆★ なので書き直す:94 の prisma/schema.prisma:534 は ★古い★(いまは :531)。直すcompletionRateFromReport()(:194-201)— 行があれば ★return runCompletionRate(report)★。行が無ければ null(いまと同じ)
:163-193)を書き直す。表を「行が無い → null/行があり task_area = 0 → null/それ以外 → runCompletionRate()」の3行にする。「面積から再計算しないこと」(:171-179)は ★逆★ なので消し、D-155 の経緯(D-151 の clean_ratio 列 → D-155 で1回ごとの面積比。暫定)を書く:186-190)を書き直す★: 「departed === false ⟹ completion_rate === null。★逆は成り立たない★(task_area = 0 の清掃は departed === true で completion_rate === null)」。【未決1】の決定(案A/案C)と、その帰結をここに書く:181-184)は ★残す★(clean_area = 0、task_area > 0 なら 0.0。表1 R8)lib/db/__tests__/clean-log-mapping.test.ts: 行の形 { clean_ratio: … } だけで作っているもの(:173・:255-256・:282・:289 ほか)に面積を足す。★clean_ratio 列と面積比が食い違う行★(例: clean_ratio: 12.3, clean_area: 50, task_area: 100 → 50.0)を1件以上入れ、★列を読んでいないこと★を固定する。task_area = 0 → null も足すlib/db/report-mapping.ts(レポートKPI の当期)aggregateCleanStatsByFacility() の :482-484 / :492-493:
const runRate = executed && report !== undefined ? runCompletionRate(report) : null; // … cleanRatioSum: bucket.cleanRatioSum + (runRate ?? 0), cleanRatioCount: bucket.cleanRatioCount + (runRate === null ? 0 : 1),(
runCompletionRate は @/lib/judge/kpi から import。★lib/db/clean-log-mapping.ts は import しない★ — このファイルは未実施の判定を引数で受け取る作りで、依存を増やさない。:442-448)executed と planned の数え方は変えない★(task_area = 0 の清掃も実施1回に数える。完了率の件数にだけ入らない)CleanStatsBucket.cleanRatioSum / cleanRatioCount(:282-295)、CleanStatsReportLike(:391-411。★clean_ratio は残す★。D6)、aggregateCleanStatsByFacility()(:428-437)、kpiFromCleanStats()(:504-505)kpiFromSummaryRatios()(:225-240)と SummaryRatios(:217-223)は変えない★(5-4):265-280(errorCount の説明)は完了率と無関係。★触らない★lib/db/__tests__/report-mapping.test.ts: clean_ratio だけで行を作っているものに面積を足す。clean_ratio 列と面積比が食い違う行で「面積比のほうが使われる」ことを1件固定する。task_area = 0 の行は executed に入り完了率の件数に入らないことを1件固定するcompletionRateFromReport() を通っているので、3-1 で自動的に新しい式になる。★行に面積の列が載っているかだけ確かめた★:
| 経路 | どこで行を読むか | 面積の列 |
|---|---|---|
| 清掃詳細ログ | lib/db/index.ts:802-809(findMany、select なし=全列) |
載っている |
| エリア別完了率 | lib/db/index.ts:1076-1082(同上) |
載っている |
| アラート | lib/db/index.ts:1243-1249(同上。完了率は出さない) |
— |
| 連続日数・要レスキュー | lib/db/consecutive-source.ts:370-392(select あり) |
★clean_area / task_area は既に select にある★(:387-388) |
lib/db/consecutive-source.ts: ★select は変えない★(clean_ratio も残す。D6。テストが select のキーを完全一致で見ている)。コメントを直す: :34-37 / :72-79 / :130-132 / :249-252 / :283-288 / :382-386。要点は「★面積は R-3 の重み付けではなく、runCompletionRate() で1回ごとの完了率を出すために読んでいる★(:265-277 の『列を増やしてよい条件』の条件3 を満たし直した)」lib/db/clean-log-mapping.ts の ConsecutiveInput.clean_area / task_area(:343-362): docstring の「completion_rate を面積から再計算しないこと」(:351-354)は ★逆★。「completion_rate は runCompletionRate() で作ったもの。★ここで割り直さないこと★(規則が2箇所に散る)」に直すlib/judge/rescue.ts: 中身は変えない(completion_rate を受け取るだけ)。コメントを直す: :20-23 / :50 / :72 / :78-84 / :113-118 / :139-142。★「面積加重にしないこと」は残す★(今も正しい)lib/db/rescue-mapping.ts:39-50: 「R-3 は clean_ratio の単純平均」を「1回ごとの完了率の単純平均」に。★「completion_rate から面積を捏造しないこと」(:49)は残す★lib/clean-logs/areas.ts:85-113 / :129-137: 中身は変えない(AR 段階4 で分子・分母の数え方が整理される)。表(:89-92)の「clean_task_reports.clean_ratio の生値」を「1回ごとの完了率(runCompletionRate())」に。:94-98 の経緯は残す(AR §2)lib/db/index.ts: :541(R-3 の説明)/ :695(「clean_ratio から judgeGrade()」→「完了率から」)/ :931-933(「report ? report.clean_ratio : null の形に戻さないこと」は ★今も正しい★。不変条件の書き方だけ 3-1 に合わせる)/ :1020-1026(AR 段階1-5 で直る。AS では「行の完了率は runCompletionRate()」に合わせるだけ)/ :1107-1112lib/types/index.ts の docstring: :109-110 / :247-252 / :296-305 / :312-319 / :344 / :1092-1096departed で数える(★【未決1】が案A のときだけ★)lib/judge/__tests__/rescue.test.ts に U1〜U5、lib/db/__tests__/report-mapping.test.ts に launchFailedDaysInRun() の U1〜U5、lib/db/__tests__/consecutive-source.test.ts に departed の詰め方)ConsecutiveInput(lib/db/clean-log-mapping.ts:328)に departed: boolean を足す(必須。optional にしない)
consecutiveInputsFromRows()(lib/db/consecutive-source.ts:242-256): departed: !notExecutedFromReport(report)rescueInputsFromCleanLogs()(lib/db/rescue-mapping.ts:51-68): departed: log.departedRescueRowInput(lib/judge/rescue.ts:68-76)に departed: boolean を足す。foldRescueDays() の :153 を const notExecuted = !row.departed; に。★completion_rate の Σ と件数は null を数えないまま★(:154-155)launchFailedDaysInRun()(lib/db/report-mapping.ts:647)を const isFailed = !row.departed; に。docstring :629-630 の不変条件の記述を直すisProblemCompletion()(lib/db/clean-log-mapping.ts:323-325)は変えない★(表5 U2 のとおり、null は問題日のまま)lib/judge/rescue.ts:16 の表(「R-1 … completion_rate === null が3スケジュール日以上連続」)を「departed === false」に直す★いまは groupBy + _sum で施設ごとに clean_ratio を合計している(lib/db/clean-area-source.ts:249-263)。 ★上限100・切り捨ては groupBy で書けず、生SQL は禁止(5-5)★なので、★完了率と実施回数の材料は行を取り寄せて JS で作る★。 ★面積の合計は今までどおり groupBy で作る★(予定外を含む全行。行を運ばない)。
lib/db/clean-area-source.tsCleanAreaFacilityGroupRow(:73-77)と groupBy の引数(:102-111 / :253-261)から ★clean_ratio の _sum と _count を外す★(使わなくなる)。面積の _sum は残す{ facility_id: bigint; clean_timetable_id: bigint | null; clean_area: number; task_area: number; clean_ratio: number }(★clean_ratio は読まないが select に入れる。D6★)CleanAreaStatsSourcePrisma(:102-111)に次の2つを足す(テストからスタブを渡せる最小の形。既存の作法どおり):
cleanTaskReport.findMany({ where: CleanAreaWhere & { clean_timetable_id: { not: null } }, select: { facility_id, clean_timetable_id, clean_area, task_area, clean_ratio } }) — ★where は集計・番人と同じものに { not: null } を足しただけ★(countDuplicatedTimetables() の :299 と同じ形)cleanTimetable.findMany({ where: { id: { in: bigint[] }, precheck: number }, select: { id: true } }) — ★precheck は CLEAN_TIMETABLE_PRECHECK.main(lib/config/index.ts:226-229)。0 を直書きしない★cleanAreaStatsFromRows(groupRows, reports, mainTimetableIds: ReadonlySet<string>) を足す★(cleanAreaStatsFromGroupRows()(:219-232)を置き換える):
groupRows から(_sum の null は 0。いまと同じ)reports のうち ★clean_timetable_id が null でなく、mainTimetableIds に入っているものだけ★(★「本清掃の集合に入っている」という肯定条件で数える。errorCountByMainTimetable()(report-mapping.ts:377-389)と同じ考え方★。dangling・事前チェックの行はこれで自然に落ちる):
executed_count += 1const rate = runCompletionRate(report)。null でなければ clean_ratio_sum += rate / clean_ratio_count += 1groupRows に無い施設の行が reports に来たら例外を投げる★(同じ where を使っていれば起きない。起きたら where の食い違いなので、黙って足さない)facility_id は Number() に通す(:197-199 の罠。いまと同じ)CleanAreaFacilityStats は変えない(clean_ratio_sum は number | null のままでよいが、常に数値を入れる)loadCleanAreaFacilityStats(prisma, where)(:249-263)— ★関数名とシグネチャは変えない★(:242)。中で:
groupBy(面積)と findMany(完了率用の行)を Promise.all でclean_timetable_id を重複なしで集め、chunkForInClause() で分けて cleanTimetable.findMany(★塊が0個ならクエリを撃たない★。lib/db/chunked.ts:12-15)toString() して Set にし、4. の純粋関数に渡す:17-26(「完了率に面積を使わない」→「1回ごとの完了率に面積を使う。Σ面積 ÷ Σ面積 は使わない」)、:194-218(executed_count の意味が「本清掃に紐づくレポートの行数」に変わった。★予定外を含まない★)、:234-247(★「groupBy を使う(行を運ばない)」は面積だけになった。完了率用の行は運ぶ★。理由: 上限・切り捨てが groupBy で書けず、生SQL は禁止)countDuplicatedTimetables()(:265-305)は ★変えない★。:285-287「除いた NULL 行の面積は集計側では足されている」は今も正しいlib/db/index.ts の cleanArea()(:1782-1861):1846-1854)は変えなくてよい(loadCleanAreaFacilityStats() の中で済む):1786-1794 を直す: ★「行を運ばない」「行を取り寄せてJSで足すと期間を広げた瞬間に破綻します」は、完了率用の取り寄せには当てはまらなくなった★。★なぜ運ぶことにしたか(上限・切り捨て・生SQL 禁止)★と、★運ぶのは clean_timetable_id が NULL でない行の5列だけ★であることを書く。★期間を指定しないと全期間(保持2年)を運ぶ★ことも書く(性能は §11 で監督が判断する)lib/db/fixture-clean-area.ts:49-88):71-74 / :83-84 の clean_ratio_sum に row.completion_rate を足している所を、★runCompletionRate(row) を通した値★にする(null なら Σ にも件数にも足さない)。executed_count は今のまま(completion_rate !== null の行=レポートがある行を数える)lib/fixtures/areas.ts)には予定外の行が無い★ことを docstring に書く(予定外を外す規則は 4-1 の純粋関数のテスト=表4 で確かめる)USE_FIXTURES の true/false で数字が変わらないこと★は、段階6 で fixtures の面積を作り直した後に lib/db/__tests__/fixture-clean-area.test.ts で確かめるlib/types/index.ts の CleanAreaFacilityStats(:1202-1242)・CleanAreaRow(:1287-1303)・CleanAreaTotal(:1316-1322)の docstring: executed_count は「本清掃に紐づくレポートの行数(予定外を含まない)」、clean_area / task_area は「予定外を含む全行の合計」、completion_rate は「1回ごとの完了率の単純平均」d-watch-api.yaml: :876-886(GET /clean-area の説明)/ :2002-2004 / :2016-2023 / :2024-2027 / :2082-2085 / :2086-2089。★面積の合計と実施回数・完了率で母集団が違う★ことを明記する(面積は予定外を含み、回数・完了率は含まない)lib/db/__tests__/clean-area-source.test.ts: 表4 の F1〜F7 を純粋関数 cleanAreaStatsFromRows() に対して書く。スタブで loadCleanAreaFacilityStats() を通し、★findMany の where に clean_timetable_id: { not: null } が付くこと★、★cleanTimetable.findMany の where に precheck: CLEAN_TIMETABLE_PRECHECK.main が付くこと★、★行が0件なら cleanTimetable.findMany を呼ばないこと★を固定するlib/clean-area/__tests__/aggregate.test.ts / app/api/clean-area/__tests__/route.test.ts は形が変わらないので、落ちたものだけ直すlib/config/index.ts の cleanErrorLabel()(:314-316)の後ろに足す:
export const CLEAN_TASK_STATUS = {
notStarted: 0, cleaning: 1, interrupted: 2, cancelled: 3, completed: 4, endedAbnormally: 5,
} as const;
export const CLEAN_TASK_STATUS_LABELS: Readonly<Record<number, string>> = { /* 表3 の日本語 */ };
export function cleanTaskStatusLabel(status: number): string {
return CLEAN_TASK_STATUS_LABELS[status] ?? String(status);
}docstring: 出所(第10回 N-2 原文。docs/handoff/TeamWorks回答_第10回_20261002.md:63)/★原文から1文字も変えない★/★表に無い値は生値(CSV実測の 6 など。意味は未受領・第11回で確認)★/★判定には使わない(D-155 項2)★/CLEAN_ERROR_LABELS とは ★別のテーブルの別のコード表★(clean_status_histories.clean_error)で、★互いに読み替えない★
CLEAN_ERROR の docstring(:231-274。該当は :239)の「status をこのコード表で読み替えないこと(値の意味が未受領)」は「status には別の表(CLEAN_TASK_STATUS_LABELS)がある」に直すlib/format/clean-result.ts:
formatCleanTaskStatus()(:58-64): null → CLEAN_RESULT_NOT_DEPARTED_LABEL(いまと同じ)、それ以外 → cleanTaskStatusLabel(status):1-45)を書き直す。「★status は生値をそのまま返す★」「画面には 4 のような数字がそのまま出る。それが意図した挙動」(:11-22)は ★いまの仕様と逆★。★関数名を改名した理由(:24-29)と null を「出発失敗」と出す根拠(:31-41)は残す★:50-57 の @returns を直すlib/i18n.ts: 表3 の6語の英訳を足す(出発失敗(:208)の近く。★「英語は仮。ユーザーが後でまとめて見直す」とコメント★)。重複キーは lint が落とすので、既存キーと重ならないことを確かめる(2026-10-02 時点で6語とも未登録)components/features/detail-log/CleanLogTable.tsx:221-226: セルを t(formatCleanTaskStatus(r.task_status)) にする。コメント(:221-225)を「表示名を t() に通す。表に無い値は数字のまま(辞書に無いので t() も数字を返す)」に直す。★status_1h / status_30m の Pill は変えない★
lib/clean-logs/csv.ts: :104 は変えない(formatCleanTaskStatus() が日本語の表示名を返すようになるので、そのまま日本語が出る。D11)。見出しのコメント :72-75「中身は status の生値(例 4)で、日本語に変換しない」を直すd-watch-api.yaml の task_status(:1682-1700): ★型は integer のまま★。description を書き直す — 値の意味(表3)、表に無い値は画面・CSV で数字のまま、★判定には使わない★、null の意味(いまと同じ)。:1688-1692(「値の意味は未受領」「推測で変換しない」)は ★古い★lib/format/__tests__/clean-result.test.ts:57(0 → "0")は逆の仕様なので "清掃開始前" に直す(:61 の 255 → "255" は今も正しい)。lib/clean-logs/__tests__/csv.test.ts:219 も同様に確かめる★。lib/clean-logs/__tests__/csv.test.ts で清掃結果の列が日本語の表示名になること(例: 4 → 清掃正常終了、6 → 6、null → 出発失敗)lib/fixtures/clean-task-reports.ts(★作り直し★)いまは ★面積を clean_ratio から独立に作っている★(設計上の約束3。:46-51)。★本書の式では完了率が面積から決まる★ので、このままだと ★DB 経由(USE_FIXTURES=false。シードを入れたローカルDB)で docs/fixtures.md §2.1 の境界値(90.1 / 90.0 / 89.5 / 70.1 / 70.0 / 10.1 / 10.0 / 9.9 / 0)がすべて壊れる★。
cleanTaskReportCleanArea()(:190-205)を「完了率から面積を作る」形に変える。引数に完了率を足す(例: cleanTaskReportCleanArea(taskArea, completionRate, cleanTimetableId)):
clean_area = round6(task_area × 完了率 ÷ 100)clean_area = round6(task_area × 係数)、係数は pseudoRandom() で 1.00〜1.40(★task_area を超える行の再現。上限100の確認になる★)runCompletionRate({ clean_area, task_area }) が元の完了率に一致すること★を 2026-10-02 に node で確かめた(task_area が小数第6位まである200通り × 完了率 0.0〜100.0 の0.1刻み、20万件で不一致0件)。★それでもテストで全行を確かめること★(下の 4.)build() の :342 で完了率を渡す。clean_ratio(:343-344)は ★log.completion_rate のまま残す★(D6。戻すときに fixtures を作り直さずに済む)。コメントを「clean_ratio 列は完了率に使っていない。列に戻すときのために、清掃ログの完了率と同じ値を入れてある」に:26-27 / :41-51)と CLEAN_AREA_BELOW_TASK_AREA_SHARE(:177-188)を直す。★約束3(面積を clean_ratio から逆算しない)は廃止★し、理由(D-155 で完了率が面積から決まるようになった)を書く。:87-88 の clean_ratio の説明も
lib/fixtures/clean-logs.ts:230-241)ので、★clean_area > task_area の行は0件になる★。CSV の分布(68.3%)の再現はやめるlib/fixtures/__tests__/clean-task-reports.test.ts:
runCompletionRate(row) === 対応する清掃ログの completion_rate:147-154(過半数が task_area 超え)/ :156-164(clean_ratio が面積比と一致しない)/ :166-171(面積比100%超で clean_ratio が低い)。★いまの仕様と逆★:50-61(clean_ratio が清掃ログの完了率と同じ)は残してよい(D6)scripts/seed-local-db.ts:657 の呼び出しに完了率(params.completionRate)を渡す。:645 のコメント(「決定4 でこれが clean_ratio になる(面積から逆算しない)」)と :675-676 を直す。:2127 のログ(clean_area > task_area の割合を CSV実測 68.3% と並べて出す)は、0% になることをコメントに書けば残してよい
lib/db/local-guard.ts)には触らない★。★シードを流すのは任意★。流すなら dwatch_local だけ(ガードが他を拒否する)。★ステージングには絶対に向けない★(CLAUDE.md §3)lib/fixtures/areas.ts:201 の round1(…) を ★round6(小数第6位)★ にする。round1 だと task_area = 120 のような値で完了率が1段ずれる(2026-10-02 に node で確認。いまの施設は 1000 / 100 なのでずれないが、面積を変えた人が踏む):18-24 と :63-69 の説明を直す(「面積は全体率の計算に使われない」→「行の完了率は面積から runCompletionRate() で決まる。全体率は行の完了率の単純平均」):115-116 の「旧定義の面積ベース 802/1200 = 66.83…%」は残す★(AR §2。Σ面積 ÷ Σ面積 に戻っていないことの確認で、今も意味がある)。:115 の「clean_ratio の単純平均」だけ「行の完了率の単純平均」にlib/fixtures/__tests__/areas.test.ts に ★全行で runCompletionRate(row) === row.completion_rate(completion_rate が null の行を除く)★ を足すdocs/fixtures.md:107-133): :116-118 の「全体率は各行の clean_ratio の単純平均」を「行の完了率(runCompletionRate())の単純平均」に:137-220): :160-161(CSV の形の説明)は実測なので残す。:170(ケース #2)を「clean_area を清掃ログの完了率から作る(clean_ratio 列にも同じ値)」に、:175(ケース #7「面積比と clean_ratio の乖離」)を ★削除★して「完了率100の行は task_area を超える面積にする(上限100の確認)。ただし fixtures の清掃ログには完了率100が無いので該当0件」に置き換える。:212-220 に D-155 の経緯を1行d-watch-api.yaml(完了率の説明)clean_task_reports.clean_ratio を完了率の出所として書いている所を、すべて「1回ごとの完了率(min(clean_area ÷ task_area × 100, 100) を小数第1位まで切り捨て。task_area = 0 は除く)の単純平均。D-155(暫定)」に直す: :338-343 / :348-350 / :563-566 / :595-602 / :1701-1710(★:1707「clean_ratio の生値(面積から再計算しない)」は逆★。:1708「行が無いとき null」に「task_area = 0 のときも null」を足す)/ :1757-1760。 段階4・段階5 で直した所と合わせて、★grep -n "clean_ratio" d-watch-api.yaml の残りが「サマリの列(*_summaries.clean_ratio)」の説明か、経緯の説明だけになること★。
| ファイル:行 | いま | 直し方 |
|---|---|---|
lib/reports/target-customer.ts:12 |
清掃完了率の合算「★できる★」(分子 clean_area / 分母 task_area) |
★「★できない★(1回ごとの完了率の合計と件数がサマリに無い。clean_area / task_area の合計で割ると Σ面積 ÷ Σ面積 になり、サマリの式と違う)」★ |
lib/clean-area/aggregate.ts:5 / :16-19 / :145 / :158 / :188 / :221-222 |
「clean_ratio の単純平均」「clean_ratio の Σ」 |
「1回ごとの完了率の単純平均」「1回ごとの完了率の Σ」。★中身は変えない★ |
lib/judge/__tests__/rescue.test.ts:42 / :215-231 / :271-275 |
「clean_ratio の生値」「面積比162.8%の行でも clean_ratio の 61 を使う」 |
テストの中身(completion_rate を直接渡している)は今も正しい。名前と説明を「1回ごとの完了率」に。3-8・3-9 は「判定は面積を読まず、渡された completion_rate だけを使う」ことの確認として残す |
lib/db/__tests__/consecutive-source.test.ts:72 / :79 / :118-122 |
clean_ratio = 50 → completion_rate = 50 |
面積を足し(例 50/100)、期待値は表1 に従う |
components/features/detail-log/AreaModal.tsx:39 |
AR 段階1-4 で直る | AS では「行の完了率」の出所を runCompletionRate() に合わせるだけ |
★最後に次の grep を流し、残ったものを §8 の分類に当てはめる★:
grep -rn "clean_ratio\|面積から再計算\|相関しない" app lib components scripts d-watch-api.yaml docs/fixtures.md --include=*.ts --include=*.tsx --include=*.yaml --include=*.md | grep -v "lib/generated"
npx tsc --noEmit -p . — エラー0件npm run lint — 指摘0件($queryRaw を使っていないこと・any が無いこと)npm test — ★全件通過★npm run build — 成功USE_FIXTURES=true)★: .claude/launch.json の d-watch-fixtures(ポート 3100)で起動する
6 のまま★、施設12 は「出発失敗」6、出発失敗は "Launch failed"/clean-area): 画面が開き、完了率と実施回数が出るjudge.areas ログ★(エリア別詳細を開いたときに標準出力に出る)に overall_completion_rate_sum / overall_completion_rate_count が出て、raw_overall_completion_rate と割り算が合うこと| ファイル | 内容 | 段階 |
|---|---|---|
lib/judge/__tests__/run-completion-rate.test.ts(新設) |
表1・表2 | 1 |
lib/format/__tests__/clean-result.test.ts(既存に追加) |
表3 | 1 / 5 |
lib/db/__tests__/clean-log-mapping.test.ts |
面積から完了率/clean_ratio 列を読まない/task_area = 0 |
3-1 |
lib/db/__tests__/report-mapping.test.ts |
当期KPI の完了率が面積から/task_area = 0 は実施に入り件数に入らない/(案A)launchFailedDaysInRun 表5 |
3-2 / 3-4 |
lib/judge/__tests__/rescue.test.ts |
(案A)表5 の R-1 | 3-4 |
lib/db/__tests__/consecutive-source.test.ts |
面積を足す/(案A)departed |
3-3 / 3-4 |
lib/db/__tests__/clean-area-source.test.ts |
表4 F1〜F7/where と precheck/0件でクエリを撃たない |
4 |
lib/db/__tests__/fixture-clean-area.test.ts |
runCompletionRate() 経由/数字が変わらない |
4 |
lib/clean-logs/__tests__/csv.test.ts |
清掃結果が日本語の表示名 | 5 |
lib/fixtures/__tests__/clean-task-reports.test.ts |
全行で面積から完了率が一致/逆の仕様のテスト3件を削除 | 6 |
lib/fixtures/__tests__/areas.test.ts |
全行で面積から完了率が一致 | 6 |
app/api/clean-logs/[id]/__tests__/route.test.ts |
judge.areas の項目名(§10) |
6 |
clean_ratio の使われ方の分類(2026-10-02。grep -rn "clean_ratio" app lib components scripts)| 分類 | 何か | 扱い |
|---|---|---|
★完了率の材料(clean_task_reports.clean_ratio 列)★ |
lib/db/clean-log-mapping.ts:106 / :200、lib/db/report-mapping.ts:408 / :492、lib/db/clean-area-source.ts:75 / :107 / :229 / :258、lib/db/fixture-clean-area.ts:73 / :83 |
★runCompletionRate() に置き換える★(段階3・4)。型・select からは消さない(D6) |
★サマリの列(*_summaries.clean_ratio)★ |
lib/db/report-mapping.ts:221 / :237 / :521(prev?.clean_ratio) |
★そのまま★(5-4。既に本書と同じ式) |
| 内部の合計・件数の名前 | cleanRatioSum / clean_ratio_sum ほか(16ファイル) |
★名前は変えない★(D7)。docstring だけ直す |
select の列 |
lib/db/consecutive-source.ts:116 / :377 |
★残す★(D6) |
| fixtures・シードが列に入れる値 | lib/fixtures/clean-task-reports.ts:88 / :344、scripts/seed-local-db.ts:676 ほか |
★残す★(D6)。説明だけ直す |
clean_status_histories 側のシード |
scripts/seed-local-db.ts:1280-1318 / :1476-1478 / :1706-1730、サマリのシード :1835-1885 |
★触らない★(旧テーブル・サマリの仮値。本書と無関係) |
| 説明(コメント・API 定義) | 上の段階3〜6 で挙げたもの | 直す |
| 経緯として書かれた説明(「旧:」「以前は」「廃止」) | 例 lib/clean-logs/areas.ts:94、lib/fixtures/areas.ts:116 |
★残す★(AR §2 と同じ) |
| 生成物 | lib/generated/prisma/** |
★触らない★ |
★完了率の画面表示は、どの画面も completion_rate を displayRate() に通すだけ★で、clean_ratio を直接表示している画面は無い(grep -rn "clean_ratio" components は AreaModal.tsx:39 のコメント1件だけ)。
prisma/schema.prisma(★DB の定義は TeamWorks の領域★。CLAUDE.md §7)lib/generated/prisma/**scripts/seed-local-db.ts の ★接続先とガード★(lib/db/local-guard.ts を含む)。★変えてよいのは 6-1 の5. の呼び出しとコメントだけ★CLAUDE.md / docs/decisions.md(監督が直す)docs/code-map.md(監督が直す。§11)status / comment / responded_at / resolved_at)★ — 指示書AT の範囲periodOfSummaryRow()(lib/db/report-mapping.ts:99)と kpiFromSummaryRatios()(:230-240)countDuplicatedTimetables()(lib/db/clean-area-source.ts:292-305)judgeGrade() / displayRate() / isProblemGrade() / matchAdviceRules() / GRADE_THRESHOLDS(判定の規則は変えない。5-7)CLEAN_ERROR / CLEAN_ERROR_LABELS の値(lib/config/index.ts:275-304。docstring の1文を直すだけ。段階5-1)CLAUDE.md §4.4 の「中断で返る=失敗」に関わる判定(D12。実データを見てから)| AR の段階 | 本書との関係 |
|---|---|
段階1-3 / 1-4 / 1-5(areas/route.ts:126 / AreaModal.tsx:39 / lib/db/index.ts:1023 のコメント) |
AR で「全体率は行の完了率の単純平均」に直す。★本書では「行の完了率 = runCompletionRate()」を足すだけ★ |
追補2(lib/judge/kpi.ts:12-14 の句を削る) |
AR で削ったあと、本書の段階2-3 で冒頭を書き直す |
★段階4(judge.areas の項目)★ |
★AR のとおり overall_clean_area / overall_task_area を消して overall_clean_ratio_sum / overall_clean_ratio_count を足す★。★そのあと本書で、この2つを overall_completion_rate_sum / overall_completion_rate_count に改名する★(D8) |
AR と AS を当てたあとの JudgeAreasLogEvent(lib/logger/events.ts)の最終形:
| 項目 | 中身 |
|---|---|
raw_overall_completion_rate |
全体率(丸める前)。いまと同じ |
★overall_completion_rate_sum★ |
全体率の分子 = ★completion_rate が null でない行の completion_rate(=1回ごとの完了率)の合計★ |
★overall_completion_rate_count★ |
全体率の分母 = その行数 |
overall_clean_area / overall_task_area / overall_clean_ratio_sum / overall_clean_ratio_count |
★出さない★ |
lib/logger/events.ts:158-171)に ★raw_overall_completion_rate === overall_completion_rate_sum / overall_completion_rate_count(分母0なら null)★ と、★項目名に式の名前を入れなかった理由(D8)★を書くapp/api/clean-logs/[id]/__tests__/route.test.ts)の項目名も合わせて直す。★AR と AS を同じ日に続けて当てるなら、AR 段階4 を最初から最終形の名前で入れてもよい★(最終形が上の表と同じなら可)docs/code-map.md(:22 / :785 / :857-884 / :947 / :1603-1609 / :2159 / :2336 / :2377 / :2408 に D-151 の定義が書いてある)task_area = 0 の扱い・status = 6 の意味・訂正後の clean_ratio・clean_timetable_histories の扱い)段階ごとに分ける(例: 段階1 / 段階2 / 段階3 / 段階4 / 段階5 / 段階6)。★git add はファイルパスを明示する★(git add -A 禁止)。 メッセージには ★何を変えたか★ と ★なぜ(D-155。TeamWorks 第10回 N-2 / N-3)★ を書く。★段階1 のコミットは「テストだけ(この時点では落ちる)」と明記する★。