claude-spotter 1.6.1 → 1.6.4

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,7 +1,52 @@
1
1
  # Changelog
2
2
 
3
3
  各節はそのversion公開時点の変更記録であり、後続versionにより置換された仕様を含む。
4
- 現行runtime契約は[`docs/00_overview.md`](docs/00_overview.md)から辿る。
4
+ 現行runtime契約は[`docs/00_overview.md`](https://github.com/kitepon/Spotter/blob/main/docs/00_overview.md)から辿る。
5
+
6
+ ## 1.6.4 — 2026-09-12
7
+
8
+ - Codex MCPの実行設定を`mcp get --json`から取得する。表示用の伏字でPATHや認証envを
9
+ 上書きし、正常なMCPを起動できなかった問題を修理した。
10
+ - 公開前のMarkdown検査で、npm 12のpackage名をキーとするpack JSONを受理する。
11
+ 従来の単一配列も保持し、不正な形式は検査失敗とする。
12
+ - Windowsの公開前検査は製品共通のnpm起動経路を使い、`.cmd`を直接起動した際の
13
+ `EINVAL`を解消する。
14
+ - Windowsの記録保存とprocess識別をPowerShell 7へ統一し、権限設定には現行の
15
+ `Set-Acl`/`Get-Acl`を使う。所有者限定の権限と読戻し検査は維持する。
16
+ - 評価DBの同時初期化でWAL切替が衝突した際、SQLiteがbusy handlerを呼ばず返す
17
+ `SQLITE_BUSY`を既存の待機予算内で扱う。期限切れや別のエラーは明示失敗とする。
18
+
19
+ ## 1.6.3 — 2026-08-30
20
+
21
+ - **factory adapterの互換判定をSpotter自身へ集約する。** `spotter diagnostics factory`の
22
+ schema 1.1は`compatibility_status`を返し、Codex hookのtrustが機械検証不能な正常状態を
23
+ `compatible`として扱う。既知の設定破損は`incompatible`、検査不能は`indeterminate`へ分離し、
24
+ 外部consumerが`checks`、catalog、reason codeを再解釈しなくてよい契約にした。互換または対象外は
25
+ exit 0、非互換または判定不能はexit 1、引数違反はexit 2とする。
26
+ - **Native Linux workstation の factory runtime-error 収集を受理する。** `linux` profileを
27
+ canonical reporter configへ追加し、`server` profileと混同せず明示opt-in収集を有効にする。
28
+ - **工場CIのLinuxを役割別に分離する。** 廃止した`wsl2`と曖昧な`linux-native`を除き、
29
+ `linux-server`と`linux-workstation`を独立したself-hosted runner契約として扱う。
30
+ - **文書の寿命と所有境界を製品内で完結させた。** 現行契約、進行中の仕事、履歴、証拠を
31
+ `docs/00_overview.md`で分離し、完了済み計画は`docs/archive/`へ移した。固定参照が残る
32
+ 旧pathだけは履歴参照stubとして維持する。
33
+ - **文書だけの変更も製品CIで検査する。** 全製品Markdownの相対link、現行・archive索引、
34
+ 履歴stub、npm tarball内Markdownの相対link/image閉包を製品所有のgateで検査する。
35
+ - **Windows nativeの製品CIをPowerShell 7へ統一した。** Git Bash依存を撤去し、3つの
36
+ Windows commandを`pwsh`で実行する。
37
+ - npm tarballに同梱されない文書や画像へのREADME/CHANGELOG/dashboard運用文書の参照を、
38
+ 製品repositoryの正規URLへ揃えた。runtime挙動と公開APIは変更しない。
39
+
40
+ ## 1.6.2 — 2026-08-29
41
+
42
+ - **Windowsの`spotter install -y`がMCP調査後に終了する。** 調査対象のprocess treeを
43
+ Windows共通経路で停止し、stdin / stdout / stderrのpipeを停止前後に破棄する。
44
+ カタログ生成後もstdin pipeがNodeのイベントループを保持し、工場セットアップが
45
+ 完了しなかった問題を修正した。
46
+ - **隔離runtime error workerが指定期限内に呼び出し元へ戻る。** timeout時は結果を先に
47
+ 確定し、子process treeのbest-effort掃除を並行して続ける。Windowsで掃除の待機時間が
48
+ 絶対期限へ上乗せされていた問題を修正した。
49
+ - Cursor hookの安定Node path試験を、空白を含むWindows pathの正しい引用形式へ対応させた。
5
50
 
6
51
  ## 1.6.1 — 2026-08-24
7
52
 
@@ -453,10 +498,10 @@ graceful shutdown ログなしの異常死 → 18:43–19:14 の 5 回 restart
453
498
  - **編集 [src/daemon/daemon.mjs](src/daemon/daemon.mjs)**: `startDaemon` が `assertNoLiveDaemon`
454
499
  (no-live 確認) 通過後・`server.listen(path)` 前に `removeStaleSocketFile(path)` を呼ぶ。liveness 確認後
455
500
  なので socket は確実に orphan であり安全に消せる。
456
- - **テスト 3 件追加 [test/transport.test.mjs](test/transport.test.mjs)**: (1) stale socket で `listen` が
501
+ - **テスト 3 件追加 [test/transport.test.mjs](https://github.com/kitepon/Spotter/blob/main/test/transport.test.mjs)**: (1) stale socket で `listen` が
457
502
  `EADDRINUSE` で落ちる挙動を実再現 → `removeStaleSocketFile` 後に fresh daemon が bind & round-trip 成功、
458
503
  (2) ENOENT は throw せず no-op、(3) Windows Named Pipe path は no-op (CI Windows matrix で実行)。
459
- - **追記 [docs/open-issues.md](docs/open-issues.md)**: 解決済みテーブルに本バグを記録 + P0「daemon 突然死」
504
+ - **追記 [docs/open-issues.md](https://github.com/kitepon/Spotter/blob/main/docs/open-issues.md)**: 解決済みテーブルに本バグを記録 + P0「daemon 突然死」
460
505
  節に回復経路修正の相互参照を追加。
461
506
  - **付随**: `package-lock.json` の version が 1.4.14 のまま drift していたのを 1.4.16 に同期。
462
507
  - `node --test` 348 / 346 pass / 0 fail / 2 skip 緑。
@@ -496,12 +541,12 @@ resurrect で確実に復活する」ことを保証する。これで auto-resu
496
541
  - **編集 [src/hooks/pre-tool-use.mjs](src/hooks/pre-tool-use.mjs)**: daemon/transport エラーで
497
542
  `die(exit 2 = ツール拒否)` をやめ、`status:"degraded"` 記録 + exit 0 (ツール許可)。記録は best-effort
498
543
  telemetry でありツールを止める理由にならない。
499
- - **更新 [docs/02_spotter-claude-contract.md](docs/02_spotter-claude-contract.md)**: `UserPromptSubmit` /
544
+ - **更新 [docs/02_spotter-claude-contract.md](https://github.com/kitepon/Spotter/blob/main/docs/02_spotter-claude-contract.md)**: `UserPromptSubmit` /
500
545
  `PreToolUse` / `Stop` の失敗時 exit-code 契約を新挙動に追従。
501
- - **追記 [docs/open-issues.md](docs/open-issues.md)**: auth-freeze バグの解決を記録。`Stop` 失敗が
546
+ - **追記 [docs/open-issues.md](https://github.com/kitepon/Spotter/blob/main/docs/open-issues.md)**: auth-freeze バグの解決を記録。`Stop` 失敗が
502
547
  セッション最終ターンだと deferred-delivery の性質上サイレントになる残課題を P2 に追記。
503
- - **テスト 11 件追加** ([test/hooks.test.mjs](test/hooks.test.mjs) /
504
- [test/codex-cli-backend.test.mjs](test/codex-cli-backend.test.mjs)): auth 分類 / `formatSpotterWarning` /
548
+ - **テスト 11 件追加** ([test/hooks.test.mjs](https://github.com/kitepon/Spotter/blob/main/test/hooks.test.mjs) /
549
+ [test/codex-cli-backend.test.mjs](https://github.com/kitepon/Spotter/blob/main/test/codex-cli-backend.test.mjs)): auth 分類 / `formatSpotterWarning` /
505
550
  UserPromptSubmit の loud degrade (auth/汎用/pending merge/resurrect 失敗/非 Error throw) / Stop degrade /
506
551
  PreToolUse degrade。`node --test` 344 pass / 1 skip 緑。
507
552
 
@@ -524,9 +569,9 @@ resurrect で確実に復活する」ことを保証する。これで auto-resu
524
569
  - **編集 [README.md](README.md) / [README.ja.md](README.ja.md)**:
525
570
  "Bell" を文脈に応じて `Claude` / `your primary Claude` / `the primary Claude` に置換、
526
571
  `(Bell)` 括弧書きは削除。日本語版の `主体 (Bell) に` は `主体に` に整形。
527
- - **編集 [.github/og.svg](.github/og.svg) と再生成された [.github/og.png](.github/og.png)**:
572
+ - **編集 [.github/og.svg](https://raw.githubusercontent.com/kitepon/Spotter/main/.github/og.svg) と再生成された [.github/og.png](https://raw.githubusercontent.com/kitepon/Spotter/main/.github/og.png)**:
528
573
  OG banner の bullet text 2 件を Claude 表記に。`svgexport` で 1280×640 PNG を再レンダリング。
529
- - **編集 [.github/concept.svg](.github/concept.svg)**:
574
+ - **編集 [.github/concept.svg](https://raw.githubusercontent.com/kitepon/Spotter/main/.github/concept.svg)**:
530
575
  内部 HTML コメント `Bell side` を `Primary Claude side` に。
531
576
 
532
577
  ### 検証
@@ -552,7 +597,7 @@ hook parity は自動的に維持される。
552
597
  - **編集 [src/hooks/lib.mjs](src/hooks/lib.mjs)**:
553
598
  `formatTransparentContext` / `formatTransparentBlockReason` から末尾の空行 +
554
599
  念押し行を削除。コメントを「header 自体が出典明示を担う」旨に書き換え。
555
- - **編集 [test/hooks.test.mjs](test/hooks.test.mjs)**:
600
+ - **編集 [test/hooks.test.mjs](https://github.com/kitepon/Spotter/blob/main/test/hooks.test.mjs)**:
556
601
  逐語アサート 2 件を本体に追従。
557
602
 
558
603
  ### 検証
@@ -638,9 +683,9 @@ silent retry することはない。codex-sidecar は `spotter codex *` の明
638
683
  - **編集 [src/cli/auditor-cmd.mjs](src/cli/auditor-cmd.mjs)**:
639
684
  `parseJudgeArgs` の backend デフォルトを `'auto'` に変更 (旧: `SPOTTER_AUDITOR_BACKEND_POLICY`
640
685
  が無いと `'haiku'` 固定だった)。
641
- - **新規 [test/codex-cli-availability.test.mjs](test/codex-cli-availability.test.mjs)**:
686
+ - **新規 [test/codex-cli-availability.test.mjs](https://github.com/kitepon/Spotter/blob/main/test/codex-cli-availability.test.mjs)**:
642
687
  POSIX / Windows / 空 PATH / malformed PATH / `path.posix` vs `path.win32` の 7 件回帰ガード。
643
- - **編集 [test/auditor-backend.test.mjs](test/auditor-backend.test.mjs)**:
688
+ - **編集 [test/auditor-backend.test.mjs](https://github.com/kitepon/Spotter/blob/main/test/auditor-backend.test.mjs)**:
644
689
  旧 `policy_current_*` / `policy_next_*` テストを availability-based テスト
645
690
  (`claude_host_codex_cli_detected` / `claude_host_codex_cli_unavailable` / `codex_host`) に置換、
646
691
  legacy policy 値の受理 + selection 無効化テスト、`createAuditorBackend` の logger 出力テストを追加。
@@ -664,7 +709,7 @@ hook 機能を `hooks stable true` と表示するが、Spotter の `codex-hook
664
709
  `codexHookDiagnostics` が現行 `hooks` と旧 `codex_hooks` の両方を enabled evidence として扱う。
665
710
  `installCodexHooks` は現行 CLI に合わせて `[features].hooks = true` を書く。既に旧
666
711
  `codex_hooks = true` がある環境では削除せず、`hooks = true` を追加して現行 CLI で確実に有効化する。
667
- - **編集 [test/codex-hook-cmd.test.mjs](test/codex-hook-cmd.test.mjs)**:
712
+ - **編集 [test/codex-hook-cmd.test.mjs](https://github.com/kitepon/Spotter/blob/main/test/codex-hook-cmd.test.mjs)**:
668
713
  現行 `hooks stable true` と旧 `codex_hooks stable true` の diagnostics 回帰テスト、
669
714
  旧 feature key が残る config への install 回帰テストを追加。
670
715
  - **編集 docs**:
@@ -779,15 +824,15 @@ v1.4.6 までは `SPOTTER_AUDITOR_BACKEND_POLICY=next` を Claude host で立て
779
824
  timeout / schema invalid / non-zero exit の場合、`createCodexCliAuditorBackend` が
780
825
  既存通り `AuditorBackendError` を投げ、daemon は Haiku に hidden fallback せず
781
826
  structured error として hook に伝搬する。
782
- - **編集 [test/auditor-backend.test.mjs](test/auditor-backend.test.mjs)**:
827
+ - **編集 [test/auditor-backend.test.mjs](https://github.com/kitepon/Spotter/blob/main/test/auditor-backend.test.mjs)**:
783
828
  Phase 1 用の "held for phase5" 固定を Phase 5 後の挙動 (Claude+`next` →
784
829
  `policy_next_claude_codex_cli`) に置き換え、`current` policy が両 host で Haiku を維持する
785
830
  test、Claude+`next` で `SPOTTER_AUDITOR_BACKEND=haiku` 明示が依然として Haiku を選ぶ
786
831
  互換 test、`createAuditorBackend` factory が `auto` + Claude + `next` で Codex CLI backend を
787
832
  返す factory-level test を追加。
788
- - **編集 [docs/02_spotter-claude-contract.md](docs/02_spotter-claude-contract.md)** /
789
- [docs/archive/SPOTTER_PRIMARY_BACKEND_TODO.md](docs/archive/SPOTTER_PRIMARY_BACKEND_TODO.md) /
790
- [docs/open-issues.md](docs/open-issues.md):
833
+ - **編集 [docs/02_spotter-claude-contract.md](https://github.com/kitepon/Spotter/blob/main/docs/02_spotter-claude-contract.md)** /
834
+ [docs/archive/SPOTTER_PRIMARY_BACKEND_TODO.md](https://github.com/kitepon/Spotter/blob/main/docs/archive/SPOTTER_PRIMARY_BACKEND_TODO.md) /
835
+ [docs/open-issues.md](https://github.com/kitepon/Spotter/blob/main/docs/open-issues.md):
791
836
  Claude host の `current` / `next` policy 表と Phase 5 ゲート、Haiku compatibility が
792
837
  `current` policy または `SPOTTER_AUDITOR_BACKEND=haiku` 明示時のみであること、hidden
793
838
  fallback 不可を明記。
@@ -832,7 +877,7 @@ spawn される。
832
877
  `~/.spotter/tool-db.codex.json` を作るようにした。以降の Codex `SessionStart` bg refresh は
833
878
  drift 追従用として残す。Codex CLI が見つからなかった場合の next steps も、Codex hooks が
834
879
  active ではないことと `codex --version` が通る環境で再実行すべきことを明示する。
835
- - **編集 [test/install.test.mjs](test/install.test.mjs)**:
880
+ - **編集 [test/install.test.mjs](https://github.com/kitepon/Spotter/blob/main/test/install.test.mjs)**:
836
881
  Codex hooks 登録時に Claude / Codex の両 host DB refresh が順に走ること、Codex CLI
837
882
  unavailable 時は Codex seed へ進まないことを固定。
838
883
  - **編集 README / README.ja / docs**:
@@ -862,7 +907,7 @@ host-global DB も分離した。
862
907
  - **編集 [src/cli/db-cmd.mjs](src/cli/db-cmd.mjs) / [src/cli/doctor.mjs](src/cli/doctor.mjs)**:
863
908
  `spotter db refresh/rebuild --host-agent codex` と `spotter doctor` の表示・消去対象を
864
909
  host-global DB に追従。
865
- - **編集 [test/tool-db.test.mjs](test/tool-db.test.mjs)**:
910
+ - **編集 [test/tool-db.test.mjs](https://github.com/kitepon/Spotter/blob/main/test/tool-db.test.mjs)**:
866
911
  Claude global cache の同名 entry が Codex refresh に write-through されず、
867
912
  Codex 側では Codex global cache / investigate を使う回帰テストを追加。
868
913
  - **編集 README / README.ja / CLAUDE.md / docs**:
@@ -886,7 +931,7 @@ host-global DB も分離した。
886
931
  - **編集 [src/core/codex-cli-backend.mjs](src/core/codex-cli-backend.mjs)**:
887
932
  `SPOTTER_CODEX_CLI_MODEL` 未設定時も `--model gpt-5.4-mini` を渡すようにした。
888
933
  `SPOTTER_CODEX_CLI_REASONING_EFFORT` 未設定時の `model_reasoning_effort="low"` は維持。
889
- - **編集 [test/codex-cli-backend.test.mjs](test/codex-cli-backend.test.mjs)**:
934
+ - **編集 [test/codex-cli-backend.test.mjs](https://github.com/kitepon/Spotter/blob/main/test/codex-cli-backend.test.mjs)**:
890
935
  default args が `gpt-5.4-mini` を含むことと、明示的に `model: ""` を渡した場合だけ
891
936
  `--model` を省略できることを固定。
892
937
  - **編集 README / README.ja / CLAUDE.md / docs**: Codex CLI auditor child の既定を
@@ -917,7 +962,7 @@ host-global DB も分離した。
917
962
  ### 変更点
918
963
 
919
964
  - **編集 [src/cli/install.mjs](src/cli/install.mjs)**: 既存 Spotter hook を見つけた場合も `hook.command` を現在の `SPOTTER_BIN` に更新する。これにより `npm install -g claude-spotter` 後、各プロジェクトで `spotter install` を再実行すれば hook は global npm 版へ揃う
920
- - **編集 [test/install.test.mjs](test/install.test.mjs)**: 古い `/old/bin/spotter.mjs` hook が `spotter install` で現在の package path に差し替わる回帰テストを追加
965
+ - **編集 [test/install.test.mjs](https://github.com/kitepon/Spotter/blob/main/test/install.test.mjs)**: 古い `/old/bin/spotter.mjs` hook が `spotter install` で現在の package path に差し替わる回帰テストを追加
921
966
 
922
967
  ### ユーザー側で必要な手順
923
968
 
@@ -931,7 +976,7 @@ host-global DB も分離した。
931
976
  ### 変更点
932
977
 
933
978
  - **編集 [src/cli/install.mjs](src/cli/install.mjs)**: project install 時に Codex CLI (`codex --version`) を検出し、存在する場合は `installCodexHooks()` を呼んで `~/.codex/hooks.json` と `[features].codex_hooks = true` を更新する。Codex CLI が無い環境では明示メッセージを出して Codex hooks 登録だけを行わない
934
- - **編集 [test/install.test.mjs](test/install.test.mjs)**: `spotter install` が Codex CLI presence 時に Codex hooks を登録する回帰テストを追加。既存 refresh 系テストは実ユーザー `~/.codex` を触らないよう DI で固定
979
+ - **編集 [test/install.test.mjs](https://github.com/kitepon/Spotter/blob/main/test/install.test.mjs)**: `spotter install` が Codex CLI presence 時に Codex hooks を登録する回帰テストを追加。既存 refresh 系テストは実ユーザー `~/.codex` を触らないよう DI で固定
935
980
  - **編集 README / README.ja / postinstall / CLAUDE.md / open issues**: インストール手順を `npm install -g claude-spotter` → 各プロジェクトで `spotter install` に集約。`spotter codex-hook install` は修復 / 明示登録用 command として残す
936
981
 
937
982
  ### ユーザー側で必要な手順
@@ -982,7 +1027,7 @@ WSL2 の CPU 使用率が 100% に張り付き、何かがプロセスを「無
982
1027
 
983
1028
  `sanitizeHaikuEnv` (v1.1.6) は `CLAUDE_CONFIG_DIR` を strip して Haiku をデフォルト `~/.claude/` で起動するが、**デフォルト config dir には User scope MCP (`~/.claude.json` 直下 `mcpServers`) と plugin MCP がフルで登録されている**。claude CLI 2.1.x は `--print` モード起動時に config dir 内の全 MCP server を eager に spawn するため、Haiku 1 回呼出ごとに数十個の `npm exec` 子プロセスが立つ。Haiku は `{name, description}` カタログ監査しかしない (= MCP server は不要) のに、起動コストとして user/project の MCP がフル load されていた構造的欠陥。
984
1029
 
985
- 加えて `daemon-702a677d-...log` で同 sessionId の `tool-db loaded` が 15 分間に 8 回記録 = sudden death + auto-resurrect が高頻度発生していた。WSL2 cgroup OOM kill が daemon プロセスごと巻き込んでいた可能性が高く、[docs/open-issues.md](docs/open-issues.md) P0 「daemon プロセスが shutdown ログなしに死ぬ」 (v0.13.2 から残置) の主因もこれと推定。
1030
+ 加えて `daemon-702a677d-...log` で同 sessionId の `tool-db loaded` が 15 分間に 8 回記録 = sudden death + auto-resurrect が高頻度発生していた。WSL2 cgroup OOM kill が daemon プロセスごと巻き込んでいた可能性が高く、[docs/open-issues.md](https://github.com/kitepon/Spotter/blob/main/docs/open-issues.md) P0 「daemon プロセスが shutdown ログなしに死ぬ」 (v0.13.2 から残置) の主因もこれと推定。
986
1031
 
987
1032
  ### 変更点
988
1033
 
@@ -992,14 +1037,14 @@ WSL2 の CPU 使用率が 100% に張り付き、何かがプロセスを「無
992
1037
  - 新 named export `emptyMcpConfigPath()` (テストから参照)
993
1038
  - `buildSpawnArgs({ ...args, mcpConfigPath })` のシグネチャを拡張、`mcpConfigPath` を必須化 (TypeError on missing/empty)、出力に `--strict-mcp-config --mcp-config <path>` を必ず含める。Windows `cmd.exe /c` 経路でも同様に
994
1039
  - `createHaikuCaller` 内 `spawn` 直前で `mcpConfigPath: EMPTY_MCP_CONFIG_PATH` を渡す
995
- - **編集 [test/haiku-caller.test.mjs](test/haiku-caller.test.mjs)**: 回帰ガード 5 件追加 + 既存 `buildSpawnArgs` 2 件を新シグネチャに追従
1040
+ - **編集 [test/haiku-caller.test.mjs](https://github.com/kitepon/Spotter/blob/main/test/haiku-caller.test.mjs)**: 回帰ガード 5 件追加 + 既存 `buildSpawnArgs` 2 件を新シグネチャに追従
996
1041
  - 新規: first call と resumed call の両方で `--strict-mcp-config` と `--mcp-config <path>` を含む
997
1042
  - 新規: `mcpConfigPath` 欠落 / 空文字 / null で TypeError
998
1043
  - 新規: `ensureWorkdir` で `empty-mcp.json` が `{"mcpServers":{}}` で書かれる
999
1044
  - 新規: `ensureWorkdir` の idempotent 性 (3 連呼出で破綻しない)
1000
1045
  - **編集 [src/cli/install.mjs](src/cli/install.mjs)**: `HOOK_EVENTS` の Stop/UserPromptSubmit timeout を 15s/30s から **60s に統一**。v0.13.1 で daemon 側 Haiku timeout を 30s→45s に緩和したのに settings.json に書く Claude Code 本体側の hook timeout が旧値のままで、Chime 等の preamble が大きい (93 KB / 357 件) 環境で daemon が 24-32s かけて正常応答を返している最中に Claude Code 側 hook が timeout kill されて「チャット入力無反応」を誘発していた既存バグの hot-fix。`docs/open-issues.md` の P0「install.mjs の hook timeout が v0.13.1 緩和を反映していない」項目を closing
1001
1046
  - **package.json**: `1.2.6` → `1.3.0` (公開 API シグネチャ変更 = `buildSpawnArgs` の新引数を伴うため minor bump)
1002
- - **編集 [docs/open-issues.md](docs/open-issues.md)**: 解決済みリストに 2 件追加、P0「daemon が shutdown ログなしに死ぬ」節に v1.3.0 で根因が大半解消した可能性を追記
1047
+ - **編集 [docs/open-issues.md](https://github.com/kitepon/Spotter/blob/main/docs/open-issues.md)**: 解決済みリストに 2 件追加、P0「daemon が shutdown ログなしに死ぬ」節に v1.3.0 で根因が大半解消した可能性を追記
1003
1048
 
1004
1049
  ### なぜ `--strict-mcp-config --mcp-config <empty>` が正解か
1005
1050
 
@@ -1045,7 +1090,7 @@ claude CLI 2.1.126 は `--print` モードで stdin の最初の read attempt
1045
1090
  ### 変更点
1046
1091
 
1047
1092
  - **編集 [src/daemon/haiku-caller.mjs](src/daemon/haiku-caller.mjs)**: 新規 `preparePromptFile(wirePrompt)` を named export として追加。`os.tmpdir()` 配下にユニーク tempfile (`spotter-prompt-<pid>-<uuid>.txt`) を作って prompt を書き込み、read-only fd と `close()` ハンドラ (fd close + unlink、両方 best-effort) を返す。`createHaikuCaller` 内 `callHaiku` の `spawn` を `stdio: ['pipe', 'pipe', 'pipe']` + `child.stdin.end(prompt)` から `stdio: [promptFile.fd, 'pipe', 'pipe']` に切替え (child.stdin が null になるので関連 noop listener も削除)。close / error / timeout の各 settle 経路で `promptFile.close()` を呼んでから resolve/reject する `settleAfterCleanup` ヘルパで cleanup を一元化、tempfile leak を防止
1048
- - **編集 [test/haiku-caller.test.mjs](test/haiku-caller.test.mjs)**: 回帰ガード 6 件追加 — (1) tempfile が書かれて読める (2) 100 KB (= pipe buffer 超え) でも全 byte 届く (3) `close()` で unlink される (4) `close()` 二重呼び出し可 (timeout-vs-close race の安全性) (5) 非 string 入力で `TypeError` (6) 並列呼び出しで tmpPath が衝突しない (UUID 保証)
1093
+ - **編集 [test/haiku-caller.test.mjs](https://github.com/kitepon/Spotter/blob/main/test/haiku-caller.test.mjs)**: 回帰ガード 6 件追加 — (1) tempfile が書かれて読める (2) 100 KB (= pipe buffer 超え) でも全 byte 届く (3) `close()` で unlink される (4) `close()` 二重呼び出し可 (timeout-vs-close race の安全性) (5) 非 string 入力で `TypeError` (6) 並列呼び出しで tmpPath が衝突しない (UUID 保証)
1049
1094
  - **package.json**: `1.2.5` → `1.2.6`
1050
1095
 
1051
1096
  ### なぜ tempfile fd 方式が正解か
@@ -1070,7 +1115,7 @@ claude CLI 2.1.126 は `--print` モードで stdin の最初の read attempt
1070
1115
  - **編集 [src/tool-db/investigate-mcp.mjs](src/tool-db/investigate-mcp.mjs)** (2 段階):
1071
1116
  1. `parseMcpListOutput` の name 区切りを `indexOf(':')` (コロン単体) から `indexOf(': ')` (コロン + スペース) に変更。サーバー名側に literal `": "` (コロン + スペース) は CLI 仕様上現れない (CLI が name と rest の間に固定でこのペアを置くため) ので、空白入り名前 (`claude.ai Google Drive`) もコロン入り名前 (`plugin:everything-claude-code:context7`) も両立する
1072
1117
  2. stdio エントリの `command` / `args` を CLI 出力行 (`<name>: <command> <args...> - <status>`) から直接抽出するよう変更。プラグイン MCP は `claude mcp list` には出るが `claude mcp get <name>` では `No MCP server found` で引けない仕様 (実測で確認) のため、CLI 行を唯一の権威ソースとして扱う必要がある。既存 `listMcpToolsOne` の `hasFullConfig` 分岐がそのまま生かされ、`claude mcp get` 経路を skip して直接 spawn するようになる。tokenisation は既存 `splitArgs` と同じ素朴 (whitespace 区切り、quote 非対応) を踏襲、空白入りパスの制約は変わらず
1073
- - **編集 [test/tool-db.test.mjs](test/tool-db.test.mjs)**: 回帰テスト 3 件追加 + 既存 1 件の expectation 拡張 — プラグイン形式 stdio (`plugin:everything-claude-code:context7` を `npx ...` で登録、`command='npx'` / `args=['-y', '@upstash/context7-mcp@2.1.4']` を assert) / プラグイン形式 HTTP (`plugin:everything-claude-code:exa` を `(HTTP)` URL で登録) / 空白入り名前の継続パース (`claude.ai Google Drive` の sse 経路) / 既存 stdio エントリ (`caveat`) も command/args を返すことを assert
1118
+ - **編集 [test/tool-db.test.mjs](https://github.com/kitepon/Spotter/blob/main/test/tool-db.test.mjs)**: 回帰テスト 3 件追加 + 既存 1 件の expectation 拡張 — プラグイン形式 stdio (`plugin:everything-claude-code:context7` を `npx ...` で登録、`command='npx'` / `args=['-y', '@upstash/context7-mcp@2.1.4']` を assert) / プラグイン形式 HTTP (`plugin:everything-claude-code:exa` を `(HTTP)` URL で登録) / 空白入り名前の継続パース (`claude.ai Google Drive` の sse 経路) / 既存 stdio エントリ (`caveat`) も command/args を返すことを assert
1074
1119
 
1075
1120
  ### 背景
1076
1121
 
@@ -1080,15 +1125,15 @@ step 1 (name 区切り修正) でフルネームは取れるようになった
1080
1125
 
1081
1126
  `indexOf(': ')` (コロン + スペース) は CLI が固定で挿入する 2 文字ペアであり、サーバー名内部にこのペアが現れることは構造的に無いので、name 内の任意の `:` (コロン単体) と ` ` (スペース単体) を許容しつつ name と rest を一意に切れる。
1082
1127
 
1083
- [docs/open-issues.md](docs/open-issues.md) P1 「`claude mcp list` text パースの脆弱性」全体は依然として残る (CLI フォーマット変更耐性は本修正でも上がらない、`--json` 出力が来たら全面切り替えしたい) が、コロン入り名前 + プラグイン MCP の具体例はこの版で塞がる。
1128
+ [docs/open-issues.md](https://github.com/kitepon/Spotter/blob/main/docs/open-issues.md) P1 「`claude mcp list` text パースの脆弱性」全体は依然として残る (CLI フォーマット変更耐性は本修正でも上がらない、`--json` 出力が来たら全面切り替えしたい) が、コロン入り名前 + プラグイン MCP の具体例はこの版で塞がる。
1084
1129
 
1085
1130
  ## 1.2.4
1086
1131
 
1087
- **v1.2.3 で `normalizeProjectPath` の挙動を変えた際に、対になる test の expectation 更新を漏らしたため macOS CI で fail していた hot-fix**。`normalizeProjectPath: separator / trailing slash / Windows case` ([test/tool-db.test.mjs:678](test/tool-db.test.mjs#L678)) は「backslash は常に forward slash になる」という旧仕様の expectation を残したまま v1.2.3 commit に取り込まれており、POSIX 上で `'C:\\Users\\u\\proj'` の入力に対して `'C:\\Users\\u\\proj'` (literal 保持) が返るのを `'C:/Users/u/proj'` で assert していた。Linux CI は v1.2.3 で緑化したが、v1.2.3 push 後の matrix 実行で macOS が同じ test で fail。
1132
+ **v1.2.3 で `normalizeProjectPath` の挙動を変えた際に、対になる test の expectation 更新を漏らしたため macOS CI で fail していた hot-fix**。`normalizeProjectPath: separator / trailing slash / Windows case` ([test/tool-db.test.mjs:678](https://github.com/kitepon/Spotter/blob/main/test/tool-db.test.mjs#L678)) は「backslash は常に forward slash になる」という旧仕様の expectation を残したまま v1.2.3 commit に取り込まれており、POSIX 上で `'C:\\Users\\u\\proj'` の入力に対して `'C:\\Users\\u\\proj'` (literal 保持) が返るのを `'C:/Users/u/proj'` で assert していた。Linux CI は v1.2.3 で緑化したが、v1.2.3 push 後の matrix 実行で macOS が同じ test で fail。
1088
1133
 
1089
1134
  ### 変更点
1090
1135
 
1091
- - **編集 [test/tool-db.test.mjs](test/tool-db.test.mjs)**: `normalizeProjectPath: separator / trailing slash / Windows case` の POSIX 側 expectation を v1.2.3 で確定した「POSIX では backslash を literal に保つ」ルールに合わせ、`'C:\\Users\\u\\proj'` / `'C:/Users\\u/proj'` を変換せず返す挙動を assert。コメントで両 test (`normalizeProjectPath` 単体と `findLocalScopeServers: separator variant matches on Windows only`) の整合理由を明記
1136
+ - **編集 [test/tool-db.test.mjs](https://github.com/kitepon/Spotter/blob/main/test/tool-db.test.mjs)**: `normalizeProjectPath: separator / trailing slash / Windows case` の POSIX 側 expectation を v1.2.3 で確定した「POSIX では backslash を literal に保つ」ルールに合わせ、`'C:\\Users\\u\\proj'` / `'C:/Users\\u/proj'` を変換せず返す挙動を assert。コメントで両 test (`normalizeProjectPath` 単体と `findLocalScopeServers: separator variant matches on Windows only`) の整合理由を明記
1092
1137
 
1093
1138
  ソースは v1.2.3 から無変更、test 期待値だけの追従。
1094
1139
 
@@ -1117,7 +1162,7 @@ step 1 (name 区切り修正) でフルネームは取れるようになった
1117
1162
  ### 変更点
1118
1163
 
1119
1164
  - **編集 [src/tool-db/investigate-mcp.mjs](src/tool-db/investigate-mcp.mjs)**: `buildStdioSpawn` の Windows ブランチ条件を `/\.(cmd|bat)$/i` から「絶対 `.exe` パス以外は `cmd.exe /c` で包む」に拡張。`export` を追加してユニットテスト可能に
1120
- - **編集 [test/tool-db.test.mjs](test/tool-db.test.mjs)**: 4 件追加 — POSIX パススルー / Windows 裸名の wrap (`claude-mermaid` で v1.2.1 の症状を直接再現) / Windows `.cmd`・`.bat` の wrap / Windows 絶対 `.exe` パスは un-wrap (空白入りパスでの cmd.exe quoting リスク回避)
1165
+ - **編集 [test/tool-db.test.mjs](https://github.com/kitepon/Spotter/blob/main/test/tool-db.test.mjs)**: 4 件追加 — POSIX パススルー / Windows 裸名の wrap (`claude-mermaid` で v1.2.1 の症状を直接再現) / Windows `.cmd`・`.bat` の wrap / Windows 絶対 `.exe` パスは un-wrap (空白入りパスでの cmd.exe quoting リスク回避)
1121
1166
 
1122
1167
  ### 背景
1123
1168
 
@@ -1156,7 +1201,7 @@ function buildStdioSpawn(command, args) {
1156
1201
  ### 変更点
1157
1202
 
1158
1203
  - **編集 [src/tool-db/mcp-config.mjs](src/tool-db/mcp-config.mjs)**: `readMcpServers` を 4 ソース merge に拡張 — `legacy < user < project < local` の優先順 (公式仕様 Local > Project > User と整合、legacy `~/.claude/.mcp.json` は最下位の互換扱い)。新規 export: `userClaudeJsonPath`、`legacyUserMcpConfigPath`、`normalizeProjectPath`、`extractUserScopeServers`、`findLocalScopeServers`。`readMcpServers` に `claudeJsonPath` / `legacyUserPath` の DI パラメータを追加 (テスト用、デフォルトは実 homedir)。冒頭コメントを公式仕様 ([https://code.claude.com/docs/en/mcp](https://code.claude.com/docs/en/mcp)) に揃えて書き直し、legacy ソースの位置付けを明記
1159
- - **編集 [test/tool-db.test.mjs](test/tool-db.test.mjs)**: 13 件追加 — user/local 単独 / 4 段優先順位 / `~/.claude.json` 不在・malformed・キー欠損 / `extractUserScopeServers` の null 耐性 / `normalizeProjectPath` (separator・trailing slash・Windows case) / `findLocalScopeServers` (exact / 正規化マッチ / 非マッチ時の no-fuzzy / null 入力)
1204
+ - **編集 [test/tool-db.test.mjs](https://github.com/kitepon/Spotter/blob/main/test/tool-db.test.mjs)**: 13 件追加 — user/local 単独 / 4 段優先順位 / `~/.claude.json` 不在・malformed・キー欠損 / `extractUserScopeServers` の null 耐性 / `normalizeProjectPath` (separator・trailing slash・Windows case) / `findLocalScopeServers` (exact / 正規化マッチ / 非マッチ時の no-fuzzy / null 入力)
1160
1205
 
1161
1206
  ### 設計判断
1162
1207
 
@@ -1181,7 +1226,7 @@ function buildStdioSpawn(command, args) {
1181
1226
  - **編集 [src/daemon/daemon.mjs](src/daemon/daemon.mjs)**: tool-db 読み込みを `readLocal` に切り替え、コメントで設計意図を明記
1182
1227
  - **編集 [src/cli/db-cmd.mjs](src/cli/db-cmd.mjs)**: `spotter db list` も local DB 限定に変更 (daemon と表示の整合)
1183
1228
  - **編集 [src/index.mjs](src/index.mjs)**: 公開 export を `readMerged` → `readLocal` にリネーム (programmatic API の破壊変更 = minor bump)
1184
- - **編集 [test/tool-db.test.mjs](test/tool-db.test.mjs)**: 回帰テスト 3 件追加 — (1) prune 挙動 (snapshot に無いツールは local から消える、global は append-only で残る)、(2) investigate 失敗時の保持 (toolNames に含まれている限り既存値を残す)、(3) `readLocal` 単独動作 (global DB の中身が leak しない)
1229
+ - **編集 [test/tool-db.test.mjs](https://github.com/kitepon/Spotter/blob/main/test/tool-db.test.mjs)**: 回帰テスト 3 件追加 — (1) prune 挙動 (snapshot に無いツールは local から消える、global は append-only で残る)、(2) investigate 失敗時の保持 (toolNames に含まれている限り既存値を残す)、(3) `readLocal` 単独動作 (global DB の中身が leak しない)
1185
1230
 
1186
1231
  ### 背景
1187
1232
 
@@ -1214,8 +1259,8 @@ global DB を廃止せず「他プロジェクト用キャッシュ」に格下
1214
1259
 
1215
1260
  - **編集 [src/daemon/haiku-caller.mjs](src/daemon/haiku-caller.mjs)**: 純粋関数 `sanitizeHaikuEnv(baseEnv)` を named export として新設、`createHaikuCaller` の spawn env 構築時に `CLAUDE_CONFIG_DIR` を strip。haiku はデフォルト `~/.claude/` で起動する
1216
1261
  - **編集 [src/daemon/daemon.mjs](src/daemon/daemon.mjs)**: `runHaikuJudgment` で `E_HAIKU_TIMEOUT` / `E_INTERNAL` (auth / spawn / exit != 0) 発生時も throw 前に `callHaiku.reset()` で session を rotate。haiku-caller は成功時のみ `isFirstCall=false` を倒す設計なので、失敗が続くと同じ UUID を `--session-id` で再送して claude CLI 側の "already in use" に化ける経路を塞ぐ
1217
- - **編集 [test/haiku-caller.test.mjs](test/haiku-caller.test.mjs)**: `sanitizeHaikuEnv` の回帰テスト 2 件 (strip 動作 / absent 時 no-op + 原本非破壊)
1218
- - **編集 [test/daemon.test.mjs](test/daemon.test.mjs)**: `runHaikuJudgment` が E_INTERNAL / E_HAIKU_TIMEOUT で reset() を呼ぶ回帰テスト 2 件
1262
+ - **編集 [test/haiku-caller.test.mjs](https://github.com/kitepon/Spotter/blob/main/test/haiku-caller.test.mjs)**: `sanitizeHaikuEnv` の回帰テスト 2 件 (strip 動作 / absent 時 no-op + 原本非破壊)
1263
+ - **編集 [test/daemon.test.mjs](https://github.com/kitepon/Spotter/blob/main/test/daemon.test.mjs)**: `runHaikuJudgment` が E_INTERNAL / E_HAIKU_TIMEOUT で reset() を呼ぶ回帰テスト 2 件
1219
1264
 
1220
1265
  ### 背景
1221
1266
 
@@ -1274,7 +1319,7 @@ SessionStart 毎の `spotter db refresh` で `listMcpServers` が 1 回、stdio
1274
1319
  - **編集 [src/tool-db/investigate-mcp.mjs](src/tool-db/investigate-mcp.mjs)**: `listMcpServers` / `getStdioConfig` が projectRoot を受け取っておきながら `execClaude(claude mcp list / mcp get)` に `cwd` を渡していなかったため、`.mcp.json` 読み込みと claude CLI の walk-up が別プロジェクトを見る可能性があった。`cwd: projectRoot` を付与し、`listMcpToolsOne` を通じて projectRoot を伝搬するシグネチャに変更。通常は `process.cwd() === projectRoot` で表面化しないが、API の意味論を実装に揃える
1275
1320
  - **編集 [src/tool-db/claude-ai-baseline.mjs](src/tool-db/claude-ai-baseline.mjs)**: flat な `listClaudeAiNames` / `getClaudeAiDescription` を削除、server 単位の `getClaudeAiBaselineByServer()` に再編。Gmail / Calendar / Drive を個別集合として保持し、呼び出し側で現実に存在するサーバーのみ注入できるようにした
1276
1321
  - **編集 [src/tool-db/refresh.mjs](src/tool-db/refresh.mjs)**: `buildInvestigationSnapshot` で `listMcpServers` の結果に基づき baseline を filter。`claude mcp list` に `claude.ai Gmail` / `claude.ai Google Calendar` / `claude.ai Google Drive` が存在しない環境 (隔離 `CLAUDE_CONFIG_DIR`, claude.ai OAuth 未連携, 部分連携) では該当 baseline は投入されない。純粋関数 `filterClaudeAiBaseline` を named export として切り出しテスト可能にした
1277
- - **編集 [test/tool-db.test.mjs](test/tool-db.test.mjs)**: `filterClaudeAiBaseline` の回帰テスト 3 件追加 — 全 3 サーバー存在 / Gmail のみ存在 / 全不在
1322
+ - **編集 [test/tool-db.test.mjs](https://github.com/kitepon/Spotter/blob/main/test/tool-db.test.mjs)**: `filterClaudeAiBaseline` の回帰テスト 3 件追加 — 全 3 サーバー存在 / Gmail のみ存在 / 全不在
1278
1323
 
1279
1324
  ### 背景
1280
1325
 
@@ -1305,10 +1350,10 @@ v0.8.0 で claude.ai OAuth 系 MCP (Gmail / Calendar / Drive) を手書き basel
1305
1350
  - コマンド表の `spotter db refresh` コメント更新 (「組込み 遅延ツール」削除、v1.1.0 以降は通常不要な旨追記)、`spotter db rebuild` の挙動を local+global wipe に訂正
1306
1351
  - 設計ドキュメント節を 4 本立て (catalog-design / open-issues / CLAUDE.md §0 / spotter-plan 歴史記録) に再編
1307
1352
  - Haiku timeout 表記を v0.5.0 (30s) → v0.13.1 (45s) に訂正
1308
- - **編集 [docs/01_catalog-design.md](docs/01_catalog-design.md)**:
1353
+ - **編集 [docs/01_catalog-design.md](https://github.com/kitepon/Spotter/blob/main/docs/01_catalog-design.md)**:
1309
1354
  - 新節「収集タイミング (v1.1.0 以降)」追加 — install 同期 seed / SessionStart bg refresh / db refresh / db rebuild の 4 経路を整理
1310
1355
  - 歴史節に v1.1.x の「収集タイミング自動化」を追記
1311
- - **編集 [docs/archive/spotter-plan.md](docs/archive/spotter-plan.md)**:
1356
+ - **編集 [docs/archive/spotter-plan.md](https://github.com/kitepon/Spotter/blob/main/docs/archive/spotter-plan.md)**:
1312
1357
  - 冒頭に「v0.1 時点の設計議事録」である旨のブリッジ追加、現行設計の真実源 (01_catalog-design.md / open-issues.md / CLAUDE.md) へのリンクを明示
1313
1358
 
1314
1359
  ## 1.1.2
@@ -1319,8 +1364,8 @@ v0.8.0 で claude.ai OAuth 系 MCP (Gmail / Calendar / Drive) を手書き basel
1319
1364
 
1320
1365
  - **編集 [src/cli/install.mjs](src/cli/install.mjs)**: `refresh` 呼び出しを try/catch で包み、throw 直前に stderr で復旧経路 (`spotter db refresh`) を露出。§0 の fallback 禁止は守りつつ、「hook 登録済み + tool-db なし」状態に陥ったユーザーに次の一手を示す診断メッセージを追加
1321
1366
  - **編集 [src/cli/install.mjs](src/cli/install.mjs)**: `runInstall` に `refreshFn` パラメータを追加 (default: 実 refresh)。テストから mock を注入できるようにした
1322
- - **編集 [test/install.test.mjs](test/install.test.mjs)**: 新規 2 件追加 — (1) 2 回目 install でも refresh が呼ばれる回帰ガード (v1.1.1 fix の直接検証)、(2) refresh 失敗時に stderr に復旧ヒントが出ることを確認
1323
- - **編集 [docs/open-issues.md](docs/open-issues.md)**: P2 に「tool-db.json の並列書き込み race condition」を追記 (install と SessionStart bg refresh が同時に走ると last-writer-wins、実害観測なしなので放置)
1367
+ - **編集 [test/install.test.mjs](https://github.com/kitepon/Spotter/blob/main/test/install.test.mjs)**: 新規 2 件追加 — (1) 2 回目 install でも refresh が呼ばれる回帰ガード (v1.1.1 fix の直接検証)、(2) refresh 失敗時に stderr に復旧ヒントが出ることを確認
1368
+ - **編集 [docs/open-issues.md](https://github.com/kitepon/Spotter/blob/main/docs/open-issues.md)**: P2 に「tool-db.json の並列書き込み race condition」を追記 (install と SessionStart bg refresh が同時に走ると last-writer-wins、実害観測なしなので放置)
1324
1369
 
1325
1370
  ### 設計判断
1326
1371
 
@@ -1347,7 +1392,7 @@ v1.0.0 以前は `spotter install` が hook 登録だけで tool-db を作らず
1347
1392
  - **編集 [src/cli/install.mjs](src/cli/install.mjs)**: settings.json 書き込み後に project-mode で `refresh({projectRoot})` を同期実行し tool-db を seed。失敗時は §0 準拠で throw (hook だけ登録されて DB が無い中途半端な状態を残さない)。`skipRefresh` オプションを新設 (既存テストが user 環境をスキャンしないように)。"next steps" メッセージから `spotter db refresh` の手動実行指示を削除
1348
1393
  - **編集 [src/hooks/session-start.mjs](src/hooks/session-start.mjs)**: daemon readiness 確立後に `spawnRefreshDetached({projectRoot})` を発火。hook 自体は即 return、refresh は detached child として bg 実行。**現セッションの daemon は起動時の tool-db で固定**のため反映は次セッション以降
1349
1394
  - **編集 [src/hooks/spawn-daemon.mjs](src/hooks/spawn-daemon.mjs)**: `spawnRefreshDetached` を追加 export。`node <spotterBin> db refresh` を `detached: true, stdio: 'ignore', unref()` で起動、hook を遅延させない
1350
- - **テスト更新 [test/install.test.mjs](test/install.test.mjs)**: 全 6 件が `skipRefresh: true` を渡すよう更新
1395
+ - **テスト更新 [test/install.test.mjs](https://github.com/kitepon/Spotter/blob/main/test/install.test.mjs)**: 全 6 件が `skipRefresh: true` を渡すよう更新
1351
1396
 
1352
1397
  ### 設計判断
1353
1398
 
@@ -1387,8 +1432,8 @@ Spotter の役割は「Bell にとって**言われないと思い出さない**
1387
1432
  - **編集 [src/tool-db/refresh.mjs](src/tool-db/refresh.mjs)**: `buildInvestigationSnapshot` から deferred 経路を削除、スキル / サブエージェント経路を追加。MCP live fetch + `claude.ai` baseline (Gmail / Calendar / Drive) は維持
1388
1433
  - **編集 [src/cli/db-cmd.mjs](src/cli/db-cmd.mjs)**: `spotter db rebuild` が local DB に加えて **global DB も wipe** するように仕様変更。旧バージョンから上がってきたユーザーが古い deferred エントリを抱えたままにならないため
1389
1434
  - **編集 [src/index.mjs](src/index.mjs)**: `listSkillsAll` / `listActivePlugins` / `listAgentsAll` の export 追加
1390
- - **リネーム [docs/catalog-design-deferred-mcp.md](docs/01_catalog-design.md) → [docs/01_catalog-design.md](docs/01_catalog-design.md)**: 大幅書き直し。対象範囲・分類軸・収集経路を v1.0.0 仕様で更新
1391
- - **テスト更新 [test/tool-db.test.mjs](test/tool-db.test.mjs)**: deferred baseline テスト 3 件削除、frontmatter テスト 3 件 + skill テスト 2 件 + agent テスト 2 件を追加。計 32 件全通過
1435
+ - **リネーム [docs/catalog-design-deferred-mcp.md](https://github.com/kitepon/Spotter/blob/main/docs/01_catalog-design.md) → [docs/01_catalog-design.md](https://github.com/kitepon/Spotter/blob/main/docs/01_catalog-design.md)**: 大幅書き直し。対象範囲・分類軸・収集経路を v1.0.0 仕様で更新
1436
+ - **テスト更新 [test/tool-db.test.mjs](https://github.com/kitepon/Spotter/blob/main/test/tool-db.test.mjs)**: deferred baseline テスト 3 件削除、frontmatter テスト 3 件 + skill テスト 2 件 + agent テスト 2 件を追加。計 32 件全通過
1392
1437
 
1393
1438
  ### 結果
1394
1439
 
@@ -1410,7 +1455,7 @@ preamble 初回送信サイズ推定 15-25K tokens (Haiku 4.5 の 200K コンテ
1410
1455
  ### 残課題
1411
1456
 
1412
1457
  - **初回 Haiku latency の観測**: 268 件 preamble で `duration_ms` が 45s timeout に接近しないか実運用で確認。超えるようなら再緩和か件数絞り込みを再検討
1413
- - **baseline 自動追従機構**: `claude.ai` MCP baseline は手書きのまま。Claude 側で追加があっても検知できない。長期的には監視機構が必要 ([docs/open-issues.md](docs/open-issues.md) P1 継続)
1458
+ - **baseline 自動追従機構**: `claude.ai` MCP baseline は手書きのまま。Claude 側で追加があっても検知できない。長期的には監視機構が必要 ([docs/open-issues.md](https://github.com/kitepon/Spotter/blob/main/docs/open-issues.md) P1 継続)
1414
1459
  - **v0.13.0 新軸の過検出**: turn_end 軸 (ツール適用機会監査) の誤爆パターンは別問題、継続観測
1415
1460
 
1416
1461
  ## 0.13.3
@@ -1432,7 +1477,7 @@ preamble 初回送信サイズ推定 15-25K tokens (Haiku 4.5 の 200K コンテ
1432
1477
 
1433
1478
  ### 残課題
1434
1479
 
1435
- - v0.13.0 新軸の**カタログ内過検出** (Read 乱発 / caveat 誤爆等) は別問題。[docs/open-issues.md](docs/open-issues.md) の P0 観測タスクとして継続
1480
+ - v0.13.0 新軸の**カタログ内過検出** (Read 乱発 / caveat 誤爆等) は別問題。[docs/open-issues.md](https://github.com/kitepon/Spotter/blob/main/docs/open-issues.md) の P0 観測タスクとして継続
1436
1481
  - few-shot 例の `current_time` は現 tool-db に無い名前。Haiku が cargo-cult するリスクを filter で潰したが、例そのものを実在ツールに差し替えるかは要検討 (ただし例の抽象性が失われる tradeoff あり)
1437
1482
 
1438
1483
  ## 0.13.2
@@ -1476,7 +1521,7 @@ preamble 初回送信サイズ推定 15-25K tokens (Haiku 4.5 の 200K コンテ
1476
1521
 
1477
1522
  ### 残課題
1478
1523
 
1479
- Haiku 突然死 (shutdown ログなしで daemon 再起動する事象、v0.12.0 auto-resurrect で救われているが見えない欠落ターンが発生する) は未対処。[docs/open-issues.md](docs/open-issues.md) P0 に残置。
1524
+ Haiku 突然死 (shutdown ログなしで daemon 再起動する事象、v0.12.0 auto-resurrect で救われているが見えない欠落ターンが発生する) は未対処。[docs/open-issues.md](https://github.com/kitepon/Spotter/blob/main/docs/open-issues.md) P0 に残置。
1480
1525
 
1481
1526
  ## 0.13.0
1482
1527
 
@@ -1495,13 +1540,13 @@ Haiku 突然死 (shutdown ログなしで daemon 再起動する事象、v0.12.0
1495
1540
 
1496
1541
  - **編集 [src/daemon/haiku-caller.mjs](src/daemon/haiku-caller.mjs)**: `SHARED_HEADER` の stage=turn_end 説明を書き換え、few-shot を 4 件 (検証/登録/照会/pass) に拡張。`buildFinalStagePrompt` から `userInput` 引数を削除、`<user_input>` タグも削除
1497
1542
  - **編集 [src/daemon/daemon.mjs](src/daemon/daemon.mjs)**: `handleTurnEnd` の `buildFinalStagePrompt` 呼び出しから `userInput` 引数削除、`savedUserInput` 変数削除。`state.lastUserInput` は `no_user_input` pass 分岐用に保持継続 (コメントで意図明記)
1498
- - **編集 [test/haiku-caller.test.mjs](test/haiku-caller.test.mjs)**: `buildFinalStagePrompt` の 3 テストから `userInput:` 引数削除、`<user_input>` タグ包含アサートを非包含アサートに反転
1499
- - **編集 [test/daemon.test.mjs](test/daemon.test.mjs)**: turn_end の per-turn prompt に `<user_input>` タグも user 発言原文も含まれないことを確認するテストを 1 件追加
1500
- - **編集 [CLAUDE.md](CLAUDE.md)**: Product Concept に「判定軸 (v0.13.0 で 2 軸化)」セクションを追加、user_input=要請充足チェック / turn_end=ツール適用機会の監査 を明記
1543
+ - **編集 [test/haiku-caller.test.mjs](https://github.com/kitepon/Spotter/blob/main/test/haiku-caller.test.mjs)**: `buildFinalStagePrompt` の 3 テストから `userInput:` 引数削除、`<user_input>` タグ包含アサートを非包含アサートに反転
1544
+ - **編集 [test/daemon.test.mjs](https://github.com/kitepon/Spotter/blob/main/test/daemon.test.mjs)**: turn_end の per-turn prompt に `<user_input>` タグも user 発言原文も含まれないことを確認するテストを 1 件追加
1545
+ - **編集 [CLAUDE.md](https://github.com/kitepon/Spotter/blob/main/CLAUDE.md)**: Product Concept に「判定軸 (v0.13.0 で 2 軸化)」セクションを追加、user_input=要請充足チェック / turn_end=ツール適用機会の監査 を明記
1501
1546
 
1502
1547
  ### 非互換
1503
1548
 
1504
- - **判定挙動の意味論変更**: v0.12.x までの「user_input 要請に対応するツール」しか指摘しなかった Stop hook が、v0.13.0 からは user_input 非依存で「応答に対する適用機会」を指摘する。false positive / false negative の方向性も変わるため、過検出率 / pass 率の再計測が必要 ([docs/open-issues.md](docs/open-issues.md) P0 に観測タスクを追加)
1549
+ - **判定挙動の意味論変更**: v0.12.x までの「user_input 要請に対応するツール」しか指摘しなかった Stop hook が、v0.13.0 からは user_input 非依存で「応答に対する適用機会」を指摘する。false positive / false negative の方向性も変わるため、過検出率 / pass 率の再計測が必要 ([docs/open-issues.md](https://github.com/kitepon/Spotter/blob/main/docs/open-issues.md) P0 に観測タスクを追加)
1505
1550
  - **API 変更**: `buildFinalStagePrompt({ userInput, usedTools, finalResponse })` → `buildFinalStagePrompt({ usedTools, finalResponse })`。外部から直接呼ばれる API ではない (daemon 内部) ため影響範囲は Spotter 本体のみ
1506
1551
 
1507
1552
  ## 0.12.0
@@ -1524,7 +1569,7 @@ Haiku 突然死 (shutdown ログなしで daemon 再起動する事象、v0.12.0
1524
1569
  - **編集 [src/hooks/user-prompt.mjs](src/hooks/user-prompt.mjs)**: `sendRequest` が `E_UNREACHABLE` で失敗したら `spawnDaemonAndWaitReady` を呼んで retry (1 回のみ)
1525
1570
  - **削除 [src/hooks/ppid-probe.mjs]**: env dump 用の調査 hook、役目終了
1526
1571
  - **編集 `.claude/settings.json`**: probe hook 登録撤去(端末ローカル設定であり、repository 配布物には含めない)
1527
- - **編集 [test/daemon.test.mjs](test/daemon.test.mjs)**: parent-watch test 2 件を削除、heartbeat timeout / heartbeat reset / heartbeatTimeoutMs validation の 3 件を追加
1572
+ - **編集 [test/daemon.test.mjs](https://github.com/kitepon/Spotter/blob/main/test/daemon.test.mjs)**: parent-watch test 2 件を削除、heartbeat timeout / heartbeat reset / heartbeatTimeoutMs validation の 3 件を追加
1528
1573
 
1529
1574
  ### 非互換
1530
1575
 
@@ -1566,7 +1611,7 @@ Haiku 突然死 (shutdown ログなしで daemon 再起動する事象、v0.12.0
1566
1611
  - **編集 [src/tool-db/mcp-config.mjs](src/tool-db/mcp-config.mjs)**: `readMcpServers({projectRoot})` シグネチャへ変更。`projectRoot` が渡されれば user scope に project scope を merge して返す。missing file は空として扱う
1567
1612
  - **編集 [src/tool-db/investigate-mcp.mjs](src/tool-db/investigate-mcp.mjs)**: `listMcpServers` / `listMcpToolsAll` が `projectRoot` を受け取って伝搬
1568
1613
  - **編集 [src/tool-db/refresh.mjs](src/tool-db/refresh.mjs)**: `buildInvestigationSnapshot` / `refresh` が `projectRoot` を伝搬 (CLI からは既に渡されている、経路が繋がった)
1569
- - **編集 [test/tool-db.test.mjs](test/tool-db.test.mjs)**: project-scope override + missing-file fallback の 2 ケース追加 (total 99 tests)
1614
+ - **編集 [test/tool-db.test.mjs](https://github.com/kitepon/Spotter/blob/main/test/tool-db.test.mjs)**: project-scope override + missing-file fallback の 2 ケース追加 (total 99 tests)
1570
1615
 
1571
1616
  ### 非互換
1572
1617
 
@@ -1590,7 +1635,7 @@ v0.8.0 の `spotter db refresh` 実測で x-api (HTTP MCP) が 401 Unauthorized
1590
1635
  - **新規 [src/tool-db/mcp-config.mjs](src/tool-db/mcp-config.mjs)**: `~/.claude/.mcp.json` をパース、`describeServer()` で `{command, args, env}` (stdio) または `{url, headers}` (http/sse) のディスクリプタに正規化
1591
1636
  - **編集 [src/tool-db/investigate-mcp.mjs](src/tool-db/investigate-mcp.mjs)**: `listMcpServers` を `claude mcp list` + `.mcp.json` の併用へ。CLI で得た name ごとに `.mcp.json` のエントリを優先使用し、なければ CLI 情報にフォールバック。`spawnAndQuery` が `env` を受け取って `{...process.env, ...env}` で spawn 時に merge
1592
1637
  - **編集 [src/tool-db/investigate-mcp-http.mjs](src/tool-db/investigate-mcp-http.mjs)**: `listToolsHttp` が `headers` パラメータを受け取って fetch の HTTP headers に merge
1593
- - **編集 [test/tool-db.test.mjs](test/tool-db.test.mjs)**: `describeServer` の unit test 5 件追加 (stdio + env、stdio 最小、http + headers、sse 判別、未知エントリ)
1638
+ - **編集 [test/tool-db.test.mjs](https://github.com/kitepon/Spotter/blob/main/test/tool-db.test.mjs)**: `describeServer` の unit test 5 件追加 (stdio + env、stdio 最小、http + headers、sse 判別、未知エントリ)
1594
1639
 
1595
1640
  ### 実測
1596
1641
 
@@ -1646,7 +1691,7 @@ v0.7.0 リリース直後、新規セッションで `spotter db refresh` を打
1646
1691
 
1647
1692
  Haiku が「Bell が呼び忘れているツール」を判定するには、Bell が今のセッションで実際に呼べるツールを知っている必要がある。v0.6.x までのカタログは `current_time` / `web_search` / `read_file` のような **抽象的な汎用ツール 5 件** を手書きしていただけで、Caveat や Gmail のような MCP ツール、TodoWrite や WebSearch のような Claude Code 組込みの遅延ツールは Haiku の視野に入っていなかった。結果、ユーザーが「過去に解決したナレッジを残したい」と言っても Spotter は Caveat を推奨できないという的外れな状態だった。
1648
1693
 
1649
- 設計思想は現行の [docs/01_catalog-design.md](docs/01_catalog-design.md) に引き継ぎ。要点:
1694
+ 設計思想は現行の [docs/01_catalog-design.md](https://github.com/kitepon/Spotter/blob/main/docs/01_catalog-design.md) に引き継ぎ。要点:
1650
1695
 
1651
1696
  - **Haiku に渡すのは name + description のペアだけ**。schema は不要 — どう呼ぶかは Bell が ToolSearch で解決する責任 (役割分業)
1652
1697
  - **MCP ツールの description は MCP サーバーから直接取得**。Spotter は中継者に徹し、手書きで言い換えない (single source of truth = MCP server)
@@ -1669,7 +1714,7 @@ Haiku が「Bell が呼び忘れているツール」を判定するには、Bel
1669
1714
  - **編集 [src/cli/doctor.mjs](src/cli/doctor.mjs)**: catalog チェック → tool-db (global + local) のチェック
1670
1715
  - **編集 [bin/spotter.mjs](bin/spotter.mjs)**: `spotter catalog edit/lint` を `spotter db list/refresh/rebuild` に置換
1671
1716
  - **削除**: `src/catalog/`, `src/cli/catalog.mjs`, `templates/tools.yaml`, `test/catalog.test.mjs`, `test/loader.test.mjs`
1672
- - **新規 [test/tool-db.test.mjs](test/tool-db.test.mjs)**: 21 件 (loader/lookup/investigate-mcp/deferred-baseline)
1717
+ - **新規 [test/tool-db.test.mjs](https://github.com/kitepon/Spotter/blob/main/test/tool-db.test.mjs)**: 21 件 (loader/lookup/investigate-mcp/deferred-baseline)
1673
1718
 
1674
1719
  ### Breaking
1675
1720
 
@@ -1699,7 +1744,7 @@ Haiku が「Bell が呼び忘れているツール」を判定するには、Bel
1699
1744
  - **[src/daemon/daemon.mjs](src/daemon/daemon.mjs)**: `startDaemon({ parentPid, parentWatchIntervalMs })` を追加。`parentPid` が指定されると 5 秒間隔 (default) で `process.kill(parentPid, 0)` を ping し、ESRCH を検知したら自身を shutdown。`parentWatchIntervalMs` はテスト用に短縮可能。`parentPid !== null && (!Number.isInteger || <= 0)` は TypeError で reject。
1700
1745
  - **[src/cli/daemon-cmd.mjs](src/cli/daemon-cmd.mjs)**: `--parent-pid <N>` 引数をパースして `startDaemon` に渡す。
1701
1746
  - **[src/hooks/session-start.mjs](src/hooks/session-start.mjs)**: daemon spawn 時に `--parent-pid <process.ppid>` を付与。`process.ppid` は SessionStart hook から見た親 = Claude Code 本体。
1702
- - **[test/daemon.test.mjs](test/daemon.test.mjs)**: 子プロセスを fake parent として spawn → daemon 起動 → 子を SIGKILL → daemon の `server.on('close')` が発火することを検証する E2E テストを追加。`parentPid: 0` / `1.5` が TypeError になることのバリデーションテストも追加。
1747
+ - **[test/daemon.test.mjs](https://github.com/kitepon/Spotter/blob/main/test/daemon.test.mjs)**: 子プロセスを fake parent として spawn → daemon 起動 → 子を SIGKILL → daemon の `server.on('close')` が発火することを検証する E2E テストを追加。`parentPid: 0` / `1.5` が TypeError になることのバリデーションテストも追加。
1703
1748
 
1704
1749
  ### 効果
1705
1750
 
@@ -1733,8 +1778,8 @@ v0.5.2 で可視化した duration_ms を数ターン観測したところ、`mo
1733
1778
 
1734
1779
  - **[src/daemon/haiku-caller.mjs](src/daemon/haiku-caller.mjs)**: `buildPreamble({ catalog })` を新設。`SHARED_HEADER` に `stage=user_input` / `stage=turn_end` 両方の判定指示と few-shot を集約し、カタログと一緒に初回 1 回だけ送る。`buildFirstStagePrompt` / `buildFinalStagePrompt` はカタログと role を剥がして per-turn payload (stage マーカー + 入力タグ) のみに縮小。`createHaikuCaller({ preamble, ... })` が optional preamble を受け取り、`isFirstCall === true` のときだけ prompt に prepend する。`reset()` は `isFirstCall = true` を復元するので role collapse 回復時は新 session に preamble が再送される。
1735
1780
  - **[src/daemon/daemon.mjs](src/daemon/daemon.mjs)**: startup で `buildPreamble({ catalog })` を 1 回作って `createHaikuCaller` に渡す。`handleUserInput` / `handleTurnEnd` の呼び出し側はカタログを渡さないシンプルな形に戻る (カタログは daemon 内部でのみ保持、preamble に封じ込む)。
1736
- - **[test/haiku-caller.test.mjs](test/haiku-caller.test.mjs)**: `buildPreamble` が role+schema+catalog+few-shot を全て含むこと、per-turn 側のプロンプトが catalog/role を含まないこと、non-string な preamble が TypeError になることを検証。
1737
- - **[test/daemon.test.mjs](test/daemon.test.mjs)**: 既存の「every Haiku invocation receives the full catalog prompt」テストを **逆の主張 (per-turn prompt は catalog を含まない)** に置き換え。
1781
+ - **[test/haiku-caller.test.mjs](https://github.com/kitepon/Spotter/blob/main/test/haiku-caller.test.mjs)**: `buildPreamble` が role+schema+catalog+few-shot を全て含むこと、per-turn 側のプロンプトが catalog/role を含まないこと、non-string な preamble が TypeError になることを検証。
1782
+ - **[test/daemon.test.mjs](https://github.com/kitepon/Spotter/blob/main/test/daemon.test.mjs)**: 既存の「every Haiku invocation receives the full catalog prompt」テストを **逆の主張 (per-turn prompt は catalog を含まない)** に置き換え。
1738
1783
 
1739
1784
  ### 期待される効果
1740
1785
 
@@ -1758,8 +1803,8 @@ v0.5.1 の hot-fix で session-scoped Haiku がようやく生きた状態で動
1758
1803
 
1759
1804
  - **[src/daemon/haiku-caller.mjs](src/daemon/haiku-caller.mjs)**: `createHaikuCaller` の返り値に `isFirstCall` getter を追加。daemon 側が「次の呼び出しが初回かどうか」をスナップショットできる。
1760
1805
  - **[src/daemon/daemon.mjs](src/daemon/daemon.mjs)**: `callHaikuTracked` が raw 文字列に加えて `{ durationMs, mode }` を返す構造に変更。`runHaikuJudgment` / `handleUserInput` / `handleTurnEnd` の戻り値構造も合わせて `{ parsed, meta }` に統一。ログ出力に `mode=first|resumed, duration_ms=<N>` を追加。role collapse 回復パスも meta を引き継ぐため silent-pass ログにも duration が残る。
1761
- - **[test/haiku-caller.test.mjs](test/haiku-caller.test.mjs)**: `isFirstCall` の初期値と `reset()` 後の挙動を検証するテストを追加。
1762
- - **[test/daemon.test.mjs](test/daemon.test.mjs)**: `user_input` / `turn_end` のログ行に `mode=first` / `mode=resumed` と `duration_ms=<N>` が含まれることを検証するテストを 2 件追加。
1806
+ - **[test/haiku-caller.test.mjs](https://github.com/kitepon/Spotter/blob/main/test/haiku-caller.test.mjs)**: `isFirstCall` の初期値と `reset()` 後の挙動を検証するテストを追加。
1807
+ - **[test/daemon.test.mjs](https://github.com/kitepon/Spotter/blob/main/test/daemon.test.mjs)**: `user_input` / `turn_end` のログ行に `mode=first` / `mode=resumed` と `duration_ms=<N>` が含まれることを検証するテストを 2 件追加。
1763
1808
 
1764
1809
  ### 観測できるようになったこと
1765
1810
 
@@ -1786,7 +1831,7 @@ v0.5.0 リリース直後の実セッションで、Stop hook の Haiku 判定
1786
1831
  ### 変更点
1787
1832
 
1788
1833
  - **[src/daemon/haiku-caller.mjs](src/daemon/haiku-caller.mjs)**: resume 時は `--session-id` を外して `--resume <uuid>` のみを渡す形に修正。初回は従来どおり `--session-id <uuid>` で新規セッション確立。
1789
- - **[test/haiku-caller.test.mjs](test/haiku-caller.test.mjs)**: `buildSpawnArgs: subsequent call` のアサーションを「`--session-id` が含まれない / `--resume <uuid>` が正しく渡る」に書き換え。
1834
+ - **[test/haiku-caller.test.mjs](https://github.com/kitepon/Spotter/blob/main/test/haiku-caller.test.mjs)**: `buildSpawnArgs: subsequent call` のアサーションを「`--session-id` が含まれない / `--resume <uuid>` が正しく渡る」に書き換え。
1790
1835
 
1791
1836
  ### 残る既知課題
1792
1837
 
@@ -1865,7 +1910,7 @@ v0.4.0 以降「再度 session-scoped を提案しないこと」を絶対制約
1865
1910
 
1866
1911
  - **[src/hooks/transcript-reader.mjs](src/hooks/transcript-reader.mjs) 新設**: transcript JSONL の末尾から assistant の text ブロックだけを抽出する `getLastAssistantText()`。Throughline (MIT, 同作者) から必要最小限を移植。**thinking ブロック / tool_use ブロックは除外**されるので、ユーザーに見えた最終応答テキストだけが Haiku に渡る。
1867
1912
  - **[src/hooks/stop.mjs](src/hooks/stop.mjs) 書き換え**: `input.final_response` (存在しないフィールド) を廃止、`input.transcript_path` (§0 に従い `requireString` で必須化) から `getLastAssistantText()` 経由で最終応答を取得。
1868
- - **[test/transcript-reader.test.mjs](test/transcript-reader.test.mjs) 追加**: 8 ケース。thinking 除外、tool_use スキップ、複数 text ブロックの連結、欠損ファイル、partial JSONL 末尾 (書き込み途中) への耐性等。
1913
+ - **[test/transcript-reader.test.mjs](https://github.com/kitepon/Spotter/blob/main/test/transcript-reader.test.mjs) 追加**: 8 ケース。thinking 除外、tool_use スキップ、複数 text ブロックの連結、欠損ファイル、partial JSONL 末尾 (書き込み途中) への耐性等。
1869
1914
 
1870
1915
  ### 効果
1871
1916
 
@@ -2098,4 +2143,4 @@ Initial release.
2098
2143
 
2099
2144
  ### Design
2100
2145
 
2101
- 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).
2146
+ 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](https://github.com/kitepon/Spotter/blob/main/docs/archive/spotter-plan.md).