💻 システム開発

SCALE_Base_最新基準点

最終更新 2026年06月23日 / 31_システム開発部/_SCALE_Base_最新基準点.md

SCALE Base 最新基準点(2026-06-01 更新・v1.271)

2026-06-01 事故まとめ&再発防止(必読)

今日 v1.267〜271 の連続デプロイ中に「画面崩れ・黒画面・ビルド不能」が連発した。真因は2つ:

事故①: Google Drive 同期事故(最重要・根本原因)

  • scale-base は Google Drive 上にあるため、同期コンフリクトで「ファイル名 2.ext」という重複コピーが作られ、本体ファイルが消える
  • 今日消えた本体: lib/tools-library.ts(→MODULE_NOT_FOUNDでビルド不能)/ postcss.config.mjs(→Tailwind効かずCSS 28KBの不完全版に→素HTML表示・画面崩れ)/ public/*.svg,png(ロゴ等欠損)
  • CSS正常版は152KB。28KBになっていたら postcss.config 欠損を疑う
  • 再発防止(実装済 v1.271 ce-06-01-05): scripts/check-drive-conflicts.sh 新設 + deploy.sh Step0 で自動チェック(重複/必須欠損があれば deploy 中止)。bash scripts/check-drive-conflicts.sh --fix で重複削除+git復元

事故②: HTMLキャッシュで黒画面(v1.270 ce-06-01-04 で対処済)

  • _headers のデフォルト * → max-age=300(5分) が末尾スラッシュURL(/home/等)に適用→古いHTMLが5分キャッシュ→短時間の連続デプロイで buildId が変わり旧JSが消え ChunkLoadError→スプラッシュで黒画面
  • 対処: HTMLルートを no-cache/_next/static/* のみ immutable

事故③: デプロイ認証失効(API Token方式で恒久化)

  • wrangler OAuth が 403 失効。~/.cf_token(API Token)を export CLOUDFLARE_API_TOKEN="$(cat ~/.cf_token)" でデプロイ

** 教訓: ①Drive上のプロジェクトは「" 2"重複でファイル消失」が構造リスク→デプロイ前ガード必須(導入済) ②Next.js静的×Pagesは末尾スラッシュURLを no-cache に ③連続 --clean デプロイは buildId 毎回変化で要注意 ④デプロイ完了は version.json で必ず確認(背景デプロイの途中停止に注意) ⑤根本対策候補: 正本をDrive外(ローカル+GitHub)へ移すと①が構造的に解消**

最新スタンプ: changelog ce-2026-06-01-05 / baseline 2026-06-01_post-deploy-v1271 / app v1.271


2026-06-23 08:50 更新(ce-2026-06-23-01 / app v1.313 → v1.314)【未使用12システム一括削除+ホームのカードランチャー撤去】

大串FB: 「SCALE Baseに入れてるけど全然使ってないものがある。サイト自体とセクションごと全削除したい」「このホーム画面もいらない、左にバーがあればそこから行ける」

削除した12システム(機能・セクションごと全撤去):
Command Center / Design Studio / Writing / SEO / HP管理 / Recruit(hr) / サービス管理 / Data Lake / AI Ops / Partners & Academy / Brand & PR / R&D Lab

撤去範囲:
- app/(dashboard)/<id> 実ページ 約130枚(各 layout.tsx 含む)
- lib/systems.ts:systems登録・SystemId型・departmentGroups・SYSTEM_ABSORBED(pipeline/automation撤去) を整理 → 部署グループは 全体 / 事業 / マーケティング / コーポレート の4つ
- lib/subnav-groups.ts:削除12システムのサブナビ定義を撤去
- 専用AI関数4本(functions/api/ seo-audit・seo-generate・design-feedback・writing)
- 孤立lib 11本(seo-data・seo-types・design-data・command-data・datalake-data・recruit-database/mock/types/utils・hp-showcase-data・ai-extensions-data・pinterest-gallery)

ホーム撤去: home/page.tsx のカードランチャーを廃止 → /home/tasks/work-log(作業報告)へリダイレクトするスタブに。ログイン後着地(app/page.tsx)とサイドバーロゴ(SystemSidebar.tsx)も作業報告へ。左サイドバーがナビの単一導線

据え置き(今回は未削除): ナビ外残骸 dir = automation / insight / pipeline / cmo / pm / system-mgmt / fs-local(別掃除タスク)。これらの subnav/lib(automation-data・trending-data・tools-library 等=残存利用あり)は保持。

保持システム: tasks(Task) / sites(サイト一覧) / pass●●●●●●(PW管理) / admin(管理) / scheduling(日程調整) / contracts(契約書対応) + 外部リンク(SCALE CRM・SCALE Lead・TERASU・SCALE Build・X・Finance・Obsidian)

検証: ✅ ビルド成功(型エラー/参照切れ0)・本番 version.json v1.314・GitHub Actions success・保持ルート全200・削除12ルート404・out/ から12ルート消滅確認

バックアップ: ~/scale-base-backups/scale-base_2026-06-23_083759_pre-mass-delete.tar.gz(削除前・復元ポイント)

git: push済(9ac2f62・160 files changed / 23,552 deletions)

** 補足(Drive同期注意): この基準点ノートは開いた時点で Drive同期により v1.301 版に戻っていた(2026-06-20のPW管理改修 v1.302〜310・中断報告Slack化 v1.312・初期値プレフィル撤去 v1.313 が本文未反映)。欠落分の詳細は lib/changelog.ts(正本)参照**。本更新で frontmatter を v1.314 にスタンプ。

最新スタンプ: changelog ce-2026-06-23-01 / app v1.314 / デプロイ=git push自動化


2026-06-16 10:45 更新(ce-2026-06-16-01 / app v1.300 → v1.301)【日報Slackの定例タスクをPJTグループ化・全報告統一】

大串FB: 「定例タスクはPJTがあってグループ化されてると思う。その括りで見やすいようにSlack通知して」(朝日報の定例がフラット羅列のスクショ・細川さん35件)

真因/背景:
- 画面UI(朝日報の定例選択)は既に groupByPjt でPJTグループ表示していたが、Slack文面だけフラット羅列だった
- 定例が多い日は縦長で見づらい

実装(案A・大串承認済み):
- 共通ヘルパー新設(lib/report-notify.ts): formatRoutinesByPjtForSlack(PJTグループ化+グループ見出し+個別タスク)/ routineSectionLabel(セクション見出し・総件数/合計時間)。グループ化は画面UIと同じ lib/pjt-infergroupByPjt(project優先→名前推論)
- 全4報告に適用: 朝日報(今日やる定例)/ 作業開始(定例)/ 夜日報(やった定例を通常と分離)/ 作業終了(完了した定例)
- グループごとに「件数 / 合計時間」、件数の多い順(画面UIと同じ並び)

見え方(実データ再現):

*▼ 今日やる定例タスク(35件・合計10時間40分)*
*X*  17件 / 5時間35分
・X コメント返信・朝(大串垢) (10分)
…
*LinkedIn*  8件 / 1時間5分
…

決定事項(AskUserQuestion):
- フォーマット = 案A(グループ+個別タスク)
- 「X1件引用(大串)」が別グループ(X1)になる癖 = そのまま(pjt-infer 不変)
- 横展開 = 朝/開始/終了/夜の全報告統一

不変(退化禁止):
- グループ化は画面UIと同じ groupByPjt。night の定例判定は「bottomTasks との名前一致」。これを名前以外に変えると退化
- end の削除済み定例IDは素のidで救済表示(従来挙動維持)

検証: ✅ version.json v1.301/ce-2026-06-16-01・型チェックOK・実データ再現で案A通り

ファイル: lib/report-notify.ts / morning・start・night・end の page.tsx / lib/changelog.ts / CLAUDE.md

バックアップ: pre 2026-06-16_104252_pre-deploy / post 2026-06-16_104336_post-deploy

git: push済(c598fb5)

最新スタンプ: changelog ce-2026-06-16-01 / baseline 2026-06-16_104336_post-deploy / app v1.301


2026-06-12 20:45 更新(ce-2026-06-12-04 / app v1.299 → v1.300)【夜日報の本日分/昨日分の導線混乱を解消】

大串FB: 「本日のよる日報を提出しようとしたら昨日の出るんだが」(スクショ: ?date=2026-06-11 遅延提出モードが開いている)

真因(導線調査で確定):
- 「本日の稼働終了(夜日報)」ボタン自体は正しく今日に飛ぶ(date無し→targetDate=今日)
- ?date=昨日 を渡す導線は3つ: ①未提出赤アラート ②上部常設「昨日の夜日報を提出」ボタン(v1.290) ③通知ベルの night-overdue
- ②が青のprimary風スタイルで画面上一番目立ち、「夜日報を出すならコレ」に見える視覚階層が原因(本日用ボタンは地味な紫アウトライン)

修正(2点・1リリース):
1. 夜日報ページに救済バナー: ?date=過去日 で開いたらヘッダー直下に「これは YYYY-MM-DD の遅延提出です。今日の分を出すつもりならこちら →」+「今日(日付)の夜日報に切り替える」ボタンを常時表示。どの導線から入っても今日へワンクリックで戻れる。切り替えは window.location.href のフルナビゲーション(入力中state・draft復元フラグの持ち越し事故を構造的に防ぐ。入力途中分は日付別draftに自動保存済み)
2. 過去日入口のghost格下げ: ダッシュボード上部の「昨日の夜日報を提出」を 青solid → bg-bg3/60 + border のghostスタイルに。本日用CTAより目立たない視覚階層へ是正

不変(退化禁止):
- 過去日入口の位置・機能・日付ピッカーは v1.290(ce-2026-06-03-05「導線は勝手に消さない」)のまま維持
- 未提出赤アラート・通知ベル night-overdue 導線も無変更

検証(本番バンドル実測): ✅ version.json v1.300/ce-2026-06-12-04・切り替えバナー/ghost化とも配信中をJS chunk grepで確認・work-log/night 両ページ200

ファイル: app/(dashboard)/tasks/work-log/night/page.tsx / app/(dashboard)/tasks/work-log/page.tsx / lib/changelog.ts / CLAUDE.md

バックアップ: pre 2026-06-12_203419_pre-deploy.tar.gz(v1.299状態・復元ポイント)/ post 2026-06-12_204245_post-deploy.tar.gz(v1.300確定)

git: push済(最終 8885f8d)

最新スタンプ: changelog ce-2026-06-12-04 / baseline 2026-06-12_204245_post-deploy / app v1.300


2026-06-12 15:40 更新(ce-2026-06-12-03 / app v1.298 → v1.299)【作業中で追加したタスクを当日朝日報に自動反映】

大串FB: 「作業中で追加したタスクは、その日の作業開始報告の朝日報で選んだタスクに入れたいね。実際その日やろうとして漏れてて、作業中のところで追加したわけだから!」

実装内容:
- appendTaskToMorningReport 新設(lib/work-log.ts): 当日(セッション業務日)の朝日報を matchesWorkDate で特定し、routine → selectedRoutineIds / base → baseTaskIds / ID無し ad-hoc → todayTasks に追記。重複は内部スキップ。saveReports(userId) で KV 同期
- 適用3経路(ActiveBoard.tsx): addTask(クイック追加)・addExistingBaseTask(マイタスクから追加)・addExistingRoutineTask(定例から追加)
- 効果: 2回目以降の作業開始報告の「朝日報から選択」リストに、作業中で追加したタスクも自然に出る

設計判断:
- 朝日報が未提出の日は何もしない(勝手に朝日報を作ると未提出通知・リマインドが黙る)
- 追記のみ(ボードから削除しても朝日報からは消さない)
- 日付はセッション業務日(session.date)基準=深夜跨ぎは開始日の朝日報へ(ce-06-01-01 踏襲)
- 投稿済み朝日報の Slack 文面は遡って編集しない(アプリ内データのみ反映)

ファイル: lib/work-log.ts / components/tasks/work-log/ActiveBoard.tsx / lib/changelog.ts(ce-2026-06-12-03)/ CLAUDE.md(v1.299)

バックアップ:
- pre-deploy: scale-base_2026-06-12_133617_pre-deploy.tar.gz(v1.298 状態・このリリースの復元ポイント)
- post-deploy: scale-base_2026-06-12_133658_post-deploy.tar.gz(v1.299 確定)

本番URL確認: ✅ version.json = v1.299/ce-2026-06-12-03 / work-log 各ページ HTTP 200 / Cache-Control no-cache

git: push済(89e0d93..17235f5 main・最終 17235f5)

最新スタンプ: changelog ce-2026-06-12-03 / baseline 2026-06-12_133658_post-deploy / app v1.299


2026-06-12 09:35 更新(ce-2026-06-12-02 / app v1.297 → v1.298)【根治・新規タスクが過去の同名タスクの累計時間を継承】

大串FB: 「作業中で今日入れた商談準備が、いきなり累計37分から始まっていた。まだやってないのに。その場で入れたもの=新規タスク判定して欲しい」

真因(実データで裏取り済):
- 商談準備は日ごとに別タスク(別ID)として正しく作成されていた(KV実データで6件確認・全部完了済)
- しかし累計集計 getAccumulatedMsForTask が「ID一致 or 名前一致」のOR判定 → 新規タスク(新ID)でも過去セッションの同名エントリ(6/2の19.5分+6/9の14.4分)を名前一致で合算 → 今日の3分が「累計37:07」表示に

根治内容:
1. ID厳格一致(lib/work-log.ts): taskId がある場合は sourceId 完全一致のみ。名前一致フォールバックは「クエリ・entry 両方に ID が無い」レガシー ad-hoc 同士のみ
2. pickTimeTrackTaskByName 新設(lib/auto-register-task.ts): 同名複数時は 自分担当の未完了(新しい順)→ 自分担当(新しい順)→ 全候補(新しい順)で1件解決。unfinishedOnly=true で「これからやる」文脈用(全部完了済みなら undefined=新規扱い・累計0)
3. 名前→タスク解決の統一: morning(Slack残時間suffix/超過集計/行表示/集計)・end/night(累計suffix/超過集計)・start(文字列タスク集計)の累計用IDを全てヘルパー経由に。morning/end/night のタスク名クリック(openTaskDetail)も最古の完了済みでなくアクティブな1件を開く
4. 想定時間の推定継承は維持: 同名過去タスクから estimate を引く便利機能(findBaseByName の mineWithEst 優先等)は従来どおり

設計判断(文脈で解決を分ける):
- 朝日報/作業開始=「これからやる」→ unfinishedOnly(完了済み同名に紐付けない)
- 夜日報/終了報告=「やった事実」→ 直近完了も対象(直近完了=今やったタスク)

不変(退化禁止):
- 長期タスクの複数日累計(同一IDで継続)・定例の周期内集計(sinceISO)・v1.296 routineId完了判定・v1.293 trim正規化は全て維持
- 累計/残時間の集計はID厳格一致が正。名前一致ORに戻すと同名新規タスクが過去実績を継承して退化

ファイル:
- lib/work-log.ts / lib/auto-register-task.ts
- app/(dashboard)/tasks/work-log/{morning,end,night,start}/page.tsx
- lib/changelog.ts(ce-2026-06-12-02)/ CLAUDE.md(v1.298)

バックアップ:
- pre-deploy: scale-base_2026-06-12_092711_pre-deploy.tar.gz(v1.297 状態・このリリースの復元ポイント)
- post-deploy: scale-base_2026-06-12_092741_post-deploy.tar.gz(v1.298 確定)

本番URL確認: ✅ version.json = v1.298/ce-2026-06-12-02 / work-log 全7ページ HTTP 200 / chunk全200 / Cache-Control no-cache

git: push済(f1d7067..89e0d93 main)

最新スタンプ: changelog ce-2026-06-12-02 / baseline 2026-06-12_092741_post-deploy / app v1.298


2026-06-12 09:01 更新(ce-2026-06-12-01 / app v1.296 → v1.297)【定例タスク 停止ボタンと最終実施の列重なり解消】

実施内容:
- 定例タスク一覧の「最終実施」列の中身(日付input+✓/今ボタン)が「停止」列にはみ出して重なるUI不具合を修正
- colgroup: 最終実施 140px→184px / 停止 56px→64px
- 最終実施 td: py-2.5 px-2 + 内側 div flex items-center gap-1 min-w-0 overflow-hidden(列内に確実に収める)
- 停止 td: py-2.5 px-2 text-center

ファイル:
- app/(dashboard)/tasks/routines/page.tsx(colgroup+最終実施/停止 td)
- lib/changelog.ts(最上段 ce-2026-06-12-01)
- CLAUDE.md(バージョンスタンプ v1.297)

バックアップ:
- pre-deploy: scale-base_2026-06-12_085529_pre-deploy.tar.gz
- post-deploy: scale-base_2026-06-12_085628_post-deploy.tar.gz

本番URL確認: ✅ version.json = v1.297 / /tasks/routines/ HTTP 200 / 異常アセット 0

git: push済(5fd6e72..f1d7067 main)

最新スタンプ: changelog ce-2026-06-12-01 / baseline 2026-06-12_085628_post-deploy / app v1.297


SCALE Base 最新基準点(2026-06-01 更新・v1.270)

2026-06-01 08:15(ce-06-01-04 / app v1.269 → v1.270)【緊急根治・更新後の黒画面】

ce-2026-06-01-04(v1.270)更新後に黒画面(スプラッシュで固まる)バグ根治
- 大串FB「クリックして更新したら黒画面になった、すぐ修正」
- 真因: public/_headers のデフォルト * → max-age=300(5分) が、Next.js静的エクスポートの末尾スラッシュURL(/home/ /tasks/work-log/ 等。/.html にも / にもマッチしない)に適用され HTMLが5分キャッシュ。短時間に複数回 --clean デプロイ→buildId毎回更新→古いHTMLが「消えた buildId のJS」を参照→404→ChunkLoadError→スプラッシュで固まる
- 対策: _headers 再構成。/_next/static/
(ハッシュ付き不変)のみ immutable長期、version.json は no-store、それ以外(HTMLルート含む)は /* → no-cache, must-revalidate。古いHTMLが配信されない構造に
- 即時復旧: クリーン再デプロイで全chunk 200・配信HTML buildIdとCDNアセット一致を確認
- ファイル: public/_headers

** 学び:* Next.js静的エクスポート×Cloudflare Pagesでは、HTMLルートは必ず no-cache にする(末尾スラッシュURLは /.html にマッチしない)。デプロイ後は「chunk全部200 + Cache-Control no-cache」を検証する。短時間の連続 --clean デプロイは buildId が変わるので特に注意

最新スタンプ: changelog ce-2026-06-01-04 / app v1.270


SCALE Base 最新基準点(2026-06-01 更新・v1.269)

2026-06-01 朝(ce-06-01-01〜03 / app v1.266 → v1.269)【今日完了漏れ根治・開始モーダル復活・5分10分ボタン】

ce-2026-06-01-01(v1.267)【根治】前日セッションを翌朝終了→完了タスクが翌日「今日完了」に漏れる
- 大串FB「朝イチの最初の作業報告なのに完了タスクに昨日分(SCALE HPのリサーチ/Xポスト作成/読書)が出る」
- 真因: end report の date/定例lastDone/Slackスレが getTodayDate()(=終了操作した今日)基準。前日開始→翌朝終了で「翌日の完了」扱いに
- 対策: reportDate=running.date(セッション業務日)に統一。markRoutineDoneToday に date 引数追加。既存の誤データは翌日以降 self-heal
- Slackスレ重複の真因もコレ(end reportが翌日付→その日の別スレ生成)。dedup自体は実機検証で正常(「大串」「大串 勇輝」表記ブレも同一ts合流)
- ファイル: end/page.tsx / lib/auto-register-task.ts

ce-2026-06-01-02(v1.268)目安時間ボタンに5分10分追加+短い順
- EstimateMinutesPicker PRESETS を [15,30,60,90,120,180]→[5,10,15,30,60,90,120,180] 昇順。全目安時間入力に反映

ce-2026-06-01-03(v1.269)作業開始報告のタスク追加モーダル復活
- 大串FB「作業開始報告でタスク追加してもモーダル出ない、作業中と同じモーダル出して」
- ce-2026-05-08-01 で外していた TaskDetailModal 自動オープンを start/page.tsx handleTaskBlur の新規base作成分岐に復活

副次対応:
- Drive同期事故: lib/tools-library.ts が消え "tools-library 2.ts" に化けてビルド不能→git checkoutで復元・重複削除
- デプロイ認証失効: wrangler OAuth 403失効→API Token方式に切替。~/.cf_token 保存、export CLOUDFLARE_API_TOKEN="$(cat ~/.cf_token)" してdeploy(恒久運用)

バックアップ: post-deploy 2026-06-01_080251_post-deploy.tar.gz(v1.269確定)
本番確認: ✅ home/start/end/routines 200・version.json v1.269/ce-06-01-03

** 学び:** ①日付基準は「操作時刻」でなく「業務日(セッション開始日)」(深夜跨ぎで破綻) ②wrangler OAuthは失効しやすい→API Tokenが恒久安定 ③Drive配下は同期コンフリクトで " 2"重複ファイルが生まれビルドを壊す

最新スタンプ: changelog ce-2026-06-01-03 / baseline 2026-06-01_080251_post-deploy / app v1.269


SCALE Base 最新基準点(2026-05-30 更新・v1.266)

2026-05-30 19:20(ce-2026-05-30-01 / app v1.265 → v1.266)【作業終了報告で経過時間を手動修正可能に】

  • 大串FB「作業終了のタイミングで時間を自動で出すが、手動でも変更できるようにしたい」
  • end ページの経過時間カードに「✎ 開始/終了時刻を手動で修正する」を追加。datetime-local で開始/終了を直接修正→稼働時間をリアルタイムプレビュー(netSessionMinutes・停止控除込み)→提出で session.startedAt/endedAt/minutes・集計・Slack通知に反映。「自動に戻す」で自動算出へ。不正時刻は提出時に alert で中断
  • これまで手動修正はダッシュボードのセッション表(ce-29-07)だけ→終了報告の流れでも直せるように
  • ファイル: app/(dashboard)/tasks/work-log/end/page.tsx
  • バックアップ: post-deploy 2026-05-30_191021_post-deploy.tar.gz(v1.266)/ 本番 v1.266・home 200 確認
  • 最新スタンプ: changelog ce-2026-05-30-01 / baseline 2026-05-30_191021_post-deploy / app v1.266

SCALE Base 最新基準点(2026-05-29 更新・v1.265)

2026-05-29 夕方 まとめ(ce-29-06〜08 / app v1.262 → v1.265)【Slackスレ統合・手動修正/タイマー是正・夜日報全デバイス同期】

ce-2026-05-29-06(v1.263)Slack日次報告スレ重複の根治
- 大串FB「作業報告/終了報告のSlack通知、1日1スレにまとめてほしいのに何本も立つ」。スクショで 5/29『大串 勇輝』08:30 と『大串』16:39 が別スレ
- 真因: daily-thread.ts が親メッセージを「表示名の完全一致」で照合→「大串 勇輝/大串」のブレで別スレ化
- 対策: Slack metadata { event_type:'scale_daily_report', event_payload:{uid,date} } を親に埋め、userId(表示名非依存)で照合。既存スレも姓(第1トークン)正規化で合流。metadata投稿失敗時はプレーン投稿フォールバック
- ファイル: functions/api/daily-thread.ts

ce-2026-05-29-07(v1.264)手動修正機能 + タイマー勝手に止まる是正
- 大串FB①「エラーで数値バグったまま→手動で戻したい」→ ダッシュボード「今日の作業セッション」表に鉛筆ボタン: 開始/終了時刻修正(稼働時間プレビュー&再計算)・「稼働中に戻す」・「停止区間クリア」
- 大串FB②「作業スタートしてたのに勝手に止まってた・タイマー勝手に止めるな」→ ce-29-01 の16h自動クローズが長時間作業の実セッションを止めていた。「記録クランプ(MAX 16h)」と「live放置判定(自動クローズ)」を分離し後者を ABANDONED=36h に緩和。live時計のboundも36hに。記録/集計の16h上限は維持(240h汚染防止)
- ファイル: lib/work-log.ts / ActiveBoard.tsx / work-log/page.tsx

ce-2026-05-29-08(v1.265)夜日報の今日やったタスクを全デバイス同期
- 大串FB「別Chromeで作業した日のタスクが夜日報に入らない。ログインアカウントで全デバイス同期して」
- 真因: 夜日報が end report だけから完了タスク集計→別デバイスの end report 同期前/欠落で空に
- 対策: 作業中画面で done にしたタスク(sessions[].progress・userId単位でKV同期)からも集めて end report と統合(mergeUnique)。さらに WorkLogProvider に pullNow を公開し夜日報マウント時にKV再取得→開いた瞬間に最新反映
- 設計確認: sessions も reports も KVキーは userId 単位。同一アカウントでログインしていれば全デバイス同期される
- ファイル: night/page.tsx / work-log-api.tsx

デプロイ事故メモ: v1.265 は最初の background デプロイが途中で止まり本番が v1.264 のままだった→「クリックで更新」が出ない(✓最新のまま)状態に。再デプロイで解消。バックグラウンドデプロイは完了確認(version.json)を必ず取る

バックアップ: post-deploy 2026-05-29_182320_post-deploy.tar.gz(v1.265 確定)
本番確認: ✅ base.scale-group.co.jp v1.265 / home・夜日報 200 / Slackスレ統合・オリジンゲート維持

最新スタンプ: 最新changelog ce-2026-05-29-08 / baseline 2026-05-29_182320_post-deploy / app v1.265

** 学び: ①Slackの一意キーは表示名でなくmetadata(uid) ②自動クリーンアップ閾値は実運用の最大値(長時間作業)を考慮(16hは短すぎ→36h) ③集計は同期済みソース(userId KV)を複数束ねると堅牢 ④バックグラウンドデプロイは version.json で完了確認必須**(途中停止に気付けない)


SCALE Base 最新基準点(2026-05-29 更新・v1.262)

2026-05-29 11:00 更新(ce-29-05 / app v1.261 → v1.262)【UI・定例タスク目安時間の縦長解消】+ 🚀デプロイ方針変更

ce-2026-05-29-05(v1.262)定例タスクの目安時間UIを「選択値ラベル+クリック編集」に
- 大串FB「定例業務の目安時間の見栄え超悪い・選択した時間だけ表示すれば良い・1タスクが縦に長すぎ」
- 真因: /tasks/routines の目安時間セルが EstimateMinutesPicker のフルUI(chip群+自由入力+ヒント3段)を常時描画→行が縦に肥大
- 修正: メモ欄と同じ「普段は fmtEstimateLabel のラベルのみ表示・クリックで編集ピッカー展開・選択(onChange)で即保存して閉じる」に。✕/外クリックでも閉じる。/tasks/list は元々 compact で無変更
- ファイル: app/(dashboard)/tasks/routines/page.tsx

🚀 デプロイ方針変更(2026-05-29 大串FB・恒久):
- 「この自社システムはプレビューじゃなくて直接実装していい。外販してないしHPみたいに直接影響ない」
- → SCALE Base は社内専用のため preview 不要・bash scripts/deploy.sh(prod) 直接実行OK
- ただし tar.gz backup + changelog + 退化チェック + 本番URL確認は従来どおり必須(安全確認は省略しない)
- preview 必須は引き続き TERASU公式HP / SCALE CRM 等の対外影響ありシステムのみ

バックアップ: post-deploy 2026-05-29_114646_post-deploy.tar.gz(v1.262 確定)
本番URL確認: ✅ base.scale-group.co.jp HTTP 200・version.json v1.262/ce-29-05

最新スタンプ: 最新changelog ce-2026-05-29-05 / baseline 2026-05-29_114646_post-deploy / app v1.262


SCALE Base 最新基準点(2026-05-29 更新・v1.261)

2026-05-29 全コード棚卸し(ce-29-01〜04 / app v1.257 → v1.261)【作業時間バグ根治 + 同期堅牢化 + セキュリティ + 端末間消失根治 + 不要コード削除】

スマホ版で噴出した数値バグを起点に、3並列の読取専用監査で全686ファイルを洗い出し、「過去コードに残った再発バグの温床」を一気に根治。preview→OK→prod の2段で本番反映済(本番=v1.261)。

ce-2026-05-29-01(v1.258)作業時間バグ根治(240時間 / 0分で加算されない)
- 真因: セッション時間計算(netSessionMinutes/diffMinutes/getAccumulatedMsForTask/elapsedMs)が end−start を上限なしで計算。①ActiveBoard が endedAt=null の古い dangling セッション(数日前)を無条件に現セッション扱い→ライブ時計240h→終了で240h記録 ②端末間クロックずれで endedAt<startedAt→0分 ③保存済みの壊れた minutes(=14400) を effectiveSessionMinutes がそのまま返し集計汚染
- 対策: MAX_SESSION_MINUTES=16h で全時間計算を bound / ActiveBoard・getUserState・dashboard runningSession が壊れた dangling を現セッションに拾わない / dangling 自動クローズ(タスク実測ぶんだけ honest 記録)/ クロックずれ時は trackedMinutesForSession で救済
- start ページの reuse 判定も isSessionDurationCorrupt に統一(24h窓→corrupt判定。reuse即クローズの無限ループ防止)

ce-2026-05-29-02(v1.259)work-log KV同期の堅牢化 + 幻の稼働中防止 + 不要コード削除
- syncSessionsToKV/syncReportsToKV が fetch(...).catch(()=>{}) で res.ok 未チェック・無リトライ→PUT失敗を握り潰し「保存したのに巻き戻る」class。tasks-api(saveToAPI)は対策済だったが work-log側は未対策で残存→putWorkLogKV(res.okチェック+指数バックオフ3回再試行)に統一
- getUserState が壊れた dangling を currentSessionId に拾い「幻の稼働中」→ !isSessionDurationCorrupt フィルタ
- 削除: 入れ子重複 scale-base/lib(172KB・参照0)・orphan lib 3本(recruit-ai-screening/recruit-slack/work-log-bridge・参照0)・deprecated stub markLocalWrite/shouldSkipKVPull・空hooks/

ce-2026-05-29-03(v1.260)オリジンゲート(課金暴発防止)+ _archived_apps削除
- 大串FB「勝手にお金がかからないように」。Claude API を叩く AI プロキシ等が無認証で外部から叩ける状態→従量課金暴発リスク
- functions/_origin-guard.ts + functions/api/_middleware.ts で /api/ 横断ガード。自オリジン以外からの非GET呼び出しを403。クライアント無改修(正規 fetch は Origin 自動送信で素通り)
- guard対象: 課金AI14本 + slack-post/daily-thread + goals/insight-gallery(変更系)。
slack-events(Slack Webhook・独自HMAC)は除外(入れると壊れる)
- 限界: Origin は偽装可能→bot/クローラ/curl は止まるが標的型は完全防御でない。完全防御は Cloudflare Access が本筋
- _archived_apps/(2.7MB・参照0) 削除
- ⚠️
未対応(別途判断)*: /api/pass●●●●●● が無認証で全パスワード平文返却(GET)。データ露出問題→Cloudflare Access での本格対応を推奨(破壊回避で今回未変更)

ce-2026-05-29-04(v1.261)端末間レポート/セッション消失の根治(tombstone付き read-merge)
- 真因: syncXxxToKV が「自端末ローカル全リスト」を whole-replace PUT→PC↔スマホ同時提出で後勝ち端末が相手の提出を消す(finding#1)。snapshot-exclusive は削除復活は防ぐが同時追加は守れない
- 対策: worker はソース不在で改修不可→クライアント側で PUT直前に KV最新GET→mergeByIdExcludingTomb(KV∪ローカル ローカル優先 tombstone除外)→PUT。他端末の追加を保持
- 削除復活の再発防止: tombstone方式。saveReports/saveSessions の prev↔new差分で削除idを自動記録(全削除経路網羅)・14日prune・pull側でも除外
- 残る限界: 他端末で削除したitemは削除を知らない端末が再PUTで復活し得る(クライアント単独マージの構造限界・データ消失でなく重複復活・重複削除UIで回収可)

バックアップ:
- post-deploy(最新): 2026-05-29_101815_post-deploy.tar.gz(v1.261 確定)
- 作業前: 2026-05-29_090148_before-session-time-rootfix.tar.gz

本番URL確認: ✅ 新ドメイン/旧URL とも HTTP 200・version.json v1.261/ce-29-04・オリジンゲート 403・slack-events 401(guard対象外維持)

** 重要な学び:
-
「過去の堅牢化が片側にしか効いてない」が再発バグの温床: tasks-api は res.ok+リトライ・wipeブロック等で堅牢だったが、対の work-log(sessions/reports)同期は未対策で穴が残っていた。同種ロジックは両方を揃えて監査する
-
時間計算は必ず上限 bound: end−start を信じると dangling/クロックずれで absurd 値(240h)。MAX で bound + 壊れデータは honest な実測値に倒す
-
クライアント単独の同期には限界がある: 他端末削除の伝播はサーバ側マージ(=worker)が本筋。tombstone は次善(追加保持+自端末削除尊重、他端末削除復活は許容)
-
無認証API=課金/データ露出リスク**: 静的SPAでもPages Functionsは素通し。最低限オリジンゲート、本格はCloudflare Access

最新スタンプ:
- 最新changelog: ce-2026-05-29-04
- 最新baseline: 2026-05-29_101815_post-deploy.tar.gz
- 最新アプリver: v1.261


SCALE Base 最新基準点(2026-05-27 更新・履歴)

2026-05-27 夜 まとめ更新(ce-07〜13 / app v1.252 → v1.257)【作業報告系バグ多数根治 + 致命的タスク消失根治】

2026-05-27 の連続デプロイ(v1.252〜v1.257)をまとめて記録。各 ce の詳細は lib/changelog.ts 参照。

ce-2026-05-27-07(v1.252)期日変更の理由プロンプト削除
- TaskDetailModal.handleDueDateChange の window.prompt を削除。dateChanges 履歴は handleSave で「期日変更」ラベル付きで残る

ce-2026-05-27-08(v1.253)期日変更が保存されないバグ根治
- saveToAPI が res.ok を check してなかった → 4xx/5xx で silently 失敗 → snapshot 3秒後クリア → KV pull で古いデータ復帰。saveToAPI を boolean 返却 + putWithSnapshot で PUT 失敗時は snapshot 保持 + 指数バックオフ最大3回再試行

ce-2026-05-27-09(v1.254)EstimateMinutesPicker UX刷新 + 定例タブ位置変更
- 目安時間 picker を select+記入式 → chip群 + 常時自由入力テキストボックスに全面刷新。compact prop 追加(インラインセル用)。定例タスクサブナビを左から2番目に(SubNav.tsx + subnav-groups.ts)

ce-2026-05-27-10(v1.255)【致命・根治】タスク全消失バグ + 3層防御
- 大串FB「タスクシートの全タスクが勝手に消えた」。真因: fetchFromAPI 失敗時 null → loadAll で null||[]=[] → setTasks([]) でメモリ wipe → 次の saveTasks([]) で KV WIPE の連鎖。883件消失(KV履歴なく復旧不能・大串は手動再入力で了承)
- 3層防御実装: ①fetchFromAPI を throw に + loadAll の safeFetch 独立 try/catch で失敗時 state 保持 ②saveTasks に「10件以上→0件」wipe ブロック(alert + return)③localStorage rolling backup(scale-tasks-backup-stable)+ /tasks/list 復旧バナー UI(restoreTasksFromLocalBackup / getTasksLocalBackupInfo)

ce-2026-05-27-11(v1.256 に同梱)EstimateMinutesPicker 時間単位化
- 自由入力を「分」→「時間(小数可)」に。minutesToHoursText / hoursTextToMinutes helper。内部値は minutes のまま維持(DB互換)。0.5→30分, 1.5→90分

ce-2026-05-27-12(v1.256)停止中セッション誤終了の防止
- メンバーFB「作業停止して再開しようとしたら勝手に終了されてた」。真因: ActiveBoard 右下フローティングバーで「作業再開(小)」の隣に「作業終了する(大・派手)」があり誤タップ。ボタンサイズ反転(停止中: 再開=大派手・終了=小地味 / 稼働中: その逆)+ endSession に確認ダイアログ追加

ce-2026-05-27-13(v1.257)作業終了の確認ダイアログ削除
- 大串FB「念のための確認いらない」。ce-12 の endSession confirm を削除。誤終了防止はボタンサイズ反転 UX だけで担保(confirm 不要)。再発したら Undo トースト検討

バックアップ:
- post-deploy(最新): 2026-05-27_212846_post-deploy.tar.gz(v1.257 確定)

本番URL確認: ✅ HTTP 200(version.json: v1.257 / ce-2026-05-27-13)

** 重要な学び(このセッションの教訓):
-
「fetch 失敗を null 返却 → ||[] で空配列扱い」がデータ消失の最大級バグパターン。失敗は throw、呼び出し側で state を触らない設計が鉄則
-
KV / localStorage / React state の 3層分散がスマホ版で多数の race を生んだ。ce-03 で snapshot-exclusive 同期に統一したが、saveToAPI の res.ok 未チェック(ce-08)や fetchFromAPI の null 扱い(ce-10)の穴が残っていた
-
データ操作系には必ず「破壊ブロック + ローカル backup + 復旧 UI」の3点セットを入れる
-
UX の誤タップ防止は「確認ダイアログ」より「視覚優先度(ボタンサイズ)」の方が大串の好み**(confirm は摩擦として嫌われる)

最新スタンプ:
- 最新changelog: ce-2026-05-27-13
- 最新baseline: 2026-05-27_212846_post-deploy.tar.gz
- 最新アプリver: v1.257


SCALE Base 最新基準点(2026-05-27 更新・履歴)

2026-05-27 17:25 更新(ce-2026-05-27-06 / app v1.250 → v1.251)【根治・作業中断が勝手に解除されるバグ】

実施内容(1リリース・syncSessionsToKV 抜け漏れ修正):
1. ce-2026-05-27-06 作業中断が勝手に解除されるバグ修正
- メンバー報告(大串):「勘違いかもしれないけど、作業中断って押していたのに少し時間経ったりしたら、勝手にスタートされてたかも」
- 真因: components/tasks/work-log/ActiveBoard.tsxpauseSession (line 666) / resumeSession (line 683) が saveSessions(updated)userId 引数なしで呼んでいた
- lib/work-log.ts saveSessions の挙動: if (opts?.userId) { notifySessionsSnapshot + syncSessionsToKV } = userId 無しだと localStorage だけ更新、snapshot 不登録、KV PUT 不実行
- 症状の連鎖:
1. pauseSession 押下 → localStorage に pause 追加(ローカルだけ)
2. 30秒 polling の pullFromKV 起動 → snapshot 無いので KV からそのまま取得(pause 前の古いデータ)
3. localStorage に上書き → pause 消える
4. ActiveBoard 再 render で isSessionPaused=false → 「勝手に再開」表示
- 修正: pauseSession / resumeSession の saveSessions 呼び出しを saveSessions(updated, { userId: user?.id }) に変更。これで notifySessionsSnapshot で snapshot が立ち、syncSessionsToKV で KV PUT が走るので、次の pull は snapshot 採用で構造的に守られる
- 他の saveSessions 呼び出しの監査: 全 saveSessions 呼び出し(page.tsx 4箇所 / start/page.tsx 2箇所 / end/page.tsx 1箇所 / ActiveBoard 5箇所)すべて userId を渡していることを grep で確認済

主な編集ファイル:
- components/tasks/work-log/ActiveBoard.tsx(pauseSession / resumeSession の saveSessions に userId 追加)
- lib/changelog.ts / CLAUDE.md

バックアップ:
- 事前: 2026-05-27_172530_before-ce-2026-05-27-06-deploy.tar.gz
- post-deploy: 2026-05-27_172743_post-deploy.tar.gz(v1.251 確定)

本番URL確認: ✅ HTTP 200(home/ / version.json: v1.251 / ce-2026-05-27-06)

退化防止: ce-2026-05-27-05(calendar connectedEmail)/ ce-2026-05-27-03(snapshot-exclusive 同期)/ ce-2026-05-25-13(endSession userId)すべて無変更

** 学び(Vault 蓄積・「シグネチャの引数漏れ」が一番事故源):
-
「optional 引数」が事故の最大源: saveSessions(data, opts?) のような optional 引数は、呼び出し側で渡し忘れると silent fail。型エラーすら出ない。pauseSession/resumeSession で「userId なし」を渡しても TypeScript が黙る → 実行時に KV PUT 抜け
-
同じ関数の呼び出しは grep で全部監査する: 1箇所修正したら他にも漏れが無いか必ず確認。今回は page.tsx / start/page.tsx / end/page.tsx は OK、ActiveBoard だけ漏れていた
-
「ローカルだけ更新で KV 無視」を許容しない設計に**: 将来的には saveSessions の引数を required にする検討。userId は必須にして、保護したくない call site だけ明示的に { userId: null } で抜けるパターンが安全

最新スタンプ:
- 最新changelog: ce-2026-05-27-06
- 最新baseline: 2026-05-27_172743_post-deploy.tar.gz
- 最新アプリver: v1.251


SCALE Base 最新基準点(2026-05-27 更新・前回)

2026-05-27 15:55 更新(ce-2026-05-27-05 / app v1.249 → v1.250)【再修正・カレンダーフィルタを connectedEmail ベースに】

実施内容(1リリース・ce-04 副作用の修正):
1. ce-2026-05-27-05 カレンダーフィルタを connectedEmail ベースに修正
- メンバー報告(大串):「俺のカレンダーしか登録してないから、俺のカレンダーからの読み込みは俺にだけ反映できればOK、細川は気にしない」
- ce-04 の副作用: organizer/creator フィルタは「自分が組織した event だけ」を取込む。外部から招待された MTG(organizer = 外部の人)は creator も外部 → 取込まれない副作用があった。MTG など他人組織のタスクも取込みたい大串の用途と合わなかった
- 真因の整理: "team" scope は単一 Google アカウントで全員共有。events は接続者本人 (=大串) のカレンダー全体。「接続者本人かどうか」だけ判定すれば、その本人にとって意味のある event は全部取込んで OK
- 修正 1(events API): functions/api/google-calendar/events.ts で google_tokens の email カラムも SELECT し、response に connectedEmail を含める。これが「Google アカウント接続者の email = カレンダーの持ち主」
- 修正 2(morning page): user.email === connectedEmail ならカレンダー全イベント取込(外部招待 MTG 含む)、違うユーザーは早期 return で自動取込 skip。ce-04 の organizer/creator フィルタは削除
- UX 結果: 大串が calendar 接続者本人 → 自分のカレンダー全イベントが朝日報に自動マージ(外部招待 MTG も含む・以前と同じ)。細川がログインしても calendar 接続者本人ではない → 何も取込まれない → 細川担当のタスクが生成されない

主な編集ファイル:
- functions/api/google-calendar/events.ts(connectedEmail を response に追加)
- app/(dashboard)/tasks/work-log/morning/page.tsx(filter を user.email === connectedEmail に変更)
- lib/changelog.ts / CLAUDE.md

バックアップ:
- 事前: 2026-05-27_155359_before-ce-2026-05-27-05-deploy.tar.gz
- post-deploy: 2026-05-27_155516_post-deploy.tar.gz(v1.250 確定)

本番URL確認: ✅ HTTP 200(home/ / version.json: v1.250 / ce-2026-05-27-05)

退化防止: ce-2026-05-27-03(snapshot-exclusive 同期)/ ce-2026-05-27-02(朝日報 onBlur モーダル)すべて無変更

** 学び(Vault 蓄積・所有権判定の解像度):
-
「フィルタの粒度」と「ユーザー意図」を必ず合わせる: ce-04 で organizer 一致だけにフィルタしたが、ユーザーは「外部 MTG も含めて自分のカレンダー全部」を取込みたかった。フィルタ実装前に「何を含める / 何を除外する」を一度ユーザーに確認すべきだった
-
共有 OAuth scope の所有権は「接続したアカウント」で決まる: 「team」共有 scope なら、connectedEmail = カレンダーの持ち主。それと user.email を比較すれば「接続者本人 vs それ以外」を構造的に区別できる
-
早期 return が UX として一番素直**: 接続者本人でないユーザーは calendarAutoLoaded を立てて即 return。複雑なフィルタを通すよりシンプル

最新スタンプ:
- 最新changelog: ce-2026-05-27-05
- 最新baseline: 2026-05-27_155516_post-deploy.tar.gz
- 最新アプリver: v1.250


SCALE Base 最新基準点(2026-05-27 更新・前回)

2026-05-27 15:50 更新(ce-2026-05-27-04 / app v1.248 → v1.249)【根治・カレンダー自動取込で他ユーザーにも担当ついちゃう】

実施内容(1リリース・OAuth scope の構造的問題への mitigation):
1. ce-2026-05-27-04 カレンダー自動取込で他ユーザーにも担当付く問題
- メンバー報告(大串):「俺のカレンダーからのタスク自動登録で細川にも担当ついちゃう、俺のタスクだから俺のカレンダーからのものは細川につけないで」
- 真因: Google Calendar の OAuth scope が 'team' で全員共有(=大串の Google アカウント 1 つに接続)。/api/google-calendar/events が返すのは "team" 接続済みアカウント = 大串のカレンダー全イベント。細川がログインして morning を開いても同じ events が返り、todayTasks に自動マージ → 保存時 autoRegisterMemoTasks が細川を currentUserName として新規タスク作成 → 同じ MTG/予定について「大串担当タスク」「細川担当タスク」が両方できていた
- 修正 1(events API): functions/api/google-calendar/events.ts 各イベントに organizerEmail / creatorEmail を含めて返す(Google API の e.organizer?.email / e.creator?.email 由来)
- 修正 2(morning page): app/(dashboard)/tasks/work-log/morning/page.tsx のカレンダー自動取込ロジックに isMine(e) フィルタを追加。organizerEmail === user.email || creatorEmail === user.email のイベントだけ todayTasks に追加。それ以外は除外 → autoRegisterMemoTasks に到達しないので細川担当のタスクが生成されない

主な編集ファイル:
- functions/api/google-calendar/events.ts(organizerEmail/creatorEmail を response に追加)
- app/(dashboard)/tasks/work-log/morning/page.tsx(isMine フィルタ追加)
- lib/changelog.ts / CLAUDE.md

バックアップ:
- 事前: 2026-05-27_154849_before-ce-2026-05-27-04-deploy.tar.gz
- post-deploy: 2026-05-27_155016_post-deploy.tar.gz(v1.249 確定)

本番URL確認: ✅ HTTP 200(home/ / version.json: v1.249 / ce-2026-05-27-04)

副作用(明示): 細川が組織したイベントは "team" カレンダー(=大串の calendar)に存在しないため、細川の morning には何も自動取込されなくなる。これは現状の "1 Google アカウント共有" 設計の制約。将来的にメンバーごとに個別 OAuth scope を切る設計に進化させると解消できる

退化防止: ce-2026-05-27-03(snapshot-exclusive 同期)/ ce-2026-05-27-02(朝日報 onBlur モーダル)/ ce-2026-05-27-01(NotificationCenter)すべて無変更

** 学び(Vault 蓄積・OAuth scope と所有権):
-
「共有 OAuth scope」は便利だがデータ所有権の境界を曖昧にする: チーム全員が 1 つの Google アカウントを共有すると、フェッチしたデータは「誰のもの?」が決まらない。自動アクションを実行する前に「organizer / creator」フィールドで所有権を必ず確認する設計が必要
-
共有データを per-user に分けるには「フィルタ」か「scope 分割」: 今回は素早く済むフィルタ案。将来 scope 分割するなら DB の google_tokens テーブルを per-user の row にする
-
「自動登録系」は所有権検証必須**: Slack scan や calendar import など外部から流入するデータは「これは誰のタスクか」をはっきりさせてから assignee を決める。曖昧なら「未割当」が安全

最新スタンプ:
- 最新changelog: ce-2026-05-27-04
- 最新baseline: 2026-05-27_155016_post-deploy.tar.gz
- 最新アプリver: v1.249


SCALE Base 最新基準点(2026-05-27 更新・前回)

2026-05-27 09:55 更新(ce-2026-05-27-03 / app v1.247 → v1.248)【設計根治・snapshot-exclusive 同期 + 防御層全削除】

実施内容(1リリース・構造的根治):
1. ce-2026-05-27-03 race が構造的に起きない snapshot-exclusive 同期に書き換え + 防御層全削除
- メンバー報告(大串):「防御系って対症療法イメージ。根本から起こらない設計に見直して」
- 旧設計の限界: ce-02/ce-04 の markLocalWrite + shouldSkipKVPull + inflight カウンタは「KV pull を一時的に待たせる」対症療法。slow ネットワークで PUT が 10秒以上遅れたら穴。さらに「ローカル削除した item が KV propagation 中に復活する」race は旧 mergeSessions の構造的欠陥として残っていた
- 新設計の核心: 「自分が PUT した snapshot」を ref で保持 → KV pull が来たら snapshot を完全に採用(KV を無視)。3秒後に snapshot をクリア → 以降は KV をそのまま採用。これで「自分の最新書き込みが消える / 自分の削除が復活する」race が構造的に発生しない
- 設計トレードオフ: snapshot 保持中の 3秒間は他端末の新規追加が見えない(次の pull で取り込まれる)。削除/編集の確実性 > 他端末の即時新規追加 を優先する設計判断

主な編集ファイル:
- lib/tasks-api.tsx(inflightSnapshot + putWithSnapshot + snapshotOrKv merge。markTasksLocalWrite/shouldSkipTasksKVPull/_tasksInflightWrites 全削除)
- lib/work-log.ts(markLocalWrite/shouldSkipKVPull を deprecated stub に。notifySessionsSnapshot/notifyReportsSnapshot 追加)
- lib/work-log-api.tsx(旧 mergeSessions/mergeReports 削除。sessionsSnapshot/reportsSnapshot ref で snapshot 受け取り)
- components/tasks/work-log/ActiveBoard.tsx(recentlyAddedRef / synthetic Task fallback / append 分岐 全削除)
- lib/changelog.ts / CLAUDE.md

バックアップ:
- 事前: 2026-05-27_094342_before-merge-based-refactor.tar.gz
- post-deploy: 2026-05-27_095401_post-deploy.tar.gz(v1.248 確定)

本番URL確認: ✅ HTTP 200(home/ / version.json: v1.248 / ce-2026-05-27-03)

除去されたコード量: 約 200 行(ヘルパー + 防御層 + 重複ロジック)。コードが「シンプル + 設計が読める」状態に

退化防止: ce-2026-05-27-02(朝日報 onBlur モーダル)/ ce-2026-05-27-01(NotificationCenter)/ ce-2026-05-26-07(end prefill submittedRef)/ ce-2026-05-26-05(重複削除 UI)すべて無変更

** 学び(Vault 蓄積・設計レベル根治の威力):
-
「防御層を厚くする」 < 「構造的に起きない設計」: 多段防御は穴を減らすが消せない。snapshot-exclusive のような「データフローを反転」する設計変更は穴を構造的に消せる
-
「snapshot を絶対視」がシンプル: 旧 merge は「ローカル ∪ KV」で「ローカル削除を保持できない」構造的欠陥があった。snapshot がある間は KV を完全無視 = シンプルかつ正しい
-
「3秒の遅延」と「事故の絶対回避」のトレードオフ: 3秒間は他端末の新規が見えない代わりに、自分の削除/編集が消えない。事故性のあるパスを優先する判断が UX の信頼性に直結
-
コード量の削減 = 保守性向上**: 200行の防御層を削除でき、新規 race が出ても snapshot ロジックだけ調整すれば対処可能に

最新スタンプ:
- 最新changelog: ce-2026-05-27-03
- 最新baseline: 2026-05-27_095401_post-deploy.tar.gz
- 最新アプリver: v1.248


SCALE Base 最新基準点(2026-05-27 更新・前回)

2026-05-27 08:25 更新(ce-2026-05-27-02 / app v1.246 → v1.247)【改善・朝日報の新規タスクモーダル onBlur 発火】

実施内容(1リリース・UX一貫性):
1. ce-2026-05-27-02 朝日報の新規タスク入力でモーダル出ない問題修正
- メンバー報告(大串):「作業中ではモーダル出るのに、朝日報だと新規タスクのモーダル出ない、ちゃんと実装できるようにして」
- 真因: app/(dashboard)/tasks/work-log/morning/page.tsx のタスク input が onKeyDown(Enter) ハンドラだけだった。Enter キー以外(別UI クリック / Tab / モバイル「完了」ボタン)でフォーカスを外す経路では handleTaskLineEnter が呼ばれず、base 登録 + setSelectedTask の自動オープンが発火しなかった
- 挙動の差: ActiveBoard の addTask は + ボタン押下で常に base 登録 + setSelectedTask が走る。start/page.tsx は ce-2026-05-08-01 で意図的に onBlur 経由のモーダル自動オープンを廃止(その方針を維持)。morning は ce-2026-05-23-02 で Enter 限定で復活したが onBlur が落ちていた状態
- 修正: morning の各タスク input に onBlur={() => handleTaskLineEnter(idx)} を追加。handleTaskLineEnter は冒頭で「既に baseTaskIds/selectedRoutineIds に紐付け済みなら return」の dedup が入っているので、Enter と onBlur のダブル発火でも 2 度 base 作成されない安全設計

主な編集ファイル:
- app/(dashboard)/tasks/work-log/morning/page.tsx(input に onBlur 追加)
- lib/changelog.ts / CLAUDE.md

バックアップ:
- 事前: 2026-05-27_082456_before-ce-2026-05-27-02-deploy.tar.gz
- post-deploy: 2026-05-27_082727_post-deploy.tar.gz(v1.247 確定)

本番URL確認: ✅ HTTP 200(home/ / version.json: v1.247 / ce-2026-05-27-02)

退化防止: ce-2026-05-27-01(NotificationCenter)/ ce-2026-05-26-07(end prefill)/ ce-2026-05-23-02(朝日報 Enter モーダル)/ ce-2026-05-08-01(start モーダル廃止)すべて無変更

** 学び(Vault 蓄積・UI 一貫性の落とし穴):
-
「同じ画面体験」を期待される所では Enter + onBlur 両方フックする: モバイルでは Enter キーを押す習慣が薄く、別UI を直接タップでフォーカス離脱するのが普通。Enter 限定ハンドラは「PC ユーザーは満足、モバイルでは機能してない」となりやすい
-
dedup を最初から仕込んでおくとダブル発火安全**: handleTaskLineEnter 内に if (existingBase && baseTaskIds.includes(existingBase.id)) return; を入れておくと、複数のトリガー(Enter / onBlur / 別ボタン)を同時に張れる

最新スタンプ:
- 最新changelog: ce-2026-05-27-02
- 最新baseline: 2026-05-27_082727_post-deploy.tar.gz
- 最新アプリver: v1.247


SCALE Base 最新基準点(2026-05-27 更新・前回)

2026-05-27 08:20 更新(ce-2026-05-27-01 / app v1.245 → v1.246)【復活+拡張・通知ベル機能 / 未提出/未完了の一元管理】

実施内容(1リリース・UX根本改善):
1. ce-2026-05-27-01 通知ベル機能を実装+未提出/未完了の一元管理
- メンバー報告(大串):「前まで右上に通知来てそこから出せたのに、その機能なくなった。スマホver出してから不具合多い、根本から見直して」
- 真因: components/layout/Header.tsx の Bell が onClick 無しで赤ドット出すだけの飾りだった。過去 v9 系で存在していた「通知パネル」が SCALE Base 移行時に未復活
- 新規: components/layout/NotificationCenter.tsx — Bell 押下でドロップダウンを開閉。WorkLogProvider の reloadCount を購読して 30 秒ごと / PC↔スマホ同期で自動更新。クリック外 / Esc で閉じる。バッジに件数(9件以上は 9+)
- 検出ロジック 5 種:
1. night-overdue: 当日より過去の業務日で稼働セッションあり (endedAt あり) なのに夜日報無し → 日付ごとに 1 行、クリックで /tasks/work-log/night?date=YYYY-MM-DD
2. morning-today: 今日の朝日報無し + (時刻 ≥ 9 or 当日稼働セッションあり)
3. night-today: 今日の夜日報無し + (時刻 ≥ 18 or 当日終了済みセッションあり)
4. dangling-session: 進行中(endedAt=null)セッションが 2 件以上
5. dup-session: 同日終了済みセッションで startedAt/endedAt が ±60秒 で並走
- Header 改修: Bell 直書き JSX → <NotificationCenter /> に置換

主な編集ファイル:
- components/layout/NotificationCenter.tsx(新規)
- components/layout/Header.tsx(Bell → NotificationCenter 差し替え)
- lib/changelog.ts / CLAUDE.md

バックアップ:
- 事前: 2026-05-27_082015_before-ce-2026-05-27-01-deploy.tar.gz
- post-deploy: 2026-05-27_082144_post-deploy.tar.gz(v1.246 確定)

本番URL確認: ✅ HTTP 200(home/ / version.json: v1.246 / ce-2026-05-27-01)

退化防止: ce-2026-05-26-07(end prefill)/ ce-2026-05-26-06(Slack スレ重複)/ ce-2026-05-26-05(重複セッション)すべて無変更。/tasks/work-log/ 上部の「過去の夜日報が未提出です」アラートも保持(同期表示・冗長で確実)

** 学び(Vault 蓄積・UX 機能のリグレッション):
-
「機能ありそうな見た目」で実体が無いコンポーネントは UX 退化: Bell が赤ドット付きで存在するのに onClick 無しは「あるはずなのに動かない」と感じさせる最悪の状態。飾り UI は退化リスク
-
「全ページの Header に通知を置く」が UX 改善の汎用解: 個別ページの上部アラートは「そのページを開かないと気付けない」。Header 配置なら他のシステムを使っている時でも未提出に気付ける
-
「30秒ごとに reactive 再計算」は WorkLogProvider と相性が良い**: PC で submit → 30秒以内に スマホの Bell バッジが減る。同じ仕組みを Slack 通知の代わりに使える可能性

最新スタンプ:
- 最新changelog: ce-2026-05-27-01
- 最新baseline: 2026-05-27_082144_post-deploy.tar.gz
- 最新アプリver: v1.246


SCALE Base 最新基準点(2026-05-26 更新・前回)

2026-05-26 15:10 更新(ce-2026-05-26-07 / app v1.244 → v1.245)【根治・作業終了報告で前回の星/報告が prefill される UX 劣化バグ】

実施内容(1リリース・思考停止 UX 防止):
1. ce-2026-05-26-07 作業終了報告で前回の星/報告が prefill されるバグの根治
- メンバー報告(大串):「作業終了報告の際に星や報告が勝手に入力されちゃってる、まっさらなところに入力したい。最初から入力されてると、もうそれでいいやと思考がなっちゃう」
- 真因: ce-2026-05-26-01 で追加した unmount cleanup が、handleSave で clearDraft(today) した直後に router.push で unmount → useEffect cleanup → draftStateRef.current にまだ提出値が残っているため !isDraftEmptysaveDraft で localStorage に書き戻し。次に end ページを開くと loadDraft で前回値が prefill されていた
- 症状: 1セッション目で星 4 + ブロッカー入力 + 提出 → 不可視で unmount が draft 再保存 → 2セッション目の end ページが「星 4 + 前回のブロッカー文字列」で開く →「同じでいいや」となって思考が止まる UX 劣化
- 修正: 各ページに submittedRef = useRef(false) を追加。handleSave で clearDraft → submittedRef.current = true → router.push の順で flag を立てる。unmount cleanup 冒頭で if (submittedRef.current) return; で skip。「未提出のまま離脱した場合」は従来通り unmount save(追加タスク消失バグ対策の安全弁は維持)

主な編集ファイル:
- app/(dashboard)/tasks/work-log/end/page.tsx
- app/(dashboard)/tasks/work-log/morning/page.tsx
- app/(dashboard)/tasks/work-log/night/page.tsx
- lib/changelog.ts / CLAUDE.md

バックアップ:
- 事前: 2026-05-26_150957_before-ce07-deploy.tar.gz
- post-deploy: 2026-05-26_151127_post-deploy.tar.gz(v1.245 確定)

本番URL確認: ✅ HTTP 200(home/ / version.json: v1.245 / ce-2026-05-26-07)

既存の prefill 値 対策: 既に stale draft が localStorage に残っているユーザーは、end ページ上部の「下書きを復元しました」バナーの「下書きを破棄」リンクを 1 回クリックすると state リセット + clearDraft で完全クリーンになる。今後の submit からは prefill 復活しない

退化防止: ce-2026-05-26-06(Slack スレ重複根治)/ ce-2026-05-26-05(重複セッション)/ ce-2026-05-26-04(synthetic Task)/ ce-2026-05-26-01(追加タスク消失の unmount cleanup)すべて無変更。submittedRef は「提出済みケースのみ skip」なので未提出離脱は従来通り saveDraft する

** 学び(Vault 蓄積・defensive cleanup の副作用):
-
「ローカル state を unmount 時に必ず保存」は副作用が出やすい: ce-01 で「未提出離脱で消えない」目的で入れた cleanup が、submit パスで「クリアした draft を即再保存」してしまった。「未提出 vs 提出済み」を区別する flag (submittedRef) は cleanup の必須セット
-
UX 視点での「再現可能性」テスト: 機能としては「データは保存される」で問題なしだが、ユーザーの主観では「思考が止まる」UX 劣化。バグレポートが「動かない」ではなく「使いたくない」になる前に拾えるか
-
defensive useRef × cleanup パターンのテンプレ**: ① 状態を ref に同期 ② submit 後 flag を立てる ③ unmount cleanup で flag が立ってたら skip、立ってなかったら save。この 3 点セットは draft 保存のあるすべてのフォームに適用すべき

最新スタンプ:
- 最新changelog: ce-2026-05-26-07
- 最新baseline: 2026-05-26_151127_post-deploy.tar.gz
- 最新アプリver: v1.245


SCALE Base 最新基準点(2026-05-26 更新・前回)

2026-05-26 15:00 更新(ce-2026-05-26-06 / app v1.243 → v1.244)【根治・Slack日次報告スレが PC とスマホで別に立つ重複バグ】

実施内容(1リリース・Slack 検索方式で 1日1スレ統合):
1. ce-2026-05-26-06 Slack 日次報告スレが PC とスマホで別に立つ重複バグの根治
- メンバー報告(大串):「スマホで作業報告したら Slack に PC とは別スレが立つ」「5/26 細川 が 2 スレある」
- 真因: lib/report-notify.tsensureDailyThreadscale-slack-daily-thread:<userId>:<date> キーで localStorage 単独でキャッシュ。localStorage はデバイス毎に独立しているため、PC では PC が作った ts、スマホでは スマホが作った ts を保持 → それぞれ別スレッドへ投稿していた
- 検討: scale-task-cron KV に共有保存しようとしたが、worker は固定キー(tasks/projects/bottom_tasks/members/audit_log)以外を invalid key で拒否。scale-task-cron は触らない方針(lock 違反)のため、共有 KV ストレージ案は不採用
- 採用: サーバーサイドで Slack conversations.history を呼び、JST 今日 0:00 以降の親メッセージから :date: *M/D 日次報告(ユーザー名)* 完全一致を検索する方式に変更。Slack 自体を SoT として使うため、追加ストレージ不要 + 自己整合(重複親があれば最古に合流 / なければ新規)
- 新規: functions/api/daily-thread.ts — POST { userId, userName, date, channel } → { ts }。① conversations.history で今日の親メッセージを検索 ② マッチがあれば最古の ts を返す ③ 無ければ chat.postMessage で新規親を投稿して ts を返す
- 改修: lib/report-notify.ts ensureDailyThread を /api/daily-thread 呼び出しに置換。localStorage は 2nd-level cache(API 失敗時の最後の砦)として残置

主な編集ファイル:
- functions/api/daily-thread.ts(新規・サーバー側 GET-or-CREATE + Slack 検索)
- lib/report-notify.ts(ensureDailyThread の中身置換)
- lib/changelog.ts(1件追記)/ CLAUDE.md(最新スタンプ)

バックアップ:
- 事前: 2026-05-26_150240_before-ce06-deploy.tar.gz
- post-deploy: 2026-05-26_150423_post-deploy.tar.gz(v1.244 確定)

本番URL確認: ✅ HTTP 200(home/ / version.json: v1.244 / ce-2026-05-26-06)+ /api/daily-thread POST 動作確認済み(1回目 source=newly-created → 2回目 source=slack-search で同じ ts 返却)

退化防止: ce-2026-05-26-05(重複セッション + 削除UI)/ ce-2026-05-26-04(synthetic Task)/ ce-2026-05-26-03(セッション時間0分)/ 朝日報・作業開始・作業終了・夜日報のテキストフォーマット / REPORT_CHANNEL すべて無変更

既存の重複対応(5/26 細川 2 スレ):
今日の 13:12 スレ(3件の返信)は、過去の localStorage 同期欠落で発生したもの。今後の投稿は最古の 05:03 スレに合流するため、13:12 スレは 3 件の返信だけが残るオーファン状態に。手動で 13:12 スレを削除する場合は Slack 上で実施

** 学び(Vault 蓄積・SoT 設計の選択肢):
-
「他人と共有が必要な状態は localStorage に置くな」: ユーザー単位だけならローカルで足りるが、デバイス間で同じ状態を見せたい場合は必ず共有ストレージへ。タスク状態も Slack スレ ts も同じ
-
「共有ストレージが使えない時は SoT そのものに問い合わせる」: scale-task-cron が固定キーしか受け付けない制約下で、Slack 自体を SoT として「conversations.history で検索」する設計に切り替えたら、追加ストレージ不要で自己整合する解になった
-
「自己整合・冪等な検索 API」が複数デバイス問題の最終解**: 状態を持たず毎回 SoT を引きに行く設計は overhead はあるが、衝突・古いキャッシュ・データ消失 すべてに自動対処できる

最新スタンプ:
- 最新changelog: ce-2026-05-26-06
- 最新baseline: 2026-05-26_150423_post-deploy.tar.gz
- 最新アプリver: v1.244


SCALE Base 最新基準点(2026-05-26 更新・前回)

2026-05-26 11:30 更新(ce-2026-05-26-05 / app v1.242 → v1.243)【根治・PC-スマホ同時起動で重複セッション + 重複削除UI】

実施内容(1リリース・新規防止 + 既発生クリーンアップ UI):
1. ce-2026-05-26-05 PC-スマホ同時起動で同セッションが2件作られる重複バグ + 重複削除 UI
- メンバー報告(大串):「09:59-11:24 のセッションが 2件並ぶ(1h24m / 1h25m)」
- 真因: start/page.tsx handleSave が genId('ses') で毎回新しい sessionId を作成。PC で稼働開始 → KV PUT → スマホは KV pull 遅延でローカル sessions に未反映 → スマホで稼働開始 押下時にローカルに進行中セッション無いと判定 → 別 sessionId で 2 つ目を作成 → 両方が並走して end も両方走り 1分の差で記録
- 修正 1(新規防止): handleSave 冒頭で loadSessionsFromKVByUser(user.id) を await して KV 最新を pull → ローカルとマージ。「24時間以内に開始 + 自分のセッション + 未終了」が見つかれば既存セッションを reuse(tasks/selectedRoutineIds 後勝ち上書き、startedAt は保持)。start report も既存 sessionId にひもづくものを upsert
- 修正 2(async 化): KV pull await のため handleSave を async function に変更。activeSession 変数で reuse/新規を統一
- 修正 3(重複削除 UI): dashboard の今日のセッションテーブル右端に削除ボタン(ゴミ箱アイコン)追加。同ユーザー・開始 ±60秒・終了 ±60秒 のセッションがあれば「重複候補」バッジ表示 + ボタン色強調。clicked → confirm → session + 関連 start/end report も連動削除

主な編集ファイル:
- app/(dashboard)/tasks/work-log/start/page.tsx(KV pull + reuse 分岐 + async 化)
- app/(dashboard)/tasks/work-log/page.tsx(handleDeleteSession + テーブル UI + 重複バッジ)
- lib/changelog.ts(1件追記)/ CLAUDE.md(最新スタンプ)

バックアップ:
- 事前: 2026-05-26_113022_before-ce05-deploy.tar.gz
- post-deploy: 2026-05-26_113146_post-deploy.tar.gz(v1.243 確定)

本番URL確認: ✅ HTTP 200(home/ / tasks/work-log/ / base.scale-group.co.jp/tasks/work-log/ / version.json: v1.243 / ce-2026-05-26-05)

退化防止: ce-2026-05-26-04(synthetic Task fallback)/ ce-2026-05-26-03(セッション時間0分)/ ce-2026-05-25-32(72時間バグ)/ ce-2026-05-25-10(dual session 警告)すべて無変更

** 学び(Vault 蓄積・複数端末データ衝突の防止設計):
-
「新規 ID を作る前に KV から最新を引け」: ローカル sessions だけで判定すると、他端末で作った状態を認知できず必ず重複が出る。保存直前に await loadSessionsFromKVByUser → reuse 判定 が複数端末で正しく動く設計
-
「既発生データの片付け UI」も同時に出す: 防止策を入れても、すでに発生した重複は残る。「重複候補」バッジ + ワンクリック削除 UI を最初から付けると、ユーザーはサポート問い合わせなしで自己解決できる
-
session.id がプライマリキーなのに無条件採番してた構造的欠陥**: ID 生成は「既存が無いことを確認した後だけ」呼ぶのが原則。今回 startSession に reuse 分岐を入れたことで他の同種箇所(morning report の genId('rep') 等)も同じパターンで強化できる

最新スタンプ:
- 最新changelog: ce-2026-05-26-05
- 最新baseline: 2026-05-26_113146_post-deploy.tar.gz
- 最新アプリver: v1.243


SCALE Base 最新基準点(2026-05-26 更新・前回)

2026-05-26 11:00 更新(ce-2026-05-26-04 / app v1.241 → v1.242)【完全根治・2回目以降のタスク追加 fallback モーダル再発】

実施内容(1リリース・多段防御):
1. ce-2026-05-26-04 新タスク追加 2回目以降の fallback モーダル再発の完全根治
- メンバー報告(大串):「1つのタスク追加だと起きないけど、2回目以降に起きる」「TERASU CRMのせーごくんFB反映」タスクで再発
- 真因: ce-02 の保護 4 秒では PUT が slow ネットワーク (3G/PWA) で遅れた場合や、ユーザーが 5 秒以上待ってからクリックした場合に loadAll の GET が古いデータで上書きする隙間があった。連続 2 つ目のタスク追加で 2 つの PUT が並行すると、後の PUT 完了前に loadAll が走ると 1 つ目しか反映されてない KV データで baseTasks が巻き戻る
- 修正 1(最後の砦): ActiveBoard.tsx クリックハンドラに synthetic Task フォールバック追加。baseTasks / recentlyAddedRef どちらにも無くて source=base or sourceId 有 のタスクは、progress エントリ (taskText / status / sourceId) から最小 Task を構築して TaskDetailModal を開く。「紐付けが解決できませんでした」フォールバックモーダルは source=base のタスクでは 絶対に出ない 構造に
- 修正 2(保存も整合): TaskDetailModal の onSave 分岐を「baseTasks に id あれば update / なければ append」に変更。synthetic Task の編集を保存しても baseTasks に追加されてデータ整合が保たれる
- 修正 3(KV pull 保護強化): lib/tasks-api.tsx の TASKS_LOCAL_WRITE_PROTECTION_MS を 4000→10000ms に延長。saveToAPI で PUT 中の inflight カウンタを追跡 → PUT 中は問答無用で pull スキップ。PUT 完了直後 + 完了から 2 秒後 にも markTasksLocalWrite を打って多段防御

主な編集ファイル:
- components/tasks/work-log/ActiveBoard.tsx(クリックハンドラに synthetic Task fallback + onSave の append 分岐)
- lib/tasks-api.tsx(保護 10 秒 + inflight カウンタ + PUT 完了 +2 秒の追加 mark)
- lib/changelog.ts(1件追記)/ CLAUDE.md(最新スタンプ)

バックアップ:
- 事前: 2026-05-26_100703_before-ce04-deploy.tar.gz
- post-deploy: 2026-05-26_100850_post-deploy.tar.gz(v1.242 確定)

本番URL確認: ✅ HTTP 200(home/ / tasks/work-log/active/ / version.json: v1.242 / ce-2026-05-26-04)

退化防止: ce-2026-05-26-03 (セッション時間0分) / ce-2026-05-26-02 (KV pull 競合) / ce-2026-05-26-01 (unmount cleanup) / ce-2026-05-23-01 (旧モーダル中身空対策) すべて無変更

** 学び(Vault 蓄積・「保護期間 + 最後の砦」二重設計):
-
「タイマー保護期間」だけだと slow ネットワークで漏れる: 4 秒・10 秒・60 秒、どこに設定しても境界条件で漏れる。inflight カウンタで「PUT 中は必ずスキップ」+ PUT 完了後にも mark を打つことで、PUT が遅くても穴を塞げる
-
「symptom を構造的に出さない fallback」を最後の砦に置け: クリックハンドラで synthetic Task を構築して TaskDetailModal を必ず開く設計にすれば、上流の保護がどう抜けようと「紐付けが解決できませんでした」モーダルは絶対に出ない。バグの原因不明な状態でも症状を消せる
-
synthetic Task の保存は「append vs update」分岐で整合**: 旧 onSave は .map() で update のみだったため synthetic Task が消えていた。exists ? update : append の 1 行分岐で同じ UX でデータ整合も維持

最新スタンプ:
- 最新changelog: ce-2026-05-26-04
- 最新baseline: 2026-05-26_100850_post-deploy.tar.gz
- 最新アプリver: v1.242


SCALE Base 最新基準点(2026-05-26 更新・前回)

2026-05-26 10:50 更新(ce-2026-05-26-03 / app v1.240 → v1.241)【根治・作業セッション時間0分表示バグ】

実施内容(1リリース・集計バグ根治 + 旧データ救済):
1. ce-2026-05-26-03 作業セッション時間 0分表示バグ根治
- メンバー報告(細川):「ダッシュボードの今日の作業セッション、06:17-08:28 のセッションが0分と表示される」
- 真因: ActiveBoard.endSession は session.endedAt をセットするだけで minutes 計算は end ページの handleSave 任せだった。ユーザーが end ページに到達する前に離脱 / handleSave 内部で例外 / KV pull race のいずれかで minutes が初期値 0 のまま保存される dangling データが発生
- 症状: ダッシュボード「今日の作業セッション」表示が s.minutes 直参照のため「0分」、totalMinutesToday / stats / night の集計も 0 を足して稼働時間が過少表示
- 修正1(根本): ActiveBoard.endSession で endedAt セット時に netSessionMinutes(ended, endIso) で minutes も同時計算。end ページの handleSave も同じ計算式で冪等
- 修正2(旧データ救済): lib/work-log.tseffectiveSessionMinutes(session) ヘルパー追加(s.minutes > 0 ? s.minutes : netSessionMinutes(s, s.endedAt) で fallback)。既に minutes=0 で保存された壊れたデータも表示・集計時に正しい値が出る
- 修正3(全集計に適用): dashboard / stats / night すべての sum + s.minutessum + effectiveSessionMinutes(s) に置換

主な編集ファイル:
- components/tasks/work-log/ActiveBoard.tsx(endSession で minutes 計算 + import netSessionMinutes)
- app/(dashboard)/tasks/work-log/end/page.tsx(handleSave も netSessionMinutes に統一)
- lib/work-log.ts(effectiveSessionMinutes 新規 export)
- app/(dashboard)/tasks/work-log/page.tsx(totalMinutesToday + 今日のセッション表示)
- app/(dashboard)/tasks/work-log/stats/page.tsx(5箇所の集計)
- app/(dashboard)/tasks/work-log/night/page.tsx(today / 週 / 月 の集計)
- lib/changelog.ts(1件追記)/ CLAUDE.md(最新スタンプ)

バックアップ:
- 事前: 2026-05-26_094818_before-ce03-deploy.tar.gz
- post-deploy: 2026-05-26_095126_post-deploy.tar.gz(v1.241 確定)

本番URL確認: ✅ HTTP 200 全て(home/ / tasks/work-log/ / base.scale-group.co.jp/tasks/work-log/ / version.json: v1.241 / ce-2026-05-26-03)

退化防止: ce-2026-05-26-02(KV pull競合)/ ce-2026-05-26-01(unmount cleanup)/ ce-2026-05-25-32(72時間バグ)/ pausedDurationMs / netSessionMinutes 式 すべて無変更

** 学び(Vault 蓄積・データ確定のタイミング設計):
-
「データ最終確定」は一番上流の操作で済ませろ: endSession(ユーザーが「作業終了する」を押した瞬間)が最も信頼できる確定点なのに、minutes 計算を end ページの handleSave に委譲していた。途中で離脱や例外があると 0 のまま残る。確定すべき値は確定できる場所で確定するのが安全
-
「壊れたデータを表示時に救済する fallback ヘルパー」を 1 つ用意するパターン: effectiveSessionMinutes のように「stored > 0 ならそれ、0/未定義なら再計算」のヘルパーを 1 つ作って全集計に通すと、過去データも未来データも 1 関数で吸収できる。data migration なしで救済可能
-
集計の sum + obj.field パターンは fallback 経路がない時の事故源**: s.minutes 直参照を全部 helper 経由に置換することで、フィールドの 0/undefined/壊れケースを 1 箇所で扱える

最新スタンプ:
- 最新changelog: ce-2026-05-26-03
- 最新baseline: 2026-05-26_095126_post-deploy.tar.gz
- 最新アプリver: v1.241


SCALE Base 最新基準点(2026-05-26 更新・前回)

2026-05-26 10:00 更新(ce-2026-05-26-02 / app v1.239 → v1.240)【根治・新タスク追加→クリック fallback モーダル KV pull 競合】

実施内容(1リリース・KV pull 競合根治):
1. ce-2026-05-26-02 新タスク追加→クリック時に「紐付けが解決できませんでした」フォールバックモーダル出るバグの根治
- メンバー報告:「定例MTGのアジェンダを朝日報か作業開始報告、作業中のところで登録 → 以下のようなモーダルが出て理想のモーダルと違う」
- 真因: lib/tasks-api.tsx の TasksProvider: saveTaskssetTasks(local) + saveToAPI(async PUT)。直後の loadAll() が ① 60s interval ② focus ③ visibilitychange のいずれかで発火 → fetchFromAPI が KV 伝搬遅延で「新規タスク未反映の古いデータ」を返す → setTasks で上書き → 新規タスクがローカル baseTasks から消える → ActiveBoard のクリックハンドラで baseTasks.find(x => x.id === p.sourceId) が null → 旧モーダルへフォールバック → ce-2026-05-23-01 で追加した「紐付けが解決できませんでした」表示が出る
- 修正 1(根本): lib/tasks-api.tsxmarkTasksLocalWrite() / shouldSkipTasksKVPull() を追加(work-log.ts と同パターン・4秒保護期間)。saveToAPI 冒頭で markTasksLocalWrite を必ず呼び、loadAllforce=true 以外なら保護期間中スキップ。初回マウントと明示 reload は force=true で通す
- 修正 2(防御): ActiveBoard.tsxrecentlyAddedRef = useRef<Map<taskId, Task>> を追加。addTask で新規 or 既存マッチした Task をここにもキャッシュ。クリックハンドラと旧モーダル baseTask 解決の両方で「baseTasks.find が null なら recentlyAddedRef を引く」フォールバックを追加

主な編集ファイル:
- lib/tasks-api.tsx(markLocalWrite 機構 + loadAll に force オプション + saveToAPI で markLocalWrite 呼ぶ)
- components/tasks/work-log/ActiveBoard.tsx(recentlyAddedRef + addTask でキャッシュ + クリックハンドラ/旧モーダル fallback)
- lib/changelog.ts(1件追記)/ CLAUDE.md(最新スタンプ)

バックアップ:
- 事前: 2026-05-26_091759_before-ce02-deploy.tar.gz
- post-deploy: 2026-05-26_091856_post-deploy.tar.gz(v1.240 確定)

本番URL確認: ✅ HTTP 200 全て(home/ / tasks/work-log/active/ / tasks/work-log/morning/ / base.scale-group.co.jp/home/ / version.json: v1.240 / ce-2026-05-26-02)

退化防止: ce-2026-05-26-01(unmount cleanup)/ ce-2026-05-25-32(72時間バグ)/ ce-2026-05-23-01(旧モーダル中身空対策)すべて無変更。work-log.ts 側の markLocalWrite も無変更

** 学び(Vault 蓄積・KV pull 競合の根本対策):
-
「ローカル書き込み → 即 KV pull が発火する経路」が複数ある場合、保護期間で防ぐのが定石: タイマー(60s) / focus / visibilitychange の 3 経路がある TasksProvider では、saveToAPI 直後に loadAll が走ると古いデータで上書きされる。markLocalWrite で書き込み時刻を localStorage に記録 → shouldSkipKVPull で 4 秒以内ならスキップ。これで KV 伝搬遅延を吸収
-
work-log.ts と tasks-api.tsx の対称設計: 同じパターン(markLocalWrite/shouldSkipKVPull)を 2 つの Provider に独立して持たせる。KEY を別にして衝突回避(scale-worklog-last-local-write vs scale-tasks-last-local-write
-
「root fix + defensive fallback」の二重保護**: 根本治療(KV pull スキップ)+ 念のため UI 側で recentlyAddedRef キャッシュを持つ。同種のクリックハンドラ fallback バグの再発防止としても効く

最新スタンプ:
- 最新changelog: ce-2026-05-26-02
- 最新baseline: deploy 後に更新
- 最新アプリver: v1.240


SCALE Base 最新基準点(2026-05-26 更新・前回)

2026-05-26 09:00 更新(ce-2026-05-26-01 / app v1.238 → v1.239)【再発根治・タスク消失バグ unmount cleanup】

実施内容(1リリース・再発バグ二重保護):
1. ce-2026-05-26-01 作業終了タスク消失バグ再発根治
- メンバー再報告:「作業終了で追加タスク入れ込み中→他画面飛んで戻る→タスク消える」
- 真因: ce-2026-05-25-08 の !draftRestoreAttempted ガードは保持されていたが、別経路で再発。React の挙動: input onChange → setState → 次の render → useEffect (microtask) 実行。ユーザーが setState 直後に router.push で別画面遷移 → end ページ unmount → useEffect 実行されず → saveDraft 呼ばれない → 戻ってきた時に loadDraft が古い値
- 修正: useRef で draftStateRef を作成し最新 state を常に同期。unmount cleanup useEffect で saveDraft(draftStateRef.current) を必ず呼ぶ。これで通常の useEffect 遅延ですり抜けた場合でも確実保存
- 影響範囲: end / morning / night の 3 画面すべてに同じ仕組み追加(同種バグの予防)

主な編集ファイル:
- app/(dashboard)/tasks/work-log/end/page.tsx(useRef + unmount cleanup)
- app/(dashboard)/tasks/work-log/morning/page.tsx(同上)
- app/(dashboard)/tasks/work-log/night/page.tsx(同上)
- lib/changelog.ts(1件追記)/ CLAUDE.md(最新スタンプ)

バックアップ:
- 事前ラベル付き: 2026-05-26_085614_before-draft-revival.tar.gz
- post-deploy: deploy 後に更新

本番URL確認: (次タスクで実施)

退化防止: ce-2026-05-25-32 (72時間バグ) / ce-2026-05-25-08 (draft 復元競合) すべて無変更

** 学び(Vault 蓄積・useEffect 遅延の罠):
-
React の setState → useEffect 実行は microtask 遅延: input onChange の中で setState → 同期的に router.push されると、unmount 後に useEffect 実行で saveDraft が呼ばれない
-
「state 連動の自動保存 useEffect」だけでは不十分: unmount cleanup で「最新 state を必ず保存」する二重保護がデータ消失防止の defensive パターン
-
useRef で最新 state を別経路で保持**: state ↔ ref を同期し、cleanup で ref から読み取る → unmount でも確実にアクセス可能

最新スタンプ:
- 最新changelog: ce-2026-05-26-01
- 最新baseline: deploy 後に更新
- 最新アプリver: v1.239


SCALE Base 最新基準点(2026-05-25 更新)

2026-05-25 17:30 更新(ce-2026-05-25-32 / app v1.237 → v1.238)【致命fix・72時間バグ + PC同期不全】

実施内容(1リリース・データ破壊系致命バグ根治):
1. ce-2026-05-25-32 end ページの sessionId URL クエリ受け渡しで 72時間バグ根治
- メンバー報告:「スマホで作業終了報告したら作業時間が3時間半→72時間に / 報告画面が数日前の画面 / スマホで終了したのに PC ではまだ作業中」
- 真因: ce-2026-05-25-11 で end ページの runningId 取得を「進行中 or 直近10分以内に endedAt セット」に修正したが、WorkLogProvider の KV pull で「endedAt=null のまま数日前から放置された dangling session」が localStorage に混入すると、それが候補に拾われ targetId に。結果 handleSave で diffMinutes(running.startedAt, endedAt) が数日分 = 72時間 の巨大値に。saveSessions で古いセッションに endedAt セット → 現在の進行中セッションは変更されず PC で「作業中」のまま
- 修正 1: ActiveBoard endSession で router.push(\/tasks/work-log/end/?sessionId=\${session.id}`)で URL クエリに sessionId 必ず付与 - **修正 2**: end ページで useSearchParams で querySessionId 取得。3段階優先で targetId 決定: ① URL クエリ(最優先)② 進行中 + 24時間以内開始の最新セッション ③ 直近10分以内 endedAt の最新セッション - **修正 3**: fallback の filter でstartedAtMs > oneDayAgoMs` で 24時間以上前の dangling session を除外
- useEffect deps に querySessionId 追加 で URL 変化時に再実行

主な編集ファイル:
- components/tasks/work-log/ActiveBoard.tsx(router.push に URL クエリ追加)
- app/(dashboard)/tasks/work-log/end/page.tsx(useSearchParams import + 3段階優先 targetId 決定)
- lib/changelog.ts(1件追記)/ CLAUDE.md(最新スタンプ)

バックアップ:
- 事前ラベル付き: 2026-05-26_074640_before-ce32-deploy.tar.gz
- post-deploy: 2026-05-26_064831_post-deploy.tar.gz(v1.238 確定)

本番URL確認: ✅ HTTP 200(home/ / tasks/work-log/end/?sessionId=test / version.json: v1.238 / ce-2026-05-25-32)

退化防止: ce-2026-05-25-31 (safe-area + li overflow 撤回) / ce-2026-05-25-30 (タスク行 -mx-1 撤回) / ce-2026-05-25-13 (報告できない根治) すべて無変更

** 学び(Vault 蓄積・データ破壊バグの教訓):
-
「画面表示の候補ロジック」をデータ更新(saveSessions 等)に流用するな: ce-11 の runningId 取得は「画面表示候補」として設計されたが、handleSave がそれをそのまま「データ更新対象」として使ったので、古いセッションに endedAt が書き込まれた。データ更新対象のセッション ID は呼び出し元から明示的に渡すのが安全
-
「KV pull で過去データが混入する」リスクを常に考える: ローカル単体なら起きないバグも、他端末/過去データが mix される環境では発生。localStorage の中身を全て信用しない、確実な ID を別経路で渡す**

最新スタンプ:
- 最新changelog: ce-2026-05-25-32
- 最新baseline: 2026-05-26_064831_post-deploy.tar.gz
- 最新アプリver: v1.238


2026-05-25 16:30 更新(ce-2026-05-25-31 / app v1.236 → v1.237)【根本フィット・safe-area撤回 + li overflow撤回】

実施内容(1リリース・「右寄り」「完了押せず途切れる」 2点根治):
1. ce-2026-05-25-31 safe-area-inset-left/right 撤回 + li overflow-hidden 撤回
- 大串FB「全体的に右寄り・完了とか押せずに途切れる」
- 真因 A: ce-28 で最外側 div に paddingLeft: env(safe-area-inset-left), paddingRight: env(safe-area-inset-right) 追加。iPhone 縦持ちで左右の safe-area-inset 値が非対称な場合(例: 左のみ padding 入る)コンテンツが右にズレる
- 真因 B: ce-22 で li に w-full max-w-full overflow-hidden 追加。basis-full の独立行ボタン群が li 内右 padding を超えた時に右側が overflow-hidden で隠れる → 完了ボタンに到達できない
- 修正 A: 最外側 div から safe-area-inset-left/right を撤回
- 修正 B: li の className から w-full max-w-full overflow-hidden を削除。main の overflow-x-hidden で全体保護があるので不要

主な編集ファイル:
- app/(dashboard)/layout.tsx(最外側 div の safe-area 撤回)
- components/tasks/work-log/ActiveBoard.tsx(li の overflow-hidden 撤回)
- lib/changelog.ts(1件追記)/ CLAUDE.md(最新スタンプ)

バックアップ:
- 事前ラベル付き: 2026-05-25_165912_before-safearea-li-revert.tar.gz
- post-deploy: 2026-05-25_163201_post-deploy.tar.gz(v1.237 確定)

本番URL確認: ✅ HTTP 200(home/ / version.json: v1.237 / ce-2026-05-25-31)

退化防止: ce-2026-05-25-30 (タスク行 -mx-1 撤回) / ce-2026-05-25-29 (main overflow-x-hidden) / ce-2026-05-25-28 (Header AppVersionBadge 撤去) ※後者の safe-area 部分のみ撤回

** 学び(Vault 蓄積・最後の学び):
-
「safe-area-inset」を縦持ち縦長アプリに無闇に追加するな: 縦持ち iPhone でも左右非対称な値が入る可能性があり、結果として全体が左右どちらかに寄る原因になる。横持ち対応必要時にのみ追加
-
「overflow-hidden」は階層が重なるほど致命的: main + card + li の 3 階層に overflow-hidden があると、どこかでコンテンツが隠れて「ここまで届かない」が発生。最上位 (main) 1 箇所のみで十分
-
「ボタンが押せない」 = 「画面外で押せない」or「overflow で隠れて押せない」の 2 通り。後者は意外と気付きにくい**

最新スタンプ:
- 最新changelog: ce-2026-05-25-31
- 最新baseline: 2026-05-25_163201_post-deploy.tar.gz
- 最新アプリver: v1.237


2026-05-25 16:15 更新(ce-2026-05-25-30 / app v1.235 → v1.236)【タスク行ボタン群 -mx-1 撤回・画面ピッタリフィット】

実施内容(1リリース・フィット感修正):
1. ce-2026-05-25-30 タスク行ボタン群の -mx-1/overflow-x-auto 撤回
- 大串FB「これって画面ぴったりにフィットしている認識?」+ スクショで右ボタン群が画面端寄り
- 真因: ce-22 で basis-full 独立行化 + ce-23 で 4ボタン切れ対策に overflow-x-auto sm:overflow-visible + -mx-1 sm:mx-0 px-1 sm:px-0 を入れた。これがボタン群が li の右 padding を侵食して画面端まで広がる状態 = 「画面端ピッタリで中途半端」の正体
- 修正: ラッパー div の className を basis-full sm:basis-auto flex items-center justify-end gap-1 sm:gap-2 shrink-0 overflow-x-auto sm:overflow-visible -mx-1 sm:mx-0 px-1 sm:px-0basis-full sm:basis-auto flex items-center justify-end gap-1 sm:gap-2 shrink-0 にシンプル化
- 効果: ボタン群が li の通常 padding 内で右寄せ → カード左右 padding と同じ感覚の余白

主な編集ファイル:
- components/tasks/work-log/ActiveBoard.tsx(タスク行ラッパー div シンプル化)
- lib/changelog.ts(1件追記)/ CLAUDE.md(最新スタンプ)

バックアップ:
- 事前ラベル付き: 2026-05-25_164338_before-task-row-margin-revert.tar.gz
- post-deploy: 2026-05-25_161546_post-deploy.tar.gz(v1.236 確定)

本番URL確認: ✅ HTTP 200(home/ / version.json: v1.236 / ce-2026-05-25-30)

退化防止: ce-2026-05-25-29 (main overflow-x-hidden) / ce-2026-05-25-28 (Header AppVersionBadge 撤去) / ce-2026-05-25-27 (tabs scrollbar 可視化) すべて無変更

** 学び(Vault 蓄積):
-
「画面端まで要素を引き伸ばす CSS(-mx, negative margin)」は『フィット感』と相反する: padding 内に収めて画面端から余白を保つのが「画面にフィット」の正解
-
「スクロール救済(overflow-x-auto)」も「フィット感」と相反する: 「収まらないからスクロール」発想は「綺麗に収める」発想と真逆。最初から収まるように要素サイズを決めるのが正解
-
2 時間半対応の最後の最後で気付いた**: 認識正常化 (ce-29) しても、過去に入れた「逆発想の修正」を撤回しないと完璧にフィットしない

最新スタンプ:
- 最新changelog: ce-2026-05-25-30
- 最新baseline: 2026-05-25_161546_post-deploy.tar.gz
- 最新アプリver: v1.236


2026-05-25 15:50 更新(ce-2026-05-25-29 / app v1.234 → v1.235)【認識正常化・真因 6 段目】

実施内容(1リリース・認識完全正常化):
1. ce-2026-05-25-29 main overflow-x-hidden 復活で右padding 確保
- 大串FB「スクロールできないけど〜〜〜」+ 認識確認で「画面内に綺麗に収めたい・スクロール不要・めっちゃちゃんと画面にフィット」が判明
- これまでの誤解: 「スクロールできない」を 「スクロール機能不全」 と捉えて overflow-x-auto で右スクロール許可してた → 真逆の対応
- 本当の要望: 「画面に綺麗にフィット = スクロール不要 = 右側にもちゃんと padding」
- 修正: main の overflow-y-auto overflow-x-autooverflow-y-auto overflow-x-hidden に戻す。これで右側 padding 16px が確実に視覚的に確保される
- overflow-x-hidden の弊害が無い理由: ce-22 のタスク行 basis-full 化 + ce-23 ボタン縮小 + ce-27 tabs scrollbar 撤回 等で、内側コンテンツはすでに完全に画面内に収まっている

主な編集ファイル:
- app/(dashboard)/layout.tsx(main の overflow-x を auto → hidden)
- lib/changelog.ts(1件追記)/ CLAUDE.md(最新スタンプ)

バックアップ:
- 事前ラベル付き: 2026-05-25_163734_before-overflow-hidden-revival.tar.gz
- post-deploy: 2026-05-25_160959_post-deploy.tar.gz(v1.235 確定)

本番URL確認: ✅ HTTP 200(home/ / version.json: v1.235 / ce-2026-05-25-29)

退化防止: ce-2026-05-25-28 (Header AppVersionBadge 撤去 + safe-area 左右) / ce-2026-05-25-27 (tabs scrollbar 可視化) すべて無変更

** 学び(Vault 蓄積・2 時間半対応の最終総括):
-
「スクロールできない」は機能不全ではなくフラストレーション表現の可能性が高い: 「綺麗じゃないけどスクロールで救済もできないモヤモヤ」を「スクロールできない」と表現することがある。最初に 「したいことは何か」を確認 すべきだった
-
ユーザーの要望は技術用語ではなく感覚で語られる: 「中途半端」「綺麗じゃない」「フィットしてない」等の感覚表現を、技術的に何を意味するか 推測ではなく確認 すべき
-
2 時間半の対応で得た最大の学び = 認識合わせを最優先する: ce-14 〜 ce-28 の 15 リリースは全部「スクロール機能不全の修正」前提だった。本当は「レイアウトをフィットさせる」要望だった。一発目の認識ずれが 15 リリース分の遠回りを生んだ**

最新スタンプ:
- 最新changelog: ce-2026-05-25-29
- 最新baseline: 2026-05-25_160959_post-deploy.tar.gz
- 最新アプリver: v1.235


2026-05-25 15:40 更新(ce-2026-05-25-28 / app v1.233 → v1.234)【真因 5 段目・Header アバター画面外+safe-area 左右】

実施内容(1リリース・「中途半端」根治):
1. ce-2026-05-25-28 Header AppVersionBadge 完全撤去 + safe-area-inset-left/right
- 大串FB「明らかに中途半端な画面で終わってる・そもそも中途半端って概念がない?」「大アバターさえ画面外」
- 真因 5-A: Header right block (Bell 36 + 区切り 9 + アバター 28 + AppVersionBadge ピル 44 + gap) = 約 135px が画面右端を超えて押し出されていた
- 真因 5-B: iPhone PWA viewport-fit=cover で上下の safe-area-inset-top は確保(ce-12)したが、左右の safe-area-inset-left/right は未対応。これが「物理的端ピッタリで引っかかる感」の原因
- 修正 5-A: Header.tsx 107-112行の AppVersionBadge + ユーザー名表示を完全削除。Header right block = Bell + アバター のみに圧縮(合計 ~80px)。ver 確認は Sidebar 左下で可能なので機能損失なし
- 修正 5-B: app/(dashboard)/layout.tsx の最外側 div に style={{ paddingLeft: env(safe-area-inset-left), paddingRight: env(safe-area-inset-right) }} 追加。縦持ち時の左右 safe area 確保

主な編集ファイル:
- components/layout/Header.tsx(AppVersionBadge + import 削除)
- app/(dashboard)/layout.tsx(最外側 div に safe-area-inset 左右)
- lib/changelog.ts(1件追記)/ CLAUDE.md(最新スタンプ)

バックアップ:
- 事前ラベル付き: 2026-05-25_163908_before-header-ver-removal.tar.gz
- post-deploy: 2026-05-25_154149_post-deploy.tar.gz(v1.234 確定)

本番URL確認: ✅ HTTP 200(home/ / version.json: v1.234 / ce-2026-05-25-28)

退化防止: ce-2026-05-25-27 (tabs scrollbar 可視化) / ce-2026-05-25-26 (main padding 明示) / ce-2026-05-25-25 / ce-2026-05-25-24 すべて無変更

** 学び(Vault 蓄積・「中途半端」の根本理解):
-
「中途半端」=「画面端に対する要素位置・余白の違和感」: ユーザーの「中途半端」発言は具体的な機能不全ではなく、視覚的な美意識の表現。表示が「画面内に綺麗に収まっている」ことを満たすには、左右 safe-area + 各要素の幅圧縮 + 画面端から要素まで一定 padding が必要
-
「機能と表示空間のトレードオフ」: ver 確認機能は重要だが Header の限られたスペースで詰め込むと崩れる → 別の場所(Sidebar)に分離が正解
-
「viewport-fit=cover を使う場合、safe-area-inset-top だけでなく left/right も対応」**: 縦持ちでも Dynamic Island の影響範囲は左右に少し及ぶ可能性

最新スタンプ:
- 最新changelog: ce-2026-05-25-28
- 最新baseline: 2026-05-25_154149_post-deploy.tar.gz
- 最新アプリver: v1.234


2026-05-25 15:30 更新(ce-2026-05-25-27 / app v1.232 → v1.233)【真因 4 段目・section tabs scrollbar 可視化】

実施内容(1リリース・スクロール可視化):
1. ce-2026-05-25-27 section tabs scrollbar 可視化 + Header verピル スマホ「✓」圧縮
- 大串FB「ダッシュボードタブで右にスクロール動かない・明らかに見切れてる」
- 真因 4-A: Header.tsx Mobile section tabs(作業報告/タスク管理/レポート/カレンダー/設定)が scrollbar-hide で隠れて「ここはスクロール可能」とユーザーが気付けなかった + 「設定」タブが画面外
- 真因 4-B: Header right block の AppVersionBadge ピル「✓最新」が画面右端からはみ出して見えていなかった
- 修正 4-A: nav の scrollbar-hide を撤去 → スクロールバー可視化。右スワイプで「設定」タブに到達可能と認識できる
- 修正 4-B: AppVersionBadge ピル padding を px-1.5 sm:px-2 に圧縮 + 「✓ 最新」テキストを <span className="sm:hidden">✓</span><span className="hidden sm:inline">✓ 最新</span> でスマホは「✓」のみに圧縮

主な編集ファイル:
- components/layout/Header.tsx(Mobile section tabs scrollbar-hide 撤去)
- components/layout/AppVersionBadge.tsx(ピル padding 圧縮 + スマホで「✓」のみ)
- lib/changelog.ts(1件追記)/ CLAUDE.md(最新スタンプ)

バックアップ:
- 事前ラベル付き: 2026-05-25_162502_before-tabs-scrollbar-visible.tar.gz
- post-deploy: 2026-05-25_152755_post-deploy.tar.gz(v1.233 確定)

本番URL確認: ✅ HTTP 200(home/ / version.json: v1.233 / ce-2026-05-25-27)

退化防止: ce-2026-05-25-26 (main padding 明示) / ce-2026-05-25-25 (main overflow-x-auto) / ce-2026-05-25-24 (Header ver スマホ短縮) すべて無変更

** 学び(Vault 蓄積・「右にスクロールできない」の真相):
-
「スクロールできない」とユーザーが言ったとき、CSS仕様で「不要だから動かない」と「機能してるけど見えないから気付けない」の 2 種類がある: 後者の解決は scrollbar 可視化や視覚ヒント
-
scrollbar-hide は注意して使う**: モバイルでは「ここはスクロール可能」を視覚的に伝える手段が無くなる。意図的に「画面いっぱい使うコンテナ」にだけ使うべき

最新スタンプ:
- 最新changelog: ce-2026-05-25-27
- 最新baseline: 2026-05-25_152755_post-deploy.tar.gz
- 最新アプリver: v1.233


2026-05-25 15:20 更新(ce-2026-05-25-26 / app v1.231 → v1.232)【最終理解・padding 明示化】

実施内容(1リリース・最終理解):
1. ce-2026-05-25-26 main padding 明示化(px-4 py-4 md:p-6)+ 「スクロールできない=正常動作」結論
- 大串 FB「ずっと右にスクロールできない」の最終理解
- 最終理解: ce-22 のタスク行 basis-full 化 + ce-23 ボタン縮小 + ce-25 main overflow-x-auto の累積で、現在のスマホ画面ではタスク行・カード類全てが画面内に収まっている。横スクロール対象がないため、右スワイプで動かないのは CSS 仕様上の正常動作
- ユーザー認識との差: 「右に隙間がない違和感」=「padding 不揃い」が真因。「スクロールできれば見える」ではなく「そもそも見えてるが余白が狭い」
- 修正: layout.tsx main の p-4 md:p-6px-4 py-4 md:p-6 に明示分離。左右 padding 16px を確実に確保
- overflow-y-auto overflow-x-auto は維持: 万一今後コンテンツがはみ出した場合に横スクロールできる保険

主な編集ファイル:
- app/(dashboard)/layout.tsx(main padding 明示化)
- lib/changelog.ts(1件追記)/ CLAUDE.md(最新スタンプ)

バックアップ:
- 事前ラベル付き: 2026-05-25_154147_before-main-padding-explicit.tar.gz
- post-deploy: 2026-05-25_151419_post-deploy.tar.gz(v1.232 確定)

本番URL確認: ✅ HTTP 200(home/ / version.json: v1.232 / ce-2026-05-25-26)

退化防止: ce-2026-05-25-25 / ce-2026-05-25-24 / ce-2026-05-25-23 / ce-2026-05-25-22 すべて無変更

** 学び(Vault 蓄積・スマホ修正 2時間半 の最終総括):
-
「ユーザーが『スクロールできない』と言う時、コンテンツが本当にはみ出してるか確認すべき: 「スクロールできない=故障」と思い込んで原因を探す前に、「スクロール対象が存在するか」を CSS 視点で先に確認する
-
「画面内に収まる + 横スクロール保険」が完璧な構成: コンテンツが収まる場合は静的、はみ出す場合は scroll に。両方カバー
-
ce-15 → ce-25 までの 7 リリースで、overflow と CSS 仕様の理解を更新: 個別 component 修正と global layout 修正を 両方** きちんとやることの重要性

最新スタンプ:
- 最新changelog: ce-2026-05-25-26
- 最新baseline: 2026-05-25_151419_post-deploy.tar.gz
- 最新アプリver: v1.232


2026-05-25 15:10 更新(ce-2026-05-25-25 / app v1.230 → v1.231)【真因 3 段目・横スクロール突破】

実施内容(1リリース・横スクロール許可の最終突破):
1. ce-2026-05-25-25 main overflow-x-auto 明示追加(親 overflow-hidden を main 自身で突破)
- 大串 FB「やっぱりずっと右にスクロールができない、右端までいけない」
- 真因(見落とした 3 段目): app/(dashboard)/layout.tsx の最外側 <div className="h-screen flex overflow-hidden bg-bg">overflow-hidden (両方向) があり、これが祖先として効いていた。ce-24 で main を overflow-y-auto (横はデフォルト visible) にしても、祖先の overflow-hidden で横方向が制限されていた
- 修正: main の className を flex-1 overflow-y-auto p-4 md:p-6flex-1 overflow-y-auto overflow-x-auto p-4 md:p-6 に変更。main 自身に overflow-x-auto を明示追加することで、main 内で横スクロールバーが反応する構造に
- 効果: スマホで右スワイプ → main 内の横スクロールバーが反応 → 切れた部分に到達可能。PC では横はみ出しが無ければスクロールバー出ない(デフォルト動作)
- 最外側 div の overflow-hidden は維持: h-screen の高さ管理 + Sidebar drawer slide アニメーションの動作領域として必要。main 側で個別に overflow-x-auto を明示する方が安全

主な編集ファイル:
- app/(dashboard)/layout.tsx(main に overflow-x-auto 追加)
- lib/changelog.ts(1件追記)/ CLAUDE.md(最新スタンプ)

バックアップ:
- 事前ラベル付き: 2026-05-25_152024_before-main-overflow-x-auto.tar.gz
- post-deploy: 2026-05-25_145244_post-deploy.tar.gz(v1.231 確定)

本番URL確認: ✅ HTTP 200(home/ / version.json: v1.231 / ce-2026-05-25-25)

退化防止: ce-2026-05-25-24 (main overflow-y-auto + Header ver スマホ短縮) / ce-2026-05-25-23 (3ボタン縮小+横スクロール保険) / ce-2026-05-25-22 (タスク行 basis-full 独立行) すべて無変更

** 学び(Vault 蓄積・overflow 3 段階の理解):
-
「親要素の overflow が子の overflow を制限する」 CSS 仕様: <parent overflow-hidden><child overflow-visible>...</child></parent> の場合、子の visible は祖先で制限される。子で overflow-auto を明示する必要
-
「main の overflow を撤回しただけでは祖先の overflow-hidden が効いて横スクロール禁止のまま」: 親階層を全部辿らないと「実際に horizontal scroll が許可されてるか」分からない
-
「横スクロールを許可したい階層自身に overflow-x-auto」を明示するのが安全**: 祖先に依存せず確実に動く

最新スタンプ:
- 最新changelog: ce-2026-05-25-25
- 最新baseline: 2026-05-25_145244_post-deploy.tar.gz
- 最新アプリver: v1.231


2026-05-25 15:00 更新(ce-2026-05-25-24 / app v1.229 → v1.230)【根本修正・main overflow + Header ver】

実施内容(1リリース・2 時間 FB の真因 2 つを根本修正):
1. ce-2026-05-25-24 main overflow-x-auto + Header ver スマホ短縮
- 大串 2 時間 FB「右にスクロールできない・画面詰まってて見づらい・根本から何か修正しないと治らなそう・見落としている原因とかあるよ」
- 真因 A (ce-15 の main overflow-x-hidden): 「右切れの根本対策」として入れたが、これがユーザー希望「ダメなら横スクロール」を物理的に妨害していた。スマホで右スワイプしても何も起きない元凶
- 真因 B (ce-18 の ver テキスト常時表示): 「ver 出てない」FB に対して常時表示にしたが、Header 右側ブロック合計幅(アバター 28 + verテキスト 35 + ピル 55 + gap = 130px)が画面端ピッタリ → 「v1.229 ✓」が切れる元凶
- 修正 A: main overflow-y-auto overflow-x-hiddenoverflow-y-auto のみ。横スクロールは browser に任せる
- 修正 B: AppVersionBadge に alwaysShowVersion prop 追加。Header は default (false) スマホ非表示・PC 表示、Sidebar は alwaysShowVersion={true} 常時表示
- スマホでの ver 確認方法: Sidebar 開く(ハンバーガーメニュー)→ 左下に「v1.230 ✓最新」常時表示

主な編集ファイル:
- app/(dashboard)/layout.tsx(main overflow-x-hidden 撤回)
- components/layout/AppVersionBadge.tsx(alwaysShowVersion prop 追加)
- components/layout/SystemSidebar.tsx(AppVersionBadge に alwaysShowVersion 渡し)
- lib/changelog.ts(1件追記)/ CLAUDE.md(最新スタンプ)

バックアップ:
- 事前ラベル付き: 2026-05-25_154351_before-overflow-auto-revert.tar.gz
- post-deploy: 2026-05-25_144733_post-deploy.tar.gz(v1.230 確定)

本番URL確認: ✅ HTTP 200(home/ / version.json: v1.230 / ce-2026-05-25-24)

退化防止: ce-2026-05-25-23 (3ボタン縮小+横スクロール保険) / ce-2026-05-25-22 (タスク行 basis-full 独立行) / ce-2026-05-25-21 / ce-2026-05-25-20 すべて無変更

** 学び(Vault 蓄積・スマホ修正 2 時間 のレッスン):
-
「右切れの根本対策」として入れた overflow-x-hidden 自体が「右スクロール禁止」の元凶になる罠: 個別 component で右切れする箇所を 1 つずつ修正する方が遠回りに見えて正解だった。親に overflow-x-hidden は入れない・各 component で min-w-0 / flex-wrap / 横スクロール対応する のがレスポンシブの正しいやり方
-
「機能要望と表示空間のトレードオフ」は分離して解決すべき: ver 確認したい (機能) ↔ Header 圧迫 (表示) → 2 つの場所に分けて解決(Header 簡素 + Sidebar 詳細)
-
「2 時間も付き合ってくれたユーザー」のために 1 個ずつ修正するな: ce-14 → -17 → -18 → -19 → -20 → -21 → -22 → -23 → -24 と修正を重ねた最終的な学び = 「最初の修正で根本を疑う」+「ユーザーの希望を矛盾なく満たす設計」が肝心**

最新スタンプ:
- 最新changelog: ce-2026-05-25-24
- 最新baseline: 2026-05-25_144733_post-deploy.tar.gz
- 最新アプリver: v1.230


2026-05-25 14:50 更新(ce-2026-05-25-23 / app v1.228 → v1.229)【3ボタン縮小 + 横スクロール保険】

実施内容(1リリース・4個目「完了」切れ根治):
1. ce-2026-05-25-23 3ボタン縮小 + 独立行に overflow-x-auto 保険
- 大串FB「○ 4個目(完了)が切れる」
- 真因: ce-22 で basis-full 独立行に追い出したが、4 ボタン(計測 36 + 未着手 32 + 進行中 32 + 完了 32 + gap)= 約 145-160px。一見収まるが、ボタン padding/border/実描画の差でギリギリ overflow し「完了」が切れる
- 修正1: 3ボタン縮小: min-w-[32px] px-1.5min-w-[28px] sm:min-w-[32px] px-1 sm:px-2.5 shrink-0。スマホは 28px x 3 = 84px に圧縮
- 修正2: 独立行 overflow-x-auto: ラッパー div に overflow-x-auto sm:overflow-visible 追加。万一はみ出しても右スワイプで完了に到達可能
- 修正3: 独立行 padding 調整: -mx-1 sm:mx-0 px-1 sm:px-0 でコンテンツ幅最大化

主な編集ファイル:
- components/tasks/work-log/ActiveBoard.tsx(3ボタン縮小 + ラッパー overflow-x-auto)
- lib/changelog.ts(1件追記)/ CLAUDE.md(最新スタンプ)

バックアップ:
- 事前ラベル付き: 2026-05-25_152849_before-btn-shrink-scroll.tar.gz
- post-deploy: 2026-05-25_143531_post-deploy.tar.gz(v1.229 確定)

本番URL確認: ✅ HTTP 200(home/ / version.json: v1.229 / ce-2026-05-25-23)

退化防止: ce-2026-05-25-22 (タスク行 basis-full 独立行) / ce-2026-05-25-21 / ce-2026-05-25-20 / ce-2026-05-25-19 すべて無変更

** 学び(Vault 蓄積):
-
「計算上収まる」と「実際に収まる」は別: CSS padding/border/サブピクセル描画の差で 数 px ずれる。安全マージン + 横スクロール保険 の二重対策が確実
-
overflow-x-auto sm:overflow-visible** は「スマホはスクロール可能、PC は通常表示」を両立する黄金パターン。ユーザーの「ダメなら横スクロール」希望を満たす

最新スタンプ:
- 最新changelog: ce-2026-05-25-23
- 最新baseline: 2026-05-25_143531_post-deploy.tar.gz
- 最新アプリver: v1.229


2026-05-25 14:40 更新(ce-2026-05-25-22 / app v1.227 → v1.228)【タスク行スマホ完全縦並び化・右padding 復活】

実施内容(1リリース・カード右余白 復活根治):
1. ce-2026-05-25-22 タスク行スマホ完全縦並び化 + タスク追加エリア wrap
- 大串FB「左側はブロックとスマホ横に隙間ちょっと空いていて、右側も同じようにして欲しいのにブロックが全部表示されてないし隙間もない」
- 真因: タスク行 li 内の合計要素幅(ドラッグ16 + 丸トグル44 + flex-1タスク名 + 計測36 + 3ボタン108 + 昇格50 + 削除14 + gap)= 約 300px がスマホ内側幅 279px 超え → main の overflow-x-hidden で隠れた分カード右側 padding が食われ画面端まで広がる現象
- 修正1: 計測+3ボタン+昇格+削除を 1 ラッパー div でくくり basis-full sm:basis-auto強制的に独立行(全幅・右寄せ)。PC は basis-auto で従来通り横並び
- 修正2: タスク追加エリア: input + 「タスク追加」ボタンも横並びで overflow → flex-wrap + input: w-full sm:flex-1button: w-full sm:w-auto でスマホ縦並び、PC 横並び。placeholder も短縮
- 修正3: li 自体に max-w-full overflow-hidden 保険
- 修正4: 削除ボタンはスマホで hover ないので opacity-60 sm:opacity-0 sm:group-hover:opacity-100 で常時 60% 表示

スマホでのタスク行レイアウト(v1.228):
- 1行目: 「[ドラッグ] [○丸トグル] LinkedInシステム 想定 2時間 残 8分(86%)」(flex-1 全幅利用 → タスク名改行しない)
- 2行目: 「 [▷計測] [○][○][✓] [削除]」(右寄せ・独立行)

主な編集ファイル:
- components/tasks/work-log/ActiveBoard.tsx(li 内ボタン群を 1 ラッパー basis-full + タスク追加エリア wrap)
- lib/changelog.ts(1件追記)/ CLAUDE.md(最新スタンプ)

バックアップ:
- 事前ラベル付き: 2026-05-25_145153_before-task-row-stacked.tar.gz
- post-deploy: 2026-05-25_142803_post-deploy.tar.gz(v1.228 確定)

本番URL確認: ✅ HTTP 200(home/ / tasks/work-log/active/ / version.json: v1.228 / ce-2026-05-25-22)

退化防止: ce-2026-05-25-21 (3ボタン+凡例アイコン化) / ce-2026-05-25-20 (3ボタンスマホ表示) / ce-2026-05-25-19 (タスク行 flex-wrap) すべて無変更

** 学び(Vault 蓄積・スマホ完全マスター):
-
「カード右側 padding が消える」現象は「内側コンテンツの右はみ出しが main の overflow-x-hidden で隠れる時に padding まで食われる」: 個別 component の小手先修正では治らず、ボタン群を basis-full で独立行に追い出す根本構造変更が必要
-
flex-wrap だけでは「子要素が縮まない場合は overflow したまま」: basis-full sm:basis-auto で「スマホでは必ず別行」を明示的に指定するのが確実
-
「左右の余白を揃える」要望は「コンテンツが画面幅内に完全に収まる」と同義**: 1px でも overflow すると右 padding が消える

最新スタンプ:
- 最新changelog: ce-2026-05-25-22
- 最新baseline: 2026-05-25_142803_post-deploy.tar.gz
- 最新アプリver: v1.228


2026-05-25 14:30 更新(ce-2026-05-25-21 / app v1.226 → v1.227)【ステータス3ボタン+凡例 スマホアイコンのみ化】

実施内容(1リリース・見栄え改善):
1. ce-2026-05-25-21 ステータス3ボタン+凡例をスマホでアイコンのみ化
- 大串 FB:「完了とか計測押せるようになったけど見栄え悪い / 文字小さくしてOK / 全画面にきれいに収まるように」
- 真因: ce-2026-05-25-20 で hidden md:flex 撤回して 3ボタン表示したが、「未着手/進行中/完了」のテキスト分の幅がスマホ画面幅を超え「完」で右切れていた
- 修正1: 3ボタン: 各テキストを <span className="hidden sm:inline"> でスマホ非表示・アイコンのみ表示。padding 縮小 (px-1.5 sm:px-2.5) + min-w-[32px] でタップターゲット確保 + aria-label でアクセシビリティ維持
- 修正2: 凡例: 「[○]未着手 [○]進行中 [✓]完了」テキストもスマホ非表示
- スマホレイアウト: 「[○丸トグル] タスク名 想定/実測/残バッジ」(1行目) → 「[▷36x36 計測] [○][○][✓] 3ボタン」(2行目・全て画面内)。3ボタン 32x3=~100px + 計測 36px + gap 16px = ~150px < スマホ画面幅 343px

主な編集ファイル:
- components/tasks/work-log/ActiveBoard.tsx(3ボタン + 凡例 hidden sm:inline + padding 縮小)
- lib/changelog.ts(1件追記)/ CLAUDE.md(最新スタンプ)

バックアップ:
- 事前ラベル付き: 2026-05-25_141416_before-status-icon-only.tar.gz
- post-deploy: 2026-05-25_141816_post-deploy.tar.gz(v1.227 確定)

本番URL確認: ✅ HTTP 200(home/ / tasks/work-log/active/ / version.json: v1.227 / ce-2026-05-25-21)

退化防止: ce-2026-05-25-20 (3ボタンスマホ表示) / ce-2026-05-25-19 (タスク行 flex-wrap) / ce-2026-05-25-18 / ce-2026-05-25-17 すべて無変更

** 学び(Vault 蓄積):
-
「表示する」と「見栄え良く表示する」は別問題: ce-20 で表示はしたが「見栄え悪い」FB → アイコンのみで省幅化が次のステップ。「機能性確保 → 見栄え最適化」の 2 段階で進めるのが堅実
-
hidden sm:inline でテキスト省略 + アイコン残し + aria-label でアクセシビリティ維持** は、レスポンシブで「機能 + 見栄え + a11y」を両立する黄金パターン

最新スタンプ:
- 最新changelog: ce-2026-05-25-21
- 最新baseline: 2026-05-25_141816_post-deploy.tar.gz
- 最新アプリver: v1.227


2026-05-25 14:20 更新(ce-2026-05-25-20 / app v1.225 → v1.226)【スマホでも 完了/進行中/未着手 ボタン表示】

実施内容(1リリース・UX 機能性回復):
1. ce-2026-05-25-20 ステータス3ボタンセット「未着手/進行中/完了」をスマホで表示
- 大串 FB:「完了ボタンまでたどり着けない / 押せないではなく、そこにたどり着けないって感じ / 全部押すことはできる(見えるところは)」
- 真因: ce-2026-05-25-05 で「ActiveBoard ステータス3ボタンセットが右切れの原因」として hidden md:flex でスマホ非表示にした → 代替の cycleStatus 丸トグルが「循環式」のため、未着手 → 進行中 → 完了 までタップ 2 回必要 + ユーザーが「完了ボタン」を期待していると到達できない
- 修正: ActiveBoard 1348行 <div className="shrink-0 hidden md:flex"><div className="shrink-0 flex">。スマホでも 3ボタン表示。ce-19 の flex-wrap で次行に折り返されるので画面内に収まる
- スマホレイアウト: 「[○丸トグル] タスク名 想定/実測/残バッジ」(1行目) → 「[▷36x36 計測] [未着手 / 進行中 / 完了 3ボタン]」(2行目に折り返し)
- UX 改善: 「完了」をワンタップで指定可能(循環式の不便さ解消)+ 全機能スマホでアクセス可能

主な編集ファイル:
- components/tasks/work-log/ActiveBoard.tsx(1348行 hidden md:flex 撤回)
- lib/changelog.ts(1件追記)/ CLAUDE.md(最新スタンプ)

バックアップ:
- 事前ラベル付き: 2026-05-25_140639_before-status-3btn-mobile.tar.gz
- post-deploy: 2026-05-25_140947_post-deploy.tar.gz(v1.226 確定)

本番URL確認: ✅ HTTP 200(home/ / tasks/work-log/active/ / version.json: v1.226 / ce-2026-05-25-20)

退化防止: ce-2026-05-25-19 (タスク行 flex-wrap) / ce-2026-05-25-18 (ver表示+フローティング被り) / ce-2026-05-25-17 / ce-2026-05-25-15 (overflow-x-hidden) すべて無変更

** 学び(Vault 蓄積):
-
「見切れ」対策で UI を hidden にする前に「代替手段が機能的に同等か」を確認すべき: ce-05 で「循環式の丸トグルがあるからスマホでは 3 ボタン非表示でOK」と判断したが、実際は「ユーザーは『完了』を直接指定したい」と思っていた → 機能を奪うのは UX 悪化
-
「押せない」と「たどり着けない」は別の問題**: ユーザーが「押せない」と言ったら「画面外に出てる or タッチ範囲が狭い」を疑い、「たどり着けない」と言ったら「そもそも表示されてない or 表示はあるが操作できる場所が遠い」を疑う

最新スタンプ:
- 最新changelog: ce-2026-05-25-20
- 最新baseline: 2026-05-25_140947_post-deploy.tar.gz
- 最新アプリver: v1.226


2026-05-25 14:10 更新(ce-2026-05-25-19 / app v1.224 → v1.225)【タスク行 flex-wrap で計測ボタン押せる】

実施内容(1リリース・タスク行計測ボタン右切れ根治):
1. ce-2026-05-25-19 今日やるタスク行を flex-wrap で計測ボタン折り返し対応
- 大串 FB:「今日やるタスクで計測とか完了とかにしたいのに右にいけないから押せない / 全画面に極力収めて欲しいけど、無理ならスクロールして横にいけるように」
- 真因: ActiveBoard 1214行 li の flex items-center gap-2 で flex-nowrap デフォルト → スマホでタスク名+バッジ群+計測ボタンが横並びで合計幅オーバーするが wrap せず、計測ボタンが画面外に押し出されて押せない。ce-15 で main に overflow-x-hidden を入れたので、はみ出た部分は完全に見えなくなっていた
- 修正: 1214行を flex flex-wrap sm:flex-nowrap items-center gap-2 に変更。スマホは wrap 可能、PC は従来通り 1行レイアウト維持。計測ボタン(shrink-0)は wrap で次行に下がる
- 副次修正: アコーディオン「マイタスク 14件 / 「+ 追加」でセッションに含められます」「定例タスク 2件 / 同左」の説明文を hidden sm:inline でスマホ非表示(冗長・「+ 追加」ボタン自体は各行に出るので)
- スマホレイアウト: 「[○丸トグル] タスク名 想定/実測/残バッジ」(1行目) → 「[▷計測36x36]」(2行目・必要な場合のみ wrap)。余裕があれば 1 行内に収まる

主な編集ファイル:
- components/tasks/work-log/ActiveBoard.tsx(li 1214行 flex-wrap + アコーディオン説明文 hidden sm:inline)
- lib/changelog.ts(1件追記)/ CLAUDE.md(最新スタンプ)

バックアップ:
- 事前ラベル付き: 2026-05-25_135924_before-task-row-wrap.tar.gz
- post-deploy: 2026-05-25_140338_post-deploy.tar.gz(v1.225 確定)

本番URL確認: ✅ HTTP 200(home/ / tasks/work-log/active/ / version.json: v1.225 / ce-2026-05-25-19)

退化防止: ce-2026-05-25-18 (ver表示+フローティング被り) / ce-2026-05-25-17 (Timer 右側完全別実装) / ce-2026-05-25-15 (overflow-x-hidden) すべて無変更

** 学び(Vault 蓄積):
-
「タップできない」は「画面外で押せない」の症状の一つ: overflow-x-hidden を入れた後、「右にいきたいけど行けない」FB は「要素が wrap してない」を疑う
-
flex-nowrap がデフォルトという罠**: flex items-center だけ書いた要素は wrap しない。複数子要素を持つ row 構造は最初から flex-wrap sm:flex-nowrap が defensive

最新スタンプ:
- 最新changelog: ce-2026-05-25-19
- 最新baseline: 2026-05-25_140338_post-deploy.tar.gz
- 最新アプリver: v1.225


2026-05-25 14:00 更新(ce-2026-05-25-18 / app v1.223 → v1.224)【ver表示+フローティング被り根治】

実施内容(1リリース・2問題根治):
1. ce-2026-05-25-18 ver番号スマホ常時表示 + フローティング被り対策
- 大串スクショ FB:「そもそもスマホverでver出てないのと、まだ見切れてる」
- 真因 (A) ver番号スマホ非表示: ce-2026-05-25-05 で「Header上部混雑解消」のため hidden md:inline で sm 未満非表示にしたが、ver 確認の機能性を犠牲にしていた
- 修正 (A): AppVersionBadge の <span className="font-mono hidden md:inline"><span className="font-mono text-[9px] sm:text-xs leading-none"> に変更。スマホは text-[9px] でコンパクト、PC は text-xs。Header 右上 + Sidebar 左下の両方で ver 番号常時表示
- 真因 (B) フローティング被り: ActiveBoard のフローティング「[II 作業停止][作業終了する]」が fixed bottom z-40 で固定表示 → メインコンテンツ最下部のカード(経過時間/残タスクの想定合計/現ペースで完了まで等)を覆い隠していた
- 修正 (B): work-log/page.tsx と ActiveBoard.tsx の各最下部に <div className="h-24 sm:h-16" /> 余白追加 → フローティングが被ってもコンテンツが見える

主な編集ファイル:
- components/layout/AppVersionBadge.tsx(hidden md:inline 撤廃)
- app/(dashboard)/tasks/work-log/page.tsx(isRunning 時のみ最下部 h-24 余白追加)
- components/tasks/work-log/ActiveBoard.tsx(最下部 h-24 sm:h-16 余白追加)
- lib/changelog.ts(1件追記)/ CLAUDE.md(最新スタンプ)

バックアップ:
- 事前ラベル付き: 2026-05-25_134908_before-ver-and-floating.tar.gz
- post-deploy: 2026-05-25_135338_post-deploy.tar.gz(v1.224 確定)

本番URL確認: ✅ HTTP 200(home/ / tasks/work-log/ / version.json: v1.224 / ce-2026-05-25-18)

退化防止: ce-2026-05-25-17 (Timer 右側完全別実装) / ce-2026-05-25-16 / ce-2026-05-25-15 (overflow-x-hidden) / ce-2026-05-25-14 すべて無変更

** 学び(Vault 蓄積):
-
「Header 上部混雑対策」と「ver確認の機能性」はトレードオフではない: 文字サイズを縮めれば両立可能。一度「hidden で隠す」と決めても、後でユーザーが機能を使えなくなる FB が来る → 機能性優先で常時表示が正解
-
固定フローティングは必ずメインコンテンツ最下部余白とセットで配置: fixed bottom の要素は親のスクロール内に居ないので、メインコンテンツの末尾に余白カードを置かないと、ユーザーがスクロールしても見える範囲がフローティングに食われる
-
「見切れ」の真因は「画面外に出てる」だけじゃない**: 「フローティングの裏に隠れてる」も「見切れ」のうち。スクショで「下のカードが見えない」 = フローティング被り の可能性を常に疑う

最新スタンプ:
- 最新changelog: ce-2026-05-25-18
- 最新baseline: 2026-05-25_135338_post-deploy.tar.gz
- 最新アプリver: v1.224


2026-05-25 13:50 更新(ce-2026-05-25-17 / app v1.222 → v1.223)【Timer Card 右側スマホ完全別実装】

実施内容(1リリース・責任分離方式で根治):
1. ce-2026-05-25-17 Timer Card 右側スマホ完全別実装
- 真因(ce-16 で見落とした最後の壁): ce-16 で flex-col 縦並びは実現したが、右ブロック内側を flex items-baseline gap-2 で横並びにした際、flex のデフォルト flex-wrap: nowrap のため内側 span 群が 1 行強制 + whitespace-nowrap で改行不可 → 画面幅を超えて overflow した
- 修正: スマホ用 (sm:hidden) と PC 用 (hidden sm:block) を完全別 element として実装する責任分離パターン。各々独立した HTML 要素なので互いの CSS が干渉しない
- スマホ表示: <p className="sm:hidden text-xs text-text2 truncate">今日 3時間27分 / 宣言 4時間30分</p> の 1 行のみ + truncate で念のため右切れ保護
- PC 表示: 従来通り <div className="hidden sm:block text-right shrink-0 whitespace-nowrap"> で 3 行縦並び(本日の稼働 / 3時間27分 / 朝日報宣言 4時間30分)

主な編集ファイル:
- app/(dashboard)/tasks/work-log/page.tsx(Timer Card 右側を sm:hidden / hidden sm:block で完全分離)
- lib/changelog.ts(1件追記)/ CLAUDE.md(最新スタンプ)

バックアップ:
- 事前ラベル付き: 2026-05-25_134306_before-timer-mobile-only.tar.gz
- post-deploy: 2026-05-25_134531_post-deploy.tar.gz(v1.223 確定)

本番URL確認: ✅ HTTP 200(home/ / tasks/work-log/ / version.json: v1.223 / ce-2026-05-25-17)

退化防止: ce-2026-05-25-16 / ce-2026-05-25-15 (overflow-x-hidden + 全Card) / ce-2026-05-25-14 (見切れ網羅) / ce-2026-05-25-13 (報告できない根治) すべて無変更

** 学び(Vault 蓄積・スマホ右切れ完全マスター):
-
「スマホ専用 UI と PC 専用 UI を完全分離する責任分離パターン」が、レスポンシブで唯一確実に動く: 共通の HTML を responsive class で出し分けると、片方に最適化した時もう片方が壊れる。sm:hidden / hidden sm:block で完全別 element にすれば干渉ゼロ
-
flex のデフォルト flex-wrap: nowrap は罠: flex を書いたら自動的に flex-wrap を考えないと、内側要素が 1 行強制で overflow する
-
5 段階の見切れ修正(ce-14 → -15 → -16 → -17)から学んだこと: 「flex-wrap だけで OK」「flex-col で wrap 確実」「flex items-baseline gap-2 で横並び圧縮」全部、内側要素がさらに wrap できる構造でないと意味がない。最終的には「sm:hidden / hidden sm:block で完全分離」が正解**

最新スタンプ:
- 最新changelog: ce-2026-05-25-17
- 最新baseline: 2026-05-25_134531_post-deploy.tar.gz
- 最新アプリver: v1.223


2026-05-25 13:40 更新(ce-2026-05-25-16 / app v1.221 → v1.222)【Timer Card 右切れ最終根治】

実施内容(1リリース・Timer Card 右切れ根治):
1. ce-2026-05-25-16 Timer Card ヘッダー右側「本日の稼働/宣言」を完全縦並び化
- 真因(ce-15 で見落とした): flex-wrap は子要素が wrap 可能なときに 1 行に収まらない子を次行に押し出す機能。しかし flex-1 の左ブロックが残り幅を全部取り、右の shrink-0 ブロックが縮まないため、右が次行に行かず親の幅を超えて overflow した
- 修正: 親の flex items-centerflex flex-col sm:flex-row sm:items-center で、スマホは完全縦並び
- スマホ表示形式: 「大串 / 2026年5月25日 月曜日 13:32」(1行目) → 「本日の稼働 3時間27分 / 宣言 4時間30分」(2行目で横並び圧縮)
- PC 表示形式: 従来通りの横並び(左右)+ 右側内部は縦並び(sm:block sm:text-right)
- 物理的に右切れ発生しない構造

主な編集ファイル:
- app/(dashboard)/tasks/work-log/page.tsx(Timer Card ヘッダー右側を flex-col sm:flex-row 化)
- lib/changelog.ts(1件追記)/ CLAUDE.md(最新スタンプ)

バックアップ:
- 事前ラベル付き: 2026-05-25_133428_before-timer-header-vertical.tar.gz
- post-deploy: 2026-05-25_133639_post-deploy.tar.gz(v1.222 確定)

本番URL確認: ✅ HTTP 200(home/ / tasks/work-log/ / version.json: v1.222 / ce-2026-05-25-16)

退化防止: ce-2026-05-25-15 (overflow-x-hidden + Timer Card 全要素 + 進捗ペース全体) / ce-2026-05-25-14 / ce-2026-05-25-13 すべて無変更

** 学び(Vault 蓄積):
-
flex-wrap だけでは右側を次行に追い出せない」根本理解: 左が flex-1 で残り幅を全部取ると、右の shrink-0 ブロックは縮まないし wrap もしない → 親の幅を超えて overflow する。スマホで強制縦並びにするなら flex-col sm:flex-row を直接指定するのが唯一の確実解
-
ce-15 で対応漏れた本質: 「flex-wrap + min-w-0 + whitespace-nowrap」の組み合わせは「テキストが短い場合」には wrap で対応できるが、「右側ブロックが固定的に幅を必要とする場合」は wrap してくれない。flex-row → flex-col の構造変更が必要**

最新スタンプ:
- 最新changelog: ce-2026-05-25-16
- 最新baseline: 2026-05-25_133639_post-deploy.tar.gz
- 最新アプリver: v1.222


2026-05-25 13:30 更新(ce-2026-05-25-15 / app v1.220 → v1.221)【スマホ見切れ完全版】

実施内容(1リリース・スマホ右切れ 7箇所根治 + 根本対策):
1. ce-2026-05-25-15 スマホ右切れ網羅【完全版】
- 大串再 FB:「まだこんな感じ・原因追求が甘い・一回で全部やりきって」
- 根本対策: app/(dashboard)/layout.tsx の main に overflow-x-hidden 追加。個別コンポーネントの flex-wrap/min-w-0 漏れがあっても画面右にスクロールしなくなる。今後の退化も防げる
- ①Timer Card padding: p-6 md:p-8p-4 sm:p-6 md:p-8。スマホで内側コンテンツに 32px 余裕
- ②Timer Card ヘッダー「本日の稼働/朝日報宣言」: text-right shrink-0 で右はみ出し → flex-wrap + whitespace-nowrap + 「朝日報」を sm 未満で省略 + フォント縮小(text-base sm:text-xl)+ label を sm 未満で text-[9px]
- ③Timer Card 進捗バー上「セッション宣言 X時間 に対して Y分 (Z%)」: max-w-md mx-auto で横幅制約 → max-w-full md:max-w-md + flex を sm 未満で縦並び(左ラベルと右数値が縦に並ぶ)
- ④ActiveBoard 進捗ペースピル: ce-14 でも切れていた → スマホで h3 と ピル を完全縦並び(flex-col sm:flex-row + self-start sm:self-auto)+ max-w-full truncate
- ⑤ActiveBoard 進捗バー上「完了 X / 進行中 Y / 想定合計 Z (W%)」: スマホ縦並び + 「完了」ラベルを sm 未満で省略 + 「進行中」表記を md 以上のみ + 「想定」を「合計」に短縮
- ⑥work-log/page.tsx 見出し説明文: 57文字 → スマホは 17文字「ボタンで日報・作業時間を自動生成」/ PC は full text

主な編集ファイル:
- app/(dashboard)/layout.tsx(main に overflow-x-hidden 追加 ← 根本対策)
- app/(dashboard)/tasks/work-log/page.tsx(Timer Card 全要素 + 見出し説明文)
- components/tasks/work-log/ActiveBoard.tsx(進捗ペースピル + 進捗バー上数値)
- lib/changelog.ts(1件追記)/ CLAUDE.md(最新スタンプ)

バックアップ:
- 事前ラベル付き: 2026-05-25_132321_before-mobile-overflow-v2.tar.gz
- post-deploy: 2026-05-25_132950_post-deploy.tar.gz(v1.221 確定)

本番URL確認: ✅ HTTP 200(home/ / tasks/work-log/ / version.json: v1.221 / ce-2026-05-25-15)

退化防止: ce-2026-05-25-14 (スマホ右切れ第一弾) / ce-2026-05-25-13 (報告できない根治) / ce-2026-05-25-12 (完璧化監査) / ce-2026-05-25-11 / ce-2026-05-25-10 / ce-2026-05-25-09 / ce-2026-05-25-08 / ce-2026-05-25-07 / ce-2026-05-25-06 すべて無変更

** 学び(Vault 蓄積):
-
「右切れ」修正は個別 component 対応では完璧にならない: overflow-x-hidden を root container に入れる「保険的根本対策」+ 個別 responsive で完成形。今後の退化も防げる
-
「原因追求が甘い」FB を受けた後の正しい対応: スクショから全要素を洗い出す。1要素見つけたら、その周辺の全要素も同じパターンで見切れる可能性をチェック。今回は Timer Card 1 箇所修正したつもりが、その上の「本日の稼働」「進捗バー上」「ボタン」全部漏れていた
-
flex-wrap だけでは縦並びにならない理由: 内側の span が whitespace-nowrap 等で一行になると、その span 自体が幅オーバー → wrap した結果も右端から切れる。スマホでは flex-col sm:flex-row明示的に縦並び指定**するのが確実

最新スタンプ:
- 最新changelog: ce-2026-05-25-15
- 最新baseline: 2026-05-25_132950_post-deploy.tar.gz
- 最新アプリver: v1.221


2026-05-25 13:10 更新(ce-2026-05-25-14 / app v1.219 → v1.220)【スマホ見切れ網羅】

実施内容(1リリース・スマホ右側見切れ 5箇所根治):
1. ce-2026-05-25-14 スマホ右側見切れ網羅対応
- 大串スクショ FB:「右側見切れているのは治ってない / きれいに全画面見れるようにして欲しい」
- A. work-log/page.tsx Timer Card「作業停止」ボタン: 「作業停止(外出・別件など)」の長文がスマホ画面幅で切れ → 補足を hidden sm:inline で sm 未満非表示 + padding 縮小 (px-4 sm:px-6 / py-2.5 sm:py-3)
- B. ActiveBoard 進捗ペースピル: 「まだ完了タスクなし (X.XXx)」がスマホで切れ → スマホは絵文字+倍率の短縮表記「🚀 1.20x」/ PC は full text。whitespace-nowrap でピル内テキスト折り返し抑止 + flex 親に min-w-0
- C. ActiveBoard 凡例 3 カード(計測/進行中/完了): grid grid-cols-3 固定で各カードが圧縮 → スマホ(md 未満)では hidden md:block で非表示。直上の凡例(未着手/進行中/完了 アイコン)でカバー
- D. ActiveBoard タスク行「計測」ボタン: [▷ 計測] テキスト + shrink-0 で右切れ → スマホはアイコンのみ + 36x36 ヒットエリア / PC はテキスト付き。<span className="hidden sm:inline"> でラベル切替
- E. ActiveBoard Header カード(embedded=false / /tasks/work-log/active 表示): 経過時間 + 作業停止ボタン横並びで右切れ → overflow-hidden + min-w-0 + flex-wrap + shrink-0 + ボタン padding sm 未満で縮小 + timer フォント sm 未満で text-2xl

主な編集ファイル:
- app/(dashboard)/tasks/work-log/page.tsx(Timer Card 作業停止ボタン)
- components/tasks/work-log/ActiveBoard.tsx(Header カード + 進捗ペースピル + 凡例 + 計測ボタン)
- lib/changelog.ts(1件追記)/ CLAUDE.md(最新スタンプ)

バックアップ:
- 事前ラベル付き: 2026-05-25_130534_before-mobile-overflow-fix.tar.gz
- post-deploy: 2026-05-25_131933_post-deploy.tar.gz(v1.220 確定)

本番URL確認: ✅ HTTP 200(home/ / tasks/work-log/ / active/ / version.json: v1.220 / ce-2026-05-25-14)

退化防止: ce-2026-05-25-13 (報告できない根治) / ce-2026-05-25-12 (完璧化監査) / ce-2026-05-25-11 (end runningId 取得修正) / ce-2026-05-25-10 (debounce + dual session + admin role) / ce-2026-05-25-09 / ce-2026-05-25-08 / ce-2026-05-25-07 / ce-2026-05-25-06 すべて無変更

** 学び(Vault 蓄積):
-
「右側見切れ」の真因は 5 箇所に分散: 単純に flex-wrap だけでは解決しない。①ボタンテキスト長 ②ピルテキスト長 ③grid 列数 ④アイコン+テキスト並び ⑤親 div の overflow の5層を全部チェック
-
スマホでは「テキストを隠してアイコンのみ」「補足説明を hidden sm:inline」「複雑グリッドを md:hidden で隠す」がパターン化された解
-
overflow-hidden + min-w-0 + flex-wrap + shrink-0 の組み合わせ**を、コンテナ + 各 flex 親 + 各 flex 子の3層に適切に配置するのが Tailwind responsive の核

最新スタンプ:
- 最新changelog: ce-2026-05-25-14
- 最新baseline: 2026-05-25_131933_post-deploy.tar.gz
- 最新アプリver: v1.220


2026-05-25 17:30 更新(ce-2026-05-25-13 / app v1.218 → v1.219)【再致命fix】

実施内容(1リリース・「報告できない」の真因根治):
1. ce-2026-05-25-13 ce-11 の修正は副作用根治のみで、真因は別だった
- メンバー再報告:「PCverで報告のシステム治ってない」
- ①真因(最重要): end/page.tsx 641行 disabled={!running || !blockers.trim() || satisfaction < 1} で blockers(報告/連絡/相談)と satisfaction(満足度 1-5)が両方とも必須。多くの作業では blockers は「特になし」、satisfaction は未選択(初期値 0)→ ボタンが薄く押せない → ユーザーから見ると「報告できない」
- ①修正: disabled 条件を !running のみに緩和。handleSave 内で safeBlockers(空なら「(特になし)」)+ safeSatisfaction(0 なら 3)のデフォルト値で送信。Slack 通知も safeBlockers が「(特になし)」の時は省略
- ②保険: handleSave 全体 try/catch: postReport や addReport / saveSessions の途中で例外 throw されると router.push に到達せず「ボタン押したけど画面遷移しない」状態 → 全体 try/catch で alert + console.error 表示
- ③保険: ActiveBoard endSession の saveSessions に opts (userId) 渡し: 旧実装は localStorage のみで KV PUT 漏れ → 別端末から見ると session.endedAt=null のまま → dual session 警告誤検出の可能性。2 箇所(isPaused 時の最終 pause 閉じと session.endedAt セット)で修正
- ④UI 文言修正: 「満足度の選択は必須です(1〜5)」赤字を「未選択時は 3 として送信されます」推奨文言に変更

主な編集ファイル:
- app/(dashboard)/tasks/work-log/end/page.tsx(disabled 緩和 + handleSave try/catch + safeBlockers/safeSatisfaction)
- components/tasks/work-log/ActiveBoard.tsx(endSession の saveSessions に opts.userId 渡し 2 箇所)
- lib/changelog.ts(1件追記)/ CLAUDE.md(最新スタンプ)

バックアップ:
- 事前ラベル付き: 2026-05-25_122415_before-end-report-rescue.tar.gz
- post-deploy: 2026-05-25_123213_post-deploy.tar.gz(v1.219 確定)

本番URL確認: ✅ HTTP 200(home/ / tasks/work-log/end/ / version.json: v1.219 / ce-2026-05-25-13)

退化防止: ce-2026-05-25-12 (完璧化監査) / ce-2026-05-25-11 (end runningId 取得修正) / ce-2026-05-25-10 (debounce + dual session + admin role) / ce-2026-05-25-09 (markLocalWrite + shouldSkipKVPull) / ce-2026-05-25-08 (draft 復元競合根治 + currentSessionId derive) / ce-2026-05-25-07 / ce-2026-05-25-06 すべて無変更

** 学び(Vault 蓄積):
-
「報告できない」を if (!running) return; のような handleSave 内部だけで考えてはいけないdisabled={...} の UI 制約も「ユーザー視点では『報告できない』の真因」になる。UI と関数ロジックの両方を洗うべき
-
必須バリデーションは UX 上のトラップ: 業務システムでは「ほとんどの場合空欄で OK」のフィールドを必須にすると、ユーザーは「何を入れたら良いか分からず固まる」。デフォルト値で送信 + 推奨表示が正解
-
2 段階の真因**: ce-11 で handleSave 内の早期 return は確かに修正したが、その手前の UI で disabled だった → 「修正対象が複数の層にまたがる」場合は両方確認すべき

最新スタンプ:
- 最新changelog: ce-2026-05-25-13
- 最新baseline: 2026-05-25_123213_post-deploy.tar.gz
- 最新アプリver: v1.219


2026-05-25 17:00 更新(ce-2026-05-25-12 / app v1.217 → v1.218)【完璧化監査】

実施内容(1リリース・徹底洗い出し対応 4 点):
1. ce-2026-05-25-12 完璧化監査: 残・想定問題の 4 点を 1 リリース投入
- ①SystemSidebar 2モードに safe-area-inset-top: collapsed (PC 縮小・iPad PWA で表示) と drawer/expanded (スマホ drawer・iPhone PWA で表示) の両方の fixed top-0 コンテナに paddingTop: env(safe-area-inset-top) 追加。PWA standalone でロゴ・閉じるボタンがステータスバー領域に被るのを防ぐ
- ②SectionSidebar に safe-area-inset-top: hidden md:flex でスマホ非表示だが、iPad PWA で表示時にステータスバー被るので念のため対応
- ③history ページの member ロール時データ制限: admin/manager のみ loadAllReportsFromKV / loadAllSessionsFromKV で全員データ取得、member は loadReportsFromKVByUser / loadSessionsFromKVByUser で自分の userId 分のみ取得。member 端末の localStorage に他人データが書かれないプライバシー強化
- ④updateUserState の currentSessionId 引数を無視: ce-2026-05-25-08 で getUserState 内で sessions から derive 化したため、KEY_STATE に書いても上書きされて無視される。start/end ページから後方互換で渡される currentSessionId は no-op として明示的に除外(混乱防止)

完璧化監査で確認した「実害なし」項目(修正不要と判定):
- KEY_STATE.morningReportDone は myReports.some で reports から判定するので非同期で問題なし
- saveActiveProgressMap は setActiveProgress 経由のみで markLocalWrite が二重防御
- 30秒ポーリング + focus pull の同時実行は両方とも shouldSkipKVPull で gate
- WorkLogProvider のメモリリーク無し(cleanup で全 listener remove)
- オフライン挙動は fire-and-forget + localStorage で動作継続
- 複数進行中セッション (dual session) は ce-2026-05-25-10 の警告 UI で対応済み
- KV pull 上書きは ce-2026-05-25-09 の markLocalWrite で対応済み
- KV PUT 帯域は ce-2026-05-25-10 の debounce で対応済み

主な編集ファイル:
- components/layout/SystemSidebar.tsx(2 モードに safe-area-inset-top)
- components/layout/SectionSidebar.tsx(safe-area-inset-top)
- app/(dashboard)/tasks/work-log/history/page.tsx(member 時は user 別 KV pull)
- lib/work-log.ts(updateUserState で currentSessionId 引数除外)
- lib/changelog.ts(1件追記)/ CLAUDE.md(最新スタンプ)

バックアップ:
- 事前ラベル付き: 2026-05-25_113936_before-perfection-audit.tar.gz
- post-deploy: 2026-05-25_114428_post-deploy.tar.gz(v1.218 確定)

本番URL確認: ✅ HTTP 200(home/ / tasks/work-log/history/ / end/ / version.json: v1.218 / ce-2026-05-25-12)

退化防止: ce-2026-05-25-11 (作業終了報告できないバグ根治) / ce-2026-05-25-10 (debounce + dual session + admin role) / ce-2026-05-25-09 (markLocalWrite + shouldSkipKVPull) / ce-2026-05-25-08 (draft 復元競合根治 + currentSessionId derive) / ce-2026-05-25-07 (Header safe-area + 右切れ + Day 2 同期) / ce-2026-05-25-06 (WorkLogProvider) すべて無変更

** 学び(Vault 蓄積):**
- 「viewport-fit=cover を有効にしたら fixed top-0 の全コンポーネントに safe-area-inset-top の padding を漏れなくチェックすべき」: Header だけ対応するとサイドバー類で被る。1 つの設定変更で 影響範囲は全コンポーネントに及ぶ
- 「データ取得制限は『API取得時の制限』と『UI閲覧制限』の 2 段階で実装するのが堅牢」: UI 制限だけだと DevTools で localStorage を直接見られると他人データが露出する。member には API 取得時点で自分の分のみ取るのが正しい
- 「複数の正しい修正が組み合わさって退化する」リスクは「複合的なライフサイクル変更」では常に確認。今日は ce-08 + ce-11 で対応したが、今後も同種のリスクは継続監視

最新スタンプ:
- 最新changelog: ce-2026-05-25-12
- 最新baseline: 2026-05-25_114428_post-deploy.tar.gz
- 最新アプリver: v1.218


2026-05-25 16:15 更新(ce-2026-05-25-11 / app v1.216 → v1.217)【致命fix】

実施内容(1リリース・緊急 hotfix):
1. ce-2026-05-25-11 作業終了報告できないバグ根治(end ページの runningId 取得修正)
- メンバー報告:「報告がバグってて作業終了報告できない」
- 発症パス: ActiveBoard で「作業終了」ボタン押下 → endSession 内で session.endedAt=now セット → end ページ遷移 → useEffect で getUserState(user.id) → 内部の sessions.find(s => !s.endedAt) が null(さっき endedAt セットしたばかり)→ setRunningId(null) → running=null → handleSave で if (!running) return; → 報告ボタン押下しても何も起こらない
- 真因: ce-2026-05-25-08 で getUserState を sessions derive 化した時、PC-スマホ同期のため「進行中セッション」を抽出する設計にした。これは work-log(root) の「待機中 vs 稼働中」判定には正しいが、end ページの「直前まで稼働していた終了対象セッション」取得には不適合だった
- 修正: end/page.tsx useEffect で getUserState を使うのを廃止。直接 sessions から「進行中(endedAt=null)または直近 10 分以内に endedAt セット」の最新セッションを runningId にする
- 閾値 10 分の意図: ActiveBoard endSession 直後 → end ページ遷移 → 報告入力 → 送信のフローで余裕。古いセッションを誤って終了化する事故は防げる
- work-log(root) の getUserState は変更なし: そちらは「待機中 vs 稼働中」判定に derive が正しい(endSession で「待機中」に切り替わるのは意図通り)
- 影響範囲: end ページのみ。他画面の getUserState 利用箇所は影響なし

主な編集ファイル:
- app/(dashboard)/tasks/work-log/end/page.tsx(useEffect の runningId 取得を直接 sessions 検索に変更)
- lib/changelog.ts(1件追記)/ CLAUDE.md(最新スタンプ)

バックアップ:
- 直前: 2026-05-25_113020_post-deploy.tar.gz(v1.216 baseline)
- post-deploy: 2026-05-25_113426_post-deploy.tar.gz(v1.217 確定)

本番URL確認: ✅ HTTP 200(home/ / tasks/work-log/end/ / active/ / version.json: v1.217 / ce-2026-05-25-11)

退化防止: ce-2026-05-25-10 (debounce + dual session + admin role) / ce-2026-05-25-09 (markLocalWrite + shouldSkipKVPull) / ce-2026-05-25-08 (draft 復元競合根治 + currentSessionId derive) / ce-2026-05-25-07 (Header safe-area + 右切れ + Day 2 同期) / ce-2026-05-25-06 (WorkLogProvider) すべて無変更

** 学び(Vault 蓄積):
- 「getUserState の currentSessionId を sessions derive 化した時、!endedAt 縛りで「終了対象セッション」も取れなくなる」: 同じ関数でも呼び出し画面ごとに必要なセマンティクスが違う(「進行中だけ」vs「直前のセッション」)→ derive ロジックを 1 箇所に持たせるのではなく、各画面で必要な抽出を直接書く方が安全
- 「ce-2026-05-23-04 で ActiveBoard endSession に endedAt 即セットを入れた」+ 「ce-2026-05-25-08 で getUserState derive 化」の
組み合わせ退化**。各単体修正は正しいが、組み合わさると end ページが壊れる。複合的な変更ではセッションのライフサイクル全体を観測してから投入すべき

最新スタンプ:
- 最新changelog: ce-2026-05-25-11
- 最新baseline: 2026-05-25_113426_post-deploy.tar.gz
- 最新アプリver: v1.217


2026-05-25 15:55 更新(ce-2026-05-25-10 / app v1.215 → v1.216)

実施内容(1リリース・残3タスク 1回投入):
1. ce-2026-05-25-10 debounce KV PUT + dual session 警告 UI + history admin role 制限

① debounce KV PUT(lib/work-log.ts)
- 問題: setActiveProgress(ActiveBoard のステータス変更・タイマー ON/OFF・タスク追加)が連続発火で saveSessions → KV PUT 連発(〜500KB×N)
- 修正: syncReportsToKV / syncSessionsToKV を 1.5 秒 debounce 化。pendingReportsSync / pendingSessionsSync の Map で userId 別 timer 管理。連続変更があれば最後の状態だけ PUT される
- beforeunload で pending な PUT を navigator.sendBeacon で flush(タブクローズ時の未 PUT 喪失防止)
- markLocalWrite は即時呼ぶので、3秒の pull protection 内に PUT が完了する設計

② dual session 警告 UI(work-log/page.tsx)
- 問題: PC で開始 → スマホでも開始 → 両方 endedAt=null で残る → currentSessionId は 1個しか指せず、もう一方が「閉じ忘れ」になる
- 修正: danglingSessions = mySessions.filter(s => !s.endedAt && s.id !== runningSession?.id) で検出。1件以上あれば琥珀色警告バナー + 各セッションの「終了する」ボタン
- handleForceEndDangling: confirm ダイアログ → 該当 session に endedAt と minutes をセット → saveSessions で確定

③ admin role 制限(history/page.tsx)
- 問題: history ページは loadAllSessionsFromKV / loadAllReportsFromKV で全員データ取得していたが、誰でも閲覧可能だった
- 修正: canViewOthers = user.role === 'admin' || user.role === 'manager'。member は自分のみ強制(useEffect で他人選択時に自動リセット) + select disabled + 「全員」option は admin/manager のみ表示
- Q1「全社共有」回答に対する閲覧権限制限の実装(物理的にはユーザー別キーで持ち、論理的にロール制限)

主な編集ファイル:
- lib/work-log.ts(syncReportsToKV / syncSessionsToKV を debounce 化 + beforeunload flush)
- app/(dashboard)/tasks/work-log/page.tsx(danglingSessions detect + 警告 UI + handleForceEndDangling)
- app/(dashboard)/tasks/work-log/history/page.tsx(canViewOthers role 制御 + select disabled)
- lib/changelog.ts(1件追記)/ CLAUDE.md(最新スタンプ)

バックアップ:
- 事前ラベル付き: 2026-05-25_112614_before-day3-trio.tar.gz
- post-deploy: deploy 後に更新

本番URL確認: (次タスクで実施)

退化防止: ce-2026-05-25-09 (markLocalWrite + shouldSkipKVPull) / ce-2026-05-25-08 (draft 復元競合根治 + currentSessionId derive) / ce-2026-05-25-07 (Header safe-area + 右切れ + Day 2 同期) / ce-2026-05-25-06 (WorkLogProvider) すべて無変更

** 学び(Vault 蓄積):**
- 「fire-and-forget の頻発する PUT は debounce + beforeunload flush + sendBeacon の組合せが定石」(debounce だけだとタブクローズで消える / sendBeacon は async でも完了する Web API)
- 「ロール制限は『データ取得制限』と『閲覧制限』が別レイヤー」: 物理的に取得しても UI で disabled にする方が、scale-task-cron 側の認可実装より早い。本格的には Workers 側で role check するべきだが、Day 1 では UI 制限のみ

最新スタンプ:
- 最新changelog: ce-2026-05-25-10
- 最新baseline: deploy 後に更新
- 最新アプリver: v1.216


2026-05-25 15:35 更新(ce-2026-05-25-09 / app v1.214 → v1.215)

実施内容(1リリース・予防修正・ユーザー検証前):
1. ce-2026-05-25-09 KV pull が直前のローカル編集を上書きする事故の予防修正
- 問題シナリオ: (1) PC で ActiveBoard のタスクを「進行中」に変更 → setActiveProgress → localStorage 更新 + KV PUT 開始(非同期・数百ms) (2) タブ切り替えて戻る or 別アプリから戻る (3) WorkLogProvider の onFocus が pullFromKV 即実行 (4) KV から GET → まだ古いデータが返る(PUT 完了前)(5) mergeSessions で remote 優先 → 古い「未着手」状態に上書き (6) UI 巻き戻り
- 発症形態: 「タスク状態が勝手に戻る」「timer 計測時間が巻き戻る」「追加タスクが消える」
- 修正: lib/work-log.ts に markLocalWrite() + shouldSkipKVPull() ヘルパ追加 + KEY_LAST_LOCAL_WRITE = 'scale-worklog-last-local-write' + LOCAL_WRITE_PROTECTION_MS = 3000
- markLocalWrite を呼ぶ箇所: setActiveProgress / saveSessions / saveReports(全ローカル書き込み網羅)
- shouldSkipKVPull: WorkLogProvider.pullFromKV() の冒頭で「直近 3秒以内のローカル書き込みあれば pull スキップ」判定。スキップ時は次の 30秒ポーリングまで待つ
- トレードオフ: 手動操作中の直後 3 秒間は他端末更新が反映されない。編集消失防止のため許容

主な編集ファイル:
- lib/work-log.ts(markLocalWrite + shouldSkipKVPull 追加 / setActiveProgress / saveSessions / saveReports で markLocalWrite 呼び出し)
- lib/work-log-api.tsx(pullFromKV の冒頭で shouldSkipKVPull チェック)
- lib/changelog.ts(1件追記)/ CLAUDE.md(最新スタンプ)

バックアップ:
- 事前ラベル付き: 2026-05-25_111923_before-local-write-guard.tar.gz
- post-deploy: 2026-05-25_112239_post-deploy.tar.gz(v1.215 確定)

本番URL確認: ✅ HTTP 200(home/ / tasks/work-log/ / active/ / version.json: v1.215)

退化防止: ce-2026-05-25-08 (draft 復元競合根治 + currentSessionId derive) / ce-2026-05-25-07 (Header safe-area + 右切れ + Day 2 同期) / ce-2026-05-25-06 (WorkLogProvider) すべて無変更

** 学び(Vault 蓄積):
- 「楽観的 UI + KV PUT fire-and-forget + 別経路の pull」というパターンでは、PUT 完了前の pull が古いデータを返して
direct after-write の pull で local 編集が消える事故が起きる**。pull スキップ窓(write→3秒)で防ぐのが最小工数の解
- 「focus / visibilitychange は短時間に連続発火しやすい」→ pull の即時実行は注意。short-window throttle と相性が良い

最新スタンプ:
- 最新changelog: ce-2026-05-25-09
- 最新baseline: 2026-05-25_112239_post-deploy.tar.gz
- 最新アプリver: v1.215


2026-05-25 15:10 更新(ce-2026-05-25-08 / app v1.213 → v1.214)

実施内容(1リリース・致命fix 2件):
1. ce-2026-05-25-08 作業終了タスク消失バグ根治 + スマホで進行中セッション自動 ActiveBoard 表示
- ①真因(タスク消失): end/morning/night の保存 useEffect が「再 mount 時に初期 state=空」のタイミングで先に走り、isDraftEmpty=true で clearDraft → その後の復元 useEffect が loadDraft=null で入力消失していた
- ①修正: 3画面の保存 useEffect の早期 return に !draftRestoreAttempted 追加 + deps に追加。復元処理が試みられるまで saveDraft/clearDraft を抑止して順序保証
- ②真因(スマホで作業中画面が出ない): getUserState() が localStorage の KEY_STATE から currentSessionId を読んでいたが、これは KV 同期対象外で他端末セッションが反映されなかった(ce-2026-05-25-06 で sessions/reports は KV 同期したが state は端末完結のまま)
- ②修正: getUserState 内で sessions から動的 derive: const myRunning = sessions.find(s => s.userId === userId && !s.endedAt); state = { ...state, currentSessionId: myRunning?.id ?? null };。KV pull で他端末の進行中セッションが入った時点で currentSessionId が自動更新 → work-log(root) ページが isRunning=true 判定で ActiveBoard を埋め込み表示
- 副作用: start ページの updateUserState(currentSessionId: x) 呼び出しは no-op になるが(saveSessions 後の sessions から derive されるため)、コードは後方互換のため残置

主な編集ファイル:
- lib/work-log.ts(getUserState で currentSessionId を sessions から derive)
- app/(dashboard)/tasks/work-log/end/page.tsx / morning/page.tsx / night/page.tsx(保存 useEffect に !draftRestoreAttempted ガード追加)
- lib/changelog.ts(1件追記)/ CLAUDE.md(最新スタンプ)

バックアップ:
- 直前: 2026-05-25_110457_post-deploy.tar.gz(v1.213 baseline)
- post-deploy: 2026-05-25_111203_post-deploy.tar.gz(v1.214 確定)

本番URL確認: ✅ HTTP 200(home/ / tasks/work-log/ / active/ / end/ / version.json: v1.214)

退化防止: ce-2026-05-25-07 (Header safe-area + 右切れ + Day 2 同期) / ce-2026-05-25-06 (WorkLogProvider) / sessions の KV PUT (work-log/sessions?userId=) すべて無変更

** 学び(Vault 蓄積):
- 「useEffect の実行順序は同じ deps だと React の宣言順だが、保存系 useEffect と復元系 useEffect が共存する場合は
保存系を !restoreAttempted でガードするのが安全」
- 「KV 同期は完全じゃない: sessions/reports だけ同期しても、それを参照する state (端末固有) が同期されてないとユーザー体験が破綻する。
state は KV 同期対象から derive する設計**にすると同期忘れがない」

検証手順:
1. PC で /tasks/work-log/ 開く → 「稼働開始」→ タスク入力 → 開始
2. スマホで /tasks/work-log/ をハードリロード(または 30秒待つ)→ ActiveBoard が表示されることを確認
3. PC で /tasks/work-log/end/ 開く
4. 追加タスクに「テストタスク」入力
5. 別画面(タスク管理など)に飛んで戻る
6. 「テストタスク」が 残っていることを確認

最新スタンプ:
- 最新changelog: ce-2026-05-25-08
- 最新baseline: 2026-05-25_111203_post-deploy.tar.gz
- 最新アプリver: v1.214


2026-05-25 14:35 更新(ce-2026-05-25-07 / app v1.212 → v1.213)

実施内容(1リリース・致命fix 2件 + PC-スマホ同期完成):
1. ce-2026-05-25-07 スマホ Header safe-area対応 + 作業報告右切れ修正 + PC-スマホ同期 Day 2
- 大串スクショ報告:「Header の verバッジ/アバター/ベルがステータスバーに隠れて押せない / 作業報告ページ右側ボタン見切れ / PC-スマホ連携を一気に進めたい」
- 真因 1: Header 隠れ: ce-2026-05-25-01 で viewportFit=cover を入れたが Header に safe-area-inset-top padding 漏れ。PWA standalone で iPhone ステータスバー(Dynamic Island)領域までコンテンツが広がるため Header の上半分が隠れて操作不能
- 修正 1: <header className="h-14">min-h-14 + style={{ paddingTop: "env(safe-area-inset-top)" }} で bg-bg2 がステータスバー領域まで塗られて Header 本体が安全領域内に収まる
- 真因 2: 作業報告右切れ: tasks/work-log/page.tsx 174-187 の flex justify-between で右ボタン2個(履歴/週次月次)がスマホ画面幅で押し出されて見切れ
- 修正 2: 親 div を flex items-start justify-between gap-3 flex-wrap + min-w-0 / 右ボタン側を shrink-0 + ボタンテキストを <span className="hidden sm:inline"> でスマホ非表示(アイコンのみ) + min-h-[36px] タップターゲット確保
- PC-スマホ同期 Day 2: morning / history / stats / night / work-log(root) の 5画面に useWorkLog import + const { reloadCount } = useWorkLog() + データ load useEffect の deps に reloadCount 追加。全 8画面同期完了(Day 1 の ActiveBoard / start / end + Day 2 の 5画面)

主な編集ファイル:
- components/layout/Header.tsx(safe-area-inset-top padding 追加)
- app/(dashboard)/tasks/work-log/page.tsx(右切れ修正 + reloadCount 追加)
- app/(dashboard)/tasks/work-log/morning/page.tsx / history/page.tsx / stats/page.tsx / night/page.tsx(useWorkLog import + reloadCount deps 追加)
- lib/changelog.ts(1件追記)/ CLAUDE.md(最新スタンプ)

バックアップ:
- 事前ラベル付き: 2026-05-25_105907_before-header-safearea.tar.gz
- post-deploy: deploy 後に更新

本番URL確認: (次タスクで実施)

退化防止: PWA基盤(ce-2026-05-25-01) / 絵文字矢印置換(ce-2026-05-25-02) / sessionStorage→localStorage 認証(ce-2026-05-25-03) / Header verバッジ常時表示(ce-2026-05-25-04) / Header テキスト省略+ActiveBoard 3ボタン非表示(ce-2026-05-25-05) / WorkLogProvider基盤(ce-2026-05-25-06) すべて無変更

** 学び(Vault 蓄積):
- 「viewport-fit=cover を追加したら Header に safe-area-inset-top の padding-top を
同時に追加する」のはセット。漏らすと PWA で致命的に操作不能(v1.207 で viewport 追加・v1.213 まで気付かなかった)
- 「<header className="h-14"> 固定高は safe-area padding と相性悪い」→ min-h-14 + style で paddingTop を確保する形が正解
- 「flex justify-between でスマホ見切れたら
flex-wrap + アイコンのみ sm:inline テキスト** が最小改修パターン」

最新スタンプ:
- 最新changelog: ce-2026-05-25-07
- 最新baseline: deploy 後に更新
- 最新アプリver: v1.213


2026-05-25 14:00 更新(ce-2026-05-25-06 / app v1.211 → v1.212)

実施内容(1件・大型新機能 / PC-スマホ同期 Day 1):
1. ce-2026-05-25-06 PC-スマホ同期 Day 1: 作業報告データを KV から自動 pull
- 大串 FB:「PCと連動してなさそうだから連動させて。スマホで開始してPCで終了みたいな場面も結構ありそう」
- 設計: scale-task-cron Workers のソースが手元になく active-progress 専用エンドポイント追加できないため、ActiveTaskProgress[] を WorkSession に同梱する設計を採用(既存 sessions PUT エンドポイントで一緒に sync される)
- キー設計(Q1: 全社共有): 物理キーは userId 別 work_log_sessions:{userId} で書き込み、admin は将来 loadAllSessionsFromKV で全員ループ pull する設計(Day 1 では自分の userId 分のみ pull)
- 競合解決(Q2: last-write-wins): 同一ユーザーの 2デバイス間競合は「直前の操作が正」。merge は id ベース・remote 優先・local のみの新規 id は維持(KV PUT 前データ消失防止)
- マイグレーション(Q3: 一律 push): WorkLogProvider 起動時に migrateActiveProgressIntoSessions(userId) 1度きり実行 → 旧 KEY_ACTIVE_PROGRESS の cache を sessions[].progress に統合 → saveSessions で KV PUT。フラグ scale-base-work-log-migrated-v1 で再実行防止
- 切替方式(Q4: 一気切替): feature flag なし。既存 API シグネチャ維持 + 各画面は useWorkLog().reloadCount を deps に追加するだけで自動反映
- 新規ファイル: lib/work-log-api.tsx(WorkLogProvider / useWorkLog / mergeSessions/Reports / JSON 深さ比較で不要な再 render 抑止)
- WorkLogProvider 動作: 起動時マイグレーション + 即時 KV pull → 30秒ポーリング + window.focus + visibilitychange で再 pull → localStorage との JSON 比較で変化あれば書き戻し + reloadCount bump → 各画面の useEffect が再実行
- 画面改修(Day 1 範囲): ActiveBoard / start / end の各データ load useEffect の deps に reloadCount 追加。WorkLogDock は既に 1秒ポーリング済みなので変更不要
- Day 2 範囲: morning / history / stats / night / work-log(root) の各画面の deps に reloadCount 追加(リロード許容範囲なので Day 1 では省略)

主な編集ファイル:
- lib/work-log.ts(WorkSession.progress 追加 / loadActiveProgressMap rebuild / setActiveProgress 経由 saveSessions / loadSessionsFromKVByUser / loadReportsFromKVByUser / migrateActiveProgressIntoSessions 追加)
- lib/work-log-api.tsx 新規(Provider)
- app/(dashboard)/layout.tsx(WorkLogProvider userId={user.id} を TasksProvider 内側に追加)
- components/tasks/work-log/ActiveBoard.tsx / app/(dashboard)/tasks/work-log/start/page.tsx / app/(dashboard)/tasks/work-log/end/page.tsx(useWorkLog import + reloadCount deps 追加)
- lib/changelog.ts(1件追記)/ CLAUDE.md(最新スタンプ)
- Vault: 31_システム開発部/SCALE_Base/2026-05-25_設計提案_作業報告_PC-スマホ連動.md(設計提案・着手前作成済)

バックアップ:
- 事前ラベル付き: 2026-05-25_104243_before-work-log-kv-sync.tar.gz
- post-deploy: 2026-05-25_105450_post-deploy.tar.gz (v1.212 確定)

本番URL確認: (次タスクで実施)

退化防止: スマホHeader verバッジ常時表示(ce-2026-05-25-04) / スマホ毎回ログイン根治(ce-2026-05-25-03) / PWA基盤(ce-2026-05-25-01) / 絵文字矢印置換 + verバッジタップ拡大(ce-2026-05-25-02) / ChangelogModal Portal化(ce-2026-05-23-07) / AppVersionBadge ピル切替(ce-2026-05-23-05) / dangling timer 修正(ce-2026-05-23-04) すべて無変更

** 学び(Vault 蓄積):
- 「外部 Workers のソースが手元にないとき、新規エンドポイント追加できないので
既存エンドポイントに乗せる**設計を検討する」(active-progress を session.progress に同梱)
- 「Context Provider で reloadCount を bump し、各画面の useEffect deps に入れる」パターンが、既存 useState + useEffect 構造を破壊せず KV pull → 画面更新を実現する最小改修

最新スタンプ:
- 最新changelog: ce-2026-05-25-06
- 最新baseline: 2026-05-25_105450_post-deploy.tar.gz
- 最新アプリver: v1.212


2026-05-25 11:45 更新(ce-2026-05-25-05 / app v1.210 → v1.211)

実施内容(1件・スマホUI 2点同時修正):
1. ce-2026-05-25-05 スマホ Header 上部混雑解消 + 作業報告右切れ修正
- 報告:「最新になってたけど、画面上部にメニューありすぎてタップできない / 作業報告も画面右側切れてる / PC-スマホ同期はまだ?」
- 画面上部混雑: AppVersionBadge の「v1.XXX」テキストを hidden md:inline でスマホ非表示にし、ピル(✓最新 / クリックで更新)だけ表示してコンパクト化
- 右切れ真因: ActiveBoard 各タスク行に「未着手/進行中/完了」3ボタンセット(固定幅 shrink-0)があり、スマホ画面幅に収まらず右にはみ出していた
- 右切れ修正: 3ボタンセットの親 div を hidden md:flex でスマホ非表示。代替: 左の丸トグル(cycleStatus 循環)で操作可能(既に 44x44 ヒットエリア確保済み)
- PC-スマホ同期: 未実装。Vault 31_システム開発部/SCALE_Base/2026-05-25_設計提案_作業報告_PC-スマホ連動.md の設計に沿って、次の ce で実装予定(大串からの 4点回答待ち)

主な編集ファイル:
- components/layout/AppVersionBadge.tsx
- components/tasks/work-log/ActiveBoard.tsx
- lib/changelog.ts(1件追記)/ CLAUDE.md(最新スタンプ)

バックアップ:
- post-deploy: 2026-05-25_101754_post-deploy.tar.gz (v1.211 確定)

本番URL確認: ✅ HTTP 200(home/ / version.json: v1.211)

退化防止: スマホHeader verバッジ常時表示(ce-2026-05-25-04) / スマホ毎回ログイン根治(ce-2026-05-25-03) / PWA基盤(ce-2026-05-25-01) / 絵文字矢印置換 + verバッジタップ拡大(ce-2026-05-25-02) すべて無変更

最新スタンプ:
- 最新changelog: ce-2026-05-25-05
- 最新baseline: 2026-05-25_101754_post-deploy.tar.gz
- 最新アプリver: v1.211


2026-05-25 11:30 更新(ce-2026-05-25-04 / app v1.209 → v1.210)

実施内容(1件・スマホUI修正):
1. ce-2026-05-25-04 スマホ Header に verバッジ常時表示(モバイルから「クリックで更新」に到達できないバグ修正)
- 報告:「PC だと左下からクリックで更新できるけど、スマホ版だとどこからできる?画面が出ないから困ってる」
- 真因: components/layout/Header.tsx の AppVersionBadge を含む div が hidden lg:block だったため lg 未満(スマホ)では非表示。Sidebar 左下にもバッジはあるが、サイドバー開かないと見えない → モバイルから到達できなかった
- 修正: Header の div を flex flex-col items-end leading-tight で常時表示に変更。ユーザー名 <p> のみ hidden lg:block を維持(スペース節約)
- 効果: スマホでも Header 右上に「v1.XXX [✓ 最新]」緑ピル or 新版時「v1.XXX [クリックで更新]」橙ピルが表示。タップで動作

主な編集ファイル:
- components/layout/Header.tsx
- lib/changelog.ts(1件追記)/ CLAUDE.md(最新スタンプ)

バックアップ:
- post-deploy: 2026-05-25_100647_post-deploy.tar.gz (v1.210 確定)

本番URL確認: ✅ HTTP 200(home/ / version.json: v1.210)

退化防止: スマホ毎回ログイン根治(ce-2026-05-25-03) / PWA基盤(ce-2026-05-25-01) / 絵文字矢印置換 + verバッジタップ拡大(ce-2026-05-25-02) すべて無変更

最新スタンプ:
- 最新changelog: ce-2026-05-25-04
- 最新baseline: 2026-05-25_100647_post-deploy.tar.gz
- 最新アプリver: v1.210


2026-05-25 11:15 更新(ce-2026-05-25-03 / app v1.208 → v1.209)

実施内容(1件・致命バグ根治):
1. ce-2026-05-25-03 スマホで毎回ログイン求められるバグを根治
- 報告:「スマホver だと毎回ログイン求められるけど、pcverだと求められないのなんで?極力スマホverで求められないように」
- 真因: lib/auth-context.tsx が認証情報を sessionStorage に保存していた。sessionStorage はタブを閉じる/アプリ強制終了で消えるWeb API。スマホはアプリ切替/バックグラウンド終了が頻発するので毎回ログイン化。PC は同じタブ開きっぱなしで使うので問題出にくかった
- 修正: useEffect の読み取り / login の書き込み / logout の削除 を全部 sessionStoragelocalStorage に置換
- マイグレーション: 既存ユーザー再ログイン不要なよう、起動時に旧 sessionStorage(SESSION_KEY) と legacy localStorage(scale-base-user) を新 localStorage(SESSION_KEY) に自動コピー
- iOS Safari ITP 補足: localStorage でも 7日アクセスなしで消える可能性あるが、PWA standalone(ホーム画面追加して起動)では ITP 影響を受けない。PWA で使うのが最も永続性高い(ce-2026-05-25-01 で対応済み)

主な編集ファイル:
- lib/auth-context.tsx(sessionStorage 全置換 + マイグレーションロジック追加)
- lib/changelog.ts(1件追記)/ CLAUDE.md(最新スタンプ)

バックアップ:
- post-deploy: 2026-05-25_100325_post-deploy.tar.gz (v1.209 確定)

本番URL確認: ✅ HTTP 200(home/ / version.json: v1.209)

退化防止: PWA基盤(ce-2026-05-25-01) / 絵文字矢印置換 + verバッジ拡大(ce-2026-05-25-02) / ChangelogModal Portal化 / dangling timer 修正 すべて無変更

最新スタンプ:
- 最新changelog: ce-2026-05-25-03
- 最新baseline: 2026-05-25_100325_post-deploy.tar.gz
- 最新アプリver: v1.209


2026-05-25 11:00 更新(ce-2026-05-25-02 / app v1.207 → v1.208)

実施内容(1件・UI/UX微修正 + 重要設計提案):
1. ce-2026-05-25-02 絵文字矢印置換 + verバッジタップ拡大 + PC-スマホ連動 設計提案
- 要望:「絵文字矢印やだ」「verが押せない」「PC連動して」「スマホ画面見切れ」
- 絵文字置換: tasks/work-log/page.tsx「→ 作業を始める」と design/manual/page.tsx「詳しく見る →」を <ChevronRight />
- verバッジ: AppVersionBadge を min-h-[32px] + p-1 -m-1 でヒットエリア拡張、ピル text 9→10 / py-px→py-0.5
- タスクページ見切れ: 稼働開始ボタンの「→ 作業を始める」補足をスマホで hidden(ボタン幅縮小)
- PC-スマホ連動: 大改修案件として設計提案ノートを Vault に作成 → 31_システム開発部/SCALE_Base/2026-05-25_設計提案_作業報告_PC-スマホ連動.md
- 現状: localStorage 完結 → 端末ごとに完全独立
- 提案: scale-task-cron KV に work_log_*:{userId} として同期
- 工数約 4 営業日 / feature flag で並走運用設計
- 次の ce で Day 1 着手予定(着手前にキー設計と競合解決方針を大串に確認)

主な編集ファイル:
- app/(dashboard)/tasks/work-log/page.tsx / app/(dashboard)/design/manual/page.tsx / components/layout/AppVersionBadge.tsx
- lib/changelog.ts(1件追記)/ CLAUDE.md(最新スタンプ)
- Vault: 31_システム開発部/SCALE_Base/2026-05-25_設計提案_作業報告_PC-スマホ連動.md 新規

バックアップ:
- post-deploy: 2026-05-25_095859_post-deploy.tar.gz (v1.208 確定)

本番URL確認: ✅ HTTP 200(home/ / work-log/ / active/ / manifest.json / version.json: v1.208)

退化防止: PWA基盤(ce-2026-05-25-01) / ChangelogModal Portal化 / AppVersionBadge ピル切替 / dangling timer 修正 / 朝日報 Enter モーダル すべて無変更

次の ce 候補(優先度順):
1. PC-スマホ連動 実装(設計提案に基づく Day 1〜Day 4・最優先)
2. スマホ実機スクショ後の見切れ網羅対応
3. C対策(morning/start/end の input UX)

最新スタンプ:
- 最新changelog: ce-2026-05-25-02
- 最新baseline: 2026-05-25_095859_post-deploy.tar.gz
- 最新アプリver: v1.208


2026-05-25 09:50 更新(ce-2026-05-25-01 / app v1.206 → v1.207)

実施内容(1件・PWA化+スマホ最適化 第一段階):
1. ce-2026-05-25-01 PWA化(ホーム画面追加でアプリ風起動)+ スマホ操作性 第一段階
- 要望:「スマホでの使いづらさが今一番の課題。合間作業のメンバー、PC触ってない時の作業も計測したい。アプリリリースもしたい(お金かからない?)」
- 回答:「App Store/Play 配信は Apple $99/年 + Google $25 単発が必要。社内ツールなら PWA で十分・無料」→ PWA 化で着手
- PWA基盤:
- public/manifest.json 新規(name/short_name/start_url=/home/ / display=standalone / theme_color / icons 192/180/512 maskable / shortcuts 作業中/朝日報/作業開始)
- public/sw.js 新規(PWA インストール要件を満たす最小 SW・network のみ pass●●●●●●)
- components/ServiceWorkerRegister.tsx 新規(client component で本番のみ /sw.js を register)
- app/layout.tsx: import に Viewport 型追加 / metadata.manifest + appleWebApp + formatDetection / export const viewport (viewportFit=cover / themeColor=#0f1115 等) / body 内に
- A対策(タップしづらい): ActiveBoard ステータストグルを 44x44 ヒットエリア + アイコン size 20→22 + active 押下フィードバック
- B対策(レイアウト崩れ): ActiveBoard 作業停止/終了フローティングと一括選択バーを safe-area-inset-bottom 対応 / max-w を sm 用と md 用で分岐
- B対策: WorkLogDock も safe-area-inset-bottom 対応(iPhone ホームインジケーター被り解消)
- C対策残: morning/start/end の input 入力 UX 改善は範囲広く別 ce で対応予定

** ハマりポイント(学び): return ( {/* コメント */} <div>...</div> ); は JSX 構文エラー(return ( の中は 1要素のみ)。コメントは return の 前** に JS コメント (//) として書くか、Fragment で囲む。今回ビルド 1回失敗 → 修正 → 再デプロイ。

主な編集ファイル:
- 新規: public/manifest.json / public/sw.js / components/ServiceWorkerRegister.tsx
- 変更: app/layout.tsx / components/tasks/work-log/ActiveBoard.tsx / components/layout/WorkLogDock.tsx
- lib/changelog.ts(1件追記)/ CLAUDE.md(最新スタンプ)

バックアップ:
- post-deploy: 2026-05-25_094121_post-deploy.tar.gz (v1.207 確定)

本番URL確認: ✅ HTTP 200(home/ / tasks/work-log/active/ / manifest.json / sw.js / icon-192 / apple-touch-icon / version.json: v1.207)

退化防止: ChangelogModal Portal化(ce-2026-05-23-07) / AppVersionBadge ピル切替(ce-2026-05-23-05) / dangling timer 修正(ce-2026-05-23-04) / 朝日報 Enter モーダル(ce-2026-05-23-02) / TaskDetailModal 中身空対策(ce-2026-05-23-01) すべて無変更

最新スタンプ:
- 最新changelog: ce-2026-05-25-01
- 最新baseline: 2026-05-25_094121_post-deploy.tar.gz
- 最新アプリver: v1.207


2026-05-23 16:35 更新(ce-2026-05-23-07 / app v1.205 → v1.206)

実施内容(1件・致命バグ根治 / 認識違いの修正):
1. ce-2026-05-23-07 更新履歴モーダルが Sidebar 幅に閉じ込められて1文字ずつ縦折り返しになるバグを根治
- 報告:「まだこうなってるよ〜 課題の認識合ってる?」+ スクショ(モーダルが 1文字幅で縦に折り返し)
- 真因(前回 ce-2026-05-23-06 の認識違い): max-w-2xl → max-w-5xl の拡大は意味があったが、ChangelogModalAppVersionBadge の子としてレンダリングされ、AppVersionBadgeSystemSidebar の中にあった。SystemSidebartransition-transform + -translate-x-* を持つため、CSS 仕様により内部の position: fixed の基準が viewport ではなく Sidebar に変わり、inset-0 が Sidebar 幅(~200px)に閉じ込められていた → 1文字幅まで折り返し
- 修正: components/layout/ChangelogModal.tsximport { createPortal } from "react-dom" 追加。return JSX を createPortal(<div ...>...</div>, document.body) に変更。SSR ハイドレーションズレ防止の mounted ガード追加
- 効果: モーダルが Sidebar/Header の transform に影響されず viewport 基準で描画 → ce-2026-05-23-06 の max-w-5xl 拡大も正しく効く(画面の幅いっぱい近くまで広がる)

主な編集ファイル:
- components/layout/ChangelogModal.tsx(4箇所: import + mounted + createPortal 包み込み)
- lib/changelog.ts(1件追記)/ CLAUDE.md(最新スタンプ)

バックアップ:
- post-deploy: 2026-05-23_163538_post-deploy.tar.gz (v1.206 確定)

本番URL確認: ✅ HTTP 200(home/ / version.json: v1.206)

退化防止: AppVersionBadge ピル切替(ce-2026-05-23-05) / dangling timer 修正(ce-2026-05-23-04) / 朝日報 Enter モーダル(ce-2026-05-23-02) / TaskDetailModal 中身空対策(ce-2026-05-23-01) / WorkLogDock すべて無変更

** 学び(Vault 蓄積):** 「fixed inset-0 は親要素に transform/filter/perspective/contain が当たっていると viewport ではなく親要素基準になる」CSS仕様。Sidebar/モバイル開閉のスライドアニメで transition-transform を使っているコンポーネント配下のモーダルは必ず createPortal(..., document.body) で外に逃がすべき。

最新スタンプ:
- 最新changelog: ce-2026-05-23-07
- 最新baseline: 2026-05-23_163538_post-deploy.tar.gz
- 最新アプリver: v1.206


2026-05-23 15:30 更新(ce-2026-05-23-06 / app v1.204 → v1.205)

実施内容(1件・UI拡大):
1. ce-2026-05-23-06 更新履歴モーダル(ChangelogModal)を大画面化
- 要望:「ver 押すとこんな細くアップデート情報出るんだけど、もっと大画面で出して」
- 横幅 max-w-2xl (672px) → max-w-5xl (1024px) ≒ 1.5倍
- 高さ max-h-[70vh] → max-h-[85vh]
- 外周 padding p-4 sm:p-8 → p-3 sm:p-6(モーダル本体を広げる)
- 各サイズ拡大: h2 text-lg → text-xl / ver番号 text-xs → text-sm / title text-sm → text-base / summary text-[13px] → text-sm / details text-[12px] → text-[13px]
- エントリ行 padding gap 拡大: px-3.5 py-2.5 gap-2.5 → px-4 py-3 gap-3

主な編集ファイル:
- components/layout/ChangelogModal.tsx
- lib/changelog.ts(1件追記)/ CLAUDE.md(最新スタンプ)

バックアップ:
- post-deploy: 2026-05-23_142634_post-deploy.tar.gz (v1.205 確定)

本番URL確認: ✅ HTTP 200(home/ / version.json: v1.205)

退化防止: AppVersionBadge ピル切替(ce-2026-05-23-05)/ dangling timer 修正(ce-2026-05-23-04)/ WorkLogDock / 朝日報 Enter モーダル / TaskDetailModal 中身空対策 すべて無変更

最新スタンプ:
- 最新changelog: ce-2026-05-23-06
- 最新baseline: 2026-05-23_142634_post-deploy.tar.gz
- 最新アプリver: v1.205


2026-05-23 14:20 更新(ce-2026-05-23-05 / app v1.203 → v1.204)

実施内容(1件・改善 / SCALE CRM v11.5 R7a 完全再現):
1. ce-2026-05-23-05 新バージョン検出の更新導線を左下バッジに一本化
- 要望:「右上のボタンじゃなくて左下のバージョンのところに『クリックして更新』って押すイメージだった。SCALE CRM 完全再現して」
- 前回 ce-2026-05-23-03 で実装した右上バナーは SCALE CRM v9.206 の旧仕様だった。現行 v11.5 R7a は _renderVersionBadgeState で左下バッジに状態ピル統合の形に変わっていたので完全再現に書き直し
- 拡張 components/layout/AppVersionBadge.tsx: 5分ごと /version.json fetch + 状態に応じてピル切り替え:
- 新版あり: 「v1.XXX [クリックで更新]」橙色ピル (#f59e0b) / onClick → location.reload() / title「新バージョン X があります。クリックで安全に最新へ更新(業務中はあとででもOK)」
- 最新時: 「v1.XXX [✓ 最新]」緑色ピル (#10b981) / onClick → 更新履歴モーダル
- 撤去 components/layout/VersionUpdateBanner.tsx 削除(旧仕様の右上バナー廃止)
- 撤去 app/(dashboard)/layout.tsx から VersionUpdateBanner の import と配置を削除
- データ層(generate-version-json.cjs / public/version.json / deploy.sh の generate ステップ)は変更なし。バッジ側がここを参照

主な編集ファイル:
- components/layout/AppVersionBadge.tsx(state + 5分fetch + ピル切替)
- 削除: components/layout/VersionUpdateBanner.tsx
- app/(dashboard)/layout.tsx(VersionUpdateBanner 撤去)
- lib/changelog.ts(1件追記)/ CLAUDE.md(最新スタンプ)

バックアップ:
- post-deploy: 2026-05-23_141734_post-deploy.tar.gz (v1.204 確定)

本番URL確認: ✅ HTTP 200(home/ / tasks/work-log/active/ / version.json: v1.204)

退化防止: ChangelogModal / WorkLogDock / ActiveBoard / morning Enter モーダル(ce-2026-05-23-02)/ dangling timer 修正(ce-2026-05-23-04)/ TaskDetailModal 中身空対策(ce-2026-05-23-01)すべて無変更

最新スタンプ:
- 最新changelog: ce-2026-05-23-05
- 最新baseline: 2026-05-23_141734_post-deploy.tar.gz
- 最新アプリver: v1.204


2026-05-23 12:30 更新(ce-2026-05-23-04 / app v1.202 → v1.203)

実施内容(1件・バグ修正 / 3経路一括根治):
1. ce-2026-05-23-04 止め忘れた timer が無限累計加算され続けるバグを根治
- 報告: 「計測押してないのにずっとタイマー進み続けるのある。チャネルワークスのやつ。前のセッションで止め忘れが原因かな? 作業終了報告をした=それも強制ストップしないと」+ スクショ(累計 20:03:08・+19時間3分超過 2005%)
- 真因1 lib/work-log.tsgetAccumulatedMsForTasksession.endedAt を見ず、p.timerStartedAt があれば常に now - timerStartedAt を加算 → 終了済みセッションに残った dangling timer が無限加算
- 真因2 ActiveBoard.tsxendSession が「動く timer は停止」するものの session.endedAt は end ページ任せ → ユーザーが end ページに到達せず離脱すると session が中ぶらりんで残る
- 修正1 getAccumulatedMsForTask: running 集計を Math.max(0, (s.endedAt ? endedAtMs : now) - startedMs) でクランプ。endedAt 後の時間は加算しない → 既に壊れている過去データもこの計算側修正で即座に正常表示化
- 修正2 endSession: interruptions に区間記録(pauseSession と同パターン)+ session.endedAt も即セット(end ページが再度上書きしても冪等)
- 修正3 end/page.tsxrunning 取得を !s.endedAt 縛りから「runningId 指定があれば endedAt 問わず取得」に緩和(修正2との整合・handleSave 動作維持)
- データ自動回復: 既存の壊れたデータ(過去 session に timerStartedAt 残存)はハードリロードで新ロジックが走り累計が即座に正しい値に修正される

主な編集ファイル:
- lib/work-log.ts(getAccumulatedMsForTask クランプ)
- components/tasks/work-log/ActiveBoard.tsx(endSession 強化)
- app/(dashboard)/tasks/work-log/end/page.tsx(running 取得緩和)
- lib/changelog.ts(1件追記)/ CLAUDE.md(最新スタンプ)

バックアップ:
- post-deploy: 2026-05-23_123621_post-deploy.tar.gz (v1.203 確定)

本番URL確認: ✅ HTTP 200(home/ / tasks/work-log/active/ / morning/ / end/ / version.json)
前回機能動作確認: /version.json が v1.203 / ce-2026-05-23-04 に自動更新 ✓(generate-version-json.cjs が deploy.sh から自動実行されている証拠)

退化防止: TaskDetailModal中身空対策(ce-2026-05-23-01) / 朝日報 Enter モーダル(ce-2026-05-23-02) / 新バージョン検出バナー(ce-2026-05-23-03) / WorkLogDock / ChangelogModal / AppVersionBadge すべて無変更

最新スタンプ:
- 最新changelog: ce-2026-05-23-04
- 最新baseline: 2026-05-23_123621_post-deploy.tar.gz
- 最新アプリver: v1.203


2026-05-23 10:55 更新(ce-2026-05-23-03 / app v1.201 → v1.202)

実施内容(1件・新機能 / SCALE CRM・TERASU CRM 同等仕様):
1. ce-2026-05-23-03 新バージョン検出バナーを導入(クリックで反映)
- 要望: 「SCALE base のアップデート設定を SCALE CRM / TERASU CRM と全く同じ仕様に。クリックして更新ボタンが出る仕様」
- 参考元: SCALE CRM core.js v9.206 _checkAppVersion + v11.5 R7a(自動リロード廃止・手動クリック方針)
- 仕組み:
- scripts/generate-version-json.cjs 新設: lib/changelog.ts を読み取り、public/version.json{ version: 'v1.XXX', latestId, latestTitle, ... } を出力(build 毎に上書き)
- scripts/deploy.sh 修正: BUILD_DIR の rsync 後・npx next build 前に generate を実行
- components/layout/VersionUpdateBanner.tsx 新設: 5分ごとに /version.json?_={ts} を no-store fetch、APP_VERSION と異なれば右上にグラデーションバナー表示(🆙 新バージョン v1.XXX / クリックで反映)
- クリック → location.reload()、× → 30 分 snooze(localStorage)、自動リロード無し(セッション喪失リスク回避・SCALE CRM v9.207 で廃止された方針踏襲)
- app/(dashboard)/layout.tsx<VersionUpdateBanner /> 配置(WorkLogDock の下・z-70)
- キャッシュ戦略: public/headers の /* ルール(max-age=0, must-revalidate)+ fetch no-store + ?=timestamp の三重で最新性保証
- 本番確認: https://base.scale-group.co.jp/version.json → HTTP 200 / {"version":"v1.202",...} / Cache-Control: max-age=0, must-revalidate ✓

主な編集ファイル:
- 新規: scripts/generate-version-json.cjs / components/layout/VersionUpdateBanner.tsx / public/version.json
- 変更: scripts/deploy.sh / app/(dashboard)/layout.tsx
- lib/changelog.ts(1件追記)/ CLAUDE.md(最新スタンプ)

バックアップ:
- post-deploy: 2026-05-23_110326_post-deploy.tar.gz (v1.202 確定)

本番URL確認: ✅ HTTP 200(home/ / tasks/work-log/active/ / tasks/work-log/morning/ / version.json)

退化防止: ChangelogModal / AppVersionBadge / WorkLogDock / ActiveBoard / morning Enter モーダル(ce-2026-05-23-02)/ 旧モーダル中身空対策(ce-2026-05-23-01)すべて無変更

最新スタンプ:
- 最新changelog: ce-2026-05-23-03
- 最新baseline: 2026-05-23_110326_post-deploy.tar.gz
- 最新アプリver: v1.202


2026-05-23 09:40 更新(ce-2026-05-23-02 / app v1.200 → v1.201)

実施内容(1件・新機能 / ActiveBoard 踏襲):
1. ce-2026-05-23-02 朝日報で Enter 確定時に TaskDetailModal 自動オープン(作業中追加と同じ動き)
- 要望: 「朝日報でタスクを新規で入れたときに、作業中のときにタスク追加したときと同じようにモーダル表示させてほしい」
- 新規関数 handleTaskLineEnter(idx)app/(dashboard)/tasks/work-log/morning/page.tsx に追加
- 各タスク入力欄の Enter キーで呼び出し → 行のテキストを autoRegisterMemoTasks に通して分岐処理:
- 既存 base/routine 同名で既に紐付け済み → 何もしない(重複処理回避)
- 新規 base 作成 → saveTasks + baseTaskIds + setTimeout で setSelectedTask → TaskDetailModal 自動オープン
- 既存 base 同名 → baseTaskIds + モーダル(推定時間確認/編集用・ActiveBoard 踏襲)
- 定例タスク同名 → selectedRoutineIds に追加(routine は TaskDetailModal 対応外のためモーダル無し)
- 既存の onKeyDown Enter で「最終行なら addTaskLine」する動きは維持
- 送信ボタン押下時の autoRegisterMemoTasks 一括登録は変更なし(Enter で先行登録済みは alreadySelectedIds で重複処理されない設計)

主な編集ファイル:
- app/(dashboard)/tasks/work-log/morning/page.tsx(関数1個追加 + onKeyDown 1行追加)
- lib/changelog.ts(1件追記)/ CLAUDE.md(最新スタンプ)

バックアップ:
- post-deploy: 2026-05-23_085431_post-deploy.tar.gz (v1.201 確定)

本番URL確認: ✅ HTTP 200(home/ / tasks/work-log/morning/ / tasks/work-log/active/)

退化防止: ActiveBoard / start / TaskDetailModal / autoRegisterMemoTasks / ce-2026-05-23-01 のクリックハンドラ修正 / WorkLogDock / ChangelogModal / AppVersionBadge すべて無変更

最新スタンプ:
- 最新changelog: ce-2026-05-23-02
- 最新baseline: 2026-05-23_085431_post-deploy.tar.gz
- 最新アプリver: v1.201


2026-05-23 09:00 更新(ce-2026-05-23-01 / app v1.199 → v1.200)

実施内容(1件・バグ修正 / 3経路一括):
1. ce-2026-05-23-01 作業中画面でタスク名クリック時にモーダルの中身が空になるバグを修正
- 報告: 「作業中画面で追加したタスクのタスク名押してもモーダル出ない(中身空)。1つ目はOK、2つ目だとできなかった」+ スクショ(ヘッダ「未着手」+ 名前 + 閉じるボタンだけのモーダル)
- 真因: クリックハンドラ (1214-1226) と旧モーダル baseTask 解決 (1651-1655) の両方で名前一致 fallback に isMineAssignee 縛りがあり、新規追加直後 / 担当者ゆらぎで null になると Body の {baseTask && (...)} / {routine && (...)} 両方スキップ → 「ヘッダ+閉じるボタンだけ」表示
- 修正1 クリックハンドラ: 解決順を「sourceId一致 → 自分担当優先名前一致 → 全 base 名前一致 → 旧モーダル」に厳密化。isMineAssignee 単独依存を撤廃
- 修正2 旧モーダル baseTask 解決: 自分担当優先 → 全 base 名前一致 の順で fallback 追加
- 修正3・退化防止 旧モーダル Body に baseTask/routine 両方 null 時のフォールバック表示を追加(種別/紐付けID/累計時間 +「タスクシート開いてリロードすると詳細表示」案内)。Footer リンクも常時表示。今後の解決失敗時に「中身空」が構造的に再発しない

主な編集ファイル:
- components/tasks/work-log/ActiveBoard.tsx(3箇所)
- lib/changelog.ts(1件追記)/ CLAUDE.md(最新スタンプ)

バックアップ:
- post-deploy: 2026-05-23_084846_post-deploy.tar.gz (v1.200 確定)

本番URL確認: ✅ HTTP 200(home/ / tasks/work-log/active/)

退化防止: WorkLogDock(ce-2026-05-16-04 右下化) / ChangelogModal+AppVersionBadge(ce-2026-05-16-03) / addExistingRoutineTask(ce-2026-05-15-02) / estimateMinutes修正(ce-2026-05-16-01) すべて無変更

最新スタンプ:
- 最新changelog: ce-2026-05-23-01
- 最新baseline: 2026-05-23_084846_post-deploy.tar.gz
- 最新アプリver: v1.200


2026-05-16 14:40 更新(ce-2026-05-16-04 / app v1.198 → v1.199)

実施内容(1件・UI微調整):
1. ce-2026-05-16-04 作業報告グローバルドックの表示位置を下部中央 → 右下に変更
- 要望: 「表示場所は右下がいいな」(ce-2026-05-16-02 で追加した作業報告ドック対象)
- 変更: components/layout/WorkLogDock.tsx ラッパーを fixed bottom-0 inset-x-0 ... justify-centerfixed bottom-3 right-3 ... justify-end
- 維持: 小画面オーバーフロー対策 max-w / pointer-events 透過 / 表示条件(進行中セッション時のみ・/tasks/work-log 配下非表示)は変更なし
- 競合確認: ActiveBoard 作業停止/終了フローティング(bottom-6 right-6 z-40)とは画面排他のため競合なし。ドックは z-50

主な編集ファイル:
- components/layout/WorkLogDock.tsx
- lib/changelog.ts(1件追記)/ CLAUDE.md(最新スタンプ)

バックアップ:
- post-deploy: 2026-05-16_153822_post-deploy.tar.gz (v1.199 確定)

本番URL確認: ✅ HTTP 200(home/ / tasks/work-log/active/)

退化防止: ChangelogModal/AppVersionBadge(ce-2026-05-16-03) / WorkLogDock本体機能 / ActiveBoard / estimateMinutes修正 すべて無変更

最新スタンプ:
- 最新changelog: ce-2026-05-16-04
- 最新baseline: 2026-05-16_153822_post-deploy.tar.gz
- 最新アプリver: v1.199


2026-05-16 12:10 更新(ce-2026-05-16-03 / app v1.197 → v1.198)

実施内容(1件・改善 / SCALE CRM 方式踏襲):
1. ce-2026-05-16-03 ver バッジ押下で更新履歴をその場モーダル可視化 + サイドバー更新履歴セクション撤去
- 要望: 「SCALE CRM 参考に下の ver 押したら何が変わったか可視化できる体制に。設定するから更新履歴セクションは削除でOK」
- 参考元: SCALE CRM service.jsshowCoCreateVersionHistory()(左下バッジ→変更履歴モーダル)
- 新規 components/layout/ChangelogModal.tsx: CHANGELOG を新しい順に整形。最新を青ハイライト+「← 今のバージョン」。各行 ver番号/カテゴリ/タイトル/日付、クリックで summary+details+scope 展開。Esc/背景で閉じる
- 新規 components/layout/AppVersionBadge.tsx: ver 表示共通化。旧 <a href="/changelog"><button> 化しモーダルtrigger。className で Header/Sidebar 見た目踏襲
- 変更: Header.tsx / SystemSidebar.tsx のver リンク → <AppVersionBadge />(ページ遷移廃止)
- 撤去: systems.ts(SystemId型 / 全体グループ / id=changelog定義 / FileClock未使用import)、always-allowed-systems.ts(空Set化)、app/(dashboard)/changelog/page.tsx ディレクトリ削除(モーダルが完全上位互換・内部遷移リンク0件確認済)
- /changelog 直アクセス時は Next 404 not-found(Cloudflare静的配信のためHTTPは200・導線無し・実害なし)

主な編集ファイル:
- 新規: components/layout/ChangelogModal.tsx / components/layout/AppVersionBadge.tsx
- 変更: components/layout/Header.tsx / components/layout/SystemSidebar.tsx / lib/systems.ts / lib/always-allowed-systems.ts
- 削除: app/(dashboard)/changelog/page.tsx
- lib/changelog.ts(1件追記)/ CLAUDE.md(最新スタンプ)

バックアップ:
- post-deploy: 2026-05-16_103309_post-deploy.tar.gz (v1.198 確定)

本番URL確認: ✅ HTTP 200(home/ / tasks/work-log/active/ / tasks/list/)。/changelog は撤去(404 not-found)

退化防止: WorkLogDock / ActiveBoard / estimateMinutes修正(ce-2026-05-16-01) は一切変更なし。lib/changelog.ts 過去エントリ内 href:/changelog は履歴データのため温存

最新スタンプ:
- 最新changelog: ce-2026-05-16-03
- 最新baseline: 2026-05-16_103309_post-deploy.tar.gz
- 最新アプリver: v1.198


2026-05-16 10:50 更新(ce-2026-05-16-02 / app v1.196 → v1.197)

実施内容(1件・新機能):
1. ce-2026-05-16-02 作業報告グローバルドック(全ページ下部バー + ポップアウト小窓)を追加
- 要望: 「作業報告をずっと使う。Base内で他を開いている時/他アプリ開いている時も下にバーが出て押したら飛べると最高。常用するものだから」
- 新規: components/layout/WorkLogDock.tsx を作成し app/(dashboard)/layout.tsx に組み込み(全 dashboard 配下に表示)
- 表示条件: ログイン済 かつ 進行中セッション(endedAt=null)あり かつ /tasks/work-log 配下以外(重複回避)
- 内容: 状態ドット(作業中=緑/停止中=琥珀)/ 計測中タスク名(計測中→進行中→未完了→セッション名の優先度)/ 経過時間(pause控除・ActiveBoard と同一 pausedDurationMs ロジック)。クリックで /tasks/work-log/active
- ポップアウト: Document Picture-in-Picture API(Chrome/Edge 116+)で 300x160 常時最前面小窓。タスク名+大タイマーを毎秒同期。小窓クリックで本体タブへフォーカス+作業中画面へ。非対応ブラウザはアラート案内
- データ層: 1秒間隔で localStorage の sessions / active-progress を再読込(既存 work-log データ層を流用・新規KVなし)

主な編集ファイル:
- components/layout/WorkLogDock.tsx(新規)
- app/(dashboard)/layout.tsx(import 1行 + ドック1行)
- lib/changelog.ts(1件追記)/ CLAUDE.md(最新スタンプ)

バックアップ:
- post-deploy: 2026-05-16_094420_post-deploy.tar.gz (v1.197 確定)

本番URL確認: ✅ HTTP 200(home/ / tasks/work-log/active/ / tasks/routines/ / tasks/list/)

退化防止: ActiveBoard.tsx / start・active ページ / ce-2026-05-16-01 の estimateMinutes 修正は一切変更なし

最新スタンプ:
- 最新changelog: ce-2026-05-16-02
- 最新baseline: 2026-05-16_094420_post-deploy.tar.gz
- 最新アプリver: v1.197


2026-05-16 07:40 更新(ce-2026-05-16-01 / app v1.195 → v1.196)

実施内容(1件・バグ修正 / 5経路一括):
1. ce-2026-05-16-01 定例タスクの目安時間が作業開始/作業中で反映・カウントされないバグを修正
- 報告: 「作業開始報告や作業中などで定例タスクを追加しても、定例タスクは目安時間が反映&カウントされてない」
- 実データ確認: 定例タスク 43件中 39件に estimateMinutes 設定済(データは正常)→ 原因はコード側の構造的欠陥と確定
- 真因1 ActiveBoard 初期化: start.tasks テキスト処理が base 名前一致のみで routine 判定が無く、定例が source='start' になり estimateMinutes を引けなかった → 定例名一致なら source='routine' + sourceId 紐付けを追加
- 真因2 morning.todayTasks も同じ欠落 → 同様に routine 判定追加(source='morning' 化を防止)
- 真因3 進捗ペースカードの getEstMssource==='routine' && sourceId を厳密要求し名前 fallback 無し → taskText 名前一致で base/routine の est を拾う fallback 追加
- 真因4 renderRow の estimateMin が baseMatch?.est ?? routineMatch?.est 連結で、同名 base に est=0 が入ると 0 が valid 扱いされ定例 est を握りつぶしていた → 「正の数値のみ有効」+ source==='routine' 時 routine 優先に変更
- 真因5 start/page の expected 合算が tasks.forEach で base 発見時に return し routine を見ず、同名 base に est 無いと定例 est が合算されなかった → base に est 無ければ routine の est を採用

主な編集ファイル:
- components/tasks/work-log/ActiveBoard.tsx(初期化2箇所 + getEstMs + renderRow)
- app/(dashboard)/tasks/work-log/start/page.tsx(expected 合算)
- lib/changelog.ts(1件追記)/ CLAUDE.md(最新スタンプ)

バックアップ:
- post-deploy: 2026-05-16_074020_post-deploy.tar.gz (v1.196 確定)
- ※ デプロイ1回目 Cloudflare 502(一時障害)→ 2回目で成功

本番URL確認: ✅ HTTP 200(home/ / tasks/work-log/active/ / tasks/work-log/start/)

退化防止: addExistingRoutineTask / addExistingBaseTask / マイタスク・定例追加UI(ce-2026-05-15-02)は変更なし

最新スタンプ:
- 最新changelog: ce-2026-05-16-01
- 最新baseline: 2026-05-16_074020_post-deploy.tar.gz
- 最新アプリver: v1.196


SCALE Base 最新基準点(2026-05-15 更新)

2026-05-15 14:00 更新(ce-2026-05-15-02 / app v1.194 → v1.195)

実施内容(1件・新機能):
1. ce-2026-05-15-02 作業中画面で定例タスクを後から追加できるUIを追加
- 背景: これまで作業中ボードはマイタスクだけ後追い追加可能で、定例(routine)タスクは作業開始時の選択にしか追加できなかった。「あとから定例も追加したい」というFBを反映。
- 新規UI: マイタスクUIの直下に「定例タスク(自分担当・周期内未完了 N件)」アコーディオン。展開すると 頻度ラベル / タスク名 / 推定時間 / 「+ 追加」ボタン の行を表示。
- 表示条件: isMineAssignee(b, user.name) && !isRoutineDoneInCurrentPeriod(b)(自分担当 + 現在の周期で未完了 / lastDone を周期単位で判定)
- 新規関数: addExistingRoutineTask(routineId) を追加。addExistingBaseTask と同じパターンで、既存同IDが progress にあれば優先タスク領域に持ち上げ、なければ優先領域末尾に新規挿入。
- 追加済み表示: progress に同 routineId が既に存在し優先領域に居る場合は、ボタンを「追加済」表示で disabled(重複追加防止)
- import 追加: isRoutineDoneInCurrentPeriod / FREQ_LABELS を lib/tasks-api から追加 import
- 既存機能 addExistingBaseTask / マイタスク追加UI は変更なし(退化なし)

主な編集ファイル:
- components/tasks/work-log/ActiveBoard.tsx
- lib/changelog.ts(1件追記)
- CLAUDE.md(最新スタンプ)

バックアップ:
- pre-deploy: 2026-05-15_095350_pre-deploy.tar.gz
- post-deploy: 2026-05-15_095420_post-deploy.tar.gz (v1.195 確定)

本番URL確認: ✅ HTTP 200(base.scale-group.co.jp/home/ / tasks/work-log/active/)

最新スタンプ:
- 最新changelog: ce-2026-05-15-02
- 最新baseline: 2026-05-15_095420_post-deploy.tar.gz
- 最新アプリver: v1.195


2026-05-15 07:36 更新(ce-2026-05-15-01 / app v1.193 → v1.194)

実施内容(1件・バグ修正):
1. ce-2026-05-15-01 作業開始報告「今日完了したタスク」に他人担当が混入するバグを修正
- 真因: bottomTasks.forEach(b => { if (b.lastDone === today) ... }) で担当者チェックなし → 他メンバーが今日やった routine が自分の「今日完了」集合に混入
- 修正1: todayCompletedRoutineIds 構築箇所に isMineAssignee(b, user.name) 追加
- 修正2: prevCompletedRoutineIds(過去完了非表示用)も同様に修正
- 修正3・防御: 朝日報外の todayCompletedNames を completedItems に追加する際に isMineAssignee(matched, user.name) チェック追加
- 修正4・防御: todayCompletedRoutineIds → completedItems 追加時も isMineAssignee チェック追加

主な編集ファイル:
- app/(dashboard)/tasks/work-log/start/page.tsx
- lib/changelog.ts(1件追記)
- CLAUDE.md(最新スタンプ)

バックアップ:
- pre-deploy snapshot: deploy.sh が自動取得
- post-deploy: 2026-05-15_073643_post-deploy.tar.gz (v1.194 確定)

本番URL確認: ✅ HTTP 200(base.scale-group.co.jp/home/ / tasks/work-log/start)

最新スタンプ:
- 最新changelog: ce-2026-05-15-01
- 最新baseline: 2026-05-15_073643_post-deploy.tar.gz
- 最新アプリver: v1.194


SCALE Base 最新基準点(2026-05-14 更新)

2026-05-14 13:36 更新(ce-2026-05-14-01 / app v1.192 → v1.193)

実施内容(1件・バグ修正):
1. ce-2026-05-14-01 マイタスクの「+ 追加」ボタン無反応バグを修正
- 真因: addExistingBaseTask の重複判定で progress.some(p => p.sourceId === id || p.taskText === t.name) を使用 → 定例(routine)と同名 base が共存するとき taskText 同名で全件無反応で弾かれていた
- 修正1: 重複判定を sourceId === id && source === 'base' のみに変更(同名違いタスクは別物として独立追加可)
- 修正2: 既存同 base が見つかったら return ではなく isSessionPriority=true にして優先タスク領域に「持ち上げる」動作に変更(押下で必ず反応)

主な編集ファイル:
- components/tasks/work-log/ActiveBoard.tsx
- lib/changelog.ts(1件追記)
- CLAUDE.md(最新スタンプ)

バックアップ:
- 事前ラベル付き: 2026-05-14_133535_before-mytask-add-fix.tar.gz
- post-deploy: 2026-05-14_133654_post-deploy.tar.gz (v1.193 確定)

本番URL確認: ✅ HTTP 200(base.scale-group.co.jp/home/ / tasks/work-log/active)

最新スタンプ:
- 最新changelog: ce-2026-05-14-01
- 最新baseline: 2026-05-14_133654_post-deploy.tar.gz
- 最新アプリver: v1.193


SCALE Base 最新基準点(2026-05-13 更新)

2026-05-13 12:34 更新(ce-2026-05-13-09 〜 -11 / app v1.189 → v1.192)

実施内容(3件・サイドバー大整理):
1. ce-2026-05-13-09 AIアシスタント機能を削除(アーカイブ退避)
- SystemId 型 + departmentGroups + systems 配列から assistant 削除
- DEMO_USERS の allowedSystems からも削除(大串 / ハヤテ / センリ / 細川)
- 退避: _archived_apps/assistant_20260513/ _archived_apps/lib_assistant_20260513/ _archived_apps/functions_assistant_20260513/
2. ce-2026-05-13-10 Docs → Obsidian にリネーム + 外部アプリ起動化
- systems.ts: id="docs" の name/shortName=Obsidian / icon=Brain / color=#7c3aed / sections=[] / externalUrl=obsidian://open?vault=SCALE-Brain
- external-auth.ts: 非HTTPプロトコル(obsidian://)には auth クエリを付けない early return 追加
- 退避: _archived_apps/docs_20260513/
3. ce-2026-05-13-11 グループ再構成(「事業」新設・「システム開発」廃止)
- 旧「SCALE Lead/品質管理」→「事業」にリネーム + SCALE Build 追加
- 旧「システム開発」グループ廃止(SCALE Build → 事業 / サービス管理 → 全体)
- 「全体」に scale-lead(SCALE CRM)と services(サービス管理)を追加
- 9グループ → 8グループ

新サイドバー構成(8グループ):
- 全体: Task / Obsidian / 管理 / 更新履歴 / PW管理 / 日程調整 / Design Studio / Writing / AI Ops / Data Lake / SCALE CRM / サービス管理
- 事業: SCALE Lead / TERASU / SCALE Build
- マーケティング: X / SEO / HP管理
- 事業戦略: Command Center
- コーポレート: Finance / 契約書対応
- 人事: Recruit / Partners & Academy
- ブランド・PR: Brand & PR
- R&D: R&D Lab

主な編集ファイル:
- lib/systems.ts(SystemId / departmentGroups / Obsidian リネーム / assistant 削除)
- lib/external-auth.ts(obsidian:// プロトコル early return)
- lib/auth-context.tsx(DEMO_USERS から assistant 削除)
- lib/changelog.ts(3件追記)
- CLAUDE.md(最新スタンプ)

アーカイブ退避:
- _archived_apps/assistant_20260513/ (旧 app/(dashboard)/assistant/)
- _archived_apps/docs_20260513/ (旧 app/(dashboard)/docs/)
- _archived_apps/lib_assistant_20260513/assistant-data.ts
- _archived_apps/functions_assistant_20260513/assistant.ts

バックアップ:
- 事前ラベル付き: 2026-05-13_122938_before-section-reorg.tar.gz
- pre-deploy: 2026-05-13_123328_pre-deploy.tar.gz
- post-deploy: 2026-05-13_123400_post-deploy.tar.gz (v1.192 確定)

本番URL確認: ✅ HTTP 200(base.scale-group.co.jp/home/)/ /assistant /docs は 404(退避済・想定通り)

最新スタンプ:
- 最新changelog: ce-2026-05-13-11
- 最新baseline: 2026-05-13_123400_post-deploy.tar.gz
- 最新アプリver: v1.192


2026-05-13 12:02 更新(ce-2026-05-13-01 〜 -08 / app v1.182 → v1.189)

実施内容(8件):
1. ce-2026-05-13-01 アプリバージョン表示(左下/右上)+ 役職表示廃止 + メンバーアイコン Header/Sidebar 反映 + TasksProvider を全ページに広げる
2. ce-2026-05-13-02 アイコン設定モーダル(左下/右上 avatar クリックで起動)
3. ce-2026-05-13-03 画像アップロード対応(256x256 中央クロップ・JPEG 85%・base64)
4. ce-2026-05-13-04 FS + PM → SCALE Lead に統合(PM 削除・FS を改名・externalUrl は scale-fs.pages.dev/login/)
5. ce-2026-05-13-05 TERASU セクション新設(externalUrl: crm.terasu.scale-group.co.jp / SKIP_AUTH_DOMAINS 追加)
6. ce-2026-05-13-06 マイタスク再度セッション内除外 + バッジ削除
7. ce-2026-05-13-07 マイタスク全タスク表示に戻す(重複追加防止は addExistingBaseTask 側で処理)
8. ce-2026-05-13-08 定例タスク累計実働を頻度単位でリセット + 「想定所要時間」→「作業時間」改名

新規ファイル:
- lib/app-version.ts(CHANGELOG.length 連動)
- components/layout/IconPickerModal.tsx

主な編集ファイル:
- lib/changelog.ts(8 件追記)
- lib/systems.ts(FS 改名・PM 削除・TERASU 新設)
- lib/auth-context.tsx(allowedSystems から pm 削除・terasu 追加)
- lib/admin-data.ts(SYSTEM_LABELS / DEPARTMENTS の pm 系を SCALE Lead 系に)
- lib/external-auth.ts(SKIP_AUTH_DOMAINS に crm.terasu.scale-group.co.jp 追加)
- lib/tasks-api.tsx(TaskMember 型に iconImage 追加 / useTasksOptional / getRoutinePeriodStartISO / getPeriodStartForTaskName / FREQ_LABELS に everyday)
- lib/work-log.ts(getAccumulatedMsForTask に sinceISO 引数)
- components/layout/SystemSidebar.tsx(avatar クリック → モーダル + APP_VERSION 表示)
- components/layout/Header.tsx(同上)
- app/(dashboard)/layout.tsx(TasksProvider を全ページラップ)
- app/(dashboard)/tasks/members/page.tsx(MemberAvatar 画像対応)
- components/tasks/work-log/ActiveBoard.tsx(マイタスク表示・頻度リセット・メモタスク案内削除)
- app/(dashboard)/tasks/work-log/{morning,start,end,night,page}.tsx(routine sinceISO 適用・想定所要→作業時間)

バックアップ:
- pre-deploy: 2026-05-13_104941_pre-deploy.tar.gz (直前ベースライン)
- post-deploy: 2026-05-13_120043_post-deploy.tar.gz (v1.189 確定)

本番URL確認: ✅ HTTP 200(base.scale-group.co.jp/home/ / tasks/work-log/* / tasks/routines/ など)

最新スタンプ:
- 最新changelog: ce-2026-05-13-08
- 最新baseline: 2026-05-13_104941_post-deploy.tar.gz
- 最新アプリver: v1.189(CHANGELOG.length 連動・Header/Sidebar 左下に表示)

緊急対応履歴(2026-05-11)

定例タスク KV データロス → audit_log から 81件復元
- 16:00 頃 ユーザーが /tasks/routines を見たら 0 件
- 原因不明(誰かが UI 経由で全削除? KV に空配列が PUT された)
- 対応: scale-task-cron worker の /data/audit_log から「定例追加 / 編集」履歴 123件を解析 → 重複排除して 81件のタスク名復元
- 担当者は名前から自動推定(大串 / 細川 / 丹羽 / あやか / 二宮 / 今井 / 石田 / 柴田)
- frequency は名前パターンから推定(「週次 / 毎週 / 今週」→ weekly、それ以外 → daily)
- estimateMinutes / dayOfWeek / link / 詳細メモ は失われたまま → ユーザー側で再設定必要
- memo に「⚠️ audit_log から復元(2026-05-11 16:25)frequency/想定時間等は要再設定」と明記
- 単一障害点: KV のみで bottom_tasks を保持・localStorage キャッシュなし → 対策案として F3 JSON バックアップに含めるなど検討余地

SCALE Base 最新基準点(2026-05-04)

新しいセッションで scale-base を編集する Claude は必ずこのノートを読む。
ここに書かれた「現状の最新版」を起点にして編集すること。
不一致を見つけたら、ここに書かれているスナップショットから復元する。

正本ローカルパス(2箇所衝突に注意)

唯一の正本(必ずここを編集する):

/Users/oogushiyuuki/Library/CloudStorage/GoogleDrive-y-ogushi@scale-group.co.jp/マイドライブ/AI/scale-base/

注意: 2026-05-04 までは /Users/oogushiyuuki/scale-base/ も存在していたが、これは古いコピーのため /Users/oogushiyuuki/scale-base_archived_20260504_was_old/ にリネーム済。直接の編集対象から除外。

別セッションが「~/scale-base が古い」と報告してきたら、この最新基準点ノートと配置マップを更新するように指示すること。


最新基準スナップショット

項目
ラベル 2026-05-04-baseline-final
タイムスタンプ 2026-05-04_091310
取得日時 2026-05-04 09:13 JST
保存先(Primary) /Users/oogushiyuuki/Library/CloudStorage/GoogleDrive-y-ogushi@scale-group.co.jp/マイドライブ/AI/scale-base-backups/scale-base_2026-05-04_091310_2026-05-04-baseline-final.tar.gz
保存先(Local) /Users/oogushiyuuki/scale-base-backups/scale-base_2026-05-04_091310_2026-05-04-baseline-final.tar.gz
サイズ 1.97 MB

復元コマンド

# 1. 一覧確認
bash /Users/oogushiyuuki/Library/CloudStorage/GoogleDrive-y-ogushi@scale-group.co.jp/マイドライブ/AI/scale-base/scripts/snapshot.sh --list | grep baseline

# 2. このスナップショットから復元
bash /Users/oogushiyuuki/Library/CloudStorage/GoogleDrive-y-ogushi@scale-group.co.jp/マイドライブ/AI/scale-base/scripts/snapshot.sh --restore=2026-05-04_091310

# 3. /tmp/scale-base-restore-2026-05-04_091310/ に展開される

この基準点に含まれる機能(2026-05-04 時点)

サイドバー構成(systems.ts)

  • 全体: AIアシスタント / Task / サイト一覧 / Design Studio / Writing / Docs / 管理 / 更新履歴 / PW管理 / 日程調整 / AI Ops / Data Lake
  • 各部署: X (30) / SEO (14) / HP管理 (13) / Command Center (6) / Recruit (14) / Finance (17) / サービス管理 (7) / SCALE CRM (10) / Brand & PR (8) / R&D Lab (8) / Partners (7) / Contracts (1)
  • 外部リンク: FS (scale-fs.pages.dev) / PM (scale-pm.pages.dev) / SCALE Lead (lead.scale-group.co.jp/base/)

Task システム(5項目構成・変更禁止)

  • 作業報告 → /tasks/work-log
  • タスク管理 → /tasks/list
  • レポート → /tasks
  • カレンダー → /tasks/calendar
  • 設定 → /tasks/settings

確定済み機能(直近 1週間)

  • 朝日報の chip 機能(残時間 / 超過 / 記載なしクリック→Picker)
  • 累計時間集計(複数セッション跨ぎ)
  • 超過警告(+30分超過 赤色表示)
  • 作業中ボード: 通常 / 定例(PJT別)/ マイタスク(朝日報未選択)の3セクション
  • 定例タスク: 複数担当 + インライン編集 + 月最終営業日対応
  • autoRegisterMemoTasks: bottomTasks 渡しで重複生成防止
  • クロスドメイン認証ブリッジ(withAuthQuery + AuthGuard)
  • changelog.ts: 3049+ 行の全履歴 + getCategoryLabel/getCategoryColor 関数(保護資産)

2026-05-04 当日の変更

  • 作業開始報告の「前回セッションで進行中タスク」セクション削除(ユーザー要望)
  • EstimateMinutesPicker の自由入力を「時間+分」2フィールドに(8時間入力時の不便解消)
  • タスクリマインド全停止(scale-task-cron の cron トリガー = [] に)
  • 朝06:00 リマインド停止
  • 09/12/15時 フォローアップ停止
  • KV API は維持
  • Finance を独立プロジェクト scale-finance に完全分離(10:30 / ce-2026-05-04-03)
  • 4/29 に独立化したものの Base に accounting 17ページが残っていた状態を解消
  • app/(dashboard)/accounting/_archived_apps/accounting_20260504/
  • lib/finance-data.ts / lib/legal-data.ts_archived_apps/lib_accounting_20260504/
  • lib/systems.ts accounting エントリを sections=[] + externalUrl=https://finance.scale-group.co.jp/
  • lib/subnav-groups.ts accounting 4グループ削除
  • 大串のみアクセス可(細川/経営部署/経理部署から accounting 権限除外)
  • スナップショット: 2026-05-04_102300_before-finance-extraction.tar.gz
  • Finance 独自ドメイン finance.scale-group.co.jp 紐付け完了(10:55 / ce-2026-05-04-04)
  • Cloudflare Pages > scale-finance > Custom domains で Active / SSL enabled
  • lib/systems.ts の externalUrl を https://finance.scale-group.co.jp/ に切替
  • DNS: 104.21.26.231 / 172.67.168.147 / HTTPS 200 / title=SCALE Finance
  • 命名統一: crm / form / terasu.scale-group.co.jp と同じパターン
  • scale-finance 全17ページ 編集機能実装(11:00 頃)
  • lib/finance-store.ts 新規(localStorage 永続化)
  • components/finance/EditableCell.tsx + RowActions.tsx(追加/削除/リセット)
  • 17ページ全部 EditableCell 対応(売上 / 経費 / 請求書 / クライアント / パートナー / 個人顧客 / 経費マスタ / キャッシュフロー / カレンダー / 契約書 / 税務法務 / レポート / アシスタント / 設定 / ダッシュボード)
  • X を独立プロジェクト scale-x に完全分離(13:00 / ce-2026-05-04-05)
  • 4/29 に独立化したものの Base 側に X コードが30+ページ残っていた状態を解消(Finance と同パターン)
  • scale-x: SystemSidebar 実装(5グループ + Pilot 2タブ + ダッシュボード = 全19セクション)
  • Base 退避: app/(dashboard)/x/ → _archived_apps/x_20260504/
  • Base 退避: components/x/ / lib/x-* / functions/api/x-generate.ts も全て _archived_apps へ
  • lib/systems.ts x エントリを sections=[] + externalUrl
  • lib/subnav-groups.ts x グループ削除
  • スナップショット: 2026-05-04_130015_before-x-extraction.tar.gz
  • X 新プロジェクト scale-x-app + 独自ドメイン x.scale-group.co.jp(13:40 / ce-2026-05-04-06)
  • scale-x.pages.dev で AuthGuard isLoading 永遠 true 問題で「This page couldn't load」エラー → 新規プロジェクトで解決
  • /Users/oogushiyuuki/.../マイドライブ/AI/scale-x-app/ 新規作成(scale-x コピー)
  • AuthGuard 素通り化(暫定・XAuthProvider の DEV_MODE 既定 true で実質ログイン不要)
  • SystemSidebar 実装(5グループ + Pilot + ダッシュボード = 19セクション)
  • Cloudflare Pages 新規プロジェクト scale-x-app 作成
  • 独自ドメイン x.scale-group.co.jp Active / SSL enabled
  • Base externalUrl を https://x.scale-group.co.jp/ に最終切替
  • 旧 scale-x.pages.dev は放置(後日削除可)
  • SCALE CRM (id: crm) を Base から完全削除(14:12 / ce-2026-05-04-07)
  • 4/29 ce-04-29-35 で scale-base-crm.pages.dev に分離宣言したものの Base 内に id: crm 残骸(10セクション)が残存
  • app/(dashboard)/crm/_archived_apps/crm_20260504/ 退避
  • lib/crm-data.ts / functions/api/crm.ts も退避
  • lib/systems.ts から id: 'crm' エントリ + SystemId 型から 'crm' + departmentGroups から 'crm' を削除
  • lib/subnav-groups.ts の crm グループ削除
  • lib/auth-context.tsx 大串/細川/センリ の allowedSystems から 'crm' 削除
  • サイドバーから「SCALE CRM」表示が完全消滅(externalUrl 化ではなく削除)
  • scale-base-crm.pages.dev は直URLで存在継続(後日削除可)
  • スナップショット: 2026-05-04_141100_before-crm-deletion.tar.gz
  • サイドバー表示名: SCALE Lead → SCALE CRM(14:20 / ce-2026-05-04-08)
  • id=scale-lead は互換性のため維持(name/shortName のみ変更)
  • Base 独自ドメイン base.scale-group.co.jp 紐付け + 全11プロジェクトのリンク更新(14:55 / ce-2026-05-04-09)
  • Cloudflare Pages > scale-base > Custom domains で Active / SSL enabled
  • sed 一括置換: scale-base.pages.dev → base.scale-group.co.jp(finance/x-app/base-crm/rnd/contracts/brand/command/partners/hp-admin/seo/recruit)
  • 全12プロジェクト再デプロイ完了 / 旧 scale-base.pages.dev も並行稼働継続(後方互換)
  • SCALE CRM externalUrl 切替(15:05 / ce-2026-05-04-10)
  • 旧 lead.scale-group.co.jp/base/ → 新 crm.scale-group.co.jp/
  • SKIP_AUTH_DOMAINS 追加で URL クリーン化(15:15 / ce-2026-05-04-11)
  • lib/external-auth.ts: 独自認証ドメイン(crm/lead.scale-group.co.jp)に ?auth= クエリを付けない
  • SCALE CRM クリック → きれいな https://crm.scale-group.co.jp/
  • SCALE Build セクション追加(15:50 / ce-2026-05-04-12)
  • lib/systems.ts に id=build エントリ(システム開発グループ先頭)
  • externalUrl: https://build.scale-group.co.jp/ / SKIP_AUTH_DOMAINS にも追加
  • 独自ドメイン4兄弟完成: base / finance / x / build .scale-group.co.jp
  • 作業報告のセッション間引き継ぎを KV API 化(17:30 / ce-2026-05-04-13)
  • 独自ドメイン切替で localStorage が分離して引き継ぎが消える事故への根本対応
  • scale-task-cron worker に /bridge/next-session + /bridge/tomorrow-plan エンドポイント新設(GET/POST/DELETE・TTL 48h)
  • lib/work-log-bridge.ts 新規 / morning・end・night の3ファイルを bridge ヘルパー経由に
  • KV 優先・localStorage フォールバックの二重書き込みフェーズ(後方互換維持)
  • スナップショット: 2026-05-04_172145_pre-deploy.tar.gz
  • 5独立プロジェクトにサイドバー実装(19:30 / ce-2026-05-04-14)
  • 4/29 解体後にサイドバー欠落していた独立プロジェクトのうち利用頻度高い5つを修復
  • 対象: scale-base-crm / scale-command / scale-rnd / scale-hp-admin / scale-seo
  • scale-x-app をテンプレに header + sidebar + main の flex 構造を統一
  • 各プロジェクトに components/layout/SystemSidebar.tsx 新規・app/layout.tsx を flex 化
  • scale-command は AuthGate.tsx 内 render なので AuthGate を編集(SubNav 維持)
  • 全5URL HTTP 200 確認済み
  • 残り4(contracts / brand / partners / recruit)は別セッションで対応予定

他セッションが編集する時の必須手順

1. 編集前

  • このノートを読む
  • 「最新基準点に含まれる機能」を確認
  • もし現状が基準点と乖離していたら → 復元コマンドでまず戻す

2. 編集中

  • _SCALE_全システム実装ルール の必須ルールを守る
  • Read → Edit のみ(配列全置換禁止)
  • changelog.ts の編集は append のみ
  • 末尾の getCategoryLabel / getCategoryColor は触らない
  • Task ナビ構成(5項目)は変更禁止

3. 編集後

  • 必ず bash scripts/deploy.sh でデプロイ(pre/post snapshot 自動取得)
  • lib/changelog.ts 最上段にエントリ追加
  • _SCALE_Base_設計書 の該当箇所を更新
  • このノート(最新基準点)の baseline_ts と「2026-05-XX 当日の変更」を更新

4. 大きな変更前

  • bash scripts/snapshot.sh --label=before-<作業名> でラベル付きスナップショット
  • 復元できる体制を確保してから編集

関連ノート

  • _SCALE_Base_設計書 — 最新の SCALE Base 仕様
  • _SCALE_全システム実装ルール — 退化禁止・事故防止ルール
  • _SCALE_全システム配置マップ — 全システム配置・パス
  • /Users/oogushiyuuki/Library/CloudStorage/GoogleDrive-y-ogushi@scale-group.co.jp/マイドライブ/AI/scale-base/CLAUDE.md — Project CLAUDE.md
  • /Users/oogushiyuuki/Library/CloudStorage/GoogleDrive-y-ogushi@scale-group.co.jp/マイドライブ/AI/scale-base/AGENTS.md — Next.js 16 ルール

基準点 更新履歴

日付 スナップショット 内容
2026-05-04 2026-05-04_091310_2026-05-04-baseline-final 初版・ラベル付きベースライン取得(タスクリマインド停止・自由入力2フィールド化・前回セッション継承UI削除など3件反映後)