Upgrade to Pro — share decks privately, control downloads, hide ads and more …

今時のフルスタック主導の iOSアプリ開発

Avatar for nakajijapan nakajijapan
September 18, 2026
11

今時のフルスタック主導の iOSアプリ開発

extension DC 2026 Day1

Avatar for nakajijapan

nakajijapan

September 18, 2026

Transcript

  1. @nakajijapan Daichi Nakajima CTO / Software Engineer 🏢 Pepabo ->

    Cookpad -> Campfire -> DeNA -> Startup企業s -> KNOWLEDGEWORK -> BaseMe Shari ★113 PhotoSlider ★248
  2. モバイルエンジニアを起点に見る範囲 幅広く対応 Front-End Design Server Side Security PdM Infrastructure Mission

    Mobile Web版をベースにして、iOSは 別軸でモバイルらしい体験を作る © BaseMe Inc. 10
  3. 1 つの機能が、全部の層をまたぐ 二段階認証。iOS・Web・サーバー・インフラを、一人で対応 1 4 iOS パスワードや Apple で アプリ

    ログインする Web パスワードや Apple で ブラウザ ログインする 6 ログイン完了。 6 桁を入力する 信頼した端末は次回省略 ログイン完了。 6 桁を入力する 2 信頼した端末は次回省略 5 二段階が有効なら、 サーバー 確かめて、 本物の鍵は渡さず API 本物の鍵を渡す 短い合言葉だけ返す 3 インフラ SMS で 6 桁を送る SMS を送る土台と鍵の置き場 守りと計測 同じ機能の中で 入力と電話登録の 機能フラグで段階的に出す。 電話を失っても 有効にした数と失敗を 回数を絞る 古いアプリを締め出さない 控えの番号で戻れる 数える どの層が欠けても成り立たない機能は、全部の層を一人で触って通す。 © BaseMe Inc. 12
  4. 開発スケジュール 239 ios/ のコミット数 240 188 180 120 60 22

    0 4月 5月 6月 足場を置いた月 8.5倍 App Store 設計に時間を消費し、開発を加速度的に上げていく © BaseMe Inc.
  5. 役割ごとに、4 点を決める 曖昧に「任せる」のではなく、役ごとに決めておく 何を iOS の実装パイプラインでは 入力は何か planner には 1〜4

    行の依頼。builder には仕様書と設計 何を出力させるか planner は仕様書と受け入れ基準。builder は実装と自己評価 何で正しさを確かめるか evaluator が、ビルド・テスト・シミュレータで受け入れ基準ごとに pass / fail どこで人に戻すか 同じスプリントで 3 回 fail したら、人に上げる この 4 点が決まったとき、AI は仮想チームとして機能する © BaseMe Inc. 16
  6. AIに渡す仕事を、4層に分ける 4 つの層。上ほど毎回、下ほど動かして確かめる 毎回読む CLAUDE.md rules セッションのたびに 10 節 23

    本 / 由来 17 必要なとき読む 自前スキル 借りたスキル 12 52 / ハッシュ固定 作業に合わせて 役割として動く orchestrator が回す 動かして確かめる シミュレータ・テスト planner architect builder evaluator fixer DebugHarness テスト E2E 21 ケース 2,266 本 夜間 ここまでは、たぶん皆さんもやっています。 © BaseMe Inc. 17
  7. AIに渡す仕事を、4層に分ける 4 つの層。上ほど毎回、下ほど動かして確かめる 毎回読む CLAUDE.md rules セッションのたびに 10 節 23

    本 / 由来 17 必要なとき読む 自前スキル 借りたスキル 12 52 / ハッシュ固定 作業に合わせて 役割として動く orchestrator が回す 動かして確かめる シミュレータ・テスト planner architect builder evaluator fixer DebugHarness テスト E2E 21 ケース 2,266 本 夜間 ここまでは、たぶん皆さんもやっています。 © BaseMe Inc. 18
  8. 自前スキル 12 本は、開発の流れに沿って置いてある どの段で、何を AI に読ませるか。借り物の 52 本は、この外側 作る ビルドする

    動かして見る 遅い・固まる・落ちる PR を出す App Store へ generate-feature xcodebuild-baseme ios-simulator-skill swiftui-perf-investigate pr-create-draft appstore-release 画面を MVVM の型で一括生成 正しいビルドの打ち方。罠の対処つき シミュレータを触る・撮る・読む Instruments で追う手順 PR は必ず draft で。テンプレを埋める 提出から公開まで design-to-swiftui review-ios Figma やスクショから SwiftUI へ iOS の PR を見る観点 api-client pr-review-triage サーバー API の通信コード bot の指摘を鵜呑みにしない markdown-render-parity markdown の描画 3 経路を揃える web-parity-audit Web の機能を移すときの調査表 上の段が、開発の流れ。下が、その段で AI に読ませる自前のスキル。数は 12 本。 どれも、一度踏んだ手順を、次に AI が同じ手順で踏めるように書いたもの。 © BaseMe Inc. 19
  9. 誰が、いつ読むか 4 つの層。上ほど毎回、下ほど動かして確かめる 毎回読む CLAUDE.md rules セッションのたびに 10 節 23

    本 / 由来 17 必要なとき読む 自前スキル 借りたスキル 12 52 / ハッシュ固定 作業に合わせて 役割として動く orchestrator が回す 動かして確かめる シミュレータ・テスト planner architect builder evaluator fixer DebugHarness テスト E2E 21 ケース 2,266 本 夜間 ここまでは、たぶん皆さんもやっています。 © BaseMe Inc. 20
  10. iOS の実装は、役割を分けて回す planner から fixer まで。渡すものと、fail のときに戻る場所を決めてある orchestrator(司令塔) 順番に回し、pass か

    fail を見て次を決める スプリント。1 機能ずつ、この中を回る 自分 1〜4 行の依頼 planner architect 依頼を仕様書に広げる。 受け入れ基準まで書く 仕様書 builder 仕様書から設計。 iOS とサーバーの API。 コードは書かない evaluator 1 機能を実装。 シミュレータで動かして 自己評価を出す ビルドとテスト。 受け入れ基準ごとに pass か fail 次の機能へ pass 全部 pass したら PR。 merge するのは自分 設計書 fail fixer 3 回 fail 3回 evaluator に戻る 最小の変更で直して、 evaluator に戻す 役では直せない。 人間(自分)に戻す Claude Code のサブエージェント。ios/.claude/agents に置いてある。ここまでは役に任せられる。 © BaseMe Inc. 22
  11. アーキテクチャ 5 つの層。数字は 現在の実数 MVVM View 画面。表示だけ Design System SwiftUI

    の画面。状態も処理も持たない。 共通部品は右の Design System から取る ViewModel 状態と処理 Analytics ViewModel 48 本。状態は @Observable(49 ファイル)。 画面が何を出すかは、ここで決まる 通信 サーバーとのやりとり Test 確かめる側 BM* の共通部品 15 種。 色・余白・字はトークンから。画面をまたいで揃える PostHog にイベント(定義 34 種)とセッション録画。 Crashlytics に落ちた記録。dSYM は CI から Realtime API の型は swagger から自動生成。手で書かない。 チャットの本文は SSE、カードの進捗は ActionCable(右) SSE でチャットの本文を流す。 WebSocket でカードの進捗を押す Unit と UI で 282 ファイル・2,266 本。#Preview 334 のうち共通部品はスナップショットへ。 VRT は S3 に基準画像、E2E は夜間。AI が書いた差分は、ここを通って初めて信じる © BaseMe Inc. 26
  12. モバイル側(iOS) ここは自分で設計しました。既製のライブラリは入れていません。 受け口 URLSessionDataDelegate .lines は使わない チャンクをそのまま受ける 行ごとに溜まると流れて見えない SSEParser テストできる形にする

    仕様どおりに組む protocol で切り出す テスト 10 ファイル・1,447 行 つなぎっぱなし ActionCableClient WebSocketを閉じ込める 状態を1列に並べる unchecked Sendable なし 生のバイトで受ける 解析 actor 1本 切れたとき 自動で戻す 指数バックオフ ping を見張る 購読の一覧は捨てない 最大 30 秒 6秒来なかったら切れたとみなす 戻ってきたらつなぎ直す © BaseMe Inc. 27
  13. 登録した当日の体験を直した、1 か月 登録した当日に、どこまで使ってもらえるか。赤い帯は、つまずいたところ 8月上旬 分析 登録した日に何をした人が、7 日後にまた開いているかを調べた 8月上旬 疑う役が差し戻し 直すべき点を

    7 つ挙げて、分析を突き返した 8月上旬 判断 条件つきで採用。登録より先に、Ken と話してもらう案 8月中旬 実装 入力なしで始まる新しい入口を作った。68 コミット 8月末 実験に移す A/B の振り分けが、アプリの画面に届いていなかった。直した 8月末 指標を入れる 効果を測る指標が 1 つも無かった。3 つ足した 9月頭 読み直し 指摘どおりに集計し直しても、差は残った 分析から指標まで、こういうのも自分でやっています。間違えても、ここまでは回ります。 © BaseMe Inc. 28
  14. ミスを0にするのではなく、直すまでの俊敏さ 設計を先に行っても、ビルドもテストも通る場所でミスは残る。狙うのはゼロではなく、一人で見つけて直せる俊敏さ 1. 振り分けが、画面に届いていなかった 前 サーバー A / B を決める

    × 2. 効果を測る指標が、1 つも無かった アプリの画面 結果を見ていない 前 だから、A と B の出し分けが起きない 後 実験 2 指標: 0 個 動かしても、効いたかどうかが読めない PostHog の実験 アプリの画面 振り分けを決める A と B を出し分け 振り分けを PostHog の実験に載せ替えた 実験 1 後 イベントを 指標を組む 3 つ足す 効果が読める 測るためのイベントを 3 つ足して、指標を組んだ 見つけて直すところまで一人で回る。 © BaseMe Inc. 29
  15. 現状やれていること、4 本 この章が発表の中心 何を 一言で 4-1 体験をつくる 動かして、計測して、初めて分かる 4-2 正しく確かめる

    古いアプリを見ない。推測で直す前に測る。どちらも失敗から rule にした 4-3 境界をつなぐ API の型は生成する。約束がなければ、AI の型でも壊れる 4-4 経験を次の AI 入力へ戻す 失敗を rule・skill・CI の関門に戻す AI が速く書くほど、確認・約束・学習の仕組みが重要になる © BaseMe Inc. 31
  16. 4-1 体験をつくる 何を 一言で 4-1 体験をつくる 動かして、計測して、初めて分かる 4-2 正しく確かめる 古いアプリを見ない。推測で直す前に測る。どちらも失敗から

    rule にした 4-3 境界をつなぐ API の型は生成する。約束がなければ、AI の型でも壊れる 4-4 経験を次の AI 入力へ戻す 失敗を rule・skill・CI の関門に戻す AI が速く書くほど、確認・約束・学習の仕組みが重要になる © BaseMe Inc. 32
  17. AI チャットが、16 秒固まった ユーザーがやったことと、起きたこと 1 2 3 4 Ken と、長くやりとりする

    答えの最後に、選択肢のチップが 出る 画面が止まる。16.23 秒 もう 1 往復すると 答えは文字が流れて届く。 1 文字ずつ画面が更新される どれかをタップする 何も押せない。 Instruments では Severe Hang CPU が 100% に張り付く。 そのまま落ちることもある 止まっていた時間 0秒 16.23 秒 この間、指が効かない 起きた構成 SwiftUI AI と一緒に作った画面。 コードを読んでも分からない。動かして、初めて分かった。 @Observable SSE ストリーミング どれも普通。特別なことはしていない コードを読んでも分からなかった。動かして、初めて分かった。 © BaseMe Inc. 33
  18. Time Profiler の答え。自分のコードは 0.5% Time Profiler は、時間を細かく刻んで「そのとき動いていた関数」を数える道具。誰が呼んだかは数えない 固まっていた 16 秒の間、メインスレッドは誰の関数を動かしていたか

    0.5% 自分が書いた関数 99.5% 自分の関数が直接使った時間の合計。どれも軽い SwiftUI の中の関数 レイアウトの計算に、ほとんどの時間が消えている Time Profiler で分かること Time Profiler で分からないこと 誰が時間を使ったか。 答えは「自分の関数ではなく、SwiftUI のレイアウト計算」。 誰がそれを何度も呼んだか。 自分のどの書き方が引き金なのかは、ここからは読めない。 行き止まり 次の道具 自分のコードを削っても直らない。削る場所が無い 「誰が呼んだか」の積み重ねが見える Hangs へ。次のスライド 自分のコードを削っても、直らない。ここで一度、行き止まりになった。 © BaseMe Inc. 34
  19. 出てきた名前は、誰の処理か Hangs が出した呼び出しの積み重ね。上が画面を出す土台、下へ行くほど自分の選んだ部品に近づく 呼ばれた順 画面を出す土台 1 回ぶんの画面の変更を、まとめて確定させる CA::Transaction::commit UIKit と

    SwiftUI の橋 UIHostingView.layoutSubviews SwiftUI の中心 AG::Graph::UpdateStack::update LazyVStack の位置計算 LazySubviewPlacements.placeSubviews 高さのキャッシュを捨てる LazyLayoutViewCache.invalidateSize Apple の中。 自分では触れない 並べ直しの指示が来るたび、SwiftUI 全体のレイアウトが走 る View・状態・レイアウトの依存の網。1 つ変わると、つなが る節点を全部更新 子の位置と高さを決める。Lazy でも、位置は全部の子で計算 する 1 つ変わると、全部捨てる。これが何度も呼ばれていた 自分が選んだ入れ物。 LazyVStack の中 犯人 犯人は自分の関数ではなく、自分が選んだ入れ物だった。 © BaseMe Inc. 35
  20. 1 文字届くたびに、全部測り直していた 「1 つ変わる」とは、最後の吹き出しが 1 文字ぶん伸びること。入れ物によって、そのあとの反応が違う LazyVStack(前) 起きること(どちらも同じ) チャットの画面。答えは 1

    文字ずつ届く 測り直し 1 つ変わると 測り直し 測り直し 測り直し 高さのメモを全部捨てて、 全部測り直す 16 秒 止まる 測り直し 測り直し +1 測り直し 答えの途中の吹き出し… 1 文字ごとに、全部。 長い答えほど回数が増えて、止まる 測り直し ↑ 1 文字ぶん、高さが伸びる VStack(後) これが「1 つ変わる」。 1 つ変わると 最後の吹き出しの高さが、 変わった 1 つだけ測り直す。 ほかはそのまま 1 文字届くたびに変わる。 長い答えなら、何百回も起きる 止まらない 1 文字ごとに、1 個ぶん。 回数が増えても軽い 測り直し 16 秒を消したのは、入れ物を変えた 1 語。 LazyVStack { VStack { Lazy の利点は「見える分だけ作る」こと。数十件のチャットでは効かない。数百を超えるなら List を使う 大量で固定のViewを扱うならLazyVStack 可変高Markdownが更新されるため、実測では VStack の方が滑らか © BaseMe Inc. これが宗派y区数千になってくるとまた別問題 36
  21. 体験品質の確認方法 UI とアニメーションで、決めていること 3 つ 01 02 03 静止画で判定しない Profiler

    を取る 計測の道具を疑う 固まった 16 秒、メインスレッドは誰の関数を動かしていたか 指のスワイプ(0.4 秒) × アプリの録画 idb の合成スワイプ 正解(デザイナーの動画) 0.5% 自分の関数 99.5% SwiftUI の中 6ms に固まって届く 止まった後の 1枚 コマごとに要素の位置を追い、2 本を並べる Time Profiler Hangs 誰が時間を使ったか 誰が何度も呼んだか 画面: ほぼ動かない メインスレッド: 暇 6.8 秒で 3 コマ ほぼ待ち状態 矛盾。凍ったのはアプリではなく、道具の嘘 止まった後の 1 枚は、何も証明しない。 録画をコマに分解して、要素の位置を毎コマ追う。 正解の動画も同じ方法で測る。仕様の数字はそこから出る simctl recordVideo → ffmpeg / ffprobe でコマに分解 読んでも分からなかった。疑う前に、測る。 時間の 99.5% は、自分の関数の外だった。 道具を 2 つ重ねて、初めて犯人に届いた Instruments: Time Profiler → Hangs 計測が矛盾したら、まず道具を疑う。 合成スワイプはタッチを 6ms に固めて届ける。 実時間で動くドラッグに替えて、測り直した idb → ホストから実時間のドラッグ / 実機で触る ここは今も、自分で確かめています。 © BaseMe Inc. 37
  22. 4-2 正しく確かめる 2 本目。例は 2 つ。見ていたアプリが古かった話と、見ていた値が古かった話 何を 一言で 4-1 体験をつくる

    動かして、計測して、初めて分かる 4-2 正しく確かめる 古いアプリを見ない。推測で直す前に測る。どちらも失敗から rule にした 4-3 境界をつなぐ API の型は生成する。約束がなければ、AI の型でも壊れる 4-4 経験を次の AI 入力へ戻す 失敗を rule・skill・CI の関門に戻す AI が速く書くほど、確認・約束・学習の仕組みが重要になる © BaseMe Inc. 38
  23. 古いアプリを見て、実在しない不具合を追った ノートの背景色を直したのに、「まだ白い」と言われ続けた コード 新 シミュレータ ビルド #F9F9FC ✓ 新しい色を書いた BUILD

    SUCCEEDED × エラーは出ない 旧 #FAFAFA 古い app のまま 入れ直していない 「直した」 「直っていない」 見ていたのは、コードとビルド 見ていたのは、シミュレータの画面 AI 確かめる側 AI は「直した」と言い、確かめる側は「直っていない」と言う。どちらも嘘はついていない。 見ていたものが違った! © BaseMe Inc. 39
  24. 直したのは、アプリではなく AI が読む手順 アプリのコードは 1 行も変えていない。変えたのは、AI が読む 4 ファイル AI

    が読む手順 アプリのコード + 消す 変えた のは 0行 変えていない ビルド 入れ直す 測る ここが抜けていた 目ではなくピクセルで + rule + skill 消して、ビルドして、入れ直してから測る。鮮度は 1 点で確か める 色は目で見ない。ピクセルで測る + evaluator + fixer 検証の前に、必ず鮮度の関門を通す 直した後の再検証も、同じ関門を通す 検証 BUILD SUCCEEDED でも、1 ファイルもコンパイルしていないことがある。それも rule に書いた。 © BaseMe Inc. 40
  25. もう 1 つ。アイコンを変えたのに、drawer だけ古い 設定でアイコンを変えると、横から出るメニュー(drawer)にも同じアイコンが出る。6 月、「登録できない」と報告が来た 1 設定でアイコンを変える 新 保存

    ✓ 2 設定画面は、新しいアイコンに なる 状態更新 ? drawer を開く 旧 表示 × 3 古いアイコンのまま 閉じて、もう一度開く 新 その時だけ、新しいアイコンに なる この時点の仮説 保存ではなく、状態更新から表示までのどこかで止まっている 止まっているのは、この間のどこか 見えていたのは「保存失敗」ではなく、「保存後に表示だけが追いつかない」だった。 © BaseMe Inc. 41
  26. 3 回推測で外して、1 回の計測で当てた 推測を試すたびに、実機の確認で 6〜22 分。だから、ログを 3 か所に置いて 1 回で測った

    推測で直す 1 閉じる処理を消してみた 測ってから直す × 外れ 1 実機で確かめるのに 6〜22 分 2 状態を直接読んでみた 画面の一番上で読んでみた 届いた ログを 1 行入れて、1 回動かす × 外れ 2 実機で確かめるのに 6〜22 分 3 更新は届いているか 再描画は走っているか 走っていない ログを 1 行入れて、1 回動かす × 外れ 実機で確かめるのに 6〜22 分 3 なぜ走らないか 「変化なし」と判定 ログを 1 行入れて、1 回動かす 3 回やって、何も分からなかった 1 回で、原因に届いた 推測 1 回ごとに、実機の確認で時間だけが減っていく id が同じで URL だけ違うと、「変化なし」と判定されていた 推測で直す前に、1 回測る。これがそのまま rule になった。 © BaseMe Inc. 42
  27. 直したのは、比べ方 同じ人なら変化なし、ではなく、同じ中身なら変化なし、にした 前 id だけ比べる 後 いま表示している 保存された 全部を比べる いま表示している

    保存された id 42 id 42 id 42 id 42 name Nakajima name Nakajima name Nakajima name Nakajima url /old.png url /new.png url /old.png url /new.png id だけ見る 42 = 42 → 変化なし id・name・url を全部見る url が違う → 変化あり URL の違いは見ていない id が同じでも、中身が違えば描き直す → drawer は描き直さない → drawer が新しくなる 直したのは 1 行。見つけるのに 3 回外して、測ったら 1 回だった。 © BaseMe Inc. 43
  28. 4-3 境界をつなぐ 何を 一言で 4-1 体験をつくる 動かして、計測して、初めて分かる 4-2 正しく確かめる 古いアプリを見ない。推測で直す前に測る。どちらも失敗から

    rule にした 4-3 境界をつなぐ API の型は生成する。約束がなければ、AI の型でも壊れる 4-4 経験を次の AI 入力へ戻す 失敗を rule・skill・CI の関門に戻す AI が速く書くほど、確認・約束・学習の仕組みが重要になる © BaseMe Inc. 44
  29. 実装のずれは、2 通りで起きた どちらも、手元ではビルドもテストも通る。見た目では分からない ケース 1 サーバーだけが進む サーバー側 iOS の生成物 size

    を 数字 に直した size は 文字列 のまま 前は文字列だった。仕様を正した ケース 2 生成し直していない。古い 本番に出ていたら ビルド ✓ テスト ✓ 数字を文字列に 入れられず、落ちる AI が、生成したファイルに手で足す 生成したファイル(手で編集しない、と書いてある) 次に生成し直した瞬間 struct Suggestion: Codable + Equatable + var title + = nil 動く 見た目は何も問題ない AI が「便利だから」と足した 手で足した分が消える。 消えたところを使っていると壊れる どちらも、型としては正しい Swift。 コンパイラは文句を言わない。 テストも通る。 だから、人は気づかない。 人が動かした差分も、AI が足した差分も、コンパイラは文句を言わない。 © BaseMe Inc. 45
  30. 手で書ける場所を、無くした 型の正はサーバーに 1 か所。iOS 側は生成するだけ。手で触ったら CI が止める 型の流れ サーバーのテスト swagger.yaml

    生成スクリプト Generated/*.swift 型の正はここ。 レスポンスの形を書く テストから生成。 手で編集しない swagger を読んで Swift を書き出す 先頭に 「手で編集しない」 止める場所 CI(iOS に変更があるたびに走る) 差分なし → 通る もう一度、生成する 手元の生成物とは無関係に、 CI が自分で作り直す 手元の生成物と比べる git diff を取るだけ 人が手で直した 1 文字も、 AI が足した 1 行も、 生成し忘れた 1 ファイルも、 ここで赤になる。 差分あり → 赤にする 人も AI も、生成物を直接編集しない。編集しても CI で赤になる。 © BaseMe Inc. 46
  31. 4-4 経験を次の AI 入力へ戻す 何を 一言で 4-1 体験をつくる 動かして、計測して、初めて分かる 4-2

    正しく確かめる 古いアプリを見ない。推測で直す前に測る。どちらも失敗から rule にした 4-3 境界をつなぐ API の型は生成する。約束がなければ、AI の型でも壊れる 4-4 経験を次の AI 入力へ戻す 失敗を rule・skill・CI の関門に戻す AI が速く書くほど、確認・約束・学習の仕組みが重要になる © BaseMe Inc. 47
  32. 失敗を直して終わると、次のAIも同じ誤った道を踏む 足場は先に組めない。転んだ場所にしか置けない。そして置いた rule にも穴があった 戻す係がいなかった rule を書いても、3 つの穴があった AI が書く

    1 失敗する 先に書けない 4 月に想像で書いた 3 本は、6 月の失敗を 1 つも止めなかった。 足場は、転んだ場所にしか置けない 同じ穴を踏む 2 次のセッションの AI 4〜5 月の 5 本には由来が無い。AI が似た状況で応用できず、 人もあとで消していいか判断できない 人が直す 直して終わり × 3 rule に戻す 「なぜ」が無い 全部読ませると、読まれない CLAUDE.md に書いていた頃、長くなると人間が更新しなくなった。 更新されない記憶は、無いより悪い 戻す係がいない 失敗は直る。でも rule には戻らない。だから次のセッションの AI が、同じ失敗を繰り返す だから決めた 戻す係 書き方 戻す先 ふりかえりの役。提案だけ出し、入れるのは人 由来を書く。触るときだけ読ませる rule・skill・agent・DebugHarness を分ける © BaseMe Inc. 48
  33. ruleは、失敗から育てる ふりかえりの役を置いた 6 月から、rule に由来が付くようになった。月ごとの本数 追加された rule の本数 由来なし 6月

    失敗の由来つき ふりかえりの役を置いた 16 本 3本 4月 2本 5月 6月 1本 1本 0本 7月 8月 9月 4〜5 月の 5 本は由来なし。想像で書いた 最初の由来つき rule は、古いアプリを見ていた失敗から生まれた 7 月以降は 2 本だけ。録画に入力欄を残さない/段を進める演出の時間を上書きしない © BaseMe Inc. 49
  34. ローカルとCIの判定を揃える 戻す先は rule だけではない。CI でしか見つからなかった違反を、ローカルの手順に戻した例 前 ローカル 戻した先。rule ではなく、手順に戻した CI

    push lint はゆるい設定。 違反があっても通る swiftlint --strict。 ここで初めて落ちる ios/Makefile +5 行 lint-strict のターゲットを新設。既存の lint はそのまま ios/.claude/skills/review-ios/SKILL.md 直して、また push。往復が増える +20 行 build gate の隣に Lint gate。make lint-strict を回し、違反があれば GATE: FAIL 後 ローカル CI push make lint-strict。 CI と同じ判定を手元で。 ここで落ちて、ここで直す 変更なし。 同じ判定なので、通る .github/workflows/ci-ios.yml 変更なし 元から swiftlint lint --strict。SwiftLint 0.57.0 にピン留め 副産物: HomeSpeechBubble.swift が 514 行 → 229 行。HomeBubbleShape と HomeGreetingContent に分割 CI を変えたのではない。ローカルの手順に、CI と同じ 1 行を足した。経験を戻す先は、rule だけではない。 そもそもちゃんとしろ案件 © BaseMe Inc. 50
  35. 4 本に共通すること 4 本とも、AI が速く書いたものを、あとから何で止めたか AI が 実装 確認 約束

    動かして測ってから、信じる サーバーと iOS の約束。型は生成して、手で は書かない 1 体験をつくる 3 境界をつなぐ 動かして計測する。 静止画で判定しない 型は生成する。 手で書ける場所を無くして、 CI で止める 学習 次の AI に、由来ごと渡す 4 経験を次の AI に戻す 失敗の由来を rule に書いて、 次の AI に読ませる 2 正しく確かめる 直す前に測る。 古いアプリを見ない 速く書けるほど、速く壊せる。だから、確認・約束・学習を仕組みにしておく。 © BaseMe Inc. 51
  36. まだ、課題に上がっていること 4 つ。どれも、AI が回す流れの中で、人が抜けられない場所 01 02 仕様に書いた 0.8 秒 実際に動いた

    0.2 秒 動きの仕様を、どこまで言葉にでき るか 体験の良し悪しを、どう測れる形に するか 書いた数字が、そのまま動くとは限らない。 録画で測るまで分からない 静止画は CI が比べる。動きは、まだ人が録 画を見て決めている ✓ 静止画 CI が比べる 人が見る 全体の設定に上書きされた 03 AI 人 動き 04 合否 差し戻し rule を入れる merge AI に渡す判断と、人が持つ判断 を、どう分けるか 合否と差し戻しは AI。rule を入れる、 merge する、は人。全体の決まりは、まだ無 い 仮想チームの成果を、誰が引き受け るか planner architect builder evaluator fixer merge 最後に merge するのは自分。一人だから成 り立っている 自分ひとり 線は、場所ごとに引いている 一度解決して終わりにせず、観測できるようにして、次の判断を少し速くする。ここまでしかできていない。 © BaseMe Inc. 53
  37. まだ、課題に上がっていること 4 つ。どれも、AI が回す流れの中で、人が抜けられない場所 01 02 仕様に書いた 0.8 秒 実際に動いた

    0.2 秒 動きの仕様を、どこまで言葉にでき るか 体験の良し悪しを、どう測れる形に するか 書いた数字が、そのまま動くとは限らない。 録画で測るまで分からない 静止画は CI が比べる。動きは、まだ人が録 画を見て決めている ✓ 静止画 CI が比べる 人が見る 全体の設定に上書きされた 03 AI 人 動き 04 合否 差し戻し rule を入れる merge AI に渡す判断と、人が持つ判断 を、どう分けるか 合否と差し戻しは AI。rule を入れる、 merge する、は人。全体の決まりは、まだ無 い 仮想チームの成果を、誰が引き受け るか planner architect builder evaluator fixer merge 最後に merge するのは自分。一人だから成 り立っている 自分ひとり 線は、場所ごとに引いている 一度解決して終わりにせず、観測できるようにして、次の判断を少し速くする。ここまでしかできていない。 © BaseMe Inc. 54
  38. ⚫︎ ⚫︎ ⚫︎ ⚫︎ ⚫︎ ⚫︎ アニメーション: 動きは、仕様を細かく決める必要がある アイテムのアニメーション Lottie

    Kenのアニメーション モバイル用に最適化した動画を生成 複雑なアニメーション、インタラクション SwiftUI (keyframe / transition) 人間との同時並行が必要 © BaseMe Inc.