claude-spotter 1.4.3 → 1.4.5
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 +57 -3
- package/README.ja.md +12 -6
- package/README.md +14 -7
- package/package.json +1 -1
- package/src/cli/db-cmd.mjs +7 -8
- package/src/cli/doctor.mjs +12 -9
- package/src/cli/install.mjs +1 -1
- package/src/core/codex-cli-backend.mjs +3 -2
- package/src/tool-db/loader.mjs +6 -3
- package/src/tool-db/refresh.mjs +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,59 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 1.4.5
|
|
4
|
+
|
|
5
|
+
**Codex global tool-db を Claude global tool-db から分離**。v1.4.4 までは local DB は
|
|
6
|
+
`.spotter/tool-db.json` と `.spotter/tool-db.codex.json` に分かれていたが、refresh 時の
|
|
7
|
+
description 再利用 cache は Claude / Codex とも `~/.spotter/tool-db.json` を共有していた。
|
|
8
|
+
Claude 側で苦労して塞いだ「別環境の DB が監査視野に混ざる」設計事故を Codex 側で再発させないため、
|
|
9
|
+
host-global DB も分離した。
|
|
10
|
+
|
|
11
|
+
### 変更点
|
|
12
|
+
|
|
13
|
+
- **編集 [src/tool-db/loader.mjs](src/tool-db/loader.mjs)**:
|
|
14
|
+
`globalDbPath(hostAgent)` を host-aware にし、Claude は既存互換の
|
|
15
|
+
`~/.spotter/tool-db.json`、Codex は `~/.spotter/tool-db.codex.json` を使うようにした。
|
|
16
|
+
- **編集 [src/tool-db/refresh.mjs](src/tool-db/refresh.mjs)**:
|
|
17
|
+
`refresh({hostAgent})` の local → global → investigate lookup が同じ host の
|
|
18
|
+
global cache だけを見るようにした。
|
|
19
|
+
- **編集 [src/cli/db-cmd.mjs](src/cli/db-cmd.mjs) / [src/cli/doctor.mjs](src/cli/doctor.mjs)**:
|
|
20
|
+
`spotter db refresh/rebuild --host-agent codex` と `spotter doctor` の表示・消去対象を
|
|
21
|
+
host-global DB に追従。
|
|
22
|
+
- **編集 [test/tool-db.test.mjs](test/tool-db.test.mjs)**:
|
|
23
|
+
Claude global cache の同名 entry が Codex refresh に write-through されず、
|
|
24
|
+
Codex 側では Codex global cache / investigate を使う回帰テストを追加。
|
|
25
|
+
- **編集 README / README.ja / CLAUDE.md / docs**:
|
|
26
|
+
local だけでなく global description cache も Claude / Codex で分離する設計に更新。
|
|
27
|
+
|
|
28
|
+
### ユーザー側で必要な手順
|
|
29
|
+
|
|
30
|
+
1. `npm install -g claude-spotter@1.4.5`
|
|
31
|
+
2. 既存の shared global cache を掃除するため、各プロジェクトで
|
|
32
|
+
`spotter db rebuild` と `spotter db rebuild --host-agent codex` を 1 回ずつ実行
|
|
33
|
+
3. 各プロジェクトで `spotter install`
|
|
34
|
+
|
|
35
|
+
## 1.4.4
|
|
36
|
+
|
|
37
|
+
**Codex CLI auditor の default model を明示固定**。Spotter の hook 判定は高頻度・低遅延・低コストの
|
|
38
|
+
構造化 JSON 監査であり、Codex CLI の暗黙 default model に依存すると、`--ignore-user-config` 環境で
|
|
39
|
+
実際に呼ぶ model が不透明になるため修正。
|
|
40
|
+
|
|
41
|
+
### 変更点
|
|
42
|
+
|
|
43
|
+
- **編集 [src/core/codex-cli-backend.mjs](src/core/codex-cli-backend.mjs)**:
|
|
44
|
+
`SPOTTER_CODEX_CLI_MODEL` 未設定時も `--model gpt-5.4-mini` を渡すようにした。
|
|
45
|
+
`SPOTTER_CODEX_CLI_REASONING_EFFORT` 未設定時の `model_reasoning_effort="low"` は維持。
|
|
46
|
+
- **編集 [test/codex-cli-backend.test.mjs](test/codex-cli-backend.test.mjs)**:
|
|
47
|
+
default args が `gpt-5.4-mini` を含むことと、明示的に `model: ""` を渡した場合だけ
|
|
48
|
+
`--model` を省略できることを固定。
|
|
49
|
+
- **編集 README / README.ja / CLAUDE.md / docs**: Codex CLI auditor child の既定を
|
|
50
|
+
`gpt-5.4-mini` + `model_reasoning_effort="low"` と明記。
|
|
51
|
+
|
|
52
|
+
### ユーザー側で必要な手順
|
|
53
|
+
|
|
54
|
+
1. `npm install -g claude-spotter@1.4.4`
|
|
55
|
+
2. 各プロジェクトで `spotter install`
|
|
56
|
+
|
|
3
57
|
## 1.4.3
|
|
4
58
|
|
|
5
59
|
**README の Codex refresh 手順表現を v1.4.2 の実装と一致させる docs patch release**。v1.4.2 で Codex hooks 登録は `spotter install` に集約済みだが、README / README.ja の common commands コメントに `codex-hook install` 後という古い表現が残っていたため修正。
|
|
@@ -411,7 +465,7 @@ v0.8.0 で claude.ai OAuth 系 MCP (Gmail / Calendar / Drive) を手書き basel
|
|
|
411
465
|
- **編集 [docs/catalog-design.md](docs/catalog-design.md)**:
|
|
412
466
|
- 新節「収集タイミング (v1.1.0 以降)」追加 — install 同期 seed / SessionStart bg refresh / db refresh / db rebuild の 4 経路を整理
|
|
413
467
|
- 歴史節に v1.1.x の「収集タイミング自動化」を追記
|
|
414
|
-
- **編集 [docs/spotter-plan.md](docs/spotter-plan.md)**:
|
|
468
|
+
- **編集 [docs/archive/spotter-plan.md](docs/archive/spotter-plan.md)**:
|
|
415
469
|
- 冒頭に「v0.1 時点の設計議事録」である旨のブリッジ追加、現行設計の真実源 (catalog-design.md / open-issues.md / CLAUDE.md) へのリンクを明示
|
|
416
470
|
|
|
417
471
|
## 1.1.2
|
|
@@ -1174,7 +1228,7 @@ layers cover the same proliferation cases.
|
|
|
1174
1228
|
|
|
1175
1229
|
## 0.1.1 — ⚠️ DEPRECATED 2026-04-19
|
|
1176
1230
|
|
|
1177
|
-
**Do not install this version.** Real-world testing against a live Claude Code session revealed that the "one daemon per session" model is based on a wrong assumption — `SessionStart` hooks fire per subagent (Task tool invocation), not only at top-level session startup. Within 41 seconds of install, 213 orphan daemons accumulated and Haiku API calls uniformly timed out. `npm uninstall -g` also did not execute `preuninstall`, leaving hook entries in `~/.claude/settings.json`. See [docs/spotter-plan.md §18](https://github.com/kitepon-rgb/Spotter/blob/main/docs/spotter-plan.md#18) for details and the v0.2 redesign plan.
|
|
1231
|
+
**Do not install this version.** Real-world testing against a live Claude Code session revealed that the "one daemon per session" model is based on a wrong assumption — `SessionStart` hooks fire per subagent (Task tool invocation), not only at top-level session startup. Within 41 seconds of install, 213 orphan daemons accumulated and Haiku API calls uniformly timed out. `npm uninstall -g` also did not execute `preuninstall`, leaving hook entries in `~/.claude/settings.json`. See [docs/archive/spotter-plan.md §18](https://github.com/kitepon-rgb/Spotter/blob/main/docs/archive/spotter-plan.md#18) for details and the v0.2 redesign plan.
|
|
1178
1232
|
|
|
1179
1233
|
## 0.1.1 (pre-deprecation notes)
|
|
1180
1234
|
|
|
@@ -1201,4 +1255,4 @@ Initial release.
|
|
|
1201
1255
|
|
|
1202
1256
|
### Design
|
|
1203
1257
|
|
|
1204
|
-
All non-negotiable design decisions — including transparency vs invisibility, JSON I/O, socket abstraction, message envelope, SessionStart readiness — are documented in [docs/spotter-plan.md](docs/spotter-plan.md).
|
|
1258
|
+
All non-negotiable design decisions — including transparency vs invisibility, JSON I/O, socket abstraction, message envelope, SessionStart readiness — are documented in [docs/archive/spotter-plan.md](docs/archive/spotter-plan.md).
|
package/README.ja.md
CHANGED
|
@@ -63,6 +63,10 @@ spotter uninstall # このプロジェクトの hook 登録を解除
|
|
|
63
63
|
|
|
64
64
|
### 1 ターンの監査フロー
|
|
65
65
|
|
|
66
|
+
Claude Code と Codex では `Stop` の受け口が違います。下の図は Claude host の流れです。
|
|
67
|
+
Codex native `Stop` は遅延配送で、不足ツールの指摘を queue し、次の same-session
|
|
68
|
+
`UserPromptSubmit` で提示します。
|
|
69
|
+
|
|
66
70
|
```mermaid
|
|
67
71
|
flowchart TD
|
|
68
72
|
U([User 発話]) --> UPH[UserPromptSubmit hook<br/>Spotter が発話とカタログから一次判定]
|
|
@@ -101,7 +105,7 @@ flowchart LR
|
|
|
101
105
|
DB --> H[Haiku 監査<br/>session-scoped, preamble-once]
|
|
102
106
|
```
|
|
103
107
|
|
|
104
|
-
監査対象のツール (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 を読みます。グローバル
|
|
108
|
+
監査対象のツール (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 を読みます。グローバル description cache も host ごとに分離され、Claude は `~/.spotter/tool-db.json`、Codex は `~/.spotter/tool-db.codex.json` を使います。これらは同じ host の他プロジェクト間でだけ再利用され、監査入力には混ぜません。各 host-local DB は **その host の現時点の discovery 結果と一致** (refresh 時に prune される) するため、別プロジェクトや別 host のツールリストで上書きされることはありません。
|
|
105
109
|
|
|
106
110
|
**`spotter install` が Claude catalog の初回 seed を自動実行し、Claude Code セッション起動ごとに SessionStart hook が bg で `spotter db refresh` を走らせる**ため、Claude 通常運用で手動コマンドを叩く必要はありません。Codex CLI が使える環境では、同じ `spotter install` が Codex native hooks も登録します。Codex `SessionStart` hook は `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` に該当サーバーが存在する環境で注入されます。**手書きでツールリストを管理する必要はありません**。
|
|
107
111
|
|
|
@@ -128,7 +132,7 @@ spotter db refresh --host-agent codex
|
|
|
128
132
|
# Codex MCP / スキルから description を収集して .spotter/tool-db.codex.json を更新
|
|
129
133
|
# (Claude は install + Claude SessionStart、Codex は spotter install 後の
|
|
130
134
|
# Codex SessionStart で自動実行されるので通常は不要)
|
|
131
|
-
spotter db rebuild # Claude local + global DB を両方消してから refresh (カタログ設計変更時のクリーン用)
|
|
135
|
+
spotter db rebuild # Claude local + Claude global DB を両方消してから refresh (カタログ設計変更時のクリーン用)
|
|
132
136
|
spotter status # 稼働中の daemon 一覧
|
|
133
137
|
spotter doctor # 環境診断 (Node / claude CLI / Codex readiness / tool-db 整合性)
|
|
134
138
|
spotter diagnostics logs # daemon log から pass=false / backend latency / anomaly signal を集計
|
|
@@ -159,21 +163,23 @@ SPOTTER_CODEX_RISK_CHECK=1 spotter daemon start --session-id ... --project-root
|
|
|
159
163
|
Primary auditor backend policy: Claude hooks は現行の Haiku compatibility path を既定のまま維持します。
|
|
160
164
|
Codex native hooks は Codex CLI を既定 backend とし、Haiku へ fallback しません。
|
|
161
165
|
Codex 側の SessionStart hook は `.spotter/tool-db.codex.json` を bg refresh し、Claude DB には触れません。
|
|
166
|
+
Codex CLI auditor の子プロセスは、hook 判定を安く速く保つため既定で `gpt-5.4-mini` と
|
|
167
|
+
`model_reasoning_effort="low"` を明示指定します。実測や制御された実験では
|
|
168
|
+
`SPOTTER_CODEX_CLI_MODEL` / `SPOTTER_CODEX_CLI_REASONING_EFFORT` で上書きできます。
|
|
162
169
|
明示 smoke には `SPOTTER_AUDITOR_BACKEND=codex-sidecar` も使えます。
|
|
163
170
|
|
|
164
171
|
## 設計ドキュメント
|
|
165
172
|
|
|
166
173
|
- **現行設計 (カタログ / 収集経路 / 分類軸)**: [docs/catalog-design.md](docs/catalog-design.md) — v1.0.0 以降の真実源
|
|
167
174
|
- **現時点で塞がっていない穴 + 実測未検証の懸念**: [docs/open-issues.md](docs/open-issues.md) — 新規作業に入る前に必読
|
|
168
|
-
- **
|
|
169
|
-
- **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
|
|
170
|
-
- **Primary auditor backend migration**: [docs/SPOTTER_PRIMARY_BACKEND_TODO.md](docs/SPOTTER_PRIMARY_BACKEND_TODO.md) — Codex CLI / `codex-sidecar` auditor backend の rollout 状況
|
|
175
|
+
- **Runtime contract**: [docs/SPOTTER_CLAUDE_CONTRACT.md](docs/SPOTTER_CLAUDE_CONTRACT.md) — Claude hook / daemon / Haiku 契約と Codex native hook policy
|
|
171
176
|
- **実装規範と不変条件 (§0)**: [CLAUDE.md](CLAUDE.md) — フォールバック禁止 / silent fallback 禁止 / 暫定コード禁止
|
|
172
|
-
-
|
|
177
|
+
- **Archive**: [docs/archive/](docs/archive/) — 完了済み Codex rollout 計画、primary backend smoke log、v0.1 設計議事録
|
|
173
178
|
|
|
174
179
|
## 既知の制約
|
|
175
180
|
|
|
176
181
|
- Stop hook は Bell の最初の応答が**出力された後**に発火するため、Spotter が Stop で差し戻した場合、ユーザーは「最初の応答 + 補正応答」の 2 連続を見ます (Claude Code の hook 仕様による制約)。UserPromptSubmit 段階での先回り検出を精度の軸にしています
|
|
182
|
+
- Codex native `Stop` は **即時ブロックではなく遅延配送**です。Codex `Stop` で不足ツールを見つけた場合、Spotter は `.spotter/codex-pending/` に指摘を保存し、次の same-session `UserPromptSubmit` で `additionalContext` として提示します。これは Codex の現行 `decision:"block"` が `Stop Blocked` / exit code 1 になりやすい実測結果を避けるためです
|
|
177
183
|
- **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 改訂とセットで今後検討
|
|
178
184
|
|
|
179
185
|
<details>
|
package/README.md
CHANGED
|
@@ -63,6 +63,10 @@ spotter uninstall # remove hooks from this project
|
|
|
63
63
|
|
|
64
64
|
### Audit flow per turn
|
|
65
65
|
|
|
66
|
+
Claude Code and Codex have different `Stop` surfaces. The diagram below is the Claude
|
|
67
|
+
host flow. Codex native `Stop` uses deferred delivery: findings are queued and shown on
|
|
68
|
+
the next same-session `UserPromptSubmit`.
|
|
69
|
+
|
|
66
70
|
```mermaid
|
|
67
71
|
flowchart TD
|
|
68
72
|
U([User prompt]) --> UPH[UserPromptSubmit hook<br/>Spotter audits prompt against catalog]
|
|
@@ -101,7 +105,7 @@ flowchart LR
|
|
|
101
105
|
DB --> H[Haiku audit<br/>session-scoped, preamble-once]
|
|
102
106
|
```
|
|
103
107
|
|
|
104
|
-
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.
|
|
108
|
+
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. Global description caches are host-specific too: Claude uses `~/.spotter/tool-db.json`, while Codex uses `~/.spotter/tool-db.codex.json`. They are shared only across projects for the same host and are never audit sources. 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.
|
|
105
109
|
|
|
106
110
|
**`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. When Codex CLI is available, the same `spotter install` registers Codex native hooks; their `SessionStart` hook 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.**
|
|
107
111
|
|
|
@@ -128,7 +132,7 @@ spotter db refresh --host-agent codex
|
|
|
128
132
|
# rediscover Codex MCP / skills and update .spotter/tool-db.codex.json
|
|
129
133
|
# (Claude refresh is automatic on install + Claude SessionStart;
|
|
130
134
|
# Codex refresh is automatic on Codex SessionStart after spotter install)
|
|
131
|
-
spotter db rebuild # wipe Claude local + global DBs and refresh from scratch
|
|
135
|
+
spotter db rebuild # wipe Claude local + Claude global DBs and refresh from scratch
|
|
132
136
|
# (use after catalog-shape changes)
|
|
133
137
|
spotter status # list running daemons
|
|
134
138
|
spotter doctor # environment check (Node / claude CLI / Codex readiness / tool-db integrity)
|
|
@@ -161,28 +165,31 @@ Primary auditor backend policy: Claude hooks keep the current Haiku-compatible p
|
|
|
161
165
|
default. Codex native hooks use Codex CLI by default and do not fall back to Haiku;
|
|
162
166
|
their SessionStart hook refreshes `.spotter/tool-db.codex.json` in the background
|
|
163
167
|
without touching the Claude DB.
|
|
168
|
+
Codex CLI auditor child processes explicitly use `gpt-5.4-mini` with
|
|
169
|
+
`model_reasoning_effort="low"` by default so hook checks stay cheap and fast;
|
|
170
|
+
`SPOTTER_CODEX_CLI_MODEL` and `SPOTTER_CODEX_CLI_REASONING_EFFORT` can override
|
|
171
|
+
those values for smoke tests or controlled experiments.
|
|
164
172
|
`SPOTTER_AUDITOR_BACKEND=codex-sidecar` is available for explicit sidecar auditor smoke.
|
|
165
173
|
|
|
166
174
|
## Design docs
|
|
167
175
|
|
|
168
176
|
- **Current design** (catalog, discovery, classification axes): [docs/catalog-design.md](docs/catalog-design.md) — source of truth from v1.0.0
|
|
169
177
|
- **Open issues + unverified concerns**: [docs/open-issues.md](docs/open-issues.md) — read this before starting new work
|
|
170
|
-
- **
|
|
171
|
-
- **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
|
|
172
|
-
- **Primary auditor backend migration**: [docs/SPOTTER_PRIMARY_BACKEND_TODO.md](docs/SPOTTER_PRIMARY_BACKEND_TODO.md) — Codex CLI / `codex-sidecar` auditor backend rollout status
|
|
178
|
+
- **Runtime contract**: [docs/SPOTTER_CLAUDE_CONTRACT.md](docs/SPOTTER_CLAUDE_CONTRACT.md) — Claude hook / daemon / Haiku contract plus Codex native hook policy
|
|
173
179
|
- **Implementation invariants (§0)**: [CLAUDE.md](CLAUDE.md) — no fallbacks, no silent failures, no provisional code
|
|
174
|
-
- **
|
|
180
|
+
- **Archived plans and history**: [docs/archive/](docs/archive/) — completed Codex rollout plans, primary backend smoke logs, and the frozen v0.1 design discussion
|
|
175
181
|
|
|
176
182
|
## Known limitations
|
|
177
183
|
|
|
178
184
|
- The `Stop` hook fires **after** Bell's first answer has already been streamed to the user. When Spotter sends Bell back, the user sees both the original answer and the corrected one. Detection accuracy in `UserPromptSubmit` (the *pre-response* stage) is therefore Spotter's primary axis of quality
|
|
185
|
+
- Codex native `Stop` is **deferred**, not an immediate block. If Spotter finds a missed tool at Codex `Stop`, it writes the finding to `.spotter/codex-pending/` and surfaces it on the next same-session `UserPromptSubmit` as `additionalContext`. This avoids Codex's current `Stop Blocked` / exit-code-1 behavior for `decision:"block"`
|
|
179
186
|
- **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
|
|
180
187
|
|
|
181
188
|
<details>
|
|
182
189
|
<summary><strong>📋 Recent highlights</strong></summary>
|
|
183
190
|
|
|
184
191
|
- **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
|
|
185
|
-
- **Per-project audit isolation** — the daemon audits against the local DB only;
|
|
192
|
+
- **Per-project / per-host audit isolation** — the daemon audits against the local DB only; global DBs are host-specific description caches. Tools discovered in *other* projects or another host can never bleed into this project's audit set
|
|
186
193
|
- **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
|
|
187
194
|
- **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
|
|
188
195
|
- **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
|
package/package.json
CHANGED
package/src/cli/db-cmd.mjs
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
//
|
|
3
3
|
// spotter db list — print the LOCAL tool-db (what the daemon actually audits)
|
|
4
4
|
// spotter db refresh — discover available tools and update DB (3-tier resolve)
|
|
5
|
-
// spotter db rebuild — wipe local + global DBs then refresh
|
|
5
|
+
// spotter db rebuild — wipe host-local + host-global DBs then refresh
|
|
6
6
|
//
|
|
7
7
|
// Run inside a project that has been `spotter install`-ed.
|
|
8
8
|
|
|
@@ -52,20 +52,19 @@ export async function runDbRefresh({ argv = [] } = {}) {
|
|
|
52
52
|
process.stdout.write(
|
|
53
53
|
`${resolved.size} tool(s) resolved (local=${counts.local}, global=${counts.global}, investigated=${counts.investigated})\n`
|
|
54
54
|
+ `local DB: ${localDbPath(projectRoot, opts.hostAgent)}\n`
|
|
55
|
-
+ `global DB: ${globalDbPath()}\n`
|
|
55
|
+
+ `global DB: ${globalDbPath(opts.hostAgent)}\n`
|
|
56
56
|
);
|
|
57
57
|
}
|
|
58
58
|
|
|
59
59
|
export async function runDbRebuild({ argv = [] } = {}) {
|
|
60
60
|
const projectRoot = requireProjectRoot();
|
|
61
61
|
const opts = parseDbArgs(argv);
|
|
62
|
-
//
|
|
63
|
-
//
|
|
64
|
-
//
|
|
65
|
-
// touches names currently produced by investigation. Users need a clean slate.
|
|
62
|
+
// Wipe BOTH host-local and host-global DB. Rationale: catalog scope changes and
|
|
63
|
+
// description drift must not leak between Claude and Codex; each host cache is a
|
|
64
|
+
// separate clean-slate unit.
|
|
66
65
|
await saveDb(localDbPath(projectRoot, opts.hostAgent), emptyDb());
|
|
67
|
-
await saveDb(globalDbPath(), emptyDb());
|
|
68
|
-
process.stderr.write(`spotter db rebuild: cleared ${opts.hostAgent} local + global DB, refreshing...\n`);
|
|
66
|
+
await saveDb(globalDbPath(opts.hostAgent), emptyDb());
|
|
67
|
+
process.stderr.write(`spotter db rebuild: cleared ${opts.hostAgent} local + ${opts.hostAgent} global DB, refreshing...\n`);
|
|
69
68
|
await runDbRefresh({ argv });
|
|
70
69
|
}
|
|
71
70
|
|
package/src/cli/doctor.mjs
CHANGED
|
@@ -78,15 +78,18 @@ export async function runDoctor() {
|
|
|
78
78
|
if (!sidecar.ok) warnings += 1;
|
|
79
79
|
}
|
|
80
80
|
|
|
81
|
-
// tool-db (global
|
|
82
|
-
//
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
81
|
+
// tool-db (host-specific global caches). Since v1.2.0 these are not part of
|
|
82
|
+
// audit input; each host audits its project-local DB only. Empty caches are fine.
|
|
83
|
+
for (const hostAgent of ['claude', 'codex']) {
|
|
84
|
+
try {
|
|
85
|
+
const path = globalDbPath(hostAgent);
|
|
86
|
+
const global = await loadDb(path);
|
|
87
|
+
const count = Object.keys(global.tools).length;
|
|
88
|
+
mark(true, `${hostAgent} global cache DB: ${count} tools at ${path}`);
|
|
89
|
+
} catch (err) {
|
|
90
|
+
mark(false, `${hostAgent} global cache DB`, `${err.message} (cache only; audit uses local DB)`);
|
|
91
|
+
warnings += 1;
|
|
92
|
+
}
|
|
90
93
|
}
|
|
91
94
|
|
|
92
95
|
// tool-db (local) if cwd is inside a Spotter project. Claude and Codex use
|
package/src/cli/install.mjs
CHANGED
|
@@ -143,7 +143,7 @@ export async function runInstall({
|
|
|
143
143
|
const resolved = await refreshFn({ projectRoot: cwd, hostAgent: 'claude', logFn: log });
|
|
144
144
|
console.log(` ${resolved.size} tool(s) resolved`);
|
|
145
145
|
console.log(` local DB: ${localDbPath(cwd, 'claude')}`);
|
|
146
|
-
console.log(` global DB: ${globalDbPath()}`);
|
|
146
|
+
console.log(` global DB: ${globalDbPath('claude')}`);
|
|
147
147
|
} catch (err) {
|
|
148
148
|
// §0: throw (fallback 禁止). But surface the recovery path so the user isn't
|
|
149
149
|
// left with "hooks registered, tool-db missing" and no clue what to run.
|
|
@@ -7,6 +7,7 @@ import { AuditorBackendError } from './auditor-error.mjs';
|
|
|
7
7
|
import { filterCatalogMisses, parseAuditorResponse } from './auditor-response.mjs';
|
|
8
8
|
|
|
9
9
|
const DEFAULT_CODEX_CLI_TIMEOUT_MS = 45_000;
|
|
10
|
+
const DEFAULT_CODEX_CLI_MODEL = 'gpt-5.4-mini';
|
|
10
11
|
const DEFAULT_CODEX_CLI_REASONING_EFFORT = 'low';
|
|
11
12
|
const STDERR_LIMIT = 32 * 1024;
|
|
12
13
|
const STDOUT_LIMIT = 64 * 1024;
|
|
@@ -73,7 +74,7 @@ export function createCodexCliAuditorBackend({
|
|
|
73
74
|
env,
|
|
74
75
|
spawnFn,
|
|
75
76
|
timeoutMs,
|
|
76
|
-
model: env?.SPOTTER_CODEX_CLI_MODEL,
|
|
77
|
+
model: env?.SPOTTER_CODEX_CLI_MODEL || DEFAULT_CODEX_CLI_MODEL,
|
|
77
78
|
reasoningEffort: env?.SPOTTER_CODEX_CLI_REASONING_EFFORT || DEFAULT_CODEX_CLI_REASONING_EFFORT,
|
|
78
79
|
});
|
|
79
80
|
let rawFinal;
|
|
@@ -146,7 +147,7 @@ export function buildCodexCliAuditorPrompt({ catalog, input }) {
|
|
|
146
147
|
return lines.join('\n');
|
|
147
148
|
}
|
|
148
149
|
|
|
149
|
-
export function buildCodexExecArgs({ schemaPath, lastMessagePath, projectRoot, prompt, model =
|
|
150
|
+
export function buildCodexExecArgs({ schemaPath, lastMessagePath, projectRoot, prompt, model = DEFAULT_CODEX_CLI_MODEL, reasoningEffort = DEFAULT_CODEX_CLI_REASONING_EFFORT }) {
|
|
150
151
|
for (const [name, value] of Object.entries({ schemaPath, lastMessagePath, projectRoot, prompt })) {
|
|
151
152
|
if (typeof value !== 'string' || value.length === 0) {
|
|
152
153
|
throw new TypeError(`buildCodexExecArgs: ${name} must be a non-empty string`);
|
package/src/tool-db/loader.mjs
CHANGED
|
@@ -3,7 +3,8 @@
|
|
|
3
3
|
// Two layers:
|
|
4
4
|
// - local: <project>/.spotter/tool-db.json (Claude host)
|
|
5
5
|
// <project>/.spotter/tool-db.codex.json (Codex host)
|
|
6
|
-
// - global: ~/.spotter/tool-db.json
|
|
6
|
+
// - global: ~/.spotter/tool-db.json (Claude host)
|
|
7
|
+
// ~/.spotter/tool-db.codex.json (Codex host)
|
|
7
8
|
//
|
|
8
9
|
// Both have the same shape:
|
|
9
10
|
// { "version": 1, "tools": { "<name>": "<description>", ... } }
|
|
@@ -22,8 +23,10 @@ export class ToolDbSchemaError extends Error {
|
|
|
22
23
|
}
|
|
23
24
|
}
|
|
24
25
|
|
|
25
|
-
export function globalDbPath() {
|
|
26
|
-
|
|
26
|
+
export function globalDbPath(hostAgent = 'claude') {
|
|
27
|
+
const host = normalizeToolDbHostAgent(hostAgent);
|
|
28
|
+
const file = host === 'claude' ? 'tool-db.json' : `tool-db.${host}.json`;
|
|
29
|
+
return join(homedir(), '.spotter', file);
|
|
27
30
|
}
|
|
28
31
|
|
|
29
32
|
export function localDbPath(projectRoot, hostAgent = 'claude') {
|
package/src/tool-db/refresh.mjs
CHANGED
|
@@ -101,14 +101,14 @@ export async function refresh({
|
|
|
101
101
|
return resolveAll({
|
|
102
102
|
toolNames,
|
|
103
103
|
localPath: localDbPath(projectRoot, toolDbHostAgent),
|
|
104
|
-
globalPath: globalDbPath(),
|
|
104
|
+
globalPath: globalDbPath(toolDbHostAgent),
|
|
105
105
|
investigate,
|
|
106
106
|
logFn,
|
|
107
107
|
});
|
|
108
108
|
}
|
|
109
109
|
|
|
110
110
|
// Read-only: load the LOCAL tool-db only — the daemon's audit must reflect what this
|
|
111
|
-
// specific project can actually use. The global DB is a
|
|
111
|
+
// specific project can actually use. The host-specific global DB is a cache written by
|
|
112
112
|
// `refresh` (so other projects can pick up descriptions cheaply) but is NEVER mixed
|
|
113
113
|
// into the daemon's audit catalog. Mixing global in caused phantom-tool suggestions
|
|
114
114
|
// from previously-visited projects bleeding into unrelated ones.
|