開発の振り返り — 何が起き、どう見つけたか

AI3体+まとめ役1体で1日開発した記録 / 2026-09-04〜05

0. この文書の位置づけ

着手前の計画書は「事前レビューで課題を7件つぶした」ことを実績として挙げていました。 ですが実際には、作り始めてから間違いが出続けました。しかもその大半は 「自動チェックには合格するのに、画面には嘘が出る」種類でした。

つぶした数より、つぶし損ねたものの性質のほうが情報量が多い 事前レビューで防げたのは「考えれば分かること」だけでした。実際に出た間違いは 一つひとつは正しいのに、組み合わせると答えが合わなくなる種類に偏っており、 これは机上のレビューでは原理的に出てきません。 以下は隠さずに書きます。ここを正直に書けることのほうが、計画書の主張より強い実績になると判断しました。

本文の数値はすべて現物から取りました。出どころは作業中の記録、変更履歴、 および自動チェックの実行結果(2026-09-04 実行、全176件合格)です。推測で埋めた箇所はありません。

1. AI3体を同時に動かして、最初に起きたこと

担当を3つに分け、それぞれ別のAIに任せました。

担当受け持ち
担当A会計の計算(限界利益、値引きしてよい下限、損益分岐)
担当B売れ行きの試算と、3つのやり方の比較
担当C画面
まとめ役取りまとめ、変更の記録、担当間の調停

1-1. 動き出した時点で、3体とも自分の担当を知らなかった

まとめ役は担当ごとの指示書を3つ用意し、「3つの画面に上の文章を貼ってください」と依頼しました。 しかし実際に貼られたのは指示書ではなく、その依頼文そのものでした。

実測(担当Aが自分で確認):

3体それぞれの記録を照合したところ
  いずれも同じ時刻に開始
  最初に受け取った文章が3つとも一字一句同じ

つまり3体は、自分がA・B・Cのどれなのかを知らないまま同時に動き出しました。

1-2. 担当が三重にズレた

時刻起きたこと
04:473体が同じ文章で起動。各自が状況を推測し始める
04:56担当Aが「3体とも同格だ」と推測し、名乗り合いの手順を他の2体へ送信。この推測は外れ(まとめ役は別の場所で動いており、3体の記録には現れていなかった)
04:57まとめ役が正式な担当を通知
05:0xまとめ役が、名乗り合いの残骸を見て担当を誤読し、割り当てを入れ替え → さらに撤回して元へ戻す
05:0x担当Bが、ファイルの作成時刻から逆算して自分をAだと判断し、担当Aの領域へ書き込み
誤った推測は、すべて同じ型だった 「痕跡は見たが、それを残した人の意図を確かめていない」型です。 名乗り合いの残骸も、ファイルの作成時刻も、「誰が何のために残したか」を確かめずに判断の根拠に使われました。 起動時の選択(人が3つとも同じ選択肢を選んだ)も、3体を区別しない情報なのに指名と解釈されました。

1-3. 実害と、実害が小さく済んだ理由

実害は1件。担当Bが、担当Aの作ったファイル2つを新規作成のつもりで上書きしました。

処理は取り合いにせず、突き合わせてから決めました。

担当Aの版 : 上限 = (増えた客数 − 元々買う客数) × 1個あたりの利益
担当Bの版 : 上限 = 増えた客数 × 1個あたりの利益 ÷ (増えた客数 + 元々買う客数)   ← 採用

クーポンの費用は「増えた客」にも「元々買う客」にも発生するのに、
利益は増えた客からしか出ない。その非対称を割り算の分母で表現できているのが担当Bの版。
担当Aの版は、元々買う客1人につき利益を丸ごと失う形になっており、罰が重すぎた。
体制上の結論 中身が本格的に書かれる前に解決したため、失われた作業はありません。 再発防止として担当表を1つのファイルに置き、それを唯一の正としました。 あわせて担当同士で役割を交渉しないことを決まりにしました。 当事者同士の交渉は「誰も全体を見ていない状態」を作ります。矛盾に気づいたらまとめ役へ報告し、自分の作業は続ける。

2. 見つかった間違いと、その発見のしかた

誰が見つけたかではなく、どの見方をしたときに出たかが次に使える資産になります。

