個人健康データ基盤「yuru」運用記 その4 — ファイルを1つ動かせなかった:Synology Driveの共有をチームフォルダに作り直すまでの3日間

前回(その3)は、AIの記憶の誤りを制度で潰しながら、180万サンプルの救出と3階層バックアップまでを書いた。締めで「能動的な実装キューは空になった」と書いたが、yuru はその後も、サプリの組み替え実験で小さく動き続けている。今回はその実験の途中で起きた、ごく小さな作業の話だ——レシピ文書を1枚、Obsidian のアーカイブフォルダへ移す。それが Synology Drive の権限構造に阻まれ、3日がかりの引っ越しになった。通奏低音はその3の続きである。今回間違えたのは主にチャット側の Claude で、それを止めたのは、ログと設定を実際に読んだ Claude Code だった。自分の勉強用メモ。


この記事の位置づけ

体制はその3と同じ。調査と実装は Claude Code、方針の壁打ちとブリーフはチャット側の Claude、判断と GUI 操作は私。今回は NAS の DSM、各端末の同期アプリ、Mac の Drive クライアントと GUI の操作が多く、私の手番がいつもより多い。

舞台は yuru 本体ではなく、その周辺である。サプリのブレンドレシピは Obsidian の Vault に置き、Vault は Synology Drive で家中の端末と Mac Studio に同期している。yuru のサプリの記録と Vault のレシピ文書は対で運用していて、レシピを改訂するたびに Claude Code が両方を更新する。

今回扱ったテーマは8つ。

  1. レシピを1枚、アーカイブへ動かすだけだった
  2. 共有されたフォルダは、消せない
  3. 前提が3つ崩れた
  4. 見覚えのない端末「T1201」
  5. コピーは一致、権限は全滅
  6. Mac側は、作り直しを2回
  7. 毎朝4時に旧Vaultへ書いていたもの
  8. 撤去と、バックアップの線引き

1. レシピを1枚、アーカイブへ動かすだけだった

Obsidianに置いているサプリのブレンドレシピを、v3からv4に改訂した。作業はClaude Codeに任せた。v4を新規作成し、v3を同じフォルダのアーカイブ/へ移す。それだけのはずだった。

報告は「v3の移動が完了していない」だった。Synology Driveのクライアントは、リネーム(移動)を「削除+追加」に分解してサーバーへ送る。追加は通ったが、削除は権限不足で拒否され、消したはずのv3がサーバーから書き戻された。結果、v3が元の場所とアーカイブの2か所に並んだ。

Claude Codeは別の手も示した。NASに管理者でSSHし、サーバー上のファイルを直接消す。ただしそれは共有の権限設定を迂回する操作なので、自分の判断ではやらない、と止まって聞いてきた。ここで止まってくれたのは正しかったと思う。迂回で1枚消しても、次に整理するときにまた同じ壁に当たる。

2. 共有されたフォルダは、消せない

原因は構造にあった。

このVaultは、家の端末が共通で使っているDriveのユーザー(以下「端末用ユーザー」)のMy Driveに置かれていて、Mac StudioのDriveクライアント(Claude Code用の別ユーザー)には「自分と共有」で見せていた。Synology Driveの個人共有では、共有された側はファイルを足せても、所有者のファイルを消したり名前を変えたりはできない。Claude CodeがVaultを整理しようとするたびに、この壁に当たる構造だった。

設定1つで直る話ではないので、置き場所ごと変えることにした。チームフォルダ。DSMの共有フォルダをDriveで同期できるようにしたもので、権限は共有フォルダのACL(読み書き)だけで決まり、「所有者」という概念がない。Claude Code用の同期フォルダ(会話ログのアーカイブ)が既にこの方式で動いていたので、その横展開になる。

分担はこうした。DSMでの共有フォルダ作成とチームフォルダ化、各端末の同期設定は私がGUIで。NASへのSSHでのコピーと検証はClaude Codeに。旧Vaultは最後まで消さず、全端末が新しい方へ移ってから撤去する。

3. 前提が3つ崩れた

コピーに入る前の権限確認で、Claude Codeが止まった。

