claude-spotter 0.5.1 → 0.5.2
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 +29 -0
- package/package.json +1 -1
- package/src/daemon/daemon.mjs +11 -8
- package/src/daemon/haiku-caller.mjs +5 -0
- package/src/version.mjs +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,34 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.5.2
|
|
4
|
+
|
|
5
|
+
**Haiku 呼び出しのレイテンシ可視化 (観測性の改善のみ、機能変更なし)**。
|
|
6
|
+
|
|
7
|
+
### 事の発端
|
|
8
|
+
|
|
9
|
+
v0.5.1 の hot-fix で session-scoped Haiku がようやく生きた状態で動き始めた。実セッション観測で `--resume` 経路の Haiku 判定はエラーなく走っているものの、**そこに「cold-start が実際に消えたか」を読み取れる情報が daemon ログに出ていない**。プラン §5.5 が前提としていた「`--resume` で毎ターン 20–50 秒の claude -p spawn コストを消せる」が実効的に効いているかは、呼び出し時間が見えないと判断できない。
|
|
10
|
+
|
|
11
|
+
### 変更点
|
|
12
|
+
|
|
13
|
+
- **[src/daemon/haiku-caller.mjs](src/daemon/haiku-caller.mjs)**: `createHaikuCaller` の返り値に `isFirstCall` getter を追加。daemon 側が「次の呼び出しが初回かどうか」をスナップショットできる。
|
|
14
|
+
- **[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 が残る。
|
|
15
|
+
- **[test/haiku-caller.test.mjs](test/haiku-caller.test.mjs)**: `isFirstCall` の初期値と `reset()` 後の挙動を検証するテストを追加。
|
|
16
|
+
- **[test/daemon.test.mjs](test/daemon.test.mjs)**: `user_input` / `turn_end` のログ行に `mode=first` / `mode=resumed` と `duration_ms=<N>` が含まれることを検証するテストを 2 件追加。
|
|
17
|
+
|
|
18
|
+
### 観測できるようになったこと
|
|
19
|
+
|
|
20
|
+
これまでは `user_input: pass=true, missing=` だけだったログ行が `user_input: pass=true, missing=, mode=first, duration_ms=8432` のように出る。次のセッションから:
|
|
21
|
+
|
|
22
|
+
- **`mode=resumed` の duration_ms が mode=first より有意に短い**なら `--resume` の効果が実測で確認できる
|
|
23
|
+
- **role_collapse_reset が発生しても duration_ms が見える**ので、回復が高速なのか cold-start 待ちなのかが区別できる
|
|
24
|
+
- **timeout 30s に対する余裕**が数値で見える (ギリギリなら延長、余裕なら短縮の判断材料)
|
|
25
|
+
|
|
26
|
+
これらは v0.5.0 / v0.5.1 の「resume の実効 spawn 削減量未検証」「role collapse 実発生頻度の観測」という既知課題を **観測可能な状態に引き上げる**ための最小変更。判断材料が貯まるまで追加の構造変更は凍結。
|
|
27
|
+
|
|
28
|
+
### 機能的には非変更
|
|
29
|
+
|
|
30
|
+
ログフォーマット以外の挙動は一切変わらない。envelope 契約・hook の終了コード・Haiku プロンプト・catalog 形式・回復ロジックのいずれも手付かず。
|
|
31
|
+
|
|
3
32
|
## 0.5.1
|
|
4
33
|
|
|
5
34
|
**v0.5.0 の Haiku spawn が初呼び出し時点で落ちていたバグの hot-fix**。
|
package/package.json
CHANGED
package/src/daemon/daemon.mjs
CHANGED
|
@@ -88,23 +88,26 @@ export async function startDaemon({
|
|
|
88
88
|
|
|
89
89
|
const callHaikuTracked = async (prompt) => {
|
|
90
90
|
lastHaikuCallAt = Date.now();
|
|
91
|
-
|
|
91
|
+
const mode = callHaiku.isFirstCall === false ? 'resumed' : 'first';
|
|
92
|
+
const start = Date.now();
|
|
93
|
+
const raw = await callHaiku(prompt);
|
|
94
|
+
return { raw, meta: { durationMs: Date.now() - start, mode } };
|
|
92
95
|
};
|
|
93
96
|
|
|
94
97
|
// v0.5.0: shared Haiku-invocation + parse helper. On E_HAIKU_SCHEMA (role collapse),
|
|
95
98
|
// rotates the Haiku session-id and silent-passes the turn (reason: role_collapse_reset).
|
|
96
99
|
// Other Haiku errors (timeout, spawn failure) still propagate — §14 unexpected → throw.
|
|
97
100
|
const runHaikuJudgment = async (stage, prompt) => {
|
|
98
|
-
const raw = await callHaikuTracked(prompt);
|
|
101
|
+
const { raw, meta } = await callHaikuTracked(prompt);
|
|
99
102
|
try {
|
|
100
|
-
return parseHaikuResponse(raw);
|
|
103
|
+
return { parsed: parseHaikuResponse(raw), meta };
|
|
101
104
|
} catch (err) {
|
|
102
105
|
if (err instanceof HaikuError && err.code === 'E_HAIKU_SCHEMA') {
|
|
103
106
|
logFn(`${stage}: role collapse detected, session reset: ${err.message}`);
|
|
104
107
|
if (typeof callHaiku.reset === 'function') {
|
|
105
108
|
callHaiku.reset();
|
|
106
109
|
}
|
|
107
|
-
return { pass: true, missing_tools: [], reason: 'role_collapse_reset' };
|
|
110
|
+
return { parsed: { pass: true, missing_tools: [], reason: 'role_collapse_reset' }, meta };
|
|
108
111
|
}
|
|
109
112
|
throw err;
|
|
110
113
|
}
|
|
@@ -166,9 +169,9 @@ export async function startDaemon({
|
|
|
166
169
|
state.lastUserInput = userInput;
|
|
167
170
|
state.usedTools = []; // reset tools for this turn
|
|
168
171
|
|
|
169
|
-
const parsed = await runHaikuJudgment('user_input', buildFirstStagePrompt({ catalog, userInput }));
|
|
172
|
+
const { parsed, meta } = await runHaikuJudgment('user_input', buildFirstStagePrompt({ catalog, userInput }));
|
|
170
173
|
logFn(
|
|
171
|
-
`user_input: pass=${parsed.pass}, missing=${parsed.missing_tools.map((m) => m.name).join(',')}${
|
|
174
|
+
`user_input: pass=${parsed.pass}, missing=${parsed.missing_tools.map((m) => m.name).join(',')}, mode=${meta.mode}, duration_ms=${meta.durationMs}${
|
|
172
175
|
parsed.reason ? `, reason=${parsed.reason}` : ''
|
|
173
176
|
}`
|
|
174
177
|
);
|
|
@@ -207,7 +210,7 @@ export async function startDaemon({
|
|
|
207
210
|
|
|
208
211
|
const savedUserInput = state.lastUserInput;
|
|
209
212
|
const savedUsedTools = state.usedTools.slice();
|
|
210
|
-
const parsed = await runHaikuJudgment(
|
|
213
|
+
const { parsed, meta } = await runHaikuJudgment(
|
|
211
214
|
'turn_end',
|
|
212
215
|
buildFinalStagePrompt({
|
|
213
216
|
catalog,
|
|
@@ -217,7 +220,7 @@ export async function startDaemon({
|
|
|
217
220
|
})
|
|
218
221
|
);
|
|
219
222
|
logFn(
|
|
220
|
-
`turn_end: pass=${parsed.pass}, missing=${parsed.missing_tools.map((m) => m.name).join(',')}${
|
|
223
|
+
`turn_end: pass=${parsed.pass}, missing=${parsed.missing_tools.map((m) => m.name).join(',')}, mode=${meta.mode}, duration_ms=${meta.durationMs}${
|
|
221
224
|
parsed.reason ? `, reason=${parsed.reason}` : ''
|
|
222
225
|
}`
|
|
223
226
|
);
|
|
@@ -263,5 +263,10 @@ export function createHaikuCaller({ timeoutMs, claudeBin = 'claude', model = HAI
|
|
|
263
263
|
enumerable: true,
|
|
264
264
|
});
|
|
265
265
|
|
|
266
|
+
Object.defineProperty(callHaiku, 'isFirstCall', {
|
|
267
|
+
get: () => isFirstCall,
|
|
268
|
+
enumerable: true,
|
|
269
|
+
});
|
|
270
|
+
|
|
266
271
|
return callHaiku;
|
|
267
272
|
}
|
package/src/version.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const version = '0.5.
|
|
1
|
+
export const version = '0.5.2';
|