#何が起きていたかどう見つかったか型
1 勝ち負けの分かれ目を計算する部分が、入力の並び順によって3通りの答えを返していた まとめ役が不合格になるチェックを書いて差し戻し → 担当Bが修正 単体
2 捨てる費用を2回引いていた。値引きしてよい下限価格が、本来より16円低く出ていた 担当Cがおかしな結果から逆算(捨てる費用を100円にしたら成績が下がる、という逆転を観測) 組み合わせ
3 売り切れて引き分けになった場面を「ここから負け始める」と表示していた 担当Aが、他担当の中身を読むだけで発見(1文字も書き換えず)。「同点を負けに数える書き方」から推論し、実測で確認 単体
4 来客の多さを表す倍率が2回かかっていた。画面が調整済みの値を渡すのに、計算側でもう一度掛けていた 担当Bが担当Cの中身をレビュー中に自分の不備として発見。自分のチェックでは出ない条件だった 組み合わせ
5 比較の基準にする値が、画面のつまみを動かすと一緒に動いていた。基準は動いてはいけない 同上 組み合わせ
6 説明文を作るしくみが3つあり、検査を通した正規のものが一度も使われていなかった。画面に出ていたのは無検査の文章 担当Aのレビュー。画面が受け取った文字列をそのまま表示していることから、経路を逆にたどった 組み合わせ
7 比べる相手の利益がゼロ近くを通る場面で、比率が2218%に跳ね上がる 担当A。最初の見立ては誤り(後述 3-4)。追試が失敗したあと自分で見立て直した 組み合わせ
8 20回分の試算では誤差が無視できない大きさだった(ある商材で ±3.4ポイント) 担当Bの自己申告。200回分で測り直して自分から報告した 単体
9 「この条件では両者は一致します」という注意書きが誤り。一致するのは特定の1条件だけで、サービス枠の商材は既定で一致しない 担当Cが実測で発見。まとめ役が担当Bの回答を、条件を確かめずに横流ししていた 組み合わせ
10 定価で売れた割合の平均の出し方が違っていた。1個も売れなかった日が「100%」として混ざり、成績が良く見えていた 担当Aのレビュー。すぐ隣の指標は正しく処理されている不一致から気づいた 組み合わせ
11 同じものを指す名前が2箇所で食い違っていた。つなぐと動かない 担当Aのレビュー。他の受け渡し9本は全部一致しており、名前だけがズレていた 組み合わせ
12 試算に使う日数の組が3種類あり、同じ画面の見出しとグラフが違うデータの数字を出していた 担当Aのレビュー。実測で見出し 13.17% / グラフ 10.66%(2.51ポイント差) 組み合わせ
12件中9件が「組み合わせると答えが合わなくなる」型だった どの担当も、自分の受け持ちの自動チェックは合格させていました。合わなくなったのは、 正しい部品どうしが、互いの前提を少しずつ違えて解釈していた箇所です。 机上のレビューで防げるのは #1・#3・#8 のような単体の型までで、残りはつないでからでないと現れません。 「着手前に7件つぶした」は、実は最も見つけやすい7件をつぶしただけだった可能性が高い。

2-1. 有効だった見方

見方これで出た件数
他の担当の中身を、手を入れずに読むだけで粗探しする(書かない・受け持ちを越えない)6件
おかしな結果から逆にたどる(「捨てる費用を上げたのに成績が下がるのはおかしい」)1件
他人の受け持ちを読んでいて、自分の不備に気づく2件
自分の出した数値を、自分で疑って測り直す1件
できたものを実際に画面に出して読む下記 2-2

2-2. 自動チェックに合格していても、読むと嘘だった文

説明文を作るしくみは、禁止したい言い回し16パターン × 総当たり1008通りで検査していました。 それでも、実際に画面に出して読んだら2件の嘘が見つかりました。

画面に出ていた文何が嘘か
残り480分・在庫33個。この1個を残す価値は202円まで下がっています。 残り8時間の時点で、まだ何も下がっていない。値引きする場面だけの言い回しを、全場面で出していた
エンジンの利益は+13.9%です。 「利益率が13.9%」と読める。実際は相手との差が13.9%
検査は「守るべき条件」で書き、確認は「画面で読む」で行う 文章を一字一句まで固定すると、言い回しを直すたびに不合格になり、検査が改善の足かせになります。 一方、条件の検査だけでは上の2件は永久に合格のまま通ります。 機械には条件を守らせ、嘘かどうかは人が読んで判定するという分担にしました。

3. まとめ役自身のミス