1つ目。ユーザー名が違った。 チャット側のClaudeは、スマホのDriveアプリでアカウント名の下に出ていた文字列をDSMのユーザー名と読んで、ブリーフに書いていた。NASにそんなユーザーはいなかった(/etc/passwdにもhomesにもない)。実際のVaultは端末用ユーザーのホームにあった。画面の文字列は、ユーザー名ではなく接続先の名前だったらしい。

2つ目。新しいフォルダに、本当の利用者の権限がなかった。 私が作ったチームフォルダには、管理者とClaude Code用ユーザーの読み書きは付いていたが、端末用ユーザーが無かった。このままでは、Mac Studio以外の全端末が新しいVaultに入れない。

3つ目。スマホの同期が止まっていた。 スマホのDriveアプリを開くと、Vaultの同期タスクが「同期できません。再度タスクをセットアップしてください」のまま、2日近く止まっていた。別の同期タスクも同じ状態。v3の重複を見て、私はスマホから元の場所のv3を消していたのだが、その削除はNASに一度も届いていなかった。DriveアプリのファイルタブはNASを直接見ているので閲覧はできてしまい、同期が止まっていることに気づかなかった。

スマホのDriveアプリ。同期タスクが2つとも止まっていた

4. 見覚えのない端末「T1201」

切り替えの対象を決めるため、Claude CodeにDriveのログから「旧Vaultを同期している端末」を洗わせた。MacBook Air、Windowsの録画機、Mac Studio、Galaxy Z Fold7(型番SM-F966Q)。ここまでは分かる。退役済みの旧録画機が1台、8月を最後に接続していないのも分かる。

残る1台が分からなかった。T1201という名前のAndroid端末が、前日の夜にもVaultへ書き込んでいた。

チャット側のClaudeは「同じGalaxyがアプリの再ログインで再登録され、名前が変わっただけ」という仮説を出した。活動期間が重なっていないように見えたからだ。Claude Codeはログを突き合わせて、これを否定した。

  • T1201が登録された後も、SM-F966Qは使われ続けていた
  • 8月のある夜、40分ほどの間に、2台が別々のIPから同じノートを交互に編集していた
  • 自宅のDHCP(Mac Studioのdnsmasq)のリースに、同時期に2つのMACアドレスがあった。SM-F966Qはホスト名「Galaxy-Z-Fold7」で裏が取れたが、T1201はホスト名を名乗っておらず、MACもランダム化されていた

同じ時間に同じノートを2台で交互に書いているなら、私が2台を手に持っていたことになる。思い当たったのが、机の横で電源に挿しっぱなしのタブレット(ALLDOCUBE iPlay 60 Pad Pro)だった。

設定画面に出ているWi-FiのMACアドレスは、Claude Codeが報告した値と一致しなかった。ただし同じ画面に、IPv6のリンクローカルアドレスも出ていた。fe80::7061:eaff:feac:341f。これはMACアドレスから作られる形式(EUI-64)で、真ん中のff:feを取り除き、先頭バイトの1ビットを戻すと72:61:ea:ac:34:1f。ログのT1201の値そのものだった。画面のMACは端末本来のもので、自宅のWi-Fiに対しては別のランダムなMACを名乗っていた、というだけだった。

タブレットの状態画面。IPv6のリンクローカルアドレスからランダムMACを復元できた

T1201はメーカーの内部型番らしい(シリアル番号の先頭が同じ系統)。稼働時間は1346時間、56日連続。存在を忘れていても無理はない。

5. コピーは一致、権限は全滅

コピーはrsync -rltで行った。権限・所有者を保持しない形にしたのは、共有フォルダのACLを継承させたかったからだ。除外は2種類。NASが自動で作るサムネイル置き場の@eaDirと、重複していた元の場所のv3。

ファイル65件・1,431,734バイト、SHA-256は全件一致。ここまでは良かった。

ところが、コピー先の88件(ファイル65、ディレクトリ22、Vault本体)のACLを見ると、全部がSynologyのACLを失った「Linux mode」になっていた。 Vault本体と.obsidianはパーミッション700で、端末用ユーザーもClaude Code用ユーザーも中に入れない。

