Obsidianはしばしば「メモ帳」「ナレッジベース」「第二の脳」と表現される。しかし、設計書や技術文書を扱っていると、これらの表現には違和感が残る。
自分の感覚では、Obsidianは「書き溜める場所」ではない。 むしろ、文章を圧縮し、分解し、再利用可能な形に整えるための帳面に近い。
本記事では、Obsidianを「圧縮帳」と捉える視点と、なぜ設計書において特にこの使い方が有効なのかを整理する。
生成AIは非常に便利だが、現状は「文章を増やす方向」に強く偏っている。
その結果、文章は読みやすいようでいて、責務が混ざり合った塊になりがちである。
これはコードで言えば、
に相当する状態だ。
設計書の最終的な成果物は「コード」である。 そしてコードは、クラスやモジュールといった役割を持った部品の組み合わせとして表現される。
にもかかわらず、設計書だけが
という未圧縮状態のままだと、次の工程で歪みが生じる。
設計書が未圧縮だと、コードを書く段階で誰かが「圧縮」することになる。 これはバグや認識ズレの温床になる。
ここで重要になるのが、文章のSRP(単一責務原則)という考え方である。
これはコード設計では当たり前の感覚だが、自然言語ではあまり意識されてこなかった。
Obsidianのリンクは、単なる関連付けではない。
文章中で、
それは「この部分は独立した責務を持ち始めている」という合図である。
その内容を丸ごとリンク先ノートに移し、元の文章にはリンクだけを残す。
これは、
という行為と本質的に同じである。
文章をインラインで書き続けると、知識は直積的に増殖する。
これをObsidianのリンクによって分解すると、
という形に分離できる。
結果として、情報量は減るが、意味量は減らない。 これは可逆圧縮に近い。
文章を強く圧縮すると、通常は「読みにくさ」が問題になる。
しかしObsidianでは、
つまり、展開コストが極端に低い。
これはIDEで
体験とよく似ている。
プログラマーは長年、IDEを通して次の知恵を身につけてきた。
Obsidianは、この設計思想を自然言語の世界に持ち込んだツールだと考えられる。
つまり、
| ノート | クラス |
| リンク | 参照 |
| グラフ | 構造図 |
| AI | リファクタリング補助 |
という対応関係が成立する。
Obsidianは、メモを溜める場所ではない。
そのための「圧縮帳」である。
生成AIと組み合わせることで、
という分業が可能になる。
ーーーーーーーーーーーーー
圧縮処理をシステム化するには、ドキュメントのライフサイクルを管理する必要がある。
vault/ ├── 00_inbox/ # 圧縮前の生ドキュメント(投入口) ├── 01_processing/ # 圧縮処理中 ├── 10_concepts/ # 用語・概念(クラス相当) │ ├── terms/ # 用語定義 │ ├── patterns/ # パターン・原則 │ └── domains/ # ドメイン知識 ├── 20_docs/ # 圧縮済みドキュメント(本体) │ ├── design/ # 設計書 │ ├── specs/ # 仕様書 │ └── notes/ # 考察・メモ └── 90_archive/ # オリジナル保存(参照用)
--- status: raw | processing | compressed | archived source: "90_archive/original_filename.md" compressed_at: 2025-01-17 extracted_concepts: - "[[SRP]]" - "[[God Class]]" compression_ratio: 0.6 ---
┌─────────────────────────────────────────────────────────┐
│ Human Layer │
│ ┌─────────────────────────────────────────────────┐ │
│ │ Obsidian UI + Plugins │ │
│ │ - Dataview(ステータス一覧、未処理件数) │ │
│ │ - Templater(承認・却下のワークフロー) │ │
│ │ - Graph View(概念の関係可視化) │ │
│ │ - Hover Preview(リンク先の即時確認) │ │
│ └─────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────┘
│
Vault (共有層)
│
┌─────────────────────────────────────────────────────────┐
│ Agent Layer │
│ ┌─────────────────────────────────────────────────┐ │
│ │ Claude Code Custom Agent │ │
│ │ - inbox監視、圧縮処理、概念抽出・ノート生成 │ │
│ └──────────────────────┬──────────────────────────┘ │
│ ┌──────────────────────▼──────────────────────────┐ │
│ │ MCP (Obsidian連携) │ │
│ │ - ファイル操作、検索、frontmatter操作 │ │
│ └─────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────┘
| 処理 | 担当 | 理由 |
| ファイル投入 | 人間 | 何を圧縮対象にするかは人間判断 |
| 抽出候補の提示 | エージェント | パターン検出は機械が得意 |
| 抽出の承認 | 人間 | 概念の粒度・命名は人間判断 |
| 圧縮実行 | エージェント | 機械的な置換処理 |
| 概念の再利用判断 | 人間 | 文脈依存の判断 |
| リンク先ホバー確認 | 人間 | 読み手としての体験 |
Obsidian内のノートをデータベースのように検索・集計・表示できるプラグイン。SQLやExcelのフィルタに近い感覚で、vault内の情報を動的に抽出できる。
リスト表示:
```dataview LIST FROM "00_inbox" WHERE status = "raw" ```
テーブル表示:
```dataview TABLE status, file.mtime as "更新日" FROM "20_docs" SORT file.mtime DESC LIMIT 10 ```
| 情報 | 例 |
| frontmatter | status, tags, created など自由に定義 |
| ファイル情報 | file.name, file.mtime, file.size |
| インラインフィールド | 本文中の key:: value 形式 |
| タグ | #tag |
| リンク | <nowiki>link?</nowiki> |
MCP経由でDataview DQLを実行できる:
const result = await mcp.search_vault({
query: 'LIST FROM "00_inbox" WHERE status = "raw"',
queryType: "dataview"
});
人間もエージェントも同じDataviewクエリ言語で情報にアクセスできる。
「こんな検索がしたい」から逆算してスキーマを決める。
--- # === 識別 === type: design_doc doc_type: 基本設計 | 詳細設計 | IF設計 | DB設計 target_system: "決済システム" domain: 金融 | 公共 | 社内 # === バージョン === version: "1.2" created: 2025-01-10 changed_at: 2025-01-17 change_summary: "エラーハンドリング追加" # === ワークフロー === status: draft | review | approved | done assignee: "[[田中]]" due_date: 2025-01-31 # === レビュー === reviewer: "[[鈴木]]" review_status: none | pending | done review_date: # === 依存関係 === depends_on: - "[[認証モジュール]]" - "[[共通エラー処理]]" # === 圧縮管理 === compression_status: raw | normalized | compressed extracted_concepts: - "[[SRP]]" - "[[冪等性]]" ---
frontmatterでの管理:
open_issues:
- id: TBD-001
question: "タイムアウト値は何秒にするか"
context: "外部API呼び出し時"
raised_at: 2025-01-10
status: open | discussing | resolved
resolved_by: "[[MTG-2025-01-17]]"
本文中のマーカー:
外部API呼び出し時のタイムアウトは %%TBD-001%% 秒とする。
---
type: meeting_note
meeting_id: MTG-2025-01-17
date: 2025-01-17
participants:
- "[[田中]]"
- "[[鈴木]]"
agenda_source:
- "[[決済システム詳細設計]]"
decisions:
- tbd_id: TBD-001
source_doc: "[[決済システム詳細設計]]"
question: "タイムアウト値は何秒にするか"
decision: "30秒とする"
rationale: "外部APIのSLAが20秒のため、余裕を持たせて30秒"
decided_by: "田中"
new_issues:
- question: "リトライ間隔の初期値"
target_doc: "[[決済システム詳細設計]]"
---
## 概要 設計書の未決定事項(TBD)を会議決定に基づき更新 ## 変更内容 | TBD-ID | 変更前 | 変更後 | 根拠 | |--------|--------|--------|------| | TBD-001 | 未定 | 30秒 | SLA+余裕 | ## 根拠となる議事録 - [[MTG-2025-01-17]]
| 方式 | 処理 | 消費トークン |
| 従来(全文読み込み) | 議事録+設計書3件を全部読む | 26,000 |
| 構造化(ピンポイント) | decisionsフィールド+該当行のみ | 500 |
| プログラミング | ドキュメント処理 |
| 値渡し(オブジェクト全体コピー) | 全文読み込み |
| 参照渡し(ポインタだけ) | TBD-IDで「どこを見ればいいか」だけ渡す |
構造化により、AIの継戦能力(長時間の自律処理)が向上する。
/**
* @dataview type: service
* @dataview domain: 決済
* @dataview tbd: TBD-001
*/
public class PaymentService {
// TODO(TBD-001): タイムアウト値は設計確定待ち
// source: docs/決済システム詳細設計.md
private static final int TIMEOUT = 0;
}
Obsidian (設計書)
TBD-001: resolved, decision: 30秒
│
│ 同期エージェント
▼
ソースコード
TODO(TBD-001) → 解決済みならコード更新+TODO削除
│
▼
GitHub Issue
#123 → 自動クローズ
Dataviewは .md ファイルのみが対象。.java, .py などは読み取れない。
Dataviewはオープンソース(MIT License)なので改造可能。
// 改造後のイメージ
getSupportedExtensions(): string[] {
return ['.md', '.java', '.py', '.ts', '.go'];
}
extractFromCode(file: TFile): Metadata {
// @dataview key: value 形式をパース
}
/**
* @dataview type: service
* @dataview domain: 決済
* @dataview status: implementing
* @dataview depends: [[認証モジュール]]
* @dataview tbd: TBD-001
*/
public class PaymentService {
```dataview TABLE file.name as "クラス", domain, status FROM "src" WHERE type = "service" ```
設計書とコードを横断検索できるようになる。
| 方法 | メリット | デメリット |
| Dataview本体をフォーク | 完全な自由度 | 本家追従のメンテコスト |
| Dataview拡張プラグイン | 本家と独立、軽量 | APIの制約を受ける |
| 本家にPR | メンテ不要、コミュニティ貢献 | マージされるか不明 |