担当側の間違いだけを並べると、取りまとめ側が正しかったように読めます。事実は違います。

3-1. 「最後の時点の下限価格は必ずマイナスになる」という誤ったチェックを書いた

下限価格がマイナスになりうることはこのしくみの主張の一つですが、必ずマイナスになるとは言えません。 計算式そのものは6商材すべてで正しく、誤っていたのは「必ずマイナス」という追加の期待のほうでした(担当Bが実測して指摘)。

商材値引きシール代など捨てる費用最後の時点の下限
唐揚げ弁当8円12円−4円
握り寿司 10貫8円18円−10円
手作りコロッケ 5個8円8円0円
彩り野菜サラダ8円7円+1円

捨てる費用が値引きシール代を下回る商材では、下限はプラスになります。

3-2. 引数の順番を取り違えたまま、常に合格する空のチェックを2件書いた

値を渡す順番を間違えたチェックを書き、0と0を比べるだけの空のチェックになっていました。 合格していましたが、何も検査していませんでした。型の検査を別途かけて初めて発覚しました。

これは担当Aが指摘していた構造と同じだった 担当Aは自分の検査に「サンプル件数の下限」を入れていました。理由は 「サンプルを作る部分が壊れると、何も検査していないのに合格になる」から。 同じ事故が、まとめ役側で別の原因により起きました。 チェックは「落ちること」を確認して初めてチェックになります。

3-3. 勝ち負けの差が一方向にしか動かない、と誤って仮定した

分かれ目を探す処理を「条件が悪くなるほど負けに近づく」という前提で書いていました。 実測では、3つの条件のうち2つで一方向ではありませんでした(途中に谷がある)。

価格への反応の強さを振ったとき
  強い ←                                        → 弱い
  17.8%   9.8%   12.0%   14.1%   5.2%   38.1%      ← 途中で下がって、また上がる

来客の多さを振ったとき
  少ない ←                                      → 多い
  132.7%  294.0%  135.5%  13.2%  9.1%  2.0%        ← 細かく刻むと途中に谷がある

1つの数字では領域を表せないため、負けている区間そのものを返す形に変え、 分かれ目は「いまの設定から見て最も近い境目」と定義し直しました。 実例として、ある商材では旧定義の境目が負けの区間から抜ける側を指しており、 「どこまでズレたら負けるか」の答えとして誤っていました。

3-4. 自分で確かめていない伝聞を、確かめたように他の担当へ渡した

担当Aが中身を読んで報告した懸念を、まとめ役は自分で確かめずに担当Bへ差し戻しました。 担当Aの最初の見立ては「ゼロ除算を防ぐしくみが作動して比率が異常値になる」というもので、これは誤りでした。

結果として担当Bは「作動した形跡を探す」という永久に見つからない方向へ誘導され、 「再現できません」と報告しました。正しい条件は、担当Aが自分の見立ての誤りを訂正して特定しました。

唐揚げ弁当・来客の多さを振ったとき(自動チェックの実行結果)
  0.55倍  一律ルール= −1,726円  エンジン=3,348円  比率=  294.0%
  0.60倍  一律ルール=   −184円  エンジン=3,904円  比率= 2218.8%   ← 相手がほぼトントン
  0.70倍  一律ルール= +2,008円  エンジン=4,728円  比率=  135.5%

  同じ区間を「円の差額」で見ると: 最大 7,053円 / 中央 2,720円(桁は跳ねない)

ゼロ除算を防ぐしくみは一度も作動していない。
相手の利益がゼロ「近く」を通るだけで比率が暴れる。ちょうどゼロである必要はなかった。
伝聞を実測のように渡すと、受け手の探す方向まで誤らせる 「再現できませんでした」と返ってきた時点で疑うべきだったのは、 担当Bの探し方ではなく渡した条件そのものでした。 自分で確かめていない情報は「未確認」と明示して渡す。

3-5. 効果の数字を、誤差なしで公開しようとした

中間判定を当初40回分の試算の平均だけで出していました。 担当Bの自己申告(20回分では誤差が ±3.4ポイントある)を受けて400回分に増やし、 同じ日を突き合わせた差として誤差の幅を併記する形に改めました。

3-6. 比較相手を、比較に使うのと同じデータで調整していた