rsyncは-pを付けなくても、新しく作ったファイルの最終的なモードをchmodで整える。SynologyのACLは、chmodが走った時点で外れて素のLinuxのパーミッションに戻る。-pを外すだけでは防げなかった。

直し方はSynologyのsynoacltool -enforce-inherit(親のACLの継承を強制し直す)。中身に手を付けないので、SHAの突合をそのまま活かせる。ところが実行すると、直ったのはVault本体の1件だけだった。このコマンドは指定したパスにしか効かず、配下へは再帰しない。 findで親から順に1件ずつ当てて、88件すべてが継承ありになった。

find /volume1/obsidian/Obsidian_Vault -mindepth 1 \
  -exec synoacltool -enforce-inherit {} \;

中身が変わっていないことは、65件のSHA-256を並べた一覧のハッシュで確かめた。実行前も後も同じ値。「何も変わっていない」ことを1行で言える検証は便利だった。

6. Mac側は、作り直しを2回

Mac Studioに同期タスクを作り、Claude Codeに突合を頼むと、今度はlsが返ってこなかった。

タスクがオンデマンド同期で作られていた。オンデマンド同期はmacOSのFile Provider経由になり、プロセスがファイルに触るたびに、macOSのプライバシー制御(TCC)がアクセス許可を確認する。ログには、Claude Codeの親プロセスの名前で許可を求めたまま、結果が出ない記録が残っていた。Mac Studioは画面の前に人がいないサーバーで、ダイアログに答える人がいない。毎朝Vaultに書く常駐スクリプトも、同じ場所で止まるはずだった。

8月にブログの受け渡しフォルダで同じ罠を踏んでいた(作成ウィザードの終盤で、オンデマンドのチェックが勝手に復活する)。今回も詳細設定でチェックを外して作り直した。

配置でも1回やり直した。Driveクライアントは同期タスクの入れ子を許さないので、オンデマンドのときは希望の場所に置けず、一段深い不格好なパスになっていた。通常同期で作り直すと、既存の会話ログのアーカイブと同じ階層にまっすぐ並んだ。

Driveクライアントの同期タスク一覧(作り直し前。オンデマンドの雲マークが付いている)

突合ではもう1つ差が出た。.obsidianと.trashの12件が降りてこない。同期タスクの既定のフィルタが「.で始まる名前を除外」になっていた。Mac StudioにはObsidianのアプリが入っていないので、設定ファイルを同期する理由がない。外さずに「意図的な除外」として記録した。Claude Codeが誤ってObsidianの設定を触る可能性が消える、という副産物もある。

7. 毎朝4時に旧Vaultへ書いていたもの

旧Vaultのパスを参照しているものを洗わせると、1つ見つかった。毎朝4時に、自宅ネットワークの管理ノートの自動生成部分を書き換えるLaunchAgent。終わるとUptime Kumaにpushで生存を知らせる。

旧経路を先に消していたら、翌朝からこのジョブは失敗し、Kumaが落ちて通知が鳴っていた。撤去の順序はこう決めた。

  1. スクリプトの参照先を新しいVaultに切り替えて、手動で1回実行する
  2. 翌朝4時の定期実行が成功したことを確かめる
  3. それから旧経路を消す

2で1つ引っかかった。翌朝スマホでKumaを開くと、緑の「正常」。ただ、このモニターは25時間に1回のpushを待つ設定なので、前夜の手動実行のビートだけでも朝は緑になる。緑は「4時に動いた」証明にならない。スマホの画面では最新ビートの時刻が出なかったので、Claude Codeに3点を見させた。実行ログの最終行、ノートの更新日時、Kumaの最新ビート。3つとも4時0分5秒で揃って、合格にした。

Kumaのモニター。緑でも、最新ビートの時刻を見ないと判定できない

8. 撤去と、バックアップの線引き

端末の切り替えは私がやった。MacBook AirとWindows機はDriveクライアントで、Galaxyとタブレットはアプリで、新しいチームフォルダの同期タスクを作り、Obsidianで保管庫を開き直す。旧Vaultのフォルダに被せず、別のフォルダに作るのがポイント。確認として、1台で無題のファイルの名前を変え、残りの3台に届くのを見た。

