claude-spotter 1.2.5 → 1.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +122 -0
- package/README.ja.md +101 -27
- package/README.md +103 -31
- package/bin/spotter.mjs +37 -6
- package/package.json +2 -2
- package/scripts/postinstall.mjs +4 -1
- package/src/cli/auditor-cmd.mjs +359 -0
- package/src/cli/codex-cmd.mjs +254 -0
- package/src/cli/codex-hook-cmd.mjs +752 -0
- package/src/cli/db-cmd.mjs +46 -12
- package/src/cli/diagnostics-cmd.mjs +120 -0
- package/src/cli/doctor.mjs +94 -19
- package/src/cli/install.mjs +23 -9
- package/src/core/auditor-backend.mjs +230 -0
- package/src/core/auditor-error.mjs +16 -0
- package/src/core/auditor-response.mjs +96 -0
- package/src/core/codex-cli-backend.mjs +342 -0
- package/src/core/codex-risk-dispatch.mjs +93 -0
- package/src/core/codex-sidecar-auditor-backend.mjs +310 -0
- package/src/core/codex-sidecar-policy.mjs +194 -0
- package/src/core/codex-sidecar-runner.mjs +740 -0
- package/src/core/codex-transcript.mjs +65 -0
- package/src/core/daemon-log-diagnostics.mjs +407 -0
- package/src/core/host-agent.mjs +18 -0
- package/src/core/judgment.mjs +86 -0
- package/src/core/sidecar-context.mjs +117 -0
- package/src/daemon/daemon.mjs +90 -97
- package/src/daemon/haiku-caller.mjs +107 -95
- package/src/daemon/transport.mjs +10 -2
- package/src/hooks/lib.mjs +8 -2
- package/src/hooks/session-start.mjs +9 -4
- package/src/hooks/spawn-daemon.mjs +2 -2
- package/src/hooks/user-prompt.mjs +16 -10
- package/src/index.mjs +70 -1
- package/src/tool-db/frontmatter.mjs +66 -3
- package/src/tool-db/investigate-codex.mjs +241 -0
- package/src/tool-db/investigate-mcp-http.mjs +3 -1
- package/src/tool-db/investigate-mcp.mjs +73 -10
- package/src/tool-db/loader.mjs +16 -3
- package/src/tool-db/refresh.mjs +16 -6
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,127 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 1.4.0
|
|
4
|
+
|
|
5
|
+
**Codex native hooks を npm 配布可能な完成状態へ昇格する minor bump**。`npm install -g claude-spotter@1.4.0` で `spotter` CLI を global install し、各プロジェクトでは `spotter install`、Codex を使う場合は追加で `spotter codex-hook install` を実行するだけで動く状態にした。手書き tool list や install 時の Codex seed は不要で、Codex 側 catalog は SessionStart hook が自動更新する。
|
|
6
|
+
|
|
7
|
+
### 主要変更
|
|
8
|
+
|
|
9
|
+
- **Codex native hooks**: `spotter codex-hook install|uninstall|diagnostics|session-start|user-prompt-submit|stop` を npm 配布対象として整備。Codex `SessionStart` は `spotter db refresh --host-agent codex` を detached 起動し、Codex tool catalog を `.spotter/tool-db.codex.json` に更新する。Claude `.spotter/tool-db.json` には触れない
|
|
10
|
+
- **Codex primary auditor backend**: Codex host の既定 backend を Codex CLI (`codex exec`) にした。`UserPromptSubmit` / `Stop` は Codex local DB だけを読み、Codex CLI unavailable / schema invalid / non-zero exit / timeout は structured error として surface する。Haiku への hidden fallback はしない
|
|
11
|
+
- **Codex CLI safety**: 子 Codex は read-only sandbox、stdin `ignore`、`model_reasoning_effort="low"`、hook auditor timeout 20s、bounded stderr diagnostics、`--output-schema` / `--output-last-message` を使う。timeout 時も last-message file に schema-valid final JSON があれば `completionReason=last_message_before_process_close` として success 扱いし、process close 遅延による誤 timeout を避ける
|
|
12
|
+
- **再帰 / セッション増殖ガード**: Codex CLI / `codex-sidecar` 子プロセスに `SPOTTER_PARENT_PID`、`SPOTTER_BACKEND`、`SPOTTER_CHILD_BACKEND` を入れ、hook 共通入口 `isChildCall()` がこれらを stdin 読み取り前に検知して return する。Claude 時代に経験した sub-agent / child session 増殖事故の再発を避ける
|
|
13
|
+
- **host-local tool-db 分離**: Claude は `.spotter/tool-db.json`、Codex は `.spotter/tool-db.codex.json` を使う。`spotter db refresh --host-agent codex` は Codex MCP / skills discovery だけを反映し、Claude refresh と相互に prune / overwrite しない
|
|
14
|
+
- **`codex-sidecar` の位置づけ整理**: primary auditor としては明示 override (`SPOTTER_AUDITOR_BACKEND=codex-sidecar`) で使えるが、Codex host default は Codex CLI。`codex-sidecar` は durable result / diagnostics / worktree / MCP boundary を持つ second-pass (`risk-check`, `review`, `explore`, `opinion`) と approved `work` workflow の基盤として残す
|
|
15
|
+
- **diagnostics / docs**: `spotter doctor` に Codex CLI / Codex hooks / `codex-sidecar` readiness を追加。README / README.ja / CLAUDE.md / contract docs / open issues / migration TODO を v1.4.0 の完成条件へ更新
|
|
16
|
+
- **packaging hardening**: npm publish 時に bin が消える罠を避けるため `package.json` の `bin.spotter` を `bin/spotter.mjs` に正規化。package-lock も `1.4.0` に更新。MCP initialize の `clientInfo.version` は `src/version.mjs` 由来にして package version drift を解消
|
|
17
|
+
|
|
18
|
+
### 実測 / 検証
|
|
19
|
+
|
|
20
|
+
- `npm test`: 272 tests, 271 pass, 1 skip
|
|
21
|
+
- Codex native hook smoke: `UserPromptSubmit Completed` / `Stop Completed`
|
|
22
|
+
- Codex hook latency smoke: normal `UserPromptSubmit` 約 7.4s、short `Stop` skip 約 0.08s
|
|
23
|
+
- 4 象限 primary auditor matrix: `claude.codex-cli=10041ms`, `claude.codex-sidecar=12863ms`, `codex.codex-cli=10383ms`, `codex.codex-sidecar=13983ms`
|
|
24
|
+
- `spotter codex risk-check --host-agent codex`: durable `.spotter/sidecar-results/*-codex-risk-check.json` を保存
|
|
25
|
+
- `spotter codex work --dry-run --approve-work --allowed-path ... --remove-worktree --host-agent codex`: scoped work workflow success
|
|
26
|
+
|
|
27
|
+
### ユーザー側で必要な手順
|
|
28
|
+
|
|
29
|
+
1. `npm install -g claude-spotter@1.4.0` で global update
|
|
30
|
+
2. Claude Code で使う各プロジェクトで `spotter install` を実行する。これは `.claude/settings.json` と `.spotter/marker.json` を作り、Claude catalog の初回 seed も実行する
|
|
31
|
+
3. Codex native hooks を使う場合は一度だけ `spotter codex-hook install` を実行する。以後、Codex `SessionStart` が `.spotter/tool-db.codex.json` を自動 refresh する
|
|
32
|
+
4. `spotter doctor` と `spotter codex-hook diagnostics` で global CLI / Codex hooks / tool-db 状態を確認できる
|
|
33
|
+
|
|
34
|
+
## 1.3.0
|
|
35
|
+
|
|
36
|
+
**Haiku spawn 時に user/project の MCP server を一切 load しないよう強制 — WSL2 で観測された CPU 100% 飽和 + 孤児 `npm exec` プロセス累積 + チャット入力無反応 の根本原因を断った minor bump**。修正は `claude -p` 起動引数に `--strict-mcp-config --mcp-config <empty>` を必ず付けるだけの最小実装、副作用なし。
|
|
37
|
+
|
|
38
|
+
### 観測した症状 (2026-05-04 WSL2 実環境)
|
|
39
|
+
|
|
40
|
+
WSL2 の CPU 使用率が 100% に張り付き、何かがプロセスを「無限増殖」させている — というユーザー報告から調査開始。`ps -eo pid,ppid,pcpu,etime,cmd --sort=-pcpu` の上位に **etime 3〜10 秒の `npm exec @modelcontextprotocol/server-*` / `@playwright/mcp` / `@upstash/context7-mcp` / `homework-mcp` / `caveat mcp` / `mcp-server-github` / `mcp-server-memory` 等が大量並走** し、親 PID は `claude -p --resume <uuid> --model claude-haiku-4-5-20251001` (= Spotter daemon の Haiku caller)。Spotter daemon が 3 並走、各々の Haiku 起動ごとに 60+ 個の MCP server を spawn → 終了 → 再 spawn のサイクルで CPU を食いつぶしていた。隣接プロジェクト ([Chime](file:///home/kite/projects/Chime)) で「VSCode 拡張のチャット入力が無反応」体感症状の真因も同根 (WSL2 全体の CPU 飽和で拡張側の入力処理がドロップ)。
|
|
41
|
+
|
|
42
|
+
### 真因
|
|
43
|
+
|
|
44
|
+
`sanitizeHaikuEnv` (v1.1.6) は `CLAUDE_CONFIG_DIR` を strip して Haiku をデフォルト `~/.claude/` で起動するが、**デフォルト config dir には User scope MCP (`~/.claude.json` 直下 `mcpServers`) と plugin MCP がフルで登録されている**。claude CLI 2.1.x は `--print` モード起動時に config dir 内の全 MCP server を eager に spawn するため、Haiku 1 回呼出ごとに数十個の `npm exec` 子プロセスが立つ。Haiku は `{name, description}` カタログ監査しかしない (= MCP server は不要) のに、起動コストとして user/project の MCP がフル load されていた構造的欠陥。
|
|
45
|
+
|
|
46
|
+
加えて `daemon-702a677d-...log` で同 sessionId の `tool-db loaded` が 15 分間に 8 回記録 = sudden death + auto-resurrect が高頻度発生していた。WSL2 cgroup OOM kill が daemon プロセスごと巻き込んでいた可能性が高く、[docs/open-issues.md](docs/open-issues.md) P0 「daemon プロセスが shutdown ログなしに死ぬ」 (v0.13.2 から残置) の主因もこれと推定。
|
|
47
|
+
|
|
48
|
+
### 変更点
|
|
49
|
+
|
|
50
|
+
- **編集 [src/daemon/haiku-caller.mjs](src/daemon/haiku-caller.mjs)**:
|
|
51
|
+
- 定数 `EMPTY_MCP_CONFIG_PATH = ~/.spotter/workdir/empty-mcp.json` と `EMPTY_MCP_CONFIG_BODY = '{"mcpServers":{}}'` を追加
|
|
52
|
+
- `ensureWorkdir` を拡張し、空 MCP config ファイルを idempotent に書き出す
|
|
53
|
+
- 新 named export `emptyMcpConfigPath()` (テストから参照)
|
|
54
|
+
- `buildSpawnArgs({ ...args, mcpConfigPath })` のシグネチャを拡張、`mcpConfigPath` を必須化 (TypeError on missing/empty)、出力に `--strict-mcp-config --mcp-config <path>` を必ず含める。Windows `cmd.exe /c` 経路でも同様に
|
|
55
|
+
- `createHaikuCaller` 内 `spawn` 直前で `mcpConfigPath: EMPTY_MCP_CONFIG_PATH` を渡す
|
|
56
|
+
- **編集 [test/haiku-caller.test.mjs](test/haiku-caller.test.mjs)**: 回帰ガード 5 件追加 + 既存 `buildSpawnArgs` 2 件を新シグネチャに追従
|
|
57
|
+
- 新規: first call と resumed call の両方で `--strict-mcp-config` と `--mcp-config <path>` を含む
|
|
58
|
+
- 新規: `mcpConfigPath` 欠落 / 空文字 / null で TypeError
|
|
59
|
+
- 新規: `ensureWorkdir` で `empty-mcp.json` が `{"mcpServers":{}}` で書かれる
|
|
60
|
+
- 新規: `ensureWorkdir` の idempotent 性 (3 連呼出で破綻しない)
|
|
61
|
+
- **編集 [src/cli/install.mjs](src/cli/install.mjs)**: `HOOK_EVENTS` の Stop/UserPromptSubmit timeout を 15s/30s から **60s に統一**。v0.13.1 で daemon 側 Haiku timeout を 30s→45s に緩和したのに settings.json に書く Claude Code 本体側の hook timeout が旧値のままで、Chime 等の preamble が大きい (93 KB / 357 件) 環境で daemon が 24-32s かけて正常応答を返している最中に Claude Code 側 hook が timeout kill されて「チャット入力無反応」を誘発していた既存バグの hot-fix。`docs/open-issues.md` の P0「install.mjs の hook timeout が v0.13.1 緩和を反映していない」項目を closing
|
|
62
|
+
- **package.json**: `1.2.6` → `1.3.0` (公開 API シグネチャ変更 = `buildSpawnArgs` の新引数を伴うため minor bump)
|
|
63
|
+
- **編集 [docs/open-issues.md](docs/open-issues.md)**: 解決済みリストに 2 件追加、P0「daemon が shutdown ログなしに死ぬ」節に v1.3.0 で根因が大半解消した可能性を追記
|
|
64
|
+
|
|
65
|
+
### なぜ `--strict-mcp-config --mcp-config <empty>` が正解か
|
|
66
|
+
|
|
67
|
+
- **Anthropic auth は影響なし** — credentials は `~/.claude/.credentials.json` 等から従来どおり読まれる (`--bare` を使うと keychain skip で OAuth が壊れるが、`--strict-mcp-config` は MCP config を制限するだけで auth とは独立)
|
|
68
|
+
- **副作用ゼロ** — Haiku は `{name, description}` カタログ監査しか必要としない、MCP server を呼ばない。Spotter のカタログ収集 (`investigate-mcp.mjs`) は別経路 (`claude mcp list` + `.mcp.json` 直読み) で行うので Haiku 側に MCP は要らない
|
|
69
|
+
- **クロスプラットフォーム** — `--strict-mcp-config --mcp-config <path>` は Linux/macOS/Windows 全てで動作、`--mcp-config` は v0.x 時代から claude CLI に存在
|
|
70
|
+
- **既存の v1.1.6 `sanitizeHaikuEnv` と直交** — Bell の isolated `CLAUDE_CONFIG_DIR` 継承防止 (auth 失敗回避) は引き続き必要、本修正は MCP load 防止という別軸で重ねがけ
|
|
71
|
+
|
|
72
|
+
### Chime / Spotter ユーザー側で必要な手順
|
|
73
|
+
|
|
74
|
+
1. `npm install -g claude-spotter@1.3.0` で global update
|
|
75
|
+
2. Haiku spawn の MCP-disable は次の SessionStart から自動的に新コードが効く
|
|
76
|
+
3. 既 install プロジェクトでも `spotter install` を再実行して、`.claude/settings.json` の UserPromptSubmit / Stop hook timeout を 60s に更新する (旧 settings の 15s/30s は global update だけでは書き換わらない)
|
|
77
|
+
4. 既存の孤児 daemon があれば `kill <pid>` + `rm ~/.spotter/runtime/session-*.pid` で掃除 (今後は v1.3.0 の MCP-disable で sudden death 自体が大幅減少見込み)
|
|
78
|
+
|
|
79
|
+
## 1.2.6
|
|
80
|
+
|
|
81
|
+
**チャット入力が無視される実害バグの根治**。実プロジェクト ([Chime](file:///home/kite/projects/Chime)) のセッションで Spotter daemon が UserPromptSubmit / Stop hook を Haiku 呼び出しで何度も `E_INTERNAL: haiku exited with code 1` させ、Claude Code 側 hook timeout (30s) に貼り付いて入力が応答しない状態が頻発していた。原因は Haiku を起動する `claude -p` への stdin 引き渡し方式と、claude CLI 2.1.x の stdin 取扱いの仕様の組合せで、推測ではなく実プロジェクト同条件 (`tools=357 件 / preamble=93 KB`) の最小再現で確定した。
|
|
82
|
+
|
|
83
|
+
### 観測された stderr
|
|
84
|
+
|
|
85
|
+
```
|
|
86
|
+
Warning: no stdin data received in 3s, proceeding without it.
|
|
87
|
+
If piping from a slow command, redirect stdin explicitly: < /dev/null to skip, or wait longer.
|
|
88
|
+
Error: Input must be provided either through stdin or as a prompt argument when using --print
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
### 真因 (推測ではなく実測で確定)
|
|
92
|
+
|
|
93
|
+
claude CLI 2.1.126 は `--print` モードで stdin の最初の read attempt が **約 3 秒** 以内に readable にならないと「stdin 無し」と判定して引数モードに切替えようとし、prompt が無いので exit 1 する。一方 Spotter は v0.7.0 の tool-db 化で preamble (role + schema + few-shot + 全カタログの JSON) を初回 1 回送信しているが、Chime のように `MCP × スキル × サブエージェント = 357 件` ある環境では preamble が **93 KB** 程度に達する。Linux の kernel pipe buffer (デフォルト 64 KB) を超えるため、Node 側 `child.stdin.end(buf)` の write が drain 待ちになり、claude CLI が起動 (auth + config + plugin 探索) を 3 秒以内に終えて最初の read syscall を発行しないと「3 秒間 no stdin data」と CLI 側で判定 → stdin 放棄 → exit 1。CLI は "Warning" を出して続行するふりをするが、実際は `--print` 引数も無いので "Input must be provided" で死ぬ。
|
|
94
|
+
|
|
95
|
+
実測 (2026-05-04, /home/kite/projects/Chime での Spotter セッション + WORKDIR 隔離環境):
|
|
96
|
+
|
|
97
|
+
| stdin 経路 | duration | exit code | stderr |
|
|
98
|
+
|---|---|---|---|
|
|
99
|
+
| `child.stdin.end(prompt)` (pipe) | 17 秒 | 1 | "no stdin data received in 3s" + "Input must be provided" |
|
|
100
|
+
| **tempfile fd を `stdio[0]` に渡す (本修正)** | **24-32 秒** | **0** | (空) — 正常 JSON 応答 |
|
|
101
|
+
|
|
102
|
+
このバグの可視結果は、daemon log の以下メッセージが繰り返し出る現象として観測されていた:
|
|
103
|
+
- `user_input: haiku invocation failed (E_INTERNAL), rotating session before rethrow: haiku exited with code 1: Warning: no stdin data received in 3s ...`
|
|
104
|
+
- 当該 turn は session を rotate して `mode=first` の cold-start に逆戻り (preamble 再送 → ますます重い) → 30s hook timeout に貼り付き → ユーザー視点で「チャット入力が無視される」
|
|
105
|
+
|
|
106
|
+
### 変更点
|
|
107
|
+
|
|
108
|
+
- **編集 [src/daemon/haiku-caller.mjs](src/daemon/haiku-caller.mjs)**: 新規 `preparePromptFile(wirePrompt)` を named export として追加。`os.tmpdir()` 配下にユニーク tempfile (`spotter-prompt-<pid>-<uuid>.txt`) を作って prompt を書き込み、read-only fd と `close()` ハンドラ (fd close + unlink、両方 best-effort) を返す。`createHaikuCaller` 内 `callHaiku` の `spawn` を `stdio: ['pipe', 'pipe', 'pipe']` + `child.stdin.end(prompt)` から `stdio: [promptFile.fd, 'pipe', 'pipe']` に切替え (child.stdin が null になるので関連 noop listener も削除)。close / error / timeout の各 settle 経路で `promptFile.close()` を呼んでから resolve/reject する `settleAfterCleanup` ヘルパで cleanup を一元化、tempfile leak を防止
|
|
109
|
+
- **編集 [test/haiku-caller.test.mjs](test/haiku-caller.test.mjs)**: 回帰ガード 6 件追加 — (1) tempfile が書かれて読める (2) 100 KB (= pipe buffer 超え) でも全 byte 届く (3) `close()` で unlink される (4) `close()` 二重呼び出し可 (timeout-vs-close race の安全性) (5) 非 string 入力で `TypeError` (6) 並列呼び出しで tmpPath が衝突しない (UUID 保証)
|
|
110
|
+
- **package.json**: `1.2.5` → `1.2.6`
|
|
111
|
+
|
|
112
|
+
### なぜ tempfile fd 方式が正解か
|
|
113
|
+
|
|
114
|
+
- **file は kernel が即時 readable と判定** — pipe と違い「writer 側の進捗」を待たないので、CLI 起動が遅くても 3 秒タイマーに引っかからない
|
|
115
|
+
- **pipe buffer の制約から完全に独立** — 64 KB / 1 MB / 10 MB どんな payload でも file 経由なら一発で届く
|
|
116
|
+
- **クロスプラットフォーム** — Windows でも `os.tmpdir()` は機能、`stdio[0]` への numeric fd 受け渡しも Node が抽象化済み
|
|
117
|
+
- **CLI 引数モード (`-p "<prompt>"`) と違い ARG_MAX に縛られない** — Windows の CommandLineW 32K 制限を回避
|
|
118
|
+
|
|
119
|
+
### Chime で「無反応」が消えるまでに必要な手順 (ユーザー側)
|
|
120
|
+
|
|
121
|
+
1. `npm install -g claude-spotter@1.2.6` で global update
|
|
122
|
+
2. Chime 側の既 install プロジェクトでは hook 設定 (`~/.claude.json` の per-project hooks) は変わらない (`spotter.mjs` のパスは固定) ので **再 install 不要**、次の SessionStart から自動的に新コードが効く
|
|
123
|
+
3. 既存の孤児 daemon があれば `rm ~/.spotter/runtime/session-*.pid` で掃除 (生存 daemon 0 件確認後のみ)
|
|
124
|
+
|
|
3
125
|
## 1.2.5
|
|
4
126
|
|
|
5
127
|
**ECC プラグイン経由の MCP サーバー 6 件 (context7 / exa / github / memory / playwright / sequential-thinking) のツール群 (61 件) が Spotter のカタログから silent に欠落していた **二重構造バグ**を修正**。実プロジェクト (Web) で `spotter install` 実行時のログに ``mcp investigate failed for "plugin": Command failed: cmd.exe /c claude mcp get plugin`` が **6 連発** で出ていたのを契機に発見。これらのプラグイン MCP の呼び忘れを Spotter が検出できない状態だった (Web プロジェクトで rebuild すると 309 → 370 件、プラグイン由来 61 件が追加されることを確認)。
|
package/README.ja.md
CHANGED
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
|
|
14
14
|
> **気づく役と実行する役を分離する。** Claude Code の横で並走し、Bell (主役の Claude) が**ツールを呼び忘れたとき**だけ静かに指摘する監査役。
|
|
15
15
|
|
|
16
|
-
Claude
|
|
16
|
+
Claude には「使えるツールがあるのに、使うべきタイミングで使わない」という構造的な弱点があります。記録すべき決定を memory / caveat MCP に残さない、docs lookup MCP を呼ばずに古い知識で応答する、ブラウザ自動化 MCP で確認せず UI 状態を推測する — **「分からないと自覚できない」から、ツールを取りに行けない**。
|
|
17
17
|
|
|
18
18
|
Spotter はツールカタログを完全に把握した別エージェント (Claude Haiku 4.5) をセッション毎に常駐させ、Bell の発話予定と応答を並走監査します。見落としを検出すると透明化された指摘として Bell に届け、補正応答を促します。**Bell が自覚して呼ぶ**設計は本プロダクトの存在意義を破壊するため、Bell から呼ぶのではなく hook 経由で Bell の意思と独立に検出する構造を取っています。
|
|
19
19
|
|
|
@@ -23,14 +23,16 @@ Spotter が拾うのは、たとえばこういう瞬間です。
|
|
|
23
23
|
|
|
24
24
|
| 状況 | Bell の応答 | Spotter の指摘 |
|
|
25
25
|
|---|---|---|
|
|
26
|
-
|
|
|
27
|
-
|
|
|
28
|
-
|
|
|
26
|
+
| 「この OAuth の落とし穴を覚えて」 | 了解だけして進める | memory / caveat MCP の使用機会 |
|
|
27
|
+
| 「このパッケージの最新版 API は?」 | 学習時点の知識で答える | docs lookup MCP の照会機会 |
|
|
28
|
+
| 「この危ない patch をレビューして」 | 自分だけで見直す | reviewer sub-agent の使用機会 |
|
|
29
29
|
| 事実の断定 | 裏付けなしで「〜です」 | 検証用ツールの差し込み余地 |
|
|
30
|
+
| 「この UI 今もちゃんと動く?」 | コード読みだけで結論 | ブラウザ自動化 MCP の使用機会 |
|
|
31
|
+
| 「以前何を決めたっけ?」 | 推測 / 失念のまま回答 | メモリ / ノート系 MCP の照会機会 |
|
|
30
32
|
|
|
31
33
|
判定軸は 2 段階:
|
|
32
34
|
|
|
33
|
-
- **入力時 (`stage=user_input`)**:
|
|
35
|
+
- **入力時 (`stage=user_input`)**: ユーザー要請に対し、ローカルカタログの description から用途が明確に該当するツールを列挙する **要請充足チェック**
|
|
34
36
|
- **応答後 (`stage=turn_end`)**: Bell の最終応答に対し、事実の断定 / 記録すべき新情報 / 既知情報の参照それぞれに、カタログ上のツール (検証 / 登録 / 照会) を差し込める余地がないかを問う **ツール適用機会の監査**
|
|
35
37
|
|
|
36
38
|
## インストール
|
|
@@ -39,9 +41,14 @@ Spotter が拾うのは、たとえばこういう瞬間です。
|
|
|
39
41
|
npm install -g claude-spotter
|
|
40
42
|
cd your-project
|
|
41
43
|
spotter install
|
|
44
|
+
# 任意: Codex native hooks を使う場合
|
|
45
|
+
spotter codex-hook install
|
|
42
46
|
```
|
|
43
47
|
|
|
44
48
|
`v0.3.0` 以降は**プロジェクト単位の明示的 install** を採用しています (v0.2 までの `postinstall` 自動登録はデーモン増殖の主因だったため撤回)。各プロジェクトの `.claude/settings.json` に hook を登録し、そのプロジェクトでの Claude Code セッションのみで有効になります。
|
|
49
|
+
Codex 対応は `spotter codex-hook install` で別途有効化します。Codex hook は user-level に登録されますが、実際に動くプロジェクトは `spotter install` が作る `.spotter/marker.json` で制限されます。
|
|
50
|
+
|
|
51
|
+
Spotter を upgrade した後、release note で hook 設定変更が案内されている場合は、各 install 済みプロジェクトで `spotter install` を再実行してください。global package update でコード経路は変わりますが、既存 `.claude/settings.json` の timeout 値は自動では書き換わりません。
|
|
45
52
|
|
|
46
53
|
```bash
|
|
47
54
|
spotter uninstall # このプロジェクトの hook 登録を解除
|
|
@@ -51,27 +58,54 @@ spotter uninstall # このプロジェクトの hook 登録を解除
|
|
|
51
58
|
|
|
52
59
|
- **Node.js 22.5 以上**
|
|
53
60
|
- **Claude Code 2.0 以上**
|
|
54
|
-
-
|
|
61
|
+
- **現行 Claude-backed auditor path では Claude Max プラン** (`claude -p` で Haiku を起動するため)
|
|
62
|
+
- **Codex native hooks では Codex CLI**。Codex host の監査は既定で `codex exec` を使い、Haiku へ fallback しません
|
|
55
63
|
|
|
56
64
|
## アーキテクチャ
|
|
57
65
|
|
|
66
|
+
### 1 ターンの監査フロー
|
|
67
|
+
|
|
68
|
+
```mermaid
|
|
69
|
+
flowchart TD
|
|
70
|
+
U([User 発話]) --> UPH[UserPromptSubmit hook<br/>Spotter が発話とカタログから一次判定]
|
|
71
|
+
UPH --> BT[Bell Thinking<br/>Spotter の推奨を<br/>additionalContext で受信]
|
|
72
|
+
BT --> BA([Bell の最初の応答])
|
|
73
|
+
BA --> SH[Stop hook<br/>応答と使用済みツールから最終チェック]
|
|
74
|
+
SH --> DEC{見落とし<br/>あり?}
|
|
75
|
+
DEC -->|なし| DONE([完了])
|
|
76
|
+
DEC -->|あり| SB[差し戻し<br/>max 1 回<br/>stop_hook_active で自動担保]
|
|
77
|
+
SB --> BA2([Bell の補正応答]) --> DONE
|
|
58
78
|
```
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
79
|
+
|
|
80
|
+
### カタログの収集経路
|
|
81
|
+
|
|
82
|
+
```mermaid
|
|
83
|
+
flowchart LR
|
|
84
|
+
subgraph SRC[収集ソース]
|
|
85
|
+
direction TB
|
|
86
|
+
MCP[MCP サーバー<br/>claude mcp list で列挙]
|
|
87
|
+
SK[スキル<br/>SKILL.md frontmatter]
|
|
88
|
+
AG[サブエージェント<br/>agent .md frontmatter]
|
|
89
|
+
BL[claude.ai baseline<br/>Gmail / Calendar / Drive<br/>存在時のみ注入]
|
|
90
|
+
end
|
|
91
|
+
subgraph SCOPES["MCP の env / headers — 4 スコープ、上位が衝突に勝つ"]
|
|
92
|
+
direction TB
|
|
93
|
+
L["Local — projects.<root>.mcpServers in ~/.claude.json"]
|
|
94
|
+
P["Project — <root>/.mcp.json"]
|
|
95
|
+
US["User — mcpServers in ~/.claude.json"]
|
|
96
|
+
LG["Legacy — ~/.claude/.mcp.json"]
|
|
97
|
+
end
|
|
98
|
+
SCOPES -. merge .-> MCP
|
|
99
|
+
MCP --> DB[(ホスト別ローカル tool-db<br/>name + description<br/>プロジェクト単位)]
|
|
100
|
+
SK --> DB
|
|
101
|
+
AG --> DB
|
|
102
|
+
BL --> DB
|
|
103
|
+
DB --> H[Haiku 監査<br/>session-scoped, preamble-once]
|
|
70
104
|
```
|
|
71
105
|
|
|
72
|
-
監査対象のツール (name + description) は `<project>/.spotter/tool-db.json`
|
|
106
|
+
監査対象のツール (name + description) は host-local に分離されます。Claude は `<project>/.spotter/tool-db.json`、Codex は `<project>/.spotter/tool-db.codex.json` を使います。**daemon が監査に使うのは Claude local DB のみ**で、Codex native hooks は Codex local DB を読みます。グローバル DB `~/.spotter/tool-db.json` は他プロジェクトでの description 再利用キャッシュとしてのみ機能し、監査入力には混ぜません。各 host-local DB は **その host の現時点の discovery 結果と一致** (refresh 時に prune される) するため、別プロジェクトや別 host のツールリストで上書きされることはありません。
|
|
73
107
|
|
|
74
|
-
|
|
108
|
+
**`spotter install` が Claude catalog の初回 seed を自動実行し、Claude Code セッション起動ごとに SessionStart hook が bg で `spotter db refresh` を走らせる**ため、Claude 通常運用で手動コマンドを叩く必要はありません。Codex native hooks も同じ考え方で、`spotter codex-hook install` が Codex `SessionStart` hook を登録し、Codex セッション開始時に `spotter db refresh --host-agent codex` を bg 起動して `.spotter/tool-db.codex.json` を更新します。Claude catalog には書き込みません。Claude discovery は `claude mcp list` と Claude skills / sub-agents、Codex discovery は `codex mcp list/get` と Codex skills を読むため、両 host の利用可能ツール差分を別 DB として保持できます。各 MCP サーバーの `tools/list` は JSON-RPC で取得 (HTTP / SSE / stdio transport 対応)、スキルとサブエージェントは frontmatter から直接抽出、claude.ai baseline (OAuth proxy 経由の Gmail / Calendar / Drive 25 件) は Claude 側でのみ `claude mcp list` に該当サーバーが存在する環境で注入されます。**手書きでツールリストを管理する必要はありません**。
|
|
75
109
|
|
|
76
110
|
## Throughline との関係
|
|
77
111
|
|
|
@@ -88,19 +122,54 @@ Stop hook → Spotter が応答と使用済みツールを見て最終チェッ
|
|
|
88
122
|
## よく使うコマンド
|
|
89
123
|
|
|
90
124
|
```bash
|
|
91
|
-
spotter db list #
|
|
92
|
-
spotter db
|
|
93
|
-
#
|
|
94
|
-
spotter db
|
|
125
|
+
spotter db list # 現在の Claude local tool-db を表示
|
|
126
|
+
spotter db list --host-agent codex
|
|
127
|
+
# 現在の Codex local tool-db を表示
|
|
128
|
+
spotter db refresh # Claude MCP / スキル / サブエージェントから description を収集して Claude DB 更新
|
|
129
|
+
spotter db refresh --host-agent codex
|
|
130
|
+
# Codex MCP / スキルから description を収集して .spotter/tool-db.codex.json を更新
|
|
131
|
+
# (Claude は install + Claude SessionStart、Codex は codex-hook install 後の
|
|
132
|
+
# Codex SessionStart で自動実行されるので通常は不要)
|
|
133
|
+
spotter db rebuild # Claude local + global DB を両方消してから refresh (カタログ設計変更時のクリーン用)
|
|
95
134
|
spotter status # 稼働中の daemon 一覧
|
|
96
|
-
spotter doctor # 環境診断 (Node / claude CLI / tool-db 整合性)
|
|
135
|
+
spotter doctor # 環境診断 (Node / claude CLI / Codex readiness / tool-db 整合性)
|
|
136
|
+
spotter diagnostics logs # daemon log から pass=false / backend latency / anomaly signal を集計
|
|
137
|
+
spotter codex risk-check --findings findings.json --host-agent claude
|
|
138
|
+
# Spotter finding を codex-sidecar に渡して read-only risk analysis
|
|
139
|
+
spotter codex review|explore|opinion --findings findings.json --host-agent claude
|
|
140
|
+
# その他の read-only codex-sidecar second-pass workflow
|
|
141
|
+
spotter codex work --findings findings.json --instruction "docs 更新" --approve-work \
|
|
142
|
+
--allowed-path docs/ --preserve-worktree
|
|
143
|
+
# 承認済み codex-sidecar work を isolated worktree で実行
|
|
144
|
+
spotter codex-hook install
|
|
145
|
+
# Codex native SessionStart / UserPromptSubmit / Stop hook を登録
|
|
146
|
+
spotter codex-hook diagnostics
|
|
147
|
+
# Codex hooks feature と Spotter hook 登録を診断
|
|
97
148
|
spotter uninstall # hook 登録を解除 (~/.spotter は残す)
|
|
98
149
|
```
|
|
99
150
|
|
|
151
|
+
Codex risk dispatch を daemon から非同期に流す場合:
|
|
152
|
+
|
|
153
|
+
```bash
|
|
154
|
+
SPOTTER_CODEX_RISK_CHECK=1 spotter daemon start --session-id ... --project-root ...
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
有効時は daemon が `pass:false` finding を detached process の
|
|
158
|
+
`spotter codex risk-check` に渡します。hook 応答は Codex を待ちません。
|
|
159
|
+
配線だけ確認する場合は `SPOTTER_CODEX_RISK_CHECK_DRY_RUN=1` を併用します。
|
|
160
|
+
|
|
161
|
+
Primary auditor backend policy: Claude hooks は現行の Haiku compatibility path を既定のまま維持します。
|
|
162
|
+
Codex native hooks は Codex CLI を既定 backend とし、Haiku へ fallback しません。
|
|
163
|
+
Codex 側の SessionStart hook は `.spotter/tool-db.codex.json` を bg refresh し、Claude DB には触れません。
|
|
164
|
+
明示 smoke には `SPOTTER_AUDITOR_BACKEND=codex-sidecar` も使えます。
|
|
165
|
+
|
|
100
166
|
## 設計ドキュメント
|
|
101
167
|
|
|
102
168
|
- **現行設計 (カタログ / 収集経路 / 分類軸)**: [docs/catalog-design.md](docs/catalog-design.md) — v1.0.0 以降の真実源
|
|
103
169
|
- **現時点で塞がっていない穴 + 実測未検証の懸念**: [docs/open-issues.md](docs/open-issues.md) — 新規作業に入る前に必読
|
|
170
|
+
- **Claude contract capture**: [docs/SPOTTER_CLAUDE_CONTRACT.md](docs/SPOTTER_CLAUDE_CONTRACT.md) — Codex 作業で維持すべき hook / daemon / Haiku の現行契約
|
|
171
|
+
- **Claude / Codex 両対応ブリーフ**: [docs/SPOTTER_CODEX_DUAL_SUPPORT.md](docs/SPOTTER_CODEX_DUAL_SUPPORT.md) と完了済み [TODO](docs/SPOTTER_CODEX_DUAL_SUPPORT_TODO.md) — second-pass `codex-sidecar` workflow
|
|
172
|
+
- **Primary auditor backend migration**: [docs/SPOTTER_PRIMARY_BACKEND_TODO.md](docs/SPOTTER_PRIMARY_BACKEND_TODO.md) — Codex CLI / `codex-sidecar` auditor backend の rollout 状況
|
|
104
173
|
- **実装規範と不変条件 (§0)**: [CLAUDE.md](CLAUDE.md) — フォールバック禁止 / silent fallback 禁止 / 暫定コード禁止
|
|
105
174
|
- **歴史記録 (v0.1 時点の設計議事録)**: [docs/spotter-plan.md](docs/spotter-plan.md) — 作成時点で固定された議論過程のスナップショット、現行設計は上記 3 点を参照
|
|
106
175
|
|
|
@@ -110,11 +179,16 @@ spotter uninstall # hook 登録を解除 (~/.spotter は残す)
|
|
|
110
179
|
- **JSON スキーマ違反は v0.5.0 以降「想定済み異常」として silent pass + session renew で回復**します (role collapse 検知パス、daemon ログに `role_collapse_reset` を残す)。一方 **Haiku timeout は引き続き throw** され、UserPromptSubmit がブロックされてユーザー入力が Bell に届かない症状として顕在化します (timeout は v0.5.0 で 30s、v0.13.1 で 45s に拡張)。timeout の fail-open 化 (pass 扱い) は §0 改訂とセットで今後検討
|
|
111
180
|
|
|
112
181
|
<details>
|
|
113
|
-
<summary><strong>📋
|
|
182
|
+
<summary><strong>📋 最近のハイライト</strong></summary>
|
|
114
183
|
|
|
115
|
-
|
|
184
|
+
- **プラグイン形式の MCP サーバー対応** — `plugin:everything-claude-code:context7` のように名前に内部コロンを含むサーバーを正しくパースし、配下のツールをカタログに取り込めるようになった (旧版はこの形式のサーバーをすべて単一の `"plugin"` に潰して、Bell の監査から silent に脱落させていた)
|
|
185
|
+
- **プロジェクト単位の監査隔離** — daemon が監査に使うのはローカル DB のみ。グローバル DB は description 再利用キャッシュに役割限定。**他プロジェクト**でインストールしたツールが現プロジェクトの監査に混入することはない
|
|
186
|
+
- **手放しでカタログ維持** — `spotter install` が Claude DB を自動 seed、Claude / Codex それぞれの SessionStart が host-local DB を bg refresh する。手書き管理は一切不要
|
|
187
|
+
- **Codex native hooks** — Codex host は primary auditor backend として Codex CLI を使い、`.spotter/tool-db.codex.json` を Claude DB と分離し、backend failure は Haiku fallback ではなく明示 error として扱う
|
|
188
|
+
- **監査対象** — ユーザー追加分 (MCP / スキル / サブエージェント) のみ。Claude Code 本体側のツールは意図的に対象外 (Bell は元から自発率が高いため)
|
|
189
|
+
- **実装規範** — フォールバック禁止 / silent fallback 禁止 / 暫定コード禁止 ([CLAUDE.md §0](CLAUDE.md))
|
|
116
190
|
|
|
117
|
-
|
|
191
|
+
リリース履歴の全文は [CHANGELOG](CHANGELOG.md) を参照。
|
|
118
192
|
|
|
119
193
|
</details>
|
|
120
194
|
|
package/README.md
CHANGED
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
|
|
14
14
|
> **Separate the spotter from the doer.** Spotter runs alongside Claude Code and quietly flags the moments when Bell (your primary Claude) **forgets to use a tool it has access to**.
|
|
15
15
|
|
|
16
|
-
Claude has a structural blind spot: **it can't reach for a tool it doesn't realize it needs**. It
|
|
16
|
+
Claude has a structural blind spot: **it can't reach for a tool it doesn't realize it needs**. It may skip a project memory MCP when a decision should be recorded, answer from stale memory instead of a docs-lookup MCP, or reason about UI state without a browser-automation MCP. The model can't always tell when it doesn't know — so the tool stays unused.
|
|
17
17
|
|
|
18
18
|
Spotter pins a second agent (Claude Haiku 4.5) next to Bell. The second agent has the full tool catalog memorized and audits both the user's prompt and Bell's reply in parallel. When it spots a missed tool, it injects a transparent recommendation into Bell's context and, if needed, asks Bell to amend its answer. **Bell is never asked to self-audit** — that would defeat the entire premise. Detection happens through hooks, independent of Bell's intent.
|
|
19
19
|
|
|
@@ -23,14 +23,16 @@ Examples of what Spotter catches:
|
|
|
23
23
|
|
|
24
24
|
| Situation | What Bell would do | What Spotter flags |
|
|
25
25
|
|---|---|---|
|
|
26
|
-
| "
|
|
27
|
-
| "
|
|
28
|
-
| "
|
|
29
|
-
| Asserting a fact |
|
|
26
|
+
| "Please remember this OAuth gotcha" | Acknowledge and move on | Missed call to a memory / caveat MCP |
|
|
27
|
+
| "How does this package API work in the latest version?" | Answer from training-time knowledge | Missed call to a docs-lookup MCP |
|
|
28
|
+
| "Review this risky patch" | Self-review only | Missed call to a reviewer sub-agent |
|
|
29
|
+
| Asserting a fact | State it without verification | Opportunity to call a verification tool |
|
|
30
|
+
| "Does this UI still render correctly?" | Reason from source code alone | Missed call to a browser-automation MCP |
|
|
31
|
+
| "What did we decide about X earlier?" | Guess or admit forgetting | Missed call to a memory / notes MCP |
|
|
30
32
|
|
|
31
33
|
Spotter audits in two stages:
|
|
32
34
|
|
|
33
|
-
- **`stage=user_input`** — given the user's prompt, list any tools whose
|
|
35
|
+
- **`stage=user_input`** — given the user's prompt, list any local catalog tools whose description clearly applies. A *prompt-fulfillment* check
|
|
34
36
|
- **`stage=turn_end`** — given Bell's final reply, look for places where a catalog tool (verification / recording / lookup) could plug in. A *missed-opportunity* audit. Zero findings is fine; tools already used in this turn are not re-flagged
|
|
35
37
|
|
|
36
38
|
## Install
|
|
@@ -39,9 +41,14 @@ Spotter audits in two stages:
|
|
|
39
41
|
npm install -g claude-spotter
|
|
40
42
|
cd your-project
|
|
41
43
|
spotter install
|
|
44
|
+
# Optional, for Codex native hooks:
|
|
45
|
+
spotter codex-hook install
|
|
42
46
|
```
|
|
43
47
|
|
|
44
48
|
Since `v0.3.0`, Spotter requires **explicit per-project install** (the earlier `postinstall` auto-registration was the leading cause of orphan daemons). `spotter install` writes hooks into the project's `.claude/settings.json`; the audit is then active only in Claude Code sessions for that project.
|
|
49
|
+
Codex support is enabled separately by `spotter codex-hook install`, which writes user-level Codex hooks; project activation still depends on the same per-project `.spotter/marker.json` created by `spotter install`.
|
|
50
|
+
|
|
51
|
+
After upgrading Spotter, re-run `spotter install` in each installed project when release notes mention hook setting changes. The global package update changes the code path, but existing `.claude/settings.json` timeout values are not rewritten automatically.
|
|
45
52
|
|
|
46
53
|
```bash
|
|
47
54
|
spotter uninstall # remove hooks from this project
|
|
@@ -51,27 +58,54 @@ spotter uninstall # remove hooks from this project
|
|
|
51
58
|
|
|
52
59
|
- **Node.js 22.5+**
|
|
53
60
|
- **Claude Code 2.0+**
|
|
54
|
-
- **Claude Max plan** (Spotter spawns Haiku via `claude -p`)
|
|
61
|
+
- **Claude Max plan** for the current Claude-backed auditor path (Spotter spawns Haiku via `claude -p`)
|
|
62
|
+
- **Codex CLI** for Codex native hooks. Codex host auditing uses `codex exec` by default and does not fall back to Haiku
|
|
55
63
|
|
|
56
64
|
## Architecture
|
|
57
65
|
|
|
66
|
+
### Audit flow per turn
|
|
67
|
+
|
|
68
|
+
```mermaid
|
|
69
|
+
flowchart TD
|
|
70
|
+
U([User prompt]) --> UPH[UserPromptSubmit hook<br/>Spotter audits prompt against catalog]
|
|
71
|
+
UPH --> BT[Bell thinking<br/>receives Spotter's recommendations<br/>as additionalContext]
|
|
72
|
+
BT --> BA([Bell's first answer])
|
|
73
|
+
BA --> SH[Stop hook<br/>Spotter re-audits answer + tools used]
|
|
74
|
+
SH --> DEC{Missed<br/>tool?}
|
|
75
|
+
DEC -->|No| DONE([Done])
|
|
76
|
+
DEC -->|Yes| SB[Send-back to Bell<br/>max 1 round<br/>guarded by stop_hook_active]
|
|
77
|
+
SB --> BA2([Bell's amended answer]) --> DONE
|
|
58
78
|
```
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
79
|
+
|
|
80
|
+
### Catalog discovery
|
|
81
|
+
|
|
82
|
+
```mermaid
|
|
83
|
+
flowchart LR
|
|
84
|
+
subgraph SRC[Discovery sources]
|
|
85
|
+
direction TB
|
|
86
|
+
MCP[MCP servers<br/>via claude mcp list]
|
|
87
|
+
SK[Skills<br/>SKILL.md frontmatter]
|
|
88
|
+
AG[Sub-agents<br/>agent .md frontmatter]
|
|
89
|
+
BL[claude.ai baseline<br/>Gmail / Calendar / Drive<br/>injected when present]
|
|
90
|
+
end
|
|
91
|
+
subgraph SCOPES["MCP env / headers — 4 scopes, top wins on collision"]
|
|
92
|
+
direction TB
|
|
93
|
+
L["Local — projects.<root>.mcpServers in ~/.claude.json"]
|
|
94
|
+
P["Project — <root>/.mcp.json"]
|
|
95
|
+
US["User — mcpServers in ~/.claude.json"]
|
|
96
|
+
LG["Legacy — ~/.claude/.mcp.json"]
|
|
97
|
+
end
|
|
98
|
+
SCOPES -. merged into .-> MCP
|
|
99
|
+
MCP --> DB[(Host-local tool-db<br/>name + description<br/>per project)]
|
|
100
|
+
SK --> DB
|
|
101
|
+
AG --> DB
|
|
102
|
+
BL --> DB
|
|
103
|
+
DB --> H[Haiku audit<br/>session-scoped, preamble-once]
|
|
70
104
|
```
|
|
71
105
|
|
|
72
|
-
The audited
|
|
106
|
+
The audited catalog is host-local: Claude uses `<project>/.spotter/tool-db.json`, while Codex uses `<project>/.spotter/tool-db.codex.json`. **The daemon audits against the Claude local DB only**, and Codex native hooks read the Codex local DB. The global DB at `~/.spotter/tool-db.json` is a description-reuse cache shared across projects, not an audit source. Each host-local DB matches that host's **current** discovery snapshot for the project (stale entries are pruned on refresh), so tools from another project or another host cannot overwrite this session's audit catalog.
|
|
73
107
|
|
|
74
|
-
|
|
108
|
+
**`spotter install` seeds the Claude catalog automatically, and the SessionStart hook runs a background `spotter db refresh` on every Claude Code session start** — so you don't need to invoke Claude catalog commands by hand. Codex native hooks do the same for Codex: `spotter codex-hook install` registers a Codex `SessionStart` hook that starts `spotter db refresh --host-agent codex` in the background, updating `.spotter/tool-db.codex.json` without touching the Claude catalog. Claude discovery reads `claude mcp list` plus Claude skills / sub-agents; Codex discovery reads `codex mcp list/get` plus Codex skills. Each MCP server's `tools/list` is fetched via JSON-RPC (HTTP / SSE / stdio transports supported); skill and sub-agent metadata comes straight from frontmatter; the claude.ai baseline (25 hand-curated entries for Gmail / Calendar / Drive over OAuth proxy) is injected only for Claude when `claude mcp list` confirms the server is present. **You never have to maintain the tool list by hand.**
|
|
75
109
|
|
|
76
110
|
## Spotter and Throughline
|
|
77
111
|
|
|
@@ -88,21 +122,56 @@ Both share the principle of **"don't rely on the primary agent (Bell) to do it i
|
|
|
88
122
|
## Common commands
|
|
89
123
|
|
|
90
124
|
```bash
|
|
91
|
-
spotter db list # show the current local tool-db
|
|
92
|
-
spotter db
|
|
93
|
-
#
|
|
94
|
-
|
|
95
|
-
spotter db
|
|
125
|
+
spotter db list # show the current Claude local tool-db
|
|
126
|
+
spotter db list --host-agent codex
|
|
127
|
+
# show the current Codex local tool-db
|
|
128
|
+
spotter db refresh # rediscover Claude MCP / skills / sub-agents and update the Claude DB
|
|
129
|
+
spotter db refresh --host-agent codex
|
|
130
|
+
# rediscover Codex MCP / skills and update .spotter/tool-db.codex.json
|
|
131
|
+
# (Claude refresh is automatic on install + Claude SessionStart;
|
|
132
|
+
# Codex refresh is automatic on Codex SessionStart after codex-hook install)
|
|
133
|
+
spotter db rebuild # wipe Claude local + global DBs and refresh from scratch
|
|
96
134
|
# (use after catalog-shape changes)
|
|
97
135
|
spotter status # list running daemons
|
|
98
|
-
spotter doctor # environment check (Node / claude CLI / tool-db integrity)
|
|
136
|
+
spotter doctor # environment check (Node / claude CLI / Codex readiness / tool-db integrity)
|
|
137
|
+
spotter diagnostics logs # summarize daemon logs for pass=false / backend latency / anomaly signals
|
|
138
|
+
spotter codex risk-check --findings findings.json --host-agent claude
|
|
139
|
+
# run read-only codex-sidecar risk analysis for Spotter findings
|
|
140
|
+
spotter codex review|explore|opinion --findings findings.json --host-agent claude
|
|
141
|
+
# run other read-only codex-sidecar second-pass workflows
|
|
142
|
+
spotter codex work --findings findings.json --instruction "Update docs" --approve-work \
|
|
143
|
+
--allowed-path docs/ --preserve-worktree
|
|
144
|
+
# run approved codex-sidecar work in an isolated worktree
|
|
145
|
+
spotter codex-hook install
|
|
146
|
+
# register Codex native SessionStart / UserPromptSubmit / Stop hooks
|
|
147
|
+
spotter codex-hook diagnostics
|
|
148
|
+
# check Codex hooks feature and Spotter hook entries
|
|
99
149
|
spotter uninstall # remove hooks from this project (leaves ~/.spotter intact)
|
|
100
150
|
```
|
|
101
151
|
|
|
152
|
+
Optional async Codex risk dispatch:
|
|
153
|
+
|
|
154
|
+
```bash
|
|
155
|
+
SPOTTER_CODEX_RISK_CHECK=1 spotter daemon start --session-id ... --project-root ...
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
When enabled, the daemon dispatches `pass:false` findings to `spotter codex risk-check`
|
|
159
|
+
in a detached process. Hook responses do not wait for Codex. Add
|
|
160
|
+
`SPOTTER_CODEX_RISK_CHECK_DRY_RUN=1` to exercise the wiring without calling Codex.
|
|
161
|
+
|
|
162
|
+
Primary auditor backend policy: Claude hooks keep the current Haiku-compatible path by
|
|
163
|
+
default. Codex native hooks use Codex CLI by default and do not fall back to Haiku;
|
|
164
|
+
their SessionStart hook refreshes `.spotter/tool-db.codex.json` in the background
|
|
165
|
+
without touching the Claude DB.
|
|
166
|
+
`SPOTTER_AUDITOR_BACKEND=codex-sidecar` is available for explicit sidecar auditor smoke.
|
|
167
|
+
|
|
102
168
|
## Design docs
|
|
103
169
|
|
|
104
170
|
- **Current design** (catalog, discovery, classification axes): [docs/catalog-design.md](docs/catalog-design.md) — source of truth from v1.0.0
|
|
105
171
|
- **Open issues + unverified concerns**: [docs/open-issues.md](docs/open-issues.md) — read this before starting new work
|
|
172
|
+
- **Claude contract capture**: [docs/SPOTTER_CLAUDE_CONTRACT.md](docs/SPOTTER_CLAUDE_CONTRACT.md) — current hook / daemon / Haiku behavior that Codex work must preserve
|
|
173
|
+
- **Claude / Codex dual-support brief**: [docs/SPOTTER_CODEX_DUAL_SUPPORT.md](docs/SPOTTER_CODEX_DUAL_SUPPORT.md) and completed [TODO](docs/SPOTTER_CODEX_DUAL_SUPPORT_TODO.md) — second-pass `codex-sidecar` workflows
|
|
174
|
+
- **Primary auditor backend migration**: [docs/SPOTTER_PRIMARY_BACKEND_TODO.md](docs/SPOTTER_PRIMARY_BACKEND_TODO.md) — Codex CLI / `codex-sidecar` auditor backend rollout status
|
|
106
175
|
- **Implementation invariants (§0)**: [CLAUDE.md](CLAUDE.md) — no fallbacks, no silent failures, no provisional code
|
|
107
176
|
- **Historical record (v0.1 design discussion)**: [docs/spotter-plan.md](docs/spotter-plan.md) — frozen design-discussion snapshot
|
|
108
177
|
|
|
@@ -112,13 +181,16 @@ spotter uninstall # remove hooks from this project (leaves ~/.spotter int
|
|
|
112
181
|
- **Since v0.5.0, JSON schema violations from Haiku are treated as expected-anomalies** (silent pass + session renew, logged as `role_collapse_reset`) — this is the role-collapse recovery path. **Haiku timeouts still throw**, which surfaces as `UserPromptSubmit` blocking the user's prompt from reaching Bell. Timeouts have been raised twice (30s in v0.5.0, 45s in v0.13.1); making timeouts fail-open is deferred until §0 is revisited
|
|
113
182
|
|
|
114
183
|
<details>
|
|
115
|
-
<summary><strong>📋
|
|
116
|
-
|
|
117
|
-
**Structural fix for a regression that suggested tools the current project can't actually use.** The catalog the daemon audits against is now **local-only**. The global DB has been demoted to a cross-project description-reuse cache. A prune step was added to the end of `resolveAll`: any local entry not present in the current project's discovery snapshot is removed. This closes the path through which MCP servers / skills / sub-agents discovered in other projects used to linger in this project's audit set.
|
|
184
|
+
<summary><strong>📋 Recent highlights</strong></summary>
|
|
118
185
|
|
|
119
|
-
|
|
186
|
+
- **Plugin-scoped MCP servers** — names like `plugin:everything-claude-code:context7` (with internal colons) are now parsed correctly and their tools enter the catalog. Earlier versions silently collapsed all plugin MCP servers into a single literal `"plugin"`, dropping their tools from Bell's audit
|
|
187
|
+
- **Per-project audit isolation** — the daemon audits against the local DB only; the global DB has been demoted to a description-reuse cache. Tools discovered in *other* projects can never bleed into this project's audit set
|
|
188
|
+
- **Zero-touch catalog** — `spotter install` seeds the Claude DB automatically; Claude and Codex SessionStart hooks keep their host-local DBs fresh in the background. You never have to maintain the tool list by hand
|
|
189
|
+
- **Codex native hooks** — Codex host uses Codex CLI as the primary auditor backend, keeps a separate `.spotter/tool-db.codex.json`, and surfaces backend failures explicitly instead of falling back to Haiku
|
|
190
|
+
- **Audit scope** — only user-added surface (MCP servers / skills / sub-agents). Claude Code's built-in tools are intentionally out of scope; Bell already uses those reliably
|
|
191
|
+
- **Implementation invariants** — no fallbacks, no silent failures, no provisional code (see [§0 in CLAUDE.md](CLAUDE.md))
|
|
120
192
|
|
|
121
|
-
Full
|
|
193
|
+
Full release history: [CHANGELOG](CHANGELOG.md).
|
|
122
194
|
|
|
123
195
|
</details>
|
|
124
196
|
|