「値引き率と発動タイミングを総当たりして最も強い一律ルールを選び、それにも勝てるか」という比較で、 調整と採点に同じデータを使っていました。相手にだけ答えを見せてから勝負させたのと同じです。 調整用200回分/採点用200回分(重複なし)に分けて測り直しました。

3-7. 功績を誤って記録した

変更の記録で、クーポン原資の計算式を担当Aの功績として書きましたが、正しくは担当Bの版でした。 上書き事故の経緯を知る前に書いたもので、事実誤認でした。訂正を記録に残しています。

3-8. 公開したあとの2件

ここまでは公開前に見つけたものです。公開後にさらに2件出ました。

何が起きたか経理でいうと
文中の囲みブロックが、意図しないところで改行されていた。見出しラベル用の設定が、文中の強調すべてに当たっていた(4文書で34箇所) 書式設定の適用範囲を広げすぎた
それを直したのに、読む人の画面では直っていなかった。原因はブラウザのキャッシュ。サーバーは正しいものを返していたが、受け取る側には届いていなかった 差し替えたはずの資料が、受け取った側では古い版のまま回覧されていた
この文書自身が説いていることを、公開する当人が飛ばした 2-2 に「できたものを実際に画面に出して読む」と書いておきながら、 まとめ役はサーバーの応答だけを見て「直った」と報告しました。指摘されるまでに2回です。 出す側を確認することと、受け取る側で確認することは別です。 対処として、書式ファイルの名前に中身から計算した文字列を入れ、内容が変われば名前も変わるようにしました。

4. 数値の訂正

4-1. 一律ルール(消滅120分前に30%引き)との比較

400回分の試算・同じ日を突き合わせた差・誤差の幅つき。

商材種別一律ルールエンジン差負ける日の割合
唐揚げ弁当物販6,371円7,000円+9.9% ± 0.9pt9%
握り寿司 10貫物販5,357円6,169円+15.2% ± 1.4pt18%
刺身盛り合わせ物販3,411円4,121円+20.8% ± 1.6pt9%
手作りコロッケ 5個物販7,266円7,780円+7.1% ± 0.5pt8%
彩り野菜サラダ物販2,624円2,950円+12.4% ± 1.1pt13%
焼き鳥 5本盛り物販5,566円6,109円+9.7% ± 1.2pt19%
整体 60分枠枠7,520円7,979円+6.1% ± 1.4pt28%
美容室 カラー枠 90分枠15,137円15,656円+3.4% ± 1.4pt31%
パーソナルトレーニング 50分枠13,850円14,491円+4.6% ± 1.4pt30%
ネイル 60分枠枠11,879円12,308円+3.6% ± 1.3pt31%
ヨガレッスン 1枠枠17,588円18,369円+4.4% ± 0.8pt24%
平日ランチ席枠9,180円11,252円+22.6% ± 1.5pt9%

12商材すべてで平均が上回り、12商材すべてで誤差の幅を考えても差が残りました。

4-2. 結果を見てから最も強く調整した一律ルールとの比較

調整用200回分で最強の設定を選び、重複しない採点用200回分で比べたもの。

商材最も強かった一律ルール差負ける日の割合
唐揚げ弁当20%引き / 180分前+8.8% ± 1.5pt19%
握り寿司 10貫25%引き / 120分前+12.7% ± 2.6pt21%
刺身盛り合わせ30%引き / 90分前+15.3% ± 2.8pt21%
手作りコロッケ 5個20%引き / 180分前+5.6% ± 0.9pt19%
彩り野菜サラダ25%引き / 120分前+9.0% ± 1.7pt22%
焼き鳥 5本盛り25%引き / 180分前+8.4% ± 1.2pt15%
整体 60分枠5%引き / 240分前+5.0% ± 2.1pt36%
美容室 カラー枠 90分25%引き / 120分前+4.0% ± 2.2pt27%
パーソナルトレーニング 50分15%引き / 90分前+4.4% ± 2.2pt32%
ネイル 60分枠25%引き / 60分前+2.5% ± 2.0pt37%
ヨガレッスン 1枠40%引き / 60分前+4.0% ± 1.1pt28%
平日ランチ席20%引き / 60分前+2.8% ± 0.8pt26%
訂正: 枠の商材の差は「+0.2〜4.2%」ではなく「+2.5〜5.0%」だった 旧数値が低く出ていたのは同じデータで調整して同じデータで採点していたためで、 相手を都合よく合わせ込んだぶん、エンジンに不利な測り方になっていました。 調整と採点を分けたら差は広がりました。 自分に不利な測り方をしていた誤りなので、訂正すると主張が強くなる方向へ動いています。