撤去は、Mac StudioのDriveクライアントで旧タスクを削除、旧Vaultの共有を解除してごみ箱へ、退役した録画機のクライアント登録を解除、の3つ。

ここでも1つ。Driveクライアントは、同期タスクを消してもローカルのフォルダを消さない。 旧Vaultのコピーが66件、Mac Studioに残っていた。Claude Codeに新しいVaultと突き合わせさせると、同一62件、名前が変わっただけが1件(端末の同期確認で私がリネームしたファイル)、意図的に除外したv3が1件、違いがあるのは自動生成部分と端末依存の設定ファイルだけの2件。旧側にしかない内容はゼロと確かめてから、ゴミ箱へ移した。

最後に、話がバックアップに逸れた。毎朝のスクリプトはリモートのないgitリポジトリで、正本がMac Studioの中にしかない。健康データ用に作ったNAS+クラウドの3段のバックアップに、~/toolsも足すべきではないか。

足さないことにした。あのバックアップは「健康データを、家ごと失う事故からも守る」ために設計と検証をしたもので、性質の違うものを混ぜると、容量も暗号化の鍵も週次の確認も意味がぼやける。Mac Studioの環境全体は、NASへのTime Machineが1時間ごとに取っていた。チャット側のClaudeは最初、tmutil statusのRunning = 0を「動いていない」と読んでいたが、それは「今この瞬間はバックアップ中でない」という意味だった。

9. このセッションで固まった設計原則(追記版)

  • 同期の権限は設計で解く — 個人の共有は「見せる」ための仕組みで、複数の主体が整理する場所には向かない。迂回で1回消すより、所有者のいない置き場へ移す方が安い
  • Synologyで中身を移したら、ACLを全件見る — rsync -rlt でもACLは外れる。synoacltool -enforce-inherit は再帰しない
  • ヘッドレス機にオンデマンド同期は使わない — 許可のダイアログに答える人がいない
  • 「変わっていない」は一覧のハッシュ1つで言う — 修復の前後、移行の前後で同じ値が出れば十分
  • 撤去は、依存を先に切り替えて本番の1周を見てから — 旧経路を消すのは、定期実行の成功を確かめた後
  • バックアップは目的ごとに経路を分ける — 健康データを家ごと失う事故から守る経路と、環境を丸ごと戻す経路は別の仕組みにする

アンチパターン集(追記)

  • 所有者のいるフォルダを共有して、複数の主体に整理させる — 削除とリネームが通らない
  • 画面の文字列を確かめずに識別子として使う — 接続先の名前をユーザー名と読んだ
  • 閲覧できることを、同期できている証拠にする — アプリのファイル一覧はNASを直接見ている
  • 緑の監視画面で定期実行の成功を判定する — 間隔の長い push 型は、前回のビートで緑のまま
  • 同期タスクを消せばローカルも消えると思う — Drive クライアントはフォルダを残す

おわりに

その3の結びに、AIの記憶の弱点は「それを前提とした制度に」置くと書いた。今回、その制度は記憶以外のところでも効いた。チャット側の Claude は、ユーザー名を読み違え、別々の端末を同じ端末だと決めつけ、動いている Time Machine を止まっていると読んだ。どれも、ログと設定を実際に読んだ Claude Code が止まって聞いてきたことで、手戻りが小さく済んだ。推論の強いAIでも、前提は実物で崩れる。崩れたときに止まる仕組みがあるかどうかが、分業の質を決める。

ファイル1つを動かすつもりが、3日がかりの引っ越しになった。ただ、途中で見つかったのは、止まっていたスマホの同期、忘れていたタブレット、旧Vaultに書き続けるスクリプトと、どれも放っておけば別の日に別の形で表に出ていたものばかりだった。その3で書いた「小さな要望の実装を丁寧にやると、システムの本当の弱点が芋づるで出てくる」は、今回もそのまま当てはまった。


このシステムはローカル完結・個人利用。Vault も健康データも自宅の NAS と Mac Studio の中にあり、外部には出していない。「個人の健康データ基盤『yuru』をゼロから作り直して運用に乗せるまでの全記録」「運用記 その2」「運用記 その3」の続編。