claude-spotter 1.4.25 → 1.4.26
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,16 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 1.4.26 — 2026-07-20
|
|
4
|
+
|
|
5
|
+
- **SessionEnd cleanupを冪等化。** daemonが未起動または既に停止済みの`E_UNREACHABLE`は
|
|
6
|
+
`already-stopped`として記録し、正常な終了状態をstderr warningへ誤分類しない。他のcleanup
|
|
7
|
+
failureは従来どおりwarningと構造eventを残す。
|
|
8
|
+
- **Windows native Codex hookをPowerShell実行可能に修正。** quoted Node commandの先頭へ
|
|
9
|
+
Windowsだけcall operator `&`を付ける。installerのownership判定は新旧両形式を認識し、
|
|
10
|
+
再installで旧形式をcanonicalへ更新、uninstallでも除去できる。
|
|
11
|
+
- **Windows runtime error storeのACL処理を安定化。** 混雑したWindows runnerでも
|
|
12
|
+
PowerShellによるprivate ACL設定が誤ってtimeoutしないよう、上限を15秒へ拡張した。
|
|
13
|
+
|
|
3
14
|
## 1.4.25 — 2026-07-14
|
|
4
15
|
|
|
5
16
|
- **Windows Codex CLI実行経路を修正。** `spotter install`、`spotter doctor`、Codex hook /
|
|
@@ -12,7 +23,9 @@
|
|
|
12
23
|
POSIXと実体`.exe`の直接spawn、stdin prompt、非0終了時のfail-loud診断は維持する。
|
|
13
24
|
- **検証。** 530 tests(528 pass / 2 platform skip)、68-file pack、FOX Windows nativeの
|
|
14
25
|
tarball仮導入、install、warning 0のdoctor、Codex hooks / catalog、実Codex CLI auditor、
|
|
15
|
-
codex-sidecar auditor diagnostics、dotagents `verify-install
|
|
26
|
+
codex-sidecar auditor diagnostics、dotagents `verify-install`を通過した。公開commit
|
|
27
|
+
`65bccf8`をnpm `latest`、`v1.4.25` tag、GitHub Releaseへ同期し、Mac、main-server、
|
|
28
|
+
FOX WSL2、FOX Windows nativeのregistry版global installとwarning 0のdoctorを確認した。
|
|
16
29
|
|
|
17
30
|
## 1.4.24 — 2026-07-14
|
|
18
31
|
|
package/package.json
CHANGED
|
@@ -464,11 +464,11 @@ export async function runCodexHookDiagnosticsCommand({
|
|
|
464
464
|
writeOutput(JSON.stringify(result, null, 2) + '\n');
|
|
465
465
|
}
|
|
466
466
|
|
|
467
|
-
export async function installCodexHooks({ codexHome = defaultCodexHome(), nodePath = resolveCodexHookNodePath(), spotterBin = SPOTTER_BIN } = {}) {
|
|
467
|
+
export async function installCodexHooks({ codexHome = defaultCodexHome(), nodePath = resolveCodexHookNodePath(), spotterBin = SPOTTER_BIN, platform = process.platform } = {}) {
|
|
468
468
|
const hooksPath = join(codexHome, 'hooks.json');
|
|
469
469
|
const configPath = join(codexHome, 'config.toml');
|
|
470
470
|
const current = await loadJson(hooksPath);
|
|
471
|
-
const next = mergeCodexHooks(current, { nodePath, spotterBin });
|
|
471
|
+
const next = mergeCodexHooks(current, { nodePath, spotterBin, platform });
|
|
472
472
|
const hooksChanged = JSON.stringify(current) !== JSON.stringify(next);
|
|
473
473
|
if (hooksChanged) {
|
|
474
474
|
await mkdir(dirname(hooksPath), { recursive: true });
|
|
@@ -879,14 +879,15 @@ async function loadJson(path) {
|
|
|
879
879
|
}
|
|
880
880
|
}
|
|
881
881
|
|
|
882
|
-
function mergeCodexHooks(current, { nodePath, spotterBin }) {
|
|
882
|
+
function mergeCodexHooks(current, { nodePath, spotterBin, platform = process.platform }) {
|
|
883
883
|
const next = structuredClone(current ?? {});
|
|
884
884
|
next.hooks = next.hooks ?? {};
|
|
885
|
-
|
|
885
|
+
const prefix = platform === 'win32' ? '& ' : '';
|
|
886
|
+
addCodexHook(next, 'SessionStart', `${prefix}${quoteArg(nodePath)} ${quoteArg(spotterBin)} codex-hook session-start`, {
|
|
886
887
|
timeout: 5,
|
|
887
888
|
});
|
|
888
|
-
addCodexHook(next, 'UserPromptSubmit', `${quoteArg(nodePath)} ${quoteArg(spotterBin)} codex-hook user-prompt-submit`);
|
|
889
|
-
addCodexHook(next, 'Stop', `${quoteArg(nodePath)} ${quoteArg(spotterBin)} codex-hook stop`);
|
|
889
|
+
addCodexHook(next, 'UserPromptSubmit', `${prefix}${quoteArg(nodePath)} ${quoteArg(spotterBin)} codex-hook user-prompt-submit`);
|
|
890
|
+
addCodexHook(next, 'Stop', `${prefix}${quoteArg(nodePath)} ${quoteArg(spotterBin)} codex-hook stop`);
|
|
890
891
|
return next;
|
|
891
892
|
}
|
|
892
893
|
|
|
@@ -943,7 +944,7 @@ function isSpotterCodexHook(hook) {
|
|
|
943
944
|
}
|
|
944
945
|
|
|
945
946
|
function isSpotterCodexCommand(command, event = null) {
|
|
946
|
-
const match = command.match(/^(?:"((?:\\.|[^"\\])*)"|(\S+))\s+(?:"((?:\\.|[^"\\])*)"|(\S+))\s+codex-hook\s+(session-start|user-prompt-submit|stop)\s*$/);
|
|
947
|
+
const match = command.match(/^(?:&\s+)?(?:"((?:\\.|[^"\\])*)"|(\S+))\s+(?:"((?:\\.|[^"\\])*)"|(\S+))\s+codex-hook\s+(session-start|user-prompt-submit|stop)\s*$/);
|
|
947
948
|
if (!match) return false;
|
|
948
949
|
const nodePath = unescapeQuotedCommandToken(match[1] ?? match[2]);
|
|
949
950
|
const spotterPath = unescapeQuotedCommandToken(match[3] ?? match[4]);
|
|
@@ -635,7 +635,7 @@ async function runWindowsAcl(path, { directory }, options) {
|
|
|
635
635
|
const executable = options.powerShellPath ?? 'powershell.exe';
|
|
636
636
|
const script = buildWindowsAclPowerShell({ directory });
|
|
637
637
|
await spawnForExit(executable, ['-NoProfile', '-NonInteractive', '-Command', script], {
|
|
638
|
-
timeoutMs: options.aclTimeoutMs ??
|
|
638
|
+
timeoutMs: options.aclTimeoutMs ?? 15_000,
|
|
639
639
|
env: { ...process.env, SPOTTER_ACL_PATH: path },
|
|
640
640
|
});
|
|
641
641
|
}
|
|
@@ -20,6 +20,7 @@ export async function runSessionEnd({
|
|
|
20
20
|
readInput = readStdinJson,
|
|
21
21
|
sendRequestFn = sendRequest,
|
|
22
22
|
recordHookEventFn = recordClaudeHookEvent,
|
|
23
|
+
writeError = (text) => process.stderr.write(text),
|
|
23
24
|
} = {}) {
|
|
24
25
|
if (isChildCall()) return;
|
|
25
26
|
const input = await readInput();
|
|
@@ -41,6 +42,13 @@ export async function runSessionEnd({
|
|
|
41
42
|
event: { hook: 'SessionEnd', status: 'shutdown', durationMs: Date.now() - startedAt },
|
|
42
43
|
});
|
|
43
44
|
} catch (err) {
|
|
45
|
+
if (err?.code === 'E_UNREACHABLE') {
|
|
46
|
+
await recordHookEventFn({
|
|
47
|
+
projectRoot,
|
|
48
|
+
event: { hook: 'SessionEnd', status: 'already-stopped', durationMs: Date.now() - startedAt },
|
|
49
|
+
});
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
44
52
|
await recordHookEventFn({
|
|
45
53
|
projectRoot,
|
|
46
54
|
event: {
|
|
@@ -51,8 +59,7 @@ export async function runSessionEnd({
|
|
|
51
59
|
},
|
|
52
60
|
});
|
|
53
61
|
// §14.1 exception — don't fail the Claude Code session just because cleanup failed.
|
|
54
|
-
|
|
55
|
-
process.exit(0);
|
|
62
|
+
writeError(`spotter-hook: session-end shutdown warning: ${err.code ?? '?'}: ${err.message}\n`);
|
|
56
63
|
}
|
|
57
64
|
}
|
|
58
65
|
|