— 巻物について —

なぜ影分身を
作っているか

契約書も議事録もアイデアも、放っておけば埋もれる。検索しても形式がバラバラで掘り当てられない。 書いた本人ですら忘れる情報を、自然な言葉で問い返せる状態にしたい —— そこを出発点に、個人が扱う知識の「記憶補助」を AI に委ねる実験として作っている。

— 三つの原則 —

形式を問わない

契約書も CSV も走り書きの Markdown も、同じ入口で投げ込めること。ユーザーに形式を意識させたら負け。

意味で分解する

全文検索は「単語が一致するか」しか見ない。影分身は AI が意味の粒度 (全体 / 章 / 事実) で切り分け、どの高さからでも掘れるようにする。

呼び出しは会話で

ファイル名を覚えているわけがない。「先月の予算会議の話」で通じる呼び出し口を、ベクトル検索 + RAG で作る。

— 三層構造とは —

投入されたデータはその場で Macro (全体像)、Meso (章や節のまとまり)、Atom (段落・行・事実の最小単位) に切り分けられ、すべてに 1024 次元のベクトル埋め込みが付きます。

粒度を決め打ちしないので、 「この契約書の要点は」という俯瞰的な問いにも、 「第 12 条の違約金はいくらだったか」という事実単位の問いにも、 同じエンジンで応じられます。

さらに、複数の巻物の間で値が一致する箇所を AI が裏で発見し絆陣 として結び直します。別々に投げ込んだ契約書と見積もりが「同じ取引先ですね」と気づいてくれる、そのための仕組みです。

— 技術選定 —

フレームワーク
Next.js 16 App Router + Turbopack

Server Components と Route Handlers が tRPC と自然に接続。Edge と Node の使い分けも細かく決められる。

API レイヤ
tRPC v11 + Zod v4

フロントとバックで型が途切れないこと。全 mutation が Zod で boundary validation される安心感。

データベース
PostgreSQL + pgvector (Drizzle ORM)

ベクトルとリレーショナルを 1 箇所に。Drizzle のスキーマ駆動で migration も PR レビュー可能に。

非同期処理
Inngest (concurrency by userId + memoryId)

Claude / Voyage の呼び出しを step 単位でリトライし、同じ Memory の並行処理を阻止できる。

LLM / Embedding
Anthropic Claude + Voyage AI

Claude は日本語の構造化精度が高く、Voyage voyage-3-large は 1024 次元で検索速度と品質のバランスが良い。

認証 / 配信
Clerk + Vercel

認証の boilerplate を書かず、Next.js の deploy パイプラインと噛み合う。

— 守りの設計 —

個人の資料を預けるには、漏らさないこと・壊さないことが前提です。 このコードベースで意識している具体的な防御策:

  • 全 tRPC mutation で `userId` の WHERE 条件を明示 (二重防御)
  • URL 取込は SSRF ガード (private ネット遮断 + streaming size cap)
  • Fragment parent cascade / connection_pairs の UNIQUE index で orphan を防止
  • Inngest concurrency を userId + memoryId でキーイングし同一 Memory の race を排除
  • X-Frame-Options / HSTS / Referrer-Policy / Permissions-Policy を配信ヘッダに

— 作り手 —

個人開発者 mohadayo が、自身の仕事の資料を整理する道具として作り始めたプロジェクトです。 コードは GitHub で公開しており、改善提案・バグ報告は Issue / PR で歓迎しています。