4-3. それでも、枠の商材について言えることは限られる

物販は +5.6〜15.3%、枠は +2.5〜5.0%。加えて枠の負ける日の割合は 26〜37% あり、 3日に1日は一律ルールのほうが良い日があります。

枠の商材についての正直な言い方 「一律ルールより儲かる」ではなく 「最適な値引き率と発動タイミングを事前に知らなくても、それに並ぶ結果が出せる」。 比較相手は結果を見てから最も強い設定を選んだ一律ルールであり、 現場が事前にその設定を引き当てられる保証はありません。この言い換えは説明文にも組み込んであります。

4-4. 負ける領域

唐揚げ弁当 / 思い込みがズレている場合
(エンジンは「価格に強く反応する」と信じたまま、実際の反応だけが弱くなっていく)

  分かれ目 = 反応の強さ −0.79    負ける区間 = −0.79 より弱い側
  −2.6:+9.8%  −1.2:+6.7%  −0.8:+0.3%  −0.6:−5.5%  −0.4:−13.5%

唐揚げ弁当 / 正しく分かっている場合 : 調べた範囲の全域で勝つ
整体 60分枠 / 両方の場合            : 調べた範囲の全域で勝つ

エンジンが「よく反応する」と信じたまま、実際の反応がそれより弱くなると一律ルールに負けます。 これは値引いても客が増えない世界で、エンジンだけが値引き続ける状態であり、負け方として筋が通っています。

5. 持ち越す論点

論点状態
値引き率の刻みが5%単位であることの影響。 在庫が1個増えると選ばれる値引き率が飛ぶため、「この1個を残す価値」が一部で逆転する(858点中31点、最大 +128%)。数値の誤差ではなく、刻みを設けたことによる構造的な性質 仕様として受け入れる。画面では「在庫が減るほど残す価値が上がる」と言い切らない(傾向として述べる)
サービス枠の価格反応 −2.00 と、時間経過による反応の強まり 0.50 は仮の値で、出典がない。 このしくみは反応の強さを推定せず外から与えるため、推定の精度は主張の対象外 画面に常時「仮の値・出典なし」と表示。前提が外れたときどうなるかを見せることで、弱点を機能に転換している
クーポン原資の1枚あたり上限、値引きによる食い合いの控除、予算と実績の差異分析 受け皿だけ用意。現時点で画面に出していないのは意図どおり
架空のデータであること自体 解消しない。ただし「同じ日を3つのやり方で回して比べる」ことは実際の販売データでは原理的にできない(実際に起きたことは1通りしか記録されない)。架空のデータは代用品ではなく必要条件である
解消した論点(2026-09-04〜05) ・試算に使う日数の組が3種類あった件 → 1つに統一し、画面のどの数字も同じデータを見るようにした
・比率のグラフが跳ねる件 → 縦軸に円の差額を追加し、比率は分母が十分大きいときだけ出すようにした
・書式の適用範囲が広すぎた件と、ブラウザのキャッシュで更新が届かなかった件(3-8)→ どちらも対処済み

6. この体制について言えること

AI3体の同時進行は、動き出した時点で担当が壊れるという派手な事故から始まりました。 それでも成果が出たのは、体制そのものより次の3つが効いたためだと考えています。

  1. 他の担当の中身を、読むだけで粗探しする役を明示的に置いたこと。 12件中6件はこの見方でしか出ませんでした。書く権限を持たない読み手は、 「動かすために辻褄を合わせる」誘惑がないぶん、前提の食い違いに気づきやすい。
  2. 受け持ちを守り、取り合いをしなかったこと。 唯一の実害だった上書き事故も、突き合わせてから「導き方が正しいほうを採る」と判断したため、 結果的に中身が良くなりました。
  3. 自分のミスを記録に残したこと。 まとめ役の誤り(3-1〜3-8)を消していたら、 「合格しているのに何も検査していない」型の事故が2回起きた事実が残りませんでした。 これは同じ体制を次に組むとき、最も価値のある情報です。
最後に、この文書自体の限界 ここに書いたのは記録に残った間違いだけです。 気づかれずに直されたもの、そもそも気づかれていないものは数えられていません。 「12件見つかった」は「12件しかなかった」ではありません。