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 CHANGED
@@ -1,11 +1,22 @@
1
1
  # Changelog
2
2
 
3
- ## 1.4.23 — release candidate (pending)
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送信は行わない。npm公開、tag、CI、registry由来installの確認は未実施。
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 は release candidate(公開待ち)です。** 以下の factory diagnostics と
252
- local runtime error aggregate は collection が既定OFFで、公開・tag・CI・registry由来
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-spotter",
3
- "version": "1.4.23",
3
+ "version": "1.4.24",
4
4
  "description": "Audit agent running alongside Claude Code that catches missed tool calls — 気づく役と実行する役の分離",
5
5
  "type": "module",
6
6
  "bin": {
@@ -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 validatePrivateStat(info, options, { directory, platform }) {
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';