# Jarvis Daemon — 運用ガイド

## 1. このディレクトリは何か

**Lv2 ライブ議論参加システム**のループ部分。

Jarvis が音声文字起こし（`transcript.md`）を5秒ごとにポーリングし、  
発言すべきタイミングと判断したら Anthropic API を直叩きして `jarvis_responses.md` に書き込む。

### なぜ外部 Python デーモンか

2026-05-04、Claude Code の `/loop` コマンドを使ったループ実装で**トークン爆発事故**が発生。  
1分間隔で 100k トークンを毎ループ同梱する設計になっており、  
Max 5x プランの消費枠を **15〜30 分で焼き切る**という事故だった。

外部 Python デーモン化により：
- Claude Code のセッショントークンを消費しない
- トークン上限・発話頻度制限を**コードで強制**できる
- 暴走しても `./stop_daemon.sh` 一発で物理停止できる

---

## 2. 必要なもの

| 項目 | 要件 |
|---|---|
| Python | 3.10 以上 |
| Anthropic API キー | [console.anthropic.com](https://console.anthropic.com/settings/keys) で発行 |
| 課金 | **Claude Code の Max プランとは別**。Anthropic API の従量課金 |
| OS | macOS（launchd 想定）または Linux |

---

## 3. セットアップ（初回のみ）

```bash
# 1. .env を作成して API キーを設定
cp .env.example .env
nano .env   # ANTHROPIC_API_KEY=sk-ant-... を書く

# 2. 起動
./start_daemon.sh
```

以上。2コマンドで完了。

---

## 4. 運用コマンド

| コマンド | 説明 |
|---|---|
| `./start_daemon.sh` | デーモン起動 |
| `./start_daemon.sh --dry-run` | dry-run モード（API コールするが書き込まない） |
| `./start_daemon.sh --no-install` | pip install をスキップして起動 |
| `./stop_daemon.sh` | デーモン停止 + 通算トークン消費表示 |
| `./status_daemon.sh` | 状態・トークン消費・コスト・アクティビティ確認 |
| `./tail_logs.sh` | daemon.log をリアルタイム監視（デフォルト） |
| `./tail_logs.sh tokens` | tokens.jsonl を監視（jq あれば整形） |
| `./tail_logs.sh events` | events.jsonl を監視（speak/silent/error） |
| `./tail_logs.sh dry_run` | dry_run.log を監視 |

---

## 5. 安全装置

### 5-1. トークン上限（config.py で設定）

| 設定 | デフォルト値 |
|---|---|
| `MAX_TOKENS_PER_HOUR` | 100,000 トークン/時 |
| `MAX_TOKENS_PER_DAY` | 1,000,000 トークン/日 |

上限に達したらその周期は発話をスキップし、ログに記録する。  
上限値は `.env` で上書きも可能（`MAX_TOKENS_PER_HOUR=50000` など）。

### 5-2. 発話頻度制限

`MIN_INTERVAL_BETWEEN_SPEAK_SEC`（デフォルト 300秒 = 5分）  
直近の発話から5分以内は発話しない。  
ただし「ジャービス」等の合言葉 C が含まれていれば即発話（例外）。

### 5-3. dry-run モード

```bash
./start_daemon.sh --dry-run
# または .env に JARVIS_DAEMON_DRY_RUN=1 を追加
```

API コールして応答を生成するが、`jarvis_responses.md` への書き込みは行わない。  
コスト確認・プロンプト調整・新機能テストに使う。

### 5-4. 物理停止

```bash
./stop_daemon.sh
```

SIGTERM → 5秒待機 → SIGKILL の順で確実に停止する。  
「暴走かも」と思ったらこれ一発でOK。

---

## 6. ファイル構成と関係

```
live_session/
├── transcript.md        ← 音声文字起こし（読み取り専用）
├── last_pos.txt         ← 最終読み取り位置（daemon が読み書き）
├── jarvis_responses.md  ← Jarvis の応答（daemon が追記）
└── daemon/              ← このディレクトリ
    ├── jarvis_daemon.py ← デーモン本体（別エージェントが実装）
    ├── config.py        ← 設定定数
    ├── requirements.txt ← pip パッケージ
    ├── prompts/         ← system_prompt.md, dna_core.md
    ├── logs/            ← daemon.log, tokens.jsonl, events.jsonl（.gitignore 対象）
    ├── .env             ← API キー（.gitignore 対象）
    ├── .daemon.pid      ← 実行中 PID（.gitignore 対象）
    ├── start_daemon.sh  ← 起動
    ├── stop_daemon.sh   ← 停止
    ├── status_daemon.sh ← 状態確認
    └── tail_logs.sh     ← ログ監視
```

---

## 7. トラブルシューティング

### API キーが無効

```
AuthenticationError: ...
```

→ [console.anthropic.com/settings/keys](https://console.anthropic.com/settings/keys) でキーを再発行し `.env` を更新。

### daemon が起動しない

```bash
./tail_logs.sh daemon
```

直近ログを確認。よくある原因：
- `jarvis_daemon.py` がない（別エージェントの実装を待つ）
- `requirements.txt` の依存が未インストール（`pip install -r requirements.txt`）
- `config.py` のパスが環境に合っていない

### 暴走・コスト超過の疑い

```bash
./stop_daemon.sh      # 即停止
./status_daemon.sh    # 消費確認
./tail_logs.sh events # 発話ログ確認
```

### PIDファイルが残っている

プロセスが異常終了すると `.daemon.pid` が残ることがある。

```bash
rm .daemon.pid
./start_daemon.sh
```

### ログが大きくなりすぎた

```bash
# daemon.log をローテーション（手動）
mv logs/daemon.log logs/daemon.log.$(date +%Y%m%d)
```

または logrotate を設定する。

---

## 8. コスト目安

| モデル | 入力 ($/M tok) | 出力 ($/M tok) | 想定時間コスト |
|---|---|---|---|
| claude-sonnet-4-6 | $3.00 | $15.00 | $0.03〜$0.10/時間 |

> 発話頻度（`MIN_INTERVAL_BETWEEN_SPEAK_SEC`）と  
> 入力コンテキストサイズ（`TRANSCRIPT_CONTEXT_LINES`）に大きく左右される。  
> プロンプトキャッシュ有効時は入力コストが最大 90% 削減。

---

## 9. この仕組みが解決した事故（再発防止記録）

**2026-05-04 — Claude Code /loop 暴走事故**

- Claude Code の `/loop` コマンドで1分間隔ループを実装
- 毎ループに transcript.md（∼100kトークン）を丸ごと同梱
- Max 5x プランの消費枠を **15〜30分で消費**してしまった
- その後のセッションすべてでトークン不足が発生

**対策：** 外部 Python デーモン化 + トークン上限の強制 + 発話頻度制限

---

## 10. 将来案（Lv3 への発展）

- **音声リアルタイム参加**（Lv3）: transcript.md ポーリングではなく  
  音声ストリームを直接受け取り、WebSocket 経由でリアルタイム応答
- **TTS 統合**: 応答テキストを音声に変換してスピーカーから発話
- **感情・トーン分析**: 発話タイミングの判断精度向上
- **マルチ Jarvis**: 複数の Jarvis インスタンスが協調して議論に参加
