自分についてAIに聞けば、自分自身より自分の過去を正確に把握している
これが構想文書 requirement.md §20 の最終ゴール。単なるメモ置き場ではなく、人生・仕事・思考・健康・プロジェクトのデータベースを作り、AIをそのインターフェースとして使う。
ゴールに到達したかどうかは、次の問いに答えられるかで測る。すべて原文(§20・§15)にある問いである(一人称のみ「自分」に置き換えた)。
自分はなぜこの事業を始めた?
去年と比べて何が変わった?
今の自分が抱えている問題は何?
過去の自分なら、この問題をどう考えていた?
今の生活習慣と仕事の成果に相関はある?
過去に考えたアイデアの中で、いま実行すべきものはどれ?
今の自分がやめるべきことは何?
過去の意思決定と現在の状況を踏まえて、次に何をすべき?
三層 — Memory / State / Activity
§16 の最終形。3つの層がすべて AI Retrieval(AIによる検索・取得の層)を経由して、Claude でも自作AIでも同じように読める状態にする。
データの3分類 + 意思決定を別格に扱う
| 分類 | 中身 | 例(原文) | 置き場所 |
|---|---|---|---|
| Fact | 事実・測った値 | 体重 76.2kg/歩数 9,832/摂取カロリー 2,143kcal | 数値。人が直接編集する必要がない |
| Knowledge | 知識・調査結果 | SupabaseでRLSを設定する方法/React Server Componentsの調査結果 | Markdown |
| Thought | 自分自身の思考 | 「自分は本当に法人化したほうがいいのか?」 | Markdown。第二の脳ではこれが最重要 |
| Decision | 意思決定(別格) | Decision / Reason / Status の3点セットで残す | Markdown |
| Event | 時系列の出来事 | {"type":"idea.created","source":"iphone",…} | MVP外。着手時に「索引の対象か」を必ず決める |
器の名前ではなく、3つの要求を守る
「Markdownを正本にする」は形式へのこだわりではない。守りたいのは次の3つで、これを満たすなら器(データの格納形式)は何でもいい。逆に満たさない器は、名前がMarkdownでも失格になる。
| # | 要求 | これを満たさない器の例 |
|---|---|---|
| P-1 | grepできる(AIがファイル読み込み・全文検索・パターン一致という基本操作だけで確実に読める) | DBの中の行 |
| P-2 | 差分が安定している(git diff が人に読める) | 1行に全部入ったJSON |
| P-3 | 人が直接編集できる | バイナリ・専用エディタが要る形式 |
構想文書が PostgreSQL に置こうとしていた5件(Event Log / Decision / Entity / タグ / 計測)のうち、PostgreSQLを必要とするものは0件だった。逆に、3つ全部を必要としないものもある — 計測データ(体重・PFC)は P-3 を必要としないので Markdown の外に出せる。「全部Markdown」でも「全部DB」でもない。
索引が要る理由は「意味の理解」ではない
コードを1行も書かず grep と sed だけで本人の問いに答える実験(原典の呼称 PT-R0)を実際に走らせた。2問とも通った。それでも索引は要る。ただし理由が変わった。
domain(第1階層ディレクトリ)/ heading_path(見出しの階層)+start_line(行番号)/ 既定除外(ノイズになるディレクトリを最初から外す)に対応していた。実験が通った理由は3つで、どれもベクトルでも索引でもない。①パスとファイル名が意味を持っている(finance/simulations/2026-03-27_incorporation-simulation.md)/②見出しが自己説明的(666KBのファイルでも grep -nE '^#{1,3} ' で253本の目次が出て当たりが付く)/③語彙が一貫している(「法人化」に表記ゆれが無い)。
これは設計の成果ではなく、本人がこれまでデータリポジトリを書いてきたやり方の成果である。したがってこの3つは「システムが提供するもの」ではなく「システムより先に守るべきもの」。日付をパスに入れる/見出しを内容の名前にする/同じものを同じ語で呼ぶ — これをやめると、どんな索引を作っても剪定が効かなくなる。
正本と派生物の境界
設計の骨格はこの1本の線に集約される。正本は git の中に、派生物は git の外に置く。索引をデータリポジトリの外に置く決め手は「重いから」ではない。
.gitignore に索引の行が無いのは書き忘れではなく、「行が無いことが正しい」状態(索引はそもそもリポジトリの外にある)。ログをリポジトリの外に出したのも同じ理由で、logs/(再生成可)と events/(再生成不能)が隣り合うと、片方を ignore した人がもう片方も同じだと判断して事故が起きる。左枠のディレクトリ名は既存の第1階層(ドメイン)で、business=事業、finance=家計・資産、goals=目標、health=健康、mental=気分ログ、pokemon=趣味の対戦記録、projects=プロジェクト文書、research=調査、sessions=AIエージェントの作業記録、tasks=日次タスク。iPhone のメモが検索に載るまで
MVP で作るものは4つしかない。①iPhoneのショートカット(7アクション)②Macの取り込みスクリプト(launchd・5分おき)③チャンク表を作る index build ④それを LIKE(SQL の部分文字列一致)で引く search CLI。言語モデルは1回も呼ばない。ベクトル検索も全文検索エンジンも常駐プロセスも、MVPには無い。
稼働中の launchd ジョブ3本
✅ 実測済 3本とも登録・稼働中、直近の終了コードは 0(2026-09-04 観測)。ログを3本に分けるのは、同じファイルに混ぜると検知器(ログを監視する仕組み)が黙って別のものを数え始めるため。
| 役割 | ジョブのラベル | 間隔 | 実体 | ログ | 処理 |
|---|---|---|---|---|---|
| メモ取り込み | com.shika.life-inbox | 300s | bin/ingest-notes.sh | logs/ingest.log | iCloud life-inbox/ → notes/ |
| 索引更新 | com.shika.life-index | 900s | bin/index-refresh.sh | logs/index.log | index build の定期実行(詳細: 索引ジョブ) |
| 健康データ取り込み | com.shika.life-health | 3600s | bin/ingest-health.sh | logs/health.log | 監視ディレクトリ → health/metrics/(⚠️ パーサ未実装) |
取り込みスクリプトが満たす規定 — M-1〜M-8
この8つは「気をつける」では守れないので規定として固定されている。各行の右側が、その規定が無いときに起きる事故である。
| # | 規定 | 何を防ぐか |
|---|---|---|
| M-1 | 最初に受信ディレクトリを ls し、失敗なら ERROR を1行書いて非ゼロで終わる | 🔴 TCC で読めないとき「0件だった」と区別がつかない |
| M-2 | 更新時刻(mtime)が60秒以内のファイルはスキップ | iPhoneが書いている最中/同期中のファイルを途中まで読む |
| M-3 | サイズ0、または --- で始まらないファイルは移動せずスキップし WARN | iCloud が未ダウンロードのプレースホルダを空メモとして取り込む |
| M-4 | 順序を固定 — ①追記 → ②読み直して確認 → ③そのあと退避 | 先に移動すると、追記に失敗した瞬間にメモが消える |
| M-5 | ~/.local/state/personal-os/ingested/ へ移動する。削除しない | 取り込みバグに気づいたときやり直せる。削除は本人が明示的にやる |
| M-6 | 書式は固定。frontmatter(ファイル先頭のメタデータ)は notes/ に持ち込まない(captured_at を見出しに変換して捨てる) | notes/ がリポジトリで最も frontmatter の多い場所になるのは、あとから入れた仕組みの都合でしかない |
| M-7 | 毎回ログに1行書く(0件でも書く) | 🔴 無音で死んだデーモンと、メモが無い日を区別する唯一の手段 |
| M-8 | git add / git commit を絶対にしない | 機械はコミットしない。⭐ 副産物として notes/ の変更が必ず人の目を通る |
リポジトリ内の既存スクリプト(別プロジェクトの同期処理 sync.sh)は set -euo pipefail である。揃えないのは慣行を無視しているからではなく、仕事の性質が違うから。sync.sh は「失敗したら止まってよい」仕事、取り込みスクリプトは「失敗を記録してから止まる」必要がある仕事(M-1)。
実測: set -e; ls /nonexistent 2>/dev/null; echo ERROR…; exit 3 は ERROR を1行も出さずに exit=1 で死ぬ。ログには何も残らない。
詳細: phase1-implementation.md §9(手順8 — 取り込みスクリプト・plist・回帰テスト)
メモ1件が通る状態と、静かに落ちる分岐
正常系は6状態。重要なのは分岐のほうで、赤い枝はどれもエラーを出さずに止まる。だから検知は「エラーが出ないこと」ではなく「1行必ず出ること」で行う。
/bin/bash)に付いていないと効かない。閉じていない継ぎ目 — 個別には全部通るのに、繋ぐと落ちる
| # | 継ぎ目 | 状態 |
|---|---|---|
| S-1 | search ↔ index build(スキーマ契約) | 🔴 1度実測で破れた。search が SELECT k, v FROM meta を読み、テーブル定義は meta(key, value) だった。本物の索引に対して no such column: k で落ちた。是正済みだが契約が4件まだ未確定 |
| S-2 | ingest(取り込み) ↔ index build | ✅ 唯一つながっている。notes/2026-09-02.md を実際に索引に通し、domain='notes' doc_date_source='path_day' で引けることを実測済み |
| S-3 | 全部 ↔ 本人の環境(FDA/TCC・iPhone・ADP・本番のパス) | ⬜ 1件も検証されていない。本人が手を動かすまで測れない |
search はダミー索引で受け入れクエリ7本を通し、index build は自分の索引で受け入れ基準5本を通した。両方とも正しく仕事をしている。それでも繋がらなかった。誰の担当範囲にも「繋ぐ」が入っていなかったからである。
したがって手順12(結合検証)は省略可能な確認ではない。これを通していない状態は MVP が完成していない状態である。
詳細: phase1-implementation.md §1(何が既に動いていて、何が未検証か)・§12(結合検証)
文書は2階級しかない — 記録と正本
「全ファイルに日付を付ける」規格は誤りだった。文書を記録(record)と正本(living)の2階級に分け、日付の有無そのものを階級の表現にする。日付を持たないことが正しいファイルが122本(35.0%・実測当時)ある。
--format full(本文つき出力)を絞らずに叩くと正本が1件も出ない(並び順が日付のあるものを先に出すため)。回避策は --domain / --path で絞ること。規約 N-0〜N-9
| # | 規約 | 根拠・実測 |
|---|---|---|
| N-0 | 文書は2階級しかない(記録/正本) | 上図 |
| N-1 | 種別と分類はディレクトリで決める。タグにしない。第1階層(=ドメイン)は現在14個で増やさない。深さは4階層以内。ルート直下は README.md 以外を置かない | domain はパス第1階層から自動で付く。⭐ タグの付け忘れが原理的に起きない |
| N-2 | 日付はパス要素の先頭に置く。<domain>/<種類>/<YYYY-MM-DD>_<topic>.md。最左が勝つ=ディレクトリが勝つ | 正本には日付を書かない |
| N-3 | YYYY-MM(月粒度)を廃止する。日次か日付なしかの2つだけ | 誤検出が実在(「2026年4月時点のデータを扱う分析文書」が日付と誤読される)。🔴 月粒度は打ち間違いの受け皿 — 2月30日を打つと「2月1日」に化ける |
| N-4 | 見出しから日付を拾う段を廃止する | いまこの段が生んでいる4チャンク・3ファイルは、すべて正本の中の1節(例: health/overview.md の「2026-10-01」は目標日) |
| N-5 | 拡張子は .md だけ。「拾わなかったもの」を毎回出す | 実測: .md 以外が132本(json 104・txt 4・ソース12・設定8・画像3・.DS_Store 1・🔴 .env 1) |
| N-6 | frontmatter は使わない | index build に frontmatter 解析コードは1行も無い。取り込みデーモンは frontmatter を剥がす。例外は AIエージェントのスキル定義ファイル SKILL.md 15本だけ(外部ツール側の規格) |
| N-7 | 日付は JST の暦日。date('now')(UTC)を使わない | 日付比較でズレる |
| N-8 | 住所を持たないチャンクを作らない(見出しが1つも無い/見出しの前に本文がある は規格違反) | heading_path='' を生むと剪定の本体が効かなくなる |
| N-9 | 本文は NFKC 正規形(Unicode の互換正規化)で書く | ひらがな/カタカナは NFKC で寄らない。SQLite は ASCII しか大文字小文字を理解しない |
実際のファイル形式
notes/2026-09-02.md — 出先メモ(記録・機械専有)# メモ 2026-09-02 > 🤖 このファイルは取り込みデーモンが追記する。人も AI も編集しない。 > 出所: iPhone ショートカット life-memo → iCloud Drive life-inbox/。 > 整理・分類はしない(設計)。 ## 2026-09-02T08:12:03+09:00 (メモ本文)health/metrics/2026-09-04.md — 計測(記録・機械専有)
# 計測 2026-09-04 > 🤖 機械が書く観測の記録。規則・項目・値の意味は README.md。 ## 2026-09-04T00:00:00+09:00 | 項目 | 値 | 出所アプリ | 経路 | | --- | --- | --- | --- | | 体重 | 未取得 | — | asken→health | | 体脂肪率 | 未取得 | — | asken→health | | 歩数 | 未取得 | — | iPhone→health | … 全10項目(体重・体脂肪率・歩数・睡眠時間・消費カロリー・ 安静時心拍数・摂取カロリー・タンパク質・脂質・炭水化物) asken = 食事記録アプリ「あすけん」
- 運動(ワークアウト)は項目を作らない。Apple Watch を着けているだけでは貯まらず、永久に埋まらない欄になるため。
- 睡眠時間は導出値。
asleepCore + asleepDeep + asleepREM + asleepUnspecified + asleep(廃止値)(HealthKit の睡眠ステージ)。inBed(就床時間)は足さない。 - 上書きせず追記する。当日・前日の値を Apple が再推定して置き換えることがあるため、同じ日付を後からもう一度取り込んで
## <ISO8601>ブロックを足す。notes/と違って重複排除しない — 測定値は同じ日付・同じ値が何度でも正当に来る。 - ⚠️ 人が
health/metrics/に手で書き足したときに検出する仕組みは、まだ無い。
健康データ取り込みの契約(原典の呼称 H-CONTRACT)
転送層(どう Mac まで運ぶか)と整形層(どう Markdown にするか)を分けるための契約。監視ディレクトリを iCloud Drive ではなく ~/.local/state/(TCC保護領域の外)に置いたので、配送手段が変わっても差し替わるのは「落とす側」だけになる。
| 項目 | 契約 |
|---|---|
| 落ち先 | ~/.local/state/personal-os/inbox-health/ |
| ファイル名 | <source>_<YYYY-MM-DD>_<HHMMSS>.<ext> 例 healthkit_2026-09-04_101500.csv |
| 完了判定 | mtime が60秒以上前。かつ同名の .part が無いこと |
| 退避 | 削除しない。ingested-health/ へ mv -n |
| 順序 | ①書く → ②読み直して確認 → ③そのあと退避 |
| ログ | 0件でも必ず1行(run done ok= skip= warn= unknown= err= other=) |
| git | 機械は git add / git commit を絶対にしない |
search は「どのファイルか」を返す道具であって、値を返す道具ではない。チャンクは行を重複させ、列ヘッダを落とし、キーワード一致は母数を欠く(実測: 食事記録28ファイル中 search "タンパク質" が当たるのは19ファイル=32%欠落)。
採る形は正本を直接横断する: grep -rh --include='2026-08-*.md' '^| 体重' health/metrics/。母数の検知器(取れた行数/ファイル数/暦日数)を必ず併記する。
詳細: health-ingest-ops.md(健康データ運用)・note-format-spec.md §1(規格)・§4(移行手順)
言語モデルを1回も呼ばない索引
index build は純粋なテキスト処理。search は LIKE の部分文字列一致とパス/日付の絞り込みだけ。ランキングを持たない。上位 k=30(約25,000字)をそのまま AI に渡す。索引ジョブの内部(段階・ふるい・分割・差分・スキーマ・失敗モード)は別紙 Markdown 索引ジョブ に詳述してあるので、本節は概要にとどめる。
索引ジョブの概要
- 索引は原本に追従する側であって、原本ではない。Markdown から一方向に生成する派生物で、失っても作り直せる。→ 索引ジョブ §1
- スケジューラは薄いラッパーを起動し、7つの段階を通る。途中で降りる出口が3つある(対象なし・変更なし・エラー)。→ §2
- 対象は4段階でふるいにかける。拡張子(
.mdのみ)・ディレクトリ名・サブモジュール・バージョン管理の除外設定。→ §3 - 見出し(H1〜H3)で割り、300字未満は併合、1500字超は分割+200字オーバーラップ。コードフェンス内は見出しとして扱わない。単位は「文字」であってバイトではない(UTF-8 バイト長で実装すると日本語で規則が実質3倍厳しくなる)。実測ではチャンクは最短8字・平均875字・最長1,499字で、「300字未満は併合」は全チャンクを300字以上にする保証ではない。→ §4
- 2つの関門で書き戻す量を絞る。ファイルの更新時刻と、チャンク本文のハッシュ(
chunk_sha)。全件作り直しは1.68秒だが、実運用ではほとんどのファイルが変わらない。→ §5 - テーブルは2つだけ。本文テーブル
chunksと、設定を持つキー・バリューmeta(8つのキー)。chunksの主な列は path/heading_path/start_line/end_line/text/chunk_sha/domain/doc_date/doc_date_source/mtime。ベクトル用の4列(embedding ほか)は最初から空で確保してある。→ §6・§7(各列が誰のどの機能を支えるか) - 3本のインデックスが 21ms を 0.35ms にする。ただし効くのは
domain = …とpathの範囲比較だけで、path LIKE 'finance/%'は全走査(4.9〜5.6ms)になる。→ §8 - このジョブの失敗はほとんどエラーを出さない。「検索結果が少し減る」という形でしか壊れないので、既知の不整合を一覧で持つ。→ §9
構想文書 §8(pgvector)と実装計画が衝突しているのは「作るか」ではなく「いつ作るか」だけである。スキーマにはベクトル列が最初から NULL で入っている。着手順は ①正解セット10問を作る → ②本人のコーパスと本人の問いでモデルを直接比べる(他人のベンチマークで代理戦争しない)。
なぜ Python 3 で書くのか — 決め手は性能ではない
索引は数秒、検索は21ms。どの言語でも誤差である。決め手は次の実測だった。
$ ls -li /usr/bin/{python3,git,clang,swift}
→ 4本とも同一 inode・118,928 B・リンク数78
$ codesign -dv /usr/bin/python3
→ Identifier=com.apple.dt.xcode_select.tool-shim-public
$ codesign -dv /usr/bin/sqlite3
→ Identifier=com.apple.sqlite3 (これだけ実バイナリ)
/usr/bin/python3 は Python ではなく、xcode-select -p の指す先へ飛ぶ shim(中継用の薄い実行ファイル)で、/usr/bin/git と同一実体である。python3 が消える条件=git が消える条件。データリポジトリは git リポジトリなので、Python 依存は既存のリスクを1バイトも増やさない。しかも壊れ方が loud(stderr+exit=1)で、「黙って空振り」にならない。
実測: この Mac には python3 が2つある(PATH先頭=Homebrew 3.14.7//usr/bin/python3=3.9.6)。launchctl getenv PATH は空なので launchd では後者になる。対話シェルで通った 3.14 の構文が launchd の 3.9 で SyntaxError になる。書いた本人は気づけない。
同じ根の問題がシェルにもある: 文字数を数える ${#str} は LANG の有無で値が変わる(実測: 同じ文字列が 12 と 36)。⭐ 「300字」の要求が実装言語の決定にかかっている。
search CLI — 現物のインターフェース
search "法人化 OR 独立" --domain finance,goals --include sessions --since 2026-01 -k 30 出力(--format full): finance/simulations/2026-03-27_incorporation-simulation.md#法人化の損益分岐 (L112-L149) [finance, 2026-03-27] <本文 852字> 必ず出す1行(件数の内訳 — 日付の出所別/ドメイン別): 32件 [日:21 月:6 見出し:3 不明:2] finance:12 goals:5 sessions:0
| オプション | 意味 |
|---|---|
| query | スペース区切り=AND / OR=OR / "…"=フレーズ / -語=除外 |
| --format | files=ファイル一覧+ヒット数(既定・剪定用)/ full=本文 / paths=住所(パス+見出し+行番号)だけ |
| -k | full/paths で返すチャンク数の上限(既定 30) |
| --domain / --path | ドメイン列挙/パス前方一致で限定 |
| --include | 既定除外を解除。既定で除外されるのは sessions(AIエージェントの作業記録)・pokemon(趣味の対戦記録)・.claude(AIエージェントの設定) |
| --since / --until | doc_date の下限/上限(YYYY-MM または YYYY-MM-DD) |
| --include-undated | 日付フィルタ時に doc_date IS NULL(=正本)も残す。既定は落とす |
| --per-file / --max-bytes | 1ファイルからの上限(既定3)/本文つき合計バイト上限(既定24000) |
なぜ LIKE で足りるのか(要点)
全件走査(6,411,071字に対して5語)で中央値 21ms(再現あり 18.8〜20.1ms)。全文検索エンジン(SQLite FTS5)は既定のトークナイザで MATCH "体重" が 🔴 0件・エラーも警告も無し(LIKE なら54件)。⭐ LIKE を採ったことで日本語2文字語の問題が構造的に消えた。FTS5・pgroonga・bigram 分割・多層の検知テスト案のいずれも MVP には要らない。器が SQLite である決め手も検索アルゴリズムではなく、常駐ゼロ・macOS標準・単一ファイルで rm 1回である。
実測値の一覧と索引の効き方: 索引ジョブ §8
SQLite の LIKE は既定で ASCII の大小を無視する。ON にすると本文検索が大小を区別しはじめ、実測では大文字を含む固有名詞が小文字パターンに NO MATCH になった。直したい箇所とは別の場所が壊れる。
索引の現在のかたち(概要)
合計 10,073 チャンク/362ファイル・28.6MB(2026-09-04 14:39 時点)。内訳は sessions 6,038・pokemon 1,777・projects 1,293 が上位で、sessions と pokemon だけで 77.6% を占めるため既定除外になっている。ただし除外は削除ではない — 過去の問いの答えが sessions/ の中の 666KB のファイルにあった実例がある。
🔴 チャンク数は「一致」を合格条件にできない。同じ対象に測り方の違う数字が複数存在する(7,853 / 8,207 / 8,362 / 8,456 のどれも正しい)。受け入れ基準で数字が「関係式・範囲」で書いてあるのは意図的で、sessions/ が単調増加するので引き直せばまた別の数字になる。
ドメイン別の全内訳: 索引ジョブ §3「索引の中身の偏り」/既知の不整合: §9
採らなかったものを、なぜ採らないかごと残す
構想(requirement.md)の技術選定は、実装計画セッションでほぼ全面的に置き換わった。ただし行は消していない。消すと、実装時に同じ案を揺り戻す余地が残るためである。左が初期案、右が決定。
grep だけで両方通った。器は pgvector とは限らない(ローカル完結が前提のため).gitignore に *.m4a 等を実績が無いうちに足す(一度履歴に入ると git filter-repo なしでは消せない)。将来「音声メモ」を実装するとき、この節は再び有効になる(00_inbox/ 01_me/ 02_projects/ …)
life/ が本体である。実測: §13の11項目のうち対応物が無いのは 00_inbox/ と 99_archive/ の2つだけ(後者は git履歴が代替)。逆に §13 には health/ も finance/ も sessions/ も無い。sessions/ 単体でリポジトリの .md 行数の 53.9%(84,116行)を占めるので、新設すると「第二の脳」を名乗るディレクトリが本人のデータの半分を含まない状態になる。採る形: 既存355ファイルを1バイトも動かさず、notes/ と bin/ を足すだけ。相対リンク202本も1本も壊れない。移行 約30分→ API → Supabase
[[wikilink]]life/ に開くこと — second-brain/ に開くとデータの53.9%が外に出る。[[wikilink]] は採らない: 実測でファイル名(basename)が衝突している(リポジトリ中24種類・131ファイル=40.6%。[[dashboard]] は76ファイルのどれかを指す)domain にはこの問題が無い.claude/skills/search/SKILL.md 1枚と search CLI で足りる。MCP(AIと外部ツールをつなぐ接続規格)を足すとアプリAとアプリBの接点が1本増える。必要になったら足すリマインダー / メモ.app
~/Library/Reminders も同じTCCの壁だった§19(AIが変わってもデータは自分のものとして残る)は、撤回されるどころか強化された。ローカル完結を選んだ結果、Anthropic にも Supabase にも Apple にも依存しない状態になっている。
各案の検討過程: mvp-implementation-plan.md・searchplan.md
構想の5フェーズと、実際に走っている手順
構想(§18)は Phase 1〜5 の階段だった。実装計画はそれを畳み直し、「iPhoneからメモ → 蓄積 → 検索して引ける」という本人の言葉の MVP を1本道にした。両者はこう対応している。
手順0〜14 — 現在の進捗
上から順に。前が終わらないと次は無駄になる。合計 約3.5〜5時間、うち本人が手を動かすのは 66分。各行の「AI」は AIエージェントが代行する作業、「👤」は本人が実機・GUI を操作する作業。
/bin/bash に FDA(フルディスクアクセス)を付与👤・5分/⚠️ 代償あり👤 ⬜.gitignore を追記AI・5分/🔴 手順6 より前(必須)。順番を逆にすると履歴から消せない✅notes/ + bin/ + CLI の置き場所AI・5分✅life-memo(7アクション)👤・30分/🔴 この節だけは1件も実測されていない👤 ⬜bin/ingest-notes.sh + テスト + launchd 設定(plist)AI・30〜45分/327行・回帰テスト 19ケース / 51アサーション PASS✅ 実装 ⬜ 本番life-memo を割り当てる👤・3分👤 ⬜index build + テーブル定義(DDL)を置いて本番の索引を1回作るAI・20〜30分/885行・本物のコーパスで動作確認済み✅search CLI を置くAI・20〜30分/542行・受け入れクエリ7本 0.13秒✅search × 本番の索引 × notes/)AI・30分/⭐ MVP 完成条件。実際に落ちた工程である⬜.claude/skills/search/SKILL.md を1枚書くAI・10分/対話中の AI が会話の中で過去の記録を引けるようになる⬜ 未作成各手順の受け入れ基準・所要・検証手順: phase1-implementation.md §2(手順0〜14 の一覧)
作るもの4つのうち3つは既に動いている。それでも bin/ingest-notes.sh は本物の iCloud life-inbox/ を1度も触っていない(FDA未付与で ls が DENY)。このスクリプトが存在する唯一の理由が、唯一テストされていない部分である。
MVP に入れないもの — 「落ちたのではなく、順番が後」
| 入れないもの | 着手条件 / なぜ入れないか |
|---|---|
| ベクトル検索 | ①正解セット10問を作る → ②本人のコーパスでモデル比較。これが無いと ranking も再ランカーも評価できない |
| BM25 / FTS5 / pgroonga | LIKE が21msで足りる。BM25は「無くても足りる」ではなく「あっても順位を直さない」。着手条件: コーパス10倍かランキングが必要になったら |
| Query Understanding(問いの解釈層) | AIエージェントから使う限りLLMは既に会話の中にいる。足すべきは別のもの(AIを呼べない口のUI) |
events/(Event Log) | AIエージェントの会話ログ保持期間を10年(cleanupPeriodDays: 3650)に設定したことで会話ログの消失が止まり、「後からでは取り返せない」から「後からやっても同じ」に移った。🔴 未決: events/*.jsonl は索引の対象か。いまの分割器は life/**.md しか見ないので、このままだと events/ は検索から完全に見えない |
insights/(AIが生成する洞察の置き場) | 書き込む主体がベクトル待ちで止まる。生産者がゼロのディレクトリを先に作らない |
data/health/*.csv | 実測: リポジトリに .csv は0件。「CSVのまま」は現状維持ではなく新形式の導入で、health/weight.md からの移行作業が別に要る |
旧名ディレクトリ ClaudeCodeClient → PersonalOS の改名 | 動くものが1バイトも増えない。sessions/ 外だけで39箇所+相対リンク8本を壊す(設計の正本文書は今も旧名ディレクトリにある) |
叩いても答えが出ない — 本人の判断が要る事項
実測で決められるものは全部決めてある。残っているのは測っても答えが出ない種類の問いと、その手前で止まっている実機作業である。
いま止まっている 66分
| 手順 | 所要 | なぜ代行できないか |
|---|---|---|
| FDA の付与 | 5分 | GUI。システム設定を触る |
| iCloud Drive に他プロセス製のファイルを置く | 3分 | Finder / TextEdit。実測: 対話シェルも AIエージェントも iCloud Drive は Operation not permitted |
| プローブ(検証用ファイル)の設置・判定 | 12分 | ⭐ AI が代行できる |
| ADP を ON | 10分 | GUI |
| iPhone ショートカット | 30分 | 実機 |
| オフライン実測 | 15分 | 実機 |
| 背面タップ | 3分 | 実機 |
判断が要る事項
| # | 問い | 選択肢 → 帰結 |
|---|---|---|
| J-1 | 旧名ディレクトリ ClaudeCodeClient を PersonalOS に改名するか | する→名前が実体に合う。39箇所+リンク8本を直す / ⭐ しない(推奨・MVP期間中)→注記だけで要件定義の並走は止まる |
| J-3 | Time Machine の宛先を設定するか | 実測: tmutil destinationinfo → "No destinations configured"。現在バックアップは GitHub への push だけで、未コミット分は失われる |
| J-5 | AIエージェントの自動メモリ(会話をまたいで保持する記憶ファイル)をデータリポジトリへ移設する範囲 | ⭐ memory/*.md のみ(17ファイル・68KB・推奨) / ディレクトリ全体(119MB)→112MBがgit履歴に入り消せない。しかもエラーは出ない |
| J-6 | 索引に sessions/(AIエージェントの作業記録)を含めるか | ⭐ 既定は除外・--include で戻す(推奨)。索引なし検索実験の問い1(「アプリの収益化について過去1年間に考えたこと」)の答えは sessions/ の中の666KBのファイルにあった。単純除外では答えが消える。2026-03〜08-23の記録は sessions/ の作業記録にしか残っていない(同期間の会話ログは消失済み) |
| Q-6 | 正本の更新イベントをどこに書くか 🔴 設計検討に当たった2エージェントの結論が一致した、唯一の「本人の裁定が要る」事項 | 案A: いまの作業記録の ## Updated Files 節のまま・ノイズを我慢 / 案B: docs/changelog/YYYY-MM-DD.md に1行足す・正確さを取る。現況実測: 正本137本中72本(52.6%)が無記録 |
| 9-1 | 月次記録7ファイル(finance/cashflow/2026-08.md 等)の行き先 | A: 締め日の記録にする / B: 日付なしの正本にする。N-3(月粒度廃止)を適用すると必ずどちらかに倒す必要がある |
文書と現物のズレ(実測で確認)
✅ 実測済 2026-09-04 14:39〜15:05 に索引と実ファイルを直接確認した結果、仕様と実装が一致していない箇所が4つある。
| 仕様 | 現物 |
|---|---|
N-3 / N-4(YYYY-MM 廃止・見出し段廃止)。文書は「確定仕様」と書いている | 🔴 未実施。索引の doc_date_source 分布は path_day: 7,332 / NULL: 2,642 / path_month: 95 / heading: 4。コード側にも両方の段がまだ残っている |
docs/changelog/(正本の更新イベントの置き場所) | ⬜ 未作成。Q-6 が未決なので整合的 |
.claude/skills/search/SKILL.md(手順13) | ⬜ 未作成。対話中の AI が会話の中で過去の記録を引く口がまだ無い |
| launchd ジョブ3本 | ✅ 完全一致で稼働中。数少ない「文書=現物」の箇所 |
旧形式の health/weight.md は 2026-09-04 で凍結され(最終行 2026-08-28)、新形式の health/metrics/ はパーサ未実装で全項目「未取得」のプレースホルダのまま。移行期間中、体重の新規記録が落ちる先が無い空白が発生している。
「日付単位で試行過程を引きたい」(A)は実装ゼロで今日から使える: search "<語>" --include sessions --since D --until D。「sessions を既定除外から外す」案は不採用 — 出力上限(既定 24,000 バイト)に達するまでの余裕が約35ファイル=3〜6日分しかなく、恒久設計にならないため。
残っているのは(B)正本の更新イベントの置き場所(Q-6)だけで、こちらは技術的には決着していて運用の裁定を待っている状態。追加実装は検知器1本(bin/check-change-log.sh)のみの予定。