claude-inspect 0.6.0 → 0.7.1

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.
@@ -132,8 +132,10 @@ export class SpawnIndex {
132
132
  links = new Map();
133
133
  /** Neue Zeilen aller Transcripts nach claude-Aufrufen durchsuchen (inkrementell). */
134
134
  async refresh(transcripts, processes, full) {
135
+ let changed = full;
135
136
  for (const f of transcripts) {
136
- await this.scanFile(f.path, f.size, f.sessionId);
137
+ if (await this.scanFile(f.path, f.size, f.sessionId))
138
+ changed = true;
137
139
  // Subagenten können ebenfalls claude-Aufrufe machen. Nach dem ersten
138
140
  // Durchlauf nur noch bei kürzlich aktiven Sessions nachsehen.
139
141
  if (!full && Date.now() - f.mtime > 3600_000)
@@ -152,7 +154,8 @@ export class SpawnIndex {
152
154
  continue;
153
155
  const path = join(dir, n);
154
156
  try {
155
- await this.scanFile(path, (await stat(path)).size, f.sessionId, m[1]);
157
+ if (await this.scanFile(path, (await stat(path)).size, f.sessionId, m[1]))
158
+ changed = true;
156
159
  }
157
160
  catch {
158
161
  /* gelöscht */
@@ -160,13 +163,26 @@ export class SpawnIndex {
160
163
  }
161
164
  }
162
165
  for (const f of transcripts)
163
- await this.readChild(f);
166
+ if (await this.readChild(f))
167
+ changed = true;
168
+ // Zuordnen ist teuer (alle Aufrufe × alle Kinder) – nur bei neuen Daten oder geänderten Prozessen
169
+ const procKey = processes
170
+ .filter((p) => p.alive)
171
+ .map((p) => `${p.pid}:${p.sessionId}:${p.parentPid ?? ''}`)
172
+ .sort()
173
+ .join(',');
174
+ if (!changed && procKey === this.procKey)
175
+ return;
176
+ this.procKey = procKey;
164
177
  this.link(processes);
165
178
  }
179
+ procKey = '';
180
+ /** true, wenn neue claude-Aufrufe dazugekommen sind */
166
181
  async scanFile(path, size, sessionId, agentId) {
167
182
  let st = this.files.get(path);
168
183
  if (st && st.size === size)
169
- return;
184
+ return false;
185
+ const before = st?.calls.length ?? -1;
170
186
  if (!st || size < st.size) {
171
187
  st = { size: 0, tail: new JsonlTail(path), calls: [] };
172
188
  this.files.set(path, st);
@@ -192,12 +208,14 @@ export class SpawnIndex {
192
208
  catch {
193
209
  /* gelöscht */
194
210
  }
211
+ return st.calls.length !== before;
195
212
  }
196
213
  /** Kopf eines Transcripts: Einstiegspunkt, erster Prompt, Startzeit, Agent. */
197
214
  async readChild(f) {
198
215
  const cached = this.children.get(f.sessionId);
199
- if (cached && cached.info.prompt !== undefined && cached.size <= f.size)
200
- return;
216
+ // unveränderte Datei nicht erneut lesen (auch wenn noch kein Prompt gefunden wurde)
217
+ if (cached && (cached.size === f.size || (cached.info.prompt !== undefined && cached.size <= f.size)))
218
+ return false;
201
219
  const info = { sessionId: f.sessionId };
202
220
  try {
203
221
  const { head } = await readHeadTail(f.path, 96 * 1024, 0);
@@ -228,6 +246,7 @@ export class SpawnIndex {
228
246
  /* gelöscht */
229
247
  }
230
248
  this.children.set(f.sessionId, { size: f.size, info });
249
+ return JSON.stringify(cached?.info) !== JSON.stringify(info);
231
250
  }
232
251
  link(processes) {
233
252
  const allCalls = [...this.files.values()].flatMap((f) => f.calls);
@@ -0,0 +1,57 @@
1
+ // Analyse einer Session durch Claude ("Analyze with Claude"): Prüfaspekte und Datentypen.
2
+ export const ASPECTS = [
3
+ {
4
+ key: 'outcome',
5
+ label: 'Task outcome',
6
+ hint: 'Did the agent do what was asked? Anything skipped, half-done or claimed without evidence?',
7
+ brief: 'Compare the user requests with what was actually done. Point out parts that were skipped, left unfinished or done differently than asked, and claims in the final answers that are not backed by the tool calls (e.g. "tests pass" without a test run).',
8
+ default: true,
9
+ },
10
+ {
11
+ key: 'efficiency',
12
+ label: 'Efficiency & cost',
13
+ hint: 'Wasted tokens and time: redundant reads, loops, oversized context, expensive model for simple work.',
14
+ brief: 'Find where time, tokens or money were wasted: files read repeatedly, searches that could have been one call, loops and retries, very large contexts, expensive models or subagents used for trivial work, long waits. Use the cost and context figures. Estimate what a leaner run would have looked like.',
15
+ default: true,
16
+ },
17
+ {
18
+ key: 'errors',
19
+ label: 'Errors & dead ends',
20
+ hint: 'Failed tool calls, retries and detours – what went wrong and how much it cost.',
21
+ brief: 'Go through failed tool calls, denied permissions, retries and abandoned approaches. For each relevant one: the cause, how the agent recovered (or did not), and how much time/cost the detour took.',
22
+ default: false,
23
+ },
24
+ {
25
+ key: 'privacy',
26
+ label: 'Privacy & data protection',
27
+ hint: 'Secrets or personal data read, printed or sent to external services.',
28
+ brief: 'Check whether sensitive data was touched: credentials, keys, tokens ([REDACTED] marks secrets that appeared in the original), .env files, SSH/cloud configs, personal data (names, emails, addresses, customer data). Did any of it end up in outputs, commits, logs or requests to external services (curl, WebFetch, MCP tools, git push)? Distinguish necessary access from unnecessary exposure.',
29
+ default: true,
30
+ },
31
+ {
32
+ key: 'security',
33
+ label: 'Security & risky actions',
34
+ hint: 'Destructive commands, force pushes, permission bypasses, untrusted code, prompt injection.',
35
+ brief: 'Look for risky actions: destructive or irreversible commands (rm -rf, reset --hard, force push, dropping data), sudo, disabled safety checks (--no-verify, bypass permissions), installing or running untrusted code (curl | sh, unknown packages), and signs of prompt injection from fetched web content or files that changed the agent\'s behaviour.',
36
+ default: false,
37
+ },
38
+ {
39
+ key: 'orchestration',
40
+ label: 'Agents & delegation',
41
+ hint: 'Subagents and spawned claude workers: sensible split, duplicate work, cost per agent.',
42
+ brief: 'Assess how work was split across subagents and spawned claude sessions: was delegation worth it, were prompts to subagents clear and complete, did agents duplicate work or wait on each other, which agent cost most relative to its contribution? If there were no subagents, say whether delegation would have helped.',
43
+ default: false,
44
+ },
45
+ {
46
+ key: 'improvements',
47
+ label: 'Setup improvements',
48
+ hint: 'What to change in prompt, CLAUDE.md, permissions or skills so the next run goes smoother.',
49
+ brief: 'Derive concrete improvements for next time: better phrasing of the request, rules or facts worth adding to CLAUDE.md, permission allow-rules that would have avoided prompts, hooks, skills or subagents that would fit. Give copy-pasteable snippets where possible.',
50
+ default: true,
51
+ },
52
+ ];
53
+ export const REVIEW_MODELS = [
54
+ { key: 'haiku', label: 'Haiku – fast, cheapest' },
55
+ { key: 'sonnet', label: 'Sonnet – balanced' },
56
+ { key: 'opus', label: 'Opus – most thorough' },
57
+ ];