claude-spotter 1.4.23 → 1.4.24
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 +13 -2
- package/README.md +3 -3
- package/package.json +1 -1
- package/src/cli/install.mjs +3 -0
- package/src/core/runtime-error-store.mjs +15 -3
package/CHANGELOG.md
CHANGED
|
@@ -1,11 +1,22 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
-
## 1.4.
|
|
3
|
+
## 1.4.24 — 2026-07-14
|
|
4
|
+
|
|
5
|
+
- **installerがruntime error state rootをowner-privateへ正規化。** `spotter install`は
|
|
6
|
+
Hook・tool DB・daemon stateを作る前に、runtime storeと同じPOSIX uid / modeまたは
|
|
7
|
+
Windows current-SID-only DACL契約でglobal state rootを準備する。fresh installだけでなく、
|
|
8
|
+
umaskにより`0755` / `0775`で残っていた既存`~/.spotter`もPOSIXでは`0700`へ修復する。
|
|
9
|
+
- **unsafe pathを修復前に拒否。** POSIXのtype・symlink・owner検証を`chmod`より前へ移し、
|
|
10
|
+
`~/.spotter`がsymlinkの場合にリンク先のmodeを変えてから失敗する副作用を防いだ。
|
|
11
|
+
read-timeのmode検証、Windows DACL、collection明示opt-in、network非依存契約は変更しない。
|
|
12
|
+
|
|
13
|
+
## 1.4.23 — 2026-07-13
|
|
4
14
|
|
|
5
15
|
- **Factory diagnostics と local runtime error store。** factory diagnostics と
|
|
6
16
|
`spotter diagnostics runtime-errors` の公開候補。収集は canonical dotagents config の
|
|
7
17
|
JSON boolean `collection.enabled: true` が明示された時だけ有効で既定OFF、保存は
|
|
8
|
-
local-only、network
|
|
18
|
+
local-only、network送信は行わない。公開commit `a117a99`、CI `29238199094`、npm
|
|
19
|
+
`latest`、tag / GitHub Release、registry由来隔離installと診断snapshotを確認済み。
|
|
9
20
|
- **隔離observerのdeadlineを実測へ整合。** 並列full-suite負荷でcold workerとreceipt
|
|
10
21
|
reconcilerが500msに収まらず、commit済みreceiptを`store_unavailable`へ誤分類するraceを
|
|
11
22
|
再現した。絶対deadlineを1.5秒へ広げたうえでreceipt reconcilerを観測workerと
|
package/README.md
CHANGED
|
@@ -248,9 +248,9 @@ otherwise the Haiku-compatible path. Codex native hooks automatically select Cod
|
|
|
248
248
|
|
|
249
249
|
## Local runtime error aggregates
|
|
250
250
|
|
|
251
|
-
**v1.4.23 は
|
|
252
|
-
|
|
253
|
-
install
|
|
251
|
+
**v1.4.23 は2026-07-13に公開済みです。** 以下の factory diagnostics と local runtime
|
|
252
|
+
error aggregate は collection が既定OFFです。npm `latest`、tag / GitHub Release、
|
|
253
|
+
公開CI、registry由来installを確認済みです。
|
|
254
254
|
|
|
255
255
|
Spotter collects fixed-code runtime failures only when the canonical dotagents factory reporter
|
|
256
256
|
configuration contains the JSON boolean `collection.enabled: true`. Missing, malformed, and disabled
|
package/package.json
CHANGED
package/src/cli/install.mjs
CHANGED
|
@@ -23,6 +23,7 @@ import { version as SPOTTER_VERSION } from '../version.mjs';
|
|
|
23
23
|
import { refresh } from '../tool-db/refresh.mjs';
|
|
24
24
|
import { localDbPath, globalDbPath } from '../tool-db/loader.mjs';
|
|
25
25
|
import { installCodexHooks } from './codex-hook-cmd.mjs';
|
|
26
|
+
import { prepareRuntimeErrorStoreDirectory } from '../core/runtime-error-store.mjs';
|
|
26
27
|
|
|
27
28
|
const HERE = dirname(fileURLToPath(import.meta.url));
|
|
28
29
|
const PACKAGE_ROOT = resolve(HERE, '..', '..');
|
|
@@ -58,6 +59,7 @@ export async function runInstall({
|
|
|
58
59
|
refreshFn = refresh,
|
|
59
60
|
codexCliPresentFn = isCodexCliPresent,
|
|
60
61
|
installCodexHooksFn = installCodexHooks,
|
|
62
|
+
prepareRuntimeErrorStoreDirectoryFn = prepareRuntimeErrorStoreDirectory,
|
|
61
63
|
auditorContext,
|
|
62
64
|
resolveDefaultAuditorContextFn = resolveDefaultAuditorContext,
|
|
63
65
|
} = {}) {
|
|
@@ -70,6 +72,7 @@ export async function runInstall({
|
|
|
70
72
|
console.log(` settings: ${settingsPath}`);
|
|
71
73
|
|
|
72
74
|
// 1. create directories
|
|
75
|
+
await prepareRuntimeErrorStoreDirectoryFn();
|
|
73
76
|
await mkdir(SPOTTER_HOME, { recursive: true });
|
|
74
77
|
await mkdir(join(SPOTTER_HOME, 'runtime'), { recursive: true });
|
|
75
78
|
await mkdir(join(SPOTTER_HOME, 'workdir'), { recursive: true });
|
|
@@ -90,6 +90,11 @@ export function defaultRuntimeErrorStorePath({
|
|
|
90
90
|
return join(homeDir, '.spotter', 'runtime-errors-v1.json');
|
|
91
91
|
}
|
|
92
92
|
|
|
93
|
+
export async function prepareRuntimeErrorStoreDirectory(options = {}) {
|
|
94
|
+
const storePath = options.storePath ?? defaultRuntimeErrorStorePath(options);
|
|
95
|
+
await ensurePrivateDirectory(dirname(storePath), options);
|
|
96
|
+
}
|
|
97
|
+
|
|
93
98
|
export function runtimeErrorFingerprint(definition) {
|
|
94
99
|
validateDefinition(definition);
|
|
95
100
|
const canonical = [
|
|
@@ -578,22 +583,29 @@ async function enforcePrivatePath(path, options, { directory, repair }) {
|
|
|
578
583
|
if (repair) await runWindowsAcl(path, { directory }, options);
|
|
579
584
|
return;
|
|
580
585
|
}
|
|
586
|
+
const initialInfo = await lstat(path);
|
|
587
|
+
validatePrivateIdentity(initialInfo, options, { directory, platform });
|
|
581
588
|
if (repair) await chmod(path, directory ? 0o700 : 0o600);
|
|
582
589
|
const info = await lstat(path);
|
|
583
590
|
validatePrivateStat(info, options, { directory, platform });
|
|
584
591
|
}
|
|
585
592
|
|
|
586
|
-
function
|
|
593
|
+
function validatePrivateIdentity(info, options, { directory, platform }) {
|
|
587
594
|
if ((directory ? !info.isDirectory() : !info.isFile()) || info.isSymbolicLink()) {
|
|
588
595
|
throw storeError('runtime error path type is unsafe');
|
|
589
596
|
}
|
|
590
597
|
if (platform === 'win32') return;
|
|
591
|
-
const expectedMode = directory ? 0o700 : 0o600;
|
|
592
|
-
if ((info.mode & 0o777) !== expectedMode) throw storeError('runtime error path mode is unsafe');
|
|
593
598
|
const getuid = options.getuidFn ?? process.getuid?.bind(process);
|
|
594
599
|
if (typeof getuid === 'function' && info.uid !== getuid()) throw storeError('runtime error path owner is unsafe');
|
|
595
600
|
}
|
|
596
601
|
|
|
602
|
+
function validatePrivateStat(info, options, { directory, platform }) {
|
|
603
|
+
validatePrivateIdentity(info, options, { directory, platform });
|
|
604
|
+
if (platform === 'win32') return;
|
|
605
|
+
const expectedMode = directory ? 0o700 : 0o600;
|
|
606
|
+
if ((info.mode & 0o777) !== expectedMode) throw storeError('runtime error path mode is unsafe');
|
|
607
|
+
}
|
|
608
|
+
|
|
597
609
|
export function buildWindowsAclPowerShell({ directory }) {
|
|
598
610
|
const securityType = directory ? 'DirectorySecurity' : 'FileSecurity';
|
|
599
611
|
const ioType = directory ? 'Directory' : 'File';
|