claude-spotter 1.5.7 → 1.5.8

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 CHANGED
@@ -1,5 +1,25 @@
1
1
  # Changelog
2
2
 
3
+ 各節はそのversion公開時点の変更記録であり、後続versionにより置換された仕様を含む。
4
+ 現行runtime契約は[`docs/00_overview.md`](docs/00_overview.md)から辿る。
5
+
6
+ ## 1.5.8 — 2026-08-05
7
+
8
+ - **コードから全ドキュメントを再照合。** 47 Markdownを現行contract、ADR、完了計画、
9
+ evidence、外部仕様snapshotへ分類し、現行文書を`bin/spotter.mjs`、`src/`、`test/`、
10
+ `package.json`、`ops/`と照合した。
11
+ - **実装との不一致を修正。** repository ownership、tool-dbの実schema、Node 22.13 engine、
12
+ CLI option、再帰guard 3環境変数、runtime-error storeのSQLite mutex、exact-session
13
+ `auditor-context`、削除済みHook formatterへのRAG pointerを現行コードへ一致させた。
14
+ - **履歴との境界を明示。** `CHANGELOG`、archive、evidence、日付付きRAGは時点記録であり、
15
+ 現行仕様に読み替えない。dashboardの4端末rolloutと各端末の現在install versionも分離した。
16
+ - **文書driftをrelease前に止める。** package version、Node engine表記、正典入口、主要現行文書の
17
+ release version、repository-local Markdown linkを`npm run verify:docs`で検証し、prepublish gateへ追加した。
18
+ - **診断とhelpも同じ契約へ統一。** `spotter doctor`のNode合格境界をnpm enginesと同じ22.13へ直し、
19
+ CLI helpに既存のfactory diagnostics、evaluation filter、model-matrix optionを完全表示する。
20
+ - **release gate逸脱を記録。** v1.5.7 prompt matrixのp95 15.432秒 / 11.687秒は
21
+ 10秒gate未達であり、合格扱いしない。次のprompt変更releaseの未完事項として残した。
22
+
3
23
  ## 1.5.7 — 2026-08-05
4
24
 
5
25
  - **標準ツール先行で比較する。** Claude Haiku / Codex CLI / Codex sidecarのauditorは、
@@ -13,7 +33,7 @@
13
33
  呼び出し元と影響範囲の調査は`lattice_sensor_callers` / `lattice_sensor_impact`を提案した。
14
34
  - **判定品質。** prompt version 3を`terra-medium` / fixture 9件 / repeat 3で2回実行し、
15
35
  合計54/54 exact、false positive / false negative / timeoutはすべて0。p95は15.432秒と11.687秒で、
16
- 実運用SLO7日窓判定とは分けて単発matrixの変動値として記録する。
36
+ release gate10秒以下は未達。v1.5.8でrelease process逸脱として明記した。
17
37
 
18
38
  ## 1.5.6 — 2026-08-05
19
39
 
