claude-spotter 1.7.2 → 1.8.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 +11 -0
- package/README.ja.md +19 -25
- package/README.md +20 -26
- package/bin/spotter.mjs +6 -10
- package/docs/11_dashboard-operations.md +3 -26
- package/ops/dashboard/hub-config.json +1 -1
- package/package.json +1 -1
- package/src/cli/auditor-cmd.mjs +1 -7
- package/src/cli/db-cmd.mjs +3 -3
- package/src/cli/doctor.mjs +19 -41
- package/src/cli/grok-hook-cmd.mjs +239 -0
- package/src/cli/install.mjs +28 -1
- package/src/core/auditor-backend.mjs +4 -13
- package/src/core/codex-cli-backend.mjs +3 -0
- package/src/core/hook-event-log.mjs +3 -3
- package/src/core/host-agent.mjs +2 -1
- package/src/daemon/daemon.mjs +0 -39
- package/src/hooks/lib.mjs +6 -5
- package/src/host/adapters.mjs +10 -1
- package/src/index.mjs +0 -32
- package/src/tool-db/investigate-grok.mjs +48 -0
- package/src/tool-db/refresh.mjs +2 -1
- package/src/cli/codex-cmd.mjs +0 -254
- package/src/core/codex-risk-dispatch.mjs +0 -101
- package/src/core/codex-sidecar-auditor-backend.mjs +0 -333
- package/src/core/codex-sidecar-policy.mjs +0 -194
- package/src/core/codex-sidecar-runner.mjs +0 -761
- package/src/core/sidecar-context.mjs +0 -117
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,17 @@
|
|
|
3
3
|
各節はそのversion公開時点の変更記録であり、後続versionにより置換された仕様を含む。
|
|
4
4
|
現行runtime契約は[`docs/00_overview.md`](https://github.com/kitepon/Spotter/blob/main/docs/00_overview.md)から辿る。
|
|
5
5
|
|
|
6
|
+
## 1.8.0 — 2026-09-27
|
|
7
|
+
|
|
8
|
+
- Grok Buildのnative hookとhost専用カタログを追加。Linux、macOS、Windows nativeの実セッションで入力時・応答後の監査を確認した。Grok 1.0.41は受動hookのstdoutを会話へ渡さないため、findingは構造eventと評価DBに記録する。
|
|
9
|
+
- Grokのheadless実行で最終応答つき`Stop`が欠けたturnを`SessionEnd`で補完する。Windowsでは`SessionStart`のカタログ更新完了を待ち、初回監査から有効なツールを使う。
|
|
10
|
+
- Windows Cursorのhook入力に付くUTF-8 BOMを受け付け、Git管理外のprojectでもCodex CLI監査を実行できるようにする。
|
|
11
|
+
- dashboardの現行構成から廃止済みFOX WSL2端末を外し、3端末を表示する。
|
|
12
|
+
|
|
13
|
+
## 1.7.3 — 2026-09-24
|
|
14
|
+
|
|
15
|
+
- 退役するcodex-sidecarの明示CLI、追加監査dispatch、primary auditor backend指定、診断と関連コードを削除する。Jev、Codex CLI、Haikuの主監査は維持する。
|
|
16
|
+
|
|
6
17
|
## 1.7.2 — 2026-09-21
|
|
7
18
|
|
|
8
19
|
- Jevの判定を実験済みの短い質問+Noulへ変更し、肯定確率0.5超を提案する。
|
package/README.ja.md
CHANGED
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
|
|
19
19
|
## 所有境界
|
|
20
20
|
|
|
21
|
-
本repositoryはSpotter製品面の全体、すなわち監査挙動、Claude/Codex hook adapter、
|
|
21
|
+
本repositoryはSpotter製品面の全体、すなわち監査挙動、Claude/Codex/Cursor/Grok hook adapter、
|
|
22
22
|
project marker、catalog discoveryとhost-local tool DB、評価store、dashboard server、
|
|
23
23
|
diagnostics、installer、release packagingを所有します。
|
|
24
24
|
[dotagents](https://github.com/kitepon/dotagents)が所有するのは共有agent指示と、
|
|
@@ -68,16 +68,18 @@ cd your-project
|
|
|
68
68
|
spotter install
|
|
69
69
|
```
|
|
70
70
|
|
|
71
|
-
macOS の Homebrew Node 環境では、Codex
|
|
71
|
+
macOS の Homebrew Node 環境では、CodexとGrokのhook commandのNodeパスに現在の実体と一致する
|
|
72
72
|
安定 symlink (`/opt/homebrew/bin/node`) を使います。
|
|
73
73
|
`/opt/homebrew/Cellar/node/<version>/...` のような version 固定パスを書かないため、
|
|
74
|
-
Homebrew で Node が更新されても
|
|
74
|
+
Homebrew で Node が更新されてもhookが古いNodeパスに取り残されません。
|
|
75
75
|
|
|
76
76
|
`v0.3.0` 以降は**プロジェクト単位の明示的 install** を採用しています (v0.2 までの `postinstall` 自動登録はデーモン増殖の主因だったため撤回)。各プロジェクトの `.claude/settings.json` に hook を登録し、そのプロジェクトでの Claude Code セッションのみで有効になります。
|
|
77
77
|
Codex CLI が使える環境では、同じ `spotter install` が user-level の Codex native hooks も登録します。実際に動くプロジェクトは `spotter install` が作る `.spotter/marker.json` で制限されるため、無関係な Codex セッションでは Spotter は起動しません。
|
|
78
78
|
Codex 側では現行の `[features].hooks = true` を有効化し、互換のため旧 `codex_hooks` diagnostics output も認識します。
|
|
79
79
|
Spotter が所有する Codex handler は現行の同期 command schema で生成します。install / upgrade 後は `/hooks` で review して新しい Codex session を開いてください。`spotter codex-hook diagnostics` は登録と readiness を診断しますが、trust を内部状態から推測しません。
|
|
80
80
|
|
|
81
|
+
Grok Buildがある環境では、`spotter install`はGrok native hookも登録し、専用の`.spotter/tool-db.grok.json`を初期化します。入力時と応答後の監査結果は`.spotter/hook-events.jsonl`と評価DBに残ります。Grok 1.0.41は受動hookのstdoutを会話へ渡さないため、findingは親会話には表示されません。登録は`spotter grok-hook diagnostics`で確認し、install後は新しいGrok sessionを開いてください。
|
|
82
|
+
|
|
81
83
|
Spotter を upgrade した後、release note で hook 設定変更が案内されている場合は、各 install 済みプロジェクトで `spotter install` を再実行してください。global package update でコード経路は変わりますが、既存 `.claude/settings.json` の timeout 値は自動では書き換わりません。
|
|
82
84
|
|
|
83
85
|
```bash
|
|
@@ -88,12 +90,20 @@ spotter uninstall # このプロジェクトの hook 登録を解除
|
|
|
88
90
|
|
|
89
91
|
```bash
|
|
90
92
|
npm uninstall -g claude-spotter
|
|
91
|
-
npm install -g claude-spotter
|
|
93
|
+
npm install -g claude-spotter@1.8.0
|
|
92
94
|
spotter --version
|
|
93
95
|
spotter install -y
|
|
94
|
-
spotter codex-hook install
|
|
95
96
|
```
|
|
96
97
|
|
|
98
|
+
公開担当は検証済みcommitを`main`へmergeし、`main`から
|
|
99
|
+
[Publish to npm](https://github.com/kitepon/Spotter/actions/workflows/publish.yml)へpackage versionを指定して実行します。
|
|
100
|
+
workflowは指定versionと`main`への着地を検査してから`npm publish`します。
|
|
101
|
+
初回だけ[npm packageのAccess設定](https://www.npmjs.com/package/claude-spotter/access)で
|
|
102
|
+
GitHub ActionsのTrusted Publisherを登録してください。ownerは`kitepon`、repositoryは`Spotter`、
|
|
103
|
+
workflow filenameは`publish.yml`、environmentは空欄、直接の`npm publish`を許可します。
|
|
104
|
+
GitHubが管理するrunnerのOIDCを使うため、以降の公開にnpm tokenの保存やCLIログインは要りません。
|
|
105
|
+
公開後はregistryのversionを確認し、対象端末へそのversionを指定してインストールします。
|
|
106
|
+
|
|
97
107
|
## 動作要件
|
|
98
108
|
|
|
99
109
|
- **Node.js 22.13 以上**(npmの`engines.node`と同じ)
|
|
@@ -245,17 +255,12 @@ spotter dashboard device --id mac --name Mac
|
|
|
245
255
|
# この端末の評価DBを127.0.0.1:53940で配信
|
|
246
256
|
spotter dashboard hub --config dashboard-hub.json --host 172.18.0.1
|
|
247
257
|
# 端末一覧と/devices/<id>/の端末別proxyを配信
|
|
248
|
-
spotter codex risk-check --findings findings.json --host-agent claude
|
|
249
|
-
# Spotter finding を codex-sidecar に渡して read-only risk analysis
|
|
250
|
-
spotter codex review|explore|opinion --findings findings.json --host-agent claude
|
|
251
|
-
# その他の read-only codex-sidecar second-pass workflow
|
|
252
|
-
spotter codex work --findings findings.json --instruction "docs 更新" --approve-work \
|
|
253
|
-
--allowed-path docs/ --preserve-worktree
|
|
254
|
-
# 承認済み codex-sidecar work を isolated worktree で実行
|
|
255
258
|
spotter codex-hook install
|
|
256
259
|
# Codex native hooks の修復 / 明示登録 (通常は spotter install が実行)
|
|
257
260
|
spotter codex-hook diagnostics
|
|
258
261
|
# Codex hook の登録/readiness を診断。trust は /hooks で review
|
|
262
|
+
spotter grok-hook diagnostics
|
|
263
|
+
# Grok native監査hookの登録を確認
|
|
259
264
|
spotter auditor model-matrix --fixtures test/fixtures/auditor-model-matrix.v2.json --recent-turns 2 --body-cap 600
|
|
260
265
|
# pinned auditor model profile を再現可能に比較する experimental eval
|
|
261
266
|
spotter uninstall # hook 登録を解除 (~/.spotter は残す)
|
|
@@ -278,21 +283,11 @@ project/tool内訳、非採用case、監査対象request、任意の提案時Thr
|
|
|
278
283
|
health確認は端末一覧request時だけなので、端末がofflineでもbackground監視や
|
|
279
284
|
retry queueを作らず、その端末だけを切り離せる。
|
|
280
285
|
|
|
281
|
-
|
|
286
|
+
3端末のservice、reverse tunnel、Caddy/Cloudflare構成は
|
|
282
287
|
[docs/11_dashboard-operations.md](https://github.com/kitepon/Spotter/blob/main/docs/11_dashboard-operations.md)を参照。
|
|
283
288
|
Windows同梱のTask Scheduler installerはnpm・SSH用の対話ユーザープロファイルを維持しつつ、
|
|
284
289
|
dashboardの2つのPowerShell actionを非対話・console非表示で起動する。
|
|
285
290
|
|
|
286
|
-
Codex risk dispatch を daemon から非同期に流す場合:
|
|
287
|
-
|
|
288
|
-
```bash
|
|
289
|
-
SPOTTER_CODEX_RISK_CHECK=1 spotter daemon start --session-id ... --project-root ...
|
|
290
|
-
```
|
|
291
|
-
|
|
292
|
-
有効時は daemon が `pass:false` finding を detached process の
|
|
293
|
-
`spotter codex risk-check` に渡します。hook 応答は Codex を待ちません。
|
|
294
|
-
配線だけ確認する場合は `SPOTTER_CODEX_RISK_CHECK_DRY_RUN=1` を併用します。
|
|
295
|
-
|
|
296
291
|
## 端末内runtime error集計
|
|
297
292
|
|
|
298
293
|
factory diagnosticsとruntime error集計は既定OFFです。canonicalなdotagents factory reporter設定で
|
|
@@ -320,7 +315,6 @@ Codex CLI auditor は versioned product policy を使い、production は反復
|
|
|
320
315
|
profile から production へ自動昇格しません。`latest` alias や
|
|
321
316
|
親 Codex の default を暗黙継承せず、失敗時に別 model へ retry しません。制御された実験では
|
|
322
317
|
`SPOTTER_CODEX_CLI_MODEL` / `SPOTTER_CODEX_CLI_REASONING_EFFORT` で上書きでき、diagnostics は unverified と表示します。
|
|
323
|
-
明示 smoke には `SPOTTER_AUDITOR_BACKEND=codex-sidecar` も使えます。
|
|
324
318
|
|
|
325
319
|
## 設計ドキュメント
|
|
326
320
|
|
|
@@ -344,7 +338,7 @@ profile から production へ自動昇格しません。`latest` alias や
|
|
|
344
338
|
- **失敗は声に出して縮退、hostを固めない** (v1.4.15) — この版でbackend failureによるpromptのsilent消去を止めた。v1.4.19以降もnon-blocking挙動は維持し、旧model可視警告文は固定`systemMessage`・stderr・構造event診断へ置換した
|
|
345
339
|
- **プラグイン形式の MCP サーバー対応** — `plugin:everything-claude-code:context7` のように名前に内部コロンを含むサーバーを正しくパースし、配下のツールをカタログに取り込めるようになった (旧版はこの形式のサーバーをすべて単一の `"plugin"` に潰して、Claude の監査から silent に脱落させていた)
|
|
346
340
|
- **プロジェクト単位の監査隔離** — daemon が監査に使うのはローカル DB のみ。グローバル DB は description 再利用キャッシュに役割限定。**他プロジェクト**でインストールしたツールが現プロジェクトの監査に混入することはない
|
|
347
|
-
- **手放しでカタログ維持** — `spotter install
|
|
341
|
+
- **手放しでカタログ維持** — `spotter install`が利用可能なhostのDBを作る。Claude / Codex / CursorはSessionStartでバックグラウンド更新し、Grokは初回監査前に更新完了を待つ
|
|
348
342
|
- **Codex native hooks** — Codex host は primary auditor backend として Codex CLI を使い、`.spotter/tool-db.codex.json` を Claude DB と分離し、backend failure は Haiku fallback ではなく明示 error として扱う
|
|
349
343
|
- **監査対象** — ユーザー追加分 (MCP / スキル / サブエージェント) のみ。Claude Code 本体側のツールは意図的に対象外 (Claude は元から自発率が高いため)
|
|
350
344
|
- **実装規範** — フォールバック禁止 / silent fallback 禁止 / 暫定コード禁止 ([AGENTS.md §0](https://github.com/kitepon/Spotter/blob/main/AGENTS.md))
|
package/README.md
CHANGED
|
@@ -18,7 +18,7 @@ Built and maintained by [Quo](https://x.com/QLyun35332) at [kitepon.dev](https:/
|
|
|
18
18
|
## Ownership boundary
|
|
19
19
|
|
|
20
20
|
This repository owns the complete Spotter product surface: auditor behavior,
|
|
21
|
-
Claude/Codex hook adapters, project markers, catalog discovery and host-local
|
|
21
|
+
Claude/Codex/Cursor/Grok hook adapters, project markers, catalog discovery and host-local
|
|
22
22
|
tool databases, evaluation storage, dashboard servers, diagnostics, installers,
|
|
23
23
|
and release packaging. [dotagents](https://github.com/kitepon/dotagents)
|
|
24
24
|
owns shared agent instructions and the optional factory-reporter configuration
|
|
@@ -69,16 +69,18 @@ cd your-project
|
|
|
69
69
|
spotter install
|
|
70
70
|
```
|
|
71
71
|
|
|
72
|
-
On macOS with Homebrew Node, Codex hook commands use the stable
|
|
72
|
+
On macOS with Homebrew Node, Codex and Grok hook commands use the stable
|
|
73
73
|
`/opt/homebrew/bin/node` symlink when it resolves to the current Node binary,
|
|
74
74
|
instead of a versioned `/opt/homebrew/Cellar/node/<version>/...` path. That keeps
|
|
75
|
-
|
|
75
|
+
both sets of hooks working across Homebrew Node upgrades.
|
|
76
76
|
|
|
77
77
|
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.
|
|
78
78
|
When the Codex CLI is available, the same `spotter install` also registers user-level Codex native hooks. Project activation still depends on the same per-project `.spotter/marker.json`, so unrelated Codex sessions do not trigger Spotter.
|
|
79
79
|
For Codex, install enables the current `[features].hooks = true` flag and still recognizes older `codex_hooks` diagnostics output for compatibility.
|
|
80
80
|
Installer-owned Codex handlers use the current synchronous command schema. After install or upgrade, review them with `/hooks`, then open a fresh Codex session; `spotter codex-hook diagnostics` reports registration/readiness but does not guess hook trust.
|
|
81
81
|
|
|
82
|
+
When Grok Build is installed, `spotter install` also registers native Grok hooks and seeds a separate `.spotter/tool-db.grok.json`. Grok prompt and final-response audits write findings to `.spotter/hook-events.jsonl` and the evaluation database. Grok 1.0.41 ignores stdout from passive hooks, so it does not show those findings in the parent conversation. Check registration with `spotter grok-hook diagnostics` and open a new Grok session after install.
|
|
83
|
+
|
|
82
84
|
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.
|
|
83
85
|
|
|
84
86
|
```bash
|
|
@@ -89,12 +91,20 @@ Release install smoke:
|
|
|
89
91
|
|
|
90
92
|
```bash
|
|
91
93
|
npm uninstall -g claude-spotter
|
|
92
|
-
npm install -g claude-spotter
|
|
94
|
+
npm install -g claude-spotter@1.8.0
|
|
93
95
|
spotter --version
|
|
94
96
|
spotter install -y
|
|
95
|
-
spotter codex-hook install
|
|
96
97
|
```
|
|
97
98
|
|
|
99
|
+
Maintainer release: merge the tested release commit into `main`, then run
|
|
100
|
+
[Publish to npm](https://github.com/kitepon/Spotter/actions/workflows/publish.yml) from `main` with the package version.
|
|
101
|
+
The workflow checks the requested version and the `main` ancestry gate before `npm publish`.
|
|
102
|
+
For the one-time npm setup, open the [package access settings](https://www.npmjs.com/package/claude-spotter/access)
|
|
103
|
+
and add a GitHub Actions trusted publisher: owner `kitepon`, repository `Spotter`,
|
|
104
|
+
workflow filename `publish.yml`, no environment, and allow direct `npm publish`.
|
|
105
|
+
The GitHub-hosted workflow uses OIDC, so later releases need no stored npm token or CLI login.
|
|
106
|
+
After publication, verify the registry version and install that exact version on each target host.
|
|
107
|
+
|
|
98
108
|
## Requirements
|
|
99
109
|
|
|
100
110
|
- **Node.js 22.13+**
|
|
@@ -249,17 +259,12 @@ spotter dashboard device --id mac --name Mac
|
|
|
249
259
|
# serve this terminal's local evaluation DB on 127.0.0.1:53940
|
|
250
260
|
spotter dashboard hub --config dashboard-hub.json --host 172.18.0.1
|
|
251
261
|
# list terminals and proxy /devices/<id>/ to their local servers
|
|
252
|
-
spotter codex risk-check --findings findings.json --host-agent claude
|
|
253
|
-
# run read-only codex-sidecar risk analysis for Spotter findings
|
|
254
|
-
spotter codex review|explore|opinion --findings findings.json --host-agent claude
|
|
255
|
-
# run other read-only codex-sidecar second-pass workflows
|
|
256
|
-
spotter codex work --findings findings.json --instruction "Update docs" --approve-work \
|
|
257
|
-
--allowed-path docs/ --preserve-worktree
|
|
258
|
-
# run approved codex-sidecar work in an isolated worktree
|
|
259
262
|
spotter codex-hook install
|
|
260
263
|
# repair / explicitly register Codex native hooks (normally handled by spotter install)
|
|
261
264
|
spotter codex-hook diagnostics
|
|
262
265
|
# check Codex hook registration/readiness; trust is reviewed with /hooks
|
|
266
|
+
spotter grok-hook diagnostics
|
|
267
|
+
# check Grok native audit hook registration
|
|
263
268
|
spotter auditor model-matrix --fixtures test/fixtures/auditor-model-matrix.v2.json --recent-turns 2 --body-cap 600
|
|
264
269
|
# experimental reproducible comparison of pinned auditor model profiles
|
|
265
270
|
spotter uninstall # remove hooks from this project (leaves ~/.spotter intact)
|
|
@@ -285,21 +290,11 @@ audited by Spotter, and optional proposal-time Throughline evidence. The hub che
|
|
|
285
290
|
when the device list is requested, so an offline terminal is isolated without a background monitor
|
|
286
291
|
or retry queue.
|
|
287
292
|
|
|
288
|
-
The reference
|
|
293
|
+
The reference three-terminal service, reverse-tunnel, and Caddy/Cloudflare layout is documented in
|
|
289
294
|
[docs/11_dashboard-operations.md](https://github.com/kitepon/Spotter/blob/main/docs/11_dashboard-operations.md).
|
|
290
295
|
On Windows, the bundled Task Scheduler installer keeps the interactive user's profile for npm and
|
|
291
296
|
SSH while starting both dashboard PowerShell actions non-interactively with hidden console windows.
|
|
292
297
|
|
|
293
|
-
Optional async Codex risk dispatch:
|
|
294
|
-
|
|
295
|
-
```bash
|
|
296
|
-
SPOTTER_CODEX_RISK_CHECK=1 spotter daemon start --session-id ... --project-root ...
|
|
297
|
-
```
|
|
298
|
-
|
|
299
|
-
When enabled, the daemon dispatches `pass:false` findings to `spotter codex risk-check`
|
|
300
|
-
in a detached process. Hook responses do not wait for Codex. Add
|
|
301
|
-
`SPOTTER_CODEX_RISK_CHECK_DRY_RUN=1` to exercise the wiring without calling Codex.
|
|
302
|
-
|
|
303
298
|
Primary auditor backend policy: Claude hooks automatically select Codex CLI when it is available on PATH,
|
|
304
299
|
otherwise the Haiku-compatible path. Codex native hooks automatically select Codex CLI. An explicit
|
|
305
300
|
`SPOTTER_AUDITOR_BACKEND` override wins on either host; runtime failure never triggers a hidden fallback.
|
|
@@ -343,14 +338,13 @@ Codex CLI auditor child processes use a versioned product policy. The production
|
|
|
343
338
|
Spotter does not inherit a `latest` alias or the parent Codex default, and an invocation failure never retries another model.
|
|
344
339
|
`SPOTTER_CODEX_CLI_MODEL` and `SPOTTER_CODEX_CLI_REASONING_EFFORT` can override
|
|
345
340
|
the production values for controlled experiments; diagnostics mark overrides as unverified.
|
|
346
|
-
`SPOTTER_AUDITOR_BACKEND=codex-sidecar` is available for explicit sidecar auditor smoke.
|
|
347
341
|
|
|
348
342
|
## Design docs
|
|
349
343
|
|
|
350
344
|
- **Current design** (catalog, discovery, classification axes): [docs/01_catalog-design.md](https://github.com/kitepon/Spotter/blob/main/docs/01_catalog-design.md) — source of truth from v1.0.0
|
|
351
345
|
- **Open issues + unverified concerns**: [docs/open-issues.md](https://github.com/kitepon/Spotter/blob/main/docs/open-issues.md) — read this before starting new work
|
|
352
346
|
- **Runtime contract**: [docs/02_spotter-claude-contract.md](https://github.com/kitepon/Spotter/blob/main/docs/02_spotter-claude-contract.md) — Claude hook / daemon / Haiku contract plus Codex native hook policy
|
|
353
|
-
- **Implementation invariants (§0)**: [AGENTS.md](https://github.com/kitepon/Spotter/blob/main/AGENTS.md) — no fallbacks, no silent failures, no provisional code
|
|
347
|
+
- **Implementation invariants (§0)**: [AGENTS.md](https://github.com/kitepon/Spotter/blob/main/AGENTS.md) — no fallbacks, no silent failures, no provisional code
|
|
354
348
|
- **Archived plans and history**: [docs/archive/](https://github.com/kitepon/Spotter/tree/main/docs/archive) — completed Codex rollout plans, primary backend smoke logs, and the frozen v0.1 design discussion
|
|
355
349
|
|
|
356
350
|
## Known limitations
|
|
@@ -367,7 +361,7 @@ the production values for controlled experiments; diagnostics mark overrides as
|
|
|
367
361
|
- **Failures degrade loudly, never freeze the host** (v1.4.15) — this release stopped backend failure from silently erasing a prompt. Since v1.4.19, the non-blocking behavior remains but the old model-visible warning text is replaced by fixed `systemMessage`, stderr, and structured event diagnostics
|
|
368
362
|
- **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 Claude's audit
|
|
369
363
|
- **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
|
|
370
|
-
- **Zero-touch catalog** — `spotter install` seeds
|
|
364
|
+
- **Zero-touch catalog** — `spotter install` seeds each available host's DB. Claude, Codex, and Cursor refresh in the background; Grok waits for refresh before its first audit
|
|
371
365
|
- **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
|
|
372
366
|
- **Audit scope** — only user-added surface (MCP servers / skills / sub-agents). Claude Code's built-in tools are intentionally out of scope; Claude already uses those reliably
|
|
373
367
|
- **Implementation invariants** — no fallbacks, no silent failures, no provisional code (see [§0 in AGENTS.md](https://github.com/kitepon/Spotter/blob/main/AGENTS.md))
|
package/bin/spotter.mjs
CHANGED
|
@@ -7,9 +7,9 @@ import { runUninstall } from '../src/cli/uninstall.mjs';
|
|
|
7
7
|
import { runDoctor } from '../src/cli/doctor.mjs';
|
|
8
8
|
import { runStatus } from '../src/cli/status.mjs';
|
|
9
9
|
import { runDbList, runDbRefresh, runDbRebuild } from '../src/cli/db-cmd.mjs';
|
|
10
|
-
import { runCodexCommand } from '../src/cli/codex-cmd.mjs';
|
|
11
10
|
import { runCodexHookCommand } from '../src/cli/codex-hook-cmd.mjs';
|
|
12
11
|
import { runCursorHookCommand } from '../src/cli/cursor-hook-cmd.mjs';
|
|
12
|
+
import { runGrokHookCommand } from '../src/cli/grok-hook-cmd.mjs';
|
|
13
13
|
import { runAuditorCommand } from '../src/cli/auditor-cmd.mjs';
|
|
14
14
|
import { runDiagnosticsCommand } from '../src/cli/diagnostics-cmd.mjs';
|
|
15
15
|
import { runEvaluationCommand } from '../src/cli/evaluation-cmd.mjs';
|
|
@@ -62,16 +62,12 @@ Usage:
|
|
|
62
62
|
spotter dashboard device --id ID [--name NAME] [--host HOST] [--port PORT] [--db PATH]
|
|
63
63
|
spotter dashboard hub --config FILE [--host HOST] [--port PORT]
|
|
64
64
|
serve the local device-routed evaluation dashboard
|
|
65
|
-
spotter codex risk-check --findings FILE
|
|
66
|
-
run read-only codex-sidecar risk analysis
|
|
67
|
-
spotter codex review|explore|opinion --findings FILE
|
|
68
|
-
run read-only codex-sidecar second-pass workflows
|
|
69
|
-
spotter codex work --findings FILE --approve-work --allowed-path PATH
|
|
70
|
-
run approved codex-sidecar worktree workflow
|
|
71
65
|
spotter codex-hook install|uninstall|diagnostics
|
|
72
66
|
(experimental) manage Codex native hooks
|
|
73
67
|
spotter cursor-hook install|uninstall|diagnostics
|
|
74
68
|
manage Cursor native catalog-refresh hooks
|
|
69
|
+
spotter grok-hook install|uninstall|diagnostics
|
|
70
|
+
manage Grok native audit hooks
|
|
75
71
|
spotter auditor judge --stage STAGE --input FILE
|
|
76
72
|
(experimental) run primary auditor backend once
|
|
77
73
|
spotter auditor matrix --stage STAGE --input FILE
|
|
@@ -128,15 +124,15 @@ async function main() {
|
|
|
128
124
|
case 'doctor':
|
|
129
125
|
await runDoctor();
|
|
130
126
|
return;
|
|
131
|
-
case 'codex':
|
|
132
|
-
await runCodexCommand({ argv: rest });
|
|
133
|
-
return;
|
|
134
127
|
case 'codex-hook':
|
|
135
128
|
await runCodexHookCommand({ argv: rest });
|
|
136
129
|
return;
|
|
137
130
|
case 'cursor-hook':
|
|
138
131
|
await runCursorHookCommand({ argv: rest });
|
|
139
132
|
return;
|
|
133
|
+
case 'grok-hook':
|
|
134
|
+
await runGrokHookCommand({ argv: rest });
|
|
135
|
+
return;
|
|
140
136
|
case 'auditor':
|
|
141
137
|
await runAuditorCommand({ argv: rest });
|
|
142
138
|
return;
|
|
@@ -5,9 +5,8 @@
|
|
|
5
5
|
|
|
6
6
|
## 固定構成
|
|
7
7
|
|
|
8
|
-
各端末のdevice serverはloopbackだけで待ち受ける。main-server
|
|
9
|
-
`127.0.0.1:53940`、FOX Windows nativeは
|
|
10
|
-
`127.0.0.1:53944`を使う。main-serverのhubは
|
|
8
|
+
各端末のdevice serverはloopbackだけで待ち受ける。main-serverとMacは
|
|
9
|
+
`127.0.0.1:53940`、FOX Windows nativeは`127.0.0.1:53944`を使う。main-serverのhubは
|
|
11
10
|
Docker Caddyから到達できる`172.18.0.1:53940`で待ち受ける。評価DBは各端末の
|
|
12
11
|
`~/.spotter/evaluation.db`をその場で読み、端末外へ複製しない。
|
|
13
12
|
|
|
@@ -15,7 +14,6 @@ Docker Caddyから到達できる`172.18.0.1:53940`で待ち受ける。評価DB
|
|
|
15
14
|
|---|---|---|
|
|
16
15
|
| main-server Ubuntu | `main-server` | `127.0.0.1:53940` |
|
|
17
16
|
| Mac | `mac` | `127.0.0.1:53941` |
|
|
18
|
-
| FOX WSL2 | `fox-wsl` | `127.0.0.1:53942` |
|
|
19
17
|
| FOX Windows native | `fox-windows` | `127.0.0.1:53943` |
|
|
20
18
|
|
|
21
19
|
hub設定の正本は`ops/dashboard/hub-config.json`である。hubは一覧request時に各upstreamの
|
|
@@ -60,27 +58,6 @@ curl --fail http://172.18.0.1:53940/
|
|
|
60
58
|
|
|
61
59
|
device envにも同じPATH行を置く。値は各端末で実測したnpm binを使い、別の起動経路へfallbackしない。
|
|
62
60
|
|
|
63
|
-
## FOX WSL2
|
|
64
|
-
|
|
65
|
-
device unitとtunnel unitを`~/.config/systemd/user/`へ配置する。device env:
|
|
66
|
-
|
|
67
|
-
```ini
|
|
68
|
-
SPOTTER_DEVICE_ID=fox-wsl
|
|
69
|
-
SPOTTER_DEVICE_NAME=FOX-WSL2
|
|
70
|
-
```
|
|
71
|
-
|
|
72
|
-
tunnel env:
|
|
73
|
-
|
|
74
|
-
```ini
|
|
75
|
-
SPOTTER_REMOTE_FORWARD=127.0.0.1:53942:127.0.0.1:53940
|
|
76
|
-
SPOTTER_TUNNEL_TARGET=main-server
|
|
77
|
-
```
|
|
78
|
-
|
|
79
|
-
```sh
|
|
80
|
-
systemctl --user daemon-reload
|
|
81
|
-
systemctl --user enable --now spotter-dashboard-device.service spotter-dashboard-tunnel.service
|
|
82
|
-
```
|
|
83
|
-
|
|
84
61
|
## FOX Windows native
|
|
85
62
|
|
|
86
63
|
同梱された`ops/dashboard/windows/`のPowerShellを固定pathへ配置する。npm global版から
|
|
@@ -163,6 +140,6 @@ reverse tunnelを確認する。hubや別端末を再起動する必要はない
|
|
|
163
140
|
公開受入:
|
|
164
141
|
|
|
165
142
|
1. 未認証`https://spotter.kitepon.dev/`がCloudflare Accessへredirectされる。
|
|
166
|
-
2. 認証後の`/`が
|
|
143
|
+
2. 認証後の`/`が3端末を表示する。
|
|
167
144
|
3. online端末のoverview、project/tool内訳、非採用case、case詳細を表示できる。
|
|
168
145
|
4. 1端末を停止しても一覧と他端末が表示でき、停止端末だけoffline/502になる。
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"devices":[{"id":"main-server","name":"main-server","upstream":"http://127.0.0.1:53940"},{"id":"mac","name":"Mac","upstream":"http://127.0.0.1:53941"},{"id":"fox-
|
|
1
|
+
{"devices":[{"id":"main-server","name":"main-server","upstream":"http://127.0.0.1:53940"},{"id":"mac","name":"Mac","upstream":"http://127.0.0.1:53941"},{"id":"fox-windows","name":"FOX Windows native","upstream":"http://127.0.0.1:53943"}]}
|
package/package.json
CHANGED
package/src/cli/auditor-cmd.mjs
CHANGED
|
@@ -10,7 +10,7 @@ const AUDITOR_USAGE = `spotter auditor — experimental primary auditor smoke co
|
|
|
10
10
|
Usage:
|
|
11
11
|
spotter auditor judge --stage user_input|turn_end --input FILE
|
|
12
12
|
[--project DIR] [--host-agent claude|codex|automation|unknown]
|
|
13
|
-
[--backend jev|haiku|codex-cli|
|
|
13
|
+
[--backend jev|haiku|codex-cli|auto]
|
|
14
14
|
spotter auditor matrix --stage user_input|turn_end --input FILE [--project DIR]
|
|
15
15
|
spotter auditor model-matrix --fixtures FILE [--profile baseline|luna|terra|terra-medium]...
|
|
16
16
|
[--repeat N] [--project DIR] [--output FILE]
|
|
@@ -134,9 +134,7 @@ export async function runAuditorMatrixCommand({
|
|
|
134
134
|
|
|
135
135
|
const AUDITOR_MATRIX_ROWS = Object.freeze([
|
|
136
136
|
Object.freeze({ id: 'claude.codex-cli', hostAgent: 'claude', backend: 'codex-cli' }),
|
|
137
|
-
Object.freeze({ id: 'claude.codex-sidecar', hostAgent: 'claude', backend: 'codex-sidecar' }),
|
|
138
137
|
Object.freeze({ id: 'codex.codex-cli', hostAgent: 'codex', backend: 'codex-cli' }),
|
|
139
|
-
Object.freeze({ id: 'codex.codex-sidecar', hostAgent: 'codex', backend: 'codex-sidecar' }),
|
|
140
138
|
]);
|
|
141
139
|
|
|
142
140
|
async function runAuditorMatrixRow({
|
|
@@ -207,15 +205,11 @@ function summarizeMatrix(matrix) {
|
|
|
207
205
|
total: matrix.length,
|
|
208
206
|
success: matrix.filter((row) => row.status === 'success').length,
|
|
209
207
|
error: matrix.filter((row) => row.status === 'error').length,
|
|
210
|
-
sidecarPrimaryAuditorImplemented: matrix
|
|
211
|
-
.filter((row) => row.backend === 'codex-sidecar')
|
|
212
|
-
.some((row) => row.status === 'success'),
|
|
213
208
|
};
|
|
214
209
|
}
|
|
215
210
|
|
|
216
211
|
function recursionSafetyFor(backend) {
|
|
217
212
|
if (backend === 'codex-cli') return 'spotter_parent_pid_backend_env';
|
|
218
|
-
if (backend === 'codex-sidecar') return 'spotter_parent_pid_sidecar_env';
|
|
219
213
|
return 'unknown';
|
|
220
214
|
}
|
|
221
215
|
|
package/src/cli/db-cmd.mjs
CHANGED
|
@@ -14,9 +14,9 @@ import { writeFile } from 'node:fs/promises';
|
|
|
14
14
|
const DB_USAGE = `spotter db — manage the host-specific tool-db
|
|
15
15
|
|
|
16
16
|
Usage:
|
|
17
|
-
spotter db list [--host-agent claude|codex|automation|cursor]
|
|
18
|
-
spotter db refresh [--host-agent claude|codex|automation|cursor]
|
|
19
|
-
spotter db rebuild [--host-agent claude|codex|automation|cursor]
|
|
17
|
+
spotter db list [--host-agent claude|codex|automation|cursor|grok]
|
|
18
|
+
spotter db refresh [--host-agent claude|codex|automation|cursor|grok]
|
|
19
|
+
spotter db rebuild [--host-agent claude|codex|automation|cursor|grok]
|
|
20
20
|
`;
|
|
21
21
|
|
|
22
22
|
function requireProjectRoot() {
|
package/src/cli/doctor.mjs
CHANGED
|
@@ -9,6 +9,7 @@ import { resolveJevApiKey, JEV_MODEL } from '../core/jev-backend.mjs';
|
|
|
9
9
|
import { loadDb, globalDbPath, localDbPath } from '../tool-db/loader.mjs';
|
|
10
10
|
import { findSpotterMarker } from '../hooks/lib.mjs';
|
|
11
11
|
import { codexHookDiagnostics } from './codex-hook-cmd.mjs';
|
|
12
|
+
import { grokHookDiagnostics, isGrokHomePresent } from './grok-hook-cmd.mjs';
|
|
12
13
|
import { buildWindowsCompatibleInvocation, execFileWindowsSafe } from '../platform/spawn.mjs';
|
|
13
14
|
|
|
14
15
|
const execFileP = promisify(execFile);
|
|
@@ -75,11 +76,18 @@ export async function runDoctor() {
|
|
|
75
76
|
warnings += 1;
|
|
76
77
|
}
|
|
77
78
|
|
|
78
|
-
if (
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
79
|
+
if (isGrokHomePresent()) {
|
|
80
|
+
try {
|
|
81
|
+
const grokHooks = await grokHookDiagnostics();
|
|
82
|
+
mark(grokHooks.installed, `grok native hooks: ${grokHooks.installed ? 'installed' : 'not installed'}`);
|
|
83
|
+
if (!grokHooks.installed) warnings += 1;
|
|
84
|
+
} catch (err) {
|
|
85
|
+
mark(false, 'grok native hooks', err.message);
|
|
86
|
+
warnings += 1;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
82
89
|
|
|
90
|
+
if (projectRoot) {
|
|
83
91
|
const auditorContext = await inspectAuditorContextConfiguration({ projectRoot });
|
|
84
92
|
mark(auditorContext.ok, `evaluation context: ${auditorContext.mode}`, auditorContext.detail);
|
|
85
93
|
if (!auditorContext.ok) warnings += 1;
|
|
@@ -87,7 +95,7 @@ export async function runDoctor() {
|
|
|
87
95
|
|
|
88
96
|
// tool-db (host-specific global caches). Since v1.2.0 these are not part of
|
|
89
97
|
// audit input; each host audits its project-local DB only. Empty caches are fine.
|
|
90
|
-
for (const hostAgent of ['claude', 'codex']) {
|
|
98
|
+
for (const hostAgent of ['claude', 'codex', ...(isGrokHomePresent() ? ['grok'] : [])]) {
|
|
91
99
|
try {
|
|
92
100
|
const path = globalDbPath(hostAgent);
|
|
93
101
|
const global = await loadDb(path);
|
|
@@ -109,6 +117,12 @@ export async function runDoctor() {
|
|
|
109
117
|
const codexDb = await checkLocalAuditDb({ projectRoot, hostAgent: 'codex' });
|
|
110
118
|
mark(codexDb.ok, `codex local audit DB: ${codexDb.count} tools at ${codexDb.path}`, codexDb.detail);
|
|
111
119
|
if (!codexDb.ok) warnings += 1;
|
|
120
|
+
|
|
121
|
+
if (isGrokHomePresent()) {
|
|
122
|
+
const grokDb = await checkLocalAuditDb({ projectRoot, hostAgent: 'grok' });
|
|
123
|
+
mark(grokDb.ok, `grok local audit DB: ${grokDb.count} tools at ${grokDb.path}`, grokDb.detail);
|
|
124
|
+
if (!grokDb.ok) warnings += 1;
|
|
125
|
+
}
|
|
112
126
|
}
|
|
113
127
|
|
|
114
128
|
console.log('');
|
|
@@ -232,42 +246,6 @@ async function checkLocalAuditDb({ projectRoot, hostAgent }) {
|
|
|
232
246
|
}
|
|
233
247
|
}
|
|
234
248
|
|
|
235
|
-
async function codexSidecarAuditorReadiness(projectRoot) {
|
|
236
|
-
const args = ['diagnostics', '--project', projectRoot, '--preset', 'auditor', '--json'];
|
|
237
|
-
const cliPath = process.env.SPOTTER_CODEX_SIDECAR_CLI_PATH;
|
|
238
|
-
const cmd = cliPath ? process.execPath : 'codex-sidecar';
|
|
239
|
-
const finalArgs = cliPath ? [cliPath, ...args] : args;
|
|
240
|
-
try {
|
|
241
|
-
const invocation = buildWindowsCompatibleInvocation({
|
|
242
|
-
command: cmd,
|
|
243
|
-
args: finalArgs,
|
|
244
|
-
env: process.env,
|
|
245
|
-
allowCmdFallback: false,
|
|
246
|
-
});
|
|
247
|
-
const { stdout } = await execFileP(invocation.command, invocation.args, {
|
|
248
|
-
timeout: 15_000,
|
|
249
|
-
windowsHide: true,
|
|
250
|
-
maxBuffer: 1024 * 1024,
|
|
251
|
-
});
|
|
252
|
-
const parsed = JSON.parse(stdout);
|
|
253
|
-
const ok = parsed?.status === 'ok' && parsed?.normalizedRequest?.workflow === 'auditor';
|
|
254
|
-
return {
|
|
255
|
-
ok,
|
|
256
|
-
status: ok ? 'available' : 'unavailable',
|
|
257
|
-
detail: ok
|
|
258
|
-
? `workflow=${parsed.normalizedRequest.workflow}, reasoning=${parsed.normalizedRequest.modelReasoningEffort ?? 'default'}`
|
|
259
|
-
: `unexpected diagnostics: status=${parsed?.status ?? 'unknown'}`,
|
|
260
|
-
};
|
|
261
|
-
} catch (err) {
|
|
262
|
-
const stderr = typeof err?.stderr === 'string' && err.stderr.trim() ? ` stderr=${err.stderr.trim().split('\n').slice(-1)[0]}` : '';
|
|
263
|
-
return {
|
|
264
|
-
ok: false,
|
|
265
|
-
status: 'unavailable',
|
|
266
|
-
detail: `${err.message}${stderr}`,
|
|
267
|
-
};
|
|
268
|
-
}
|
|
269
|
-
}
|
|
270
|
-
|
|
271
249
|
async function exists(path) {
|
|
272
250
|
try { await access(path); return true; }
|
|
273
251
|
catch { return false; }
|