[{"data":1,"prerenderedAt":341},["ShallowReactive",2],{"content-/textbook-part2-review-response":3,"all-pages-for-dir":339,"og-image-/textbook-part2-review-response":340},{"id":4,"title":5,"body":6,"category":320,"description":321,"extension":322,"meta":323,"navigation":324,"ogImage":325,"path":326,"project_name":327,"published":328,"publishedAt":329,"seo":330,"stem":331,"tags":332,"todo":325,"unpublished":328,"updatedAt":325,"__hash__":338},"pages/2026-05/2026-05-19/textbook-part2-review-response.md","教科書 Part 2 のユーザーレビューに順次対応：CFWS 回帰テスト化と figure 流用の判断",{"type":7,"value":8,"toc":303},"minimark",[9,14,27,30,33,36,40,43,51,58,69,79,82,86,89,102,113,120,124,127,134,137,141,144,155,158,161,164,168,171,178,181,188,199,205,208,211,218,221,225,228,231,236,239,243,246,249,252,258,262,265,289,293,300],[10,11,13],"h2",{"id":12},"朝518-の積み残しメモを開いた","朝、5/18 の積み残しメモを開いた",[15,16,17,18,22,23,26],"p",{},"朝一でリポジトリに座って、まず ",[19,20,21],"code",{},"memo/2026-05-18/00-backlog.md"," を Claude Code に読ませた。前日の自分が10件強の積み残しを書き出して優先度順に並べてくれていたので、上から拾えばいい状態になっていた。最優先には CFWS Issue（",[19,24,25],{},".claude/issues/2026-04-14-cfws-com-check-nonzero.md","）の #3・#4 が残っている。連結精算表の COM 検証が一部のセルで非ゼロになる、というやつ。",[15,28,29],{},"「ちょっと確認してください」と軽く渡したつもりだったが、Claude Code に最新の CFWS で COM 検証を回させたら、全 check=0 でクリーンに通ってしまった。4/14 17:10 生成の成果物では再現しない。他のライフサイクル成果物でも検証して、いずれも再現せず。",[15,31,32],{},"issue を立てた時点では確実に再現していた症状が、その後の修正の副産物として消えていたパターン。原因コミットを特定するのは時間がかかるし、いま動いているコードを壊す危険もある。",[15,34,35],{},"とはいえ消すだけで終わらせるのは怖い。同じ症状が別のタイミングで戻ってきたとき、過去 issue が残っていないと、また同じ調査をゼロから始めることになる。",[10,37,39],{"id":38},"テスト書いてるんだから全部回せと決めた","「テスト書いてるんだから全部回せ」と決めた",[15,41,42],{},"ここで一瞬「じゃあ issue クローズで終わりか」と流しかけたが、自分でブレーキを踏んで方針を切り替えた。",[15,44,45,46,50],{},"バグが再現しなくなったときの正しい挙動は、issue を消すことではなく",[47,48,49],"strong",{},"再発したら即落ちる場所にテストを置くこと","だ。Claude Code に「これだからテスト書いてるってことですよね。だから全部やったらいいんじゃないですか。イシューをクローズ扱いにして、テストとして固定化」と返した。",[15,52,53,54,57],{},"Claude Code が既存の ",[19,55,56],{},"verify_excel()"," を再利用して、Dropbox 配下の最新生成 CFWS を全部 smoke test で回す回帰テストを追加してくれた。",[15,59,60,61,64,65,68],{},"pytest を回したら、最初は warning スタックトレースまみれで落ちかけた。原因は ",[19,62,63],{},"verify_cfws_excel.py"," の冒頭で ",[19,66,67],{},"sys.stdout"," をユーティリティ側で上書きしていて、pytest の capture と衝突していたこと。スクリプト単体で実行したときには UTF-8 出力を強制するための副作用が、ライブラリとして import された瞬間にテストランナーの標準出力ハンドリングを破壊する。",[15,70,71,72,75,76,78],{},"「ロジックは純粋関数に閉じ込め、副作用はエントリポイントに集約する」という普段のルールが、ここで効いた。",[19,73,74],{},"__main__"," ガード内に ",[19,77,67],{}," の差し替えを移動させて、import 経由で呼ばれたときには副作用が走らないようにした。再実行で 3 passed、全 PASS。issue は「解決済み（回帰テストで固定化）」に書き換えて閉じた。",[15,80,81],{},"このやり取りで残った教訓は、**「再現しない issue は消すな、テストの代わりにしろ」**の一行に尽きる。",[10,83,85],{"id":84},"教科書-part-2-のユーザーレビュー-implementation-noteshtml-を作業ログにする","教科書 Part 2 のユーザーレビュー — implementation-notes.html を作業ログにする",[15,87,88],{},"CFWS の片付けが終わったところで、ユーザー（自分）から本命の指示が降ってきた。Part 2 のユーザーレビューを順次やってほしい、と。具体的には3タスク。",[90,91,92,96,99],"ul",{},[93,94,95],"li",{},"CH9 の本文字数が 5,020 字で、指示書目安 6,500〜8,500 字の下限に届いていない",[93,97,98],{},"CH7 ↔ CH8 の Part 跨ぎナビが普通の章ナビと同じ見た目で、「ここで Part が切り替わる」というシグナルが弱い",[93,100,101],{},"Part 2 の SVG が足りない章（残り 57 問）への補助図追加",[15,103,104,105,112],{},"ここで自分から追加要件を1つ足した。",[47,106,107,108,111],{},"実装が仕様から逸脱した点や、自分が知っておくべき判断は全部 ",[19,109,110],{},"memo/2026-05-19/implementation-notes.html"," に残し続けてほしい","、と。あとから「なぜここでこの選択をしたか」を辿れるようにする保険。",[15,114,115,116,119],{},"Claude Code に初期化させて、タスクごとに追記していく運用にした。HTML にしたのは、スクショや figure を直接埋め込みたかったからで、Chrome で開けば作業ログとレビュー資料を兼ねられる。後でユーザー（自分）が ",[19,117,118],{},"implementation-notes.html"," を立ち上げるよう Claude Code に頼んで、Chrome のタブで開いてレビューする流れも自然に動いた。",[10,121,123],{"id":122},"タスク1ch9-本文を-5020-7890-字に肉付け","タスク1：CH9 本文を 5,020 → 7,890 字に肉付け",[15,125,126],{},"実測してみたら CH9 は 5,935 字あった。backlog の数字よりは少し多かったが、それでも目安の下限を割っている。Claude Code に「目安範囲内（6,500〜8,500）に収まるよう肉付け、ただし内容を薄めず具体例と数値を増やす方向で」と渡した。",[15,128,129,130,133],{},"肉付けの方針として、抽象的な説明を増やすのではなく、",[47,131,132],{},"既に書かれている論点の具体例を1段深く掘る","ことを指示した。たとえば「営業 CF と純利益の乖離を読む」という節があれば、乖離の代表的なパターンを2つに増やし、それぞれに小さなケーススタディを添える。文字数稼ぎの空文を入れない縛り。",[15,135,136],{},"仕上がりは 7,890 字。目安範囲のど真ん中に着地した。dev server を立てて実機で読んでみたが、付け足された段落が浮いていない。元の論理展開を保ったまま、具体例の解像度だけ上がっている。implementation-notes に「CH9 5,935 → 7,890 字、目安範囲内」と1行記録。",[10,138,140],{"id":139},"タスク2ch7-ch8-の-part-跨ぎナビ","タスク2：CH7 ↔ CH8 の Part 跨ぎナビ",[15,142,143],{},"CH7 は Part 1 の最終章、CH8 は Part 2 の最初の章。今までは普通の「次の章へ」「前の章へ」と同じ見た目で、ユーザーが「ここで Part が変わる」と気づけない状態だった。",[15,145,146,147,150,151,154],{},"Claude Code に「Part 跨ぎ専用のナビ要素を CSS で立てて」と渡した。",[19,148,149],{},"pager--part-transition"," というモディファイアと、",[19,152,153],{},"pager__part-badge"," のスタイルを追加。CH7 章末から CH8 へ進むとき、ボタンに「PART 2 に進む ── 数字を投資判断に変える」というバッジ付きのラベルが出るようにした。",[15,156,157],{},"ここで実装の細かい判断が一つ。バッジを目立たせすぎると章ナビ全体のリズムが壊れるので、色は既存のアクセントカラーを薄く使い、Part 名と副題を縦2段で配置するに留めた。読者が「あ、次の Part に切り替わるんだな」と気づける最低限のシグナル量を狙った。",[15,159,160],{},"Chrome DevTools MCP で実機を開いて、CH7 末尾までスクロールしてスクショを取った。バッジがきちんと表示されている。CH8 側でも逆方向（前章への戻り）を確認して、両方向で Part 跨ぎが正しく見えていることを確認。",[15,162,163],{},"スクショは implementation-notes に貼って残した。同じファイルにビフォー／アフターを並べておくと、レビューする側が言葉だけ読まずに視覚で確認できる。",[10,165,167],{"id":166},"タスク3part-2-の-svg-補強-新規作成しないに方針転換","タスク3：Part 2 の SVG 補強 — 「新規作成しない」に方針転換",[15,169,170],{},"ここが今日の一番の判断ポイントだった。",[15,172,173,174,177],{},"最初は「残り 57 問への補助 SVG を1枚ずつ作る」つもりで構造調査に入った。クイズページ側（18 ページ）を Claude Code に舐めさせたら、ページ側は全問 figure 完備だった。",[47,175,176],{},"「残り 57 問」というのはページ側ではなく、教科書ページ内に埋め込まれた InlineQuiz 側の話だった","と気づいた。",[15,179,180],{},"ここで一度立ち止まる。backlog に書いた過去の自分の「57 問」が、どこの 57 問を指していたのか曖昧になっていた。クイズページ側の問題リストと教科書側の InlineQuiz は別物で、同じ問題コードを持っていても出現場所が違う。backlog を書いたときの自分は「教科書側の InlineQuiz で figure が無い問」を指していたはず、と仮説を立て直す。",[15,182,183,184,187],{},"そこで教科書ページ側の InlineQuiz を全件調査させたら、",[19,185,186],{},"highlight: null","（= figure 未割り当て）の問が 59 問あった。backlog の「57 問」とほぼ一致。仮説が裏取りできた瞬間で、ここから方針転換の根拠が固まった。",[15,189,190,191,194,195,198],{},"ここで方針を切り替えた。",[47,192,193],{},"新規 SVG を1枚ずつ作るのではなく、既存 figure の highlight キーに問を割り当てる","。Part 2 で使われている既存の figure コンポーネント（",[19,196,197],{},"Part2OcfVsNetIncome"," など）は、内部で複数の highlight モードを持っている。問の論点が figure 側の highlight 軸と一致するなら、新しく図を描かなくても figure を再利用して highlight キーを渡すだけで補強できる。",[15,200,201,202,204],{},"最初に CH9 sec-2 のクイズ Q02 で試した。CH8 にある ",[19,203,197],{}," をそのまま CH9 にも渡してみたら、グラフが表示された。同じ問題コードが CH8 で figure 付き、CH9 で figure なしで重複していたパターンで、データ側はもう揃っていた。これが見つかった瞬間に、59 問のうちかなりの割合が既存 figure の流用で片付くと確信した。",[15,206,207],{},"Claude Code に「サブエージェント 3 並列で TS ファイル単位に分担」と指示した。3 並列で走らせて、各サブエージェントが自分の担当 TS ファイルで「どの問題にどの figure の highlight キーを割り当てるか」を決めて書き換える。",[15,209,210],{},"衝突を避けるためファイル単位で分けたのが効いた。同じ figure を2つのサブエージェントが同時に書き換えるリスクは消したが、figure 側の Highlight 型は事前に main エージェント側で一括取得してサブエージェント全員に渡しておいた。共有読み込み専用情報を main で揃え、書き込みだけサブエージェントに分散させる構図。",[15,212,213,214,217],{},"3 並列の結果を回収したあと、各 figure キーがページ側の ",[19,215,216],{},"figureHighlights"," 配列に実在するかを検証させた。サブエージェントは個別の TS ファイルしか見ていないので、ページ側との整合は最後に main で取る。これを抜くと「figure キーが間違っていて画面に何も出ない」事故が起きる。",[15,219,220],{},"整合 OK を確認した上で、dev server で CH9 sec-2 のクイズ、CH10 の OCF クイズ、07-macro のグラフ表示を実機で確認して、想定通り figure が表示されていることを目視で詰めた。",[10,222,224],{"id":223},"図を作らなかった問はふさわしくないってことへの回答","「図を作らなかった問は、ふさわしくないってこと？」への回答",[15,226,227],{},"タスク3が片付いたあと、ユーザー（自分）が一つ質問を投げた。「figure を当てなかった残りの問は、その問題にふさわしくないということなんですか？」",[15,229,230],{},"これは正確には違うので、2つの理由に分けて回答してドキュメント化した。",[232,233,235],"h3",{"id":234},"理由-a既存-figure-の対比軸とクイズの論点軸が一致しない軸ズレ","理由 A：既存 figure の対比軸とクイズの論点軸が一致しない（軸ズレ）",[15,237,238],{},"既存 figure は「営業 CF vs 純利益」「売上 vs 営業利益率」など、特定の2軸の対比で設計されている。クイズの中には「複数年の傾向を時系列で見る」「業界平均との比較」など、figure の軸とは別の論点を問うものがある。軸が合わないところに無理に figure を貼ると、読者に「この図のどこを見ればいいんだ」と迷わせるだけで、教育効果が下がる。",[232,240,242],{"id":241},"理由-bそもそも対応するデータが存在しない","理由 B：そもそも対応するデータが存在しない",[15,244,245],{},"既存 figure はクイズで使う実在企業のデータをそのまま流用している。一方、クイズには架空のシナリオ問題や、まだデータ準備が済んでいない企業の問が混じる。",[15,247,248],{},"データが無い問に対しては、figure を割り当てる前にデータセット側を埋める必要がある。これは別フェーズの作業で、今日の SVG 補強タスクの範囲外。データ収集の優先度を別に立てて、そこから降ろす。",[15,250,251],{},"この A/B の区別を implementation-notes.html の §3-4 として追記した。「B 系統はやった方がいい？」と聞かれたが、「とりあえずいっか。判断だけドキュメントしといて」で着地。後から再評価できる状態にしておく方が、いま全部潰すより費用対効果が高い。",[15,253,254,255,257],{},"判断をドキュメント化するとき大事なのは、「やらなかった理由」を残すことだ。「やったこと」はコミットログを追えばわかるが、「やらなかった理由」はソースのどこにも残らない。半年後の自分や、別の人がリポジトリに入ったとき、",[19,256,118],{}," の §3-4 を読めば「ああ、ここはあえて空けたのか」と即座に理解できる。",[10,259,261],{"id":260},"振り返り今日の判断のキモ","振り返り：今日の判断のキモ",[15,263,264],{},"3つ並べて記録しておく。",[266,267,268,277,283],"ol",{},[93,269,270,273,274,276],{},[47,271,272],{},"再現しない issue はテストに固定化する","。「現状再現せず」で消すのではなく、回帰テストの種にする。CFWS の COM 検証で実践した。検出用スクリプトを ",[19,275,74],{}," ガード内に隔離してから pytest に取り込むのも、副作用を分離する基本動作。",[93,278,279,282],{},[47,280,281],{},"既存 figure の流用判断は「対比軸が合うか」で決まる","。新規作成に走る前に、既にあるものの highlight キーを増やせないかを先に検討する。Part 2 の SVG 補強で実践した。サブエージェント並列に放り込む前に、Highlight 型を main で一括取得してから配るのも肝。",[93,284,285,288],{},[47,286,287],{},"やらない判断こそドキュメント化する","。「とりあえずやらない」を曖昧にしておくと、半年後の自分が同じ調査をやり直す。implementation-notes.html の §3-4 として残したのが今日のハイライト。「やった」はコミットログ、「やらなかった」はノートに残す。",[10,290,292],{"id":291},"税理士会計士視点での応用","税理士・会計士視点での応用",[15,294,295,296,299],{},"顧問先向けの教育コンテンツや確定申告マニュアルでも、図の流用判断は同じロジックで決められる。",[47,297,298],{},"既存の図を再利用するか、新しく描き起こすかは、図の対比軸と説明したい論点の軸が一致しているかどうか","で決まる。軸がズレているところに無理矢理流用すると、読者が「どこを見ればいいか」を見失う。新規作成の前に「いまある図の highlight 軸を増やせないか」を必ず先に検討する。",[15,301,302],{},"また、「再現しない不具合」をどう扱うかも事務所運営に効く。クライアントから「前回起きたあの計算ズレ、今は起きてないんですけど」と言われたとき、issue を消すのではなくチェックリストの一項目に固定化しておくと、再発時に即座に気づける体制になる。月次レビューのテンプレートに「過去の異常パターンが再発していないか」の項目を入れておくのと同じ発想。",{"title":304,"searchDepth":305,"depth":305,"links":306},"",2,[307,308,309,310,311,312,313,318,319],{"id":12,"depth":305,"text":13},{"id":38,"depth":305,"text":39},{"id":84,"depth":305,"text":85},{"id":122,"depth":305,"text":123},{"id":139,"depth":305,"text":140},{"id":166,"depth":305,"text":167},{"id":223,"depth":305,"text":224,"children":314},[315,317],{"id":234,"depth":316,"text":235},3,{"id":241,"depth":316,"text":242},{"id":260,"depth":305,"text":261},{"id":291,"depth":305,"text":292},"dev","5/18 の積み残しから着手して、CFWS の COM 検証 issue を回帰テストに固定化し、教科書 Part 2 の CH9 肉付け／Part 跨ぎナビ／SVG 補強までを Claude Code とサブエージェントに回した一日の記録。","md",{},true,null,"/textbook-part2-review-response","eurekapu-nuxt4",false,"2026-05-19T00:00:00.000Z",{"title":5,"description":321},"2026-05/2026-05-19/textbook-part2-review-response",[333,334,335,336,337],"教科書Part2","回帰テスト","SVG","サブエージェント","判断ドキュメント化","hv4WxNbF336f_JsKu_z9bSFWd-eL0DfqvoyZvzzY5ZQ",[],"https://log.eurekapu.com/og/blog/textbook-part2-review-response.png?v=2026-05-19T00%3A00%3A00.000Z&title=%E6%95%99%E7%A7%91%E6%9B%B8%20Part%202%20%E3%81%AE%E3%83%A6%E3%83%BC%E3%82%B6%E3%83%BC%E3%83%AC%E3%83%93%E3%83%A5%E3%83%BC%E3%81%AB%E9%A0%86%E6%AC%A1%E5%AF%BE%E5%BF%9C%EF%BC%9ACFWS%20%E5%9B%9E%E5%B8%B0%E3%83%86%E3%82%B9%E3%83%88%E5%8C%96%E3%81%A8%20figure%20%E6%B5%81%E7%94%A8%E3%81%AE%E5%88%A4%E6%96%AD&author=Kei%20Komatsu&sig=e80c664cd89e7e7b",1782528839599]