@@ -1420,7 +1440,7 @@ Haiku 突然死 (shutdown ログなしで daemon 再起動する事象、v0.12.0
1420
1440
  - **編集 [src/hooks/session-start.mjs](src/hooks/session-start.mjs)**: spawn ロジックを spawn-daemon.mjs に委譲、`--parent-pid` 渡し削除
1421
1441
  - **編集 [src/hooks/user-prompt.mjs](src/hooks/user-prompt.mjs)**: `sendRequest` が `E_UNREACHABLE` で失敗したら `spawnDaemonAndWaitReady` を呼んで retry (1 回のみ)
1422
1442
  - **削除 [src/hooks/ppid-probe.mjs]**: env dump 用の調査 hook、役目終了
1423
- - **編集 [.claude/settings.json](.claude/settings.json)**: probe hook 登録撤去
1443
+ - **編集 `.claude/settings.json`**: probe hook 登録撤去(端末ローカル設定であり、repository 配布物には含めない)
1424
1444
  - **編集 [test/daemon.test.mjs](test/daemon.test.mjs)**: parent-watch test 2 件を削除、heartbeat timeout / heartbeat reset / heartbeatTimeoutMs validation の 3 件を追加
1425
1445
 
1426
1446
  ### 非互換
package/README.ja.md CHANGED
@@ -18,14 +18,16 @@
18
18
 
19
19
  ## 所有境界
20
20
 
21
- 本repositoryは監査挙動、project markerinstaller、release、diagnosticsを所有します。
22
- 製品横断のcatalogとhost統合は、kitepon.devの製品開発を支える内部基盤
23
- [dotagents](https://github.com/kitepon-rgb/dotagents)が担当します。
24
- MarkItDownは別区分の第三者CLIです。
21
+ 本repositoryはSpotter製品面の全体、すなわち監査挙動、Claude/Codex hook adapter
22
+ project marker、catalog discoveryとhost-local tool DB、評価store、dashboard server、
23
+ diagnostics、installer、release packagingを所有します。
24
+ [dotagents](https://github.com/kitepon-rgb/dotagents)が所有するのは共有agent指示と、
25
+ Spotterの端末内runtime-error集計を有効化する任意のfactory-reporter設定です。
26
+ Spotterのcatalogやhost統合はdotagentsの責務ではありません。MarkItDownは別区分の第三者CLIです。
25
27
 
26
28
  Claude には「使えるツールがあるのに、使うべきタイミングで使わない」という構造的な弱点があります。記録すべき決定を memory / caveat MCP に残さない、docs lookup MCP を呼ばずに古い知識で応答する、ブラウザ自動化 MCP で確認せず UI 状態を推測する — **「分からないと自覚できない」から、ツールを取りに行けない**。
27
29
 
28
- Spotter はツールカタログを完全に把握した別の監査エージェントで、ユーザー入力と主役 AI の応答を並走監査します。自動選択では Claude host は Codex CLI があればそれを、なければ session-scoped Haiku を選び、Codex host は Codex CLI を既定にします。明示 backend override は host より優先しますが、runtime failure で別 backend へ黙って切り替えません。応答前は検証済みtool IDだけを固定・非命令形の助言へ変換でき、応答後のfindingは構造eventに留めて後続turnへ注入しません。監査用AIの自由文が親セッションへ入ることはありません。**主役 AI が自覚して自己監査する**設計は本プロダクトの存在意義を破壊するため、hook 経由でその意思と独立に検出します。
30
+ Spotter はユーザー追加ツールのhost-local catalogを把握した別の監査エージェントで、ユーザー入力と主役 AI の応答を並走監査します。host標準ツールは提案候補に入れず、追加ツールと比較する先行基準としてだけ判断します。自動選択では Claude host は Codex CLI があればそれを、なければ session-scoped Haiku を選び、Codex host は Codex CLI を既定にします。明示 backend override は host より優先しますが、runtime failure で別 backend へ黙って切り替えません。応答前は検証済みtool IDだけを固定・非命令形の助言へ変換でき、応答後のfindingは構造eventに留めて後続turnへ注入しません。監査用AIの自由文が親セッションへ入ることはありません。**主役 AI が自覚して自己監査する**設計は本プロダクトの存在意義を破壊するため、hook 経由でその意思と独立に検出します。
29
31
 
30
32
  <p align="center">
31
33
  <img src=".github/concept.svg" alt="Claude が答え、Spotter が見ている" width="80%">
@@ -77,7 +79,6 @@ Codex 側では現行の `[features].hooks = true` を有効化し、互換の
77
79
  Spotter が所有する Codex handler は現行の同期 command schema で生成します。install / upgrade 後は `/hooks` で review して新しい Codex session を開いてください。`spotter codex-hook diagnostics` は登録と readiness を診断しますが、trust を内部状態から推測しません。
78
80
 
79
81
  Spotter を upgrade した後、release note で hook 設定変更が案内されている場合は、各 install 済みプロジェクトで `spotter install` を再実行してください。global package update でコード経路は変わりますが、既存 `.claude/settings.json` の timeout 値は自動では書き換わりません。
80
- `v1.4.19`はruntimeの出力変換だけを変更するため、install済みprojectで`spotter install`をやり直す必要はありません。global packageを更新し、新しいClaude/Codexセッションを開いてください。
81
82
 
82
83
  ```bash
83
84
  spotter uninstall # このプロジェクトの hook 登録を解除
@@ -95,13 +96,20 @@ spotter codex-hook install
95
96
 
96
97
  ## 動作要件
97
98
 
98
- - **Node.js 22.5 以上**
99
+ - **Node.js 22.13 以上**(npmの`engines.node`と同じ)
99
100
  - **Claude Code 2.0 以上**
100
101
  - **Codex CLI**。Codex native hooks の既定 backend と Claude host の優先 auditor path で使います。自動選択後の runtime failure で Haiku へ fallback しません
101
102
  - **Claude Max プラン**は Claude host が Haiku path を選ぶ場合だけ必要です(Codex CLI 不在、または `SPOTTER_AUDITOR_BACKEND=haiku` 明示時)
102
103
 
103
104
  ## アーキテクチャ
104
105
 
106
+ 実際の挙動の権威はコードです。保守対象の現行契約は
107
+ [`docs/00_overview.md`](docs/00_overview.md)、
108
+ [`docs/01_catalog-design.md`](docs/01_catalog-design.md)、
109
+ [`docs/02_spotter-claude-contract.md`](docs/02_spotter-claude-contract.md)です。
110
+ `CHANGELOG.md`、`docs/archive/`、`docs/evidence/`、日付付き`rag/`は時点記録であり、
111
+ 現行runtime契約として読んではいけません。
112
+
105
113
  ### 1 ターンの監査フロー
106
114
 
107
115
  Claude Code と Codex は同じ安全なparent-output projectorを使います。監査用AIの自由文は内部に留め、
@@ -145,7 +153,7 @@ flowchart LR
145
153
  DB --> H[独立 auditor<br/>Codex CLI があれば優先<br/>なければ session-scoped Haiku]
146
154
  ```
147
155
 
148
- 監査対象のツール (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 のツールリストで上書きされることはありません。
156
+ 監査対象のツール (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 / projectの現時点のdiscovery結果と一致**します(refresh時に不在項目をprune)。存在中のツールでdescription取得だけが一時失敗した場合は、監査範囲を縮めず最後の有効なlocal descriptionを保持します。
149
157
 
150
158
  **`spotter install` が Claude catalog の初回 seed を自動実行し、Claude Code セッション起動ごとに SessionStart hook が bg で `spotter db refresh` を走らせる**ため、Claude 通常運用で手動コマンドを叩く必要はありません。Codex CLI が使える環境では、同じ `spotter install` が Codex native hooks も登録し、`.spotter/tool-db.codex.json` も同期 seed します。これにより初回 Codex セッションから catalog を読めます。以降の 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` に該当サーバーが存在する環境で注入されます。**手書きでツールリストを管理する必要はありません**。
151
159
 
@@ -263,6 +271,23 @@ SPOTTER_CODEX_RISK_CHECK=1 spotter daemon start --session-id ... --project-root
263
271
  `spotter codex risk-check` に渡します。hook 応答は Codex を待ちません。
264
272
  配線だけ確認する場合は `SPOTTER_CODEX_RISK_CHECK_DRY_RUN=1` を併用します。
265
273
 
274
+ ## 端末内runtime error集計
275
+
276
+ factory diagnosticsとruntime error集計は既定OFFです。canonicalなdotagents factory reporter設定で
277
+ JSON booleanの`collection.enabled: true`が明示された場合だけ、固定codeの失敗を端末内へ集計します。
278
+ Spotterはreporting credentialもnetwork送信経路も持ちません。保存APIは固定templateとallow-list済み集計だけを受け付け、
279
+ 例外本文、stdout/stderr、stack、prompt、hook payload、finding、ファイル内容、絶対pathを保存しません。
280
+
281
+ daemonとCodex hookの収集境界は、bounded timeout付きのkill可能なchild process groupで実行します。
282
+ POSIXでは各accessで現在uidと`0600` file / `0700` directoryを再検証し、mutationはprivate SQLiteの
283
+ `BEGIN IMMEDIATE` mutexで直列化します。process crash時はOSがlockを解放し、PID/mtimeによるstale-owner
284
+ reclaimはありません。Windowsでは各accessで現在process SIDだけにFullControlを与えるDACLへ再構築し、
285
+ readbackを検証します。
286
+
287
+ `spotter diagnostics runtime-errors`はread-only snapshotを返し、`ack`、`resolve`、`reopen`、`compact`が
288
+ 受理後のlifecycle操作です。`spotter diagnostics logs`と`spotter diagnostics factory`はboundedな件数と
289
+ statusだけを返し、store/config pathやrecord本文を出しません。
290
+
266
291
  Primary auditor backend policy: Claude hooks の auto selection は PATH に Codex CLI があれば Codex CLI、
267
292
  なければ Haiku compatibility path。Codex native hooks の auto selection は Codex CLI です。
268
293
  `SPOTTER_AUDITOR_BACKEND` の明示 override はどちらの host でも優先し、runtime failure では別 backend へ
@@ -280,7 +305,7 @@ profile から production へ自動昇格しません。`latest` alias や
280
305
  - **現行設計 (カタログ / 収集経路 / 分類軸)**: [docs/01_catalog-design.md](docs/01_catalog-design.md) — v1.0.0 以降の真実源
281
306
  - **現時点で塞がっていない穴 + 実測未検証の懸念**: [docs/open-issues.md](docs/open-issues.md) — 新規作業に入る前に必読
282
307
  - **Runtime contract**: [docs/02_spotter-claude-contract.md](docs/02_spotter-claude-contract.md) — Claude hook / daemon / Haiku 契約と Codex native hook policy
283
- - **実装規範と不変条件 (§0)**: [CLAUDE.md](CLAUDE.md) — フォールバック禁止 / silent fallback 禁止 / 暫定コード禁止
308
+ - **実装規範と不変条件 (§0)**: [AGENTS.md](AGENTS.md) — フォールバック禁止 / silent fallback 禁止 / 暫定コード禁止(`CLAUDE.md`はimport入口のみ)
284
309
  - **Archive**: [docs/archive/](docs/archive/) — 完了済み Codex rollout 計画、primary backend smoke log、v0.1 設計議事録
285
310
 
286
311
  ## 既知の制約
@@ -300,7 +325,7 @@ profile から production へ自動昇格しません。`latest` alias や
300
325
  - **手放しでカタログ維持** — `spotter install` が Claude DB を自動 seed、Claude / Codex それぞれの SessionStart が host-local DB を bg refresh する。手書き管理は一切不要
301
326
  - **Codex native hooks** — Codex host は primary auditor backend として Codex CLI を使い、`.spotter/tool-db.codex.json` を Claude DB と分離し、backend failure は Haiku fallback ではなく明示 error として扱う
302
327
  - **監査対象** — ユーザー追加分 (MCP / スキル / サブエージェント) のみ。Claude Code 本体側のツールは意図的に対象外 (Claude は元から自発率が高いため)
303
- - **実装規範** — フォールバック禁止 / silent fallback 禁止 / 暫定コード禁止 ([CLAUDE.md §0](CLAUDE.md))
328
+ - **実装規範** — フォールバック禁止 / silent fallback 禁止 / 暫定コード禁止 ([AGENTS.md §0](AGENTS.md))
304
329
 
305
330
  リリース履歴の全文は [CHANGELOG](CHANGELOG.md) を参照。
306
331
 
package/README.md CHANGED
@@ -17,15 +17,17 @@ Built and maintained by [Quo](https://x.com/QLyun35332) at [kitepon.dev](https:/
17
17
 
18
18
  ## Ownership boundary
19
19
 
20
- This repository owns auditor behavior, project markers, installers, release,
21
- and diagnostics. The cross-product catalog and host integration are handled by
22
- [dotagents](https://github.com/kitepon-rgb/dotagents), the internal development
23
- toolchain behind kitepon.dev's products.
24
- MarkItDown is managed separately as a third-party CLI.
20
+ This repository owns the complete Spotter product surface: auditor behavior,
21
+ Claude/Codex hook adapters, project markers, catalog discovery and host-local
22
+ tool databases, evaluation storage, dashboard servers, diagnostics, installers,
23
+ and release packaging. [dotagents](https://github.com/kitepon-rgb/dotagents)
24
+ owns shared agent instructions and the optional factory-reporter configuration
25
+ that enables Spotter's local runtime-error aggregate; it does not own Spotter's
26
+ catalog or host integration. MarkItDown is a separate third-party CLI.
25
27
 
26
28
  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.
27
29
 
28
- Spotter runs a separate auditor with the full tool catalog and checks both the user's prompt and the primary agent's reply. Automatic selection uses Codex CLI on a Claude host when available, otherwise the session-scoped Haiku path; on a Codex host it defaults to Codex CLI. An explicit backend override takes precedence, but a runtime failure never silently switches backend. Before the primary reply, validated tool IDs may become fixed, non-directive advice; after the reply, findings remain structured events and are not injected into a later turn. Auditor prose never enters the parent session. **The primary agent is never asked to self-audit** — that would defeat the premise. Detection happens through hooks, independent of the primary agent's intent.
30
+ Spotter runs a separate auditor with the host-local catalog of user-added tools and checks both the user's prompt and the primary agent's reply. Host built-ins are not proposal candidates; the auditor considers them first only as the comparison baseline. Automatic selection uses Codex CLI on a Claude host when available, otherwise the session-scoped Haiku path; on a Codex host it defaults to Codex CLI. An explicit backend override takes precedence, but a runtime failure never silently switches backend. Before the primary reply, validated tool IDs may become fixed, non-directive advice; after the reply, findings remain structured events and are not injected into a later turn. Auditor prose never enters the parent session. **The primary agent is never asked to self-audit** — that would defeat the premise. Detection happens through hooks, independent of the primary agent's intent.
29
31
 
30
32
  <p align="center">
31
33
  <img src=".github/concept.svg" alt="Claude answers · Spotter watches" width="80%">
@@ -78,7 +80,6 @@ For Codex, install enables the current `[features].hooks = true` flag and still
78
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.
79
81
 
80
82
  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.
81
- `v1.4.19` changes runtime output projection only, so already installed projects do not need another `spotter install`; update the global package and open a fresh Claude/Codex session.
82
83
 
83
84
  ```bash
84
85
  spotter uninstall # remove hooks from this project
@@ -103,6 +104,13 @@ spotter codex-hook install
103
104
 
104
105
  ## Architecture
105
106
 
107
+ The code is the behavioral authority. The maintained contract documents are
108
+ [`docs/00_overview.md`](docs/00_overview.md),
109
+ [`docs/01_catalog-design.md`](docs/01_catalog-design.md), and
110
+ [`docs/02_spotter-claude-contract.md`](docs/02_spotter-claude-contract.md).
111
+ `CHANGELOG.md`, `docs/archive/`, `docs/evidence/`, and dated `rag/` entries are
112
+ point-in-time records and must not be used as the current runtime contract.
113
+
106
114
  ### Audit flow per turn
107
115
 
108
116
  Claude Code and Codex share the same safe parent-output projector. Auditor prose stays
@@ -146,7 +154,7 @@ flowchart LR
146
154
  DB --> H[Independent auditor<br/>Codex CLI when available<br/>otherwise session-scoped Haiku]
147
155
  ```
148
156
 
149
- 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.
157
+ 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 membership** for the project (stale entries are pruned on refresh). If description lookup fails transiently for a still-present tool, the last valid local description is retained instead of shrinking the audit set.
150
158
 
151
159
  **`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 and seeds `.spotter/tool-db.codex.json` synchronously, so the first Codex session has a catalog too. Later Codex `SessionStart` hooks start `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.**
152
160
 
@@ -200,7 +208,7 @@ spotter install -y --auditor-context throughline `
200
208
  ```
201
209
 
202
210
  `spotter doctor` reports this as `evaluation context` without printing commands,
203
- arguments, or conversation text. Observer snapshots stay in the terminal-local
211
+ arguments, or conversation text. Evaluation-context snapshots stay in the terminal-local
204
212
  evaluation SQLite. Spotter adds no network upload, retry, or background recovery.
205
213
 
206
214
  ## Common commands
@@ -219,6 +227,8 @@ spotter db rebuild # wipe Claude local + Claude global DBs and refresh fro
219
227
  spotter status # list running daemons
220
228
  spotter doctor # environment check (Node / claude CLI / Codex readiness / tool-db integrity)
221
229
  spotter diagnostics logs # summarize daemon logs for pass=false / backend latency / anomaly signals
230
+ spotter diagnostics factory
231
+ # emit a fixed-field read-only factory diagnostic as JSON
222
232
  spotter diagnostics runtime-errors
223
233
  # print the local allow-listed runtime-error aggregate snapshot (no network)
224
234
  spotter evaluation report
@@ -320,7 +330,7 @@ the production values for controlled experiments; diagnostics mark overrides as
320
330
  - **Current design** (catalog, discovery, classification axes): [docs/01_catalog-design.md](docs/01_catalog-design.md) — source of truth from v1.0.0
321
331
  - **Open issues + unverified concerns**: [docs/open-issues.md](docs/open-issues.md) — read this before starting new work
322
332
  - **Runtime contract**: [docs/02_spotter-claude-contract.md](docs/02_spotter-claude-contract.md) — Claude hook / daemon / Haiku contract plus Codex native hook policy
323
- - **Implementation invariants (§0)**: [CLAUDE.md](CLAUDE.md) — no fallbacks, no silent failures, no provisional code
333
+ - **Implementation invariants (§0)**: [AGENTS.md](AGENTS.md) — no fallbacks, no silent failures, no provisional code (`CLAUDE.md` is only its import entry)
324
334
  - **Archived plans and history**: [docs/archive/](docs/archive/) — completed Codex rollout plans, primary backend smoke logs, and the frozen v0.1 design discussion
325
335
 
326
336
  ## Known limitations
@@ -340,7 +350,7 @@ the production values for controlled experiments; diagnostics mark overrides as
340
350
  - **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
341
351
  - **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
342
352
  - **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
343
- - **Implementation invariants** — no fallbacks, no silent failures, no provisional code (see [§0 in CLAUDE.md](CLAUDE.md))
353
+ - **Implementation invariants** — no fallbacks, no silent failures, no provisional code (see [§0 in AGENTS.md](AGENTS.md))
344
354
 
345
355
  Full release history: [CHANGELOG](CHANGELOG.md).
346
356
 
package/bin/spotter.mjs CHANGED
@@ -44,11 +44,15 @@ Usage:
44
44
  wipe host-local + global DBs then refresh
45
45
  spotter status show running daemons
46
46
  spotter doctor environment diagnostic
47
- spotter diagnostics logs [--json] summarize daemon logs for precision diagnostics
47
+ spotter diagnostics logs [--log-dir DIR] [--project DIR] [--json]
48
+ summarize daemon and project hook-event logs
49
+ spotter diagnostics factory emit a fixed-field read-only JSON diagnostic
48
50
  spotter diagnostics runtime-errors [snapshot|ack|resolve|reopen|compact]
49
51
  consume the local allow-listed aggregate store
50
- spotter evaluation report [filters] [--json]
51
- spotter evaluation cases --outcome OUTCOME [filters] [--json]
52
+ spotter evaluation report [--project PATH] [--from ISO] [--to ISO] [--host HOST]
53
+ [--tool-id ID] [--backend NAME] [--model NAME]
54
+ [--spotter-version VERSION] [--json]
55
+ spotter evaluation cases --outcome OUTCOME [same filters] [--json]
52
56
  spotter evaluation case OBSERVATION_ID [--json]
53
57
  read saved proposal-adoption observations
54
58
  spotter dashboard device --id ID [--name NAME] [--host HOST] [--port PORT] [--db PATH]
@@ -66,7 +70,9 @@ Usage:
66
70
  (experimental) run primary auditor backend once
67
71
  spotter auditor matrix --stage STAGE --input FILE
68
72
  (experimental) compare primary auditor backend matrix
69
- spotter auditor model-matrix --fixtures FILE
73
+ spotter auditor model-matrix --fixtures FILE [--profile PROFILE] [--repeat N]
74
+ [--recent-turns 0|1|2|3] [--body-cap CHARS]
75
+ [--project DIR] [--output FILE]
70
76
  (experimental) evaluate pinned Codex auditor profiles
71
77
  spotter daemon start --session-id ID (internal) run session daemon
72
78
  spotter hook <event> (internal) hook dispatch
@@ -1,8 +1,11 @@
1
1
  # Spotter評価dashboard運用
2
2
 
3
- 現行npm配布版: **v1.5.7**(2026-08-05)。v1.5.7はauditorの提案判定promptの変更であり、
3
+ 現行npm配布版: **v1.5.8**(2026-08-05)。v1.5.8は文書整合releaseであり、
4
4
  dashboard routing構成はv1.5.3から変更していない。
5
5
 
6
+ この文書はservice設定の正本であり、各端末に現在installされているnpm versionの台帳ではない。
7
+ 端末versionは対象端末で`spotter --version`を実行して確認する。
8
+
6
9
  ## 固定構成
7
10
 
8
11
  各端末のdevice serverはloopbackだけで待ち受ける。main-server、Mac、FOX WSL2は
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-spotter",
3
- "version": "1.5.7",
3
+ "version": "1.5.8",
4
4
  "description": "Audit agent running alongside Claude Code that catches missed tool calls — 気づく役と実行する役の分離",
5
5
  "type": "module",
6
6
  "bin": {
@@ -11,8 +11,9 @@
11
11
  },
12
12
  "scripts": {
13
13
  "test": "node --test",
14
+ "verify:docs": "node scripts/verify-docs.mjs",
14
15
  "verify:release-commit": "node scripts/verify-release-commit.mjs",
15
- "prepublishOnly": "npm run verify:release-commit && npm test",
16
+ "prepublishOnly": "npm run verify:docs && npm run verify:release-commit && npm test",
16
17
  "postinstall": "node scripts/postinstall.mjs",
17
18
  "preuninstall": "node scripts/preuninstall.mjs"
18
19
  },
@@ -0,0 +1,97 @@
1
+ import { access, readFile, readdir } from 'node:fs/promises';
2
+ import { dirname, join, relative, resolve, sep } from 'node:path';
3
+ import { fileURLToPath } from 'node:url';
4
+
5
+ const root = resolve(dirname(fileURLToPath(import.meta.url)), '..');
6
+ const failures = [];
7
+ const packageJson = JSON.parse(await readFile(join(root, 'package.json'), 'utf8'));
8
+ const version = packageJson.version;
9
+
10
+ await requireText('CLAUDE.md', '@AGENTS.md\n', { exact: true });
11
+ await requireText('README.md', '**Node.js 22.13+**');
12
+ await requireText('README.ja.md', '**Node.js 22.13 以上**');
13
+ await requireText('docs/00_overview.md', `Current production release: **v${version}**`);
14
+ await requireText('docs/open-issues.md', `Spotter v${version}`);
15
+ await requireText('docs/10_spotter-dashboard-plan.md', `claude-spotter@${version}`);
16
+ await requireText('docs/11_dashboard-operations.md', `**v${version}**`);
17
+ await requireText('AGENTS.md', `> **v${version}`);
18
+ await requireText('CHANGELOG.md', `## ${version} —`);
19
+
20
+ if (packageJson.engines?.node !== '>=22.13.0') {
21
+ failures.push(`package.json: engines.node must remain >=22.13.0 (actual: ${packageJson.engines?.node ?? 'missing'})`);
22
+ }
23
+
24
+ const markdownFiles = await listMarkdown(root);
25
+ let checkedLinks = 0;
26
+ for (const file of markdownFiles) {
27
+ const repoPath = relative(root, file).split(sep).join('/');
28
+ if (repoPath.includes('/raw/')) continue;
29
+ const lines = (await readFile(file, 'utf8')).split('\n');
30
+ let inFence = false;
31
+ for (let index = 0; index < lines.length; index += 1) {
32
+ const line = lines[index];
33
+ if (/^\s*(?:```|~~~)/.test(line)) {
34
+ inFence = !inFence;
35
+ continue;
36
+ }
37
+ if (inFence) continue;
38
+ const withoutCode = line.replace(/`[^`]*`/g, '');
39
+ for (const match of withoutCode.matchAll(/\[[^\]]*\]\(([^)]+)\)/g)) {
40
+ const target = normalizeLinkTarget(match[1]);
41
+ if (!target) continue;
42
+ checkedLinks += 1;
43
+ const localPath = resolve(dirname(file), target);
44
+ try {
45
+ await access(localPath);
46
+ } catch {
47
+ failures.push(`${repoPath}:${index + 1}: missing local link target ${target}`);
48
+ }
49
+ }
50
+ }
51
+ }
52
+
53
+ if (failures.length > 0) {
54
+ process.stderr.write(`${failures.join('\n')}\n`);
55
+ process.exit(1);
56
+ }
57
+
58
+ process.stdout.write(`documentation verification: ok (${markdownFiles.length} Markdown files, ${checkedLinks} local links)\n`);
59
+
60
+ async function requireText(repoPath, expected, { exact = false } = {}) {
61
+ const content = await readFile(join(root, repoPath), 'utf8');
62
+ const valid = exact
63
+ ? content.replaceAll('\r\n', '\n') === expected.replaceAll('\r\n', '\n')
64
+ : content.includes(expected);
65
+ if (!valid) failures.push(`${repoPath}: missing canonical text ${JSON.stringify(expected)}`);
66
+ }
67
+
68
+ async function listMarkdown(directory) {
69
+ const out = [];
70
+ for (const entry of await readdir(directory, { withFileTypes: true })) {
71
+ if (entry.name === '.git' || entry.name === 'node_modules' || entry.name === '.spotter') continue;
72
+ const path = join(directory, entry.name);
73
+ if (entry.isDirectory()) out.push(...await listMarkdown(path));
74
+ else if (entry.isFile() && entry.name.endsWith('.md')) out.push(path);
75
+ }
76
+ return out;
77
+ }
78
+
79
+ function normalizeLinkTarget(raw) {
80
+ let target = raw.trim();
81
+ if (target.startsWith('<') && target.endsWith('>')) target = target.slice(1, -1);
82
+ target = target.split(/\s+["']/u, 1)[0];
83
+ if (
84
+ target === '...' ||
85
+ target.startsWith('#') ||
86
+ target.startsWith('/') ||
87
+ /^(?:https?:|mailto:|file:)/u.test(target)
88
+ ) return null;
89
+ target = target.split('#', 1)[0];
90
+ if (!target) return null;
91
+ try {
92
+ return decodeURIComponent(target);
93
+ } catch {
94
+ failures.push(`invalid percent-encoding in Markdown link: ${target}`);
95
+ return null;
96
+ }
97
+ }
@@ -0,0 +1,13 @@
1
+ import { test } from 'node:test';
2
+ import assert from 'node:assert/strict';
3
+ import { execFile } from 'node:child_process';
4
+ import { promisify } from 'node:util';
5
+
6
+ const execFileAsync = promisify(execFile);
7
+
8
+ test('maintained document versions and repository-local links stay consistent', async () => {
9
+ const { stdout } = await execFileAsync(process.execPath, ['scripts/verify-docs.mjs'], {
10
+ cwd: process.cwd(),
11
+ });
12
+ assert.match(stdout, /^documentation verification: ok \(/);
13
+ });
@@ -19,10 +19,8 @@ export async function runDoctor() {
19
19
 
20
20
  // Node version
21
21
  const nodeVersion = process.versions.node;
22
- const major = parseInt(nodeVersion.split('.')[0], 10);
23
- const minor = parseInt(nodeVersion.split('.')[1], 10);
24
- const okNode = major > 22 || (major === 22 && minor >= 5);
25
- mark(okNode, `Node.js ${nodeVersion}`, 'need >= 22.5');
22
+ const okNode = isSupportedNodeVersion(nodeVersion);
23
+ mark(okNode, `Node.js ${nodeVersion}`, 'need >= 22.13');
26
24
  if (!okNode) failures += 1;
27
25
 
28
26
  // claude CLI — on Windows the entry is `claude.cmd`; route through cmd.exe /c
@@ -116,6 +114,12 @@ export async function runDoctor() {
116
114
  console.log(`result: OK (${warnings} warnings)`);
117
115
  }
118
116
 
117
+ export function isSupportedNodeVersion(value) {
118
+ if (typeof value !== 'string' || !/^\d+\.\d+(?:\.\d+)?(?:[-+].*)?$/.test(value)) return false;
119
+ const [major, minor] = value.split('.').map(Number);
120
+ return major > 22 || (major === 22 && minor >= 13);
121
+ }
122
+
119
123
  export async function inspectCodexCliVersion({
120
124
  codexBin = 'codex',
121
125
  platform = process.platform,